diff --git a/vendor/autoload.php b/vendor/autoload.php
new file mode 100644
index 0000000..1d19169
--- /dev/null
+++ b/vendor/autoload.php
@@ -0,0 +1,22 @@
+*
+- `MathException` now extends `Exception` instead of `RuntimeException`
+
+
* You may now run into type errors if you were passing `Stringable` objects to `of()` or any of the methods
+internally calling `of()`, with `strict_types` enabled. You can fix this by casting `Stringable` objects to `string`
+first.
+
+## [0.10.2](https://github.com/brick/math/releases/tag/0.10.2) - 2022-08-11
+
+👌 **Improvements**
+
+- `BigRational::toFloat()` now simplifies the fraction before performing division (#73) thanks to @olsavmic
+
+## [0.10.1](https://github.com/brick/math/releases/tag/0.10.1) - 2022-08-02
+
+✨ **New features**
+
+- `BigInteger::gcdMultiple()` returns the GCD of multiple `BigInteger` numbers
+
+## [0.10.0](https://github.com/brick/math/releases/tag/0.10.0) - 2022-06-18
+
+💥 **Breaking changes**
+
+- Minimum PHP version is now 7.4
+
+## [0.9.3](https://github.com/brick/math/releases/tag/0.9.3) - 2021-08-15
+
+🚀 **Compatibility with PHP 8.1**
+
+- Support for custom object serialization; this removes a warning on PHP 8.1 due to the `Serializable` interface being deprecated (#60) thanks @TRowbotham
+
+## [0.9.2](https://github.com/brick/math/releases/tag/0.9.2) - 2021-01-20
+
+🐛 **Bug fix**
+
+- Incorrect results could be returned when using the BCMath calculator, with a default scale set with `bcscale()`, on PHP >= 7.2 (#55).
+
+## [0.9.1](https://github.com/brick/math/releases/tag/0.9.1) - 2020-08-19
+
+✨ **New features**
+
+- `BigInteger::not()` returns the bitwise `NOT` value
+
+🐛 **Bug fixes**
+
+- `BigInteger::toBytes()` could return an incorrect binary representation for some numbers
+- The bitwise operations `and()`, `or()`, `xor()` on `BigInteger` could return an incorrect result when the GMP extension is not available
+
+## [0.9.0](https://github.com/brick/math/releases/tag/0.9.0) - 2020-08-18
+
+👌 **Improvements**
+
+- `BigNumber::of()` now accepts `.123` and `123.` formats, both of which return a `BigDecimal`
+
+💥 **Breaking changes**
+
+- Deprecated method `BigInteger::powerMod()` has been removed - use `modPow()` instead
+- Deprecated method `BigInteger::parse()` has been removed - use `fromBase()` instead
+
+## [0.8.17](https://github.com/brick/math/releases/tag/0.8.17) - 2020-08-19
+
+🐛 **Bug fix**
+
+- `BigInteger::toBytes()` could return an incorrect binary representation for some numbers
+- The bitwise operations `and()`, `or()`, `xor()` on `BigInteger` could return an incorrect result when the GMP extension is not available
+
+## [0.8.16](https://github.com/brick/math/releases/tag/0.8.16) - 2020-08-18
+
+🚑 **Critical fix**
+
+- This version reintroduces the deprecated `BigInteger::parse()` method, that has been removed by mistake in version `0.8.9` and should have lasted for the whole `0.8` release cycle.
+
+✨ **New features**
+
+- `BigInteger::modInverse()` calculates a modular multiplicative inverse
+- `BigInteger::fromBytes()` creates a `BigInteger` from a byte string
+- `BigInteger::toBytes()` converts a `BigInteger` to a byte string
+- `BigInteger::randomBits()` creates a pseudo-random `BigInteger` of a given bit length
+- `BigInteger::randomRange()` creates a pseudo-random `BigInteger` between two bounds
+
+💩 **Deprecations**
+
+- `BigInteger::powerMod()` is now deprecated in favour of `modPow()`
+
+## [0.8.15](https://github.com/brick/math/releases/tag/0.8.15) - 2020-04-15
+
+🐛 **Fixes**
+
+- added missing `ext-json` requirement, due to `BigNumber` implementing `JsonSerializable`
+
+⚡️ **Optimizations**
+
+- additional optimization in `BigInteger::remainder()`
+
+## [0.8.14](https://github.com/brick/math/releases/tag/0.8.14) - 2020-02-18
+
+✨ **New features**
+
+- `BigInteger::getLowestSetBit()` returns the index of the rightmost one bit
+
+## [0.8.13](https://github.com/brick/math/releases/tag/0.8.13) - 2020-02-16
+
+✨ **New features**
+
+- `BigInteger::isEven()` tests whether the number is even
+- `BigInteger::isOdd()` tests whether the number is odd
+- `BigInteger::testBit()` tests if a bit is set
+- `BigInteger::getBitLength()` returns the number of bits in the minimal representation of the number
+
+## [0.8.12](https://github.com/brick/math/releases/tag/0.8.12) - 2020-02-03
+
+🛠️ **Maintenance release**
+
+Classes are now annotated for better static analysis with [psalm](https://psalm.dev/).
+
+This is a maintenance release: no bug fixes, no new features, no breaking changes.
+
+## [0.8.11](https://github.com/brick/math/releases/tag/0.8.11) - 2020-01-23
+
+✨ **New feature**
+
+`BigInteger::powerMod()` performs a power-with-modulo operation. Useful for crypto.
+
+## [0.8.10](https://github.com/brick/math/releases/tag/0.8.10) - 2020-01-21
+
+✨ **New feature**
+
+`BigInteger::mod()` returns the **modulo** of two numbers. The *modulo* differs from the *remainder* when the signs of the operands are different.
+
+## [0.8.9](https://github.com/brick/math/releases/tag/0.8.9) - 2020-01-08
+
+⚡️ **Performance improvements**
+
+A few additional optimizations in `BigInteger` and `BigDecimal` when one of the operands can be returned as is. Thanks to @tomtomsen in #24.
+
+## [0.8.8](https://github.com/brick/math/releases/tag/0.8.8) - 2019-04-25
+
+🐛 **Bug fixes**
+
+- `BigInteger::toBase()` could return an empty string for zero values (BCMath & Native calculators only, GMP calculator unaffected)
+
+✨ **New features**
+
+- `BigInteger::toArbitraryBase()` converts a number to an arbitrary base, using a custom alphabet
+- `BigInteger::fromArbitraryBase()` converts a string in an arbitrary base, using a custom alphabet, back to a number
+
+These methods can be used as the foundation to convert strings between different bases/alphabets, using BigInteger as an intermediate representation.
+
+💩 **Deprecations**
+
+- `BigInteger::parse()` is now deprecated in favour of `fromBase()`
+
+`BigInteger::fromBase()` works the same way as `parse()`, with 2 minor differences:
+
+- the `$base` parameter is required, it does not default to `10`
+- it throws a `NumberFormatException` instead of an `InvalidArgumentException` when the number is malformed
+
+## [0.8.7](https://github.com/brick/math/releases/tag/0.8.7) - 2019-04-20
+
+**Improvements**
+
+- Safer conversion from `float` when using custom locales
+- **Much faster** `NativeCalculator` implementation 🚀
+
+You can expect **at least a 3x performance improvement** for common arithmetic operations when using the library on systems without GMP or BCMath; it gets exponentially faster on multiplications with a high number of digits. This is due to calculations now being performed on whole blocks of digits (the block size depending on the platform, 32-bit or 64-bit) instead of digit-by-digit as before.
+
+## [0.8.6](https://github.com/brick/math/releases/tag/0.8.6) - 2019-04-11
+
+**New method**
+
+`BigNumber::sum()` returns the sum of one or more numbers.
+
+## [0.8.5](https://github.com/brick/math/releases/tag/0.8.5) - 2019-02-12
+
+**Bug fix**: `of()` factory methods could fail when passing a `float` in environments using a `LC_NUMERIC` locale with a decimal separator other than `'.'` (#20).
+
+Thanks @manowark 👍
+
+## [0.8.4](https://github.com/brick/math/releases/tag/0.8.4) - 2018-12-07
+
+**New method**
+
+`BigDecimal::sqrt()` calculates the square root of a decimal number, to a given scale.
+
+## [0.8.3](https://github.com/brick/math/releases/tag/0.8.3) - 2018-12-06
+
+**New method**
+
+`BigInteger::sqrt()` calculates the square root of a number (thanks @peter279k).
+
+**New exception**
+
+`NegativeNumberException` is thrown when calling `sqrt()` on a negative number.
+
+## [0.8.2](https://github.com/brick/math/releases/tag/0.8.2) - 2018-11-08
+
+**Performance update**
+
+- Further improvement of `toInt()` performance
+- `NativeCalculator` can now perform some multiplications more efficiently
+
+## [0.8.1](https://github.com/brick/math/releases/tag/0.8.1) - 2018-11-07
+
+Performance optimization of `toInt()` methods.
+
+## [0.8.0](https://github.com/brick/math/releases/tag/0.8.0) - 2018-10-13
+
+**Breaking changes**
+
+The following deprecated methods have been removed. Use the new method name instead:
+
+| Method removed | Replacement method |
+| --- | --- |
+| `BigDecimal::getIntegral()` | `BigDecimal::getIntegralPart()` |
+| `BigDecimal::getFraction()` | `BigDecimal::getFractionalPart()` |
+
+---
+
+**New features**
+
+`BigInteger` has been augmented with 5 new methods for bitwise operations:
+
+| New method | Description |
+| --- | --- |
+| `and()` | performs a bitwise `AND` operation on two numbers |
+| `or()` | performs a bitwise `OR` operation on two numbers |
+| `xor()` | performs a bitwise `XOR` operation on two numbers |
+| `shiftedLeft()` | returns the number shifted left by a number of bits |
+| `shiftedRight()` | returns the number shifted right by a number of bits |
+
+Thanks to @DASPRiD 👍
+
+## [0.7.3](https://github.com/brick/math/releases/tag/0.7.3) - 2018-08-20
+
+**New method:** `BigDecimal::hasNonZeroFractionalPart()`
+
+**Renamed/deprecated methods:**
+
+- `BigDecimal::getIntegral()` has been renamed to `getIntegralPart()` and is now deprecated
+- `BigDecimal::getFraction()` has been renamed to `getFractionalPart()` and is now deprecated
+
+## [0.7.2](https://github.com/brick/math/releases/tag/0.7.2) - 2018-07-21
+
+**Performance update**
+
+`BigInteger::parse()` and `toBase()` now use GMP's built-in base conversion features when available.
+
+## [0.7.1](https://github.com/brick/math/releases/tag/0.7.1) - 2018-03-01
+
+This is a maintenance release, no code has been changed.
+
+- When installed with `--no-dev`, the autoloader does not autoload tests anymore
+- Tests and other files unnecessary for production are excluded from the dist package
+
+This will help make installations more compact.
+
+## [0.7.0](https://github.com/brick/math/releases/tag/0.7.0) - 2017-10-02
+
+Methods renamed:
+
+- `BigNumber:sign()` has been renamed to `getSign()`
+- `BigDecimal::unscaledValue()` has been renamed to `getUnscaledValue()`
+- `BigDecimal::scale()` has been renamed to `getScale()`
+- `BigDecimal::integral()` has been renamed to `getIntegral()`
+- `BigDecimal::fraction()` has been renamed to `getFraction()`
+- `BigRational::numerator()` has been renamed to `getNumerator()`
+- `BigRational::denominator()` has been renamed to `getDenominator()`
+
+Classes renamed:
+
+- `ArithmeticException` has been renamed to `MathException`
+
+## [0.6.2](https://github.com/brick/math/releases/tag/0.6.2) - 2017-10-02
+
+The base class for all exceptions is now `MathException`.
+`ArithmeticException` has been deprecated, and will be removed in 0.7.0.
+
+## [0.6.1](https://github.com/brick/math/releases/tag/0.6.1) - 2017-10-02
+
+A number of methods have been renamed:
+
+- `BigNumber:sign()` is deprecated; use `getSign()` instead
+- `BigDecimal::unscaledValue()` is deprecated; use `getUnscaledValue()` instead
+- `BigDecimal::scale()` is deprecated; use `getScale()` instead
+- `BigDecimal::integral()` is deprecated; use `getIntegral()` instead
+- `BigDecimal::fraction()` is deprecated; use `getFraction()` instead
+- `BigRational::numerator()` is deprecated; use `getNumerator()` instead
+- `BigRational::denominator()` is deprecated; use `getDenominator()` instead
+
+The old methods will be removed in version 0.7.0.
+
+## [0.6.0](https://github.com/brick/math/releases/tag/0.6.0) - 2017-08-25
+
+- Minimum PHP version is now [7.1](https://gophp71.org/); for PHP 5.6 and PHP 7.0 support, use version `0.5`
+- Deprecated method `BigDecimal::withScale()` has been removed; use `toScale()` instead
+- Method `BigNumber::toInteger()` has been renamed to `toInt()`
+
+## [0.5.4](https://github.com/brick/math/releases/tag/0.5.4) - 2016-10-17
+
+`BigNumber` classes now implement [JsonSerializable](http://php.net/manual/en/class.jsonserializable.php).
+The JSON output is always a string.
+
+## [0.5.3](https://github.com/brick/math/releases/tag/0.5.3) - 2016-03-31
+
+This is a bugfix release. Dividing by a negative power of 1 with the same scale as the dividend could trigger an incorrect optimization which resulted in a wrong result. See #6.
+
+## [0.5.2](https://github.com/brick/math/releases/tag/0.5.2) - 2015-08-06
+
+The `$scale` parameter of `BigDecimal::dividedBy()` is now optional again.
+
+## [0.5.1](https://github.com/brick/math/releases/tag/0.5.1) - 2015-07-05
+
+**New method: `BigNumber::toScale()`**
+
+This allows to convert any `BigNumber` to a `BigDecimal` with a given scale, using rounding if necessary.
+
+## [0.5.0](https://github.com/brick/math/releases/tag/0.5.0) - 2015-07-04
+
+**New features**
+- Common `BigNumber` interface for all classes, with the following methods:
+ - `sign()` and derived methods (`isZero()`, `isPositive()`, ...)
+ - `compareTo()` and derived methods (`isEqualTo()`, `isGreaterThan()`, ...) that work across different `BigNumber` types
+ - `toBigInteger()`, `toBigDecimal()`, `toBigRational`() conversion methods
+ - `toInteger()` and `toFloat()` conversion methods to native types
+- Unified `of()` behaviour: every class now accepts any type of number, provided that it can be safely converted to the current type
+- New method: `BigDecimal::exactlyDividedBy()`; this method automatically computes the scale of the result, provided that the division yields a finite number of digits
+- New methods: `BigRational::quotient()` and `remainder()`
+- Fine-grained exceptions: `DivisionByZeroException`, `RoundingNecessaryException`, `NumberFormatException`
+- Factory methods `zero()`, `one()` and `ten()` available in all classes
+- Rounding mode reintroduced in `BigInteger::dividedBy()`
+
+This release also comes with many performance improvements.
+
+---
+
+**Breaking changes**
+- `BigInteger`:
+ - `getSign()` is renamed to `sign()`
+ - `toString()` is renamed to `toBase()`
+ - `BigInteger::dividedBy()` now throws an exception by default if the remainder is not zero; use `quotient()` to get the previous behaviour
+- `BigDecimal`:
+ - `getSign()` is renamed to `sign()`
+ - `getUnscaledValue()` is renamed to `unscaledValue()`
+ - `getScale()` is renamed to `scale()`
+ - `getIntegral()` is renamed to `integral()`
+ - `getFraction()` is renamed to `fraction()`
+ - `divideAndRemainder()` is renamed to `quotientAndRemainder()`
+ - `dividedBy()` now takes a **mandatory** `$scale` parameter **before** the rounding mode
+ - `toBigInteger()` does not accept a `$roundingMode` parameter anymore
+ - `toBigRational()` does not simplify the fraction anymore; explicitly add `->simplified()` to get the previous behaviour
+- `BigRational`:
+ - `getSign()` is renamed to `sign()`
+ - `getNumerator()` is renamed to `numerator()`
+ - `getDenominator()` is renamed to `denominator()`
+ - `of()` is renamed to `nd()`, while `parse()` is renamed to `of()`
+- Miscellaneous:
+ - `ArithmeticException` is moved to an `Exception\` sub-namespace
+ - `of()` factory methods now throw `NumberFormatException` instead of `InvalidArgumentException`
+
+## [0.4.3](https://github.com/brick/math/releases/tag/0.4.3) - 2016-03-31
+
+Backport of two bug fixes from the 0.5 branch:
+- `BigInteger::parse()` did not always throw `InvalidArgumentException` as expected
+- Dividing by a negative power of 1 with the same scale as the dividend could trigger an incorrect optimization which resulted in a wrong result. See #6.
+
+## [0.4.2](https://github.com/brick/math/releases/tag/0.4.2) - 2015-06-16
+
+New method: `BigDecimal::stripTrailingZeros()`
+
+## [0.4.1](https://github.com/brick/math/releases/tag/0.4.1) - 2015-06-12
+
+Introducing a `BigRational` class, to perform calculations on fractions of any size.
+
+## [0.4.0](https://github.com/brick/math/releases/tag/0.4.0) - 2015-06-12
+
+Rounding modes have been removed from `BigInteger`, and are now a concept specific to `BigDecimal`.
+
+`BigInteger::dividedBy()` now always returns the quotient of the division.
+
+## [0.3.5](https://github.com/brick/math/releases/tag/0.3.5) - 2016-03-31
+
+Backport of two bug fixes from the 0.5 branch:
+
+- `BigInteger::parse()` did not always throw `InvalidArgumentException` as expected
+- Dividing by a negative power of 1 with the same scale as the dividend could trigger an incorrect optimization which resulted in a wrong result. See #6.
+
+## [0.3.4](https://github.com/brick/math/releases/tag/0.3.4) - 2015-06-11
+
+New methods:
+- `BigInteger::remainder()` returns the remainder of a division only
+- `BigInteger::gcd()` returns the greatest common divisor of two numbers
+
+## [0.3.3](https://github.com/brick/math/releases/tag/0.3.3) - 2015-06-07
+
+Fix `toString()` not handling negative numbers.
+
+## [0.3.2](https://github.com/brick/math/releases/tag/0.3.2) - 2015-06-07
+
+`BigInteger` and `BigDecimal` now have a `getSign()` method that returns:
+- `-1` if the number is negative
+- `0` if the number is zero
+- `1` if the number is positive
+
+## [0.3.1](https://github.com/brick/math/releases/tag/0.3.1) - 2015-06-05
+
+Minor performance improvements
+
+## [0.3.0](https://github.com/brick/math/releases/tag/0.3.0) - 2015-06-04
+
+The `$roundingMode` and `$scale` parameters have been swapped in `BigDecimal::dividedBy()`.
+
+## [0.2.2](https://github.com/brick/math/releases/tag/0.2.2) - 2015-06-04
+
+Stronger immutability guarantee for `BigInteger` and `BigDecimal`.
+
+So far, it would have been possible to break immutability of these classes by calling the `unserialize()` internal function. This release fixes that.
+
+## [0.2.1](https://github.com/brick/math/releases/tag/0.2.1) - 2015-06-02
+
+Added `BigDecimal::divideAndRemainder()`
+
+## [0.2.0](https://github.com/brick/math/releases/tag/0.2.0) - 2015-05-22
+
+- `min()` and `max()` do not accept an `array` anymore, but a variable number of parameters
+- **minimum PHP version is now 5.6**
+- continuous integration with PHP 7
+
+## [0.1.1](https://github.com/brick/math/releases/tag/0.1.1) - 2014-09-01
+
+- Added `BigInteger::power()`
+- Added HHVM support
+
+## [0.1.0](https://github.com/brick/math/releases/tag/0.1.0) - 2014-08-31
+
+First beta release.
+
diff --git a/vendor/brick/math/LICENSE b/vendor/brick/math/LICENSE
new file mode 100644
index 0000000..f9b724f
--- /dev/null
+++ b/vendor/brick/math/LICENSE
@@ -0,0 +1,20 @@
+The MIT License (MIT)
+
+Copyright (c) 2013-present Benjamin Morel
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software is furnished to do so,
+subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 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/vendor/brick/math/composer.json b/vendor/brick/math/composer.json
new file mode 100644
index 0000000..ad1dfe0
--- /dev/null
+++ b/vendor/brick/math/composer.json
@@ -0,0 +1,39 @@
+{
+ "name": "brick/math",
+ "description": "Arbitrary-precision arithmetic library",
+ "type": "library",
+ "keywords": [
+ "Brick",
+ "Math",
+ "Mathematics",
+ "Arbitrary-precision",
+ "Arithmetic",
+ "BigInteger",
+ "BigDecimal",
+ "BigRational",
+ "BigNumber",
+ "Bignum",
+ "Decimal",
+ "Rational",
+ "Integer"
+ ],
+ "license": "MIT",
+ "require": {
+ "php": "^8.2"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^11.5",
+ "php-coveralls/php-coveralls": "^2.2",
+ "phpstan/phpstan": "2.1.22"
+ },
+ "autoload": {
+ "psr-4": {
+ "Brick\\Math\\": "src/"
+ }
+ },
+ "autoload-dev": {
+ "psr-4": {
+ "Brick\\Math\\Tests\\": "tests/"
+ }
+ }
+}
diff --git a/vendor/brick/math/phpstan.neon b/vendor/brick/math/phpstan.neon
new file mode 100644
index 0000000..216ba1e
--- /dev/null
+++ b/vendor/brick/math/phpstan.neon
@@ -0,0 +1,14 @@
+parameters:
+ level: 10
+ checkUninitializedProperties: true
+ paths:
+ - src
+ ignoreErrors:
+ - '~Impure call to function array_shift\(\) in pure method~'
+ - '~Possibly impure call to function assert\(\) in pure method~'
+ - '~Possibly impure call to function hex2bin\(\) in pure method~'
+ - '~Possibly impure call to function preg_match\(\) in pure method~'
+ - '~Impure static variable in pure method Brick\\Math\\Big(Integer|Decimal|Rational)::(zero|one|ten)\(\)~'
+ -
+ message: '~Parameter #\d \$\S+ of function bc\S+ expects numeric-string, string given~'
+ path: src/Internal/Calculator/BcMathCalculator.php
diff --git a/vendor/brick/math/src/BigDecimal.php b/vendor/brick/math/src/BigDecimal.php
new file mode 100644
index 0000000..1a540c7
--- /dev/null
+++ b/vendor/brick/math/src/BigDecimal.php
@@ -0,0 +1,862 @@
+value = $value;
+ $this->scale = $scale;
+ }
+
+ #[Override]
+ 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. If negative, the scale will be set to zero
+ * and the unscaled value will be adjusted accordingly.
+ *
+ * @pure
+ */
+ public static function ofUnscaledValue(BigNumber|int|float|string $value, int $scale = 0) : BigDecimal
+ {
+ $value = (string) BigInteger::of($value);
+
+ if ($scale < 0) {
+ if ($value !== '0') {
+ $value .= \str_repeat('0', -$scale);
+ }
+ $scale = 0;
+ }
+
+ return new BigDecimal($value, $scale);
+ }
+
+ /**
+ * Returns a BigDecimal representing zero, with a scale of zero.
+ *
+ * @pure
+ */
+ public static function zero() : BigDecimal
+ {
+ /** @var BigDecimal|null $zero */
+ static $zero;
+
+ if ($zero === null) {
+ $zero = new BigDecimal('0');
+ }
+
+ return $zero;
+ }
+
+ /**
+ * Returns a BigDecimal representing one, with a scale of zero.
+ *
+ * @pure
+ */
+ public static function one() : BigDecimal
+ {
+ /** @var BigDecimal|null $one */
+ static $one;
+
+ if ($one === null) {
+ $one = new BigDecimal('1');
+ }
+
+ return $one;
+ }
+
+ /**
+ * Returns a BigDecimal representing ten, with a scale of zero.
+ *
+ * @pure
+ */
+ public static function ten() : BigDecimal
+ {
+ /** @var BigDecimal|null $ten */
+ static $ten;
+
+ if ($ten === null) {
+ $ten = new BigDecimal('10');
+ }
+
+ return $ten;
+ }
+
+ /**
+ * 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.
+ *
+ * @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
+ {
+ $that = BigDecimal::of($that);
+
+ if ($that->value === '0' && $that->scale <= $this->scale) {
+ return $this;
+ }
+
+ if ($this->value === '0' && $this->scale <= $that->scale) {
+ return $that;
+ }
+
+ [$a, $b] = $this->scaleValues($this, $that);
+
+ $value = CalculatorRegistry::get()->add($a, $b);
+ $scale = $this->scale > $that->scale ? $this->scale : $that->scale;
+
+ return new BigDecimal($value, $scale);
+ }
+
+ /**
+ * Returns the difference 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 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
+ {
+ $that = BigDecimal::of($that);
+
+ if ($that->value === '0' && $that->scale <= $this->scale) {
+ return $this;
+ }
+
+ [$a, $b] = $this->scaleValues($this, $that);
+
+ $value = CalculatorRegistry::get()->sub($a, $b);
+ $scale = $this->scale > $that->scale ? $this->scale : $that->scale;
+
+ return new BigDecimal($value, $scale);
+ }
+
+ /**
+ * Returns the product of this number and the given one.
+ *
+ * The result has a scale of `$this->scale + $that->scale`.
+ *
+ * @param BigNumber|int|float|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.
+ *
+ * @pure
+ */
+ public function multipliedBy(BigNumber|int|float|string $that) : BigDecimal
+ {
+ $that = BigDecimal::of($that);
+
+ if ($that->value === '1' && $that->scale === 0) {
+ return $this;
+ }
+
+ if ($this->value === '1' && $this->scale === 0) {
+ return $that;
+ }
+
+ $value = CalculatorRegistry::get()->mul($this->value, $that->value);
+ $scale = $this->scale + $that->scale;
+
+ return new BigDecimal($value, $scale);
+ }
+
+ /**
+ * 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.
+ *
+ * @throws \InvalidArgumentException If the scale or rounding mode is invalid.
+ * @throws MathException If the number is invalid, is zero, or rounding was necessary.
+ *
+ * @pure
+ */
+ public function dividedBy(BigNumber|int|float|string $that, ?int $scale = null, RoundingMode $roundingMode = RoundingMode::UNNECESSARY) : BigDecimal
+ {
+ $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) {
+ return $this;
+ }
+
+ $p = $this->valueWithMinScale($that->scale + $scale);
+ $q = $that->valueWithMinScale($this->scale - $scale);
+
+ $result = CalculatorRegistry::get()->divRound($p, $q, $roundingMode);
+
+ return new BigDecimal($result, $scale);
+ }
+
+ /**
+ * Returns the exact result of the division of this number by the given one.
+ *
+ * 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.
+ *
+ * @throws MathException If the divisor is not a valid number, is not convertible to a BigDecimal, is zero,
+ * or the result yields an infinite number of digits.
+ *
+ * @pure
+ */
+ public function exactlyDividedBy(BigNumber|int|float|string $that) : BigDecimal
+ {
+ $that = BigDecimal::of($that);
+
+ if ($that->value === '0') {
+ throw DivisionByZeroException::divisionByZero();
+ }
+
+ [, $b] = $this->scaleValues($this, $that);
+
+ $d = \rtrim($b, '0');
+ $scale = \strlen($b) - \strlen($d);
+
+ $calculator = CalculatorRegistry::get();
+
+ foreach ([5, 2] as $prime) {
+ for (;;) {
+ $lastDigit = (int) $d[-1];
+
+ if ($lastDigit % $prime !== 0) {
+ break;
+ }
+
+ $d = $calculator->divQ($d, (string) $prime);
+ $scale++;
+ }
+ }
+
+ return $this->dividedBy($that, $scale)->stripTrailingZeros();
+ }
+
+ /**
+ * Limits (clamps) this number between the given minimum and maximum values.
+ *
+ * If the number is lower than $min, returns a copy of $min.
+ * If the number is greater than $max, returns a copy of $max.
+ * Otherwise, returns this number unchanged.
+ *
+ * @param BigNumber|int|float|string $min The minimum. Must be convertible to a BigDecimal.
+ * @param BigNumber|int|float|string $max The maximum. Must be convertible to a BigDecimal.
+ *
+ * @throws MathException If min/max are not convertible to a BigDecimal.
+ */
+ public function clamp(BigNumber|int|float|string $min, BigNumber|int|float|string $max) : BigDecimal
+ {
+ if ($this->isLessThan($min)) {
+ return BigDecimal::of($min);
+ } elseif ($this->isGreaterThan($max)) {
+ return BigDecimal::of($max);
+ }
+ return $this;
+ }
+
+ /**
+ * Returns this number exponentiated to the given value.
+ *
+ * The result has a scale of `$this->scale * $exponent`.
+ *
+ * @throws \InvalidArgumentException If the exponent is not in the range 0 to 1,000,000.
+ *
+ * @pure
+ */
+ public function power(int $exponent) : BigDecimal
+ {
+ if ($exponent === 0) {
+ return BigDecimal::one();
+ }
+
+ if ($exponent === 1) {
+ 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
+ ));
+ }
+
+ return new BigDecimal(CalculatorRegistry::get()->pow($this->value, $exponent), $this->scale * $exponent);
+ }
+
+ /**
+ * Returns the quotient of the division of this number by the given one.
+ *
+ * The quotient has a scale of `0`.
+ *
+ * @param BigNumber|int|float|string $that The divisor. Must be convertible to a BigDecimal.
+ *
+ * @throws MathException If the divisor is not a valid decimal number, or is zero.
+ *
+ * @pure
+ */
+ public function quotient(BigNumber|int|float|string $that) : BigDecimal
+ {
+ $that = BigDecimal::of($that);
+
+ if ($that->isZero()) {
+ throw DivisionByZeroException::divisionByZero();
+ }
+
+ $p = $this->valueWithMinScale($that->scale);
+ $q = $that->valueWithMinScale($this->scale);
+
+ $quotient = CalculatorRegistry::get()->divQ($p, $q);
+
+ return new BigDecimal($quotient, 0);
+ }
+
+ /**
+ * Returns the remainder of the division of this number by the given one.
+ *
+ * The remainder has a scale of `max($this->scale, $that->scale)`.
+ *
+ * @param BigNumber|int|float|string $that The divisor. Must be convertible to a BigDecimal.
+ *
+ * @throws MathException If the divisor is not a valid decimal number, or is zero.
+ *
+ * @pure
+ */
+ public function remainder(BigNumber|int|float|string $that) : BigDecimal
+ {
+ $that = BigDecimal::of($that);
+
+ if ($that->isZero()) {
+ throw DivisionByZeroException::divisionByZero();
+ }
+
+ $p = $this->valueWithMinScale($that->scale);
+ $q = $that->valueWithMinScale($this->scale);
+
+ $remainder = CalculatorRegistry::get()->divR($p, $q);
+
+ $scale = $this->scale > $that->scale ? $this->scale : $that->scale;
+
+ return new BigDecimal($remainder, $scale);
+ }
+
+ /**
+ * Returns the quotient and remainder of the division of this number by the given one.
+ *
+ * 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.
+ *
+ * @return array{BigDecimal, BigDecimal} An array containing the quotient and the remainder.
+ *
+ * @throws MathException If the divisor is not a valid decimal number, or is zero.
+ *
+ * @pure
+ */
+ public function quotientAndRemainder(BigNumber|int|float|string $that) : array
+ {
+ $that = BigDecimal::of($that);
+
+ if ($that->isZero()) {
+ throw DivisionByZeroException::divisionByZero();
+ }
+
+ $p = $this->valueWithMinScale($that->scale);
+ $q = $that->valueWithMinScale($this->scale);
+
+ [$quotient, $remainder] = CalculatorRegistry::get()->divQR($p, $q);
+
+ $scale = $this->scale > $that->scale ? $this->scale : $that->scale;
+
+ $quotient = new BigDecimal($quotient, 0);
+ $remainder = new BigDecimal($remainder, $scale);
+
+ return [$quotient, $remainder];
+ }
+
+ /**
+ * Returns the square root of this number, rounded down to the given number of decimals.
+ *
+ * @throws \InvalidArgumentException If the scale is negative.
+ * @throws NegativeNumberException If this number is negative.
+ *
+ * @pure
+ */
+ public function sqrt(int $scale) : BigDecimal
+ {
+ if ($scale < 0) {
+ throw new \InvalidArgumentException('Scale cannot be negative.');
+ }
+
+ if ($this->value === '0') {
+ return new BigDecimal('0', $scale);
+ }
+
+ if ($this->value[0] === '-') {
+ throw new NegativeNumberException('Cannot calculate the square root of a negative number.');
+ }
+
+ $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);
+ }
+
+ $value = \substr($value, 0, $addDigits);
+ }
+
+ $value = CalculatorRegistry::get()->sqrt($value);
+
+ return new BigDecimal($value, $scale);
+ }
+
+ /**
+ * Returns a copy of this BigDecimal with the decimal point moved $n places to the left.
+ *
+ * @pure
+ */
+ public function withPointMovedLeft(int $n) : BigDecimal
+ {
+ if ($n === 0) {
+ return $this;
+ }
+
+ if ($n < 0) {
+ return $this->withPointMovedRight(-$n);
+ }
+
+ return new BigDecimal($this->value, $this->scale + $n);
+ }
+
+ /**
+ * Returns a copy of this BigDecimal with the decimal point moved $n places to the right.
+ *
+ * @pure
+ */
+ public function withPointMovedRight(int $n) : BigDecimal
+ {
+ if ($n === 0) {
+ return $this;
+ }
+
+ if ($n < 0) {
+ return $this->withPointMovedLeft(-$n);
+ }
+
+ $value = $this->value;
+ $scale = $this->scale - $n;
+
+ if ($scale < 0) {
+ if ($value !== '0') {
+ $value .= \str_repeat('0', -$scale);
+ }
+ $scale = 0;
+ }
+
+ return new BigDecimal($value, $scale);
+ }
+
+ /**
+ * Returns a copy of this BigDecimal with any trailing zeros removed from the fractional part.
+ *
+ * @pure
+ */
+ public function stripTrailingZeros() : BigDecimal
+ {
+ if ($this->scale === 0) {
+ return $this;
+ }
+
+ $trimmedValue = \rtrim($this->value, '0');
+
+ if ($trimmedValue === '') {
+ return BigDecimal::zero();
+ }
+
+ $trimmableZeros = \strlen($this->value) - \strlen($trimmedValue);
+
+ if ($trimmableZeros === 0) {
+ return $this;
+ }
+
+ if ($trimmableZeros > $this->scale) {
+ $trimmableZeros = $this->scale;
+ }
+
+ $value = \substr($this->value, 0, -$trimmableZeros);
+ $scale = $this->scale - $trimmableZeros;
+
+ return new BigDecimal($value, $scale);
+ }
+
+ /**
+ * Returns the absolute value of this number.
+ *
+ * @pure
+ */
+ public function abs() : BigDecimal
+ {
+ return $this->isNegative() ? $this->negated() : $this;
+ }
+
+ /**
+ * Returns the negated value of this number.
+ *
+ * @pure
+ */
+ public function negated() : BigDecimal
+ {
+ return new BigDecimal(CalculatorRegistry::get()->neg($this->value), $this->scale);
+ }
+
+ #[Override]
+ public function compareTo(BigNumber|int|float|string $that) : int
+ {
+ $that = BigNumber::of($that);
+
+ if ($that instanceof BigInteger) {
+ $that = $that->toBigDecimal();
+ }
+
+ if ($that instanceof BigDecimal) {
+ [$a, $b] = $this->scaleValues($this, $that);
+
+ return CalculatorRegistry::get()->cmp($a, $b);
+ }
+
+ return - $that->compareTo($this);
+ }
+
+ #[Override]
+ public function getSign() : int
+ {
+ return ($this->value === '0') ? 0 : (($this->value[0] === '-') ? -1 : 1);
+ }
+
+ /**
+ * @pure
+ */
+ public function getUnscaledValue() : BigInteger
+ {
+ return self::newBigInteger($this->value);
+ }
+
+ /**
+ * @pure
+ */
+ public function getScale() : int
+ {
+ return $this->scale;
+ }
+
+ /**
+ * Returns the number of significant digits in the number.
+ *
+ * This is the number of digits to both sides of the decimal point, stripped of leading zeros.
+ * The sign has no impact on the result.
+ *
+ * Examples:
+ * 0 => 0
+ * 0.0 => 0
+ * 123 => 3
+ * 123.456 => 6
+ * 0.00123 => 3
+ * 0.0012300 => 5
+ *
+ * @pure
+ */
+ public function getPrecision(): int
+ {
+ $value = $this->value;
+
+ if ($value === '0') {
+ return 0;
+ }
+
+ $length = \strlen($value);
+
+ return ($value[0] === '-') ? $length - 1 : $length;
+ }
+
+ /**
+ * Returns a string representing the integral part of this decimal number.
+ *
+ * Example: `-123.456` => `-123`.
+ *
+ * @pure
+ */
+ public function getIntegralPart() : string
+ {
+ if ($this->scale === 0) {
+ return $this->value;
+ }
+
+ $value = $this->getUnscaledValueWithLeadingZeros();
+
+ return \substr($value, 0, -$this->scale);
+ }
+
+ /**
+ * Returns a string representing the fractional part of this decimal number.
+ *
+ * If the scale is zero, an empty string is returned.
+ *
+ * Examples: `-123.456` => '456', `123` => ''.
+ *
+ * @pure
+ */
+ public function getFractionalPart() : string
+ {
+ if ($this->scale === 0) {
+ return '';
+ }
+
+ $value = $this->getUnscaledValueWithLeadingZeros();
+
+ return \substr($value, -$this->scale);
+ }
+
+ /**
+ * Returns whether this decimal number has a non-zero fractional part.
+ *
+ * @pure
+ */
+ public function hasNonZeroFractionalPart() : bool
+ {
+ return $this->getFractionalPart() !== \str_repeat('0', $this->scale);
+ }
+
+ #[Override]
+ public function toBigInteger() : BigInteger
+ {
+ $zeroScaleDecimal = $this->scale === 0 ? $this : $this->dividedBy(1, 0);
+
+ return self::newBigInteger($zeroScaleDecimal->value);
+ }
+
+ #[Override]
+ public function toBigDecimal() : BigDecimal
+ {
+ return $this;
+ }
+
+ #[Override]
+ public function toBigRational() : BigRational
+ {
+ $numerator = self::newBigInteger($this->value);
+ $denominator = self::newBigInteger('1' . \str_repeat('0', $this->scale));
+
+ return self::newBigRational($numerator, $denominator, false);
+ }
+
+ #[Override]
+ public function toScale(int $scale, RoundingMode $roundingMode = RoundingMode::UNNECESSARY) : BigDecimal
+ {
+ if ($scale === $this->scale) {
+ return $this;
+ }
+
+ return $this->dividedBy(BigDecimal::one(), $scale, $roundingMode);
+ }
+
+ #[Override]
+ public function toInt() : int
+ {
+ return $this->toBigInteger()->toInt();
+ }
+
+ #[Override]
+ public function toFloat() : float
+ {
+ return (float) (string) $this;
+ }
+
+ /**
+ * @return numeric-string
+ */
+ #[Override]
+ public function __toString() : string
+ {
+ if ($this->scale === 0) {
+ /** @var numeric-string */
+ return $this->value;
+ }
+
+ $value = $this->getUnscaledValueWithLeadingZeros();
+
+ /** @phpstan-ignore return.type */
+ return \substr($value, 0, -$this->scale) . '.' . \substr($value, -$this->scale);
+ }
+
+ /**
+ * This method is required for serializing the object and SHOULD NOT be accessed directly.
+ *
+ * @internal
+ *
+ * @return array{value: string, scale: int}
+ */
+ public function __serialize(): array
+ {
+ return ['value' => $this->value, 'scale' => $this->scale];
+ }
+
+ /**
+ * This method is only here to allow unserializing the object and cannot be accessed directly.
+ *
+ * @internal
+ *
+ * @param array{value: string, scale: int} $data
+ *
+ * @throws \LogicException
+ */
+ public function __unserialize(array $data): void
+ {
+ /** @phpstan-ignore isset.initializedProperty */
+ if (isset($this->value)) {
+ throw new \LogicException('__unserialize() is an internal function, it must not be called directly.');
+ }
+
+ /** @phpstan-ignore deadCode.unreachable */
+ $this->value = $data['value'];
+ $this->scale = $data['scale'];
+ }
+
+ /**
+ * 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
+ {
+ $a = $x->value;
+ $b = $y->value;
+
+ if ($b !== '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);
+ }
+
+ return [$a, $b];
+ }
+
+ /**
+ * @pure
+ */
+ private function valueWithMinScale(int $scale) : string
+ {
+ $value = $this->value;
+
+ if ($this->value !== '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
+ {
+ $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;
+ }
+}
diff --git a/vendor/brick/math/src/BigInteger.php b/vendor/brick/math/src/BigInteger.php
new file mode 100644
index 0000000..48a7bb3
--- /dev/null
+++ b/vendor/brick/math/src/BigInteger.php
@@ -0,0 +1,1139 @@
+value = $value;
+ }
+
+ #[Override]
+ protected static function from(BigNumber $number): static
+ {
+ return $number->toBigInteger();
+ }
+
+ /**
+ * Creates a number from a string in a given base.
+ *
+ * The string can optionally be prefixed with the `+` or `-` sign.
+ *
+ * Bases greater than 36 are not supported by this method, as there is no clear consensus on which of the lowercase
+ * or uppercase characters should come first. Instead, this method accepts any base up to 36, and does not
+ * differentiate lowercase and uppercase characters, which are considered equal.
+ *
+ * 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.
+ *
+ * @throws NumberFormatException If the number is empty, or contains invalid chars for the given base.
+ * @throws \InvalidArgumentException If the base is out of range.
+ *
+ * @pure
+ */
+ public static function fromBase(string $number, int $base) : BigInteger
+ {
+ if ($number === '') {
+ throw new NumberFormatException('The number cannot be empty.');
+ }
+
+ if ($base < 2 || $base > 36) {
+ throw new \InvalidArgumentException(\sprintf('Base %d is not in range 2 to 36.', $base));
+ }
+
+ if ($number[0] === '-') {
+ $sign = '-';
+ $number = \substr($number, 1);
+ } elseif ($number[0] === '+') {
+ $sign = '';
+ $number = \substr($number, 1);
+ } else {
+ $sign = '';
+ }
+
+ if ($number === '') {
+ throw new NumberFormatException('The number cannot be empty.');
+ }
+
+ $number = \ltrim($number, '0');
+
+ if ($number === '') {
+ // The result will be the same in any base, avoid further calculation.
+ return BigInteger::zero();
+ }
+
+ if ($number === '1') {
+ // The result will be the same in any base, avoid further calculation.
+ return new BigInteger($sign . '1');
+ }
+
+ $pattern = '/[^' . \substr(Calculator::ALPHABET, 0, $base) . ']/';
+
+ 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 ($base === 10) {
+ // The number is usable as is, avoid further calculation.
+ return new BigInteger($sign . $number);
+ }
+
+ $result = CalculatorRegistry::get()->fromBase($number, $base);
+
+ return new BigInteger($sign . $result);
+ }
+
+ /**
+ * 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.
+ *
+ * @param string $number The number to parse.
+ * @param 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.
+ *
+ * @pure
+ */
+ 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 new \InvalidArgumentException('The alphabet must contain at least 2 chars.');
+ }
+
+ $pattern = '/[^' . \preg_quote($alphabet, '/') . ']/';
+
+ if (\preg_match($pattern, $number, $matches) === 1) {
+ throw NumberFormatException::charNotInAlphabet($matches[0]);
+ }
+
+ $number = CalculatorRegistry::get()->fromArbitraryBase($number, $alphabet, $base);
+
+ return new BigInteger($number);
+ }
+
+ /**
+ * Translates a string of bytes containing the binary representation of a BigInteger into a BigInteger.
+ *
+ * The input string is assumed to be in big-endian byte-order: the most significant byte is in the zeroth element.
+ *
+ * If `$signed` is true, the input is assumed to be in two's-complement representation, and the leading bit is
+ * interpreted as a sign bit. If `$signed` is false, the input is interpreted as an unsigned number, and the
+ * resulting BigInteger will always be positive or zero.
+ *
+ * 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.
+ *
+ * @throws NumberFormatException If the string is empty.
+ *
+ * @pure
+ */
+ public static function fromBytes(string $value, bool $signed = true) : BigInteger
+ {
+ if ($value === '') {
+ throw new NumberFormatException('The byte string must not be empty.');
+ }
+
+ $twosComplement = false;
+
+ if ($signed) {
+ $x = \ord($value[0]);
+
+ if (($twosComplement = ($x >= 0x80))) {
+ $value = ~$value;
+ }
+ }
+
+ $number = self::fromBase(\bin2hex($value), 16);
+
+ if ($twosComplement) {
+ return $number->plus(1)->negated();
+ }
+
+ return $number;
+ }
+
+ /**
+ * Generates a pseudo-random number in the range 0 to 2^numBits - 1.
+ *
+ * Using the default random bytes generator, this method is suitable for cryptographic use.
+ *
+ * @param int $numBits The number of bits.
+ * @param (callable(int): string)|null $randomBytesGenerator A function that accepts a number of bytes, and returns
+ * a string of random bytes of the given length. Defaults
+ * to the `random_bytes()` function.
+ *
+ * @throws \InvalidArgumentException If $numBits is negative.
+ */
+ public static function randomBits(int $numBits, ?callable $randomBytesGenerator = null) : BigInteger
+ {
+ if ($numBits < 0) {
+ throw new \InvalidArgumentException('The number of bits cannot be negative.');
+ }
+
+ if ($numBits === 0) {
+ return BigInteger::zero();
+ }
+
+ if ($randomBytesGenerator === null) {
+ $randomBytesGenerator = random_bytes(...);
+ }
+
+ /** @var int<1, max> $byteLength */
+ $byteLength = \intdiv($numBits - 1, 8) + 1;
+
+ $extraBits = ($byteLength * 8 - $numBits);
+ $bitmask = \chr(0xFF >> $extraBits);
+
+ $randomBytes = $randomBytesGenerator($byteLength);
+ $randomBytes[0] = $randomBytes[0] & $bitmask;
+
+ return self::fromBytes($randomBytes, false);
+ }
+
+ /**
+ * Generates a pseudo-random number between `$min` and `$max`.
+ *
+ * Using the default random bytes generator, this method is suitable for cryptographic use.
+ *
+ * @param BigNumber|int|float|string $min The lower bound. Must be convertible to a BigInteger.
+ * @param BigNumber|int|float|string $max The upper bound. Must be convertible to a BigInteger.
+ * @param (callable(int): string)|null $randomBytesGenerator A function that accepts a number of bytes, and returns
+ * a string of random bytes of the given length. Defaults
+ * to the `random_bytes()` function.
+ *
+ * @throws MathException If one of the parameters cannot be converted to a BigInteger,
+ * or `$min` is greater than `$max`.
+ */
+ public static function randomRange(
+ BigNumber|int|float|string $min,
+ BigNumber|int|float|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.');
+ }
+
+ if ($min->isEqualTo($max)) {
+ return $min;
+ }
+
+ $diff = $max->minus($min);
+ $bitLength = $diff->getBitLength();
+
+ // try until the number is in range (50% to 100% chance of success)
+ do {
+ $randomNumber = self::randomBits($bitLength, $randomBytesGenerator);
+ } while ($randomNumber->isGreaterThan($diff));
+
+ return $randomNumber->plus($min);
+ }
+
+ /**
+ * Returns a BigInteger representing zero.
+ *
+ * @pure
+ */
+ public static function zero() : BigInteger
+ {
+ /** @var BigInteger|null $zero */
+ static $zero;
+
+ if ($zero === null) {
+ $zero = new BigInteger('0');
+ }
+
+ return $zero;
+ }
+
+ /**
+ * Returns a BigInteger representing one.
+ *
+ * @pure
+ */
+ public static function one() : BigInteger
+ {
+ /** @var BigInteger|null $one */
+ static $one;
+
+ if ($one === null) {
+ $one = new BigInteger('1');
+ }
+
+ return $one;
+ }
+
+ /**
+ * Returns a BigInteger representing ten.
+ *
+ * @pure
+ */
+ public static function ten() : BigInteger
+ {
+ /** @var BigInteger|null $ten */
+ static $ten;
+
+ if ($ten === null) {
+ $ten = new BigInteger('10');
+ }
+
+ return $ten;
+ }
+
+ /**
+ * @pure
+ */
+ public static function gcdMultiple(BigInteger $a, BigInteger ...$n): BigInteger
+ {
+ $result = $a;
+
+ foreach ($n as $next) {
+ $result = $result->gcd($next);
+
+ if ($result->isEqualTo(1)) {
+ return $result;
+ }
+ }
+
+ return $result;
+ }
+
+ /**
+ * Returns the sum of this number and the given one.
+ *
+ * @param BigNumber|int|float|string $that The number to add. Must be convertible to a BigInteger.
+ *
+ * @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
+ {
+ $that = BigInteger::of($that);
+
+ if ($that->value === '0') {
+ return $this;
+ }
+
+ if ($this->value === '0') {
+ return $that;
+ }
+
+ $value = CalculatorRegistry::get()->add($this->value, $that->value);
+
+ return new BigInteger($value);
+ }
+
+ /**
+ * 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.
+ *
+ * @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
+ {
+ $that = BigInteger::of($that);
+
+ if ($that->value === '0') {
+ return $this;
+ }
+
+ $value = CalculatorRegistry::get()->sub($this->value, $that->value);
+
+ return new BigInteger($value);
+ }
+
+ /**
+ * Returns the product of this number and the given one.
+ *
+ * @param BigNumber|int|float|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.
+ *
+ * @pure
+ */
+ public function multipliedBy(BigNumber|int|float|string $that) : BigInteger
+ {
+ $that = BigInteger::of($that);
+
+ if ($that->value === '1') {
+ return $this;
+ }
+
+ if ($this->value === '1') {
+ return $that;
+ }
+
+ $value = CalculatorRegistry::get()->mul($this->value, $that->value);
+
+ return new BigInteger($value);
+ }
+
+ /**
+ * 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.
+ *
+ * @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
+ {
+ $that = BigInteger::of($that);
+
+ if ($that->value === '1') {
+ return $this;
+ }
+
+ if ($that->value === '0') {
+ throw DivisionByZeroException::divisionByZero();
+ }
+
+ $result = CalculatorRegistry::get()->divRound($this->value, $that->value, $roundingMode);
+
+ return new BigInteger($result);
+ }
+
+ /**
+ * Limits (clamps) this number between the given minimum and maximum values.
+ *
+ * If the number is lower than $min, returns a copy of $min.
+ * If the number is greater than $max, returns a copy of $max.
+ * Otherwise, returns this number unchanged.
+ *
+ * @param BigNumber|int|float|string $min The minimum. Must be convertible to a BigInteger.
+ * @param BigNumber|int|float|string $max The maximum. Must be convertible to a BigInteger.
+ *
+ * @throws MathException If min/max are not convertible to a BigInteger.
+ */
+ public function clamp(BigNumber|int|float|string $min, BigNumber|int|float|string $max) : BigInteger
+ {
+ if ($this->isLessThan($min)) {
+ return BigInteger::of($min);
+ } elseif ($this->isGreaterThan($max)) {
+ return BigInteger::of($max);
+ }
+ return $this;
+ }
+
+
+ /**
+ * Returns this number exponentiated to the given value.
+ *
+ * @throws \InvalidArgumentException If the exponent is not in the range 0 to 1,000,000.
+ *
+ * @pure
+ */
+ public function power(int $exponent) : BigInteger
+ {
+ if ($exponent === 0) {
+ return BigInteger::one();
+ }
+
+ if ($exponent === 1) {
+ 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
+ ));
+ }
+
+ 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.
+ *
+ * @throws DivisionByZeroException If the divisor is zero.
+ *
+ * @pure
+ */
+ public function quotient(BigNumber|int|float|string $that) : BigInteger
+ {
+ $that = BigInteger::of($that);
+
+ if ($that->value === '1') {
+ return $this;
+ }
+
+ if ($that->value === '0') {
+ throw DivisionByZeroException::divisionByZero();
+ }
+
+ $quotient = CalculatorRegistry::get()->divQ($this->value, $that->value);
+
+ return new BigInteger($quotient);
+ }
+
+ /**
+ * Returns the remainder of the division of this number by the given one.
+ *
+ * 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.
+ *
+ * @throws DivisionByZeroException If the divisor is zero.
+ *
+ * @pure
+ */
+ public function remainder(BigNumber|int|float|string $that) : BigInteger
+ {
+ $that = BigInteger::of($that);
+
+ if ($that->value === '1') {
+ return BigInteger::zero();
+ }
+
+ if ($that->value === '0') {
+ throw DivisionByZeroException::divisionByZero();
+ }
+
+ $remainder = CalculatorRegistry::get()->divR($this->value, $that->value);
+
+ return new BigInteger($remainder);
+ }
+
+ /**
+ * 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.
+ *
+ * @return array{BigInteger, BigInteger} An array containing the quotient and the remainder.
+ *
+ * @throws DivisionByZeroException If the divisor is zero.
+ *
+ * @pure
+ */
+ public function quotientAndRemainder(BigNumber|int|float|string $that) : array
+ {
+ $that = BigInteger::of($that);
+
+ if ($that->value === '0') {
+ throw DivisionByZeroException::divisionByZero();
+ }
+
+ [$quotient, $remainder] = CalculatorRegistry::get()->divQR($this->value, $that->value);
+
+ return [
+ new BigInteger($quotient),
+ new BigInteger($remainder)
+ ];
+ }
+
+ /**
+ * Returns the modulo of this number and 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 of the modulo operation, when non-zero, has the same sign as the divisor.
+ *
+ * @param BigNumber|int|float|string $that The divisor. Must be convertible to a BigInteger.
+ *
+ * @throws DivisionByZeroException If the divisor is zero.
+ *
+ * @pure
+ */
+ public function mod(BigNumber|int|float|string $that) : BigInteger
+ {
+ $that = BigInteger::of($that);
+
+ if ($that->value === '0') {
+ throw DivisionByZeroException::modulusMustNotBeZero();
+ }
+
+ $value = CalculatorRegistry::get()->mod($this->value, $that->value);
+
+ return new BigInteger($value);
+ }
+
+ /**
+ * Returns the modular multiplicative inverse of this BigInteger modulo $m.
+ *
+ * @throws DivisionByZeroException If $m is zero.
+ * @throws NegativeNumberException If $m is negative.
+ * @throws MathException If this BigInteger has no multiplicative inverse mod m (that is, this BigInteger
+ * is not relatively prime to m).
+ *
+ * @pure
+ */
+ public function modInverse(BigInteger $m) : BigInteger
+ {
+ if ($m->value === '0') {
+ throw DivisionByZeroException::modulusMustNotBeZero();
+ }
+
+ if ($m->isNegative()) {
+ throw new NegativeNumberException('Modulus must not be negative.');
+ }
+
+ if ($m->value === '1') {
+ return BigInteger::zero();
+ }
+
+ $value = CalculatorRegistry::get()->modInverse($this->value, $m->value);
+
+ if ($value === null) {
+ throw new MathException('Unable to compute the modInverse for the given modulus.');
+ }
+
+ return new BigInteger($value);
+ }
+
+ /**
+ * Returns this number raised into power with modulo.
+ *
+ * This operation only works on positive numbers.
+ *
+ * @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.
+ *
+ * @throws NegativeNumberException If any of the operands is negative.
+ * @throws DivisionByZeroException If the modulus is zero.
+ *
+ * @pure
+ */
+ public function modPow(BigNumber|int|float|string $exp, BigNumber|int|float|string $mod) : BigInteger
+ {
+ $exp = BigInteger::of($exp);
+ $mod = BigInteger::of($mod);
+
+ if ($this->isNegative() || $exp->isNegative() || $mod->isNegative()) {
+ throw new NegativeNumberException('The operands cannot be negative.');
+ }
+
+ if ($mod->isZero()) {
+ throw DivisionByZeroException::modulusMustNotBeZero();
+ }
+
+ $result = CalculatorRegistry::get()->modPow($this->value, $exp->value, $mod->value);
+
+ return new BigInteger($result);
+ }
+
+ /**
+ * Returns the greatest common divisor of this number and the given one.
+ *
+ * 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.
+ *
+ * @pure
+ */
+ public function gcd(BigNumber|int|float|string $that) : BigInteger
+ {
+ $that = BigInteger::of($that);
+
+ if ($that->value === '0' && $this->value[0] !== '-') {
+ return $this;
+ }
+
+ if ($this->value === '0' && $that->value[0] !== '-') {
+ return $that;
+ }
+
+ $value = CalculatorRegistry::get()->gcd($this->value, $that->value);
+
+ return new BigInteger($value);
+ }
+
+ /**
+ * Returns the integer square root number of this number, rounded down.
+ *
+ * The result is the largest x such that x² ≤ n.
+ *
+ * @throws NegativeNumberException If this number is negative.
+ *
+ * @pure
+ */
+ public function sqrt() : BigInteger
+ {
+ if ($this->value[0] === '-') {
+ throw new NegativeNumberException('Cannot calculate the square root of a negative number.');
+ }
+
+ $value = CalculatorRegistry::get()->sqrt($this->value);
+
+ return new BigInteger($value);
+ }
+
+ /**
+ * Returns the absolute value of this number.
+ *
+ * @pure
+ */
+ public function abs() : BigInteger
+ {
+ return $this->isNegative() ? $this->negated() : $this;
+ }
+
+ /**
+ * Returns the inverse of this number.
+ *
+ * @pure
+ */
+ public function negated() : BigInteger
+ {
+ return new BigInteger(CalculatorRegistry::get()->neg($this->value));
+ }
+
+ /**
+ * Returns the integer bitwise-and combined with another integer.
+ *
+ * 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.
+ *
+ * @pure
+ */
+ public function and(BigNumber|int|float|string $that) : BigInteger
+ {
+ $that = BigInteger::of($that);
+
+ return new BigInteger(CalculatorRegistry::get()->and($this->value, $that->value));
+ }
+
+ /**
+ * Returns the integer bitwise-or combined with another integer.
+ *
+ * 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.
+ *
+ * @pure
+ */
+ public function or(BigNumber|int|float|string $that) : BigInteger
+ {
+ $that = BigInteger::of($that);
+
+ return new BigInteger(CalculatorRegistry::get()->or($this->value, $that->value));
+ }
+
+ /**
+ * Returns the integer bitwise-xor combined with another integer.
+ *
+ * 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.
+ *
+ * @pure
+ */
+ public function xor(BigNumber|int|float|string $that) : BigInteger
+ {
+ $that = BigInteger::of($that);
+
+ return new BigInteger(CalculatorRegistry::get()->xor($this->value, $that->value));
+ }
+
+ /**
+ * Returns the bitwise-not of this BigInteger.
+ *
+ * @pure
+ */
+ public function not() : BigInteger
+ {
+ return $this->negated()->minus(1);
+ }
+
+ /**
+ * Returns the integer left shifted by a given number of bits.
+ *
+ * @pure
+ */
+ public function shiftedLeft(int $distance) : BigInteger
+ {
+ if ($distance === 0) {
+ return $this;
+ }
+
+ if ($distance < 0) {
+ return $this->shiftedRight(- $distance);
+ }
+
+ return $this->multipliedBy(BigInteger::of(2)->power($distance));
+ }
+
+ /**
+ * Returns the integer right shifted by a given number of bits.
+ *
+ * @pure
+ */
+ public function shiftedRight(int $distance) : BigInteger
+ {
+ if ($distance === 0) {
+ return $this;
+ }
+
+ if ($distance < 0) {
+ return $this->shiftedLeft(- $distance);
+ }
+
+ $operand = BigInteger::of(2)->power($distance);
+
+ if ($this->isPositiveOrZero()) {
+ return $this->quotient($operand);
+ }
+
+ return $this->dividedBy($operand, RoundingMode::UP);
+ }
+
+ /**
+ * Returns the number of bits in the minimal two's-complement representation of this BigInteger, excluding a sign bit.
+ *
+ * For positive BigIntegers, this is equivalent to the number of bits in the ordinary binary representation.
+ * Computes (ceil(log2(this < 0 ? -this : this+1))).
+ *
+ * @pure
+ */
+ public function getBitLength() : int
+ {
+ if ($this->value === '0') {
+ return 0;
+ }
+
+ if ($this->isNegative()) {
+ return $this->abs()->minus(1)->getBitLength();
+ }
+
+ 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.
+ *
+ * @pure
+ */
+ public function getLowestSetBit() : int
+ {
+ $n = $this;
+ $bitLength = $this->getBitLength();
+
+ for ($i = 0; $i <= $bitLength; $i++) {
+ if ($n->isOdd()) {
+ return $i;
+ }
+
+ $n = $n->shiftedRight(1);
+ }
+
+ return -1;
+ }
+
+ /**
+ * Returns whether this number is even.
+ *
+ * @pure
+ */
+ public function isEven() : bool
+ {
+ return \in_array($this->value[-1], ['0', '2', '4', '6', '8'], true);
+ }
+
+ /**
+ * Returns whether this number is odd.
+ *
+ * @pure
+ */
+ public function isOdd() : bool
+ {
+ return \in_array($this->value[-1], ['1', '3', '5', '7', '9'], true);
+ }
+
+ /**
+ * Returns true if and only if the designated bit is set.
+ *
+ * Computes ((this & (1<
shiftedRight($n)->isOdd();
+ }
+
+ #[Override]
+ public function compareTo(BigNumber|int|float|string $that) : int
+ {
+ $that = BigNumber::of($that);
+
+ if ($that instanceof BigInteger) {
+ return CalculatorRegistry::get()->cmp($this->value, $that->value);
+ }
+
+ return - $that->compareTo($this);
+ }
+
+ #[Override]
+ public function getSign() : int
+ {
+ return ($this->value === '0') ? 0 : (($this->value[0] === '-') ? -1 : 1);
+ }
+
+ #[Override]
+ public function toBigInteger() : BigInteger
+ {
+ return $this;
+ }
+
+ #[Override]
+ public function toBigDecimal() : BigDecimal
+ {
+ return self::newBigDecimal($this->value);
+ }
+
+ #[Override]
+ public function toBigRational() : BigRational
+ {
+ return self::newBigRational($this, BigInteger::one(), false);
+ }
+
+ #[Override]
+ public function toScale(int $scale, RoundingMode $roundingMode = RoundingMode::UNNECESSARY) : BigDecimal
+ {
+ return $this->toBigDecimal()->toScale($scale, $roundingMode);
+ }
+
+ #[Override]
+ public function toInt() : int
+ {
+ $intValue = (int) $this->value;
+
+ if ($this->value !== (string) $intValue) {
+ throw IntegerOverflowException::toIntOverflow($this);
+ }
+
+ return $intValue;
+ }
+
+ #[Override]
+ public function toFloat() : float
+ {
+ return (float) $this->value;
+ }
+
+ /**
+ * Returns a string representation of this number in the given base.
+ *
+ * The output will always be lowercase for bases greater than 10.
+ *
+ * @throws \InvalidArgumentException If the base is out of range.
+ *
+ * @pure
+ */
+ public function toBase(int $base) : string
+ {
+ if ($base === 10) {
+ return $this->value;
+ }
+
+ if ($base < 2 || $base > 36) {
+ throw new \InvalidArgumentException(\sprintf('Base %d is out of range [2, 36]', $base));
+ }
+
+ 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;
+ * 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.
+ *
+ * @throws NegativeNumberException If this number is negative.
+ * @throws \InvalidArgumentException If the given alphabet does not contain at least 2 chars.
+ *
+ * @pure
+ */
+ public function toArbitraryBase(string $alphabet) : string
+ {
+ $base = \strlen($alphabet);
+
+ if ($base < 2) {
+ throw new \InvalidArgumentException('The alphabet must contain at least 2 chars.');
+ }
+
+ if ($this->value[0] === '-') {
+ throw new NegativeNumberException(__FUNCTION__ . '() does not support negative numbers.');
+ }
+
+ return CalculatorRegistry::get()->toArbitraryBase($this->value, $alphabet, $base);
+ }
+
+ /**
+ * Returns a string of bytes containing the binary representation of this BigInteger.
+ *
+ * The string is in big-endian byte-order: the most significant byte is in the zeroth element.
+ *
+ * If `$signed` is true, the output will be in two's-complement representation, and a sign bit will be prepended to
+ * the output. If `$signed` is false, no sign bit will be prepended, and this method will throw an exception if the
+ * number is negative.
+ *
+ * The string will contain the minimum number of bytes required to represent this BigInteger, including a sign bit
+ * if `$signed` is true.
+ *
+ * This representation is compatible with the `fromBytes()` factory method, as long as the `$signed` flags match.
+ *
+ * @param bool $signed Whether to output a signed number in two's-complement representation with a leading sign bit.
+ *
+ * @throws NegativeNumberException If $signed is false, and the number is negative.
+ *
+ * @pure
+ */
+ 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.');
+ }
+
+ $hex = $this->abs()->toBase(16);
+
+ if (\strlen($hex) % 2 !== 0) {
+ $hex = '0' . $hex;
+ }
+
+ $baseHexLength = \strlen($hex);
+
+ if ($signed) {
+ if ($this->isNegative()) {
+ $bin = \hex2bin($hex);
+ assert($bin !== false);
+
+ $hex = \bin2hex(~$bin);
+ $hex = self::fromBase($hex, 16)->plus(1)->toBase(16);
+
+ $hexLength = \strlen($hex);
+
+ if ($hexLength < $baseHexLength) {
+ $hex = \str_repeat('0', $baseHexLength - $hexLength) . $hex;
+ }
+
+ if ($hex[0] < '8') {
+ $hex = 'FF' . $hex;
+ }
+ } else {
+ if ($hex[0] >= '8') {
+ $hex = '00' . $hex;
+ }
+ }
+ }
+
+ $result = \hex2bin($hex);
+ assert($result !== false);
+
+ return $result;
+ }
+
+ /**
+ * @return numeric-string
+ */
+ #[Override]
+ public function __toString() : string
+ {
+ /** @var numeric-string */
+ return $this->value;
+ }
+
+ /**
+ * This method is required for serializing the object and SHOULD NOT be accessed directly.
+ *
+ * @internal
+ *
+ * @return array{value: string}
+ */
+ public function __serialize(): array
+ {
+ return ['value' => $this->value];
+ }
+
+ /**
+ * This method is only here to allow unserializing the object and cannot be accessed directly.
+ *
+ * @internal
+ *
+ * @param array{value: string} $data
+ *
+ * @throws \LogicException
+ */
+ public function __unserialize(array $data): void
+ {
+ /** @phpstan-ignore isset.initializedProperty */
+ if (isset($this->value)) {
+ throw new \LogicException('__unserialize() is an internal function, it must not be called directly.');
+ }
+
+ /** @phpstan-ignore deadCode.unreachable */
+ $this->value = $data['value'];
+ }
+}
diff --git a/vendor/brick/math/src/BigNumber.php b/vendor/brick/math/src/BigNumber.php
new file mode 100644
index 0000000..2fbdf69
--- /dev/null
+++ b/vendor/brick/math/src/BigNumber.php
@@ -0,0 +1,556 @@
+[\-\+])?' .
+ '(?[0-9]+)?' .
+ '(?\.)?' .
+ '(?[0-9]+)?' .
+ '(?:[eE](?[\-\+]?[0-9]+))?' .
+ '$/';
+
+ /**
+ * The regular expression used to parse rational numbers.
+ */
+ private const PARSE_REGEXP_RATIONAL =
+ '/^' .
+ '(?[\-\+])?' .
+ '(?[0-9]+)' .
+ '\/?' .
+ '(?[0-9]+)' .
+ '$/';
+
+ /**
+ * Creates a BigNumber of the given value.
+ *
+ * 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
+ *
+ * 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.
+ *
+ * @pure
+ */
+ final public static function of(BigNumber|int|float|string $value) : static
+ {
+ $value = self::_of($value);
+
+ if (static::class === BigNumber::class) {
+ assert($value instanceof static);
+
+ return $value;
+ }
+
+ return static::from($value);
+ }
+
+ /**
+ * @throws NumberFormatException If the format of the number is not valid.
+ * @throws DivisionByZeroException If the value represents a rational number with a denominator of zero.
+ *
+ * @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'];
+
+ $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 ??= '';
+ $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.
+ *
+ * @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.
+ *
+ * @pure
+ * @internal
+ */
+ final protected function newBigInteger(string $value) : BigInteger
+ {
+ return new BigInteger($value);
+ }
+
+ /**
+ * Proxy method to access BigDecimal's protected constructor from sibling classes.
+ *
+ * @pure
+ * @internal
+ */
+ final protected function newBigDecimal(string $value, int $scale = 0) : BigDecimal
+ {
+ return new BigDecimal($value, $scale);
+ }
+
+ /**
+ * Proxy method to access BigRational's protected constructor from sibling classes.
+ *
+ * @pure
+ * @internal
+ */
+ final protected function newBigRational(BigInteger $numerator, BigInteger $denominator, bool $checkDenominator) : BigRational
+ {
+ return new BigRational($numerator, $denominator, $checkDenominator);
+ }
+
+ /**
+ * 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.
+ *
+ * @throws \InvalidArgumentException If no values are given.
+ * @throws MathException If an argument is not valid.
+ *
+ * @pure
+ */
+ final public static function min(BigNumber|int|float|string ...$values) : static
+ {
+ $min = null;
+
+ foreach ($values as $value) {
+ $value = static::of($value);
+
+ if ($min === null || $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.
+ *
+ * @throws \InvalidArgumentException If no values are given.
+ * @throws MathException If an argument is not valid.
+ *
+ * @pure
+ */
+ final public static function max(BigNumber|int|float|string ...$values) : static
+ {
+ $max = null;
+
+ foreach ($values as $value) {
+ $value = static::of($value);
+
+ if ($max === null || $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.
+ *
+ * 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).
+ *
+ * When called on BigInteger, BigDecimal, or BigRational, sum() requires that all values can be converted to that
+ * specific subclass, and returns a result of the same type.
+ *
+ * @param BigNumber|int|float|string ...$values The values to add. All values must be convertible to the class on
+ * which this method is called.
+ *
+ * @throws \InvalidArgumentException If no values are given.
+ * @throws MathException If an argument is not valid.
+ *
+ * @pure
+ */
+ final public static function sum(BigNumber|int|float|string ...$values) : static
+ {
+ $first = array_shift($values);
+
+ if ($first === null) {
+ throw new \InvalidArgumentException(__METHOD__ . '() expects at least one value.');
+ }
+
+ $sum = static::of($first);
+
+ foreach ($values as $value) {
+ $sum = self::add($sum, static::of($value));
+ }
+
+ assert($sum instanceof static);
+
+ return $sum;
+ }
+
+ /**
+ * Adds two BigNumber instances in the correct order to avoid a RoundingNecessaryException.
+ *
+ * @pure
+ */
+ private static function add(BigNumber $a, BigNumber $b) : BigNumber
+ {
+ 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);
+ }
+
+ /**
+ * Removes optional leading zeros and applies sign.
+ *
+ * @param string|null $sign The sign, '+' or '-', optional. Null is allowed for convenience and treated as '+'.
+ * @param string $number The number, validated as a string of digits.
+ *
+ * @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.
+ *
+ * @pure
+ */
+ final public function isEqualTo(BigNumber|int|float|string $that) : bool
+ {
+ return $this->compareTo($that) === 0;
+ }
+
+ /**
+ * Checks if this number is strictly lower than the given one.
+ *
+ * @pure
+ */
+ final public function isLessThan(BigNumber|int|float|string $that) : bool
+ {
+ return $this->compareTo($that) < 0;
+ }
+
+ /**
+ * Checks if this number is lower than or equal to the given one.
+ *
+ * @pure
+ */
+ final public function isLessThanOrEqualTo(BigNumber|int|float|string $that) : bool
+ {
+ return $this->compareTo($that) <= 0;
+ }
+
+ /**
+ * Checks if this number is strictly greater than the given one.
+ *
+ * @pure
+ */
+ final public function isGreaterThan(BigNumber|int|float|string $that) : bool
+ {
+ return $this->compareTo($that) > 0;
+ }
+
+ /**
+ * Checks if this number is greater than or equal to the given one.
+ *
+ * @pure
+ */
+ final public function isGreaterThanOrEqualTo(BigNumber|int|float|string $that) : bool
+ {
+ return $this->compareTo($that) >= 0;
+ }
+
+ /**
+ * Checks if this number equals zero.
+ *
+ * @pure
+ */
+ final public function isZero() : bool
+ {
+ return $this->getSign() === 0;
+ }
+
+ /**
+ * Checks if this number is strictly negative.
+ *
+ * @pure
+ */
+ final public function isNegative() : bool
+ {
+ return $this->getSign() < 0;
+ }
+
+ /**
+ * Checks if this number is negative or zero.
+ *
+ * @pure
+ */
+ final public function isNegativeOrZero() : bool
+ {
+ return $this->getSign() <= 0;
+ }
+
+ /**
+ * Checks if this number is strictly positive.
+ *
+ * @pure
+ */
+ final public function isPositive() : bool
+ {
+ return $this->getSign() > 0;
+ }
+
+ /**
+ * Checks if this number is positive or zero.
+ *
+ * @pure
+ */
+ final public function isPositiveOrZero() : bool
+ {
+ return $this->getSign() >= 0;
+ }
+
+ /**
+ * Returns the sign of this number.
+ *
+ * Returns -1 if the number is negative, 0 if zero, 1 if positive.
+ *
+ * @return -1|0|1
+ *
+ * @pure
+ */
+ abstract public function getSign() : int;
+
+ /**
+ * Compares this number to the given one.
+ *
+ * Returns -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;
+
+ /**
+ * 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;
+
+ /**
+ * 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;
+
+ /**
+ * Converts this number to a BigRational.
+ *
+ * @pure
+ */
+ abstract public function toBigRational() : BigRational;
+
+ /**
+ * Converts this number to a BigDecimal with the given scale, using rounding if necessary.
+ *
+ * @param int $scale The scale of the resulting `BigDecimal`.
+ * @param RoundingMode $roundingMode An optional rounding mode, defaults to UNNECESSARY.
+ *
+ * @throws RoundingNecessaryException If this number cannot be converted to the given scale without rounding.
+ * This only applies when RoundingMode::UNNECESSARY is used.
+ *
+ * @pure
+ */
+ abstract public function toScale(int $scale, RoundingMode $roundingMode = RoundingMode::UNNECESSARY) : BigDecimal;
+
+ /**
+ * Returns the exact value of this number as a native integer.
+ *
+ * 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.
+ *
+ * @pure
+ */
+ abstract public function toInt() : int;
+
+ /**
+ * Returns an approximation of this number as a floating-point value.
+ *
+ * Note that this method can discard information as the precision of a floating-point value
+ * is inherently limited.
+ *
+ * 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.
+ *
+ * @pure
+ */
+ 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.
+ *
+ * @pure
+ */
+ abstract public function __toString() : string;
+
+ #[Override]
+ final public function jsonSerialize() : string
+ {
+ return $this->__toString();
+ }
+}
diff --git a/vendor/brick/math/src/BigRational.php b/vendor/brick/math/src/BigRational.php
new file mode 100644
index 0000000..56045e5
--- /dev/null
+++ b/vendor/brick/math/src/BigRational.php
@@ -0,0 +1,441 @@
+isZero()) {
+ throw DivisionByZeroException::denominatorMustNotBeZero();
+ }
+
+ if ($denominator->isNegative()) {
+ $numerator = $numerator->negated();
+ $denominator = $denominator->negated();
+ }
+ }
+
+ $this->numerator = $numerator;
+ $this->denominator = $denominator;
+ }
+
+ #[Override]
+ protected static function from(BigNumber $number): static
+ {
+ return $number->toBigRational();
+ }
+
+ /**
+ * Creates a BigRational out of a numerator and a denominator.
+ *
+ * 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.
+ *
+ * @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.
+ *
+ * @pure
+ */
+ public static function nd(
+ BigNumber|int|float|string $numerator,
+ BigNumber|int|float|string $denominator,
+ ) : BigRational {
+ $numerator = BigInteger::of($numerator);
+ $denominator = BigInteger::of($denominator);
+
+ return new BigRational($numerator, $denominator, true);
+ }
+
+ /**
+ * Returns a BigRational representing zero.
+ *
+ * @pure
+ */
+ public static function zero() : BigRational
+ {
+ /** @var BigRational|null $zero */
+ static $zero;
+
+ if ($zero === null) {
+ $zero = new BigRational(BigInteger::zero(), BigInteger::one(), false);
+ }
+
+ return $zero;
+ }
+
+ /**
+ * Returns a BigRational representing one.
+ *
+ * @pure
+ */
+ public static function one() : BigRational
+ {
+ /** @var BigRational|null $one */
+ static $one;
+
+ if ($one === null) {
+ $one = new BigRational(BigInteger::one(), BigInteger::one(), false);
+ }
+
+ return $one;
+ }
+
+ /**
+ * Returns a BigRational representing ten.
+ *
+ * @pure
+ */
+ public static function ten() : BigRational
+ {
+ /** @var BigRational|null $ten */
+ static $ten;
+
+ if ($ten === null) {
+ $ten = new BigRational(BigInteger::ten(), BigInteger::one(), false);
+ }
+
+ return $ten;
+ }
+
+ /**
+ * @pure
+ */
+ public function getNumerator() : BigInteger
+ {
+ return $this->numerator;
+ }
+
+ /**
+ * @pure
+ */
+ public function getDenominator() : BigInteger
+ {
+ return $this->denominator;
+ }
+
+ /**
+ * Returns the quotient of the division of the numerator by the denominator.
+ *
+ * @pure
+ */
+ public function quotient() : BigInteger
+ {
+ return $this->numerator->quotient($this->denominator);
+ }
+
+ /**
+ * Returns the remainder of the division of the numerator by the denominator.
+ *
+ * @pure
+ */
+ public function remainder() : BigInteger
+ {
+ return $this->numerator->remainder($this->denominator);
+ }
+
+ /**
+ * Returns the quotient and remainder of the division of the numerator by the denominator.
+ *
+ * @return array{BigInteger, BigInteger}
+ *
+ * @pure
+ */
+ public function quotientAndRemainder() : array
+ {
+ return $this->numerator->quotientAndRemainder($this->denominator);
+ }
+
+ /**
+ * Returns the sum of this number and the given one.
+ *
+ * @param BigNumber|int|float|string $that The number to add.
+ *
+ * @throws MathException If the number is not valid.
+ *
+ * @pure
+ */
+ public function plus(BigNumber|int|float|string $that) : BigRational
+ {
+ $that = BigRational::of($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);
+ }
+
+ /**
+ * Returns the difference of this number and the given one.
+ *
+ * @param BigNumber|int|float|string $that The number to subtract.
+ *
+ * @throws MathException If the number is not valid.
+ *
+ * @pure
+ */
+ public function minus(BigNumber|int|float|string $that) : BigRational
+ {
+ $that = BigRational::of($that);
+
+ $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);
+ }
+
+ /**
+ * Returns the product of this number and the given one.
+ *
+ * @param BigNumber|int|float|string $that The multiplier.
+ *
+ * @throws MathException If the multiplier is not a valid number.
+ *
+ * @pure
+ */
+ public function multipliedBy(BigNumber|int|float|string $that) : BigRational
+ {
+ $that = BigRational::of($that);
+
+ $numerator = $this->numerator->multipliedBy($that->numerator);
+ $denominator = $this->denominator->multipliedBy($that->denominator);
+
+ return new BigRational($numerator, $denominator, false);
+ }
+
+ /**
+ * Returns the result of the division of this number by the given one.
+ *
+ * @param BigNumber|int|float|string $that The divisor.
+ *
+ * @throws MathException If the divisor is not a valid number, or is zero.
+ *
+ * @pure
+ */
+ public function dividedBy(BigNumber|int|float|string $that) : BigRational
+ {
+ $that = BigRational::of($that);
+
+ $numerator = $this->numerator->multipliedBy($that->denominator);
+ $denominator = $this->denominator->multipliedBy($that->numerator);
+
+ return new BigRational($numerator, $denominator, true);
+ }
+
+ /**
+ * Returns this number exponentiated to the given value.
+ *
+ * @throws \InvalidArgumentException If the exponent is not in the range 0 to 1,000,000.
+ *
+ * @pure
+ */
+ public function power(int $exponent) : BigRational
+ {
+ if ($exponent === 0) {
+ $one = BigInteger::one();
+
+ return new BigRational($one, $one, false);
+ }
+
+ if ($exponent === 1) {
+ return $this;
+ }
+
+ return new BigRational(
+ $this->numerator->power($exponent),
+ $this->denominator->power($exponent),
+ false
+ );
+ }
+
+ /**
+ * Returns the reciprocal of this BigRational.
+ *
+ * The reciprocal has the numerator and denominator swapped.
+ *
+ * @throws DivisionByZeroException If the numerator is zero.
+ *
+ * @pure
+ */
+ public function reciprocal() : BigRational
+ {
+ return new BigRational($this->denominator, $this->numerator, true);
+ }
+
+ /**
+ * Returns the absolute value of this BigRational.
+ *
+ * @pure
+ */
+ public function abs() : BigRational
+ {
+ return new BigRational($this->numerator->abs(), $this->denominator, false);
+ }
+
+ /**
+ * Returns the negated value of this BigRational.
+ *
+ * @pure
+ */
+ public function negated() : BigRational
+ {
+ return new BigRational($this->numerator->negated(), $this->denominator, false);
+ }
+
+ /**
+ * Returns the simplified value of this BigRational.
+ *
+ * @pure
+ */
+ public function simplified() : BigRational
+ {
+ $gcd = $this->numerator->gcd($this->denominator);
+
+ $numerator = $this->numerator->quotient($gcd);
+ $denominator = $this->denominator->quotient($gcd);
+
+ return new BigRational($numerator, $denominator, false);
+ }
+
+ #[Override]
+ public function compareTo(BigNumber|int|float|string $that) : int
+ {
+ return $this->minus($that)->getSign();
+ }
+
+ #[Override]
+ public function getSign() : int
+ {
+ return $this->numerator->getSign();
+ }
+
+ #[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.');
+ }
+
+ return $simplified->numerator;
+ }
+
+ #[Override]
+ public function toBigDecimal() : BigDecimal
+ {
+ return $this->numerator->toBigDecimal()->exactlyDividedBy($this->denominator);
+ }
+
+ #[Override]
+ public function toBigRational() : BigRational
+ {
+ return $this;
+ }
+
+ #[Override]
+ public function toScale(int $scale, RoundingMode $roundingMode = RoundingMode::UNNECESSARY) : BigDecimal
+ {
+ return $this->numerator->toBigDecimal()->dividedBy($this->denominator, $scale, $roundingMode);
+ }
+
+ #[Override]
+ public function toInt() : int
+ {
+ return $this->toBigInteger()->toInt();
+ }
+
+ #[Override]
+ public function toFloat() : float
+ {
+ $simplified = $this->simplified();
+ return $simplified->numerator->toFloat() / $simplified->denominator->toFloat();
+ }
+
+ #[Override]
+ public function __toString() : string
+ {
+ $numerator = (string) $this->numerator;
+ $denominator = (string) $this->denominator;
+
+ if ($denominator === '1') {
+ return $numerator;
+ }
+
+ return $numerator . '/' . $denominator;
+ }
+
+ /**
+ * This method is required for serializing the object and SHOULD NOT be accessed directly.
+ *
+ * @internal
+ *
+ * @return array{numerator: BigInteger, denominator: BigInteger}
+ */
+ public function __serialize(): array
+ {
+ return ['numerator' => $this->numerator, 'denominator' => $this->denominator];
+ }
+
+ /**
+ * This method is only here to allow unserializing the object and cannot be accessed directly.
+ *
+ * @internal
+ *
+ * @param array{numerator: BigInteger, denominator: BigInteger} $data
+ *
+ * @throws \LogicException
+ */
+ public function __unserialize(array $data): void
+ {
+ /** @phpstan-ignore isset.initializedProperty */
+ if (isset($this->numerator)) {
+ throw new \LogicException('__unserialize() is an internal function, it must not be called directly.');
+ }
+
+ /** @phpstan-ignore deadCode.unreachable */
+ $this->numerator = $data['numerator'];
+ $this->denominator = $data['denominator'];
+ }
+}
diff --git a/vendor/brick/math/src/Exception/DivisionByZeroException.php b/vendor/brick/math/src/Exception/DivisionByZeroException.php
new file mode 100644
index 0000000..2daaf5e
--- /dev/null
+++ b/vendor/brick/math/src/Exception/DivisionByZeroException.php
@@ -0,0 +1,35 @@
+ 126) {
+ $char = \strtoupper(\dechex($ord));
+
+ if ($ord < 10) {
+ $char = '0' . $char;
+ }
+ } else {
+ $char = '"' . $char . '"';
+ }
+
+ return new self(\sprintf('Char %s is not a valid character in the given alphabet.', $char));
+ }
+}
diff --git a/vendor/brick/math/src/Exception/RoundingNecessaryException.php b/vendor/brick/math/src/Exception/RoundingNecessaryException.php
new file mode 100644
index 0000000..034a040
--- /dev/null
+++ b/vendor/brick/math/src/Exception/RoundingNecessaryException.php
@@ -0,0 +1,19 @@
+init($a, $b);
+
+ if ($aNeg && ! $bNeg) {
+ return -1;
+ }
+
+ if ($bNeg && ! $aNeg) {
+ return 1;
+ }
+
+ $aLen = \strlen($aDig);
+ $bLen = \strlen($bDig);
+
+ if ($aLen < $bLen) {
+ $result = -1;
+ } elseif ($aLen > $bLen) {
+ $result = 1;
+ } else {
+ $result = $aDig <=> $bDig;
+ }
+
+ return $aNeg ? -$result : $result;
+ }
+
+ /**
+ * Adds two numbers.
+ *
+ * @pure
+ */
+ abstract public function add(string $a, string $b) : string;
+
+ /**
+ * Subtracts two numbers.
+ *
+ * @pure
+ */
+ abstract public function sub(string $a, string $b) : string;
+
+ /**
+ * Multiplies two numbers.
+ *
+ * @pure
+ */
+ abstract public function mul(string $a, string $b) : string;
+
+ /**
+ * Returns the quotient of the division of two numbers.
+ *
+ * @param string $a The dividend.
+ * @param string $b The divisor, must not be zero.
+ *
+ * @return string The quotient.
+ *
+ * @pure
+ */
+ abstract public function divQ(string $a, string $b) : string;
+
+ /**
+ * Returns the remainder of the division of two numbers.
+ *
+ * @param string $a The dividend.
+ * @param string $b The divisor, must not be zero.
+ *
+ * @return string The remainder.
+ *
+ * @pure
+ */
+ abstract public function divR(string $a, string $b) : string;
+
+ /**
+ * Returns the quotient and remainder of the division of two numbers.
+ *
+ * @param string $a The dividend.
+ * @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;
+
+ /**
+ * Exponentiates a number.
+ *
+ * @param string $a The base number.
+ * @param int $e The exponent, validated as an integer between 0 and MAX_POWER.
+ *
+ * @return string The power.
+ *
+ * @pure
+ */
+ abstract public function pow(string $a, int $e) : string;
+
+ /**
+ * @param string $b The modulus; must not be zero.
+ *
+ * @pure
+ */
+ public function mod(string $a, string $b) : string
+ {
+ return $this->divR($this->add($this->divR($a, $b), $b), $b);
+ }
+
+ /**
+ * Returns the modular multiplicative inverse of $x modulo $m.
+ *
+ * If $x has no multiplicative inverse mod m, this method must return null.
+ *
+ * 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
+ {
+ if ($m === '1') {
+ return '0';
+ }
+
+ $modVal = $x;
+
+ if ($x[0] === '-' || ($this->cmp($this->abs($x), $m) >= 0)) {
+ $modVal = $this->mod($x, $m);
+ }
+
+ [$g, $x] = $this->gcdExtended($modVal, $m);
+
+ if ($g !== '1') {
+ return null;
+ }
+
+ return $this->mod($this->add($this->mod($x, $m), $m), $m);
+ }
+
+ /**
+ * Raises a number into power with modulo.
+ *
+ * @param string $base The base number; must be positive or zero.
+ * @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;
+
+ /**
+ * Returns the greatest common divisor of the two numbers.
+ *
+ * This method can be overridden by the concrete implementation if the underlying library
+ * 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
+ {
+ if ($a === '0') {
+ return $this->abs($b);
+ }
+
+ if ($b === '0') {
+ return $this->abs($a);
+ }
+
+ return $this->gcd($b, $this->divR($a, $b));
+ }
+
+ /**
+ * @return array{string, string, string} GCD, X, Y
+ *
+ * @pure
+ */
+ private function gcdExtended(string $a, string $b) : array
+ {
+ if ($a === '0') {
+ return [$b, '0', '1'];
+ }
+
+ [$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];
+ }
+
+ /**
+ * Returns the square root of the given number, rounded down.
+ *
+ * The result is the largest x such that x² ≤ n.
+ * The input MUST NOT be negative.
+ *
+ * @pure
+ */
+ abstract public function sqrt(string $n) : string;
+
+ /**
+ * Converts a number from an arbitrary base.
+ *
+ * This method can be overridden by the concrete implementation if the underlying library
+ * has built-in support for base conversion.
+ *
+ * @param string $number The number, positive or zero, non-empty, case-insensitively validated for the given base.
+ * @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
+ {
+ return $this->fromArbitraryBase(\strtolower($number), self::ALPHABET, $base);
+ }
+
+ /**
+ * Converts a number to an arbitrary base.
+ *
+ * This method can be overridden by the concrete implementation if the underlying library
+ * has built-in support for base conversion.
+ *
+ * @param string $number The number to convert, following the Calculator conventions.
+ * @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
+ {
+ $negative = ($number[0] === '-');
+
+ if ($negative) {
+ $number = \substr($number, 1);
+ }
+
+ $number = $this->toArbitraryBase($number, self::ALPHABET, $base);
+
+ if ($negative) {
+ return '-' . $number;
+ }
+
+ return $number;
+ }
+
+ /**
+ * Converts a non-negative number in an arbitrary base using a custom alphabet, to base 10.
+ *
+ * @param string $number The number to convert, validated as a non-empty string,
+ * containing only chars in the given alphabet/base.
+ * @param string $alphabet The alphabet that contains every digit, validated as 2 chars minimum.
+ * @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
+ {
+ // remove leading "zeros"
+ $number = \ltrim($number, $alphabet[0]);
+
+ if ($number === '') {
+ return '0';
+ }
+
+ // optimize for "one"
+ if ($number === $alphabet[1]) {
+ return '1';
+ }
+
+ $result = '0';
+ $power = '1';
+
+ $base = (string) $base;
+
+ 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)
+ );
+ }
+
+ if ($i !== 0) {
+ $power = $this->mul($power, $base);
+ }
+ }
+
+ return $result;
+ }
+
+ /**
+ * Converts a non-negative number to an arbitrary base using a custom alphabet.
+ *
+ * @param string $number The number to convert, positive or zero, following the Calculator conventions.
+ * @param string $alphabet The alphabet that contains every digit, validated as 2 chars minimum.
+ * @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
+ {
+ if ($number === '0') {
+ return $alphabet[0];
+ }
+
+ $base = (string) $base;
+ $result = '';
+
+ while ($number !== '0') {
+ [$number, $remainder] = $this->divQR($number, $base);
+ $remainder = (int) $remainder;
+
+ $result .= $alphabet[$remainder];
+ }
+
+ return \strrev($result);
+ }
+
+ /**
+ * Performs a rounded division.
+ *
+ * Rounding is performed when the remainder of the division is not zero.
+ *
+ * @param string $a The dividend.
+ * @param string $b The divisor, must not be zero.
+ * @param RoundingMode $roundingMode The rounding mode.
+ *
+ * @throws RoundingNecessaryException If RoundingMode::UNNECESSARY is provided but rounding is necessary.
+ *
+ * @pure
+ */
+ 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 {
+ $r = $this->abs($this->mul($remainder, '2'));
+ $b = $this->abs($b);
+
+ return $this->cmp($r, $b);
+ };
+
+ $increment = false;
+
+ switch ($roundingMode) {
+ case RoundingMode::UNNECESSARY:
+ if ($hasDiscardedFraction) {
+ throw RoundingNecessaryException::roundingNecessary();
+ }
+ break;
+
+ case RoundingMode::UP:
+ $increment = $hasDiscardedFraction;
+ break;
+
+ case RoundingMode::DOWN:
+ break;
+
+ case RoundingMode::CEILING:
+ $increment = $hasDiscardedFraction && $isPositiveOrZero;
+ break;
+
+ case RoundingMode::FLOOR:
+ $increment = $hasDiscardedFraction && ! $isPositiveOrZero;
+ break;
+
+ case RoundingMode::HALF_UP:
+ $increment = $discardedFractionSign() >= 0;
+ break;
+
+ case RoundingMode::HALF_DOWN:
+ $increment = $discardedFractionSign() > 0;
+ break;
+
+ case RoundingMode::HALF_CEILING:
+ $increment = $isPositiveOrZero ? $discardedFractionSign() >= 0 : $discardedFractionSign() > 0;
+ break;
+
+ case RoundingMode::HALF_FLOOR:
+ $increment = $isPositiveOrZero ? $discardedFractionSign() > 0 : $discardedFractionSign() >= 0;
+ break;
+
+ case RoundingMode::HALF_EVEN:
+ $lastDigit = (int) $quotient[-1];
+ $lastDigitIsEven = ($lastDigit % 2 === 0);
+ $increment = $lastDigitIsEven ? $discardedFractionSign() > 0 : $discardedFractionSign() >= 0;
+ break;
+ }
+
+ if ($increment) {
+ return $this->add($quotient, $isPositiveOrZero ? '1' : '-1');
+ }
+
+ return $quotient;
+ }
+
+ /**
+ * Calculates bitwise AND of two numbers.
+ *
+ * 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
+ {
+ return $this->bitwise('and', $a, $b);
+ }
+
+ /**
+ * Calculates bitwise OR of two numbers.
+ *
+ * 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
+ {
+ return $this->bitwise('or', $a, $b);
+ }
+
+ /**
+ * Calculates bitwise XOR of two numbers.
+ *
+ * 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
+ {
+ return $this->bitwise('xor', $a, $b);
+ }
+
+ /**
+ * 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
+ {
+ [$aNeg, $bNeg, $aDig, $bDig] = $this->init($a, $b);
+
+ $aBin = $this->toBinary($aDig);
+ $bBin = $this->toBinary($bDig);
+
+ $aLen = \strlen($aBin);
+ $bLen = \strlen($bBin);
+
+ if ($aLen > $bLen) {
+ $bBin = \str_repeat("\x00", $aLen - $bLen) . $bBin;
+ } elseif ($bLen > $aLen) {
+ $aBin = \str_repeat("\x00", $bLen - $aLen) . $aBin;
+ }
+
+ if ($aNeg) {
+ $aBin = $this->twosComplement($aBin);
+ }
+ if ($bNeg) {
+ $bBin = $this->twosComplement($bBin);
+ }
+
+ $value = match ($operator) {
+ 'and' => $aBin & $bBin,
+ 'or' => $aBin | $bBin,
+ 'xor' => $aBin ^ $bBin,
+ };
+
+ $negative = match ($operator) {
+ 'and' => $aNeg and $bNeg,
+ 'or' => $aNeg or $bNeg,
+ 'xor' => $aNeg xor $bNeg,
+ };
+
+ if ($negative) {
+ $value = $this->twosComplement($value);
+ }
+
+ $result = $this->toDecimal($value);
+
+ return $negative ? $this->neg($result) : $result;
+ }
+
+ /**
+ * @param string $number A positive, binary number.
+ *
+ * @pure
+ */
+ private function twosComplement(string $number) : string
+ {
+ $xor = \str_repeat("\xff", \strlen($number));
+
+ $number ^= $xor;
+
+ for ($i = \strlen($number) - 1; $i >= 0; $i--) {
+ $byte = \ord($number[$i]);
+
+ if (++$byte !== 256) {
+ $number[$i] = \chr($byte);
+ break;
+ }
+
+ $number[$i] = "\x00";
+
+ if ($i === 0) {
+ $number = "\x01" . $number;
+ }
+ }
+
+ return $number;
+ }
+
+ /**
+ * 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
+ {
+ $result = '';
+
+ while ($number !== '0') {
+ [$number, $remainder] = $this->divQR($number, '256');
+ $result .= \chr((int) $remainder);
+ }
+
+ 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
+ {
+ $result = '0';
+ $power = '1';
+
+ 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)
+ );
+ }
+
+ if ($i !== 0) {
+ $power = $this->mul($power, '256');
+ }
+ }
+
+ return $result;
+ }
+}
diff --git a/vendor/brick/math/src/Internal/Calculator/BcMathCalculator.php b/vendor/brick/math/src/Internal/Calculator/BcMathCalculator.php
new file mode 100644
index 0000000..5ba961e
--- /dev/null
+++ b/vendor/brick/math/src/Internal/Calculator/BcMathCalculator.php
@@ -0,0 +1,73 @@
+maxDigits = match (PHP_INT_SIZE) {
+ 4 => 9,
+ 8 => 18,
+ };
+ }
+
+ #[Override]
+ public function add(string $a, string $b) : string
+ {
+ /**
+ * @var numeric-string $a
+ * @var numeric-string $b
+ */
+ $result = $a + $b;
+
+ if (is_int($result)) {
+ return (string) $result;
+ }
+
+ if ($a === '0') {
+ return $b;
+ }
+
+ if ($b === '0') {
+ return $a;
+ }
+
+ [$aNeg, $bNeg, $aDig, $bDig] = $this->init($a, $b);
+
+ $result = $aNeg === $bNeg ? $this->doAdd($aDig, $bDig) : $this->doSub($aDig, $bDig);
+
+ if ($aNeg) {
+ $result = $this->neg($result);
+ }
+
+ return $result;
+ }
+
+ #[Override]
+ public function sub(string $a, string $b) : string
+ {
+ return $this->add($a, $this->neg($b));
+ }
+
+ #[Override]
+ public function mul(string $a, string $b) : string
+ {
+ /**
+ * @var numeric-string $a
+ * @var numeric-string $b
+ */
+ $result = $a * $b;
+
+ if (is_int($result)) {
+ return (string) $result;
+ }
+
+ if ($a === '0' || $b === '0') {
+ return '0';
+ }
+
+ if ($a === '1') {
+ return $b;
+ }
+
+ if ($b === '1') {
+ return $a;
+ }
+
+ if ($a === '-1') {
+ return $this->neg($b);
+ }
+
+ if ($b === '-1') {
+ return $this->neg($a);
+ }
+
+ [$aNeg, $bNeg, $aDig, $bDig] = $this->init($a, $b);
+
+ $result = $this->doMul($aDig, $bDig);
+
+ if ($aNeg !== $bNeg) {
+ $result = $this->neg($result);
+ }
+
+ return $result;
+ }
+
+ #[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];
+ }
+
+ #[Override]
+ public function divQR(string $a, string $b) : array
+ {
+ if ($a === '0') {
+ return ['0', '0'];
+ }
+
+ if ($a === $b) {
+ return ['1', '0'];
+ }
+
+ if ($b === '1') {
+ return [$a, '0'];
+ }
+
+ if ($b === '-1') {
+ return [$this->neg($a), '0'];
+ }
+
+ /** @var numeric-string $a */
+ $na = $a * 1; // cast to number
+
+ if (is_int($na)) {
+ /** @var numeric-string $b */
+ $nb = $b * 1;
+
+ if (is_int($nb)) {
+ // the only division that may overflow is PHP_INT_MIN / -1,
+ // which cannot happen here as we've already handled a divisor of -1 above.
+ $q = intdiv($na, $nb);
+ $r = $na % $nb;
+
+ return [
+ (string) $q,
+ (string) $r
+ ];
+ }
+ }
+
+ [$aNeg, $bNeg, $aDig, $bDig] = $this->init($a, $b);
+
+ [$q, $r] = $this->doDiv($aDig, $bDig);
+
+ if ($aNeg !== $bNeg) {
+ $q = $this->neg($q);
+ }
+
+ if ($aNeg) {
+ $r = $this->neg($r);
+ }
+
+ return [$q, $r];
+ }
+
+ #[Override]
+ public function pow(string $a, int $e) : string
+ {
+ if ($e === 0) {
+ return '1';
+ }
+
+ if ($e === 1) {
+ return $a;
+ }
+
+ $odd = $e % 2;
+ $e -= $odd;
+
+ $aa = $this->mul($a, $a);
+
+ $result = $this->pow($aa, $e / 2);
+
+ if ($odd === 1) {
+ $result = $this->mul($result, $a);
+ }
+
+ return $result;
+ }
+
+ /**
+ * Algorithm from: https://www.geeksforgeeks.org/modular-exponentiation-power-in-modular-arithmetic/
+ */
+ #[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';
+ }
+
+ // special case: the algorithm below fails with power 0 mod 1 (returns 1 instead of 0)
+ if ($exp === '0' && $mod === '1') {
+ return '0';
+ }
+
+ $x = $base;
+
+ $res = '1';
+
+ // numbers are positive, so we can use remainder instead of modulo
+ $x = $this->divR($x, $mod);
+
+ while ($exp !== '0') {
+ if (in_array($exp[-1], ['1', '3', '5', '7', '9'])) { // odd
+ $res = $this->divR($this->mul($res, $x), $mod);
+ }
+
+ $exp = $this->divQ($exp, '2');
+ $x = $this->divR($this->mul($x, $x), $mod);
+ }
+
+ return $res;
+ }
+
+ /**
+ * Adapted from https://cp-algorithms.com/num_methods/roots_newton.html
+ */
+ #[Override]
+ public function sqrt(string $n) : string
+ {
+ if ($n === '0') {
+ return '0';
+ }
+
+ // initial approximation
+ $x = \str_repeat('9', \intdiv(\strlen($n), 2) ?: 1);
+
+ $decreased = false;
+
+ for (;;) {
+ $nx = $this->divQ($this->add($x, $this->divQ($n, $x)), '2');
+
+ if ($x === $nx || $this->cmp($nx, $x) > 0 && $decreased) {
+ break;
+ }
+
+ $decreased = $this->cmp($nx, $x) < 0;
+ $x = $nx;
+ }
+
+ return $x;
+ }
+
+ /**
+ * Performs the addition of two non-signed large integers.
+ *
+ * @pure
+ */
+ 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) {
+ $blockLength = $this->maxDigits;
+
+ if ($i < 0) {
+ $blockLength += $i;
+ $i = 0;
+ }
+
+ /** @var numeric-string $blockA */
+ $blockA = \substr($a, $i, $blockLength);
+
+ /** @var numeric-string $blockB */
+ $blockB = \substr($b, $i, $blockLength);
+
+ $sum = (string) ($blockA + $blockB + $carry);
+ $sumLength = \strlen($sum);
+
+ if ($sumLength > $blockLength) {
+ $sum = \substr($sum, 1);
+ $carry = 1;
+ } else {
+ if ($sumLength < $blockLength) {
+ $sum = \str_repeat('0', $blockLength - $sumLength) . $sum;
+ }
+ $carry = 0;
+ }
+
+ $result = $sum . $result;
+
+ if ($i === 0) {
+ break;
+ }
+ }
+
+ if ($carry === 1) {
+ $result = '1' . $result;
+ }
+
+ return $result;
+ }
+
+ /**
+ * Performs the subtraction of two non-signed large integers.
+ *
+ * @pure
+ */
+ private function doSub(string $a, string $b) : string
+ {
+ if ($a === $b) {
+ return '0';
+ }
+
+ // Ensure that we always subtract to a positive result: biggest minus smallest.
+ $cmp = $this->doCmp($a, $b);
+
+ $invert = ($cmp === -1);
+
+ if ($invert) {
+ $c = $a;
+ $a = $b;
+ $b = $c;
+ }
+
+ [$a, $b, $length] = $this->pad($a, $b);
+
+ $carry = 0;
+ $result = '';
+
+ $complement = 10 ** $this->maxDigits;
+
+ for ($i = $length - $this->maxDigits;; $i -= $this->maxDigits) {
+ $blockLength = $this->maxDigits;
+
+ if ($i < 0) {
+ $blockLength += $i;
+ $i = 0;
+ }
+
+ /** @var numeric-string $blockA */
+ $blockA = \substr($a, $i, $blockLength);
+
+ /** @var numeric-string $blockB */
+ $blockB = \substr($b, $i, $blockLength);
+
+ $sum = $blockA - $blockB - $carry;
+
+ if ($sum < 0) {
+ $sum += $complement;
+ $carry = 1;
+ } else {
+ $carry = 0;
+ }
+
+ $sum = (string) $sum;
+ $sumLength = \strlen($sum);
+
+ if ($sumLength < $blockLength) {
+ $sum = \str_repeat('0', $blockLength - $sumLength) . $sum;
+ }
+
+ $result = $sum . $result;
+
+ if ($i === 0) {
+ break;
+ }
+ }
+
+ // Carry cannot be 1 when the loop ends, as a > b
+ assert($carry === 0);
+
+ $result = \ltrim($result, '0');
+
+ if ($invert) {
+ $result = $this->neg($result);
+ }
+
+ return $result;
+ }
+
+ /**
+ * Performs the multiplication of two non-signed large integers.
+ *
+ * @pure
+ */
+ private function doMul(string $a, string $b) : string
+ {
+ $x = \strlen($a);
+ $y = \strlen($b);
+
+ $maxDigits = \intdiv($this->maxDigits, 2);
+ $complement = 10 ** $maxDigits;
+
+ $result = '0';
+
+ for ($i = $x - $maxDigits;; $i -= $maxDigits) {
+ $blockALength = $maxDigits;
+
+ if ($i < 0) {
+ $blockALength += $i;
+ $i = 0;
+ }
+
+ $blockA = (int) \substr($a, $i, $blockALength);
+
+ $line = '';
+ $carry = 0;
+
+ for ($j = $y - $maxDigits;; $j -= $maxDigits) {
+ $blockBLength = $maxDigits;
+
+ if ($j < 0) {
+ $blockBLength += $j;
+ $j = 0;
+ }
+
+ $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);
+
+ $line = $value . $line;
+
+ if ($j === 0) {
+ break;
+ }
+ }
+
+ if ($carry !== 0) {
+ $line = $carry . $line;
+ }
+
+ $line = \ltrim($line, '0');
+
+ if ($line !== '') {
+ $line .= \str_repeat('0', $x - $blockALength - $i);
+ $result = $this->add($result, $line);
+ }
+
+ if ($i === 0) {
+ break;
+ }
+ }
+
+ return $result;
+ }
+
+ /**
+ * Performs the division of two non-signed large integers.
+ *
+ * @return string[] The quotient and remainder.
+ *
+ * @pure
+ */
+ private function doDiv(string $a, string $b) : array
+ {
+ $cmp = $this->doCmp($a, $b);
+
+ if ($cmp === -1) {
+ return ['0', $a];
+ }
+
+ $x = \strlen($a);
+ $y = \strlen($b);
+
+ // we now know that a >= b && x >= y
+
+ $q = '0'; // quotient
+ $r = $a; // remainder
+ $z = $y; // focus length, always $y or $y+1
+
+ /** @var numeric-string $b */
+ $nb = $b * 1; // cast to number
+ // performance optimization in cases where the remainder will never cause int overflow
+ if (is_int(($nb - 1) * 10 + 9)) {
+ $r = (int) \substr($a, 0, $z - 1);
+
+ for ($i = $z - 1; $i < $x; $i++) {
+ $n = $r * 10 + (int) $a[$i];
+ /** @var int $nb */
+ $q .= \intdiv($n, $nb);
+ $r = $n % $nb;
+ }
+
+ return [\ltrim($q, '0') ?: '0', (string) $r];
+ }
+
+ for (;;) {
+ $focus = \substr($a, 0, $z);
+
+ $cmp = $this->doCmp($focus, $b);
+
+ if ($cmp === -1) {
+ if ($z === $x) { // remainder < dividend
+ break;
+ }
+
+ $z++;
+ }
+
+ $zeros = \str_repeat('0', $x - $z);
+
+ $q = $this->add($q, '1' . $zeros);
+ $a = $this->sub($a, $b . $zeros);
+
+ $r = $a;
+
+ if ($r === '0') { // remainder == 0
+ break;
+ }
+
+ $x = \strlen($a);
+
+ if ($x < $y) { // remainder < dividend
+ break;
+ }
+
+ $z = $y;
+ }
+
+ return [$q, $r];
+ }
+
+ /**
+ * Compares two non-signed large numbers.
+ *
+ * @return -1|0|1
+ *
+ * @pure
+ */
+ private function doCmp(string $a, string $b) : int
+ {
+ $x = \strlen($a);
+ $y = \strlen($b);
+
+ $cmp = $x <=> $y;
+
+ if ($cmp !== 0) {
+ return $cmp;
+ }
+
+ return \strcmp($a, $b) <=> 0; // enforce -1|0|1
+ }
+
+ /**
+ * Pads the left of one of the given numbers with zeros if necessary to make both numbers the same length.
+ *
+ * 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
+ {
+ $x = \strlen($a);
+ $y = \strlen($b);
+
+ if ($x > $y) {
+ $b = \str_repeat('0', $x - $y) . $b;
+
+ return [$a, $b, $x];
+ }
+
+ if ($x < $y) {
+ $a = \str_repeat('0', $y - $x) . $a;
+
+ return [$a, $b, $y];
+ }
+
+ return [$a, $b, $x];
+ }
+}
diff --git a/vendor/brick/math/src/Internal/CalculatorRegistry.php b/vendor/brick/math/src/Internal/CalculatorRegistry.php
new file mode 100644
index 0000000..394fae6
--- /dev/null
+++ b/vendor/brick/math/src/Internal/CalculatorRegistry.php
@@ -0,0 +1,73 @@
+= 0.5; otherwise, behaves as for DOWN.
+ * Note that this is the rounding mode commonly taught at school.
+ */
+ case HALF_UP;
+
+ /**
+ * Rounds towards "nearest neighbor" unless both neighbors are equidistant, in which case round down.
+ *
+ * Behaves as for UP if the discarded fraction is > 0.5; otherwise, behaves as for DOWN.
+ */
+ case HALF_DOWN;
+
+ /**
+ * Rounds towards "nearest neighbor" unless both neighbors are equidistant, in which case round towards positive infinity.
+ *
+ * If the result is positive, behaves as for HALF_UP; if negative, behaves as for HALF_DOWN.
+ */
+ case HALF_CEILING;
+
+ /**
+ * Rounds towards "nearest neighbor" unless both neighbors are equidistant, in which case round towards negative infinity.
+ *
+ * If the result is positive, behaves as for HALF_DOWN; if negative, behaves as for HALF_UP.
+ */
+ case HALF_FLOOR;
+
+ /**
+ * Rounds towards the "nearest neighbor" unless both neighbors are equidistant, in which case rounds towards the even neighbor.
+ *
+ * Behaves as for HALF_UP if the digit to the left of the discarded fraction is odd;
+ * behaves as for HALF_DOWN if it's even.
+ *
+ * Note that this is the rounding mode that statistically minimizes
+ * cumulative error when applied repeatedly over a sequence of calculations.
+ * It is sometimes known as "Banker's rounding", and is chiefly used in the USA.
+ */
+ case HALF_EVEN;
+}
diff --git a/vendor/composer/ClassLoader.php b/vendor/composer/ClassLoader.php
new file mode 100644
index 0000000..7824d8f
--- /dev/null
+++ b/vendor/composer/ClassLoader.php
@@ -0,0 +1,579 @@
+
+ * Jordi Boggiano
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Composer\Autoload;
+
+/**
+ * ClassLoader implements a PSR-0, PSR-4 and classmap class loader.
+ *
+ * $loader = new \Composer\Autoload\ClassLoader();
+ *
+ * // register classes with namespaces
+ * $loader->add('Symfony\Component', __DIR__.'/component');
+ * $loader->add('Symfony', __DIR__.'/framework');
+ *
+ * // activate the autoloader
+ * $loader->register();
+ *
+ * // to enable searching the include path (eg. for PEAR packages)
+ * $loader->setUseIncludePath(true);
+ *
+ * In this example, if you try to use a class in the Symfony\Component
+ * namespace or one of its children (Symfony\Component\Console for instance),
+ * the autoloader will first look for the class under the component/
+ * directory, and it will then fallback to the framework/ directory if not
+ * found before giving up.
+ *
+ * This class is loosely based on the Symfony UniversalClassLoader.
+ *
+ * @author Fabien Potencier
+ * @author Jordi Boggiano
+ * @see https://www.php-fig.org/psr/psr-0/
+ * @see https://www.php-fig.org/psr/psr-4/
+ */
+class ClassLoader
+{
+ /** @var \Closure(string):void */
+ private static $includeFile;
+
+ /** @var string|null */
+ private $vendorDir;
+
+ // PSR-4
+ /**
+ * @var array>
+ */
+ private $prefixLengthsPsr4 = array();
+ /**
+ * @var array>
+ */
+ private $prefixDirsPsr4 = array();
+ /**
+ * @var list
+ */
+ private $fallbackDirsPsr4 = array();
+
+ // PSR-0
+ /**
+ * List of PSR-0 prefixes
+ *
+ * Structured as array('F (first letter)' => array('Foo\Bar (full prefix)' => array('path', 'path2')))
+ *
+ * @var array>>
+ */
+ private $prefixesPsr0 = array();
+ /**
+ * @var list
+ */
+ private $fallbackDirsPsr0 = array();
+
+ /** @var bool */
+ private $useIncludePath = false;
+
+ /**
+ * @var array
+ */
+ private $classMap = array();
+
+ /** @var bool */
+ private $classMapAuthoritative = false;
+
+ /**
+ * @var array
+ */
+ private $missingClasses = array();
+
+ /** @var string|null */
+ private $apcuPrefix;
+
+ /**
+ * @var array
+ */
+ private static $registeredLoaders = array();
+
+ /**
+ * @param string|null $vendorDir
+ */
+ public function __construct($vendorDir = null)
+ {
+ $this->vendorDir = $vendorDir;
+ self::initializeIncludeClosure();
+ }
+
+ /**
+ * @return array>
+ */
+ public function getPrefixes()
+ {
+ if (!empty($this->prefixesPsr0)) {
+ return call_user_func_array('array_merge', array_values($this->prefixesPsr0));
+ }
+
+ return array();
+ }
+
+ /**
+ * @return array>
+ */
+ public function getPrefixesPsr4()
+ {
+ return $this->prefixDirsPsr4;
+ }
+
+ /**
+ * @return list
+ */
+ public function getFallbackDirs()
+ {
+ return $this->fallbackDirsPsr0;
+ }
+
+ /**
+ * @return list
+ */
+ public function getFallbackDirsPsr4()
+ {
+ return $this->fallbackDirsPsr4;
+ }
+
+ /**
+ * @return array Array of classname => path
+ */
+ public function getClassMap()
+ {
+ return $this->classMap;
+ }
+
+ /**
+ * @param array $classMap Class to filename map
+ *
+ * @return void
+ */
+ public function addClassMap(array $classMap)
+ {
+ if ($this->classMap) {
+ $this->classMap = array_merge($this->classMap, $classMap);
+ } else {
+ $this->classMap = $classMap;
+ }
+ }
+
+ /**
+ * Registers a set of PSR-0 directories for a given prefix, either
+ * appending or prepending to the ones previously set for this prefix.
+ *
+ * @param string $prefix The prefix
+ * @param list|string $paths The PSR-0 root directories
+ * @param bool $prepend Whether to prepend the directories
+ *
+ * @return void
+ */
+ public function add($prefix, $paths, $prepend = false)
+ {
+ $paths = (array) $paths;
+ if (!$prefix) {
+ if ($prepend) {
+ $this->fallbackDirsPsr0 = array_merge(
+ $paths,
+ $this->fallbackDirsPsr0
+ );
+ } else {
+ $this->fallbackDirsPsr0 = array_merge(
+ $this->fallbackDirsPsr0,
+ $paths
+ );
+ }
+
+ return;
+ }
+
+ $first = $prefix[0];
+ if (!isset($this->prefixesPsr0[$first][$prefix])) {
+ $this->prefixesPsr0[$first][$prefix] = $paths;
+
+ return;
+ }
+ if ($prepend) {
+ $this->prefixesPsr0[$first][$prefix] = array_merge(
+ $paths,
+ $this->prefixesPsr0[$first][$prefix]
+ );
+ } else {
+ $this->prefixesPsr0[$first][$prefix] = array_merge(
+ $this->prefixesPsr0[$first][$prefix],
+ $paths
+ );
+ }
+ }
+
+ /**
+ * Registers a set of PSR-4 directories for a given namespace, either
+ * appending or prepending to the ones previously set for this namespace.
+ *
+ * @param string $prefix The prefix/namespace, with trailing '\\'
+ * @param list|string $paths The PSR-4 base directories
+ * @param bool $prepend Whether to prepend the directories
+ *
+ * @throws \InvalidArgumentException
+ *
+ * @return void
+ */
+ public function addPsr4($prefix, $paths, $prepend = false)
+ {
+ $paths = (array) $paths;
+ if (!$prefix) {
+ // Register directories for the root namespace.
+ if ($prepend) {
+ $this->fallbackDirsPsr4 = array_merge(
+ $paths,
+ $this->fallbackDirsPsr4
+ );
+ } else {
+ $this->fallbackDirsPsr4 = array_merge(
+ $this->fallbackDirsPsr4,
+ $paths
+ );
+ }
+ } elseif (!isset($this->prefixDirsPsr4[$prefix])) {
+ // Register directories for a new namespace.
+ $length = strlen($prefix);
+ if ('\\' !== $prefix[$length - 1]) {
+ throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
+ }
+ $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
+ $this->prefixDirsPsr4[$prefix] = $paths;
+ } elseif ($prepend) {
+ // Prepend directories for an already registered namespace.
+ $this->prefixDirsPsr4[$prefix] = array_merge(
+ $paths,
+ $this->prefixDirsPsr4[$prefix]
+ );
+ } else {
+ // Append directories for an already registered namespace.
+ $this->prefixDirsPsr4[$prefix] = array_merge(
+ $this->prefixDirsPsr4[$prefix],
+ $paths
+ );
+ }
+ }
+
+ /**
+ * Registers a set of PSR-0 directories for a given prefix,
+ * replacing any others previously set for this prefix.
+ *
+ * @param string $prefix The prefix
+ * @param list|string $paths The PSR-0 base directories
+ *
+ * @return void
+ */
+ public function set($prefix, $paths)
+ {
+ if (!$prefix) {
+ $this->fallbackDirsPsr0 = (array) $paths;
+ } else {
+ $this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths;
+ }
+ }
+
+ /**
+ * Registers a set of PSR-4 directories for a given namespace,
+ * replacing any others previously set for this namespace.
+ *
+ * @param string $prefix The prefix/namespace, with trailing '\\'
+ * @param list|string $paths The PSR-4 base directories
+ *
+ * @throws \InvalidArgumentException
+ *
+ * @return void
+ */
+ public function setPsr4($prefix, $paths)
+ {
+ if (!$prefix) {
+ $this->fallbackDirsPsr4 = (array) $paths;
+ } else {
+ $length = strlen($prefix);
+ if ('\\' !== $prefix[$length - 1]) {
+ throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
+ }
+ $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
+ $this->prefixDirsPsr4[$prefix] = (array) $paths;
+ }
+ }
+
+ /**
+ * Turns on searching the include path for class files.
+ *
+ * @param bool $useIncludePath
+ *
+ * @return void
+ */
+ public function setUseIncludePath($useIncludePath)
+ {
+ $this->useIncludePath = $useIncludePath;
+ }
+
+ /**
+ * Can be used to check if the autoloader uses the include path to check
+ * for classes.
+ *
+ * @return bool
+ */
+ public function getUseIncludePath()
+ {
+ return $this->useIncludePath;
+ }
+
+ /**
+ * Turns off searching the prefix and fallback directories for classes
+ * that have not been registered with the class map.
+ *
+ * @param bool $classMapAuthoritative
+ *
+ * @return void
+ */
+ public function setClassMapAuthoritative($classMapAuthoritative)
+ {
+ $this->classMapAuthoritative = $classMapAuthoritative;
+ }
+
+ /**
+ * Should class lookup fail if not found in the current class map?
+ *
+ * @return bool
+ */
+ public function isClassMapAuthoritative()
+ {
+ return $this->classMapAuthoritative;
+ }
+
+ /**
+ * APCu prefix to use to cache found/not-found classes, if the extension is enabled.
+ *
+ * @param string|null $apcuPrefix
+ *
+ * @return void
+ */
+ public function setApcuPrefix($apcuPrefix)
+ {
+ $this->apcuPrefix = function_exists('apcu_fetch') && filter_var(ini_get('apc.enabled'), FILTER_VALIDATE_BOOLEAN) ? $apcuPrefix : null;
+ }
+
+ /**
+ * The APCu prefix in use, or null if APCu caching is not enabled.
+ *
+ * @return string|null
+ */
+ public function getApcuPrefix()
+ {
+ return $this->apcuPrefix;
+ }
+
+ /**
+ * Registers this instance as an autoloader.
+ *
+ * @param bool $prepend Whether to prepend the autoloader or not
+ *
+ * @return void
+ */
+ public function register($prepend = false)
+ {
+ spl_autoload_register(array($this, 'loadClass'), true, $prepend);
+
+ if (null === $this->vendorDir) {
+ return;
+ }
+
+ if ($prepend) {
+ self::$registeredLoaders = array($this->vendorDir => $this) + self::$registeredLoaders;
+ } else {
+ unset(self::$registeredLoaders[$this->vendorDir]);
+ self::$registeredLoaders[$this->vendorDir] = $this;
+ }
+ }
+
+ /**
+ * Unregisters this instance as an autoloader.
+ *
+ * @return void
+ */
+ public function unregister()
+ {
+ spl_autoload_unregister(array($this, 'loadClass'));
+
+ if (null !== $this->vendorDir) {
+ unset(self::$registeredLoaders[$this->vendorDir]);
+ }
+ }
+
+ /**
+ * Loads the given class or interface.
+ *
+ * @param string $class The name of the class
+ * @return true|null True if loaded, null otherwise
+ */
+ public function loadClass($class)
+ {
+ if ($file = $this->findFile($class)) {
+ $includeFile = self::$includeFile;
+ $includeFile($file);
+
+ return true;
+ }
+
+ return null;
+ }
+
+ /**
+ * Finds the path to the file where the class is defined.
+ *
+ * @param string $class The name of the class
+ *
+ * @return string|false The path if found, false otherwise
+ */
+ public function findFile($class)
+ {
+ // class map lookup
+ if (isset($this->classMap[$class])) {
+ return $this->classMap[$class];
+ }
+ if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) {
+ return false;
+ }
+ if (null !== $this->apcuPrefix) {
+ $file = apcu_fetch($this->apcuPrefix.$class, $hit);
+ if ($hit) {
+ return $file;
+ }
+ }
+
+ $file = $this->findFileWithExtension($class, '.php');
+
+ // Search for Hack files if we are running on HHVM
+ if (false === $file && defined('HHVM_VERSION')) {
+ $file = $this->findFileWithExtension($class, '.hh');
+ }
+
+ if (null !== $this->apcuPrefix) {
+ apcu_add($this->apcuPrefix.$class, $file);
+ }
+
+ if (false === $file) {
+ // Remember that this class does not exist.
+ $this->missingClasses[$class] = true;
+ }
+
+ return $file;
+ }
+
+ /**
+ * Returns the currently registered loaders keyed by their corresponding vendor directories.
+ *
+ * @return array
+ */
+ public static function getRegisteredLoaders()
+ {
+ return self::$registeredLoaders;
+ }
+
+ /**
+ * @param string $class
+ * @param string $ext
+ * @return string|false
+ */
+ private function findFileWithExtension($class, $ext)
+ {
+ // PSR-4 lookup
+ $logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext;
+
+ $first = $class[0];
+ if (isset($this->prefixLengthsPsr4[$first])) {
+ $subPath = $class;
+ while (false !== $lastPos = strrpos($subPath, '\\')) {
+ $subPath = substr($subPath, 0, $lastPos);
+ $search = $subPath . '\\';
+ if (isset($this->prefixDirsPsr4[$search])) {
+ $pathEnd = DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1);
+ foreach ($this->prefixDirsPsr4[$search] as $dir) {
+ if (file_exists($file = $dir . $pathEnd)) {
+ return $file;
+ }
+ }
+ }
+ }
+ }
+
+ // PSR-4 fallback dirs
+ foreach ($this->fallbackDirsPsr4 as $dir) {
+ if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) {
+ return $file;
+ }
+ }
+
+ // PSR-0 lookup
+ if (false !== $pos = strrpos($class, '\\')) {
+ // namespaced class name
+ $logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1)
+ . strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR);
+ } else {
+ // PEAR-like class name
+ $logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext;
+ }
+
+ if (isset($this->prefixesPsr0[$first])) {
+ foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) {
+ if (0 === strpos($class, $prefix)) {
+ foreach ($dirs as $dir) {
+ if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
+ return $file;
+ }
+ }
+ }
+ }
+ }
+
+ // PSR-0 fallback dirs
+ foreach ($this->fallbackDirsPsr0 as $dir) {
+ if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
+ return $file;
+ }
+ }
+
+ // PSR-0 include paths.
+ if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) {
+ return $file;
+ }
+
+ return false;
+ }
+
+ /**
+ * @return void
+ */
+ private static function initializeIncludeClosure()
+ {
+ if (self::$includeFile !== null) {
+ return;
+ }
+
+ /**
+ * Scope isolated include.
+ *
+ * Prevents access to $this/self from included files.
+ *
+ * @param string $file
+ * @return void
+ */
+ self::$includeFile = \Closure::bind(static function($file) {
+ include $file;
+ }, null, null);
+ }
+}
diff --git a/vendor/composer/InstalledVersions.php b/vendor/composer/InstalledVersions.php
new file mode 100644
index 0000000..2052022
--- /dev/null
+++ b/vendor/composer/InstalledVersions.php
@@ -0,0 +1,396 @@
+
+ * Jordi Boggiano
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Composer;
+
+use Composer\Autoload\ClassLoader;
+use Composer\Semver\VersionParser;
+
+/**
+ * This class is copied in every Composer installed project and available to all
+ *
+ * See also https://getcomposer.org/doc/07-runtime.md#installed-versions
+ *
+ * To require its presence, you can require `composer-runtime-api ^2.0`
+ *
+ * @final
+ */
+class InstalledVersions
+{
+ /**
+ * @var string|null if set (by reflection by Composer), this should be set to the path where this class is being copied to
+ * @internal
+ */
+ private static $selfDir = null;
+
+ /**
+ * @var mixed[]|null
+ * @psalm-var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array}|array{}|null
+ */
+ private static $installed;
+
+ /**
+ * @var bool
+ */
+ private static $installedIsLocalDir;
+
+ /**
+ * @var bool|null
+ */
+ private static $canGetVendors;
+
+ /**
+ * @var array[]
+ * @psalm-var array}>
+ */
+ private static $installedByVendor = array();
+
+ /**
+ * Returns a list of all package names which are present, either by being installed, replaced or provided
+ *
+ * @return string[]
+ * @psalm-return list
+ */
+ public static function getInstalledPackages()
+ {
+ $packages = array();
+ foreach (self::getInstalled() as $installed) {
+ $packages[] = array_keys($installed['versions']);
+ }
+
+ if (1 === \count($packages)) {
+ return $packages[0];
+ }
+
+ return array_keys(array_flip(\call_user_func_array('array_merge', $packages)));
+ }
+
+ /**
+ * Returns a list of all package names with a specific type e.g. 'library'
+ *
+ * @param string $type
+ * @return string[]
+ * @psalm-return list
+ */
+ public static function getInstalledPackagesByType($type)
+ {
+ $packagesByType = array();
+
+ foreach (self::getInstalled() as $installed) {
+ foreach ($installed['versions'] as $name => $package) {
+ if (isset($package['type']) && $package['type'] === $type) {
+ $packagesByType[] = $name;
+ }
+ }
+ }
+
+ return $packagesByType;
+ }
+
+ /**
+ * Checks whether the given package is installed
+ *
+ * This also returns true if the package name is provided or replaced by another package
+ *
+ * @param string $packageName
+ * @param bool $includeDevRequirements
+ * @return bool
+ */
+ public static function isInstalled($packageName, $includeDevRequirements = true)
+ {
+ foreach (self::getInstalled() as $installed) {
+ if (isset($installed['versions'][$packageName])) {
+ return $includeDevRequirements || !isset($installed['versions'][$packageName]['dev_requirement']) || $installed['versions'][$packageName]['dev_requirement'] === false;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Checks whether the given package satisfies a version constraint
+ *
+ * e.g. If you want to know whether version 2.3+ of package foo/bar is installed, you would call:
+ *
+ * Composer\InstalledVersions::satisfies(new VersionParser, 'foo/bar', '^2.3')
+ *
+ * @param VersionParser $parser Install composer/semver to have access to this class and functionality
+ * @param string $packageName
+ * @param string|null $constraint A version constraint to check for, if you pass one you have to make sure composer/semver is required by your package
+ * @return bool
+ */
+ public static function satisfies(VersionParser $parser, $packageName, $constraint)
+ {
+ $constraint = $parser->parseConstraints((string) $constraint);
+ $provided = $parser->parseConstraints(self::getVersionRanges($packageName));
+
+ return $provided->matches($constraint);
+ }
+
+ /**
+ * Returns a version constraint representing all the range(s) which are installed for a given package
+ *
+ * It is easier to use this via isInstalled() with the $constraint argument if you need to check
+ * whether a given version of a package is installed, and not just whether it exists
+ *
+ * @param string $packageName
+ * @return string Version constraint usable with composer/semver
+ */
+ public static function getVersionRanges($packageName)
+ {
+ foreach (self::getInstalled() as $installed) {
+ if (!isset($installed['versions'][$packageName])) {
+ continue;
+ }
+
+ $ranges = array();
+ if (isset($installed['versions'][$packageName]['pretty_version'])) {
+ $ranges[] = $installed['versions'][$packageName]['pretty_version'];
+ }
+ if (array_key_exists('aliases', $installed['versions'][$packageName])) {
+ $ranges = array_merge($ranges, $installed['versions'][$packageName]['aliases']);
+ }
+ if (array_key_exists('replaced', $installed['versions'][$packageName])) {
+ $ranges = array_merge($ranges, $installed['versions'][$packageName]['replaced']);
+ }
+ if (array_key_exists('provided', $installed['versions'][$packageName])) {
+ $ranges = array_merge($ranges, $installed['versions'][$packageName]['provided']);
+ }
+
+ return implode(' || ', $ranges);
+ }
+
+ throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
+ }
+
+ /**
+ * @param string $packageName
+ * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present
+ */
+ public static function getVersion($packageName)
+ {
+ foreach (self::getInstalled() as $installed) {
+ if (!isset($installed['versions'][$packageName])) {
+ continue;
+ }
+
+ if (!isset($installed['versions'][$packageName]['version'])) {
+ return null;
+ }
+
+ return $installed['versions'][$packageName]['version'];
+ }
+
+ throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
+ }
+
+ /**
+ * @param string $packageName
+ * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present
+ */
+ public static function getPrettyVersion($packageName)
+ {
+ foreach (self::getInstalled() as $installed) {
+ if (!isset($installed['versions'][$packageName])) {
+ continue;
+ }
+
+ if (!isset($installed['versions'][$packageName]['pretty_version'])) {
+ return null;
+ }
+
+ return $installed['versions'][$packageName]['pretty_version'];
+ }
+
+ throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
+ }
+
+ /**
+ * @param string $packageName
+ * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as reference
+ */
+ public static function getReference($packageName)
+ {
+ foreach (self::getInstalled() as $installed) {
+ if (!isset($installed['versions'][$packageName])) {
+ continue;
+ }
+
+ if (!isset($installed['versions'][$packageName]['reference'])) {
+ return null;
+ }
+
+ return $installed['versions'][$packageName]['reference'];
+ }
+
+ throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
+ }
+
+ /**
+ * @param string $packageName
+ * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as install path. Packages of type metapackages also have a null install path.
+ */
+ public static function getInstallPath($packageName)
+ {
+ foreach (self::getInstalled() as $installed) {
+ if (!isset($installed['versions'][$packageName])) {
+ continue;
+ }
+
+ return isset($installed['versions'][$packageName]['install_path']) ? $installed['versions'][$packageName]['install_path'] : null;
+ }
+
+ throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
+ }
+
+ /**
+ * @return array
+ * @psalm-return array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}
+ */
+ public static function getRootPackage()
+ {
+ $installed = self::getInstalled();
+
+ return $installed[0]['root'];
+ }
+
+ /**
+ * Returns the raw installed.php data for custom implementations
+ *
+ * @deprecated Use getAllRawData() instead which returns all datasets for all autoloaders present in the process. getRawData only returns the first dataset loaded, which may not be what you expect.
+ * @return array[]
+ * @psalm-return array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array}
+ */
+ public static function getRawData()
+ {
+ @trigger_error('getRawData only returns the first dataset loaded, which may not be what you expect. Use getAllRawData() instead which returns all datasets for all autoloaders present in the process.', E_USER_DEPRECATED);
+
+ if (null === self::$installed) {
+ // only require the installed.php file if this file is loaded from its dumped location,
+ // and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937
+ if (substr(__DIR__, -8, 1) !== 'C') {
+ self::$installed = include __DIR__ . '/installed.php';
+ } else {
+ self::$installed = array();
+ }
+ }
+
+ return self::$installed;
+ }
+
+ /**
+ * Returns the raw data of all installed.php which are currently loaded for custom implementations
+ *
+ * @return array[]
+ * @psalm-return list}>
+ */
+ public static function getAllRawData()
+ {
+ return self::getInstalled();
+ }
+
+ /**
+ * Lets you reload the static array from another file
+ *
+ * This is only useful for complex integrations in which a project needs to use
+ * this class but then also needs to execute another project's autoloader in process,
+ * and wants to ensure both projects have access to their version of installed.php.
+ *
+ * A typical case would be PHPUnit, where it would need to make sure it reads all
+ * the data it needs from this class, then call reload() with
+ * `require $CWD/vendor/composer/installed.php` (or similar) as input to make sure
+ * the project in which it runs can then also use this class safely, without
+ * interference between PHPUnit's dependencies and the project's dependencies.
+ *
+ * @param array[] $data A vendor/composer/installed.php data set
+ * @return void
+ *
+ * @psalm-param array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array} $data
+ */
+ public static function reload($data)
+ {
+ self::$installed = $data;
+ self::$installedByVendor = array();
+
+ // when using reload, we disable the duplicate protection to ensure that self::$installed data is
+ // always returned, but we cannot know whether it comes from the installed.php in __DIR__ or not,
+ // so we have to assume it does not, and that may result in duplicate data being returned when listing
+ // all installed packages for example
+ self::$installedIsLocalDir = false;
+ }
+
+ /**
+ * @return string
+ */
+ private static function getSelfDir()
+ {
+ if (self::$selfDir === null) {
+ self::$selfDir = strtr(__DIR__, '\\', '/');
+ }
+
+ return self::$selfDir;
+ }
+
+ /**
+ * @return array[]
+ * @psalm-return list}>
+ */
+ private static function getInstalled()
+ {
+ if (null === self::$canGetVendors) {
+ self::$canGetVendors = method_exists('Composer\Autoload\ClassLoader', 'getRegisteredLoaders');
+ }
+
+ $installed = array();
+ $copiedLocalDir = false;
+
+ if (self::$canGetVendors) {
+ $selfDir = self::getSelfDir();
+ foreach (ClassLoader::getRegisteredLoaders() as $vendorDir => $loader) {
+ $vendorDir = strtr($vendorDir, '\\', '/');
+ if (isset(self::$installedByVendor[$vendorDir])) {
+ $installed[] = self::$installedByVendor[$vendorDir];
+ } elseif (is_file($vendorDir.'/composer/installed.php')) {
+ /** @var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array} $required */
+ $required = require $vendorDir.'/composer/installed.php';
+ self::$installedByVendor[$vendorDir] = $required;
+ $installed[] = $required;
+ if (self::$installed === null && $vendorDir.'/composer' === $selfDir) {
+ self::$installed = $required;
+ self::$installedIsLocalDir = true;
+ }
+ }
+ if (self::$installedIsLocalDir && $vendorDir.'/composer' === $selfDir) {
+ $copiedLocalDir = true;
+ }
+ }
+ }
+
+ if (null === self::$installed) {
+ // only require the installed.php file if this file is loaded from its dumped location,
+ // and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937
+ if (substr(__DIR__, -8, 1) !== 'C') {
+ /** @var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array} $required */
+ $required = require __DIR__ . '/installed.php';
+ self::$installed = $required;
+ } else {
+ self::$installed = array();
+ }
+ }
+
+ if (self::$installed !== array() && !$copiedLocalDir) {
+ $installed[] = self::$installed;
+ }
+
+ return $installed;
+ }
+}
diff --git a/vendor/composer/LICENSE b/vendor/composer/LICENSE
new file mode 100644
index 0000000..f27399a
--- /dev/null
+++ b/vendor/composer/LICENSE
@@ -0,0 +1,21 @@
+
+Copyright (c) Nils Adermann, Jordi Boggiano
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is furnished
+to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+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/vendor/composer/autoload_classmap.php b/vendor/composer/autoload_classmap.php
new file mode 100644
index 0000000..c8f885c
--- /dev/null
+++ b/vendor/composer/autoload_classmap.php
@@ -0,0 +1,16 @@
+ $vendorDir . '/composer/InstalledVersions.php',
+ 'GPBMetadata\\GrpcGcp' => $vendorDir . '/google/grpc-gcp/src/generated/GPBMetadata/GrpcGcp.php',
+ 'Grpc\\Gcp\\AffinityConfig' => $vendorDir . '/google/grpc-gcp/src/generated/Grpc/Gcp/AffinityConfig.php',
+ 'Grpc\\Gcp\\AffinityConfig_Command' => $vendorDir . '/google/grpc-gcp/src/generated/Grpc/Gcp/AffinityConfig_Command.php',
+ 'Grpc\\Gcp\\ApiConfig' => $vendorDir . '/google/grpc-gcp/src/generated/Grpc/Gcp/ApiConfig.php',
+ 'Grpc\\Gcp\\ChannelPoolConfig' => $vendorDir . '/google/grpc-gcp/src/generated/Grpc/Gcp/ChannelPoolConfig.php',
+ 'Grpc\\Gcp\\MethodConfig' => $vendorDir . '/google/grpc-gcp/src/generated/Grpc/Gcp/MethodConfig.php',
+);
diff --git a/vendor/composer/autoload_files.php b/vendor/composer/autoload_files.php
new file mode 100644
index 0000000..e0dff4e
--- /dev/null
+++ b/vendor/composer/autoload_files.php
@@ -0,0 +1,13 @@
+ $vendorDir . '/ralouphie/getallheaders/src/getallheaders.php',
+ '6e3fae29631ef280660b3cdad06f25a8' => $vendorDir . '/symfony/deprecation-contracts/function.php',
+ '37a3dc5111fe8f707ab4c132ef1dbc62' => $vendorDir . '/guzzlehttp/guzzle/src/functions_include.php',
+ 'e39a8b23c42d4e1452234d762b03835a' => $vendorDir . '/ramsey/uuid/src/functions.php',
+);
diff --git a/vendor/composer/autoload_namespaces.php b/vendor/composer/autoload_namespaces.php
new file mode 100644
index 0000000..15a2ff3
--- /dev/null
+++ b/vendor/composer/autoload_namespaces.php
@@ -0,0 +1,9 @@
+ array($vendorDir . '/ramsey/uuid/src'),
+ 'Ramsey\\Collection\\' => array($vendorDir . '/ramsey/collection/src'),
+ 'Psr\\Log\\' => array($vendorDir . '/psr/log/src'),
+ 'Psr\\Http\\Message\\' => array($vendorDir . '/psr/http-factory/src', $vendorDir . '/psr/http-message/src'),
+ 'Psr\\Http\\Client\\' => array($vendorDir . '/psr/http-client/src'),
+ 'Psr\\Cache\\' => array($vendorDir . '/psr/cache/src'),
+ 'GuzzleHttp\\Psr7\\' => array($vendorDir . '/guzzlehttp/psr7/src'),
+ 'GuzzleHttp\\Promise\\' => array($vendorDir . '/guzzlehttp/promises/src'),
+ 'GuzzleHttp\\' => array($vendorDir . '/guzzlehttp/guzzle/src'),
+ 'Grpc\\Gcp\\' => array($vendorDir . '/google/grpc-gcp/src'),
+ 'Grpc\\' => array($vendorDir . '/grpc/grpc/src/lib'),
+ 'Google\\Type\\' => array($vendorDir . '/google/common-protos/src/Type'),
+ 'Google\\Rpc\\' => array($vendorDir . '/google/common-protos/src/Rpc'),
+ 'Google\\Protobuf\\' => array($vendorDir . '/google/protobuf/src/Google/Protobuf'),
+ 'Google\\LongRunning\\' => array($vendorDir . '/google/longrunning/src/LongRunning'),
+ 'Google\\Iam\\' => array($vendorDir . '/google/common-protos/src/Iam'),
+ 'Google\\Cloud\\Dialogflow\\' => array($vendorDir . '/google/cloud-dialogflow/src'),
+ 'Google\\Cloud\\' => array($vendorDir . '/google/common-protos/src/Cloud'),
+ 'Google\\Auth\\' => array($vendorDir . '/google/auth/src'),
+ 'Google\\Api\\' => array($vendorDir . '/google/common-protos/src/Api'),
+ 'Google\\ApiCore\\LongRunning\\' => array($vendorDir . '/google/longrunning/src/ApiCore/LongRunning'),
+ 'Google\\ApiCore\\' => array($vendorDir . '/google/gax/src'),
+ 'GPBMetadata\\Google\\Type\\' => array($vendorDir . '/google/common-protos/metadata/Type'),
+ 'GPBMetadata\\Google\\Rpc\\' => array($vendorDir . '/google/common-protos/metadata/Rpc'),
+ 'GPBMetadata\\Google\\Protobuf\\' => array($vendorDir . '/google/protobuf/src/GPBMetadata/Google/Protobuf'),
+ 'GPBMetadata\\Google\\Longrunning\\' => array($vendorDir . '/google/longrunning/metadata/Longrunning'),
+ 'GPBMetadata\\Google\\Logging\\' => array($vendorDir . '/google/common-protos/metadata/Logging'),
+ 'GPBMetadata\\Google\\Iam\\' => array($vendorDir . '/google/common-protos/metadata/Iam'),
+ 'GPBMetadata\\Google\\Cloud\\Dialogflow\\' => array($vendorDir . '/google/cloud-dialogflow/metadata'),
+ 'GPBMetadata\\Google\\Cloud\\' => array($vendorDir . '/google/common-protos/metadata/Cloud'),
+ 'GPBMetadata\\Google\\Api\\' => array($vendorDir . '/google/common-protos/metadata/Api'),
+ 'GPBMetadata\\ApiCore\\' => array($vendorDir . '/google/gax/metadata/ApiCore'),
+ 'Firebase\\JWT\\' => array($vendorDir . '/firebase/php-jwt/src'),
+ 'Brick\\Math\\' => array($vendorDir . '/brick/math/src'),
+);
diff --git a/vendor/composer/autoload_real.php b/vendor/composer/autoload_real.php
new file mode 100644
index 0000000..0655b22
--- /dev/null
+++ b/vendor/composer/autoload_real.php
@@ -0,0 +1,50 @@
+register(true);
+
+ $filesToLoad = \Composer\Autoload\ComposerStaticInit5835386f60e88a2d37220bdb9cc5dd48::$files;
+ $requireFile = \Closure::bind(static function ($fileIdentifier, $file) {
+ if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
+ $GLOBALS['__composer_autoload_files'][$fileIdentifier] = true;
+
+ require $file;
+ }
+ }, null, null);
+ foreach ($filesToLoad as $fileIdentifier => $file) {
+ $requireFile($fileIdentifier, $file);
+ }
+
+ return $loader;
+ }
+}
diff --git a/vendor/composer/autoload_static.php b/vendor/composer/autoload_static.php
new file mode 100644
index 0000000..6d8cf64
--- /dev/null
+++ b/vendor/composer/autoload_static.php
@@ -0,0 +1,227 @@
+ __DIR__ . '/..' . '/ralouphie/getallheaders/src/getallheaders.php',
+ '6e3fae29631ef280660b3cdad06f25a8' => __DIR__ . '/..' . '/symfony/deprecation-contracts/function.php',
+ '37a3dc5111fe8f707ab4c132ef1dbc62' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/functions_include.php',
+ 'e39a8b23c42d4e1452234d762b03835a' => __DIR__ . '/..' . '/ramsey/uuid/src/functions.php',
+ );
+
+ public static $prefixLengthsPsr4 = array (
+ 'R' =>
+ array (
+ 'Ramsey\\Uuid\\' => 12,
+ 'Ramsey\\Collection\\' => 18,
+ ),
+ 'P' =>
+ array (
+ 'Psr\\Log\\' => 8,
+ 'Psr\\Http\\Message\\' => 17,
+ 'Psr\\Http\\Client\\' => 16,
+ 'Psr\\Cache\\' => 10,
+ ),
+ 'G' =>
+ array (
+ 'GuzzleHttp\\Psr7\\' => 16,
+ 'GuzzleHttp\\Promise\\' => 19,
+ 'GuzzleHttp\\' => 11,
+ 'Grpc\\Gcp\\' => 9,
+ 'Grpc\\' => 5,
+ 'Google\\Type\\' => 12,
+ 'Google\\Rpc\\' => 11,
+ 'Google\\Protobuf\\' => 16,
+ 'Google\\LongRunning\\' => 19,
+ 'Google\\Iam\\' => 11,
+ 'Google\\Cloud\\Dialogflow\\' => 24,
+ 'Google\\Cloud\\' => 13,
+ 'Google\\Auth\\' => 12,
+ 'Google\\Api\\' => 11,
+ 'Google\\ApiCore\\LongRunning\\' => 27,
+ 'Google\\ApiCore\\' => 15,
+ 'GPBMetadata\\Google\\Type\\' => 24,
+ 'GPBMetadata\\Google\\Rpc\\' => 23,
+ 'GPBMetadata\\Google\\Protobuf\\' => 28,
+ 'GPBMetadata\\Google\\Longrunning\\' => 31,
+ 'GPBMetadata\\Google\\Logging\\' => 27,
+ 'GPBMetadata\\Google\\Iam\\' => 23,
+ 'GPBMetadata\\Google\\Cloud\\Dialogflow\\' => 36,
+ 'GPBMetadata\\Google\\Cloud\\' => 25,
+ 'GPBMetadata\\Google\\Api\\' => 23,
+ 'GPBMetadata\\ApiCore\\' => 20,
+ ),
+ 'F' =>
+ array (
+ 'Firebase\\JWT\\' => 13,
+ ),
+ 'B' =>
+ array (
+ 'Brick\\Math\\' => 11,
+ ),
+ );
+
+ public static $prefixDirsPsr4 = array (
+ 'Ramsey\\Uuid\\' =>
+ array (
+ 0 => __DIR__ . '/..' . '/ramsey/uuid/src',
+ ),
+ 'Ramsey\\Collection\\' =>
+ array (
+ 0 => __DIR__ . '/..' . '/ramsey/collection/src',
+ ),
+ 'Psr\\Log\\' =>
+ array (
+ 0 => __DIR__ . '/..' . '/psr/log/src',
+ ),
+ 'Psr\\Http\\Message\\' =>
+ array (
+ 0 => __DIR__ . '/..' . '/psr/http-factory/src',
+ 1 => __DIR__ . '/..' . '/psr/http-message/src',
+ ),
+ 'Psr\\Http\\Client\\' =>
+ array (
+ 0 => __DIR__ . '/..' . '/psr/http-client/src',
+ ),
+ 'Psr\\Cache\\' =>
+ array (
+ 0 => __DIR__ . '/..' . '/psr/cache/src',
+ ),
+ 'GuzzleHttp\\Psr7\\' =>
+ array (
+ 0 => __DIR__ . '/..' . '/guzzlehttp/psr7/src',
+ ),
+ 'GuzzleHttp\\Promise\\' =>
+ array (
+ 0 => __DIR__ . '/..' . '/guzzlehttp/promises/src',
+ ),
+ 'GuzzleHttp\\' =>
+ array (
+ 0 => __DIR__ . '/..' . '/guzzlehttp/guzzle/src',
+ ),
+ 'Grpc\\Gcp\\' =>
+ array (
+ 0 => __DIR__ . '/..' . '/google/grpc-gcp/src',
+ ),
+ 'Grpc\\' =>
+ array (
+ 0 => __DIR__ . '/..' . '/grpc/grpc/src/lib',
+ ),
+ 'Google\\Type\\' =>
+ array (
+ 0 => __DIR__ . '/..' . '/google/common-protos/src/Type',
+ ),
+ 'Google\\Rpc\\' =>
+ array (
+ 0 => __DIR__ . '/..' . '/google/common-protos/src/Rpc',
+ ),
+ 'Google\\Protobuf\\' =>
+ array (
+ 0 => __DIR__ . '/..' . '/google/protobuf/src/Google/Protobuf',
+ ),
+ 'Google\\LongRunning\\' =>
+ array (
+ 0 => __DIR__ . '/..' . '/google/longrunning/src/LongRunning',
+ ),
+ 'Google\\Iam\\' =>
+ array (
+ 0 => __DIR__ . '/..' . '/google/common-protos/src/Iam',
+ ),
+ 'Google\\Cloud\\Dialogflow\\' =>
+ array (
+ 0 => __DIR__ . '/..' . '/google/cloud-dialogflow/src',
+ ),
+ 'Google\\Cloud\\' =>
+ array (
+ 0 => __DIR__ . '/..' . '/google/common-protos/src/Cloud',
+ ),
+ 'Google\\Auth\\' =>
+ array (
+ 0 => __DIR__ . '/..' . '/google/auth/src',
+ ),
+ 'Google\\Api\\' =>
+ array (
+ 0 => __DIR__ . '/..' . '/google/common-protos/src/Api',
+ ),
+ 'Google\\ApiCore\\LongRunning\\' =>
+ array (
+ 0 => __DIR__ . '/..' . '/google/longrunning/src/ApiCore/LongRunning',
+ ),
+ 'Google\\ApiCore\\' =>
+ array (
+ 0 => __DIR__ . '/..' . '/google/gax/src',
+ ),
+ 'GPBMetadata\\Google\\Type\\' =>
+ array (
+ 0 => __DIR__ . '/..' . '/google/common-protos/metadata/Type',
+ ),
+ 'GPBMetadata\\Google\\Rpc\\' =>
+ array (
+ 0 => __DIR__ . '/..' . '/google/common-protos/metadata/Rpc',
+ ),
+ 'GPBMetadata\\Google\\Protobuf\\' =>
+ array (
+ 0 => __DIR__ . '/..' . '/google/protobuf/src/GPBMetadata/Google/Protobuf',
+ ),
+ 'GPBMetadata\\Google\\Longrunning\\' =>
+ array (
+ 0 => __DIR__ . '/..' . '/google/longrunning/metadata/Longrunning',
+ ),
+ 'GPBMetadata\\Google\\Logging\\' =>
+ array (
+ 0 => __DIR__ . '/..' . '/google/common-protos/metadata/Logging',
+ ),
+ 'GPBMetadata\\Google\\Iam\\' =>
+ array (
+ 0 => __DIR__ . '/..' . '/google/common-protos/metadata/Iam',
+ ),
+ 'GPBMetadata\\Google\\Cloud\\Dialogflow\\' =>
+ array (
+ 0 => __DIR__ . '/..' . '/google/cloud-dialogflow/metadata',
+ ),
+ 'GPBMetadata\\Google\\Cloud\\' =>
+ array (
+ 0 => __DIR__ . '/..' . '/google/common-protos/metadata/Cloud',
+ ),
+ 'GPBMetadata\\Google\\Api\\' =>
+ array (
+ 0 => __DIR__ . '/..' . '/google/common-protos/metadata/Api',
+ ),
+ 'GPBMetadata\\ApiCore\\' =>
+ array (
+ 0 => __DIR__ . '/..' . '/google/gax/metadata/ApiCore',
+ ),
+ 'Firebase\\JWT\\' =>
+ array (
+ 0 => __DIR__ . '/..' . '/firebase/php-jwt/src',
+ ),
+ 'Brick\\Math\\' =>
+ array (
+ 0 => __DIR__ . '/..' . '/brick/math/src',
+ ),
+ );
+
+ public static $classMap = array (
+ 'Composer\\InstalledVersions' => __DIR__ . '/..' . '/composer/InstalledVersions.php',
+ 'GPBMetadata\\GrpcGcp' => __DIR__ . '/..' . '/google/grpc-gcp/src/generated/GPBMetadata/GrpcGcp.php',
+ 'Grpc\\Gcp\\AffinityConfig' => __DIR__ . '/..' . '/google/grpc-gcp/src/generated/Grpc/Gcp/AffinityConfig.php',
+ 'Grpc\\Gcp\\AffinityConfig_Command' => __DIR__ . '/..' . '/google/grpc-gcp/src/generated/Grpc/Gcp/AffinityConfig_Command.php',
+ 'Grpc\\Gcp\\ApiConfig' => __DIR__ . '/..' . '/google/grpc-gcp/src/generated/Grpc/Gcp/ApiConfig.php',
+ 'Grpc\\Gcp\\ChannelPoolConfig' => __DIR__ . '/..' . '/google/grpc-gcp/src/generated/Grpc/Gcp/ChannelPoolConfig.php',
+ 'Grpc\\Gcp\\MethodConfig' => __DIR__ . '/..' . '/google/grpc-gcp/src/generated/Grpc/Gcp/MethodConfig.php',
+ );
+
+ public static function getInitializer(ClassLoader $loader)
+ {
+ return \Closure::bind(function () use ($loader) {
+ $loader->prefixLengthsPsr4 = ComposerStaticInit5835386f60e88a2d37220bdb9cc5dd48::$prefixLengthsPsr4;
+ $loader->prefixDirsPsr4 = ComposerStaticInit5835386f60e88a2d37220bdb9cc5dd48::$prefixDirsPsr4;
+ $loader->classMap = ComposerStaticInit5835386f60e88a2d37220bdb9cc5dd48::$classMap;
+
+ }, null, ClassLoader::class);
+ }
+}
diff --git a/vendor/composer/installed.json b/vendor/composer/installed.json
new file mode 100644
index 0000000..e1c8db7
--- /dev/null
+++ b/vendor/composer/installed.json
@@ -0,0 +1,1448 @@
+{
+ "packages": [
+ {
+ "name": "brick/math",
+ "version": "0.14.0",
+ "version_normalized": "0.14.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/brick/math.git",
+ "reference": "113a8ee2656b882d4c3164fa31aa6e12cbb7aaa2"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/brick/math/zipball/113a8ee2656b882d4c3164fa31aa6e12cbb7aaa2",
+ "reference": "113a8ee2656b882d4c3164fa31aa6e12cbb7aaa2",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^8.2"
+ },
+ "require-dev": {
+ "php-coveralls/php-coveralls": "^2.2",
+ "phpstan/phpstan": "2.1.22",
+ "phpunit/phpunit": "^11.5"
+ },
+ "time": "2025-08-29T12:40:03+00:00",
+ "type": "library",
+ "installation-source": "dist",
+ "autoload": {
+ "psr-4": {
+ "Brick\\Math\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "description": "Arbitrary-precision arithmetic library",
+ "keywords": [
+ "Arbitrary-precision",
+ "BigInteger",
+ "BigRational",
+ "arithmetic",
+ "bigdecimal",
+ "bignum",
+ "bignumber",
+ "brick",
+ "decimal",
+ "integer",
+ "math",
+ "mathematics",
+ "rational"
+ ],
+ "support": {
+ "issues": "https://github.com/brick/math/issues",
+ "source": "https://github.com/brick/math/tree/0.14.0"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/BenMorel",
+ "type": "github"
+ }
+ ],
+ "install-path": "../brick/math"
+ },
+ {
+ "name": "firebase/php-jwt",
+ "version": "v6.11.1",
+ "version_normalized": "6.11.1.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/firebase/php-jwt.git",
+ "reference": "d1e91ecf8c598d073d0995afa8cd5c75c6e19e66"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/firebase/php-jwt/zipball/d1e91ecf8c598d073d0995afa8cd5c75c6e19e66",
+ "reference": "d1e91ecf8c598d073d0995afa8cd5c75c6e19e66",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^8.0"
+ },
+ "require-dev": {
+ "guzzlehttp/guzzle": "^7.4",
+ "phpspec/prophecy-phpunit": "^2.0",
+ "phpunit/phpunit": "^9.5",
+ "psr/cache": "^2.0||^3.0",
+ "psr/http-client": "^1.0",
+ "psr/http-factory": "^1.0"
+ },
+ "suggest": {
+ "ext-sodium": "Support EdDSA (Ed25519) signatures",
+ "paragonie/sodium_compat": "Support EdDSA (Ed25519) signatures when libsodium is not present"
+ },
+ "time": "2025-04-09T20:32:01+00:00",
+ "type": "library",
+ "installation-source": "dist",
+ "autoload": {
+ "psr-4": {
+ "Firebase\\JWT\\": "src"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Neuman Vong",
+ "email": "neuman+pear@twilio.com",
+ "role": "Developer"
+ },
+ {
+ "name": "Anant Narayanan",
+ "email": "anant@php.net",
+ "role": "Developer"
+ }
+ ],
+ "description": "A simple library to encode and decode JSON Web Tokens (JWT) in PHP. Should conform to the current spec.",
+ "homepage": "https://github.com/firebase/php-jwt",
+ "keywords": [
+ "jwt",
+ "php"
+ ],
+ "support": {
+ "issues": "https://github.com/firebase/php-jwt/issues",
+ "source": "https://github.com/firebase/php-jwt/tree/v6.11.1"
+ },
+ "install-path": "../firebase/php-jwt"
+ },
+ {
+ "name": "google/auth",
+ "version": "v1.48.1",
+ "version_normalized": "1.48.1.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/googleapis/google-auth-library-php.git",
+ "reference": "023f41a2c80fb98a493dfb9dffcab643481a7ab0"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/googleapis/google-auth-library-php/zipball/023f41a2c80fb98a493dfb9dffcab643481a7ab0",
+ "reference": "023f41a2c80fb98a493dfb9dffcab643481a7ab0",
+ "shasum": ""
+ },
+ "require": {
+ "firebase/php-jwt": "^6.0",
+ "guzzlehttp/guzzle": "^7.4.5",
+ "guzzlehttp/psr7": "^2.4.5",
+ "php": "^8.1",
+ "psr/cache": "^2.0||^3.0",
+ "psr/http-message": "^1.1||^2.0",
+ "psr/log": "^3.0"
+ },
+ "require-dev": {
+ "guzzlehttp/promises": "^2.0",
+ "kelvinmo/simplejwt": "0.7.1",
+ "phpseclib/phpseclib": "^3.0.35",
+ "phpspec/prophecy-phpunit": "^2.1",
+ "phpunit/phpunit": "^9.6",
+ "sebastian/comparator": ">=1.2.3",
+ "squizlabs/php_codesniffer": "^4.0",
+ "symfony/process": "^6.0||^7.0",
+ "webmozart/assert": "^1.11"
+ },
+ "suggest": {
+ "phpseclib/phpseclib": "May be used in place of OpenSSL for signing strings or for token management. Please require version ^2."
+ },
+ "time": "2025-09-30T04:22:33+00:00",
+ "type": "library",
+ "installation-source": "dist",
+ "autoload": {
+ "psr-4": {
+ "Google\\Auth\\": "src"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "Apache-2.0"
+ ],
+ "description": "Google Auth Library for PHP",
+ "homepage": "https://github.com/google/google-auth-library-php",
+ "keywords": [
+ "Authentication",
+ "google",
+ "oauth2"
+ ],
+ "support": {
+ "docs": "https://cloud.google.com/php/docs/reference/auth/latest",
+ "issues": "https://github.com/googleapis/google-auth-library-php/issues",
+ "source": "https://github.com/googleapis/google-auth-library-php/tree/v1.48.1"
+ },
+ "install-path": "../google/auth"
+ },
+ {
+ "name": "google/cloud-dialogflow",
+ "version": "v2.2.0",
+ "version_normalized": "2.2.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/googleapis/google-cloud-php-dialogflow.git",
+ "reference": "b536e04b66e518505dbc0266c7f288f4d692cf7a"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/googleapis/google-cloud-php-dialogflow/zipball/b536e04b66e518505dbc0266c7f288f4d692cf7a",
+ "reference": "b536e04b66e518505dbc0266c7f288f4d692cf7a",
+ "shasum": ""
+ },
+ "require": {
+ "google/gax": "^1.38.0",
+ "php": "^8.1"
+ },
+ "require-dev": {
+ "google/cloud-core": "^1.52.7",
+ "phpunit/phpunit": "^9.0"
+ },
+ "suggest": {
+ "ext-grpc": "Enables use of gRPC, a universal high-performance RPC framework created by Google."
+ },
+ "time": "2025-09-20T01:29:44+00:00",
+ "type": "library",
+ "extra": {
+ "component": {
+ "id": "cloud-dialogflow",
+ "path": "Dialogflow",
+ "entry": null,
+ "target": "googleapis/google-cloud-php-dialogflow.git"
+ }
+ },
+ "installation-source": "dist",
+ "autoload": {
+ "psr-4": {
+ "Google\\Cloud\\Dialogflow\\": "src",
+ "GPBMetadata\\Google\\Cloud\\Dialogflow\\": "metadata"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "Apache-2.0"
+ ],
+ "description": "Google Cloud Dialogflow Client for PHP",
+ "support": {
+ "source": "https://github.com/googleapis/google-cloud-php-dialogflow/tree/v2.2.0"
+ },
+ "install-path": "../google/cloud-dialogflow"
+ },
+ {
+ "name": "google/common-protos",
+ "version": "4.12.4",
+ "version_normalized": "4.12.4.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/googleapis/common-protos-php.git",
+ "reference": "0127156899af0df2681bd42024c60bd5360d64e3"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/googleapis/common-protos-php/zipball/0127156899af0df2681bd42024c60bd5360d64e3",
+ "reference": "0127156899af0df2681bd42024c60bd5360d64e3",
+ "shasum": ""
+ },
+ "require": {
+ "google/protobuf": "^4.31",
+ "php": "^8.1"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^9.6"
+ },
+ "time": "2025-09-20T01:29:44+00:00",
+ "type": "library",
+ "extra": {
+ "component": {
+ "id": "common-protos",
+ "path": "CommonProtos",
+ "entry": "README.md",
+ "target": "googleapis/common-protos-php.git"
+ }
+ },
+ "installation-source": "dist",
+ "autoload": {
+ "psr-4": {
+ "Google\\Api\\": "src/Api",
+ "Google\\Iam\\": "src/Iam",
+ "Google\\Rpc\\": "src/Rpc",
+ "Google\\Type\\": "src/Type",
+ "Google\\Cloud\\": "src/Cloud",
+ "GPBMetadata\\Google\\Api\\": "metadata/Api",
+ "GPBMetadata\\Google\\Iam\\": "metadata/Iam",
+ "GPBMetadata\\Google\\Rpc\\": "metadata/Rpc",
+ "GPBMetadata\\Google\\Type\\": "metadata/Type",
+ "GPBMetadata\\Google\\Cloud\\": "metadata/Cloud",
+ "GPBMetadata\\Google\\Logging\\": "metadata/Logging"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "Apache-2.0"
+ ],
+ "description": "Google API Common Protos for PHP",
+ "homepage": "https://github.com/googleapis/common-protos-php",
+ "keywords": [
+ "google"
+ ],
+ "support": {
+ "source": "https://github.com/googleapis/common-protos-php/tree/v4.12.4"
+ },
+ "install-path": "../google/common-protos"
+ },
+ {
+ "name": "google/gax",
+ "version": "v1.38.0",
+ "version_normalized": "1.38.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/googleapis/gax-php.git",
+ "reference": "0e1bce4a30722e85485bbb132b2fa811d66b397b"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/googleapis/gax-php/zipball/0e1bce4a30722e85485bbb132b2fa811d66b397b",
+ "reference": "0e1bce4a30722e85485bbb132b2fa811d66b397b",
+ "shasum": ""
+ },
+ "require": {
+ "google/auth": "^1.45",
+ "google/common-protos": "^4.4",
+ "google/grpc-gcp": "^0.4",
+ "google/longrunning": "~0.4",
+ "google/protobuf": "^4.31",
+ "grpc/grpc": "^1.13",
+ "guzzlehttp/promises": "^2.0",
+ "guzzlehttp/psr7": "^2.0",
+ "php": "^8.1",
+ "ramsey/uuid": "^4.0"
+ },
+ "conflict": {
+ "ext-protobuf": "<4.31.0"
+ },
+ "require-dev": {
+ "phpspec/prophecy-phpunit": "^2.1",
+ "phpstan/phpstan": "^2.0",
+ "phpunit/phpunit": "^9.6",
+ "squizlabs/php_codesniffer": "4.*"
+ },
+ "time": "2025-09-17T18:22:14+00:00",
+ "type": "library",
+ "installation-source": "dist",
+ "autoload": {
+ "psr-4": {
+ "Google\\ApiCore\\": "src",
+ "GPBMetadata\\ApiCore\\": "metadata/ApiCore"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "description": "Google API Core for PHP",
+ "homepage": "https://github.com/googleapis/gax-php",
+ "keywords": [
+ "google"
+ ],
+ "support": {
+ "issues": "https://github.com/googleapis/gax-php/issues",
+ "source": "https://github.com/googleapis/gax-php/tree/v1.38.0"
+ },
+ "install-path": "../google/gax"
+ },
+ {
+ "name": "google/grpc-gcp",
+ "version": "v0.4.1",
+ "version_normalized": "0.4.1.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/GoogleCloudPlatform/grpc-gcp-php.git",
+ "reference": "e585b7721bbe806ef45b5c52ae43dfc2bff89968"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/GoogleCloudPlatform/grpc-gcp-php/zipball/e585b7721bbe806ef45b5c52ae43dfc2bff89968",
+ "reference": "e585b7721bbe806ef45b5c52ae43dfc2bff89968",
+ "shasum": ""
+ },
+ "require": {
+ "google/auth": "^1.3",
+ "google/protobuf": "^v3.25.3||^4.26.1",
+ "grpc/grpc": "^v1.13.0",
+ "php": "^8.0",
+ "psr/cache": "^1.0.1||^2.0.0||^3.0.0"
+ },
+ "require-dev": {
+ "google/cloud-spanner": "^1.7",
+ "phpunit/phpunit": "^9.0"
+ },
+ "time": "2025-02-19T21:53:22+00:00",
+ "type": "library",
+ "installation-source": "dist",
+ "autoload": {
+ "psr-4": {
+ "Grpc\\Gcp\\": "src/"
+ },
+ "classmap": [
+ "src/generated/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "Apache-2.0"
+ ],
+ "description": "gRPC GCP library for channel management",
+ "support": {
+ "issues": "https://github.com/GoogleCloudPlatform/grpc-gcp-php/issues",
+ "source": "https://github.com/GoogleCloudPlatform/grpc-gcp-php/tree/v0.4.1"
+ },
+ "install-path": "../google/grpc-gcp"
+ },
+ {
+ "name": "google/longrunning",
+ "version": "0.5.0",
+ "version_normalized": "0.5.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/googleapis/php-longrunning.git",
+ "reference": "715519ab4aaf3c4268adb2b551ee0f34135c8c5f"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/googleapis/php-longrunning/zipball/715519ab4aaf3c4268adb2b551ee0f34135c8c5f",
+ "reference": "715519ab4aaf3c4268adb2b551ee0f34135c8c5f",
+ "shasum": ""
+ },
+ "require-dev": {
+ "google/gax": "^1.38.0",
+ "phpunit/phpunit": "^9.0"
+ },
+ "time": "2025-09-20T01:29:44+00:00",
+ "type": "library",
+ "extra": {
+ "component": {
+ "id": "longrunning",
+ "path": "LongRunning",
+ "entry": null,
+ "target": "googleapis/php-longrunning"
+ }
+ },
+ "installation-source": "dist",
+ "autoload": {
+ "psr-4": {
+ "Google\\LongRunning\\": "src/LongRunning",
+ "Google\\ApiCore\\LongRunning\\": "src/ApiCore/LongRunning",
+ "GPBMetadata\\Google\\Longrunning\\": "metadata/Longrunning"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "Apache-2.0"
+ ],
+ "description": "Google LongRunning Client for PHP",
+ "support": {
+ "source": "https://github.com/googleapis/php-longrunning/tree/v0.5.0"
+ },
+ "install-path": "../google/longrunning"
+ },
+ {
+ "name": "google/protobuf",
+ "version": "v4.32.1",
+ "version_normalized": "4.32.1.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/protocolbuffers/protobuf-php.git",
+ "reference": "c4ed1c1f9bbc1e91766e2cd6c0af749324fe87cb"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/protocolbuffers/protobuf-php/zipball/c4ed1c1f9bbc1e91766e2cd6c0af749324fe87cb",
+ "reference": "c4ed1c1f9bbc1e91766e2cd6c0af749324fe87cb",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.1.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": ">=5.0.0 <8.5.27"
+ },
+ "suggest": {
+ "ext-bcmath": "Need to support JSON deserialization"
+ },
+ "time": "2025-09-14T05:14:52+00:00",
+ "type": "library",
+ "installation-source": "dist",
+ "autoload": {
+ "psr-4": {
+ "Google\\Protobuf\\": "src/Google/Protobuf",
+ "GPBMetadata\\Google\\Protobuf\\": "src/GPBMetadata/Google/Protobuf"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "description": "proto library for PHP",
+ "homepage": "https://developers.google.com/protocol-buffers/",
+ "keywords": [
+ "proto"
+ ],
+ "support": {
+ "source": "https://github.com/protocolbuffers/protobuf-php/tree/v4.32.1"
+ },
+ "install-path": "../google/protobuf"
+ },
+ {
+ "name": "grpc/grpc",
+ "version": "1.74.0",
+ "version_normalized": "1.74.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/grpc/grpc-php.git",
+ "reference": "32bf4dba256d60d395582fb6e4e8d3936bcdb713"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/grpc/grpc-php/zipball/32bf4dba256d60d395582fb6e4e8d3936bcdb713",
+ "reference": "32bf4dba256d60d395582fb6e4e8d3936bcdb713",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.0.0"
+ },
+ "require-dev": {
+ "google/auth": "^v1.3.0"
+ },
+ "suggest": {
+ "ext-protobuf": "For better performance, install the protobuf C extension.",
+ "google/protobuf": "To get started using grpc quickly, install the native protobuf library."
+ },
+ "time": "2025-07-24T20:02:16+00:00",
+ "type": "library",
+ "installation-source": "dist",
+ "autoload": {
+ "psr-4": {
+ "Grpc\\": "src/lib/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "Apache-2.0"
+ ],
+ "description": "gRPC library for PHP",
+ "homepage": "https://grpc.io",
+ "keywords": [
+ "rpc"
+ ],
+ "support": {
+ "source": "https://github.com/grpc/grpc-php/tree/v1.74.0"
+ },
+ "install-path": "../grpc/grpc"
+ },
+ {
+ "name": "guzzlehttp/guzzle",
+ "version": "7.10.0",
+ "version_normalized": "7.10.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/guzzle/guzzle.git",
+ "reference": "b51ac707cfa420b7bfd4e4d5e510ba8008e822b4"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/guzzle/guzzle/zipball/b51ac707cfa420b7bfd4e4d5e510ba8008e822b4",
+ "reference": "b51ac707cfa420b7bfd4e4d5e510ba8008e822b4",
+ "shasum": ""
+ },
+ "require": {
+ "ext-json": "*",
+ "guzzlehttp/promises": "^2.3",
+ "guzzlehttp/psr7": "^2.8",
+ "php": "^7.2.5 || ^8.0",
+ "psr/http-client": "^1.0",
+ "symfony/deprecation-contracts": "^2.2 || ^3.0"
+ },
+ "provide": {
+ "psr/http-client-implementation": "1.0"
+ },
+ "require-dev": {
+ "bamarni/composer-bin-plugin": "^1.8.2",
+ "ext-curl": "*",
+ "guzzle/client-integration-tests": "3.0.2",
+ "php-http/message-factory": "^1.1",
+ "phpunit/phpunit": "^8.5.39 || ^9.6.20",
+ "psr/log": "^1.1 || ^2.0 || ^3.0"
+ },
+ "suggest": {
+ "ext-curl": "Required for CURL handler support",
+ "ext-intl": "Required for Internationalized Domain Name (IDN) support",
+ "psr/log": "Required for using the Log middleware"
+ },
+ "time": "2025-08-23T22:36:01+00:00",
+ "type": "library",
+ "extra": {
+ "bamarni-bin": {
+ "bin-links": true,
+ "forward-command": false
+ }
+ },
+ "installation-source": "dist",
+ "autoload": {
+ "files": [
+ "src/functions_include.php"
+ ],
+ "psr-4": {
+ "GuzzleHttp\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Graham Campbell",
+ "email": "hello@gjcampbell.co.uk",
+ "homepage": "https://github.com/GrahamCampbell"
+ },
+ {
+ "name": "Michael Dowling",
+ "email": "mtdowling@gmail.com",
+ "homepage": "https://github.com/mtdowling"
+ },
+ {
+ "name": "Jeremy Lindblom",
+ "email": "jeremeamia@gmail.com",
+ "homepage": "https://github.com/jeremeamia"
+ },
+ {
+ "name": "George Mponos",
+ "email": "gmponos@gmail.com",
+ "homepage": "https://github.com/gmponos"
+ },
+ {
+ "name": "Tobias Nyholm",
+ "email": "tobias.nyholm@gmail.com",
+ "homepage": "https://github.com/Nyholm"
+ },
+ {
+ "name": "Márk Sági-Kazár",
+ "email": "mark.sagikazar@gmail.com",
+ "homepage": "https://github.com/sagikazarmark"
+ },
+ {
+ "name": "Tobias Schultze",
+ "email": "webmaster@tubo-world.de",
+ "homepage": "https://github.com/Tobion"
+ }
+ ],
+ "description": "Guzzle is a PHP HTTP client library",
+ "keywords": [
+ "client",
+ "curl",
+ "framework",
+ "http",
+ "http client",
+ "psr-18",
+ "psr-7",
+ "rest",
+ "web service"
+ ],
+ "support": {
+ "issues": "https://github.com/guzzle/guzzle/issues",
+ "source": "https://github.com/guzzle/guzzle/tree/7.10.0"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/GrahamCampbell",
+ "type": "github"
+ },
+ {
+ "url": "https://github.com/Nyholm",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/guzzle",
+ "type": "tidelift"
+ }
+ ],
+ "install-path": "../guzzlehttp/guzzle"
+ },
+ {
+ "name": "guzzlehttp/promises",
+ "version": "2.3.0",
+ "version_normalized": "2.3.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/guzzle/promises.git",
+ "reference": "481557b130ef3790cf82b713667b43030dc9c957"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/guzzle/promises/zipball/481557b130ef3790cf82b713667b43030dc9c957",
+ "reference": "481557b130ef3790cf82b713667b43030dc9c957",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7.2.5 || ^8.0"
+ },
+ "require-dev": {
+ "bamarni/composer-bin-plugin": "^1.8.2",
+ "phpunit/phpunit": "^8.5.44 || ^9.6.25"
+ },
+ "time": "2025-08-22T14:34:08+00:00",
+ "type": "library",
+ "extra": {
+ "bamarni-bin": {
+ "bin-links": true,
+ "forward-command": false
+ }
+ },
+ "installation-source": "dist",
+ "autoload": {
+ "psr-4": {
+ "GuzzleHttp\\Promise\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Graham Campbell",
+ "email": "hello@gjcampbell.co.uk",
+ "homepage": "https://github.com/GrahamCampbell"
+ },
+ {
+ "name": "Michael Dowling",
+ "email": "mtdowling@gmail.com",
+ "homepage": "https://github.com/mtdowling"
+ },
+ {
+ "name": "Tobias Nyholm",
+ "email": "tobias.nyholm@gmail.com",
+ "homepage": "https://github.com/Nyholm"
+ },
+ {
+ "name": "Tobias Schultze",
+ "email": "webmaster@tubo-world.de",
+ "homepage": "https://github.com/Tobion"
+ }
+ ],
+ "description": "Guzzle promises library",
+ "keywords": [
+ "promise"
+ ],
+ "support": {
+ "issues": "https://github.com/guzzle/promises/issues",
+ "source": "https://github.com/guzzle/promises/tree/2.3.0"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/GrahamCampbell",
+ "type": "github"
+ },
+ {
+ "url": "https://github.com/Nyholm",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/promises",
+ "type": "tidelift"
+ }
+ ],
+ "install-path": "../guzzlehttp/promises"
+ },
+ {
+ "name": "guzzlehttp/psr7",
+ "version": "2.8.0",
+ "version_normalized": "2.8.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/guzzle/psr7.git",
+ "reference": "21dc724a0583619cd1652f673303492272778051"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/guzzle/psr7/zipball/21dc724a0583619cd1652f673303492272778051",
+ "reference": "21dc724a0583619cd1652f673303492272778051",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7.2.5 || ^8.0",
+ "psr/http-factory": "^1.0",
+ "psr/http-message": "^1.1 || ^2.0",
+ "ralouphie/getallheaders": "^3.0"
+ },
+ "provide": {
+ "psr/http-factory-implementation": "1.0",
+ "psr/http-message-implementation": "1.0"
+ },
+ "require-dev": {
+ "bamarni/composer-bin-plugin": "^1.8.2",
+ "http-interop/http-factory-tests": "0.9.0",
+ "phpunit/phpunit": "^8.5.44 || ^9.6.25"
+ },
+ "suggest": {
+ "laminas/laminas-httphandlerrunner": "Emit PSR-7 responses"
+ },
+ "time": "2025-08-23T21:21:41+00:00",
+ "type": "library",
+ "extra": {
+ "bamarni-bin": {
+ "bin-links": true,
+ "forward-command": false
+ }
+ },
+ "installation-source": "dist",
+ "autoload": {
+ "psr-4": {
+ "GuzzleHttp\\Psr7\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Graham Campbell",
+ "email": "hello@gjcampbell.co.uk",
+ "homepage": "https://github.com/GrahamCampbell"
+ },
+ {
+ "name": "Michael Dowling",
+ "email": "mtdowling@gmail.com",
+ "homepage": "https://github.com/mtdowling"
+ },
+ {
+ "name": "George Mponos",
+ "email": "gmponos@gmail.com",
+ "homepage": "https://github.com/gmponos"
+ },
+ {
+ "name": "Tobias Nyholm",
+ "email": "tobias.nyholm@gmail.com",
+ "homepage": "https://github.com/Nyholm"
+ },
+ {
+ "name": "Márk Sági-Kazár",
+ "email": "mark.sagikazar@gmail.com",
+ "homepage": "https://github.com/sagikazarmark"
+ },
+ {
+ "name": "Tobias Schultze",
+ "email": "webmaster@tubo-world.de",
+ "homepage": "https://github.com/Tobion"
+ },
+ {
+ "name": "Márk Sági-Kazár",
+ "email": "mark.sagikazar@gmail.com",
+ "homepage": "https://sagikazarmark.hu"
+ }
+ ],
+ "description": "PSR-7 message implementation that also provides common utility methods",
+ "keywords": [
+ "http",
+ "message",
+ "psr-7",
+ "request",
+ "response",
+ "stream",
+ "uri",
+ "url"
+ ],
+ "support": {
+ "issues": "https://github.com/guzzle/psr7/issues",
+ "source": "https://github.com/guzzle/psr7/tree/2.8.0"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/GrahamCampbell",
+ "type": "github"
+ },
+ {
+ "url": "https://github.com/Nyholm",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/psr7",
+ "type": "tidelift"
+ }
+ ],
+ "install-path": "../guzzlehttp/psr7"
+ },
+ {
+ "name": "psr/cache",
+ "version": "3.0.0",
+ "version_normalized": "3.0.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/php-fig/cache.git",
+ "reference": "aa5030cfa5405eccfdcb1083ce040c2cb8d253bf"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/php-fig/cache/zipball/aa5030cfa5405eccfdcb1083ce040c2cb8d253bf",
+ "reference": "aa5030cfa5405eccfdcb1083ce040c2cb8d253bf",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.0.0"
+ },
+ "time": "2021-02-03T23:26:27+00:00",
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.0.x-dev"
+ }
+ },
+ "installation-source": "dist",
+ "autoload": {
+ "psr-4": {
+ "Psr\\Cache\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "PHP-FIG",
+ "homepage": "https://www.php-fig.org/"
+ }
+ ],
+ "description": "Common interface for caching libraries",
+ "keywords": [
+ "cache",
+ "psr",
+ "psr-6"
+ ],
+ "support": {
+ "source": "https://github.com/php-fig/cache/tree/3.0.0"
+ },
+ "install-path": "../psr/cache"
+ },
+ {
+ "name": "psr/http-client",
+ "version": "1.0.3",
+ "version_normalized": "1.0.3.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/php-fig/http-client.git",
+ "reference": "bb5906edc1c324c9a05aa0873d40117941e5fa90"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/php-fig/http-client/zipball/bb5906edc1c324c9a05aa0873d40117941e5fa90",
+ "reference": "bb5906edc1c324c9a05aa0873d40117941e5fa90",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7.0 || ^8.0",
+ "psr/http-message": "^1.0 || ^2.0"
+ },
+ "time": "2023-09-23T14:17:50+00:00",
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.0.x-dev"
+ }
+ },
+ "installation-source": "dist",
+ "autoload": {
+ "psr-4": {
+ "Psr\\Http\\Client\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "PHP-FIG",
+ "homepage": "https://www.php-fig.org/"
+ }
+ ],
+ "description": "Common interface for HTTP clients",
+ "homepage": "https://github.com/php-fig/http-client",
+ "keywords": [
+ "http",
+ "http-client",
+ "psr",
+ "psr-18"
+ ],
+ "support": {
+ "source": "https://github.com/php-fig/http-client"
+ },
+ "install-path": "../psr/http-client"
+ },
+ {
+ "name": "psr/http-factory",
+ "version": "1.1.0",
+ "version_normalized": "1.1.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/php-fig/http-factory.git",
+ "reference": "2b4765fddfe3b508ac62f829e852b1501d3f6e8a"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/php-fig/http-factory/zipball/2b4765fddfe3b508ac62f829e852b1501d3f6e8a",
+ "reference": "2b4765fddfe3b508ac62f829e852b1501d3f6e8a",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.1",
+ "psr/http-message": "^1.0 || ^2.0"
+ },
+ "time": "2024-04-15T12:06:14+00:00",
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.0.x-dev"
+ }
+ },
+ "installation-source": "dist",
+ "autoload": {
+ "psr-4": {
+ "Psr\\Http\\Message\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "PHP-FIG",
+ "homepage": "https://www.php-fig.org/"
+ }
+ ],
+ "description": "PSR-17: Common interfaces for PSR-7 HTTP message factories",
+ "keywords": [
+ "factory",
+ "http",
+ "message",
+ "psr",
+ "psr-17",
+ "psr-7",
+ "request",
+ "response"
+ ],
+ "support": {
+ "source": "https://github.com/php-fig/http-factory"
+ },
+ "install-path": "../psr/http-factory"
+ },
+ {
+ "name": "psr/http-message",
+ "version": "2.0",
+ "version_normalized": "2.0.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/php-fig/http-message.git",
+ "reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/php-fig/http-message/zipball/402d35bcb92c70c026d1a6a9883f06b2ead23d71",
+ "reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7.2 || ^8.0"
+ },
+ "time": "2023-04-04T09:54:51+00:00",
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.0.x-dev"
+ }
+ },
+ "installation-source": "dist",
+ "autoload": {
+ "psr-4": {
+ "Psr\\Http\\Message\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "PHP-FIG",
+ "homepage": "https://www.php-fig.org/"
+ }
+ ],
+ "description": "Common interface for HTTP messages",
+ "homepage": "https://github.com/php-fig/http-message",
+ "keywords": [
+ "http",
+ "http-message",
+ "psr",
+ "psr-7",
+ "request",
+ "response"
+ ],
+ "support": {
+ "source": "https://github.com/php-fig/http-message/tree/2.0"
+ },
+ "install-path": "../psr/http-message"
+ },
+ {
+ "name": "psr/log",
+ "version": "3.0.2",
+ "version_normalized": "3.0.2.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/php-fig/log.git",
+ "reference": "f16e1d5863e37f8d8c2a01719f5b34baa2b714d3"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/php-fig/log/zipball/f16e1d5863e37f8d8c2a01719f5b34baa2b714d3",
+ "reference": "f16e1d5863e37f8d8c2a01719f5b34baa2b714d3",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.0.0"
+ },
+ "time": "2024-09-11T13:17:53+00:00",
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "3.x-dev"
+ }
+ },
+ "installation-source": "dist",
+ "autoload": {
+ "psr-4": {
+ "Psr\\Log\\": "src"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "PHP-FIG",
+ "homepage": "https://www.php-fig.org/"
+ }
+ ],
+ "description": "Common interface for logging libraries",
+ "homepage": "https://github.com/php-fig/log",
+ "keywords": [
+ "log",
+ "psr",
+ "psr-3"
+ ],
+ "support": {
+ "source": "https://github.com/php-fig/log/tree/3.0.2"
+ },
+ "install-path": "../psr/log"
+ },
+ {
+ "name": "ralouphie/getallheaders",
+ "version": "3.0.3",
+ "version_normalized": "3.0.3.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/ralouphie/getallheaders.git",
+ "reference": "120b605dfeb996808c31b6477290a714d356e822"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/ralouphie/getallheaders/zipball/120b605dfeb996808c31b6477290a714d356e822",
+ "reference": "120b605dfeb996808c31b6477290a714d356e822",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.6"
+ },
+ "require-dev": {
+ "php-coveralls/php-coveralls": "^2.1",
+ "phpunit/phpunit": "^5 || ^6.5"
+ },
+ "time": "2019-03-08T08:55:37+00:00",
+ "type": "library",
+ "installation-source": "dist",
+ "autoload": {
+ "files": [
+ "src/getallheaders.php"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Ralph Khattar",
+ "email": "ralph.khattar@gmail.com"
+ }
+ ],
+ "description": "A polyfill for getallheaders.",
+ "support": {
+ "issues": "https://github.com/ralouphie/getallheaders/issues",
+ "source": "https://github.com/ralouphie/getallheaders/tree/develop"
+ },
+ "install-path": "../ralouphie/getallheaders"
+ },
+ {
+ "name": "ramsey/collection",
+ "version": "2.1.1",
+ "version_normalized": "2.1.1.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/ramsey/collection.git",
+ "reference": "344572933ad0181accbf4ba763e85a0306a8c5e2"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/ramsey/collection/zipball/344572933ad0181accbf4ba763e85a0306a8c5e2",
+ "reference": "344572933ad0181accbf4ba763e85a0306a8c5e2",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^8.1"
+ },
+ "require-dev": {
+ "captainhook/plugin-composer": "^5.3",
+ "ergebnis/composer-normalize": "^2.45",
+ "fakerphp/faker": "^1.24",
+ "hamcrest/hamcrest-php": "^2.0",
+ "jangregor/phpstan-prophecy": "^2.1",
+ "mockery/mockery": "^1.6",
+ "php-parallel-lint/php-console-highlighter": "^1.0",
+ "php-parallel-lint/php-parallel-lint": "^1.4",
+ "phpspec/prophecy-phpunit": "^2.3",
+ "phpstan/extension-installer": "^1.4",
+ "phpstan/phpstan": "^2.1",
+ "phpstan/phpstan-mockery": "^2.0",
+ "phpstan/phpstan-phpunit": "^2.0",
+ "phpunit/phpunit": "^10.5",
+ "ramsey/coding-standard": "^2.3",
+ "ramsey/conventional-commits": "^1.6",
+ "roave/security-advisories": "dev-latest"
+ },
+ "time": "2025-03-22T05:38:12+00:00",
+ "type": "library",
+ "extra": {
+ "captainhook": {
+ "force-install": true
+ },
+ "ramsey/conventional-commits": {
+ "configFile": "conventional-commits.json"
+ }
+ },
+ "installation-source": "dist",
+ "autoload": {
+ "psr-4": {
+ "Ramsey\\Collection\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Ben Ramsey",
+ "email": "ben@benramsey.com",
+ "homepage": "https://benramsey.com"
+ }
+ ],
+ "description": "A PHP library for representing and manipulating collections.",
+ "keywords": [
+ "array",
+ "collection",
+ "hash",
+ "map",
+ "queue",
+ "set"
+ ],
+ "support": {
+ "issues": "https://github.com/ramsey/collection/issues",
+ "source": "https://github.com/ramsey/collection/tree/2.1.1"
+ },
+ "install-path": "../ramsey/collection"
+ },
+ {
+ "name": "ramsey/uuid",
+ "version": "4.9.1",
+ "version_normalized": "4.9.1.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/ramsey/uuid.git",
+ "reference": "81f941f6f729b1e3ceea61d9d014f8b6c6800440"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/ramsey/uuid/zipball/81f941f6f729b1e3ceea61d9d014f8b6c6800440",
+ "reference": "81f941f6f729b1e3ceea61d9d014f8b6c6800440",
+ "shasum": ""
+ },
+ "require": {
+ "brick/math": "^0.8.8 || ^0.9 || ^0.10 || ^0.11 || ^0.12 || ^0.13 || ^0.14",
+ "php": "^8.0",
+ "ramsey/collection": "^1.2 || ^2.0"
+ },
+ "replace": {
+ "rhumsaa/uuid": "self.version"
+ },
+ "require-dev": {
+ "captainhook/captainhook": "^5.25",
+ "captainhook/plugin-composer": "^5.3",
+ "dealerdirect/phpcodesniffer-composer-installer": "^1.0",
+ "ergebnis/composer-normalize": "^2.47",
+ "mockery/mockery": "^1.6",
+ "paragonie/random-lib": "^2",
+ "php-mock/php-mock": "^2.6",
+ "php-mock/php-mock-mockery": "^1.5",
+ "php-parallel-lint/php-parallel-lint": "^1.4.0",
+ "phpbench/phpbench": "^1.2.14",
+ "phpstan/extension-installer": "^1.4",
+ "phpstan/phpstan": "^2.1",
+ "phpstan/phpstan-mockery": "^2.0",
+ "phpstan/phpstan-phpunit": "^2.0",
+ "phpunit/phpunit": "^9.6",
+ "slevomat/coding-standard": "^8.18",
+ "squizlabs/php_codesniffer": "^3.13"
+ },
+ "suggest": {
+ "ext-bcmath": "Enables faster math with arbitrary-precision integers using BCMath.",
+ "ext-gmp": "Enables faster math with arbitrary-precision integers using GMP.",
+ "ext-uuid": "Enables the use of PeclUuidTimeGenerator and PeclUuidRandomGenerator.",
+ "paragonie/random-lib": "Provides RandomLib for use with the RandomLibAdapter",
+ "ramsey/uuid-doctrine": "Allows the use of Ramsey\\Uuid\\Uuid as Doctrine field type."
+ },
+ "time": "2025-09-04T20:59:21+00:00",
+ "type": "library",
+ "extra": {
+ "captainhook": {
+ "force-install": true
+ }
+ },
+ "installation-source": "dist",
+ "autoload": {
+ "files": [
+ "src/functions.php"
+ ],
+ "psr-4": {
+ "Ramsey\\Uuid\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "description": "A PHP library for generating and working with universally unique identifiers (UUIDs).",
+ "keywords": [
+ "guid",
+ "identifier",
+ "uuid"
+ ],
+ "support": {
+ "issues": "https://github.com/ramsey/uuid/issues",
+ "source": "https://github.com/ramsey/uuid/tree/4.9.1"
+ },
+ "install-path": "../ramsey/uuid"
+ },
+ {
+ "name": "symfony/deprecation-contracts",
+ "version": "v3.6.0",
+ "version_normalized": "3.6.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/deprecation-contracts.git",
+ "reference": "63afe740e99a13ba87ec199bb07bbdee937a5b62"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/63afe740e99a13ba87ec199bb07bbdee937a5b62",
+ "reference": "63afe740e99a13ba87ec199bb07bbdee937a5b62",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.1"
+ },
+ "time": "2024-09-25T14:21:43+00:00",
+ "type": "library",
+ "extra": {
+ "thanks": {
+ "url": "https://github.com/symfony/contracts",
+ "name": "symfony/contracts"
+ },
+ "branch-alias": {
+ "dev-main": "3.6-dev"
+ }
+ },
+ "installation-source": "dist",
+ "autoload": {
+ "files": [
+ "function.php"
+ ]
+ },
+ "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": "A generic function and convention to trigger deprecation notices",
+ "homepage": "https://symfony.com",
+ "support": {
+ "source": "https://github.com/symfony/deprecation-contracts/tree/v3.6.0"
+ },
+ "funding": [
+ {
+ "url": "https://symfony.com/sponsor",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/fabpot",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+ "type": "tidelift"
+ }
+ ],
+ "install-path": "../symfony/deprecation-contracts"
+ }
+ ],
+ "dev": true,
+ "dev-package-names": []
+}
diff --git a/vendor/composer/installed.php b/vendor/composer/installed.php
new file mode 100644
index 0000000..a3438ff
--- /dev/null
+++ b/vendor/composer/installed.php
@@ -0,0 +1,245 @@
+ array(
+ 'name' => '__root__',
+ 'pretty_version' => 'dev-master',
+ 'version' => 'dev-master',
+ 'reference' => '923befa860dd5affe32046f42c857fdd3071b664',
+ 'type' => 'library',
+ 'install_path' => __DIR__ . '/../../',
+ 'aliases' => array(),
+ 'dev' => true,
+ ),
+ 'versions' => array(
+ '__root__' => array(
+ 'pretty_version' => 'dev-master',
+ 'version' => 'dev-master',
+ 'reference' => '923befa860dd5affe32046f42c857fdd3071b664',
+ 'type' => 'library',
+ 'install_path' => __DIR__ . '/../../',
+ 'aliases' => array(),
+ 'dev_requirement' => false,
+ ),
+ 'brick/math' => array(
+ 'pretty_version' => '0.14.0',
+ 'version' => '0.14.0.0',
+ 'reference' => '113a8ee2656b882d4c3164fa31aa6e12cbb7aaa2',
+ 'type' => 'library',
+ 'install_path' => __DIR__ . '/../brick/math',
+ 'aliases' => array(),
+ 'dev_requirement' => false,
+ ),
+ 'firebase/php-jwt' => array(
+ 'pretty_version' => 'v6.11.1',
+ 'version' => '6.11.1.0',
+ 'reference' => 'd1e91ecf8c598d073d0995afa8cd5c75c6e19e66',
+ 'type' => 'library',
+ 'install_path' => __DIR__ . '/../firebase/php-jwt',
+ 'aliases' => array(),
+ 'dev_requirement' => false,
+ ),
+ 'google/auth' => array(
+ 'pretty_version' => 'v1.48.1',
+ 'version' => '1.48.1.0',
+ 'reference' => '023f41a2c80fb98a493dfb9dffcab643481a7ab0',
+ 'type' => 'library',
+ 'install_path' => __DIR__ . '/../google/auth',
+ 'aliases' => array(),
+ 'dev_requirement' => false,
+ ),
+ 'google/cloud-dialogflow' => array(
+ 'pretty_version' => 'v2.2.0',
+ 'version' => '2.2.0.0',
+ 'reference' => 'b536e04b66e518505dbc0266c7f288f4d692cf7a',
+ 'type' => 'library',
+ 'install_path' => __DIR__ . '/../google/cloud-dialogflow',
+ 'aliases' => array(),
+ 'dev_requirement' => false,
+ ),
+ 'google/common-protos' => array(
+ 'pretty_version' => '4.12.4',
+ 'version' => '4.12.4.0',
+ 'reference' => '0127156899af0df2681bd42024c60bd5360d64e3',
+ 'type' => 'library',
+ 'install_path' => __DIR__ . '/../google/common-protos',
+ 'aliases' => array(),
+ 'dev_requirement' => false,
+ ),
+ 'google/gax' => array(
+ 'pretty_version' => 'v1.38.0',
+ 'version' => '1.38.0.0',
+ 'reference' => '0e1bce4a30722e85485bbb132b2fa811d66b397b',
+ 'type' => 'library',
+ 'install_path' => __DIR__ . '/../google/gax',
+ 'aliases' => array(),
+ 'dev_requirement' => false,
+ ),
+ 'google/grpc-gcp' => array(
+ 'pretty_version' => 'v0.4.1',
+ 'version' => '0.4.1.0',
+ 'reference' => 'e585b7721bbe806ef45b5c52ae43dfc2bff89968',
+ 'type' => 'library',
+ 'install_path' => __DIR__ . '/../google/grpc-gcp',
+ 'aliases' => array(),
+ 'dev_requirement' => false,
+ ),
+ 'google/longrunning' => array(
+ 'pretty_version' => '0.5.0',
+ 'version' => '0.5.0.0',
+ 'reference' => '715519ab4aaf3c4268adb2b551ee0f34135c8c5f',
+ 'type' => 'library',
+ 'install_path' => __DIR__ . '/../google/longrunning',
+ 'aliases' => array(),
+ 'dev_requirement' => false,
+ ),
+ 'google/protobuf' => array(
+ 'pretty_version' => 'v4.32.1',
+ 'version' => '4.32.1.0',
+ 'reference' => 'c4ed1c1f9bbc1e91766e2cd6c0af749324fe87cb',
+ 'type' => 'library',
+ 'install_path' => __DIR__ . '/../google/protobuf',
+ 'aliases' => array(),
+ 'dev_requirement' => false,
+ ),
+ 'grpc/grpc' => array(
+ 'pretty_version' => '1.74.0',
+ 'version' => '1.74.0.0',
+ 'reference' => '32bf4dba256d60d395582fb6e4e8d3936bcdb713',
+ 'type' => 'library',
+ 'install_path' => __DIR__ . '/../grpc/grpc',
+ 'aliases' => array(),
+ 'dev_requirement' => false,
+ ),
+ 'guzzlehttp/guzzle' => array(
+ 'pretty_version' => '7.10.0',
+ 'version' => '7.10.0.0',
+ 'reference' => 'b51ac707cfa420b7bfd4e4d5e510ba8008e822b4',
+ 'type' => 'library',
+ 'install_path' => __DIR__ . '/../guzzlehttp/guzzle',
+ 'aliases' => array(),
+ 'dev_requirement' => false,
+ ),
+ 'guzzlehttp/promises' => array(
+ 'pretty_version' => '2.3.0',
+ 'version' => '2.3.0.0',
+ 'reference' => '481557b130ef3790cf82b713667b43030dc9c957',
+ 'type' => 'library',
+ 'install_path' => __DIR__ . '/../guzzlehttp/promises',
+ 'aliases' => array(),
+ 'dev_requirement' => false,
+ ),
+ 'guzzlehttp/psr7' => array(
+ 'pretty_version' => '2.8.0',
+ 'version' => '2.8.0.0',
+ 'reference' => '21dc724a0583619cd1652f673303492272778051',
+ 'type' => 'library',
+ 'install_path' => __DIR__ . '/../guzzlehttp/psr7',
+ 'aliases' => array(),
+ 'dev_requirement' => false,
+ ),
+ 'psr/cache' => array(
+ 'pretty_version' => '3.0.0',
+ 'version' => '3.0.0.0',
+ 'reference' => 'aa5030cfa5405eccfdcb1083ce040c2cb8d253bf',
+ 'type' => 'library',
+ 'install_path' => __DIR__ . '/../psr/cache',
+ 'aliases' => array(),
+ 'dev_requirement' => false,
+ ),
+ 'psr/http-client' => array(
+ 'pretty_version' => '1.0.3',
+ 'version' => '1.0.3.0',
+ 'reference' => 'bb5906edc1c324c9a05aa0873d40117941e5fa90',
+ 'type' => 'library',
+ 'install_path' => __DIR__ . '/../psr/http-client',
+ 'aliases' => array(),
+ 'dev_requirement' => false,
+ ),
+ 'psr/http-client-implementation' => array(
+ 'dev_requirement' => false,
+ 'provided' => array(
+ 0 => '1.0',
+ ),
+ ),
+ 'psr/http-factory' => array(
+ 'pretty_version' => '1.1.0',
+ 'version' => '1.1.0.0',
+ 'reference' => '2b4765fddfe3b508ac62f829e852b1501d3f6e8a',
+ 'type' => 'library',
+ 'install_path' => __DIR__ . '/../psr/http-factory',
+ 'aliases' => array(),
+ 'dev_requirement' => false,
+ ),
+ 'psr/http-factory-implementation' => array(
+ 'dev_requirement' => false,
+ 'provided' => array(
+ 0 => '1.0',
+ ),
+ ),
+ 'psr/http-message' => array(
+ 'pretty_version' => '2.0',
+ 'version' => '2.0.0.0',
+ 'reference' => '402d35bcb92c70c026d1a6a9883f06b2ead23d71',
+ 'type' => 'library',
+ 'install_path' => __DIR__ . '/../psr/http-message',
+ 'aliases' => array(),
+ 'dev_requirement' => false,
+ ),
+ 'psr/http-message-implementation' => array(
+ 'dev_requirement' => false,
+ 'provided' => array(
+ 0 => '1.0',
+ ),
+ ),
+ 'psr/log' => array(
+ 'pretty_version' => '3.0.2',
+ 'version' => '3.0.2.0',
+ 'reference' => 'f16e1d5863e37f8d8c2a01719f5b34baa2b714d3',
+ 'type' => 'library',
+ 'install_path' => __DIR__ . '/../psr/log',
+ 'aliases' => array(),
+ 'dev_requirement' => false,
+ ),
+ 'ralouphie/getallheaders' => array(
+ 'pretty_version' => '3.0.3',
+ 'version' => '3.0.3.0',
+ 'reference' => '120b605dfeb996808c31b6477290a714d356e822',
+ 'type' => 'library',
+ 'install_path' => __DIR__ . '/../ralouphie/getallheaders',
+ 'aliases' => array(),
+ 'dev_requirement' => false,
+ ),
+ 'ramsey/collection' => array(
+ 'pretty_version' => '2.1.1',
+ 'version' => '2.1.1.0',
+ 'reference' => '344572933ad0181accbf4ba763e85a0306a8c5e2',
+ 'type' => 'library',
+ 'install_path' => __DIR__ . '/../ramsey/collection',
+ 'aliases' => array(),
+ 'dev_requirement' => false,
+ ),
+ 'ramsey/uuid' => array(
+ 'pretty_version' => '4.9.1',
+ 'version' => '4.9.1.0',
+ 'reference' => '81f941f6f729b1e3ceea61d9d014f8b6c6800440',
+ 'type' => 'library',
+ 'install_path' => __DIR__ . '/../ramsey/uuid',
+ 'aliases' => array(),
+ 'dev_requirement' => false,
+ ),
+ 'rhumsaa/uuid' => array(
+ 'dev_requirement' => false,
+ 'replaced' => array(
+ 0 => '4.9.1',
+ ),
+ ),
+ 'symfony/deprecation-contracts' => array(
+ 'pretty_version' => 'v3.6.0',
+ 'version' => '3.6.0.0',
+ 'reference' => '63afe740e99a13ba87ec199bb07bbdee937a5b62',
+ 'type' => 'library',
+ 'install_path' => __DIR__ . '/../symfony/deprecation-contracts',
+ 'aliases' => array(),
+ 'dev_requirement' => false,
+ ),
+ ),
+);
diff --git a/vendor/composer/platform_check.php b/vendor/composer/platform_check.php
new file mode 100644
index 0000000..14bf88d
--- /dev/null
+++ b/vendor/composer/platform_check.php
@@ -0,0 +1,25 @@
+= 80200)) {
+ $issues[] = 'Your Composer dependencies require a PHP version ">= 8.2.0". You are running ' . PHP_VERSION . '.';
+}
+
+if ($issues) {
+ if (!headers_sent()) {
+ header('HTTP/1.1 500 Internal Server Error');
+ }
+ if (!ini_get('display_errors')) {
+ if (PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') {
+ fwrite(STDERR, 'Composer detected issues in your platform:' . PHP_EOL.PHP_EOL . implode(PHP_EOL, $issues) . PHP_EOL.PHP_EOL);
+ } elseif (!headers_sent()) {
+ echo 'Composer detected issues in your platform:' . PHP_EOL.PHP_EOL . str_replace('You are running '.PHP_VERSION.'.', '', implode(PHP_EOL, $issues)) . PHP_EOL.PHP_EOL;
+ }
+ }
+ throw new \RuntimeException(
+ 'Composer detected issues in your platform: ' . implode(' ', $issues)
+ );
+}
diff --git a/vendor/firebase/php-jwt/CHANGELOG.md b/vendor/firebase/php-jwt/CHANGELOG.md
new file mode 100644
index 0000000..7b5f6ce
--- /dev/null
+++ b/vendor/firebase/php-jwt/CHANGELOG.md
@@ -0,0 +1,205 @@
+# Changelog
+
+## [6.11.1](https://github.com/firebase/php-jwt/compare/v6.11.0...v6.11.1) (2025-04-09)
+
+
+### Bug Fixes
+
+* update error text for consistency ([#528](https://github.com/firebase/php-jwt/issues/528)) ([c11113a](https://github.com/firebase/php-jwt/commit/c11113afa13265e016a669e75494b9203b8a7775))
+
+## [6.11.0](https://github.com/firebase/php-jwt/compare/v6.10.2...v6.11.0) (2025-01-23)
+
+
+### Features
+
+* support octet typed JWK ([#587](https://github.com/firebase/php-jwt/issues/587)) ([7cb8a26](https://github.com/firebase/php-jwt/commit/7cb8a265fa81edf2fa6ef8098f5bc5ae573c33ad))
+
+
+### Bug Fixes
+
+* refactor constructor Key to use PHP 8.0 syntax ([#577](https://github.com/firebase/php-jwt/issues/577)) ([29fa2ce](https://github.com/firebase/php-jwt/commit/29fa2ce9e0582cd397711eec1e80c05ce20fabca))
+
+## [6.10.2](https://github.com/firebase/php-jwt/compare/v6.10.1...v6.10.2) (2024-11-24)
+
+
+### Bug Fixes
+
+* Mitigate PHP8.4 deprecation warnings ([#570](https://github.com/firebase/php-jwt/issues/570)) ([76808fa](https://github.com/firebase/php-jwt/commit/76808fa227f3811aa5cdb3bf81233714b799a5b5))
+* support php 8.4 ([#583](https://github.com/firebase/php-jwt/issues/583)) ([e3d68b0](https://github.com/firebase/php-jwt/commit/e3d68b044421339443c74199edd020e03fb1887e))
+
+## [6.10.1](https://github.com/firebase/php-jwt/compare/v6.10.0...v6.10.1) (2024-05-18)
+
+
+### Bug Fixes
+
+* ensure ratelimit expiry is set every time ([#556](https://github.com/firebase/php-jwt/issues/556)) ([09cb208](https://github.com/firebase/php-jwt/commit/09cb2081c2c3bc0f61e2f2a5fbea5741f7498648))
+* ratelimit cache expiration ([#550](https://github.com/firebase/php-jwt/issues/550)) ([dda7250](https://github.com/firebase/php-jwt/commit/dda725033585ece30ff8cae8937320d7e9f18bae))
+
+## [6.10.0](https://github.com/firebase/php-jwt/compare/v6.9.0...v6.10.0) (2023-11-28)
+
+
+### Features
+
+* allow typ header override ([#546](https://github.com/firebase/php-jwt/issues/546)) ([79cb30b](https://github.com/firebase/php-jwt/commit/79cb30b729a22931b2fbd6b53f20629a83031ba9))
+
+## [6.9.0](https://github.com/firebase/php-jwt/compare/v6.8.1...v6.9.0) (2023-10-04)
+
+
+### Features
+
+* add payload to jwt exception ([#521](https://github.com/firebase/php-jwt/issues/521)) ([175edf9](https://github.com/firebase/php-jwt/commit/175edf958bb61922ec135b2333acf5622f2238a2))
+
+## [6.8.1](https://github.com/firebase/php-jwt/compare/v6.8.0...v6.8.1) (2023-07-14)
+
+
+### Bug Fixes
+
+* accept float claims but round down to ignore them ([#492](https://github.com/firebase/php-jwt/issues/492)) ([3936842](https://github.com/firebase/php-jwt/commit/39368423beeaacb3002afa7dcb75baebf204fe7e))
+* different BeforeValidException messages for nbf and iat ([#526](https://github.com/firebase/php-jwt/issues/526)) ([0a53cf2](https://github.com/firebase/php-jwt/commit/0a53cf2986e45c2bcbf1a269f313ebf56a154ee4))
+
+## [6.8.0](https://github.com/firebase/php-jwt/compare/v6.7.0...v6.8.0) (2023-06-14)
+
+
+### Features
+
+* add support for P-384 curve ([#515](https://github.com/firebase/php-jwt/issues/515)) ([5de4323](https://github.com/firebase/php-jwt/commit/5de4323f4baf4d70bca8663bd87682a69c656c3d))
+
+
+### Bug Fixes
+
+* handle invalid http responses ([#508](https://github.com/firebase/php-jwt/issues/508)) ([91c39c7](https://github.com/firebase/php-jwt/commit/91c39c72b22fc3e1191e574089552c1f2041c718))
+
+## [6.7.0](https://github.com/firebase/php-jwt/compare/v6.6.0...v6.7.0) (2023-06-14)
+
+
+### Features
+
+* add ed25519 support to JWK (public keys) ([#452](https://github.com/firebase/php-jwt/issues/452)) ([e53979a](https://github.com/firebase/php-jwt/commit/e53979abae927de916a75b9d239cfda8ce32be2a))
+
+## [6.6.0](https://github.com/firebase/php-jwt/compare/v6.5.0...v6.6.0) (2023-06-13)
+
+
+### Features
+
+* allow get headers when decoding token ([#442](https://github.com/firebase/php-jwt/issues/442)) ([fb85f47](https://github.com/firebase/php-jwt/commit/fb85f47cfaeffdd94faf8defdf07164abcdad6c3))
+
+
+### Bug Fixes
+
+* only check iat if nbf is not used ([#493](https://github.com/firebase/php-jwt/issues/493)) ([398ccd2](https://github.com/firebase/php-jwt/commit/398ccd25ea12fa84b9e4f1085d5ff448c21ec797))
+
+## [6.5.0](https://github.com/firebase/php-jwt/compare/v6.4.0...v6.5.0) (2023-05-12)
+
+
+### Bug Fixes
+
+* allow KID of '0' ([#505](https://github.com/firebase/php-jwt/issues/505)) ([9dc46a9](https://github.com/firebase/php-jwt/commit/9dc46a9c3e5801294249cfd2554c5363c9f9326a))
+
+
+### Miscellaneous Chores
+
+* drop support for PHP 7.3 ([#495](https://github.com/firebase/php-jwt/issues/495))
+
+## [6.4.0](https://github.com/firebase/php-jwt/compare/v6.3.2...v6.4.0) (2023-02-08)
+
+
+### Features
+
+* add support for W3C ES256K ([#462](https://github.com/firebase/php-jwt/issues/462)) ([213924f](https://github.com/firebase/php-jwt/commit/213924f51936291fbbca99158b11bd4ae56c2c95))
+* improve caching by only decoding jwks when necessary ([#486](https://github.com/firebase/php-jwt/issues/486)) ([78d3ed1](https://github.com/firebase/php-jwt/commit/78d3ed1073553f7d0bbffa6c2010009a0d483d5c))
+
+## [6.3.2](https://github.com/firebase/php-jwt/compare/v6.3.1...v6.3.2) (2022-11-01)
+
+
+### Bug Fixes
+
+* check kid before using as array index ([bad1b04](https://github.com/firebase/php-jwt/commit/bad1b040d0c736bbf86814c6b5ae614f517cf7bd))
+
+## [6.3.1](https://github.com/firebase/php-jwt/compare/v6.3.0...v6.3.1) (2022-11-01)
+
+
+### Bug Fixes
+
+* casing of GET for PSR compat ([#451](https://github.com/firebase/php-jwt/issues/451)) ([60b52b7](https://github.com/firebase/php-jwt/commit/60b52b71978790eafcf3b95cfbd83db0439e8d22))
+* string interpolation format for php 8.2 ([#446](https://github.com/firebase/php-jwt/issues/446)) ([2e07d8a](https://github.com/firebase/php-jwt/commit/2e07d8a1524d12b69b110ad649f17461d068b8f2))
+
+## 6.3.0 / 2022-07-15
+
+ - Added ES256 support to JWK parsing ([#399](https://github.com/firebase/php-jwt/pull/399))
+ - Fixed potential caching error in `CachedKeySet` by caching jwks as strings ([#435](https://github.com/firebase/php-jwt/pull/435))
+
+## 6.2.0 / 2022-05-14
+
+ - Added `CachedKeySet` ([#397](https://github.com/firebase/php-jwt/pull/397))
+ - Added `$defaultAlg` parameter to `JWT::parseKey` and `JWT::parseKeySet` ([#426](https://github.com/firebase/php-jwt/pull/426)).
+
+## 6.1.0 / 2022-03-23
+
+ - Drop support for PHP 5.3, 5.4, 5.5, 5.6, and 7.0
+ - Add parameter typing and return types where possible
+
+## 6.0.0 / 2022-01-24
+
+ - **Backwards-Compatibility Breaking Changes**: See the [Release Notes](https://github.com/firebase/php-jwt/releases/tag/v6.0.0) for more information.
+ - New Key object to prevent key/algorithm type confusion (#365)
+ - Add JWK support (#273)
+ - Add ES256 support (#256)
+ - Add ES384 support (#324)
+ - Add Ed25519 support (#343)
+
+## 5.0.0 / 2017-06-26
+- Support RS384 and RS512.
+ See [#117](https://github.com/firebase/php-jwt/pull/117). Thanks [@joostfaassen](https://github.com/joostfaassen)!
+- Add an example for RS256 openssl.
+ See [#125](https://github.com/firebase/php-jwt/pull/125). Thanks [@akeeman](https://github.com/akeeman)!
+- Detect invalid Base64 encoding in signature.
+ See [#162](https://github.com/firebase/php-jwt/pull/162). Thanks [@psignoret](https://github.com/psignoret)!
+- Update `JWT::verify` to handle OpenSSL errors.
+ See [#159](https://github.com/firebase/php-jwt/pull/159). Thanks [@bshaffer](https://github.com/bshaffer)!
+- Add `array` type hinting to `decode` method
+ See [#101](https://github.com/firebase/php-jwt/pull/101). Thanks [@hywak](https://github.com/hywak)!
+- Add all JSON error types.
+ See [#110](https://github.com/firebase/php-jwt/pull/110). Thanks [@gbalduzzi](https://github.com/gbalduzzi)!
+- Bugfix 'kid' not in given key list.
+ See [#129](https://github.com/firebase/php-jwt/pull/129). Thanks [@stampycode](https://github.com/stampycode)!
+- Miscellaneous cleanup, documentation and test fixes.
+ See [#107](https://github.com/firebase/php-jwt/pull/107), [#115](https://github.com/firebase/php-jwt/pull/115),
+ [#160](https://github.com/firebase/php-jwt/pull/160), [#161](https://github.com/firebase/php-jwt/pull/161), and
+ [#165](https://github.com/firebase/php-jwt/pull/165). Thanks [@akeeman](https://github.com/akeeman),
+ [@chinedufn](https://github.com/chinedufn), and [@bshaffer](https://github.com/bshaffer)!
+
+## 4.0.0 / 2016-07-17
+- Add support for late static binding. See [#88](https://github.com/firebase/php-jwt/pull/88) for details. Thanks to [@chappy84](https://github.com/chappy84)!
+- Use static `$timestamp` instead of `time()` to improve unit testing. See [#93](https://github.com/firebase/php-jwt/pull/93) for details. Thanks to [@josephmcdermott](https://github.com/josephmcdermott)!
+- Fixes to exceptions classes. See [#81](https://github.com/firebase/php-jwt/pull/81) for details. Thanks to [@Maks3w](https://github.com/Maks3w)!
+- Fixes to PHPDoc. See [#76](https://github.com/firebase/php-jwt/pull/76) for details. Thanks to [@akeeman](https://github.com/akeeman)!
+
+## 3.0.0 / 2015-07-22
+- Minimum PHP version updated from `5.2.0` to `5.3.0`.
+- Add `\Firebase\JWT` namespace. See
+[#59](https://github.com/firebase/php-jwt/pull/59) for details. Thanks to
+[@Dashron](https://github.com/Dashron)!
+- Require a non-empty key to decode and verify a JWT. See
+[#60](https://github.com/firebase/php-jwt/pull/60) for details. Thanks to
+[@sjones608](https://github.com/sjones608)!
+- Cleaner documentation blocks in the code. See
+[#62](https://github.com/firebase/php-jwt/pull/62) for details. Thanks to
+[@johanderuijter](https://github.com/johanderuijter)!
+
+## 2.2.0 / 2015-06-22
+- Add support for adding custom, optional JWT headers to `JWT::encode()`. See
+[#53](https://github.com/firebase/php-jwt/pull/53/files) for details. Thanks to
+[@mcocaro](https://github.com/mcocaro)!
+
+## 2.1.0 / 2015-05-20
+- Add support for adding a leeway to `JWT:decode()` that accounts for clock skew
+between signing and verifying entities. Thanks to [@lcabral](https://github.com/lcabral)!
+- Add support for passing an object implementing the `ArrayAccess` interface for
+`$keys` argument in `JWT::decode()`. Thanks to [@aztech-dev](https://github.com/aztech-dev)!
+
+## 2.0.0 / 2015-04-01
+- **Note**: It is strongly recommended that you update to > v2.0.0 to address
+ known security vulnerabilities in prior versions when both symmetric and
+ asymmetric keys are used together.
+- Update signature for `JWT::decode(...)` to require an array of supported
+ algorithms to use when verifying token signatures.
diff --git a/vendor/firebase/php-jwt/LICENSE b/vendor/firebase/php-jwt/LICENSE
new file mode 100644
index 0000000..11c0146
--- /dev/null
+++ b/vendor/firebase/php-jwt/LICENSE
@@ -0,0 +1,30 @@
+Copyright (c) 2011, Neuman Vong
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the following
+ disclaimer in the documentation and/or other materials provided
+ with the distribution.
+
+ * Neither the name of the copyright holder nor the names of other
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/vendor/firebase/php-jwt/README.md b/vendor/firebase/php-jwt/README.md
new file mode 100644
index 0000000..e45ccb8
--- /dev/null
+++ b/vendor/firebase/php-jwt/README.md
@@ -0,0 +1,425 @@
+
+[](https://packagist.org/packages/firebase/php-jwt)
+[](https://packagist.org/packages/firebase/php-jwt)
+[](https://packagist.org/packages/firebase/php-jwt)
+
+PHP-JWT
+=======
+A simple library to encode and decode JSON Web Tokens (JWT) in PHP, conforming to [RFC 7519](https://tools.ietf.org/html/rfc7519).
+
+Installation
+------------
+
+Use composer to manage your dependencies and download PHP-JWT:
+
+```bash
+composer require firebase/php-jwt
+```
+
+Optionally, install the `paragonie/sodium_compat` package from composer if your
+php env does not have libsodium installed:
+
+```bash
+composer require paragonie/sodium_compat
+```
+
+Example
+-------
+```php
+use Firebase\JWT\JWT;
+use Firebase\JWT\Key;
+
+$key = 'example_key';
+$payload = [
+ 'iss' => 'http://example.org',
+ 'aud' => 'http://example.com',
+ 'iat' => 1356999524,
+ 'nbf' => 1357000000
+];
+
+/**
+ * IMPORTANT:
+ * You must specify supported algorithms for your application. See
+ * https://tools.ietf.org/html/draft-ietf-jose-json-web-algorithms-40
+ * for a list of spec-compliant algorithms.
+ */
+$jwt = JWT::encode($payload, $key, 'HS256');
+$decoded = JWT::decode($jwt, new Key($key, 'HS256'));
+print_r($decoded);
+
+// Pass a stdClass in as the third parameter to get the decoded header values
+$headers = new stdClass();
+$decoded = JWT::decode($jwt, new Key($key, 'HS256'), $headers);
+print_r($headers);
+
+/*
+ NOTE: This will now be an object instead of an associative array. To get
+ an associative array, you will need to cast it as such:
+*/
+
+$decoded_array = (array) $decoded;
+
+/**
+ * You can add a leeway to account for when there is a clock skew times between
+ * the signing and verifying servers. It is recommended that this leeway should
+ * not be bigger than a few minutes.
+ *
+ * Source: http://self-issued.info/docs/draft-ietf-oauth-json-web-token.html#nbfDef
+ */
+JWT::$leeway = 60; // $leeway in seconds
+$decoded = JWT::decode($jwt, new Key($key, 'HS256'));
+```
+Example encode/decode headers
+-------
+Decoding the JWT headers without verifying the JWT first is NOT recommended, and is not supported by
+this library. This is because without verifying the JWT, the header values could have been tampered with.
+Any value pulled from an unverified header should be treated as if it could be any string sent in from an
+attacker. If this is something you still want to do in your application for whatever reason, it's possible to
+decode the header values manually simply by calling `json_decode` and `base64_decode` on the JWT
+header part:
+```php
+use Firebase\JWT\JWT;
+
+$key = 'example_key';
+$payload = [
+ 'iss' => 'http://example.org',
+ 'aud' => 'http://example.com',
+ 'iat' => 1356999524,
+ 'nbf' => 1357000000
+];
+
+$headers = [
+ 'x-forwarded-for' => 'www.google.com'
+];
+
+// Encode headers in the JWT string
+$jwt = JWT::encode($payload, $key, 'HS256', null, $headers);
+
+// Decode headers from the JWT string WITHOUT validation
+// **IMPORTANT**: This operation is vulnerable to attacks, as the JWT has not yet been verified.
+// These headers could be any value sent by an attacker.
+list($headersB64, $payloadB64, $sig) = explode('.', $jwt);
+$decoded = json_decode(base64_decode($headersB64), true);
+
+print_r($decoded);
+```
+Example with RS256 (openssl)
+----------------------------
+```php
+use Firebase\JWT\JWT;
+use Firebase\JWT\Key;
+
+$privateKey = << 'example.org',
+ 'aud' => 'example.com',
+ 'iat' => 1356999524,
+ 'nbf' => 1357000000
+];
+
+$jwt = JWT::encode($payload, $privateKey, 'RS256');
+echo "Encode:\n" . print_r($jwt, true) . "\n";
+
+$decoded = JWT::decode($jwt, new Key($publicKey, 'RS256'));
+
+/*
+ NOTE: This will now be an object instead of an associative array. To get
+ an associative array, you will need to cast it as such:
+*/
+
+$decoded_array = (array) $decoded;
+echo "Decode:\n" . print_r($decoded_array, true) . "\n";
+```
+
+Example with a passphrase
+-------------------------
+
+```php
+use Firebase\JWT\JWT;
+use Firebase\JWT\Key;
+
+// Your passphrase
+$passphrase = '[YOUR_PASSPHRASE]';
+
+// Your private key file with passphrase
+// Can be generated with "ssh-keygen -t rsa -m pem"
+$privateKeyFile = '/path/to/key-with-passphrase.pem';
+
+// Create a private key of type "resource"
+$privateKey = openssl_pkey_get_private(
+ file_get_contents($privateKeyFile),
+ $passphrase
+);
+
+$payload = [
+ 'iss' => 'example.org',
+ 'aud' => 'example.com',
+ 'iat' => 1356999524,
+ 'nbf' => 1357000000
+];
+
+$jwt = JWT::encode($payload, $privateKey, 'RS256');
+echo "Encode:\n" . print_r($jwt, true) . "\n";
+
+// Get public key from the private key, or pull from from a file.
+$publicKey = openssl_pkey_get_details($privateKey)['key'];
+
+$decoded = JWT::decode($jwt, new Key($publicKey, 'RS256'));
+echo "Decode:\n" . print_r((array) $decoded, true) . "\n";
+```
+
+Example with EdDSA (libsodium and Ed25519 signature)
+----------------------------
+```php
+use Firebase\JWT\JWT;
+use Firebase\JWT\Key;
+
+// Public and private keys are expected to be Base64 encoded. The last
+// non-empty line is used so that keys can be generated with
+// sodium_crypto_sign_keypair(). The secret keys generated by other tools may
+// need to be adjusted to match the input expected by libsodium.
+
+$keyPair = sodium_crypto_sign_keypair();
+
+$privateKey = base64_encode(sodium_crypto_sign_secretkey($keyPair));
+
+$publicKey = base64_encode(sodium_crypto_sign_publickey($keyPair));
+
+$payload = [
+ 'iss' => 'example.org',
+ 'aud' => 'example.com',
+ 'iat' => 1356999524,
+ 'nbf' => 1357000000
+];
+
+$jwt = JWT::encode($payload, $privateKey, 'EdDSA');
+echo "Encode:\n" . print_r($jwt, true) . "\n";
+
+$decoded = JWT::decode($jwt, new Key($publicKey, 'EdDSA'));
+echo "Decode:\n" . print_r((array) $decoded, true) . "\n";
+````
+
+Example with multiple keys
+--------------------------
+```php
+use Firebase\JWT\JWT;
+use Firebase\JWT\Key;
+
+// Example RSA keys from previous example
+// $privateKey1 = '...';
+// $publicKey1 = '...';
+
+// Example EdDSA keys from previous example
+// $privateKey2 = '...';
+// $publicKey2 = '...';
+
+$payload = [
+ 'iss' => 'example.org',
+ 'aud' => 'example.com',
+ 'iat' => 1356999524,
+ 'nbf' => 1357000000
+];
+
+$jwt1 = JWT::encode($payload, $privateKey1, 'RS256', 'kid1');
+$jwt2 = JWT::encode($payload, $privateKey2, 'EdDSA', 'kid2');
+echo "Encode 1:\n" . print_r($jwt1, true) . "\n";
+echo "Encode 2:\n" . print_r($jwt2, true) . "\n";
+
+$keys = [
+ 'kid1' => new Key($publicKey1, 'RS256'),
+ 'kid2' => new Key($publicKey2, 'EdDSA'),
+];
+
+$decoded1 = JWT::decode($jwt1, $keys);
+$decoded2 = JWT::decode($jwt2, $keys);
+
+echo "Decode 1:\n" . print_r((array) $decoded1, true) . "\n";
+echo "Decode 2:\n" . print_r((array) $decoded2, true) . "\n";
+```
+
+Using JWKs
+----------
+
+```php
+use Firebase\JWT\JWK;
+use Firebase\JWT\JWT;
+
+// Set of keys. The "keys" key is required. For example, the JSON response to
+// this endpoint: https://www.gstatic.com/iap/verify/public_key-jwk
+$jwks = ['keys' => []];
+
+// JWK::parseKeySet($jwks) returns an associative array of **kid** to Firebase\JWT\Key
+// objects. Pass this as the second parameter to JWT::decode.
+JWT::decode($jwt, JWK::parseKeySet($jwks));
+```
+
+Using Cached Key Sets
+---------------------
+
+The `CachedKeySet` class can be used to fetch and cache JWKS (JSON Web Key Sets) from a public URI.
+This has the following advantages:
+
+1. The results are cached for performance.
+2. If an unrecognized key is requested, the cache is refreshed, to accomodate for key rotation.
+3. If rate limiting is enabled, the JWKS URI will not make more than 10 requests a second.
+
+```php
+use Firebase\JWT\CachedKeySet;
+use Firebase\JWT\JWT;
+
+// The URI for the JWKS you wish to cache the results from
+$jwksUri = 'https://www.gstatic.com/iap/verify/public_key-jwk';
+
+// Create an HTTP client (can be any PSR-7 compatible HTTP client)
+$httpClient = new GuzzleHttp\Client();
+
+// Create an HTTP request factory (can be any PSR-17 compatible HTTP request factory)
+$httpFactory = new GuzzleHttp\Psr\HttpFactory();
+
+// Create a cache item pool (can be any PSR-6 compatible cache item pool)
+$cacheItemPool = Phpfastcache\CacheManager::getInstance('files');
+
+$keySet = new CachedKeySet(
+ $jwksUri,
+ $httpClient,
+ $httpFactory,
+ $cacheItemPool,
+ null, // $expiresAfter int seconds to set the JWKS to expire
+ true // $rateLimit true to enable rate limit of 10 RPS on lookup of invalid keys
+);
+
+$jwt = 'eyJhbGci...'; // Some JWT signed by a key from the $jwkUri above
+$decoded = JWT::decode($jwt, $keySet);
+```
+
+Miscellaneous
+-------------
+
+#### Exception Handling
+
+When a call to `JWT::decode` is invalid, it will throw one of the following exceptions:
+
+```php
+use Firebase\JWT\JWT;
+use Firebase\JWT\SignatureInvalidException;
+use Firebase\JWT\BeforeValidException;
+use Firebase\JWT\ExpiredException;
+use DomainException;
+use InvalidArgumentException;
+use UnexpectedValueException;
+
+try {
+ $decoded = JWT::decode($jwt, $keys);
+} catch (InvalidArgumentException $e) {
+ // provided key/key-array is empty or malformed.
+} catch (DomainException $e) {
+ // provided algorithm is unsupported OR
+ // provided key is invalid OR
+ // unknown error thrown in openSSL or libsodium OR
+ // libsodium is required but not available.
+} catch (SignatureInvalidException $e) {
+ // provided JWT signature verification failed.
+} catch (BeforeValidException $e) {
+ // provided JWT is trying to be used before "nbf" claim OR
+ // provided JWT is trying to be used before "iat" claim.
+} catch (ExpiredException $e) {
+ // provided JWT is trying to be used after "exp" claim.
+} catch (UnexpectedValueException $e) {
+ // provided JWT is malformed OR
+ // provided JWT is missing an algorithm / using an unsupported algorithm OR
+ // provided JWT algorithm does not match provided key OR
+ // provided key ID in key/key-array is empty or invalid.
+}
+```
+
+All exceptions in the `Firebase\JWT` namespace extend `UnexpectedValueException`, and can be simplified
+like this:
+
+```php
+use Firebase\JWT\JWT;
+use UnexpectedValueException;
+try {
+ $decoded = JWT::decode($jwt, $keys);
+} catch (LogicException $e) {
+ // errors having to do with environmental setup or malformed JWT Keys
+} catch (UnexpectedValueException $e) {
+ // errors having to do with JWT signature and claims
+}
+```
+
+#### Casting to array
+
+The return value of `JWT::decode` is the generic PHP object `stdClass`. If you'd like to handle with arrays
+instead, you can do the following:
+
+```php
+// return type is stdClass
+$decoded = JWT::decode($jwt, $keys);
+
+// cast to array
+$decoded = json_decode(json_encode($decoded), true);
+```
+
+Tests
+-----
+Run the tests using phpunit:
+
+```bash
+$ pear install PHPUnit
+$ phpunit --configuration phpunit.xml.dist
+PHPUnit 3.7.10 by Sebastian Bergmann.
+.....
+Time: 0 seconds, Memory: 2.50Mb
+OK (5 tests, 5 assertions)
+```
+
+New Lines in private keys
+-----
+
+If your private key contains `\n` characters, be sure to wrap it in double quotes `""`
+and not single quotes `''` in order to properly interpret the escaped characters.
+
+License
+-------
+[3-Clause BSD](http://opensource.org/licenses/BSD-3-Clause).
diff --git a/vendor/firebase/php-jwt/composer.json b/vendor/firebase/php-jwt/composer.json
new file mode 100644
index 0000000..816cfd0
--- /dev/null
+++ b/vendor/firebase/php-jwt/composer.json
@@ -0,0 +1,42 @@
+{
+ "name": "firebase/php-jwt",
+ "description": "A simple library to encode and decode JSON Web Tokens (JWT) in PHP. Should conform to the current spec.",
+ "homepage": "https://github.com/firebase/php-jwt",
+ "keywords": [
+ "php",
+ "jwt"
+ ],
+ "authors": [
+ {
+ "name": "Neuman Vong",
+ "email": "neuman+pear@twilio.com",
+ "role": "Developer"
+ },
+ {
+ "name": "Anant Narayanan",
+ "email": "anant@php.net",
+ "role": "Developer"
+ }
+ ],
+ "license": "BSD-3-Clause",
+ "require": {
+ "php": "^8.0"
+ },
+ "suggest": {
+ "paragonie/sodium_compat": "Support EdDSA (Ed25519) signatures when libsodium is not present",
+ "ext-sodium": "Support EdDSA (Ed25519) signatures"
+ },
+ "autoload": {
+ "psr-4": {
+ "Firebase\\JWT\\": "src"
+ }
+ },
+ "require-dev": {
+ "guzzlehttp/guzzle": "^7.4",
+ "phpspec/prophecy-phpunit": "^2.0",
+ "phpunit/phpunit": "^9.5",
+ "psr/cache": "^2.0||^3.0",
+ "psr/http-client": "^1.0",
+ "psr/http-factory": "^1.0"
+ }
+}
diff --git a/vendor/firebase/php-jwt/src/BeforeValidException.php b/vendor/firebase/php-jwt/src/BeforeValidException.php
new file mode 100644
index 0000000..595164b
--- /dev/null
+++ b/vendor/firebase/php-jwt/src/BeforeValidException.php
@@ -0,0 +1,18 @@
+payload = $payload;
+ }
+
+ public function getPayload(): object
+ {
+ return $this->payload;
+ }
+}
diff --git a/vendor/firebase/php-jwt/src/CachedKeySet.php b/vendor/firebase/php-jwt/src/CachedKeySet.php
new file mode 100644
index 0000000..8e8e8d6
--- /dev/null
+++ b/vendor/firebase/php-jwt/src/CachedKeySet.php
@@ -0,0 +1,274 @@
+
+ */
+class CachedKeySet implements ArrayAccess
+{
+ /**
+ * @var string
+ */
+ private $jwksUri;
+ /**
+ * @var ClientInterface
+ */
+ private $httpClient;
+ /**
+ * @var RequestFactoryInterface
+ */
+ private $httpFactory;
+ /**
+ * @var CacheItemPoolInterface
+ */
+ private $cache;
+ /**
+ * @var ?int
+ */
+ private $expiresAfter;
+ /**
+ * @var ?CacheItemInterface
+ */
+ private $cacheItem;
+ /**
+ * @var array>
+ */
+ private $keySet;
+ /**
+ * @var string
+ */
+ private $cacheKey;
+ /**
+ * @var string
+ */
+ private $cacheKeyPrefix = 'jwks';
+ /**
+ * @var int
+ */
+ private $maxKeyLength = 64;
+ /**
+ * @var bool
+ */
+ private $rateLimit;
+ /**
+ * @var string
+ */
+ private $rateLimitCacheKey;
+ /**
+ * @var int
+ */
+ private $maxCallsPerMinute = 10;
+ /**
+ * @var string|null
+ */
+ private $defaultAlg;
+
+ public function __construct(
+ string $jwksUri,
+ ClientInterface $httpClient,
+ RequestFactoryInterface $httpFactory,
+ CacheItemPoolInterface $cache,
+ ?int $expiresAfter = null,
+ bool $rateLimit = false,
+ ?string $defaultAlg = null
+ ) {
+ $this->jwksUri = $jwksUri;
+ $this->httpClient = $httpClient;
+ $this->httpFactory = $httpFactory;
+ $this->cache = $cache;
+ $this->expiresAfter = $expiresAfter;
+ $this->rateLimit = $rateLimit;
+ $this->defaultAlg = $defaultAlg;
+ $this->setCacheKeys();
+ }
+
+ /**
+ * @param string $keyId
+ * @return Key
+ */
+ public function offsetGet($keyId): Key
+ {
+ if (!$this->keyIdExists($keyId)) {
+ throw new OutOfBoundsException('Key ID not found');
+ }
+ return JWK::parseKey($this->keySet[$keyId], $this->defaultAlg);
+ }
+
+ /**
+ * @param string $keyId
+ * @return bool
+ */
+ public function offsetExists($keyId): bool
+ {
+ return $this->keyIdExists($keyId);
+ }
+
+ /**
+ * @param string $offset
+ * @param Key $value
+ */
+ public function offsetSet($offset, $value): void
+ {
+ throw new LogicException('Method not implemented');
+ }
+
+ /**
+ * @param string $offset
+ */
+ public function offsetUnset($offset): void
+ {
+ throw new LogicException('Method not implemented');
+ }
+
+ /**
+ * @return array
+ */
+ private function formatJwksForCache(string $jwks): array
+ {
+ $jwks = json_decode($jwks, true);
+
+ if (!isset($jwks['keys'])) {
+ throw new UnexpectedValueException('"keys" member must exist in the JWK Set');
+ }
+
+ if (empty($jwks['keys'])) {
+ throw new InvalidArgumentException('JWK Set did not contain any keys');
+ }
+
+ $keys = [];
+ foreach ($jwks['keys'] as $k => $v) {
+ $kid = isset($v['kid']) ? $v['kid'] : $k;
+ $keys[(string) $kid] = $v;
+ }
+
+ return $keys;
+ }
+
+ private function keyIdExists(string $keyId): bool
+ {
+ if (null === $this->keySet) {
+ $item = $this->getCacheItem();
+ // Try to load keys from cache
+ if ($item->isHit()) {
+ // item found! retrieve it
+ $this->keySet = $item->get();
+ // If the cached item is a string, the JWKS response was cached (previous behavior).
+ // Parse this into expected format array instead.
+ if (\is_string($this->keySet)) {
+ $this->keySet = $this->formatJwksForCache($this->keySet);
+ }
+ }
+ }
+
+ if (!isset($this->keySet[$keyId])) {
+ if ($this->rateLimitExceeded()) {
+ return false;
+ }
+ $request = $this->httpFactory->createRequest('GET', $this->jwksUri);
+ $jwksResponse = $this->httpClient->sendRequest($request);
+ if ($jwksResponse->getStatusCode() !== 200) {
+ throw new UnexpectedValueException(
+ \sprintf('HTTP Error: %d %s for URI "%s"',
+ $jwksResponse->getStatusCode(),
+ $jwksResponse->getReasonPhrase(),
+ $this->jwksUri,
+ ),
+ $jwksResponse->getStatusCode()
+ );
+ }
+ $this->keySet = $this->formatJwksForCache((string) $jwksResponse->getBody());
+
+ if (!isset($this->keySet[$keyId])) {
+ return false;
+ }
+
+ $item = $this->getCacheItem();
+ $item->set($this->keySet);
+ if ($this->expiresAfter) {
+ $item->expiresAfter($this->expiresAfter);
+ }
+ $this->cache->save($item);
+ }
+
+ return true;
+ }
+
+ private function rateLimitExceeded(): bool
+ {
+ if (!$this->rateLimit) {
+ return false;
+ }
+
+ $cacheItem = $this->cache->getItem($this->rateLimitCacheKey);
+
+ $cacheItemData = [];
+ if ($cacheItem->isHit() && \is_array($data = $cacheItem->get())) {
+ $cacheItemData = $data;
+ }
+
+ $callsPerMinute = $cacheItemData['callsPerMinute'] ?? 0;
+ $expiry = $cacheItemData['expiry'] ?? new \DateTime('+60 seconds', new \DateTimeZone('UTC'));
+
+ if (++$callsPerMinute > $this->maxCallsPerMinute) {
+ return true;
+ }
+
+ $cacheItem->set(['expiry' => $expiry, 'callsPerMinute' => $callsPerMinute]);
+ $cacheItem->expiresAt($expiry);
+ $this->cache->save($cacheItem);
+ return false;
+ }
+
+ private function getCacheItem(): CacheItemInterface
+ {
+ if (\is_null($this->cacheItem)) {
+ $this->cacheItem = $this->cache->getItem($this->cacheKey);
+ }
+
+ return $this->cacheItem;
+ }
+
+ private function setCacheKeys(): void
+ {
+ if (empty($this->jwksUri)) {
+ throw new RuntimeException('JWKS URI is empty');
+ }
+
+ // ensure we do not have illegal characters
+ $key = preg_replace('|[^a-zA-Z0-9_\.!]|', '', $this->jwksUri);
+
+ // add prefix
+ $key = $this->cacheKeyPrefix . $key;
+
+ // Hash keys if they exceed $maxKeyLength of 64
+ if (\strlen($key) > $this->maxKeyLength) {
+ $key = substr(hash('sha256', $key), 0, $this->maxKeyLength);
+ }
+
+ $this->cacheKey = $key;
+
+ if ($this->rateLimit) {
+ // add prefix
+ $rateLimitKey = $this->cacheKeyPrefix . 'ratelimit' . $key;
+
+ // Hash keys if they exceed $maxKeyLength of 64
+ if (\strlen($rateLimitKey) > $this->maxKeyLength) {
+ $rateLimitKey = substr(hash('sha256', $rateLimitKey), 0, $this->maxKeyLength);
+ }
+
+ $this->rateLimitCacheKey = $rateLimitKey;
+ }
+ }
+}
diff --git a/vendor/firebase/php-jwt/src/ExpiredException.php b/vendor/firebase/php-jwt/src/ExpiredException.php
new file mode 100644
index 0000000..12fef09
--- /dev/null
+++ b/vendor/firebase/php-jwt/src/ExpiredException.php
@@ -0,0 +1,18 @@
+payload = $payload;
+ }
+
+ public function getPayload(): object
+ {
+ return $this->payload;
+ }
+}
diff --git a/vendor/firebase/php-jwt/src/JWK.php b/vendor/firebase/php-jwt/src/JWK.php
new file mode 100644
index 0000000..405dcc4
--- /dev/null
+++ b/vendor/firebase/php-jwt/src/JWK.php
@@ -0,0 +1,355 @@
+
+ * @license http://opensource.org/licenses/BSD-3-Clause 3-clause BSD
+ * @link https://github.com/firebase/php-jwt
+ */
+class JWK
+{
+ private const OID = '1.2.840.10045.2.1';
+ private const ASN1_OBJECT_IDENTIFIER = 0x06;
+ private const ASN1_SEQUENCE = 0x10; // also defined in JWT
+ private const ASN1_BIT_STRING = 0x03;
+ private const EC_CURVES = [
+ 'P-256' => '1.2.840.10045.3.1.7', // Len: 64
+ 'secp256k1' => '1.3.132.0.10', // Len: 64
+ 'P-384' => '1.3.132.0.34', // Len: 96
+ // 'P-521' => '1.3.132.0.35', // Len: 132 (not supported)
+ ];
+
+ // For keys with "kty" equal to "OKP" (Octet Key Pair), the "crv" parameter must contain the key subtype.
+ // This library supports the following subtypes:
+ private const OKP_SUBTYPES = [
+ 'Ed25519' => true, // RFC 8037
+ ];
+
+ /**
+ * Parse a set of JWK keys
+ *
+ * @param array $jwks The JSON Web Key Set as an associative array
+ * @param string $defaultAlg The algorithm for the Key object if "alg" is not set in the
+ * JSON Web Key Set
+ *
+ * @return array An associative array of key IDs (kid) to Key objects
+ *
+ * @throws InvalidArgumentException Provided JWK Set is empty
+ * @throws UnexpectedValueException Provided JWK Set was invalid
+ * @throws DomainException OpenSSL failure
+ *
+ * @uses parseKey
+ */
+ public static function parseKeySet(array $jwks, ?string $defaultAlg = null): array
+ {
+ $keys = [];
+
+ if (!isset($jwks['keys'])) {
+ throw new UnexpectedValueException('"keys" member must exist in the JWK Set');
+ }
+
+ if (empty($jwks['keys'])) {
+ throw new InvalidArgumentException('JWK Set did not contain any keys');
+ }
+
+ foreach ($jwks['keys'] as $k => $v) {
+ $kid = isset($v['kid']) ? $v['kid'] : $k;
+ if ($key = self::parseKey($v, $defaultAlg)) {
+ $keys[(string) $kid] = $key;
+ }
+ }
+
+ if (0 === \count($keys)) {
+ throw new UnexpectedValueException('No supported algorithms found in JWK Set');
+ }
+
+ return $keys;
+ }
+
+ /**
+ * Parse a JWK key
+ *
+ * @param array $jwk An individual JWK
+ * @param string $defaultAlg The algorithm for the Key object if "alg" is not set in the
+ * JSON Web Key Set
+ *
+ * @return Key The key object for the JWK
+ *
+ * @throws InvalidArgumentException Provided JWK is empty
+ * @throws UnexpectedValueException Provided JWK was invalid
+ * @throws DomainException OpenSSL failure
+ *
+ * @uses createPemFromModulusAndExponent
+ */
+ public static function parseKey(array $jwk, ?string $defaultAlg = null): ?Key
+ {
+ if (empty($jwk)) {
+ throw new InvalidArgumentException('JWK must not be empty');
+ }
+
+ if (!isset($jwk['kty'])) {
+ throw new UnexpectedValueException('JWK must contain a "kty" parameter');
+ }
+
+ if (!isset($jwk['alg'])) {
+ if (\is_null($defaultAlg)) {
+ // The "alg" parameter is optional in a KTY, but an algorithm is required
+ // for parsing in this library. Use the $defaultAlg parameter when parsing the
+ // key set in order to prevent this error.
+ // @see https://datatracker.ietf.org/doc/html/rfc7517#section-4.4
+ throw new UnexpectedValueException('JWK must contain an "alg" parameter');
+ }
+ $jwk['alg'] = $defaultAlg;
+ }
+
+ switch ($jwk['kty']) {
+ case 'RSA':
+ if (!empty($jwk['d'])) {
+ throw new UnexpectedValueException('RSA private keys are not supported');
+ }
+ if (!isset($jwk['n']) || !isset($jwk['e'])) {
+ throw new UnexpectedValueException('RSA keys must contain values for both "n" and "e"');
+ }
+
+ $pem = self::createPemFromModulusAndExponent($jwk['n'], $jwk['e']);
+ $publicKey = \openssl_pkey_get_public($pem);
+ if (false === $publicKey) {
+ throw new DomainException(
+ 'OpenSSL error: ' . \openssl_error_string()
+ );
+ }
+ return new Key($publicKey, $jwk['alg']);
+ case 'EC':
+ if (isset($jwk['d'])) {
+ // The key is actually a private key
+ throw new UnexpectedValueException('Key data must be for a public key');
+ }
+
+ if (empty($jwk['crv'])) {
+ throw new UnexpectedValueException('crv not set');
+ }
+
+ if (!isset(self::EC_CURVES[$jwk['crv']])) {
+ throw new DomainException('Unrecognised or unsupported EC curve');
+ }
+
+ if (empty($jwk['x']) || empty($jwk['y'])) {
+ throw new UnexpectedValueException('x and y not set');
+ }
+
+ $publicKey = self::createPemFromCrvAndXYCoordinates($jwk['crv'], $jwk['x'], $jwk['y']);
+ return new Key($publicKey, $jwk['alg']);
+ case 'OKP':
+ if (isset($jwk['d'])) {
+ // The key is actually a private key
+ throw new UnexpectedValueException('Key data must be for a public key');
+ }
+
+ if (!isset($jwk['crv'])) {
+ throw new UnexpectedValueException('crv not set');
+ }
+
+ if (empty(self::OKP_SUBTYPES[$jwk['crv']])) {
+ throw new DomainException('Unrecognised or unsupported OKP key subtype');
+ }
+
+ if (empty($jwk['x'])) {
+ throw new UnexpectedValueException('x not set');
+ }
+
+ // This library works internally with EdDSA keys (Ed25519) encoded in standard base64.
+ $publicKey = JWT::convertBase64urlToBase64($jwk['x']);
+ return new Key($publicKey, $jwk['alg']);
+ case 'oct':
+ if (!isset($jwk['k'])) {
+ throw new UnexpectedValueException('k not set');
+ }
+
+ return new Key(JWT::urlsafeB64Decode($jwk['k']), $jwk['alg']);
+ default:
+ break;
+ }
+
+ return null;
+ }
+
+ /**
+ * Converts the EC JWK values to pem format.
+ *
+ * @param string $crv The EC curve (only P-256 & P-384 is supported)
+ * @param string $x The EC x-coordinate
+ * @param string $y The EC y-coordinate
+ *
+ * @return string
+ */
+ private static function createPemFromCrvAndXYCoordinates(string $crv, string $x, string $y): string
+ {
+ $pem =
+ self::encodeDER(
+ self::ASN1_SEQUENCE,
+ self::encodeDER(
+ self::ASN1_SEQUENCE,
+ self::encodeDER(
+ self::ASN1_OBJECT_IDENTIFIER,
+ self::encodeOID(self::OID)
+ )
+ . self::encodeDER(
+ self::ASN1_OBJECT_IDENTIFIER,
+ self::encodeOID(self::EC_CURVES[$crv])
+ )
+ ) .
+ self::encodeDER(
+ self::ASN1_BIT_STRING,
+ \chr(0x00) . \chr(0x04)
+ . JWT::urlsafeB64Decode($x)
+ . JWT::urlsafeB64Decode($y)
+ )
+ );
+
+ return \sprintf(
+ "-----BEGIN PUBLIC KEY-----\n%s\n-----END PUBLIC KEY-----\n",
+ wordwrap(base64_encode($pem), 64, "\n", true)
+ );
+ }
+
+ /**
+ * Create a public key represented in PEM format from RSA modulus and exponent information
+ *
+ * @param string $n The RSA modulus encoded in Base64
+ * @param string $e The RSA exponent encoded in Base64
+ *
+ * @return string The RSA public key represented in PEM format
+ *
+ * @uses encodeLength
+ */
+ private static function createPemFromModulusAndExponent(
+ string $n,
+ string $e
+ ): string {
+ $mod = JWT::urlsafeB64Decode($n);
+ $exp = JWT::urlsafeB64Decode($e);
+
+ $modulus = \pack('Ca*a*', 2, self::encodeLength(\strlen($mod)), $mod);
+ $publicExponent = \pack('Ca*a*', 2, self::encodeLength(\strlen($exp)), $exp);
+
+ $rsaPublicKey = \pack(
+ 'Ca*a*a*',
+ 48,
+ self::encodeLength(\strlen($modulus) + \strlen($publicExponent)),
+ $modulus,
+ $publicExponent
+ );
+
+ // sequence(oid(1.2.840.113549.1.1.1), null)) = rsaEncryption.
+ $rsaOID = \pack('H*', '300d06092a864886f70d0101010500'); // hex version of MA0GCSqGSIb3DQEBAQUA
+ $rsaPublicKey = \chr(0) . $rsaPublicKey;
+ $rsaPublicKey = \chr(3) . self::encodeLength(\strlen($rsaPublicKey)) . $rsaPublicKey;
+
+ $rsaPublicKey = \pack(
+ 'Ca*a*',
+ 48,
+ self::encodeLength(\strlen($rsaOID . $rsaPublicKey)),
+ $rsaOID . $rsaPublicKey
+ );
+
+ return "-----BEGIN PUBLIC KEY-----\r\n" .
+ \chunk_split(\base64_encode($rsaPublicKey), 64) .
+ '-----END PUBLIC KEY-----';
+ }
+
+ /**
+ * DER-encode the length
+ *
+ * DER supports lengths up to (2**8)**127, however, we'll only support lengths up to (2**8)**4. See
+ * {@link http://itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf#p=13 X.690 paragraph 8.1.3} for more information.
+ *
+ * @param int $length
+ * @return string
+ */
+ private static function encodeLength(int $length): string
+ {
+ if ($length <= 0x7F) {
+ return \chr($length);
+ }
+
+ $temp = \ltrim(\pack('N', $length), \chr(0));
+
+ return \pack('Ca*', 0x80 | \strlen($temp), $temp);
+ }
+
+ /**
+ * Encodes a value into a DER object.
+ * Also defined in Firebase\JWT\JWT
+ *
+ * @param int $type DER tag
+ * @param string $value the value to encode
+ * @return string the encoded object
+ */
+ private static function encodeDER(int $type, string $value): string
+ {
+ $tag_header = 0;
+ if ($type === self::ASN1_SEQUENCE) {
+ $tag_header |= 0x20;
+ }
+
+ // Type
+ $der = \chr($tag_header | $type);
+
+ // Length
+ $der .= \chr(\strlen($value));
+
+ return $der . $value;
+ }
+
+ /**
+ * Encodes a string into a DER-encoded OID.
+ *
+ * @param string $oid the OID string
+ * @return string the binary DER-encoded OID
+ */
+ private static function encodeOID(string $oid): string
+ {
+ $octets = explode('.', $oid);
+
+ // Get the first octet
+ $first = (int) array_shift($octets);
+ $second = (int) array_shift($octets);
+ $oid = \chr($first * 40 + $second);
+
+ // Iterate over subsequent octets
+ foreach ($octets as $octet) {
+ if ($octet == 0) {
+ $oid .= \chr(0x00);
+ continue;
+ }
+ $bin = '';
+
+ while ($octet) {
+ $bin .= \chr(0x80 | ($octet & 0x7f));
+ $octet >>= 7;
+ }
+ $bin[0] = $bin[0] & \chr(0x7f);
+
+ // Convert to big endian if necessary
+ if (pack('V', 65534) == pack('L', 65534)) {
+ $oid .= strrev($bin);
+ } else {
+ $oid .= $bin;
+ }
+ }
+
+ return $oid;
+ }
+}
diff --git a/vendor/firebase/php-jwt/src/JWT.php b/vendor/firebase/php-jwt/src/JWT.php
new file mode 100644
index 0000000..833a415
--- /dev/null
+++ b/vendor/firebase/php-jwt/src/JWT.php
@@ -0,0 +1,667 @@
+
+ * @author Anant Narayanan
+ * @license http://opensource.org/licenses/BSD-3-Clause 3-clause BSD
+ * @link https://github.com/firebase/php-jwt
+ */
+class JWT
+{
+ private const ASN1_INTEGER = 0x02;
+ private const ASN1_SEQUENCE = 0x10;
+ private const ASN1_BIT_STRING = 0x03;
+
+ /**
+ * When checking nbf, iat or expiration times,
+ * we want to provide some extra leeway time to
+ * account for clock skew.
+ *
+ * @var int
+ */
+ public static $leeway = 0;
+
+ /**
+ * Allow the current timestamp to be specified.
+ * Useful for fixing a value within unit testing.
+ * Will default to PHP time() value if null.
+ *
+ * @var ?int
+ */
+ public static $timestamp = null;
+
+ /**
+ * @var array
+ */
+ public static $supported_algs = [
+ 'ES384' => ['openssl', 'SHA384'],
+ 'ES256' => ['openssl', 'SHA256'],
+ 'ES256K' => ['openssl', 'SHA256'],
+ 'HS256' => ['hash_hmac', 'SHA256'],
+ 'HS384' => ['hash_hmac', 'SHA384'],
+ 'HS512' => ['hash_hmac', 'SHA512'],
+ 'RS256' => ['openssl', 'SHA256'],
+ 'RS384' => ['openssl', 'SHA384'],
+ 'RS512' => ['openssl', 'SHA512'],
+ 'EdDSA' => ['sodium_crypto', 'EdDSA'],
+ ];
+
+ /**
+ * Decodes a JWT string into a PHP object.
+ *
+ * @param string $jwt The JWT
+ * @param Key|ArrayAccess|array $keyOrKeyArray The Key or associative array of key IDs
+ * (kid) to Key objects.
+ * If the algorithm used is asymmetric, this is
+ * the public key.
+ * Each Key object contains an algorithm and
+ * matching key.
+ * Supported algorithms are 'ES384','ES256',
+ * 'HS256', 'HS384', 'HS512', 'RS256', 'RS384'
+ * and 'RS512'.
+ * @param stdClass $headers Optional. Populates stdClass with headers.
+ *
+ * @return stdClass The JWT's payload as a PHP object
+ *
+ * @throws InvalidArgumentException Provided key/key-array was empty or malformed
+ * @throws DomainException Provided JWT is malformed
+ * @throws UnexpectedValueException Provided JWT was invalid
+ * @throws SignatureInvalidException Provided JWT was invalid because the signature verification failed
+ * @throws BeforeValidException Provided JWT is trying to be used before it's eligible as defined by 'nbf'
+ * @throws BeforeValidException Provided JWT is trying to be used before it's been created as defined by 'iat'
+ * @throws ExpiredException Provided JWT has since expired, as defined by the 'exp' claim
+ *
+ * @uses jsonDecode
+ * @uses urlsafeB64Decode
+ */
+ public static function decode(
+ string $jwt,
+ $keyOrKeyArray,
+ ?stdClass &$headers = null
+ ): stdClass {
+ // Validate JWT
+ $timestamp = \is_null(static::$timestamp) ? \time() : static::$timestamp;
+
+ if (empty($keyOrKeyArray)) {
+ throw new InvalidArgumentException('Key may not be empty');
+ }
+ $tks = \explode('.', $jwt);
+ if (\count($tks) !== 3) {
+ throw new UnexpectedValueException('Wrong number of segments');
+ }
+ list($headb64, $bodyb64, $cryptob64) = $tks;
+ $headerRaw = static::urlsafeB64Decode($headb64);
+ if (null === ($header = static::jsonDecode($headerRaw))) {
+ throw new UnexpectedValueException('Invalid header encoding');
+ }
+ if ($headers !== null) {
+ $headers = $header;
+ }
+ $payloadRaw = static::urlsafeB64Decode($bodyb64);
+ if (null === ($payload = static::jsonDecode($payloadRaw))) {
+ throw new UnexpectedValueException('Invalid claims encoding');
+ }
+ if (\is_array($payload)) {
+ // prevent PHP Fatal Error in edge-cases when payload is empty array
+ $payload = (object) $payload;
+ }
+ if (!$payload instanceof stdClass) {
+ throw new UnexpectedValueException('Payload must be a JSON object');
+ }
+ $sig = static::urlsafeB64Decode($cryptob64);
+ if (empty($header->alg)) {
+ throw new UnexpectedValueException('Empty algorithm');
+ }
+ if (empty(static::$supported_algs[$header->alg])) {
+ throw new UnexpectedValueException('Algorithm not supported');
+ }
+
+ $key = self::getKey($keyOrKeyArray, property_exists($header, 'kid') ? $header->kid : null);
+
+ // Check the algorithm
+ if (!self::constantTimeEquals($key->getAlgorithm(), $header->alg)) {
+ // See issue #351
+ throw new UnexpectedValueException('Incorrect key for this algorithm');
+ }
+ if (\in_array($header->alg, ['ES256', 'ES256K', 'ES384'], true)) {
+ // OpenSSL expects an ASN.1 DER sequence for ES256/ES256K/ES384 signatures
+ $sig = self::signatureToDER($sig);
+ }
+ if (!self::verify("{$headb64}.{$bodyb64}", $sig, $key->getKeyMaterial(), $header->alg)) {
+ throw new SignatureInvalidException('Signature verification failed');
+ }
+
+ // Check the nbf if it is defined. This is the time that the
+ // token can actually be used. If it's not yet that time, abort.
+ if (isset($payload->nbf) && floor($payload->nbf) > ($timestamp + static::$leeway)) {
+ $ex = new BeforeValidException(
+ 'Cannot handle token with nbf prior to ' . \date(DateTime::ISO8601, (int) floor($payload->nbf))
+ );
+ $ex->setPayload($payload);
+ throw $ex;
+ }
+
+ // Check that this token has been created before 'now'. This prevents
+ // using tokens that have been created for later use (and haven't
+ // correctly used the nbf claim).
+ if (!isset($payload->nbf) && isset($payload->iat) && floor($payload->iat) > ($timestamp + static::$leeway)) {
+ $ex = new BeforeValidException(
+ 'Cannot handle token with iat prior to ' . \date(DateTime::ISO8601, (int) floor($payload->iat))
+ );
+ $ex->setPayload($payload);
+ throw $ex;
+ }
+
+ // Check if this token has expired.
+ if (isset($payload->exp) && ($timestamp - static::$leeway) >= $payload->exp) {
+ $ex = new ExpiredException('Expired token');
+ $ex->setPayload($payload);
+ throw $ex;
+ }
+
+ return $payload;
+ }
+
+ /**
+ * Converts and signs a PHP array into a JWT string.
+ *
+ * @param array $payload PHP array
+ * @param string|resource|OpenSSLAsymmetricKey|OpenSSLCertificate $key The secret key.
+ * @param string $alg Supported algorithms are 'ES384','ES256', 'ES256K', 'HS256',
+ * 'HS384', 'HS512', 'RS256', 'RS384', and 'RS512'
+ * @param string $keyId
+ * @param array $head An array with header elements to attach
+ *
+ * @return string A signed JWT
+ *
+ * @uses jsonEncode
+ * @uses urlsafeB64Encode
+ */
+ public static function encode(
+ array $payload,
+ $key,
+ string $alg,
+ ?string $keyId = null,
+ ?array $head = null
+ ): string {
+ $header = ['typ' => 'JWT'];
+ if (isset($head)) {
+ $header = \array_merge($header, $head);
+ }
+ $header['alg'] = $alg;
+ if ($keyId !== null) {
+ $header['kid'] = $keyId;
+ }
+ $segments = [];
+ $segments[] = static::urlsafeB64Encode((string) static::jsonEncode($header));
+ $segments[] = static::urlsafeB64Encode((string) static::jsonEncode($payload));
+ $signing_input = \implode('.', $segments);
+
+ $signature = static::sign($signing_input, $key, $alg);
+ $segments[] = static::urlsafeB64Encode($signature);
+
+ return \implode('.', $segments);
+ }
+
+ /**
+ * Sign a string with a given key and algorithm.
+ *
+ * @param string $msg The message to sign
+ * @param string|resource|OpenSSLAsymmetricKey|OpenSSLCertificate $key The secret key.
+ * @param string $alg Supported algorithms are 'EdDSA', 'ES384', 'ES256', 'ES256K', 'HS256',
+ * 'HS384', 'HS512', 'RS256', 'RS384', and 'RS512'
+ *
+ * @return string An encrypted message
+ *
+ * @throws DomainException Unsupported algorithm or bad key was specified
+ */
+ public static function sign(
+ string $msg,
+ $key,
+ string $alg
+ ): string {
+ if (empty(static::$supported_algs[$alg])) {
+ throw new DomainException('Algorithm not supported');
+ }
+ list($function, $algorithm) = static::$supported_algs[$alg];
+ switch ($function) {
+ case 'hash_hmac':
+ if (!\is_string($key)) {
+ throw new InvalidArgumentException('key must be a string when using hmac');
+ }
+ return \hash_hmac($algorithm, $msg, $key, true);
+ case 'openssl':
+ $signature = '';
+ if (!\is_resource($key) && !openssl_pkey_get_private($key)) {
+ throw new DomainException('OpenSSL unable to validate key');
+ }
+ $success = \openssl_sign($msg, $signature, $key, $algorithm); // @phpstan-ignore-line
+ if (!$success) {
+ throw new DomainException('OpenSSL unable to sign data');
+ }
+ if ($alg === 'ES256' || $alg === 'ES256K') {
+ $signature = self::signatureFromDER($signature, 256);
+ } elseif ($alg === 'ES384') {
+ $signature = self::signatureFromDER($signature, 384);
+ }
+ return $signature;
+ case 'sodium_crypto':
+ if (!\function_exists('sodium_crypto_sign_detached')) {
+ throw new DomainException('libsodium is not available');
+ }
+ if (!\is_string($key)) {
+ throw new InvalidArgumentException('key must be a string when using EdDSA');
+ }
+ try {
+ // The last non-empty line is used as the key.
+ $lines = array_filter(explode("\n", $key));
+ $key = base64_decode((string) end($lines));
+ if (\strlen($key) === 0) {
+ throw new DomainException('Key cannot be empty string');
+ }
+ return sodium_crypto_sign_detached($msg, $key);
+ } catch (Exception $e) {
+ throw new DomainException($e->getMessage(), 0, $e);
+ }
+ }
+
+ throw new DomainException('Algorithm not supported');
+ }
+
+ /**
+ * Verify a signature with the message, key and method. Not all methods
+ * are symmetric, so we must have a separate verify and sign method.
+ *
+ * @param string $msg The original message (header and body)
+ * @param string $signature The original signature
+ * @param string|resource|OpenSSLAsymmetricKey|OpenSSLCertificate $keyMaterial For Ed*, ES*, HS*, a string key works. for RS*, must be an instance of OpenSSLAsymmetricKey
+ * @param string $alg The algorithm
+ *
+ * @return bool
+ *
+ * @throws DomainException Invalid Algorithm, bad key, or OpenSSL failure
+ */
+ private static function verify(
+ string $msg,
+ string $signature,
+ $keyMaterial,
+ string $alg
+ ): bool {
+ if (empty(static::$supported_algs[$alg])) {
+ throw new DomainException('Algorithm not supported');
+ }
+
+ list($function, $algorithm) = static::$supported_algs[$alg];
+ switch ($function) {
+ case 'openssl':
+ $success = \openssl_verify($msg, $signature, $keyMaterial, $algorithm); // @phpstan-ignore-line
+ if ($success === 1) {
+ return true;
+ }
+ if ($success === 0) {
+ return false;
+ }
+ // returns 1 on success, 0 on failure, -1 on error.
+ throw new DomainException(
+ 'OpenSSL error: ' . \openssl_error_string()
+ );
+ case 'sodium_crypto':
+ if (!\function_exists('sodium_crypto_sign_verify_detached')) {
+ throw new DomainException('libsodium is not available');
+ }
+ if (!\is_string($keyMaterial)) {
+ throw new InvalidArgumentException('key must be a string when using EdDSA');
+ }
+ try {
+ // The last non-empty line is used as the key.
+ $lines = array_filter(explode("\n", $keyMaterial));
+ $key = base64_decode((string) end($lines));
+ if (\strlen($key) === 0) {
+ throw new DomainException('Key cannot be empty string');
+ }
+ if (\strlen($signature) === 0) {
+ throw new DomainException('Signature cannot be empty string');
+ }
+ return sodium_crypto_sign_verify_detached($signature, $msg, $key);
+ } catch (Exception $e) {
+ throw new DomainException($e->getMessage(), 0, $e);
+ }
+ case 'hash_hmac':
+ default:
+ if (!\is_string($keyMaterial)) {
+ throw new InvalidArgumentException('key must be a string when using hmac');
+ }
+ $hash = \hash_hmac($algorithm, $msg, $keyMaterial, true);
+ return self::constantTimeEquals($hash, $signature);
+ }
+ }
+
+ /**
+ * Decode a JSON string into a PHP object.
+ *
+ * @param string $input JSON string
+ *
+ * @return mixed The decoded JSON string
+ *
+ * @throws DomainException Provided string was invalid JSON
+ */
+ public static function jsonDecode(string $input)
+ {
+ $obj = \json_decode($input, false, 512, JSON_BIGINT_AS_STRING);
+
+ if ($errno = \json_last_error()) {
+ self::handleJsonError($errno);
+ } elseif ($obj === null && $input !== 'null') {
+ throw new DomainException('Null result with non-null input');
+ }
+ return $obj;
+ }
+
+ /**
+ * Encode a PHP array into a JSON string.
+ *
+ * @param array $input A PHP array
+ *
+ * @return string JSON representation of the PHP array
+ *
+ * @throws DomainException Provided object could not be encoded to valid JSON
+ */
+ public static function jsonEncode(array $input): string
+ {
+ $json = \json_encode($input, \JSON_UNESCAPED_SLASHES);
+ if ($errno = \json_last_error()) {
+ self::handleJsonError($errno);
+ } elseif ($json === 'null') {
+ throw new DomainException('Null result with non-null input');
+ }
+ if ($json === false) {
+ throw new DomainException('Provided object could not be encoded to valid JSON');
+ }
+ return $json;
+ }
+
+ /**
+ * Decode a string with URL-safe Base64.
+ *
+ * @param string $input A Base64 encoded string
+ *
+ * @return string A decoded string
+ *
+ * @throws InvalidArgumentException invalid base64 characters
+ */
+ public static function urlsafeB64Decode(string $input): string
+ {
+ return \base64_decode(self::convertBase64UrlToBase64($input));
+ }
+
+ /**
+ * Convert a string in the base64url (URL-safe Base64) encoding to standard base64.
+ *
+ * @param string $input A Base64 encoded string with URL-safe characters (-_ and no padding)
+ *
+ * @return string A Base64 encoded string with standard characters (+/) and padding (=), when
+ * needed.
+ *
+ * @see https://www.rfc-editor.org/rfc/rfc4648
+ */
+ public static function convertBase64UrlToBase64(string $input): string
+ {
+ $remainder = \strlen($input) % 4;
+ if ($remainder) {
+ $padlen = 4 - $remainder;
+ $input .= \str_repeat('=', $padlen);
+ }
+ return \strtr($input, '-_', '+/');
+ }
+
+ /**
+ * Encode a string with URL-safe Base64.
+ *
+ * @param string $input The string you want encoded
+ *
+ * @return string The base64 encode of what you passed in
+ */
+ public static function urlsafeB64Encode(string $input): string
+ {
+ return \str_replace('=', '', \strtr(\base64_encode($input), '+/', '-_'));
+ }
+
+
+ /**
+ * Determine if an algorithm has been provided for each Key
+ *
+ * @param Key|ArrayAccess|array $keyOrKeyArray
+ * @param string|null $kid
+ *
+ * @throws UnexpectedValueException
+ *
+ * @return Key
+ */
+ private static function getKey(
+ $keyOrKeyArray,
+ ?string $kid
+ ): Key {
+ if ($keyOrKeyArray instanceof Key) {
+ return $keyOrKeyArray;
+ }
+
+ if (empty($kid) && $kid !== '0') {
+ throw new UnexpectedValueException('"kid" empty, unable to lookup correct key');
+ }
+
+ if ($keyOrKeyArray instanceof CachedKeySet) {
+ // Skip "isset" check, as this will automatically refresh if not set
+ return $keyOrKeyArray[$kid];
+ }
+
+ if (!isset($keyOrKeyArray[$kid])) {
+ throw new UnexpectedValueException('"kid" invalid, unable to lookup correct key');
+ }
+
+ return $keyOrKeyArray[$kid];
+ }
+
+ /**
+ * @param string $left The string of known length to compare against
+ * @param string $right The user-supplied string
+ * @return bool
+ */
+ public static function constantTimeEquals(string $left, string $right): bool
+ {
+ if (\function_exists('hash_equals')) {
+ return \hash_equals($left, $right);
+ }
+ $len = \min(self::safeStrlen($left), self::safeStrlen($right));
+
+ $status = 0;
+ for ($i = 0; $i < $len; $i++) {
+ $status |= (\ord($left[$i]) ^ \ord($right[$i]));
+ }
+ $status |= (self::safeStrlen($left) ^ self::safeStrlen($right));
+
+ return ($status === 0);
+ }
+
+ /**
+ * Helper method to create a JSON error.
+ *
+ * @param int $errno An error number from json_last_error()
+ *
+ * @throws DomainException
+ *
+ * @return void
+ */
+ private static function handleJsonError(int $errno): void
+ {
+ $messages = [
+ JSON_ERROR_DEPTH => 'Maximum stack depth exceeded',
+ JSON_ERROR_STATE_MISMATCH => 'Invalid or malformed JSON',
+ JSON_ERROR_CTRL_CHAR => 'Unexpected control character found',
+ JSON_ERROR_SYNTAX => 'Syntax error, malformed JSON',
+ JSON_ERROR_UTF8 => 'Malformed UTF-8 characters' //PHP >= 5.3.3
+ ];
+ throw new DomainException(
+ isset($messages[$errno])
+ ? $messages[$errno]
+ : 'Unknown JSON error: ' . $errno
+ );
+ }
+
+ /**
+ * Get the number of bytes in cryptographic strings.
+ *
+ * @param string $str
+ *
+ * @return int
+ */
+ private static function safeStrlen(string $str): int
+ {
+ if (\function_exists('mb_strlen')) {
+ return \mb_strlen($str, '8bit');
+ }
+ return \strlen($str);
+ }
+
+ /**
+ * Convert an ECDSA signature to an ASN.1 DER sequence
+ *
+ * @param string $sig The ECDSA signature to convert
+ * @return string The encoded DER object
+ */
+ private static function signatureToDER(string $sig): string
+ {
+ // Separate the signature into r-value and s-value
+ $length = max(1, (int) (\strlen($sig) / 2));
+ list($r, $s) = \str_split($sig, $length);
+
+ // Trim leading zeros
+ $r = \ltrim($r, "\x00");
+ $s = \ltrim($s, "\x00");
+
+ // Convert r-value and s-value from unsigned big-endian integers to
+ // signed two's complement
+ if (\ord($r[0]) > 0x7f) {
+ $r = "\x00" . $r;
+ }
+ if (\ord($s[0]) > 0x7f) {
+ $s = "\x00" . $s;
+ }
+
+ return self::encodeDER(
+ self::ASN1_SEQUENCE,
+ self::encodeDER(self::ASN1_INTEGER, $r) .
+ self::encodeDER(self::ASN1_INTEGER, $s)
+ );
+ }
+
+ /**
+ * Encodes a value into a DER object.
+ *
+ * @param int $type DER tag
+ * @param string $value the value to encode
+ *
+ * @return string the encoded object
+ */
+ private static function encodeDER(int $type, string $value): string
+ {
+ $tag_header = 0;
+ if ($type === self::ASN1_SEQUENCE) {
+ $tag_header |= 0x20;
+ }
+
+ // Type
+ $der = \chr($tag_header | $type);
+
+ // Length
+ $der .= \chr(\strlen($value));
+
+ return $der . $value;
+ }
+
+ /**
+ * Encodes signature from a DER object.
+ *
+ * @param string $der binary signature in DER format
+ * @param int $keySize the number of bits in the key
+ *
+ * @return string the signature
+ */
+ private static function signatureFromDER(string $der, int $keySize): string
+ {
+ // OpenSSL returns the ECDSA signatures as a binary ASN.1 DER SEQUENCE
+ list($offset, $_) = self::readDER($der);
+ list($offset, $r) = self::readDER($der, $offset);
+ list($offset, $s) = self::readDER($der, $offset);
+
+ // Convert r-value and s-value from signed two's compliment to unsigned
+ // big-endian integers
+ $r = \ltrim($r, "\x00");
+ $s = \ltrim($s, "\x00");
+
+ // Pad out r and s so that they are $keySize bits long
+ $r = \str_pad($r, $keySize / 8, "\x00", STR_PAD_LEFT);
+ $s = \str_pad($s, $keySize / 8, "\x00", STR_PAD_LEFT);
+
+ return $r . $s;
+ }
+
+ /**
+ * Reads binary DER-encoded data and decodes into a single object
+ *
+ * @param string $der the binary data in DER format
+ * @param int $offset the offset of the data stream containing the object
+ * to decode
+ *
+ * @return array{int, string|null} the new offset and the decoded object
+ */
+ private static function readDER(string $der, int $offset = 0): array
+ {
+ $pos = $offset;
+ $size = \strlen($der);
+ $constructed = (\ord($der[$pos]) >> 5) & 0x01;
+ $type = \ord($der[$pos++]) & 0x1f;
+
+ // Length
+ $len = \ord($der[$pos++]);
+ if ($len & 0x80) {
+ $n = $len & 0x1f;
+ $len = 0;
+ while ($n-- && $pos < $size) {
+ $len = ($len << 8) | \ord($der[$pos++]);
+ }
+ }
+
+ // Value
+ if ($type === self::ASN1_BIT_STRING) {
+ $pos++; // Skip the first contents octet (padding indicator)
+ $data = \substr($der, $pos, $len - 1);
+ $pos += $len - 1;
+ } elseif (!$constructed) {
+ $data = \substr($der, $pos, $len);
+ $pos += $len;
+ } else {
+ $data = null;
+ }
+
+ return [$pos, $data];
+ }
+}
diff --git a/vendor/firebase/php-jwt/src/JWTExceptionWithPayloadInterface.php b/vendor/firebase/php-jwt/src/JWTExceptionWithPayloadInterface.php
new file mode 100644
index 0000000..7933ed6
--- /dev/null
+++ b/vendor/firebase/php-jwt/src/JWTExceptionWithPayloadInterface.php
@@ -0,0 +1,20 @@
+algorithm;
+ }
+
+ /**
+ * @return string|resource|OpenSSLAsymmetricKey|OpenSSLCertificate
+ */
+ public function getKeyMaterial()
+ {
+ return $this->keyMaterial;
+ }
+}
diff --git a/vendor/firebase/php-jwt/src/SignatureInvalidException.php b/vendor/firebase/php-jwt/src/SignatureInvalidException.php
new file mode 100644
index 0000000..d35dee9
--- /dev/null
+++ b/vendor/firebase/php-jwt/src/SignatureInvalidException.php
@@ -0,0 +1,7 @@
+Reference Docs
+
+## Description
+
+This is Google's officially supported PHP client library for using OAuth 2.0
+authorization and authentication with Google APIs.
+
+### Installing via Composer
+
+The recommended way to install the google auth library is through
+[Composer](http://getcomposer.org).
+
+```bash
+# Install Composer
+curl -sS https://getcomposer.org/installer | php
+```
+
+Next, run the Composer command to install the latest stable version:
+
+```bash
+composer.phar require google/auth
+```
+
+## Application Default Credentials
+
+This library provides an implementation of
+[Application Default Credentials (ADC)][application default credentials] for PHP.
+
+Application Default Credentials provides a simple way to get authorization
+credentials for use in calling Google APIs, and is
+the recommended approach to authorize calls to Cloud APIs.
+
+**Important**: If you accept a credential configuration (credential JSON/File/Stream) from an
+external source for authentication to Google Cloud Platform, you must validate it before providing
+it to any Google API or library. Providing an unvalidated credential configuration to Google APIs
+can compromise the security of your systems and data. For more information, refer to
+[Validate credential configurations from external sources][externally-sourced-credentials].
+
+[externally-sourced-credentials]: https://cloud.google.com/docs/authentication/external/externally-sourced-credentials
+
+### Set up ADC
+
+To use ADC, you must set it up by providing credentials.
+How you set up ADC depends on the environment where your code is running,
+and whether you are running code in a test or production environment.
+
+For more information, see [Set up Application Default Credentials][set-up-adc].
+
+### Enable the API you want to use
+
+Before making your API call, you must be sure the API you're calling has been
+enabled. Go to **APIs & Auth** > **APIs** in the
+[Google Developers Console][developer console] and enable the APIs you'd like to
+call. For the example below, you must enable the `Drive API`.
+
+### Call the APIs
+
+As long as you update the environment variable below to point to *your* JSON
+credentials file, the following code should output a list of your Drive files.
+
+```php
+use Google\Auth\ApplicationDefaultCredentials;
+use GuzzleHttp\Client;
+use GuzzleHttp\HandlerStack;
+
+// specify the path to your application credentials
+putenv('GOOGLE_APPLICATION_CREDENTIALS=/path/to/my/credentials.json');
+
+// define the scopes for your API call
+$scopes = ['https://www.googleapis.com/auth/drive.readonly'];
+
+// create middleware
+$middleware = ApplicationDefaultCredentials::getMiddleware($scopes);
+$stack = HandlerStack::create();
+$stack->push($middleware);
+
+// create the HTTP client
+$client = new Client([
+ 'handler' => $stack,
+ 'base_uri' => 'https://www.googleapis.com',
+ 'auth' => 'google_auth' // authorize all requests
+]);
+
+// make the request
+$response = $client->get('drive/v2/files');
+
+// show the result!
+print_r((string) $response->getBody());
+```
+
+##### Guzzle 5 Compatibility
+
+If you are using [Guzzle 5][Guzzle 5], replace the `create middleware` and
+`create the HTTP Client` steps with the following:
+
+```php
+// create the HTTP client
+$client = new Client([
+ 'base_url' => 'https://www.googleapis.com',
+ 'auth' => 'google_auth' // authorize all requests
+]);
+
+// create subscriber
+$subscriber = ApplicationDefaultCredentials::getSubscriber($scopes);
+$client->getEmitter()->attach($subscriber);
+```
+
+#### Call using an ID Token
+If your application is running behind Cloud Run, or using Cloud Identity-Aware
+Proxy (IAP), you will need to fetch an ID token to access your application. For
+this, use the static method `getIdTokenMiddleware` on
+`ApplicationDefaultCredentials`.
+
+```php
+use Google\Auth\ApplicationDefaultCredentials;
+use GuzzleHttp\Client;
+use GuzzleHttp\HandlerStack;
+
+// specify the path to your application credentials
+putenv('GOOGLE_APPLICATION_CREDENTIALS=/path/to/my/credentials.json');
+
+// Provide the ID token audience. This can be a Client ID associated with an IAP application,
+// Or the URL associated with a CloudRun App
+// $targetAudience = 'IAP_CLIENT_ID.apps.googleusercontent.com';
+// $targetAudience = 'https://service-1234-uc.a.run.app';
+$targetAudience = 'YOUR_ID_TOKEN_AUDIENCE';
+
+// create middleware
+$middleware = ApplicationDefaultCredentials::getIdTokenMiddleware($targetAudience);
+$stack = HandlerStack::create();
+$stack->push($middleware);
+
+// create the HTTP client
+$client = new Client([
+ 'handler' => $stack,
+ 'auth' => 'google_auth',
+ // Cloud Run, IAP, or custom resource URL
+ 'base_uri' => 'https://YOUR_PROTECTED_RESOURCE',
+]);
+
+// make the request
+$response = $client->get('/');
+
+// show the result!
+print_r((string) $response->getBody());
+```
+
+For invoking Cloud Run services, your service account will need the
+[`Cloud Run Invoker`](https://cloud.google.com/run/docs/authenticating/service-to-service)
+IAM permission.
+
+For invoking Cloud Identity-Aware Proxy, you will need to pass the Client ID
+used when you set up your protected resource as the target audience. See how to
+[secure your IAP app with signed headers](https://cloud.google.com/iap/docs/signed-headers-howto).
+
+#### Call using a specific JSON key
+If you want to use a specific JSON key instead of using `GOOGLE_APPLICATION_CREDENTIALS` environment variable, you can
+ do this:
+
+```php
+use Google\Auth\CredentialsLoader;
+use Google\Auth\Middleware\AuthTokenMiddleware;
+use GuzzleHttp\Client;
+use GuzzleHttp\HandlerStack;
+
+// Define the Google Application Credentials array
+$jsonKey = ['key' => 'value'];
+
+// define the scopes for your API call
+$scopes = ['https://www.googleapis.com/auth/drive.readonly'];
+
+// Load credentials from JSON containing service account credentials.
+$creds = new ServiceAccountCredentials($scopes, $jsonKey),
+
+// For other credentials types, create those classes explicitly using the
+// "type" field in the JSON key, for example:
+$creds = match ($jsonKey['type']) {
+ 'service_account' => new ServiceAccountCredentials($scope, $jsonKey),
+ 'authorized_user' => new UserRefreshCredentials($scope, $jsonKey),
+ default => throw new InvalidArgumentException('This application only supports service account and user account credentials'),
+};
+
+// optional caching
+$creds = new FetchAuthTokenCache($creds, $cacheConfig, $cache);
+
+// create middleware
+$middleware = new AuthTokenMiddleware($creds);
+$stack = HandlerStack::create();
+$stack->push($middleware);
+
+// create the HTTP client
+$client = new Client([
+ 'handler' => $stack,
+ 'base_uri' => 'https://www.googleapis.com',
+ 'auth' => 'google_auth' // authorize all requests
+]);
+
+// make the request
+$response = $client->get('drive/v2/files');
+
+// show the result!
+print_r((string) $response->getBody());
+
+```
+
+#### Call using Proxy-Authorization Header
+If your application is behind a proxy such as [Google Cloud IAP][iap-proxy-header],
+and your application occupies the `Authorization` request header,
+you can include the ID token in a `Proxy-Authorization: Bearer`
+header instead. If a valid ID token is found in a `Proxy-Authorization` header,
+IAP authorizes the request with it. After authorizing the request, IAP passes
+the Authorization header to your application without processing the content.
+For this, use the static method `getProxyIdTokenMiddleware` on
+`ApplicationDefaultCredentials`.
+
+```php
+use Google\Auth\ApplicationDefaultCredentials;
+use GuzzleHttp\Client;
+use GuzzleHttp\HandlerStack;
+
+// specify the path to your application credentials
+putenv('GOOGLE_APPLICATION_CREDENTIALS=/path/to/my/credentials.json');
+
+// Provide the ID token audience. This can be a Client ID associated with an IAP application
+// $targetAudience = 'IAP_CLIENT_ID.apps.googleusercontent.com';
+$targetAudience = 'YOUR_ID_TOKEN_AUDIENCE';
+
+// create middleware
+$middleware = ApplicationDefaultCredentials::getProxyIdTokenMiddleware($targetAudience);
+$stack = HandlerStack::create();
+$stack->push($middleware);
+
+// create the HTTP client
+$client = new Client([
+ 'handler' => $stack,
+ 'auth' => ['username', 'pass'], // auth option handled by your application
+ 'proxy_auth' => 'google_auth',
+]);
+
+// make the request
+$response = $client->get('/');
+
+// show the result!
+print_r((string) $response->getBody());
+```
+
+[iap-proxy-header]: https://cloud.google.com/iap/docs/authentication-howto#authenticating_from_proxy-authorization_header
+
+#### External credentials (Workload identity federation)
+
+Using workload identity federation, your application can access Google Cloud resources from Amazon Web Services (AWS),
+Microsoft Azure or any identity provider that supports OpenID Connect (OIDC).
+
+Traditionally, applications running outside Google Cloud have used service account keys to access Google Cloud
+resources. Using identity federation, you can allow your workload to impersonate a service account. This lets you access
+Google Cloud resources directly, eliminating the maintenance and security burden associated with service account keys.
+
+Follow the detailed instructions on how to
+[Configure Workload Identity Federation](https://cloud.google.com/iam/docs/workload-identity-federation-with-other-clouds).
+
+#### Verifying JWTs
+
+If you are [using Google ID tokens to authenticate users][google-id-tokens], use
+the `Google\Auth\AccessToken` class to verify the ID token:
+
+```php
+use Google\Auth\AccessToken;
+
+$auth = new AccessToken();
+$auth->verify($idToken);
+```
+
+If your app is running behind [Google Identity-Aware Proxy][iap-id-tokens]
+(IAP), you can verify the ID token coming from the IAP server by pointing to the
+appropriate certificate URL for IAP. This is because IAP signs the ID
+tokens with a different key than the Google Identity service:
+
+```php
+use Google\Auth\AccessToken;
+
+$auth = new AccessToken();
+$auth->verify($idToken, [
+ 'certsLocation' => AccessToken::IAP_CERT_URL
+]);
+```
+
+[google-id-tokens]: https://developers.google.com/identity/sign-in/web/backend-auth
+[iap-id-tokens]: https://cloud.google.com/iap/docs/signed-headers-howto
+
+## Caching
+Caching is enabled by passing a PSR-6 `CacheItemPoolInterface`
+instance to the constructor when instantiating the credentials.
+
+We offer some caching classes out of the box under the `Google\Auth\Cache` namespace.
+
+```php
+use Google\Auth\ApplicationDefaultCredentials;
+use Google\Auth\Cache\MemoryCacheItemPool;
+
+// Cache Instance
+$memoryCache = new MemoryCacheItemPool;
+
+// Get the credentials
+// From here, the credentials will cache the access token
+$middleware = ApplicationDefaultCredentials::getCredentials($scope, cache: $memoryCache);
+```
+
+### FileSystemCacheItemPool Cache
+The `FileSystemCacheItemPool` class is a `PSR-6` compliant cache that stores its
+serialized objects on disk, caching data between processes and making it possible
+to use data between different requests.
+
+```php
+use Google\Auth\Cache\FileSystemCacheItemPool;
+use Google\Auth\ApplicationDefaultCredentials;
+
+// Create a Cache pool instance
+$cache = new FileSystemCacheItemPool(__DIR__ . '/cache');
+
+// Pass your Cache to the Auth Library
+$credentials = ApplicationDefaultCredentials::getCredentials($scope, cache: $cache);
+
+// This token will be cached and be able to be used for the next request
+$token = $credentials->fetchAuthToken();
+```
+
+### Integrating with a third party cache
+You can use a third party that follows the `PSR-6` interface of your choice.
+
+```php
+// run "composer require symfony/cache"
+use Google\Auth\ApplicationDefaultCredentials;
+use Symfony\Component\Cache\Adapter\FilesystemAdapter;
+
+// Create the cache instance
+$filesystemCache = new FilesystemAdapter();
+
+// Create Get the credentials
+$credentials = ApplicationDefaultCredentials::getCredentials($targetAudience, cache: $filesystemCache);
+```
+
+## License
+
+This library is licensed under Apache 2.0. Full license text is
+available in [COPYING][copying].
+
+## Contributing
+
+See [CONTRIBUTING][contributing].
+
+## Support
+
+Please
+[report bugs at the project on Github](https://github.com/google/google-auth-library-php/issues). Don't
+hesitate to
+[ask questions](http://stackoverflow.com/questions/tagged/google-auth-library-php)
+about the client or APIs on [StackOverflow](http://stackoverflow.com).
+
+[google-apis-php-client]: https://github.com/google/google-api-php-client
+[application default credentials]: https://cloud.google.com/docs/authentication/application-default-credentials
+[contributing]: https://github.com/google/google-auth-library-php/tree/main/.github/CONTRIBUTING.md
+[copying]: https://github.com/google/google-auth-library-php/tree/main/COPYING
+[Guzzle]: https://github.com/guzzle/guzzle
+[Guzzle 5]: http://docs.guzzlephp.org/en/5.3
+[developer console]: https://console.developers.google.com
+[set-up-adc]: https://cloud.google.com/docs/authentication/provide-credentials-adc
diff --git a/vendor/google/auth/SECURITY.md b/vendor/google/auth/SECURITY.md
new file mode 100644
index 0000000..8b58ae9
--- /dev/null
+++ b/vendor/google/auth/SECURITY.md
@@ -0,0 +1,7 @@
+# Security Policy
+
+To report a security issue, please use [g.co/vulnz](https://g.co/vulnz).
+
+The Google Security Team will respond within 5 working days of your report on g.co/vulnz.
+
+We use g.co/vulnz for our intake, and do coordination and disclosure here using GitHub Security Advisory to privately discuss and fix the issue.
diff --git a/vendor/google/auth/VERSION b/vendor/google/auth/VERSION
new file mode 100644
index 0000000..5525f03
--- /dev/null
+++ b/vendor/google/auth/VERSION
@@ -0,0 +1 @@
+1.48.1
diff --git a/vendor/google/auth/composer.json b/vendor/google/auth/composer.json
new file mode 100644
index 0000000..127fdce
--- /dev/null
+++ b/vendor/google/auth/composer.json
@@ -0,0 +1,44 @@
+{
+ "name": "google/auth",
+ "type": "library",
+ "description": "Google Auth Library for PHP",
+ "keywords": ["google", "oauth2", "authentication"],
+ "homepage": "https://github.com/google/google-auth-library-php",
+ "license": "Apache-2.0",
+ "support": {
+ "docs": "https://cloud.google.com/php/docs/reference/auth/latest"
+ },
+ "require": {
+ "php": "^8.1",
+ "firebase/php-jwt": "^6.0",
+ "guzzlehttp/guzzle": "^7.4.5",
+ "guzzlehttp/psr7": "^2.4.5",
+ "psr/http-message": "^1.1||^2.0",
+ "psr/cache": "^2.0||^3.0",
+ "psr/log": "^3.0"
+ },
+ "require-dev": {
+ "guzzlehttp/promises": "^2.0",
+ "squizlabs/php_codesniffer": "^4.0",
+ "phpunit/phpunit": "^9.6",
+ "phpspec/prophecy-phpunit": "^2.1",
+ "sebastian/comparator": ">=1.2.3",
+ "phpseclib/phpseclib": "^3.0.35",
+ "kelvinmo/simplejwt": "0.7.1",
+ "webmozart/assert": "^1.11",
+ "symfony/process": "^6.0||^7.0"
+ },
+ "suggest": {
+ "phpseclib/phpseclib": "May be used in place of OpenSSL for signing strings or for token management. Please require version ^2."
+ },
+ "autoload": {
+ "psr-4": {
+ "Google\\Auth\\": "src"
+ }
+ },
+ "autoload-dev": {
+ "psr-4": {
+ "Google\\Auth\\Tests\\": "tests"
+ }
+ }
+}
diff --git a/vendor/google/auth/src/AccessToken.php b/vendor/google/auth/src/AccessToken.php
new file mode 100644
index 0000000..9e27b69
--- /dev/null
+++ b/vendor/google/auth/src/AccessToken.php
@@ -0,0 +1,473 @@
+httpHandler = $httpHandler
+ ?: HttpHandlerFactory::build(HttpClientCache::getHttpClient());
+ $this->cache = $cache ?: new MemoryCacheItemPool();
+ }
+
+ /**
+ * Verifies an id token and returns the authenticated apiLoginTicket.
+ * Throws an exception if the id token is not valid.
+ * The audience parameter can be used to control which id tokens are
+ * accepted. By default, the id token must have been issued to this OAuth2 client.
+ *
+ * @param string $token The JSON Web Token to be verified.
+ * @param array $options [optional] {
+ * Configuration options.
+ * @type string $audience The indended recipient of the token.
+ * @type string $issuer The intended issuer of the token.
+ * @type string $cacheKey The cache key of the cached certs. Defaults to
+ * the sha1 of $certsLocation if provided, otherwise is set to
+ * "federated_signon_certs_v3".
+ * @type string $certsLocation The location (remote or local) from which
+ * to retrieve certificates, if not cached. This value should only be
+ * provided in limited circumstances in which you are sure of the
+ * behavior.
+ * @type bool $throwException Whether the function should throw an
+ * exception if the verification fails. This is useful for
+ * determining the reason verification failed.
+ * }
+ * @return array|false the token payload, if successful, or false if not.
+ * @throws InvalidArgumentException If certs could not be retrieved from a local file.
+ * @throws InvalidArgumentException If received certs are in an invalid format.
+ * @throws InvalidArgumentException If the cert alg is not supported.
+ * @throws RuntimeException If certs could not be retrieved from a remote location.
+ * @throws UnexpectedValueException If the token issuer does not match.
+ * @throws UnexpectedValueException If the token audience does not match.
+ */
+ public function verify($token, array $options = [])
+ {
+ $audience = $options['audience'] ?? null;
+ $issuer = $options['issuer'] ?? null;
+ $certsLocation = $options['certsLocation'] ?? self::FEDERATED_SIGNON_CERT_URL;
+ $cacheKey = $options['cacheKey'] ?? $this->getCacheKeyFromCertLocation($certsLocation);
+ $throwException = $options['throwException'] ?? false; // for backwards compatibility
+
+ // Check signature against each available cert.
+ $certs = $this->getCerts($certsLocation, $cacheKey, $options);
+ $alg = $this->determineAlg($certs);
+ if (!in_array($alg, ['RS256', 'ES256'])) {
+ throw new InvalidArgumentException(
+ 'unrecognized "alg" in certs, expected ES256 or RS256'
+ );
+ }
+ try {
+ if ($alg == 'RS256') {
+ return $this->verifyRs256($token, $certs, $audience, $issuer);
+ }
+ return $this->verifyEs256($token, $certs, $audience, $issuer);
+ } catch (ExpiredException $e) { // firebase/php-jwt 5+
+ } catch (SignatureInvalidException $e) { // firebase/php-jwt 5+
+ } catch (InvalidTokenException $e) { // simplejwt
+ } catch (InvalidArgumentException $e) {
+ } catch (UnexpectedValueException $e) {
+ }
+
+ if ($throwException) {
+ throw $e;
+ }
+
+ return false;
+ }
+
+ /**
+ * Identifies the expected algorithm to verify by looking at the "alg" key
+ * of the provided certs.
+ *
+ * @param array $certs Certificate array according to the JWK spec (see
+ * https://tools.ietf.org/html/rfc7517).
+ * @return string The expected algorithm, such as "ES256" or "RS256".
+ */
+ private function determineAlg(array $certs)
+ {
+ $alg = null;
+ foreach ($certs as $cert) {
+ if (empty($cert['alg'])) {
+ throw new InvalidArgumentException(
+ 'certs expects "alg" to be set'
+ );
+ }
+ $alg = $alg ?: $cert['alg'];
+
+ if ($alg != $cert['alg']) {
+ throw new InvalidArgumentException(
+ 'More than one alg detected in certs'
+ );
+ }
+ }
+ return $alg;
+ }
+
+ /**
+ * Verifies an ES256-signed JWT.
+ *
+ * @param string $token The JSON Web Token to be verified.
+ * @param array $certs Certificate array according to the JWK spec (see
+ * https://tools.ietf.org/html/rfc7517).
+ * @param string|null $audience If set, returns false if the provided
+ * audience does not match the "aud" claim on the JWT.
+ * @param string|null $issuer If set, returns false if the provided
+ * issuer does not match the "iss" claim on the JWT.
+ * @return array the token payload, if successful, or false if not.
+ */
+ private function verifyEs256($token, array $certs, $audience = null, $issuer = null)
+ {
+ $this->checkSimpleJwt();
+
+ $jwkset = new KeySet();
+ foreach ($certs as $cert) {
+ $jwkset->add(KeyFactory::create($cert, 'php'));
+ }
+
+ // Validate the signature using the key set and ES256 algorithm.
+ $jwt = $this->callSimpleJwtDecode([$token, $jwkset, 'ES256']);
+ $payload = $jwt->getClaims();
+
+ if ($audience) {
+ if (!isset($payload['aud']) || $payload['aud'] != $audience) {
+ throw new UnexpectedValueException('Audience does not match');
+ }
+ }
+
+ // @see https://cloud.google.com/iap/docs/signed-headers-howto#verifying_the_jwt_payload
+ $issuer = $issuer ?: self::IAP_ISSUER;
+ if (!isset($payload['iss']) || $payload['iss'] !== $issuer) {
+ throw new UnexpectedValueException('Issuer does not match');
+ }
+
+ return $payload;
+ }
+
+ /**
+ * Verifies an RS256-signed JWT.
+ *
+ * @param string $token The JSON Web Token to be verified.
+ * @param array $certs Certificate array according to the JWK spec (see
+ * https://tools.ietf.org/html/rfc7517).
+ * @param string|null $audience If set, returns false if the provided
+ * audience does not match the "aud" claim on the JWT.
+ * @param string|null $issuer If set, returns false if the provided
+ * issuer does not match the "iss" claim on the JWT.
+ * @return array the token payload, if successful, or false if not.
+ */
+ private function verifyRs256($token, array $certs, $audience = null, $issuer = null)
+ {
+ $this->checkAndInitializePhpsec();
+ $keys = [];
+ foreach ($certs as $cert) {
+ if (empty($cert['kid'])) {
+ throw new InvalidArgumentException(
+ 'certs expects "kid" to be set'
+ );
+ }
+ if (empty($cert['n']) || empty($cert['e'])) {
+ throw new InvalidArgumentException(
+ 'RSA certs expects "n" and "e" to be set'
+ );
+ }
+ $publicKey = $this->loadPhpsecPublicKey($cert['n'], $cert['e']);
+
+ // create an array of key IDs to certs for the JWT library
+ $keys[$cert['kid']] = new Key($publicKey, 'RS256');
+ }
+
+ $payload = $this->callJwtStatic('decode', [
+ $token,
+ $keys,
+ ]);
+
+ if ($audience) {
+ if (!property_exists($payload, 'aud') || $payload->aud != $audience) {
+ throw new UnexpectedValueException('Audience does not match');
+ }
+ }
+
+ // support HTTP and HTTPS issuers
+ // @see https://developers.google.com/identity/sign-in/web/backend-auth
+ $issuers = $issuer ? [$issuer] : [self::OAUTH2_ISSUER, self::OAUTH2_ISSUER_HTTPS];
+ if (!isset($payload->iss) || !in_array($payload->iss, $issuers)) {
+ throw new UnexpectedValueException('Issuer does not match');
+ }
+
+ return (array) $payload;
+ }
+
+ /**
+ * Revoke an OAuth2 access token or refresh token. This method will revoke the current access
+ * token, if a token isn't provided.
+ *
+ * @param string|array $token The token (access token or a refresh token) that should be revoked.
+ * @param array $options [optional] Configuration options.
+ * @return bool Returns True if the revocation was successful, otherwise False.
+ */
+ public function revoke($token, array $options = [])
+ {
+ if (is_array($token)) {
+ if (isset($token['refresh_token'])) {
+ $token = $token['refresh_token'];
+ } else {
+ $token = $token['access_token'];
+ }
+ }
+
+ $body = Utils::streamFor(http_build_query(['token' => $token]));
+ $request = new Request('POST', self::OAUTH2_REVOKE_URI, [
+ 'Cache-Control' => 'no-store',
+ 'Content-Type' => 'application/x-www-form-urlencoded',
+ ], $body);
+
+ $httpHandler = $this->httpHandler;
+
+ $response = $httpHandler($request, $options);
+
+ return $response->getStatusCode() == 200;
+ }
+
+ /**
+ * Gets federated sign-on certificates to use for verifying identity tokens.
+ * Returns certs as array structure, where keys are key ids, and values
+ * are PEM encoded certificates.
+ *
+ * @param string $location The location from which to retrieve certs.
+ * @param string $cacheKey The key under which to cache the retrieved certs.
+ * @param array $options [optional] Configuration options.
+ * @return array
+ * @throws InvalidArgumentException If received certs are in an invalid format.
+ */
+ private function getCerts($location, $cacheKey, array $options = [])
+ {
+ $cacheItem = $this->cache->getItem($cacheKey);
+ $certs = $cacheItem ? $cacheItem->get() : null;
+
+ $expireTime = null;
+ if (!$certs) {
+ list($certs, $expireTime) = $this->retrieveCertsFromLocation($location, $options);
+ }
+
+ if (!isset($certs['keys'])) {
+ if ($location !== self::IAP_CERT_URL) {
+ throw new InvalidArgumentException(
+ 'federated sign-on certs expects "keys" to be set'
+ );
+ }
+ throw new InvalidArgumentException(
+ 'certs expects "keys" to be set'
+ );
+ }
+
+ // Push caching off until after verifying certs are in a valid format.
+ // Don't want to cache bad data.
+ if ($expireTime) {
+ $cacheItem->expiresAt(new DateTime($expireTime));
+ $cacheItem->set($certs);
+ $this->cache->save($cacheItem);
+ }
+
+ return $certs['keys'];
+ }
+
+ /**
+ * Retrieve and cache a certificates file.
+ *
+ * @param string $url location
+ * @param array $options [optional] Configuration options.
+ * @return array{array, string}
+ * @throws InvalidArgumentException If certs could not be retrieved from a local file.
+ * @throws RuntimeException If certs could not be retrieved from a remote location.
+ */
+ private function retrieveCertsFromLocation($url, array $options = [])
+ {
+ // If we're retrieving a local file, just grab it.
+ $expireTime = '+1 hour';
+ if (strpos($url, 'http') !== 0) {
+ if (!file_exists($url)) {
+ throw new InvalidArgumentException(sprintf(
+ 'Failed to retrieve verification certificates from path: %s.',
+ $url
+ ));
+ }
+
+ return [
+ json_decode((string) file_get_contents($url), true),
+ $expireTime
+ ];
+ }
+
+ $httpHandler = $this->httpHandler;
+ $response = $httpHandler(new Request('GET', $url), $options);
+
+ if ($response->getStatusCode() == 200) {
+ if ($cacheControl = $response->getHeaderLine('Cache-Control')) {
+ array_map(function ($value) use (&$expireTime) {
+ list($key, $value) = explode('=', $value) + [null, null];
+ if (trim($key) == 'max-age') {
+ $expireTime = '+' . $value . ' seconds';
+ }
+ }, explode(',', $cacheControl));
+ }
+ return [
+ json_decode((string) $response->getBody(), true),
+ $expireTime
+ ];
+ }
+
+ throw new RuntimeException(sprintf(
+ 'Failed to retrieve verification certificates: "%s".',
+ $response->getBody()->getContents()
+ ), $response->getStatusCode());
+ }
+
+ /**
+ * @return void
+ */
+ private function checkAndInitializePhpsec()
+ {
+ if (!class_exists(RSA::class)) {
+ throw new RuntimeException('Please require phpseclib/phpseclib v3 to use this utility.');
+ }
+ }
+
+ /**
+ * @return string
+ * @throws TypeError If the key cannot be initialized to a string.
+ */
+ private function loadPhpsecPublicKey(string $modulus, string $exponent): string
+ {
+ $key = PublicKeyLoader::load([
+ 'n' => new BigInteger($this->callJwtStatic('urlsafeB64Decode', [
+ $modulus,
+ ]), 256),
+ 'e' => new BigInteger($this->callJwtStatic('urlsafeB64Decode', [
+ $exponent
+ ]), 256),
+ ]);
+ $formattedPublicKey = $key->toString('PKCS8');
+ if (!is_string($formattedPublicKey)) {
+ throw new TypeError('Failed to initialize the key');
+ }
+ return $formattedPublicKey;
+ }
+
+ /**
+ * @return void
+ */
+ private function checkSimpleJwt()
+ {
+ // @codeCoverageIgnoreStart
+ if (!class_exists(SimpleJwt::class)) {
+ throw new RuntimeException('Please require kelvinmo/simplejwt ^0.2 to use this utility.');
+ }
+ // @codeCoverageIgnoreEnd
+ }
+
+ /**
+ * Provide a hook to mock calls to the JWT static methods.
+ *
+ * @param string $method
+ * @param array $args
+ * @return mixed
+ */
+ protected function callJwtStatic($method, array $args = [])
+ {
+ return call_user_func_array([JWT::class, $method], $args); // @phpstan-ignore-line
+ }
+
+ /**
+ * Provide a hook to mock calls to the JWT static methods.
+ *
+ * @param array $args
+ * @return mixed
+ */
+ protected function callSimpleJwtDecode(array $args = [])
+ {
+ return call_user_func_array([SimpleJwt::class, 'decode'], $args);
+ }
+
+ /**
+ * Generate a cache key based on the cert location using sha1 with the
+ * exception of using "federated_signon_certs_v3" to preserve BC.
+ *
+ * @param string $certsLocation
+ * @return string
+ */
+ private function getCacheKeyFromCertLocation($certsLocation)
+ {
+ $key = $certsLocation === self::FEDERATED_SIGNON_CERT_URL
+ ? 'federated_signon_certs_v3'
+ : sha1($certsLocation);
+
+ return 'google_auth_certs_cache|' . $key;
+ }
+}
diff --git a/vendor/google/auth/src/ApplicationDefaultCredentials.php b/vendor/google/auth/src/ApplicationDefaultCredentials.php
new file mode 100644
index 0000000..a64af46
--- /dev/null
+++ b/vendor/google/auth/src/ApplicationDefaultCredentials.php
@@ -0,0 +1,391 @@
+push($middleware);
+ *
+ * $client = new Client([
+ * 'handler' => $stack,
+ * 'base_uri' => 'https://www.googleapis.com/taskqueue/v1beta2/projects/',
+ * 'auth' => 'google_auth' // authorize all requests
+ * ]);
+ *
+ * $res = $client->get('myproject/taskqueues/myqueue');
+ * ```
+ */
+class ApplicationDefaultCredentials
+{
+ private const SDK_DEBUG_ENV_VAR = 'GOOGLE_SDK_PHP_LOGGING';
+
+ /**
+ * @deprecated
+ *
+ * Obtains an AuthTokenSubscriber that uses the default FetchAuthTokenInterface
+ * implementation to use in this environment.
+ *
+ * If supplied, $scope is used to in creating the credentials instance if
+ * this does not fallback to the compute engine defaults.
+ *
+ * @param string|string[] $scope the scope of the access request, expressed
+ * either as an Array or as a space-delimited String.
+ * @param callable|null $httpHandler callback which delivers psr7 request
+ * @param array|null $cacheConfig configuration for the cache when it's present
+ * @param CacheItemPoolInterface|null $cache A cache implementation, may be
+ * provided if you have one already available for use.
+ * @return AuthTokenSubscriber
+ * @throws DomainException if no implementation can be obtained.
+ */
+ public static function getSubscriber(// @phpstan-ignore-line
+ $scope = null,
+ ?callable $httpHandler = null,
+ ?array $cacheConfig = null,
+ ?CacheItemPoolInterface $cache = null
+ ) {
+ $creds = self::getCredentials($scope, $httpHandler, $cacheConfig, $cache);
+
+ /** @phpstan-ignore-next-line */
+ return new AuthTokenSubscriber($creds, $httpHandler);
+ }
+
+ /**
+ * Obtains an AuthTokenMiddleware that uses the default FetchAuthTokenInterface
+ * implementation to use in this environment.
+ *
+ * If supplied, $scope is used to in creating the credentials instance if
+ * this does not fallback to the compute engine defaults.
+ *
+ * @param string|string[] $scope the scope of the access request, expressed
+ * either as an Array or as a space-delimited String.
+ * @param callable|null $httpHandler callback which delivers psr7 request
+ * @param array|null $cacheConfig configuration for the cache when it's present
+ * @param CacheItemPoolInterface|null $cache A cache implementation, may be
+ * provided if you have one already available for use.
+ * @param string $quotaProject specifies a project to bill for access
+ * charges associated with the request.
+ * @return AuthTokenMiddleware
+ * @throws DomainException if no implementation can be obtained.
+ */
+ public static function getMiddleware(
+ $scope = null,
+ ?callable $httpHandler = null,
+ ?array $cacheConfig = null,
+ ?CacheItemPoolInterface $cache = null,
+ $quotaProject = null
+ ) {
+ $creds = self::getCredentials($scope, $httpHandler, $cacheConfig, $cache, $quotaProject);
+
+ return new AuthTokenMiddleware($creds, $httpHandler);
+ }
+
+ /**
+ * Obtains the default FetchAuthTokenInterface implementation to use
+ * in this environment.
+ *
+ * @param string|string[] $scope the scope of the access request, expressed
+ * either as an Array or as a space-delimited String.
+ * @param callable|null $httpHandler callback which delivers psr7 request
+ * @param array|null $cacheConfig configuration for the cache when it's present
+ * @param CacheItemPoolInterface|null $cache A cache implementation, may be
+ * provided if you have one already available for use.
+ * @param string|null $quotaProject specifies a project to bill for access
+ * charges associated with the request.
+ * @param string|string[]|null $defaultScope The default scope to use if no
+ * user-defined scopes exist, expressed either as an Array or as a
+ * space-delimited string.
+ * @param string|null $universeDomain Specifies a universe domain to use for the
+ * calling client library.
+ * @param null|false|LoggerInterface $logger A PSR3 compliant LoggerInterface.
+ *
+ * @return FetchAuthTokenInterface
+ * @throws DomainException if no implementation can be obtained.
+ */
+ public static function getCredentials(
+ $scope = null,
+ ?callable $httpHandler = null,
+ ?array $cacheConfig = null,
+ ?CacheItemPoolInterface $cache = null,
+ $quotaProject = null,
+ $defaultScope = null,
+ ?string $universeDomain = null,
+ null|false|LoggerInterface $logger = null,
+ ) {
+ $creds = null;
+ $jsonKey = CredentialsLoader::fromEnv()
+ ?: CredentialsLoader::fromWellKnownFile();
+ $anyScope = $scope ?: $defaultScope;
+
+ if (!$httpHandler) {
+ if (!($client = HttpClientCache::getHttpClient())) {
+ $client = new Client();
+ HttpClientCache::setHttpClient($client);
+ }
+
+ $httpHandler = HttpHandlerFactory::build($client, $logger);
+ }
+
+ if (is_null($quotaProject)) {
+ // if a quota project isn't specified, try to get one from the env var
+ $quotaProject = CredentialsLoader::quotaProjectFromEnv();
+ }
+
+ if (!is_null($jsonKey)) {
+ if ($quotaProject) {
+ $jsonKey['quota_project_id'] = $quotaProject;
+ }
+ if ($universeDomain) {
+ $jsonKey['universe_domain'] = $universeDomain;
+ }
+ $creds = CredentialsLoader::makeCredentials(
+ $scope,
+ $jsonKey,
+ $defaultScope
+ );
+ } elseif (AppIdentityCredentials::onAppEngine() && !GCECredentials::onAppEngineFlexible()) {
+ $creds = new AppIdentityCredentials($anyScope);
+ } elseif (self::onGce($httpHandler, $cacheConfig, $cache)) {
+ $creds = new GCECredentials(null, $anyScope, null, $quotaProject, null, $universeDomain);
+ $creds->setIsOnGce(true); // save the credentials a trip to the metadata server
+ }
+
+ if (is_null($creds)) {
+ throw new DomainException(self::notFound());
+ }
+ if (!is_null($cache)) {
+ $creds = new FetchAuthTokenCache($creds, $cacheConfig, $cache);
+ }
+ return $creds;
+ }
+
+ /**
+ * Obtains an AuthTokenMiddleware which will fetch an ID token to use in the
+ * Authorization header. The middleware is configured with the default
+ * FetchAuthTokenInterface implementation to use in this environment.
+ *
+ * If supplied, $targetAudience is used to set the "aud" on the resulting
+ * ID token.
+ *
+ * @param string $targetAudience The audience for the ID token.
+ * @param callable|null $httpHandler callback which delivers psr7 request
+ * @param array|null $cacheConfig configuration for the cache when it's present
+ * @param CacheItemPoolInterface|null $cache A cache implementation, may be
+ * provided if you have one already available for use.
+ * @return AuthTokenMiddleware
+ * @throws DomainException if no implementation can be obtained.
+ */
+ public static function getIdTokenMiddleware(
+ $targetAudience,
+ ?callable $httpHandler = null,
+ ?array $cacheConfig = null,
+ ?CacheItemPoolInterface $cache = null
+ ) {
+ $creds = self::getIdTokenCredentials($targetAudience, $httpHandler, $cacheConfig, $cache);
+
+ return new AuthTokenMiddleware($creds, $httpHandler);
+ }
+
+ /**
+ * Obtains an ProxyAuthTokenMiddleware which will fetch an ID token to use in the
+ * Authorization header. The middleware is configured with the default
+ * FetchAuthTokenInterface implementation to use in this environment.
+ *
+ * If supplied, $targetAudience is used to set the "aud" on the resulting
+ * ID token.
+ *
+ * @param string $targetAudience The audience for the ID token.
+ * @param callable|null $httpHandler callback which delivers psr7 request
+ * @param array|null $cacheConfig configuration for the cache when it's present
+ * @param CacheItemPoolInterface|null $cache A cache implementation, may be
+ * provided if you have one already available for use.
+ * @return ProxyAuthTokenMiddleware
+ * @throws DomainException if no implementation can be obtained.
+ */
+ public static function getProxyIdTokenMiddleware(
+ $targetAudience,
+ ?callable $httpHandler = null,
+ ?array $cacheConfig = null,
+ ?CacheItemPoolInterface $cache = null
+ ) {
+ $creds = self::getIdTokenCredentials($targetAudience, $httpHandler, $cacheConfig, $cache);
+
+ return new ProxyAuthTokenMiddleware($creds, $httpHandler);
+ }
+
+ /**
+ * Obtains the default FetchAuthTokenInterface implementation to use
+ * in this environment, configured with a $targetAudience for fetching an ID
+ * token.
+ *
+ * @param string $targetAudience The audience for the ID token.
+ * @param callable|null $httpHandler callback which delivers psr7 request
+ * @param array|null $cacheConfig configuration for the cache when it's present
+ * @param CacheItemPoolInterface|null $cache A cache implementation, may be
+ * provided if you have one already available for use.
+ * @return FetchAuthTokenInterface
+ * @throws DomainException if no implementation can be obtained.
+ * @throws InvalidArgumentException if JSON "type" key is invalid
+ */
+ public static function getIdTokenCredentials(
+ $targetAudience,
+ ?callable $httpHandler = null,
+ ?array $cacheConfig = null,
+ ?CacheItemPoolInterface $cache = null
+ ) {
+ $creds = null;
+ $jsonKey = CredentialsLoader::fromEnv()
+ ?: CredentialsLoader::fromWellKnownFile();
+
+ if (!$httpHandler) {
+ if (!($client = HttpClientCache::getHttpClient())) {
+ $client = new Client();
+ HttpClientCache::setHttpClient($client);
+ }
+
+ $httpHandler = HttpHandlerFactory::build($client);
+ }
+
+ if (!is_null($jsonKey)) {
+ if (!array_key_exists('type', $jsonKey)) {
+ throw new \InvalidArgumentException('json key is missing the type field');
+ }
+
+ $creds = match ($jsonKey['type']) {
+ 'authorized_user' => new UserRefreshCredentials(null, $jsonKey, $targetAudience),
+ 'impersonated_service_account' => new ImpersonatedServiceAccountCredentials(null, $jsonKey, $targetAudience),
+ 'service_account' => new ServiceAccountCredentials(null, $jsonKey, null, $targetAudience),
+ default => throw new InvalidArgumentException('invalid value in the type field')
+ };
+ } elseif (self::onGce($httpHandler, $cacheConfig, $cache)) {
+ $creds = new GCECredentials(null, null, $targetAudience);
+ $creds->setIsOnGce(true); // save the credentials a trip to the metadata server
+ }
+
+ if (is_null($creds)) {
+ throw new DomainException(self::notFound());
+ }
+ if (!is_null($cache)) {
+ $creds = new FetchAuthTokenCache($creds, $cacheConfig, $cache);
+ }
+ return $creds;
+ }
+
+ /**
+ * Returns a StdOutLogger instance
+ *
+ * @internal
+ *
+ * @return null|LoggerInterface
+ */
+ public static function getDefaultLogger(): null|LoggerInterface
+ {
+ $loggingFlag = getenv(self::SDK_DEBUG_ENV_VAR);
+
+ // Env var is not set
+ if (empty($loggingFlag)) {
+ return null;
+ }
+
+ $loggingFlag = strtolower($loggingFlag);
+
+ // Env Var is not true
+ if ($loggingFlag !== 'true') {
+ if ($loggingFlag !== 'false') {
+ trigger_error('The ' . self::SDK_DEBUG_ENV_VAR . ' is set, but it is set to another value than false or true. Logging is disabled');
+ }
+
+ return null;
+ }
+
+ return new StdOutLogger();
+ }
+
+ /**
+ * @return string
+ */
+ private static function notFound()
+ {
+ $msg = 'Your default credentials were not found. To set up ';
+ $msg .= 'Application Default Credentials, see ';
+ $msg .= 'https://cloud.google.com/docs/authentication/external/set-up-adc';
+
+ return $msg;
+ }
+
+ /**
+ * @param callable|null $httpHandler
+ * @param array|null $cacheConfig
+ * @param CacheItemPoolInterface|null $cache
+ * @return bool
+ */
+ private static function onGce(
+ ?callable $httpHandler = null,
+ ?array $cacheConfig = null,
+ ?CacheItemPoolInterface $cache = null
+ ) {
+ $gceCacheConfig = [];
+ foreach (['lifetime', 'prefix'] as $key) {
+ if (isset($cacheConfig['gce_' . $key])) {
+ $gceCacheConfig[$key] = $cacheConfig['gce_' . $key];
+ }
+ }
+
+ return (new GCECache($gceCacheConfig, $cache))->onGce($httpHandler);
+ }
+}
diff --git a/vendor/google/auth/src/Cache/FileSystemCacheItemPool.php b/vendor/google/auth/src/Cache/FileSystemCacheItemPool.php
new file mode 100644
index 0000000..ee0651a
--- /dev/null
+++ b/vendor/google/auth/src/Cache/FileSystemCacheItemPool.php
@@ -0,0 +1,230 @@
+
+ */
+ private array $buffer = [];
+
+ /**
+ * Creates a FileSystemCacheItemPool cache that stores values in local storage
+ *
+ * @param string $path The string representation of the path where the cache will store the serialized objects.
+ */
+ public function __construct(string $path)
+ {
+ $this->cachePath = $path;
+
+ if (is_dir($this->cachePath)) {
+ return;
+ }
+
+ if (!mkdir($this->cachePath)) {
+ throw new ErrorException("Cache folder couldn't be created.");
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getItem(string $key): CacheItemInterface
+ {
+ if (!$this->validKey($key)) {
+ throw new InvalidArgumentException("The key '$key' is not valid. The key should follow the pattern |^[a-zA-Z0-9_\.! ]+$|");
+ }
+
+ $item = new TypedItem($key);
+
+ $itemPath = $this->cacheFilePath($key);
+
+ if (!file_exists($itemPath)) {
+ return $item;
+ }
+
+ $serializedItem = file_get_contents($itemPath);
+
+ if ($serializedItem === false) {
+ return $item;
+ }
+
+ $item->set(unserialize($serializedItem));
+
+ return $item;
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @return iterable An iterable object containing all the
+ * A traversable collection of Cache Items keyed by the cache keys of
+ * each item. A Cache item will be returned for each key, even if that
+ * key is not found. However, if no keys are specified then an empty
+ * traversable MUST be returned instead.
+ */
+ public function getItems(array $keys = []): iterable
+ {
+ $result = [];
+
+ foreach ($keys as $key) {
+ $result[$key] = $this->getItem($key);
+ }
+
+ return $result;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function save(CacheItemInterface $item): bool
+ {
+ if (!$this->validKey($item->getKey())) {
+ return false;
+ }
+
+ $itemPath = $this->cacheFilePath($item->getKey());
+ $serializedItem = serialize($item->get());
+
+ $result = file_put_contents($itemPath, $serializedItem);
+
+ // 0 bytes write is considered a successful operation
+ if ($result === false) {
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function hasItem(string $key): bool
+ {
+ return $this->getItem($key)->isHit();
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function clear(): bool
+ {
+ $this->buffer = [];
+
+ if (!is_dir($this->cachePath)) {
+ return false;
+ }
+
+ $files = scandir($this->cachePath);
+ if (!$files) {
+ return false;
+ }
+
+ foreach ($files as $fileName) {
+ if ($fileName === '.' || $fileName === '..') {
+ continue;
+ }
+
+ if (!unlink($this->cachePath . '/' . $fileName)) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function deleteItem(string $key): bool
+ {
+ if (!$this->validKey($key)) {
+ throw new InvalidArgumentException("The key '$key' is not valid. The key should follow the pattern |^[a-zA-Z0-9_\.! ]+$|");
+ }
+
+ $itemPath = $this->cacheFilePath($key);
+
+ if (!file_exists($itemPath)) {
+ return true;
+ }
+
+ return unlink($itemPath);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function deleteItems(array $keys): bool
+ {
+ $result = true;
+
+ foreach ($keys as $key) {
+ if (!$this->deleteItem($key)) {
+ $result = false;
+ }
+ }
+
+ return $result;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function saveDeferred(CacheItemInterface $item): bool
+ {
+ array_push($this->buffer, $item);
+
+ return true;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function commit(): bool
+ {
+ $result = true;
+
+ foreach ($this->buffer as $item) {
+ if (!$this->save($item)) {
+ $result = false;
+ }
+ }
+
+ return $result;
+ }
+
+ private function cacheFilePath(string $key): string
+ {
+ return $this->cachePath . '/' . $key;
+ }
+
+ private function validKey(string $key): bool
+ {
+ return (bool) preg_match('|^[a-zA-Z0-9_\.]+$|', $key);
+ }
+}
diff --git a/vendor/google/auth/src/Cache/InvalidArgumentException.php b/vendor/google/auth/src/Cache/InvalidArgumentException.php
new file mode 100644
index 0000000..331e561
--- /dev/null
+++ b/vendor/google/auth/src/Cache/InvalidArgumentException.php
@@ -0,0 +1,24 @@
+getItems([$key])); // @phpstan-ignore-line
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @return iterable
+ * A traversable collection of Cache Items keyed by the cache keys of
+ * each item. A Cache item will be returned for each key, even if that
+ * key is not found. However, if no keys are specified then an empty
+ * traversable MUST be returned instead.
+ */
+ public function getItems(array $keys = []): iterable
+ {
+ $items = [];
+ foreach ($keys as $key) {
+ $items[$key] = $this->hasItem($key) ? clone $this->items[$key] : new TypedItem($key);
+ }
+
+ return $items;
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @return bool
+ * True if item exists in the cache, false otherwise.
+ */
+ public function hasItem($key): bool
+ {
+ $this->isValidKey($key);
+
+ return isset($this->items[$key]) && $this->items[$key]->isHit();
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @return bool
+ * True if the pool was successfully cleared. False if there was an error.
+ */
+ public function clear(): bool
+ {
+ $this->items = [];
+ $this->deferredItems = [];
+
+ return true;
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @return bool
+ * True if the item was successfully removed. False if there was an error.
+ */
+ public function deleteItem($key): bool
+ {
+ return $this->deleteItems([$key]);
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @return bool
+ * True if the items were successfully removed. False if there was an error.
+ */
+ public function deleteItems(array $keys): bool
+ {
+ array_walk($keys, [$this, 'isValidKey']);
+
+ foreach ($keys as $key) {
+ unset($this->items[$key]);
+ }
+
+ return true;
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @return bool
+ * True if the item was successfully persisted. False if there was an error.
+ */
+ public function save(CacheItemInterface $item): bool
+ {
+ $this->items[$item->getKey()] = $item;
+
+ return true;
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @return bool
+ * False if the item could not be queued or if a commit was attempted and failed. True otherwise.
+ */
+ public function saveDeferred(CacheItemInterface $item): bool
+ {
+ $this->deferredItems[$item->getKey()] = $item;
+
+ return true;
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @return bool
+ * True if all not-yet-saved items were successfully saved or there were none. False otherwise.
+ */
+ public function commit(): bool
+ {
+ foreach ($this->deferredItems as $item) {
+ $this->save($item);
+ }
+
+ $this->deferredItems = [];
+
+ return true;
+ }
+
+ /**
+ * Determines if the provided key is valid.
+ *
+ * @param string $key
+ * @return bool
+ * @throws InvalidArgumentException
+ */
+ private function isValidKey($key)
+ {
+ $invalidCharacters = '{}()/\\\\@:';
+
+ if (!is_string($key) || preg_match("#[$invalidCharacters]#", $key)) {
+ throw new InvalidArgumentException('The provided key is not valid: ' . var_export($key, true));
+ }
+
+ return true;
+ }
+}
diff --git a/vendor/google/auth/src/Cache/SysVCacheItemPool.php b/vendor/google/auth/src/Cache/SysVCacheItemPool.php
new file mode 100644
index 0000000..7821d6b
--- /dev/null
+++ b/vendor/google/auth/src/Cache/SysVCacheItemPool.php
@@ -0,0 +1,248 @@
+
+ */
+ private $options;
+
+ /**
+ * @var bool
+ */
+ private $hasLoadedItems = false;
+
+ /**
+ * Create a SystemV shared memory based CacheItemPool.
+ *
+ * @param array $options {
+ * [optional] Configuration options.
+ *
+ * @type int $variableKey The variable key for getting the data from the shared memory. **Defaults to** 1.
+ * @type string $proj The project identifier for ftok. This needs to be a one character string.
+ * **Defaults to** 'A'.
+ * @type int $memsize The memory size in bytes for shm_attach. **Defaults to** 10000.
+ * @type int $perm The permission for shm_attach. **Defaults to** 0600.
+ * }
+ */
+ public function __construct($options = [])
+ {
+ if (! extension_loaded('sysvshm')) {
+ throw new \RuntimeException(
+ 'sysvshm extension is required to use this ItemPool'
+ );
+ }
+ $this->options = $options + [
+ 'variableKey' => self::VAR_KEY,
+ 'proj' => self::DEFAULT_PROJ,
+ 'memsize' => self::DEFAULT_MEMSIZE,
+ 'perm' => self::DEFAULT_PERM
+ ];
+ $this->items = [];
+ $this->deferredItems = [];
+ $this->sysvKey = ftok(__FILE__, $this->options['proj']);
+ }
+
+ /**
+ * @param mixed $key
+ * @return CacheItemInterface
+ */
+ public function getItem($key): CacheItemInterface
+ {
+ $this->loadItems();
+ return current($this->getItems([$key])); // @phpstan-ignore-line
+ }
+
+ /**
+ * @param array $keys
+ * @return iterable
+ */
+ public function getItems(array $keys = []): iterable
+ {
+ $this->loadItems();
+ $items = [];
+ foreach ($keys as $key) {
+ $items[$key] = $this->hasItem($key) ?
+ clone $this->items[$key] :
+ new TypedItem($key);
+ }
+ return $items;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function hasItem($key): bool
+ {
+ $this->loadItems();
+ return isset($this->items[$key]) && $this->items[$key]->isHit();
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function clear(): bool
+ {
+ $this->items = [];
+ $this->deferredItems = [];
+ return $this->saveCurrentItems();
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function deleteItem($key): bool
+ {
+ return $this->deleteItems([$key]);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function deleteItems(array $keys): bool
+ {
+ if (!$this->hasLoadedItems) {
+ $this->loadItems();
+ }
+
+ foreach ($keys as $key) {
+ unset($this->items[$key]);
+ }
+ return $this->saveCurrentItems();
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function save(CacheItemInterface $item): bool
+ {
+ if (!$this->hasLoadedItems) {
+ $this->loadItems();
+ }
+
+ $this->items[$item->getKey()] = $item;
+ return $this->saveCurrentItems();
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function saveDeferred(CacheItemInterface $item): bool
+ {
+ $this->deferredItems[$item->getKey()] = $item;
+ return true;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function commit(): bool
+ {
+ foreach ($this->deferredItems as $item) {
+ if ($this->save($item) === false) {
+ return false;
+ }
+ }
+ $this->deferredItems = [];
+ return true;
+ }
+
+ /**
+ * Save the current items.
+ *
+ * @return bool true when success, false upon failure
+ */
+ private function saveCurrentItems()
+ {
+ $shmid = shm_attach(
+ $this->sysvKey,
+ $this->options['memsize'],
+ $this->options['perm']
+ );
+ if ($shmid !== false) {
+ $ret = shm_put_var(
+ $shmid,
+ $this->options['variableKey'],
+ $this->items
+ );
+ shm_detach($shmid);
+ return $ret;
+ }
+ return false;
+ }
+
+ /**
+ * Load the items from the shared memory.
+ *
+ * @return bool true when success, false upon failure
+ */
+ private function loadItems()
+ {
+ $shmid = shm_attach(
+ $this->sysvKey,
+ $this->options['memsize'],
+ $this->options['perm']
+ );
+ if ($shmid !== false) {
+ $data = @shm_get_var($shmid, $this->options['variableKey']);
+ if (!empty($data)) {
+ $this->items = $data;
+ } else {
+ $this->items = [];
+ }
+ shm_detach($shmid);
+ $this->hasLoadedItems = true;
+ return true;
+ }
+ return false;
+ }
+}
diff --git a/vendor/google/auth/src/Cache/TypedItem.php b/vendor/google/auth/src/Cache/TypedItem.php
new file mode 100644
index 0000000..cce6740
--- /dev/null
+++ b/vendor/google/auth/src/Cache/TypedItem.php
@@ -0,0 +1,170 @@
+key = $key;
+ $this->expiration = null;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getKey(): string
+ {
+ return $this->key;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function get(): mixed
+ {
+ return $this->isHit() ? $this->value : null;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function isHit(): bool
+ {
+ if (!$this->isHit) {
+ return false;
+ }
+
+ if ($this->expiration === null) {
+ return true;
+ }
+
+ return $this->currentTime()->getTimestamp() < $this->expiration->getTimestamp();
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function set(mixed $value): static
+ {
+ $this->isHit = true;
+ $this->value = $value;
+
+ return $this;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function expiresAt($expiration): static
+ {
+ if ($this->isValidExpiration($expiration)) {
+ $this->expiration = $expiration;
+
+ return $this;
+ }
+
+ $error = sprintf(
+ 'Argument 1 passed to %s::expiresAt() must implement interface DateTimeInterface, %s given',
+ get_class($this),
+ gettype($expiration)
+ );
+
+ throw new \TypeError($error);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function expiresAfter($time): static
+ {
+ if (is_int($time)) {
+ $this->expiration = $this->currentTime()->add(new \DateInterval("PT{$time}S"));
+ } elseif ($time instanceof \DateInterval) {
+ $this->expiration = $this->currentTime()->add($time);
+ } elseif ($time === null) {
+ $this->expiration = $time;
+ } else {
+ $message = 'Argument 1 passed to %s::expiresAfter() must be an ' .
+ 'instance of DateInterval or of the type integer, %s given';
+ $error = sprintf($message, get_class($this), gettype($time));
+
+ throw new \TypeError($error);
+ }
+
+ return $this;
+ }
+
+ /**
+ * Determines if an expiration is valid based on the rules defined by PSR6.
+ *
+ * @param mixed $expiration
+ * @return bool
+ */
+ private function isValidExpiration($expiration)
+ {
+ if ($expiration === null) {
+ return true;
+ }
+
+ // We test for two types here due to the fact the DateTimeInterface
+ // was not introduced until PHP 5.5. Checking for the DateTime type as
+ // well allows us to support 5.4.
+ if ($expiration instanceof \DateTimeInterface) {
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * @return \DateTime
+ */
+ protected function currentTime()
+ {
+ return new \DateTime('now', new \DateTimeZone('UTC'));
+ }
+}
diff --git a/vendor/google/auth/src/CacheTrait.php b/vendor/google/auth/src/CacheTrait.php
new file mode 100644
index 0000000..49aa346
--- /dev/null
+++ b/vendor/google/auth/src/CacheTrait.php
@@ -0,0 +1,110 @@
+
+ */
+ private $cacheConfig;
+
+ /**
+ * @var ?CacheItemPoolInterface
+ */
+ private $cache;
+
+ /**
+ * Gets the cached value if it is present in the cache when that is
+ * available.
+ *
+ * @param mixed $k
+ *
+ * @return mixed
+ */
+ private function getCachedValue($k)
+ {
+ if (is_null($this->cache)) {
+ return null;
+ }
+
+ $key = $this->getFullCacheKey($k);
+ if (is_null($key)) {
+ return null;
+ }
+
+ $cacheItem = $this->cache->getItem($key);
+ if ($cacheItem->isHit()) {
+ return $cacheItem->get();
+ }
+ }
+
+ /**
+ * Saves the value in the cache when that is available.
+ *
+ * @param mixed $k
+ * @param mixed $v
+ * @return mixed
+ */
+ private function setCachedValue($k, $v)
+ {
+ if (is_null($this->cache)) {
+ return null;
+ }
+
+ $key = $this->getFullCacheKey($k);
+ if (is_null($key)) {
+ return null;
+ }
+
+ $cacheItem = $this->cache->getItem($key);
+ $cacheItem->set($v);
+ $cacheItem->expiresAfter($this->cacheConfig['lifetime']);
+ return $this->cache->save($cacheItem);
+ }
+
+ /**
+ * @param null|string $key
+ * @return null|string
+ */
+ private function getFullCacheKey($key)
+ {
+ if (is_null($key)) {
+ return null;
+ }
+
+ $key = ($this->cacheConfig['prefix'] ?? '') . $key;
+
+ // ensure we do not have illegal characters
+ $key = preg_replace('|[^a-zA-Z0-9_\.!]|', '', $key);
+
+ // Hash keys if they exceed $maxKeyLength (defaults to 64)
+ if ($this->maxKeyLength && strlen($key) > $this->maxKeyLength) {
+ $key = substr(hash('sha256', $key), 0, $this->maxKeyLength);
+ }
+
+ return $key;
+ }
+}
diff --git a/vendor/google/auth/src/CredentialSource/AwsNativeSource.php b/vendor/google/auth/src/CredentialSource/AwsNativeSource.php
new file mode 100644
index 0000000..c4113f7
--- /dev/null
+++ b/vendor/google/auth/src/CredentialSource/AwsNativeSource.php
@@ -0,0 +1,375 @@
+audience = $audience;
+ $this->regionalCredVerificationUrl = $regionalCredVerificationUrl;
+ $this->regionUrl = $regionUrl;
+ $this->securityCredentialsUrl = $securityCredentialsUrl;
+ $this->imdsv2SessionTokenUrl = $imdsv2SessionTokenUrl;
+ }
+
+ public function fetchSubjectToken(?callable $httpHandler = null): string
+ {
+ if (is_null($httpHandler)) {
+ $httpHandler = HttpHandlerFactory::build(HttpClientCache::getHttpClient());
+ }
+
+ $headers = [];
+ if ($this->imdsv2SessionTokenUrl) {
+ $headers = [
+ 'X-aws-ec2-metadata-token' => self::getImdsV2SessionToken($this->imdsv2SessionTokenUrl, $httpHandler)
+ ];
+ }
+
+ if (!$signingVars = self::getSigningVarsFromEnv()) {
+ if (!$this->securityCredentialsUrl) {
+ throw new \LogicException('Unable to get credentials from ENV, and no security credentials URL provided');
+ }
+ $signingVars = self::getSigningVarsFromUrl(
+ $httpHandler,
+ $this->securityCredentialsUrl,
+ self::getRoleName($httpHandler, $this->securityCredentialsUrl, $headers),
+ $headers
+ );
+ }
+
+ if (!$region = self::getRegionFromEnv()) {
+ if (!$this->regionUrl) {
+ throw new \LogicException('Unable to get region from ENV, and no region URL provided');
+ }
+ $region = self::getRegionFromUrl($httpHandler, $this->regionUrl, $headers);
+ }
+ $url = str_replace('{region}', $region, $this->regionalCredVerificationUrl);
+ $host = parse_url($url)['host'] ?? '';
+
+ // From here we use the signing vars to create the signed request to receive a token
+ [$accessKeyId, $secretAccessKey, $securityToken] = $signingVars;
+ $headers = self::getSignedRequestHeaders($region, $host, $accessKeyId, $secretAccessKey, $securityToken);
+
+ // Inject x-goog-cloud-target-resource into header
+ $headers['x-goog-cloud-target-resource'] = $this->audience;
+
+ // Format headers as they're expected in the subject token
+ $formattedHeaders = array_map(
+ fn ($k, $v) => ['key' => $k, 'value' => $v],
+ array_keys($headers),
+ $headers,
+ );
+
+ $request = [
+ 'headers' => $formattedHeaders,
+ 'method' => 'POST',
+ 'url' => $url,
+ ];
+
+ return urlencode(json_encode($request) ?: '');
+ }
+
+ /**
+ * @internal
+ */
+ public static function getImdsV2SessionToken(string $imdsV2Url, callable $httpHandler): string
+ {
+ $headers = [
+ 'X-aws-ec2-metadata-token-ttl-seconds' => '21600'
+ ];
+ $request = new Request(
+ 'PUT',
+ $imdsV2Url,
+ $headers
+ );
+
+ $response = $httpHandler($request);
+ return (string) $response->getBody();
+ }
+
+ /**
+ * @see http://docs.aws.amazon.com/general/latest/gr/sigv4-create-canonical-request.html
+ *
+ * @internal
+ *
+ * @return array
+ */
+ public static function getSignedRequestHeaders(
+ string $region,
+ string $host,
+ string $accessKeyId,
+ string $secretAccessKey,
+ ?string $securityToken
+ ): array {
+ $service = 'sts';
+
+ # Create a date for headers and the credential string in ISO-8601 format
+ $amzdate = gmdate('Ymd\THis\Z');
+ $datestamp = gmdate('Ymd'); # Date w/o time, used in credential scope
+
+ # Create the canonical headers and signed headers. Header names
+ # must be trimmed and lowercase, and sorted in code point order from
+ # low to high. Note that there is a trailing \n.
+ $canonicalHeaders = sprintf("host:%s\nx-amz-date:%s\n", $host, $amzdate);
+ if ($securityToken) {
+ $canonicalHeaders .= sprintf("x-amz-security-token:%s\n", $securityToken);
+ }
+
+ # Step 5: Create the list of signed headers. This lists the headers
+ # in the canonicalHeaders list, delimited with ";" and in alpha order.
+ # Note: The request can include any headers; $canonicalHeaders and
+ # $signedHeaders lists those that you want to be included in the
+ # hash of the request. "Host" and "x-amz-date" are always required.
+ $signedHeaders = 'host;x-amz-date';
+ if ($securityToken) {
+ $signedHeaders .= ';x-amz-security-token';
+ }
+
+ # Step 6: Create payload hash (hash of the request body content). For GET
+ # requests, the payload is an empty string ("").
+ $payloadHash = hash('sha256', '');
+
+ # Step 7: Combine elements to create canonical request
+ $canonicalRequest = implode("\n", [
+ 'POST', // method
+ '/', // canonical URL
+ self::CRED_VERIFICATION_QUERY, // query string
+ $canonicalHeaders,
+ $signedHeaders,
+ $payloadHash
+ ]);
+
+ # ************* TASK 2: CREATE THE STRING TO SIGN*************
+ # Match the algorithm to the hashing algorithm you use, either SHA-1 or
+ # SHA-256 (recommended)
+ $algorithm = 'AWS4-HMAC-SHA256';
+ $scope = implode('/', [$datestamp, $region, $service, 'aws4_request']);
+ $stringToSign = implode("\n", [$algorithm, $amzdate, $scope, hash('sha256', $canonicalRequest)]);
+
+ # ************* TASK 3: CALCULATE THE SIGNATURE *************
+ # Create the signing key using the function defined above.
+ // (done above)
+ $signingKey = self::getSignatureKey($secretAccessKey, $datestamp, $region, $service);
+
+ # Sign the string_to_sign using the signing_key
+ $signature = bin2hex(self::hmacSign($signingKey, $stringToSign));
+
+ # ************* TASK 4: ADD SIGNING INFORMATION TO THE REQUEST *************
+ # The signing information can be either in a query string value or in
+ # a header named Authorization. This code shows how to use a header.
+ # Create authorization header and add to request headers
+ $authorizationHeader = sprintf(
+ '%s Credential=%s/%s, SignedHeaders=%s, Signature=%s',
+ $algorithm,
+ $accessKeyId,
+ $scope,
+ $signedHeaders,
+ $signature
+ );
+
+ # The request can include any headers, but MUST include "host", "x-amz-date",
+ # and (for this scenario) "Authorization". "host" and "x-amz-date" must
+ # be included in the canonical_headers and signed_headers, as noted
+ # earlier. Order here is not significant.
+ $headers = [
+ 'host' => $host,
+ 'x-amz-date' => $amzdate,
+ 'Authorization' => $authorizationHeader,
+ ];
+ if ($securityToken) {
+ $headers['x-amz-security-token'] = $securityToken;
+ }
+
+ return $headers;
+ }
+
+ /**
+ * @internal
+ */
+ public static function getRegionFromEnv(): ?string
+ {
+ $region = getenv('AWS_REGION');
+ if (empty($region)) {
+ $region = getenv('AWS_DEFAULT_REGION');
+ }
+ return $region ?: null;
+ }
+
+ /**
+ * @internal
+ *
+ * @param callable $httpHandler
+ * @param string $regionUrl
+ * @param array $headers Request headers to send in with the request.
+ */
+ public static function getRegionFromUrl(callable $httpHandler, string $regionUrl, array $headers): string
+ {
+ // get the region/zone from the region URL
+ $regionRequest = new Request('GET', $regionUrl, $headers);
+ $regionResponse = $httpHandler($regionRequest);
+
+ // Remove last character. For example, if us-east-2b is returned,
+ // the region would be us-east-2.
+ return substr((string) $regionResponse->getBody(), 0, -1);
+ }
+
+ /**
+ * @internal
+ *
+ * @param callable $httpHandler
+ * @param string $securityCredentialsUrl
+ * @param array $headers Request headers to send in with the request.
+ */
+ public static function getRoleName(callable $httpHandler, string $securityCredentialsUrl, array $headers): string
+ {
+ // Get the AWS role name
+ $roleRequest = new Request('GET', $securityCredentialsUrl, $headers);
+ $roleResponse = $httpHandler($roleRequest);
+ $roleName = (string) $roleResponse->getBody();
+
+ return $roleName;
+ }
+
+ /**
+ * @internal
+ *
+ * @param callable $httpHandler
+ * @param string $securityCredentialsUrl
+ * @param array $headers Request headers to send in with the request.
+ * @return array{string, string, ?string}
+ */
+ public static function getSigningVarsFromUrl(
+ callable $httpHandler,
+ string $securityCredentialsUrl,
+ string $roleName,
+ array $headers
+ ): array {
+ // Get the AWS credentials
+ $credsRequest = new Request(
+ 'GET',
+ $securityCredentialsUrl . '/' . $roleName,
+ $headers
+ );
+ $credsResponse = $httpHandler($credsRequest);
+ $awsCreds = json_decode((string) $credsResponse->getBody(), true);
+ return [
+ $awsCreds['AccessKeyId'], // accessKeyId
+ $awsCreds['SecretAccessKey'], // secretAccessKey
+ $awsCreds['Token'], // token
+ ];
+ }
+
+ /**
+ * @internal
+ *
+ * @return array{string, string, ?string}
+ */
+ public static function getSigningVarsFromEnv(): ?array
+ {
+ $accessKeyId = getenv('AWS_ACCESS_KEY_ID');
+ $secretAccessKey = getenv('AWS_SECRET_ACCESS_KEY');
+ if ($accessKeyId && $secretAccessKey) {
+ return [
+ $accessKeyId,
+ $secretAccessKey,
+ getenv('AWS_SESSION_TOKEN') ?: null, // session token (can be null)
+ ];
+ }
+
+ return null;
+ }
+
+ /**
+ * Gets the unique key for caching
+ * For AwsNativeSource the values are:
+ * Imdsv2SessionTokenUrl.SecurityCredentialsUrl.RegionUrl.RegionalCredVerificationUrl
+ *
+ * @return string
+ */
+ public function getCacheKey(): string
+ {
+ return ($this->imdsv2SessionTokenUrl ?? '') .
+ '.' . ($this->securityCredentialsUrl ?? '') .
+ '.' . $this->regionUrl .
+ '.' . $this->regionalCredVerificationUrl;
+ }
+
+ /**
+ * Return HMAC hash in binary string
+ */
+ private static function hmacSign(string $key, string $msg): string
+ {
+ return hash_hmac('sha256', self::utf8Encode($msg), $key, true);
+ }
+
+ /**
+ * @TODO add a fallback when mbstring is not available
+ */
+ private static function utf8Encode(string $string): string
+ {
+ return (string) mb_convert_encoding($string, 'UTF-8', 'ISO-8859-1');
+ }
+
+ private static function getSignatureKey(
+ string $key,
+ string $dateStamp,
+ string $regionName,
+ string $serviceName
+ ): string {
+ $kDate = self::hmacSign(self::utf8Encode('AWS4' . $key), $dateStamp);
+ $kRegion = self::hmacSign($kDate, $regionName);
+ $kService = self::hmacSign($kRegion, $serviceName);
+ $kSigning = self::hmacSign($kService, 'aws4_request');
+
+ return $kSigning;
+ }
+}
diff --git a/vendor/google/auth/src/CredentialSource/ExecutableSource.php b/vendor/google/auth/src/CredentialSource/ExecutableSource.php
new file mode 100644
index 0000000..f6255be
--- /dev/null
+++ b/vendor/google/auth/src/CredentialSource/ExecutableSource.php
@@ -0,0 +1,272 @@
+
+ * OIDC response sample:
+ * {
+ * "version": 1,
+ * "success": true,
+ * "token_type": "urn:ietf:params:oauth:token-type:id_token",
+ * "id_token": "HEADER.PAYLOAD.SIGNATURE",
+ * "expiration_time": 1620433341
+ * }
+ *
+ * SAML2 response sample:
+ * {
+ * "version": 1,
+ * "success": true,
+ * "token_type": "urn:ietf:params:oauth:token-type:saml2",
+ * "saml_response": "...",
+ * "expiration_time": 1620433341
+ * }
+ *
+ * Error response sample:
+ * {
+ * "version": 1,
+ * "success": false,
+ * "code": "401",
+ * "message": "Error message."
+ * }
+ *
+ *
+ * The "expiration_time" field in the JSON response is only required for successful
+ * responses when an output file was specified in the credential configuration
+ *
+ * The auth libraries will populate certain environment variables that will be accessible by the
+ * executable, such as: GOOGLE_EXTERNAL_ACCOUNT_AUDIENCE, GOOGLE_EXTERNAL_ACCOUNT_TOKEN_TYPE,
+ * GOOGLE_EXTERNAL_ACCOUNT_INTERACTIVE, GOOGLE_EXTERNAL_ACCOUNT_IMPERSONATED_EMAIL, and
+ * GOOGLE_EXTERNAL_ACCOUNT_OUTPUT_FILE.
+ */
+class ExecutableSource implements ExternalAccountCredentialSourceInterface
+{
+ private const GOOGLE_EXTERNAL_ACCOUNT_ALLOW_EXECUTABLES = 'GOOGLE_EXTERNAL_ACCOUNT_ALLOW_EXECUTABLES';
+ private const SAML_SUBJECT_TOKEN_TYPE = 'urn:ietf:params:oauth:token-type:saml2';
+ private const OIDC_SUBJECT_TOKEN_TYPE1 = 'urn:ietf:params:oauth:token-type:id_token';
+ private const OIDC_SUBJECT_TOKEN_TYPE2 = 'urn:ietf:params:oauth:token-type:jwt';
+
+ private string $command;
+ private ExecutableHandler $executableHandler;
+ private ?string $outputFile;
+
+ /**
+ * @param string $command The string command to run to get the subject token.
+ * @param string|null $outputFile
+ */
+ public function __construct(
+ string $command,
+ ?string $outputFile,
+ ?ExecutableHandler $executableHandler = null,
+ ) {
+ $this->command = $command;
+ $this->outputFile = $outputFile;
+ $this->executableHandler = $executableHandler ?: new ExecutableHandler();
+ }
+
+ /**
+ * Gets the unique key for caching
+ * The format for the cache key is:
+ * Command.OutputFile
+ *
+ * @return ?string
+ */
+ public function getCacheKey(): ?string
+ {
+ return $this->command . '.' . $this->outputFile;
+ }
+
+ /**
+ * @param callable|null $httpHandler unused.
+ * @return string
+ * @throws RuntimeException if the executable is not allowed to run.
+ * @throws ExecutableResponseError if the executable response is invalid.
+ */
+ public function fetchSubjectToken(?callable $httpHandler = null): string
+ {
+ // Check if the executable is allowed to run.
+ if (getenv(self::GOOGLE_EXTERNAL_ACCOUNT_ALLOW_EXECUTABLES) !== '1') {
+ throw new RuntimeException(
+ 'Pluggable Auth executables need to be explicitly allowed to run by '
+ . 'setting the GOOGLE_EXTERNAL_ACCOUNT_ALLOW_EXECUTABLES environment '
+ . 'Variable to 1.'
+ );
+ }
+
+ if (!$executableResponse = $this->getCachedExecutableResponse()) {
+ // Run the executable.
+ $exitCode = ($this->executableHandler)($this->command);
+ $output = $this->executableHandler->getOutput();
+
+ // If the exit code is not 0, throw an exception with the output as the error details
+ if ($exitCode !== 0) {
+ throw new ExecutableResponseError(
+ 'The executable failed to run'
+ . ($output ? ' with the following error: ' . $output : '.'),
+ (string) $exitCode
+ );
+ }
+
+ $executableResponse = $this->parseExecutableResponse($output);
+
+ // Validate expiration.
+ if (isset($executableResponse['expiration_time']) && time() >= $executableResponse['expiration_time']) {
+ throw new ExecutableResponseError('Executable response is expired.');
+ }
+ }
+
+ // Throw error when the request was unsuccessful
+ if ($executableResponse['success'] === false) {
+ throw new ExecutableResponseError($executableResponse['message'], (string) $executableResponse['code']);
+ }
+
+ // Return subject token field based on the token type
+ return $executableResponse['token_type'] === self::SAML_SUBJECT_TOKEN_TYPE
+ ? $executableResponse['saml_response']
+ : $executableResponse['id_token'];
+ }
+
+ /**
+ * @return array|null
+ */
+ private function getCachedExecutableResponse(): ?array
+ {
+ if (
+ $this->outputFile
+ && file_exists($this->outputFile)
+ && !empty(trim($outputFileContents = (string) file_get_contents($this->outputFile)))
+ ) {
+ try {
+ $executableResponse = $this->parseExecutableResponse($outputFileContents);
+ } catch (ExecutableResponseError $e) {
+ throw new ExecutableResponseError(
+ 'Error in output file: ' . $e->getMessage(),
+ 'INVALID_OUTPUT_FILE'
+ );
+ }
+
+ if ($executableResponse['success'] === false) {
+ // If the cached token was unsuccessful, run the executable to get a new one.
+ return null;
+ }
+
+ if (isset($executableResponse['expiration_time']) && time() >= $executableResponse['expiration_time']) {
+ // If the cached token is expired, run the executable to get a new one.
+ return null;
+ }
+
+ return $executableResponse;
+ }
+
+ return null;
+ }
+
+ /**
+ * @return array
+ */
+ private function parseExecutableResponse(string $response): array
+ {
+ $executableResponse = json_decode($response, true);
+ if (json_last_error() !== JSON_ERROR_NONE) {
+ throw new ExecutableResponseError(
+ 'The executable returned an invalid response: ' . $response,
+ 'INVALID_RESPONSE'
+ );
+ }
+ if (!array_key_exists('version', $executableResponse)) {
+ throw new ExecutableResponseError('Executable response must contain a "version" field.');
+ }
+ if (!array_key_exists('success', $executableResponse)) {
+ throw new ExecutableResponseError('Executable response must contain a "success" field.');
+ }
+
+ // Validate required fields for a successful response.
+ if ($executableResponse['success']) {
+ // Validate token type field.
+ $tokenTypes = [self::SAML_SUBJECT_TOKEN_TYPE, self::OIDC_SUBJECT_TOKEN_TYPE1, self::OIDC_SUBJECT_TOKEN_TYPE2];
+ if (!isset($executableResponse['token_type'])) {
+ throw new ExecutableResponseError(
+ 'Executable response must contain a "token_type" field when successful'
+ );
+ }
+ if (!in_array($executableResponse['token_type'], $tokenTypes)) {
+ throw new ExecutableResponseError(sprintf(
+ 'Executable response "token_type" field must be one of %s.',
+ implode(', ', $tokenTypes)
+ ));
+ }
+
+ // Validate subject token for SAML and OIDC.
+ if ($executableResponse['token_type'] === self::SAML_SUBJECT_TOKEN_TYPE) {
+ if (empty($executableResponse['saml_response'])) {
+ throw new ExecutableResponseError(sprintf(
+ 'Executable response must contain a "saml_response" field when token_type=%s.',
+ self::SAML_SUBJECT_TOKEN_TYPE
+ ));
+ }
+ } elseif (empty($executableResponse['id_token'])) {
+ throw new ExecutableResponseError(sprintf(
+ 'Executable response must contain a "id_token" field when '
+ . 'token_type=%s.',
+ $executableResponse['token_type']
+ ));
+ }
+
+ // Validate expiration exists when an output file is specified.
+ if ($this->outputFile) {
+ if (!isset($executableResponse['expiration_time'])) {
+ throw new ExecutableResponseError(
+ 'The executable response must contain a "expiration_time" field for successful responses ' .
+ 'when an output_file has been specified in the configuration.'
+ );
+ }
+ }
+ } else {
+ // Both code and message must be provided for unsuccessful responses.
+ if (!array_key_exists('code', $executableResponse)) {
+ throw new ExecutableResponseError('Executable response must contain a "code" field when unsuccessful.');
+ }
+ if (empty($executableResponse['message'])) {
+ throw new ExecutableResponseError('Executable response must contain a "message" field when unsuccessful.');
+ }
+ }
+
+ return $executableResponse;
+ }
+}
diff --git a/vendor/google/auth/src/CredentialSource/FileSource.php b/vendor/google/auth/src/CredentialSource/FileSource.php
new file mode 100644
index 0000000..2e79119
--- /dev/null
+++ b/vendor/google/auth/src/CredentialSource/FileSource.php
@@ -0,0 +1,87 @@
+file = $file;
+
+ if ($format === 'json' && is_null($subjectTokenFieldName)) {
+ throw new InvalidArgumentException(
+ 'subject_token_field_name must be set when format is JSON'
+ );
+ }
+
+ $this->format = $format;
+ $this->subjectTokenFieldName = $subjectTokenFieldName;
+ }
+
+ public function fetchSubjectToken(?callable $httpHandler = null): string
+ {
+ $contents = file_get_contents($this->file);
+ if ($this->format === 'json') {
+ if (!$json = json_decode((string) $contents, true)) {
+ throw new UnexpectedValueException(
+ 'Unable to decode JSON file'
+ );
+ }
+ if (!isset($json[$this->subjectTokenFieldName])) {
+ throw new UnexpectedValueException(
+ 'subject_token_field_name not found in JSON file'
+ );
+ }
+ $contents = $json[$this->subjectTokenFieldName];
+ }
+
+ return $contents;
+ }
+
+ /**
+ * Gets the unique key for caching.
+ * The format for the cache key one of the following:
+ * Filename
+ *
+ * @return string
+ */
+ public function getCacheKey(): ?string
+ {
+ return $this->file;
+ }
+}
diff --git a/vendor/google/auth/src/CredentialSource/UrlSource.php b/vendor/google/auth/src/CredentialSource/UrlSource.php
new file mode 100644
index 0000000..d2f875e
--- /dev/null
+++ b/vendor/google/auth/src/CredentialSource/UrlSource.php
@@ -0,0 +1,109 @@
+
+ */
+ private ?array $headers;
+
+ /**
+ * @param string $url The URL to fetch the subject token from.
+ * @param string|null $format The format of the token in the response. Can be null or "json".
+ * @param string|null $subjectTokenFieldName The name of the field containing the token in the response. This is required
+ * when format is "json".
+ * @param array|null $headers Request headers to send in with the request to the URL.
+ */
+ public function __construct(
+ string $url,
+ ?string $format = null,
+ ?string $subjectTokenFieldName = null,
+ ?array $headers = null
+ ) {
+ $this->url = $url;
+
+ if ($format === 'json' && is_null($subjectTokenFieldName)) {
+ throw new InvalidArgumentException(
+ 'subject_token_field_name must be set when format is JSON'
+ );
+ }
+
+ $this->format = $format;
+ $this->subjectTokenFieldName = $subjectTokenFieldName;
+ $this->headers = $headers;
+ }
+
+ public function fetchSubjectToken(?callable $httpHandler = null): string
+ {
+ if (is_null($httpHandler)) {
+ $httpHandler = HttpHandlerFactory::build(HttpClientCache::getHttpClient());
+ }
+
+ $request = new Request(
+ 'GET',
+ $this->url,
+ $this->headers ?: []
+ );
+
+ $response = $httpHandler($request);
+ $body = (string) $response->getBody();
+ if ($this->format === 'json') {
+ if (!$json = json_decode((string) $body, true)) {
+ throw new UnexpectedValueException(
+ 'Unable to decode JSON response'
+ );
+ }
+ if (!isset($json[$this->subjectTokenFieldName])) {
+ throw new UnexpectedValueException(
+ 'subject_token_field_name not found in JSON file'
+ );
+ }
+ $body = $json[$this->subjectTokenFieldName];
+ }
+
+ return $body;
+ }
+
+ /**
+ * Get the cache key for the credentials.
+ * The format for the cache key is:
+ * URL
+ *
+ * @return ?string
+ */
+ public function getCacheKey(): ?string
+ {
+ return $this->url;
+ }
+}
diff --git a/vendor/google/auth/src/Credentials/AppIdentityCredentials.php b/vendor/google/auth/src/Credentials/AppIdentityCredentials.php
new file mode 100644
index 0000000..5e4cfa5
--- /dev/null
+++ b/vendor/google/auth/src/Credentials/AppIdentityCredentials.php
@@ -0,0 +1,238 @@
+push($middleware);
+ *
+ * $client = new Client([
+ * 'handler' => $stack,
+ * 'base_uri' => 'https://www.googleapis.com/books/v1',
+ * 'auth' => 'google_auth'
+ * ]);
+ *
+ * $res = $client->get('volumes?q=Henry+David+Thoreau&country=US');
+ * ```
+ */
+class AppIdentityCredentials extends CredentialsLoader implements
+ SignBlobInterface,
+ ProjectIdProviderInterface
+{
+ /**
+ * Result of fetchAuthToken.
+ *
+ * @var array
+ */
+ protected $lastReceivedToken;
+
+ /**
+ * Array of OAuth2 scopes to be requested.
+ *
+ * @var string[]
+ */
+ private $scope;
+
+ /**
+ * @var string
+ */
+ private $clientName;
+
+ /**
+ * @param string|string[] $scope One or more scopes.
+ */
+ public function __construct($scope = [])
+ {
+ $this->scope = is_array($scope) ? $scope : explode(' ', (string) $scope);
+ }
+
+ /**
+ * Determines if this an App Engine instance, by accessing the
+ * SERVER_SOFTWARE environment variable (prod) or the APPENGINE_RUNTIME
+ * environment variable (dev).
+ *
+ * @return bool true if this an App Engine Instance, false otherwise
+ */
+ public static function onAppEngine()
+ {
+ $appEngineProduction = isset($_SERVER['SERVER_SOFTWARE']) &&
+ 0 === strpos($_SERVER['SERVER_SOFTWARE'], 'Google App Engine');
+ if ($appEngineProduction) {
+ return true;
+ }
+ $appEngineDevAppServer = isset($_SERVER['APPENGINE_RUNTIME']) &&
+ $_SERVER['APPENGINE_RUNTIME'] == 'php';
+ if ($appEngineDevAppServer) {
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Implements FetchAuthTokenInterface#fetchAuthToken.
+ *
+ * Fetches the auth tokens using the AppIdentityService if available.
+ * As the AppIdentityService uses protobufs to fetch the access token,
+ * the GuzzleHttp\ClientInterface instance passed in will not be used.
+ *
+ * @param callable|null $httpHandler callback which delivers psr7 request
+ * @return array {
+ * A set of auth related metadata, containing the following
+ *
+ * @type string $access_token
+ * @type string $expiration_time
+ * }
+ */
+ public function fetchAuthToken(?callable $httpHandler = null)
+ {
+ try {
+ $this->checkAppEngineContext();
+ } catch (\Exception $e) {
+ return [];
+ }
+
+ /** @phpstan-ignore-next-line */
+ $token = AppIdentityService::getAccessToken($this->scope);
+ $this->lastReceivedToken = $token;
+
+ return $token;
+ }
+
+ /**
+ * Sign a string using AppIdentityService.
+ *
+ * @param string $stringToSign The string to sign.
+ * @param bool $forceOpenSsl [optional] Does not apply to this credentials
+ * type.
+ * @return string The signature, base64-encoded.
+ * @throws \Exception If AppEngine SDK or mock is not available.
+ */
+ public function signBlob($stringToSign, $forceOpenSsl = false)
+ {
+ $this->checkAppEngineContext();
+
+ /** @phpstan-ignore-next-line */
+ return base64_encode(AppIdentityService::signForApp($stringToSign)['signature']);
+ }
+
+ /**
+ * Get the project ID from AppIdentityService.
+ *
+ * Returns null if AppIdentityService is unavailable.
+ *
+ * @param callable|null $httpHandler Not used by this type.
+ * @return string|null
+ */
+ public function getProjectId(?callable $httpHandler = null)
+ {
+ try {
+ $this->checkAppEngineContext();
+ } catch (\Exception $e) {
+ return null;
+ }
+
+ /** @phpstan-ignore-next-line */
+ return AppIdentityService::getApplicationId();
+ }
+
+ /**
+ * Get the client name from AppIdentityService.
+ *
+ * Subsequent calls to this method will return a cached value.
+ *
+ * @param callable|null $httpHandler Not used in this implementation.
+ * @return string
+ * @throws \Exception If AppEngine SDK or mock is not available.
+ */
+ public function getClientName(?callable $httpHandler = null)
+ {
+ $this->checkAppEngineContext();
+
+ if (!$this->clientName) {
+ /** @phpstan-ignore-next-line */
+ $this->clientName = AppIdentityService::getServiceAccountName();
+ }
+
+ return $this->clientName;
+ }
+
+ /**
+ * @return array{access_token:string,expires_at:int}|null
+ */
+ public function getLastReceivedToken()
+ {
+ if ($this->lastReceivedToken) {
+ return [
+ 'access_token' => $this->lastReceivedToken['access_token'],
+ 'expires_at' => $this->lastReceivedToken['expiration_time'],
+ ];
+ }
+
+ return null;
+ }
+
+ /**
+ * Caching is handled by the underlying AppIdentityService, return empty string
+ * to prevent caching.
+ *
+ * @return string
+ */
+ public function getCacheKey()
+ {
+ return '';
+ }
+
+ /**
+ * @return void
+ */
+ private function checkAppEngineContext()
+ {
+ if (!self::onAppEngine() || !class_exists('google\appengine\api\app_identity\AppIdentityService')) {
+ throw new \Exception(
+ 'This class must be run in App Engine, or you must include the AppIdentityService '
+ . 'mock class defined in tests/mocks/AppIdentityService.php'
+ );
+ }
+ }
+}
diff --git a/vendor/google/auth/src/Credentials/ExternalAccountCredentials.php b/vendor/google/auth/src/Credentials/ExternalAccountCredentials.php
new file mode 100644
index 0000000..afaf1ee
--- /dev/null
+++ b/vendor/google/auth/src/Credentials/ExternalAccountCredentials.php
@@ -0,0 +1,394 @@
+ */
+ private ?array $lastImpersonatedAccessToken;
+ private string $universeDomain;
+
+ /**
+ * @param string|string[] $scope The scope of the access request, expressed either as an array
+ * or as a space-delimited string.
+ * @param array $jsonKey JSON credentials as an associative array.
+ */
+ public function __construct(
+ $scope,
+ array $jsonKey
+ ) {
+ if (!array_key_exists('type', $jsonKey)) {
+ throw new InvalidArgumentException('json key is missing the type field');
+ }
+ if ($jsonKey['type'] !== self::EXTERNAL_ACCOUNT_TYPE) {
+ throw new InvalidArgumentException(sprintf(
+ 'expected "%s" type but received "%s"',
+ self::EXTERNAL_ACCOUNT_TYPE,
+ $jsonKey['type']
+ ));
+ }
+
+ if (!array_key_exists('token_url', $jsonKey)) {
+ throw new InvalidArgumentException(
+ 'json key is missing the token_url field'
+ );
+ }
+
+ if (!array_key_exists('audience', $jsonKey)) {
+ throw new InvalidArgumentException(
+ 'json key is missing the audience field'
+ );
+ }
+
+ if (!array_key_exists('subject_token_type', $jsonKey)) {
+ throw new InvalidArgumentException(
+ 'json key is missing the subject_token_type field'
+ );
+ }
+
+ if (!array_key_exists('credential_source', $jsonKey)) {
+ throw new InvalidArgumentException(
+ 'json key is missing the credential_source field'
+ );
+ }
+
+ $this->serviceAccountImpersonationUrl = $jsonKey['service_account_impersonation_url'] ?? null;
+
+ $this->quotaProject = $jsonKey['quota_project_id'] ?? null;
+ $this->workforcePoolUserProject = $jsonKey['workforce_pool_user_project'] ?? null;
+ $this->universeDomain = $jsonKey['universe_domain'] ?? GetUniverseDomainInterface::DEFAULT_UNIVERSE_DOMAIN;
+
+ $this->auth = new OAuth2([
+ 'tokenCredentialUri' => $jsonKey['token_url'],
+ 'audience' => $jsonKey['audience'],
+ 'scope' => $scope,
+ 'subjectTokenType' => $jsonKey['subject_token_type'],
+ 'subjectTokenFetcher' => self::buildCredentialSource($jsonKey),
+ 'additionalOptions' => $this->workforcePoolUserProject
+ ? ['userProject' => $this->workforcePoolUserProject]
+ : [],
+ ]);
+
+ if (!$this->isWorkforcePool() && $this->workforcePoolUserProject) {
+ throw new InvalidArgumentException(
+ 'workforce_pool_user_project should not be set for non-workforce pool credentials.'
+ );
+ }
+ }
+
+ /**
+ * @param array $jsonKey
+ */
+ private static function buildCredentialSource(array $jsonKey): ExternalAccountCredentialSourceInterface
+ {
+ $credentialSource = $jsonKey['credential_source'];
+ if (isset($credentialSource['file'])) {
+ return new FileSource(
+ $credentialSource['file'],
+ $credentialSource['format']['type'] ?? null,
+ $credentialSource['format']['subject_token_field_name'] ?? null
+ );
+ }
+
+ if (
+ isset($credentialSource['environment_id'])
+ && 1 === preg_match('/^aws(\d+)$/', $credentialSource['environment_id'], $matches)
+ ) {
+ if ($matches[1] !== '1') {
+ throw new InvalidArgumentException(
+ "aws version \"$matches[1]\" is not supported in the current build."
+ );
+ }
+ if (!array_key_exists('regional_cred_verification_url', $credentialSource)) {
+ throw new InvalidArgumentException(
+ 'The regional_cred_verification_url field is required for aws1 credential source.'
+ );
+ }
+
+ return new AwsNativeSource(
+ $jsonKey['audience'],
+ $credentialSource['regional_cred_verification_url'], // $regionalCredVerificationUrl
+ $credentialSource['region_url'] ?? null, // $regionUrl
+ $credentialSource['url'] ?? null, // $securityCredentialsUrl
+ $credentialSource['imdsv2_session_token_url'] ?? null, // $imdsV2TokenUrl
+ );
+ }
+
+ if (isset($credentialSource['url'])) {
+ return new UrlSource(
+ $credentialSource['url'],
+ $credentialSource['format']['type'] ?? null,
+ $credentialSource['format']['subject_token_field_name'] ?? null,
+ $credentialSource['headers'] ?? null,
+ );
+ }
+
+ if (isset($credentialSource['executable'])) {
+ if (!array_key_exists('command', $credentialSource['executable'])) {
+ throw new InvalidArgumentException(
+ 'executable source requires a command to be set in the JSON file.'
+ );
+ }
+
+ // Build command environment variables
+ $env = [
+ 'GOOGLE_EXTERNAL_ACCOUNT_AUDIENCE' => $jsonKey['audience'],
+ 'GOOGLE_EXTERNAL_ACCOUNT_TOKEN_TYPE' => $jsonKey['subject_token_type'],
+ // Always set to 0 because interactive mode is not supported.
+ 'GOOGLE_EXTERNAL_ACCOUNT_INTERACTIVE' => '0',
+ ];
+
+ if ($outputFile = $credentialSource['executable']['output_file'] ?? null) {
+ $env['GOOGLE_EXTERNAL_ACCOUNT_OUTPUT_FILE'] = $outputFile;
+ }
+
+ if ($serviceAccountImpersonationUrl = $jsonKey['service_account_impersonation_url'] ?? null) {
+ // Parse email from URL. The formal looks as follows:
+ // https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/name@project-id.iam.gserviceaccount.com:generateAccessToken
+ $regex = '/serviceAccounts\/(?[^:]+):generateAccessToken$/';
+ if (preg_match($regex, $serviceAccountImpersonationUrl, $matches)) {
+ $env['GOOGLE_EXTERNAL_ACCOUNT_IMPERSONATED_EMAIL'] = $matches['email'];
+ }
+ }
+
+ $timeoutMs = $credentialSource['executable']['timeout_millis'] ?? null;
+
+ return new ExecutableSource(
+ $credentialSource['executable']['command'],
+ $outputFile,
+ $timeoutMs ? new ExecutableHandler($env, $timeoutMs) : new ExecutableHandler($env)
+ );
+ }
+
+ throw new InvalidArgumentException('Unable to determine credential source from json key.');
+ }
+
+ /**
+ * @param string $stsToken
+ * @param callable|null $httpHandler
+ *
+ * @return array {
+ * A set of auth related metadata, containing the following
+ *
+ * @type string $access_token
+ * @type int $expires_at
+ * }
+ */
+ private function getImpersonatedAccessToken(string $stsToken, ?callable $httpHandler = null): array
+ {
+ if (!isset($this->serviceAccountImpersonationUrl)) {
+ throw new InvalidArgumentException(
+ 'service_account_impersonation_url must be set in JSON credentials.'
+ );
+ }
+ $request = new Request(
+ 'POST',
+ $this->serviceAccountImpersonationUrl,
+ [
+ 'Content-Type' => 'application/json',
+ 'Authorization' => 'Bearer ' . $stsToken,
+ ],
+ (string) json_encode([
+ 'lifetime' => sprintf('%ss', OAuth2::DEFAULT_EXPIRY_SECONDS),
+ 'scope' => explode(' ', $this->auth->getScope()),
+ ]),
+ );
+ if (is_null($httpHandler)) {
+ $httpHandler = HttpHandlerFactory::build(HttpClientCache::getHttpClient());
+ }
+ $response = $httpHandler($request);
+ $body = json_decode((string) $response->getBody(), true);
+ return [
+ 'access_token' => $body['accessToken'],
+ 'expires_at' => strtotime($body['expireTime']),
+ ];
+ }
+
+ /**
+ * @param callable|null $httpHandler
+ * @param array $headers [optional] Metrics headers to be inserted
+ * into the token endpoint request present.
+ *
+ * @return array {
+ * A set of auth related metadata, containing the following
+ *
+ * @type string $access_token
+ * @type int $expires_at (impersonated service accounts only)
+ * @type int $expires_in (identity pool only)
+ * @type string $issued_token_type (identity pool only)
+ * @type string $token_type (identity pool only)
+ * }
+ */
+ public function fetchAuthToken(?callable $httpHandler = null, array $headers = [])
+ {
+ $stsToken = $this->auth->fetchAuthToken($httpHandler, $headers);
+
+ if (isset($this->serviceAccountImpersonationUrl)) {
+ return $this->lastImpersonatedAccessToken = $this->getImpersonatedAccessToken(
+ $stsToken['access_token'],
+ $httpHandler
+ );
+ }
+
+ return $stsToken;
+ }
+
+ /**
+ * Get the cache token key for the credentials.
+ * The cache token key format depends on the type of source
+ * The format for the cache key one of the following:
+ * FetcherCacheKey.Scope.[ServiceAccount].[TokenType].[WorkforcePoolUserProject]
+ * FetcherCacheKey.Audience.[ServiceAccount].[TokenType].[WorkforcePoolUserProject]
+ *
+ * @return ?string;
+ */
+ public function getCacheKey(): ?string
+ {
+ $scopeOrAudience = $this->auth->getAudience();
+ if (!$scopeOrAudience) {
+ $scopeOrAudience = $this->auth->getScope();
+ }
+
+ return $this->auth->getSubjectTokenFetcher()->getCacheKey() .
+ '.' . $scopeOrAudience .
+ '.' . ($this->serviceAccountImpersonationUrl ?? '') .
+ '.' . ($this->auth->getSubjectTokenType() ?? '') .
+ '.' . ($this->workforcePoolUserProject ?? '');
+ }
+
+ public function getLastReceivedToken()
+ {
+ return $this->lastImpersonatedAccessToken ?? $this->auth->getLastReceivedToken();
+ }
+
+ /**
+ * Get the quota project used for this API request
+ *
+ * @return string|null
+ */
+ public function getQuotaProject()
+ {
+ return $this->quotaProject;
+ }
+
+ /**
+ * Get the universe domain used for this API request
+ *
+ * @return string
+ */
+ public function getUniverseDomain(): string
+ {
+ return $this->universeDomain;
+ }
+
+ /**
+ * Get the project ID.
+ *
+ * @param callable|null $httpHandler Callback which delivers psr7 request
+ * @param string|null $accessToken The access token to use to sign the blob. If
+ * provided, saves a call to the metadata server for a new access
+ * token. **Defaults to** `null`.
+ * @return string|null
+ */
+ public function getProjectId(?callable $httpHandler = null, ?string $accessToken = null)
+ {
+ if (isset($this->projectId)) {
+ return $this->projectId;
+ }
+
+ $projectNumber = $this->getProjectNumber() ?: $this->workforcePoolUserProject;
+ if (!$projectNumber) {
+ return null;
+ }
+
+ if (is_null($httpHandler)) {
+ $httpHandler = HttpHandlerFactory::build(HttpClientCache::getHttpClient());
+ }
+
+ $url = str_replace(
+ 'UNIVERSE_DOMAIN',
+ $this->getUniverseDomain(),
+ sprintf(self::CLOUD_RESOURCE_MANAGER_URL, $projectNumber)
+ );
+
+ if (is_null($accessToken)) {
+ $accessToken = $this->fetchAuthToken($httpHandler)['access_token'];
+ }
+
+ $request = new Request('GET', $url, ['authorization' => 'Bearer ' . $accessToken]);
+ $response = $httpHandler($request);
+
+ $body = json_decode((string) $response->getBody(), true);
+ return $this->projectId = $body['projectId'];
+ }
+
+ private function getProjectNumber(): ?string
+ {
+ $parts = explode('/', $this->auth->getAudience());
+ $i = array_search('projects', $parts);
+ return $parts[$i + 1] ?? null;
+ }
+
+ private function isWorkforcePool(): bool
+ {
+ $regex = '#//iam\.googleapis\.com/locations/[^/]+/workforcePools/#';
+ return preg_match($regex, $this->auth->getAudience()) === 1;
+ }
+}
diff --git a/vendor/google/auth/src/Credentials/GCECredentials.php b/vendor/google/auth/src/Credentials/GCECredentials.php
new file mode 100644
index 0000000..ab6753b
--- /dev/null
+++ b/vendor/google/auth/src/Credentials/GCECredentials.php
@@ -0,0 +1,685 @@
+push($middleware);
+ *
+ * $client = new Client([
+ * 'handler' => $stack,
+ * 'base_uri' => 'https://www.googleapis.com/taskqueue/v1beta2/projects/',
+ * 'auth' => 'google_auth'
+ * ]);
+ *
+ * $res = $client->get('myproject/taskqueues/myqueue');
+ */
+class GCECredentials extends CredentialsLoader implements
+ SignBlobInterface,
+ ProjectIdProviderInterface,
+ GetQuotaProjectInterface
+{
+ use IamSignerTrait;
+
+ // phpcs:disable
+ const cacheKey = 'GOOGLE_AUTH_PHP_GCE';
+ // phpcs:enable
+
+ /**
+ * The metadata IP address on appengine instances.
+ *
+ * The IP is used instead of the domain 'metadata' to avoid slow responses
+ * when not on Compute Engine.
+ */
+ const METADATA_IP = '169.254.169.254';
+
+ /**
+ * The metadata path of the default token.
+ */
+ const TOKEN_URI_PATH = 'v1/instance/service-accounts/default/token';
+
+ /**
+ * The metadata path of the default id token.
+ */
+ const ID_TOKEN_URI_PATH = 'v1/instance/service-accounts/default/identity';
+
+ /**
+ * The metadata path of the client ID.
+ */
+ const CLIENT_ID_URI_PATH = 'v1/instance/service-accounts/default/email';
+
+ /**
+ * The metadata path of the project ID.
+ */
+ const PROJECT_ID_URI_PATH = 'v1/project/project-id';
+
+ /**
+ * The metadata path of the project ID.
+ */
+ const UNIVERSE_DOMAIN_URI_PATH = 'v1/universe/universe-domain';
+
+ /**
+ * The header whose presence indicates GCE presence.
+ */
+ const FLAVOR_HEADER = 'Metadata-Flavor';
+
+ /**
+ * The Linux file which contains the product name.
+ */
+ private const GKE_PRODUCT_NAME_FILE = '/sys/class/dmi/id/product_name';
+
+ /**
+ * The Windows Registry key path to the product name
+ */
+ private const WINDOWS_REGISTRY_KEY_PATH = 'HKEY_LOCAL_MACHINE\\SYSTEM\\HardwareConfig\\Current\\';
+
+ /**
+ * The Windows registry key name for the product name
+ */
+ private const WINDOWS_REGISTRY_KEY_NAME = 'SystemProductName';
+
+ /**
+ * The Name of the product expected from the windows registry
+ */
+ private const PRODUCT_NAME = 'Google';
+
+ private const CRED_TYPE = 'mds';
+
+ /**
+ * Note: the explicit `timeout` and `tries` below is a workaround. The underlying
+ * issue is that resolving an unknown host on some networks will take
+ * 20-30 seconds; making this timeout short fixes the issue, but
+ * could lead to false negatives in the event that we are on GCE, but
+ * the metadata resolution was particularly slow. The latter case is
+ * "unlikely" since the expected 4-nines time is about 0.5 seconds.
+ * This allows us to limit the total ping maximum timeout to 1.5 seconds
+ * for developer desktop scenarios.
+ */
+ const MAX_COMPUTE_PING_TRIES = 3;
+ const COMPUTE_PING_CONNECTION_TIMEOUT_S = 0.5;
+
+ /**
+ * Flag used to ensure that the onGCE test is only done once;.
+ *
+ * @var bool
+ */
+ private $hasCheckedOnGce = false;
+
+ /**
+ * Flag that stores the value of the onGCE check.
+ *
+ * @var bool
+ */
+ private $isOnGce = false;
+
+ /**
+ * Result of fetchAuthToken.
+ *
+ * @var array
+ */
+ protected $lastReceivedToken;
+
+ /**
+ * @var string|null
+ */
+ private $clientName;
+
+ /**
+ * @var string|null
+ */
+ private $projectId;
+
+ /**
+ * @var string
+ */
+ private $tokenUri;
+
+ /**
+ * @var string
+ */
+ private $targetAudience;
+
+ /**
+ * @var string|null
+ */
+ private $quotaProject;
+
+ /**
+ * @var string|null
+ */
+ private $serviceAccountIdentity;
+
+ /**
+ * @var string
+ */
+ private ?string $universeDomain;
+
+ /**
+ * @param Iam|null $iam [optional] An IAM instance.
+ * @param string|string[] $scope [optional] the scope of the access request,
+ * expressed either as an array or as a space-delimited string.
+ * @param string $targetAudience [optional] The audience for the ID token.
+ * @param string $quotaProject [optional] Specifies a project to bill for access
+ * charges associated with the request.
+ * @param string $serviceAccountIdentity [optional] Specify a service
+ * account identity name to use instead of "default".
+ * @param string|null $universeDomain [optional] Specify a universe domain to use
+ * instead of fetching one from the metadata server.
+ */
+ public function __construct(
+ ?Iam $iam = null,
+ $scope = null,
+ $targetAudience = null,
+ $quotaProject = null,
+ $serviceAccountIdentity = null,
+ ?string $universeDomain = null
+ ) {
+ $this->iam = $iam;
+
+ if ($scope && $targetAudience) {
+ throw new InvalidArgumentException(
+ 'Scope and targetAudience cannot both be supplied'
+ );
+ }
+
+ $tokenUri = self::getTokenUri($serviceAccountIdentity);
+ if ($scope) {
+ if (is_string($scope)) {
+ $scope = explode(' ', $scope);
+ }
+
+ $scope = implode(',', $scope);
+
+ $tokenUri = $tokenUri . '?scopes=' . $scope;
+ } elseif ($targetAudience) {
+ $tokenUri = self::getIdTokenUri($serviceAccountIdentity);
+ $tokenUri = $tokenUri . '?audience=' . $targetAudience;
+ $this->targetAudience = $targetAudience;
+ }
+
+ $this->tokenUri = $tokenUri;
+ $this->quotaProject = $quotaProject;
+ $this->serviceAccountIdentity = $serviceAccountIdentity;
+ $this->universeDomain = $universeDomain;
+ }
+
+ /**
+ * The full uri for accessing the default token.
+ *
+ * @param string $serviceAccountIdentity [optional] Specify a service
+ * account identity name to use instead of "default".
+ * @return string
+ */
+ public static function getTokenUri($serviceAccountIdentity = null)
+ {
+ $base = 'http://' . self::METADATA_IP . '/computeMetadata/';
+ $base .= self::TOKEN_URI_PATH;
+
+ if ($serviceAccountIdentity) {
+ return str_replace(
+ '/default/',
+ '/' . $serviceAccountIdentity . '/',
+ $base
+ );
+ }
+ return $base;
+ }
+
+ /**
+ * The full uri for accessing the default service account.
+ *
+ * @param string $serviceAccountIdentity [optional] Specify a service
+ * account identity name to use instead of "default".
+ * @return string
+ */
+ public static function getClientNameUri($serviceAccountIdentity = null)
+ {
+ $base = 'http://' . self::METADATA_IP . '/computeMetadata/';
+ $base .= self::CLIENT_ID_URI_PATH;
+
+ if ($serviceAccountIdentity) {
+ return str_replace(
+ '/default/',
+ '/' . $serviceAccountIdentity . '/',
+ $base
+ );
+ }
+
+ return $base;
+ }
+
+ /**
+ * The full uri for accesesing the default identity token.
+ *
+ * @param string $serviceAccountIdentity [optional] Specify a service
+ * account identity name to use instead of "default".
+ * @return string
+ */
+ private static function getIdTokenUri($serviceAccountIdentity = null)
+ {
+ $base = 'http://' . self::METADATA_IP . '/computeMetadata/';
+ $base .= self::ID_TOKEN_URI_PATH;
+
+ if ($serviceAccountIdentity) {
+ return str_replace(
+ '/default/',
+ '/' . $serviceAccountIdentity . '/',
+ $base
+ );
+ }
+
+ return $base;
+ }
+
+ /**
+ * The full uri for accessing the default project ID.
+ *
+ * @return string
+ */
+ private static function getProjectIdUri()
+ {
+ $base = 'http://' . self::METADATA_IP . '/computeMetadata/';
+
+ return $base . self::PROJECT_ID_URI_PATH;
+ }
+
+ /**
+ * The full uri for accessing the default universe domain.
+ *
+ * @return string
+ */
+ private static function getUniverseDomainUri()
+ {
+ $base = 'http://' . self::METADATA_IP . '/computeMetadata/';
+
+ return $base . self::UNIVERSE_DOMAIN_URI_PATH;
+ }
+
+ /**
+ * Determines if this an App Engine Flexible instance, by accessing the
+ * GAE_INSTANCE environment variable.
+ *
+ * @return bool true if this an App Engine Flexible Instance, false otherwise
+ */
+ public static function onAppEngineFlexible()
+ {
+ return substr((string) getenv('GAE_INSTANCE'), 0, 4) === 'aef-';
+ }
+
+ /**
+ * Determines if this a GCE instance, by accessing the expected metadata
+ * host.
+ * If $httpHandler is not specified a the default HttpHandler is used.
+ *
+ * @param callable|null $httpHandler callback which delivers psr7 request
+ * @return bool True if this a GCEInstance, false otherwise
+ */
+ public static function onGce(?callable $httpHandler = null)
+ {
+ $httpHandler = $httpHandler
+ ?: HttpHandlerFactory::build(HttpClientCache::getHttpClient());
+
+ $checkUri = 'http://' . self::METADATA_IP;
+ for ($i = 1; $i <= self::MAX_COMPUTE_PING_TRIES; $i++) {
+ try {
+ // Comment from: oauth2client/client.py
+ //
+ // Note: the explicit `timeout` below is a workaround. The underlying
+ // issue is that resolving an unknown host on some networks will take
+ // 20-30 seconds; making this timeout short fixes the issue, but
+ // could lead to false negatives in the event that we are on GCE, but
+ // the metadata resolution was particularly slow. The latter case is
+ // "unlikely".
+ $resp = $httpHandler(
+ new Request(
+ 'GET',
+ $checkUri,
+ [
+ self::FLAVOR_HEADER => 'Google',
+ self::$metricMetadataKey => self::getMetricsHeader('', 'mds')
+ ]
+ ),
+ ['timeout' => self::COMPUTE_PING_CONNECTION_TIMEOUT_S]
+ );
+
+ return $resp->getHeaderLine(self::FLAVOR_HEADER) == 'Google';
+ } catch (ClientException $e) {
+ } catch (ServerException $e) {
+ } catch (RequestException $e) {
+ } catch (ConnectException $e) {
+ }
+ }
+
+ if (PHP_OS === 'Windows' || PHP_OS === 'WINNT') {
+ return self::detectResidencyWindows(
+ self::WINDOWS_REGISTRY_KEY_PATH . self::WINDOWS_REGISTRY_KEY_NAME
+ );
+ }
+
+ // Detect GCE residency on Linux
+ return self::detectResidencyLinux(self::GKE_PRODUCT_NAME_FILE);
+ }
+
+ private static function detectResidencyLinux(string $productNameFile): bool
+ {
+ if (file_exists($productNameFile)) {
+ $productName = trim((string) file_get_contents($productNameFile));
+ return 0 === strpos($productName, self::PRODUCT_NAME);
+ }
+ return false;
+ }
+
+ private static function detectResidencyWindows(string $registryProductKey): bool
+ {
+ if (!class_exists(COM::class)) {
+ // the COM extension must be installed and enabled to detect Windows residency
+ // see https://www.php.net/manual/en/book.com.php
+ return false;
+ }
+
+ $shell = new COM('WScript.Shell');
+ $productName = null;
+
+ try {
+ $productName = $shell->regRead($registryProductKey);
+ } catch (com_exception) {
+ // This means that we tried to read a key that doesn't exist on the registry
+ // which might mean that it is a windows instance that is not on GCE
+ return false;
+ }
+
+ return 0 === strpos($productName, self::PRODUCT_NAME);
+ }
+
+ /**
+ * Implements FetchAuthTokenInterface#fetchAuthToken.
+ *
+ * Fetches the auth tokens from the GCE metadata host if it is available.
+ * If $httpHandler is not specified a the default HttpHandler is used.
+ *
+ * @param callable|null $httpHandler callback which delivers psr7 request
+ * @param array $headers [optional] Headers to be inserted
+ * into the token endpoint request present.
+ *
+ * @return array {
+ * A set of auth related metadata, based on the token type.
+ *
+ * @type string $access_token for access tokens
+ * @type int $expires_in for access tokens
+ * @type string $token_type for access tokens
+ * @type string $id_token for ID tokens
+ * }
+ * @throws \Exception
+ */
+ public function fetchAuthToken(?callable $httpHandler = null, array $headers = [])
+ {
+ $httpHandler = $httpHandler
+ ?: HttpHandlerFactory::build(HttpClientCache::getHttpClient());
+
+ if (!$this->hasCheckedOnGce) {
+ $this->isOnGce = self::onGce($httpHandler);
+ $this->hasCheckedOnGce = true;
+ }
+ if (!$this->isOnGce) {
+ return []; // return an empty array with no access token
+ }
+
+ $response = $this->getFromMetadata(
+ $httpHandler,
+ $this->tokenUri,
+ $this->applyTokenEndpointMetrics($headers, $this->targetAudience ? 'it' : 'at')
+ );
+
+ if ($this->targetAudience) {
+ return $this->lastReceivedToken = ['id_token' => $response];
+ }
+
+ if (null === $json = json_decode($response, true)) {
+ throw new \Exception('Invalid JSON response');
+ }
+
+ $json['expires_at'] = time() + $json['expires_in'];
+
+ // store this so we can retrieve it later
+ $this->lastReceivedToken = $json;
+
+ return $json;
+ }
+
+ /**
+ * Returns the Cache Key for the credential token.
+ * The format for the cache key is:
+ * TokenURI
+ *
+ * @return string
+ */
+ public function getCacheKey()
+ {
+ return $this->tokenUri;
+ }
+
+ /**
+ * @return array|null
+ */
+ public function getLastReceivedToken()
+ {
+ if ($this->lastReceivedToken) {
+ if (array_key_exists('id_token', $this->lastReceivedToken)) {
+ return $this->lastReceivedToken;
+ }
+
+ return [
+ 'access_token' => $this->lastReceivedToken['access_token'],
+ 'expires_at' => $this->lastReceivedToken['expires_at']
+ ];
+ }
+
+ return null;
+ }
+
+ /**
+ * Get the client name from GCE metadata.
+ *
+ * Subsequent calls will return a cached value.
+ *
+ * @param callable|null $httpHandler callback which delivers psr7 request
+ * @return string
+ */
+ public function getClientName(?callable $httpHandler = null)
+ {
+ if ($this->clientName) {
+ return $this->clientName;
+ }
+
+ $httpHandler = $httpHandler
+ ?: HttpHandlerFactory::build(HttpClientCache::getHttpClient());
+
+ if (!$this->hasCheckedOnGce) {
+ $this->isOnGce = self::onGce($httpHandler);
+ $this->hasCheckedOnGce = true;
+ }
+
+ if (!$this->isOnGce) {
+ return '';
+ }
+
+ $this->clientName = $this->getFromMetadata(
+ $httpHandler,
+ self::getClientNameUri($this->serviceAccountIdentity)
+ );
+
+ return $this->clientName;
+ }
+
+ /**
+ * Fetch the default Project ID from compute engine.
+ *
+ * Returns null if called outside GCE.
+ *
+ * @param callable|null $httpHandler Callback which delivers psr7 request
+ * @return string|null
+ */
+ public function getProjectId(?callable $httpHandler = null)
+ {
+ if ($this->projectId) {
+ return $this->projectId;
+ }
+
+ $httpHandler = $httpHandler
+ ?: HttpHandlerFactory::build(HttpClientCache::getHttpClient());
+
+ if (!$this->hasCheckedOnGce) {
+ $this->isOnGce = self::onGce($httpHandler);
+ $this->hasCheckedOnGce = true;
+ }
+
+ if (!$this->isOnGce) {
+ return null;
+ }
+
+ $this->projectId = $this->getFromMetadata($httpHandler, self::getProjectIdUri());
+ return $this->projectId;
+ }
+
+ /**
+ * Fetch the default universe domain from the metadata server.
+ *
+ * @param callable|null $httpHandler Callback which delivers psr7 request
+ * @return string
+ */
+ public function getUniverseDomain(?callable $httpHandler = null): string
+ {
+ if (null !== $this->universeDomain) {
+ return $this->universeDomain;
+ }
+
+ $httpHandler = $httpHandler
+ ?: HttpHandlerFactory::build(HttpClientCache::getHttpClient());
+
+ if (!$this->hasCheckedOnGce) {
+ $this->isOnGce = self::onGce($httpHandler);
+ $this->hasCheckedOnGce = true;
+ }
+
+ try {
+ $this->universeDomain = $this->getFromMetadata(
+ $httpHandler,
+ self::getUniverseDomainUri()
+ );
+ } catch (ClientException $e) {
+ // If the metadata server exists, but returns a 404 for the universe domain, the auth
+ // libraries should safely assume this is an older metadata server running in GCU, and
+ // should return the default universe domain.
+ if (!$e->hasResponse() || 404 != $e->getResponse()->getStatusCode()) {
+ throw $e;
+ }
+ $this->universeDomain = self::DEFAULT_UNIVERSE_DOMAIN;
+ }
+
+ // We expect in some cases the metadata server will return an empty string for the universe
+ // domain. In this case, the auth library MUST return the default universe domain.
+ if ('' === $this->universeDomain) {
+ $this->universeDomain = self::DEFAULT_UNIVERSE_DOMAIN;
+ }
+
+ return $this->universeDomain;
+ }
+
+ /**
+ * Fetch the value of a GCE metadata server URI.
+ *
+ * @param callable $httpHandler An HTTP Handler to deliver PSR7 requests.
+ * @param string $uri The metadata URI.
+ * @param array $headers [optional] If present, add these headers to the token
+ * endpoint request.
+ *
+ * @return string
+ */
+ private function getFromMetadata(callable $httpHandler, $uri, array $headers = [])
+ {
+ $resp = $httpHandler(
+ new Request(
+ 'GET',
+ $uri,
+ [self::FLAVOR_HEADER => 'Google'] + $headers
+ )
+ );
+
+ return (string) $resp->getBody();
+ }
+
+ /**
+ * Get the quota project used for this API request
+ *
+ * @return string|null
+ */
+ public function getQuotaProject()
+ {
+ return $this->quotaProject;
+ }
+
+ /**
+ * Set whether or not we've already checked the GCE environment.
+ *
+ * @param bool $isOnGce
+ *
+ * @return void
+ */
+ public function setIsOnGce($isOnGce)
+ {
+ // Implicitly set hasCheckedGce to true
+ $this->hasCheckedOnGce = true;
+
+ // Set isOnGce
+ $this->isOnGce = $isOnGce;
+ }
+
+ protected function getCredType(): string
+ {
+ return self::CRED_TYPE;
+ }
+}
diff --git a/vendor/google/auth/src/Credentials/IAMCredentials.php b/vendor/google/auth/src/Credentials/IAMCredentials.php
new file mode 100644
index 0000000..96d1df7
--- /dev/null
+++ b/vendor/google/auth/src/Credentials/IAMCredentials.php
@@ -0,0 +1,91 @@
+selector = $selector;
+ $this->token = $token;
+ }
+
+ /**
+ * export a callback function which updates runtime metadata.
+ *
+ * @return callable updateMetadata function
+ */
+ public function getUpdateMetadataFunc()
+ {
+ return [$this, 'updateMetadata'];
+ }
+
+ /**
+ * Updates metadata with the appropriate header metadata.
+ *
+ * @param array $metadata metadata hashmap
+ * @param string $unusedAuthUri optional auth uri
+ * @param callable|null $httpHandler callback which delivers psr7 request
+ * Note: this param is unused here, only included here for
+ * consistency with other credentials class
+ *
+ * @return array updated metadata hashmap
+ */
+ public function updateMetadata(
+ $metadata,
+ $unusedAuthUri = null,
+ ?callable $httpHandler = null
+ ) {
+ $metadata_copy = $metadata;
+ $metadata_copy[self::SELECTOR_KEY] = $this->selector;
+ $metadata_copy[self::TOKEN_KEY] = $this->token;
+
+ return $metadata_copy;
+ }
+}
diff --git a/vendor/google/auth/src/Credentials/ImpersonatedServiceAccountCredentials.php b/vendor/google/auth/src/Credentials/ImpersonatedServiceAccountCredentials.php
new file mode 100644
index 0000000..f473f8e
--- /dev/null
+++ b/vendor/google/auth/src/Credentials/ImpersonatedServiceAccountCredentials.php
@@ -0,0 +1,295 @@
+ $jsonKey JSON credential file path or JSON array credentials {
+ * JSON credentials as an associative array.
+ *
+ * @type string $service_account_impersonation_url The URL to the service account
+ * @type string|FetchAuthTokenInterface $source_credentials The source credentials to impersonate
+ * @type int $lifetime The lifetime of the impersonated credentials
+ * @type string[] $delegates The delegates to impersonate
+ * }
+ * @param string|null $targetAudience The audience to request an ID token.
+ */
+ public function __construct(
+ string|array|null $scope,
+ string|array $jsonKey,
+ private ?string $targetAudience = null
+ ) {
+ if (is_string($jsonKey)) {
+ if (!file_exists($jsonKey)) {
+ throw new InvalidArgumentException('file does not exist');
+ }
+ $json = file_get_contents($jsonKey);
+ if (!$jsonKey = json_decode((string) $json, true)) {
+ throw new LogicException('invalid json for auth config');
+ }
+ }
+ if (!array_key_exists('service_account_impersonation_url', $jsonKey)) {
+ throw new LogicException(
+ 'json key is missing the service_account_impersonation_url field'
+ );
+ }
+ if (!array_key_exists('source_credentials', $jsonKey)) {
+ throw new LogicException('json key is missing the source_credentials field');
+ }
+ if ($scope && $targetAudience) {
+ throw new InvalidArgumentException(
+ 'Scope and targetAudience cannot both be supplied'
+ );
+ }
+ if (is_array($jsonKey['source_credentials'])) {
+ if (!array_key_exists('type', $jsonKey['source_credentials'])) {
+ throw new InvalidArgumentException('json key source credentials are missing the type field');
+ }
+ if (
+ $targetAudience !== null
+ && $jsonKey['source_credentials']['type'] === 'service_account'
+ ) {
+ // Service account tokens MUST request a scope, and as this token is only used to impersonate
+ // an ID token, the narrowest scope we can request is `iam`.
+ $scope = self::IAM_SCOPE;
+ }
+ $jsonKey['source_credentials'] = match ($jsonKey['source_credentials']['type'] ?? null) {
+ // Do not pass $defaultScope to ServiceAccountCredentials
+ 'service_account' => new ServiceAccountCredentials($scope, $jsonKey['source_credentials']),
+ 'authorized_user' => new UserRefreshCredentials($scope, $jsonKey['source_credentials']),
+ 'external_account' => new ExternalAccountCredentials($scope, $jsonKey['source_credentials']),
+ default => throw new \InvalidArgumentException('invalid value in the type field'),
+ };
+ }
+
+ $this->targetScope = $scope ?? [];
+ $this->lifetime = $jsonKey['lifetime'] ?? 3600;
+ $this->delegates = $jsonKey['delegates'] ?? [];
+
+ $this->serviceAccountImpersonationUrl = $jsonKey['service_account_impersonation_url'];
+ $this->impersonatedServiceAccountName = $this->getImpersonatedServiceAccountNameFromUrl(
+ $this->serviceAccountImpersonationUrl
+ );
+
+ $this->sourceCredentials = $jsonKey['source_credentials'];
+ }
+
+ /**
+ * Helper function for extracting the Server Account Name from the URL saved in the account
+ * credentials file.
+ *
+ * @param $serviceAccountImpersonationUrl string URL from "service_account_impersonation_url"
+ * @return string Service account email or ID.
+ */
+ private function getImpersonatedServiceAccountNameFromUrl(
+ string $serviceAccountImpersonationUrl
+ ): string {
+ $fields = explode('/', $serviceAccountImpersonationUrl);
+ $lastField = end($fields);
+ $splitter = explode(':', $lastField);
+ return $splitter[0];
+ }
+
+ /**
+ * Get the client name from the keyfile
+ *
+ * In this implementation, it will return the issuers email from the oauth token.
+ *
+ * @param callable|null $unusedHttpHandler not used by this credentials type.
+ * @return string Token issuer email
+ */
+ public function getClientName(?callable $unusedHttpHandler = null)
+ {
+ return $this->impersonatedServiceAccountName;
+ }
+
+ /**
+ * @param callable|null $httpHandler
+ *
+ * @return array {
+ * A set of auth related metadata, containing the following
+ *
+ * @type string $access_token
+ * @type int $expires_in
+ * @type string $scope
+ * @type string $token_type
+ * @type string $id_token
+ * }
+ */
+ public function fetchAuthToken(?callable $httpHandler = null)
+ {
+ $httpHandler = $httpHandler ?? HttpHandlerFactory::build(HttpClientCache::getHttpClient());
+
+ // The FetchAuthTokenInterface technically does not have a "headers" argument, but all of
+ // the implementations do. Additionally, passing in more parameters than the function has
+ // defined is allowed in PHP. So we'll just ignore the phpstan error here.
+ // @phpstan-ignore-next-line
+ $authToken = $this->sourceCredentials->fetchAuthToken(
+ $httpHandler,
+ $this->applyTokenEndpointMetrics([], 'at')
+ );
+
+ $headers = $this->applyTokenEndpointMetrics([
+ 'Content-Type' => 'application/json',
+ 'Cache-Control' => 'no-store',
+ 'Authorization' => sprintf('Bearer %s', $authToken['access_token'] ?? $authToken['id_token']),
+ ], $this->isIdTokenRequest() ? 'it' : 'at');
+
+ $body = match ($this->isIdTokenRequest()) {
+ true => [
+ 'audience' => $this->targetAudience,
+ 'includeEmail' => true,
+ ],
+ false => [
+ 'scope' => $this->targetScope,
+ 'delegates' => $this->delegates,
+ 'lifetime' => sprintf('%ss', $this->lifetime),
+ ]
+ };
+
+ $url = $this->serviceAccountImpersonationUrl;
+ if ($this->isIdTokenRequest()) {
+ $regex = '/serviceAccounts\/(?[^:]+):generateAccessToken$/';
+ if (!preg_match($regex, $url, $matches)) {
+ throw new InvalidArgumentException(
+ 'Invalid service account impersonation URL - unable to parse service account email'
+ );
+ }
+ $url = str_replace(
+ 'UNIVERSE_DOMAIN',
+ $this->getUniverseDomain(),
+ sprintf(self::ID_TOKEN_IMPERSONATION_URL, $matches['email'])
+ );
+ }
+
+ $request = new Request(
+ 'POST',
+ $url,
+ $headers,
+ (string) json_encode($body)
+ );
+
+ $response = $httpHandler($request);
+ $body = json_decode((string) $response->getBody(), true);
+
+ return match ($this->isIdTokenRequest()) {
+ true => ['id_token' => $body['token']],
+ false => [
+ 'access_token' => $body['accessToken'],
+ 'expires_at' => strtotime($body['expireTime']),
+ ]
+ };
+ }
+
+ /**
+ * Returns the Cache Key for the credentials
+ * The cache key is the same as the UserRefreshCredentials class
+ *
+ * @return string
+ */
+ public function getCacheKey()
+ {
+ return $this->getFullCacheKey(
+ $this->serviceAccountImpersonationUrl . $this->sourceCredentials->getCacheKey()
+ );
+ }
+
+ /**
+ * @return array
+ */
+ public function getLastReceivedToken()
+ {
+ return $this->sourceCredentials->getLastReceivedToken();
+ }
+
+ protected function getCredType(): string
+ {
+ return self::CRED_TYPE;
+ }
+
+ private function isIdTokenRequest(): bool
+ {
+ return !is_null($this->targetAudience);
+ }
+
+ public function getUniverseDomain(): string
+ {
+ return $this->sourceCredentials instanceof GetUniverseDomainInterface
+ ? $this->sourceCredentials->getUniverseDomain()
+ : self::DEFAULT_UNIVERSE_DOMAIN;
+ }
+}
diff --git a/vendor/google/auth/src/Credentials/InsecureCredentials.php b/vendor/google/auth/src/Credentials/InsecureCredentials.php
new file mode 100644
index 0000000..5a2bef1
--- /dev/null
+++ b/vendor/google/auth/src/Credentials/InsecureCredentials.php
@@ -0,0 +1,68 @@
+ ''
+ ];
+
+ /**
+ * Fetches the auth token. In this case it returns an empty string.
+ *
+ * @param callable|null $httpHandler
+ * @return array{access_token:string} A set of auth related metadata
+ */
+ public function fetchAuthToken(?callable $httpHandler = null)
+ {
+ return $this->token;
+ }
+
+ /**
+ * Returns the cache key. In this case it returns a null value, disabling
+ * caching.
+ *
+ * @return string|null
+ */
+ public function getCacheKey()
+ {
+ return null;
+ }
+
+ /**
+ * Fetches the last received token. In this case, it returns the same empty string
+ * auth token.
+ *
+ * @return array{access_token:string}
+ */
+ public function getLastReceivedToken()
+ {
+ return $this->token;
+ }
+}
diff --git a/vendor/google/auth/src/Credentials/ServiceAccountCredentials.php b/vendor/google/auth/src/Credentials/ServiceAccountCredentials.php
new file mode 100644
index 0000000..3d23f71
--- /dev/null
+++ b/vendor/google/auth/src/Credentials/ServiceAccountCredentials.php
@@ -0,0 +1,457 @@
+push($middleware);
+ *
+ * $client = new Client([
+ * 'handler' => $stack,
+ * 'base_uri' => 'https://www.googleapis.com/taskqueue/v1beta2/projects/',
+ * 'auth' => 'google_auth' // authorize all requests
+ * ]);
+ *
+ * $res = $client->get('myproject/taskqueues/myqueue');
+ */
+class ServiceAccountCredentials extends CredentialsLoader implements
+ GetQuotaProjectInterface,
+ SignBlobInterface,
+ ProjectIdProviderInterface
+{
+ use ServiceAccountSignerTrait;
+
+ /**
+ * Used in observability metric headers
+ *
+ * @var string
+ */
+ private const CRED_TYPE = 'sa';
+ private const IAM_SCOPE = 'https://www.googleapis.com/auth/iam';
+
+ /**
+ * The OAuth2 instance used to conduct authorization.
+ *
+ * @var OAuth2
+ */
+ protected $auth;
+
+ /**
+ * The quota project associated with the JSON credentials
+ *
+ * @var string
+ */
+ protected $quotaProject;
+
+ /**
+ * @var string|null
+ */
+ protected $projectId;
+
+ /**
+ * @var array|null
+ */
+ private $lastReceivedJwtAccessToken;
+
+ /**
+ * @var bool
+ */
+ private $useJwtAccessWithScope = false;
+
+ /**
+ * @var ServiceAccountJwtAccessCredentials|null
+ */
+ private $jwtAccessCredentials;
+
+ /**
+ * @var string
+ */
+ private string $universeDomain;
+
+ /**
+ * Whether this is an ID token request or an access token request. Used when
+ * building the metric header.
+ */
+ private bool $isIdTokenRequest = false;
+
+ /**
+ * Create a new ServiceAccountCredentials.
+ *
+ * @param string|string[]|null $scope the scope of the access request, expressed
+ * either as an Array or as a space-delimited String.
+ * @param string|array $jsonKey JSON credential file path or JSON credentials
+ * as an associative array
+ * @param string $sub an email address account to impersonate, in situations when
+ * the service account has been delegated domain wide access.
+ * @param string $targetAudience The audience for the ID token.
+ */
+ public function __construct(
+ $scope,
+ $jsonKey,
+ $sub = null,
+ $targetAudience = null
+ ) {
+ if (is_string($jsonKey)) {
+ if (!file_exists($jsonKey)) {
+ throw new \InvalidArgumentException('file does not exist');
+ }
+ $jsonKeyStream = file_get_contents($jsonKey);
+ if (!$jsonKey = json_decode((string) $jsonKeyStream, true)) {
+ throw new \LogicException('invalid json for auth config');
+ }
+ }
+ if (!array_key_exists('client_email', $jsonKey)) {
+ throw new \InvalidArgumentException(
+ 'json key is missing the client_email field'
+ );
+ }
+ if (!array_key_exists('private_key', $jsonKey)) {
+ throw new \InvalidArgumentException(
+ 'json key is missing the private_key field'
+ );
+ }
+ if (array_key_exists('quota_project_id', $jsonKey)) {
+ $this->quotaProject = (string) $jsonKey['quota_project_id'];
+ }
+ if ($scope && $targetAudience) {
+ throw new InvalidArgumentException(
+ 'Scope and targetAudience cannot both be supplied'
+ );
+ }
+ $additionalClaims = [];
+ if ($targetAudience) {
+ $additionalClaims = ['target_audience' => $targetAudience];
+ $this->isIdTokenRequest = true;
+ }
+ $this->auth = new OAuth2([
+ 'audience' => self::TOKEN_CREDENTIAL_URI,
+ 'issuer' => $jsonKey['client_email'],
+ 'scope' => $scope,
+ 'signingAlgorithm' => 'RS256',
+ 'signingKey' => $jsonKey['private_key'],
+ 'signingKeyId' => $jsonKey['private_key_id'] ?? null,
+ 'sub' => $sub,
+ 'tokenCredentialUri' => self::TOKEN_CREDENTIAL_URI,
+ 'additionalClaims' => $additionalClaims,
+ ]);
+
+ $this->projectId = $jsonKey['project_id'] ?? null;
+ $this->universeDomain = $jsonKey['universe_domain'] ?? self::DEFAULT_UNIVERSE_DOMAIN;
+ }
+
+ /**
+ * When called, the ServiceAccountCredentials will use an instance of
+ * ServiceAccountJwtAccessCredentials to fetch (self-sign) an access token
+ * even when only scopes are supplied. Otherwise,
+ * ServiceAccountJwtAccessCredentials is only called when no scopes and an
+ * authUrl (audience) is suppled.
+ *
+ * @return void
+ */
+ public function useJwtAccessWithScope()
+ {
+ $this->useJwtAccessWithScope = true;
+ }
+
+ /**
+ * @param callable|null $httpHandler
+ * @param array $headers [optional] Headers to be inserted
+ * into the token endpoint request present.
+ *
+ * @return array {
+ * A set of auth related metadata, containing the following
+ *
+ * @type string $access_token
+ * @type int $expires_in
+ * @type string $token_type
+ * }
+ */
+ public function fetchAuthToken(?callable $httpHandler = null, array $headers = [])
+ {
+ if ($this->useSelfSignedJwt()) {
+ $jwtCreds = $this->createJwtAccessCredentials();
+
+ $accessToken = $jwtCreds->fetchAuthToken($httpHandler);
+
+ if ($lastReceivedToken = $jwtCreds->getLastReceivedToken()) {
+ // Keep self-signed JWTs in memory as the last received token
+ $this->lastReceivedJwtAccessToken = $lastReceivedToken;
+ }
+
+ return $accessToken;
+ }
+
+ if ($this->isIdTokenRequest && $this->getUniverseDomain() !== self::DEFAULT_UNIVERSE_DOMAIN) {
+ $now = time();
+ $jwt = Jwt::encode(
+ [
+ 'iss' => $this->auth->getIssuer(),
+ 'sub' => $this->auth->getIssuer(),
+ 'scope' => self::IAM_SCOPE,
+ 'exp' => ($now + $this->auth->getExpiry()),
+ 'iat' => ($now - OAuth2::DEFAULT_SKEW_SECONDS),
+ ],
+ $this->auth->getSigningKey(),
+ $this->auth->getSigningAlgorithm(),
+ $this->auth->getSigningKeyId()
+ );
+ // We create a new instance of Iam each time because the `$httpHandler` might change.
+ $idToken = (new Iam($httpHandler, $this->getUniverseDomain()))->generateIdToken(
+ $this->auth->getIssuer(),
+ $this->auth->getAdditionalClaims()['target_audience'],
+ $jwt,
+ $this->applyTokenEndpointMetrics($headers, 'it')
+ );
+ return ['id_token' => $idToken];
+ }
+ return $this->auth->fetchAuthToken(
+ $httpHandler,
+ $this->applyTokenEndpointMetrics($headers, $this->isIdTokenRequest ? 'it' : 'at')
+ );
+ }
+
+ /**
+ * Return the Cache Key for the credentials.
+ * For the cache key format is one of the following:
+ * ClientEmail.Scope[.Sub]
+ * ClientEmail.Audience[.Sub]
+ *
+ * @return string
+ */
+ public function getCacheKey()
+ {
+ $scopeOrAudience = $this->auth->getScope();
+ if (!$scopeOrAudience) {
+ $scopeOrAudience = $this->auth->getAudience();
+ }
+
+ $key = $this->auth->getIssuer() . '.' . $scopeOrAudience;
+ if ($sub = $this->auth->getSub()) {
+ $key .= '.' . $sub;
+ }
+
+ return $key;
+ }
+
+ /**
+ * @return array
+ */
+ public function getLastReceivedToken()
+ {
+ // If self-signed JWTs are being used, fetch the last received token
+ // from memory. Else, fetch it from OAuth2
+ return $this->useSelfSignedJwt()
+ ? $this->lastReceivedJwtAccessToken
+ : $this->auth->getLastReceivedToken();
+ }
+
+ /**
+ * Get the project ID from the service account keyfile.
+ *
+ * Returns null if the project ID does not exist in the keyfile.
+ *
+ * @param callable|null $httpHandler Not used by this credentials type.
+ * @return string|null
+ */
+ public function getProjectId(?callable $httpHandler = null)
+ {
+ return $this->projectId;
+ }
+
+ /**
+ * Updates metadata with the authorization token.
+ *
+ * @param array $metadata metadata hashmap
+ * @param string $authUri optional auth uri
+ * @param callable|null $httpHandler callback which delivers psr7 request
+ * @return array updated metadata hashmap
+ */
+ public function updateMetadata(
+ $metadata,
+ $authUri = null,
+ ?callable $httpHandler = null
+ ) {
+ // scope exists. use oauth implementation
+ if (!$this->useSelfSignedJwt()) {
+ return parent::updateMetadata($metadata, $authUri, $httpHandler);
+ }
+
+ $jwtCreds = $this->createJwtAccessCredentials();
+ if ($this->auth->getScope()) {
+ // Prefer user-provided "scope" to "audience"
+ $updatedMetadata = $jwtCreds->updateMetadata($metadata, null, $httpHandler);
+ } else {
+ $updatedMetadata = $jwtCreds->updateMetadata($metadata, $authUri, $httpHandler);
+ }
+
+ if ($lastReceivedToken = $jwtCreds->getLastReceivedToken()) {
+ // Keep self-signed JWTs in memory as the last received token
+ $this->lastReceivedJwtAccessToken = $lastReceivedToken;
+ }
+
+ return $updatedMetadata;
+ }
+
+ /**
+ * @return ServiceAccountJwtAccessCredentials
+ */
+ private function createJwtAccessCredentials()
+ {
+ if (!$this->jwtAccessCredentials) {
+ // Create credentials for self-signing a JWT (JwtAccess)
+ $credJson = [
+ 'private_key' => $this->auth->getSigningKey(),
+ 'client_email' => $this->auth->getIssuer(),
+ ];
+ $this->jwtAccessCredentials = new ServiceAccountJwtAccessCredentials(
+ $credJson,
+ $this->auth->getScope()
+ );
+ }
+
+ return $this->jwtAccessCredentials;
+ }
+
+ /**
+ * @param string $sub an email address account to impersonate, in situations when
+ * the service account has been delegated domain wide access.
+ * @return void
+ */
+ public function setSub($sub)
+ {
+ $this->auth->setSub($sub);
+ }
+
+ /**
+ * Get the client name from the keyfile.
+ *
+ * In this case, it returns the keyfile's client_email key.
+ *
+ * @param callable|null $httpHandler Not used by this credentials type.
+ * @return string
+ */
+ public function getClientName(?callable $httpHandler = null)
+ {
+ return $this->auth->getIssuer();
+ }
+
+ /**
+ * Get the private key from the keyfile.
+ *
+ * In this case, it returns the keyfile's private_key key, needed for JWT signing.
+ *
+ * @return string
+ */
+ public function getPrivateKey()
+ {
+ return $this->auth->getSigningKey();
+ }
+
+ /**
+ * Get the quota project used for this API request
+ *
+ * @return string|null
+ */
+ public function getQuotaProject()
+ {
+ return $this->quotaProject;
+ }
+
+ /**
+ * Get the universe domain configured in the JSON credential.
+ *
+ * @return string
+ */
+ public function getUniverseDomain(): string
+ {
+ return $this->universeDomain;
+ }
+
+ protected function getCredType(): string
+ {
+ return self::CRED_TYPE;
+ }
+
+ /**
+ * @return bool
+ */
+ private function useSelfSignedJwt()
+ {
+ // When a sub is supplied, the user is using domain-wide delegation, which not available
+ // with self-signed JWTs
+ if (null !== $this->auth->getSub()) {
+ // If we are outside the GDU, we can't use domain-wide delegation
+ if ($this->getUniverseDomain() !== self::DEFAULT_UNIVERSE_DOMAIN) {
+ throw new \LogicException(sprintf(
+ 'Service Account subject is configured for the credential. Domain-wide ' .
+ 'delegation is not supported in universes other than %s.',
+ self::DEFAULT_UNIVERSE_DOMAIN
+ ));
+ }
+ return false;
+ }
+
+ // Do not use self-signed JWT for ID tokens
+ if ($this->isIdTokenRequest) {
+ return false;
+ }
+
+ // When true, ServiceAccountCredentials will always use JwtAccess for access tokens
+ if ($this->useJwtAccessWithScope) {
+ return true;
+ }
+
+ // If the universe domain is outside the GDU, use JwtAccess for access tokens
+ if ($this->getUniverseDomain() !== self::DEFAULT_UNIVERSE_DOMAIN) {
+ return true;
+ }
+
+ return is_null($this->auth->getScope());
+ }
+}
diff --git a/vendor/google/auth/src/Credentials/ServiceAccountJwtAccessCredentials.php b/vendor/google/auth/src/Credentials/ServiceAccountJwtAccessCredentials.php
new file mode 100644
index 0000000..5037376
--- /dev/null
+++ b/vendor/google/auth/src/Credentials/ServiceAccountJwtAccessCredentials.php
@@ -0,0 +1,246 @@
+ $jsonKey JSON credential file path or JSON credentials
+ * as an associative array
+ * @param string|string[] $scope the scope of the access request, expressed
+ * either as an Array or as a space-delimited String.
+ */
+ public function __construct($jsonKey, $scope = null)
+ {
+ if (is_string($jsonKey)) {
+ if (!file_exists($jsonKey)) {
+ throw new \InvalidArgumentException('file does not exist');
+ }
+ $jsonKeyStream = file_get_contents($jsonKey);
+ if (!$jsonKey = json_decode((string) $jsonKeyStream, true)) {
+ throw new \LogicException('invalid json for auth config');
+ }
+ }
+ if (!array_key_exists('client_email', $jsonKey)) {
+ throw new \InvalidArgumentException(
+ 'json key is missing the client_email field'
+ );
+ }
+ if (!array_key_exists('private_key', $jsonKey)) {
+ throw new \InvalidArgumentException(
+ 'json key is missing the private_key field'
+ );
+ }
+ if (array_key_exists('quota_project_id', $jsonKey)) {
+ $this->quotaProject = (string) $jsonKey['quota_project_id'];
+ }
+ $this->auth = new OAuth2([
+ 'issuer' => $jsonKey['client_email'],
+ 'sub' => $jsonKey['client_email'],
+ 'signingAlgorithm' => 'RS256',
+ 'signingKey' => $jsonKey['private_key'],
+ 'scope' => $scope,
+ ]);
+
+ $this->projectId = $jsonKey['project_id'] ?? null;
+ }
+
+ /**
+ * Updates metadata with the authorization token.
+ *
+ * @param array $metadata metadata hashmap
+ * @param string $authUri optional auth uri
+ * @param callable|null $httpHandler callback which delivers psr7 request
+ * @return array updated metadata hashmap
+ */
+ public function updateMetadata(
+ $metadata,
+ $authUri = null,
+ ?callable $httpHandler = null
+ ) {
+ $scope = $this->auth->getScope();
+ if (empty($authUri) && empty($scope)) {
+ return $metadata;
+ }
+
+ $this->auth->setAudience($authUri);
+
+ return parent::updateMetadata($metadata, $authUri, $httpHandler);
+ }
+
+ /**
+ * Implements FetchAuthTokenInterface#fetchAuthToken.
+ *
+ * @param callable|null $httpHandler
+ *
+ * @return null|array{access_token:string} A set of auth related metadata
+ */
+ public function fetchAuthToken(?callable $httpHandler = null)
+ {
+ $audience = $this->auth->getAudience();
+ $scope = $this->auth->getScope();
+ if (empty($audience) && empty($scope)) {
+ return null;
+ }
+
+ if (!empty($audience) && !empty($scope)) {
+ throw new \UnexpectedValueException(
+ 'Cannot sign both audience and scope in JwtAccess'
+ );
+ }
+
+ $access_token = $this->auth->toJwt();
+
+ // Set the self-signed access token in OAuth2 for getLastReceivedToken
+ $this->auth->setAccessToken($access_token);
+
+ return [
+ 'access_token' => $access_token,
+ 'expires_in' => $this->auth->getExpiry(),
+ 'token_type' => 'Bearer'
+ ];
+ }
+
+ /**
+ * Return the cache key for the credentials.
+ * The format for the Cache Key one of the following:
+ * ClientEmail.Scope
+ * ClientEmail.Audience
+ *
+ * @return string
+ */
+ public function getCacheKey()
+ {
+ $scopeOrAudience = $this->auth->getScope();
+ if (!$scopeOrAudience) {
+ $scopeOrAudience = $this->auth->getAudience();
+ }
+
+ return $this->auth->getIssuer() . '.' . $scopeOrAudience;
+ }
+
+ /**
+ * @return array
+ */
+ public function getLastReceivedToken()
+ {
+ return $this->auth->getLastReceivedToken();
+ }
+
+ /**
+ * Get the project ID from the service account keyfile.
+ *
+ * Returns null if the project ID does not exist in the keyfile.
+ *
+ * @param callable|null $httpHandler Not used by this credentials type.
+ * @return string|null
+ */
+ public function getProjectId(?callable $httpHandler = null)
+ {
+ return $this->projectId;
+ }
+
+ /**
+ * Get the client name from the keyfile.
+ *
+ * In this case, it returns the keyfile's client_email key.
+ *
+ * @param callable|null $httpHandler Not used by this credentials type.
+ * @return string
+ */
+ public function getClientName(?callable $httpHandler = null)
+ {
+ return $this->auth->getIssuer();
+ }
+
+ /**
+ * Get the private key from the keyfile.
+ *
+ * In this case, it returns the keyfile's private_key key, needed for JWT signing.
+ *
+ * @return string
+ */
+ public function getPrivateKey()
+ {
+ return $this->auth->getSigningKey();
+ }
+
+ /**
+ * Get the quota project used for this API request
+ *
+ * @return string|null
+ */
+ public function getQuotaProject()
+ {
+ return $this->quotaProject;
+ }
+
+ protected function getCredType(): string
+ {
+ return self::CRED_TYPE;
+ }
+}
diff --git a/vendor/google/auth/src/Credentials/UserRefreshCredentials.php b/vendor/google/auth/src/Credentials/UserRefreshCredentials.php
new file mode 100644
index 0000000..326f6cd
--- /dev/null
+++ b/vendor/google/auth/src/Credentials/UserRefreshCredentials.php
@@ -0,0 +1,202 @@
+ $jsonKey JSON credential file path or JSON credentials
+ * as an associative array
+ * @param string|null $targetAudience The audience for the ID token.
+ */
+ public function __construct(
+ $scope,
+ $jsonKey,
+ ?string $targetAudience = null
+ ) {
+ if (is_string($jsonKey)) {
+ if (!file_exists($jsonKey)) {
+ throw new InvalidArgumentException('file does not exist or is unreadable');
+ }
+ $json = file_get_contents($jsonKey);
+ if (!$jsonKey = json_decode((string) $json, true)) {
+ throw new LogicException('invalid json for auth config');
+ }
+ }
+ if (!array_key_exists('client_id', $jsonKey)) {
+ throw new InvalidArgumentException(
+ 'json key is missing the client_id field'
+ );
+ }
+ if (!array_key_exists('client_secret', $jsonKey)) {
+ throw new InvalidArgumentException(
+ 'json key is missing the client_secret field'
+ );
+ }
+ if (!array_key_exists('refresh_token', $jsonKey)) {
+ throw new InvalidArgumentException(
+ 'json key is missing the refresh_token field'
+ );
+ }
+ if ($scope && $targetAudience) {
+ throw new InvalidArgumentException(
+ 'Scope and targetAudience cannot both be supplied'
+ );
+ }
+ $additionalClaims = [];
+ if ($targetAudience) {
+ $additionalClaims = ['target_audience' => $targetAudience];
+ $this->isIdTokenRequest = true;
+ }
+ $this->auth = new OAuth2([
+ 'clientId' => $jsonKey['client_id'],
+ 'clientSecret' => $jsonKey['client_secret'],
+ 'refresh_token' => $jsonKey['refresh_token'],
+ 'scope' => $scope,
+ 'tokenCredentialUri' => self::TOKEN_CREDENTIAL_URI,
+ 'additionalClaims' => $additionalClaims,
+ ]);
+ if (array_key_exists('quota_project_id', $jsonKey)) {
+ $this->quotaProject = (string) $jsonKey['quota_project_id'];
+ }
+ }
+
+ /**
+ * @param callable|null $httpHandler
+ * @param array $headers [optional] Metrics headers to be inserted
+ * into the token endpoint request present.
+ * This could be passed from ImersonatedServiceAccountCredentials as it uses
+ * UserRefreshCredentials as source credentials.
+ *
+ * @return array {
+ * A set of auth related metadata, containing the following
+ *
+ * @type string $access_token
+ * @type int $expires_in
+ * @type string $scope
+ * @type string $token_type
+ * @type string $id_token
+ * }
+ */
+ public function fetchAuthToken(?callable $httpHandler = null, array $headers = [])
+ {
+ return $this->auth->fetchAuthToken(
+ $httpHandler,
+ $this->applyTokenEndpointMetrics($headers, $this->isIdTokenRequest ? 'it' : 'at')
+ );
+ }
+
+ /**
+ * Return the Cache Key for the credentials.
+ * The format for the Cache key is one of the following:
+ * ClientId.Scope
+ * ClientId.Audience
+ *
+ * @return string
+ */
+ public function getCacheKey()
+ {
+ $scopeOrAudience = $this->auth->getScope();
+ if (!$scopeOrAudience) {
+ $scopeOrAudience = $this->auth->getAudience();
+ }
+
+ return $this->auth->getClientId() . '.' . $scopeOrAudience;
+ }
+
+ /**
+ * @return array
+ */
+ public function getLastReceivedToken()
+ {
+ return $this->auth->getLastReceivedToken();
+ }
+
+ /**
+ * Get the quota project used for this API request
+ *
+ * @return string|null
+ */
+ public function getQuotaProject()
+ {
+ return $this->quotaProject;
+ }
+
+ /**
+ * Get the granted scopes (if they exist) for the last fetched token.
+ *
+ * @return string|null
+ */
+ public function getGrantedScope()
+ {
+ return $this->auth->getGrantedScope();
+ }
+
+ protected function getCredType(): string
+ {
+ return self::CRED_TYPE;
+ }
+}
diff --git a/vendor/google/auth/src/CredentialsLoader.php b/vendor/google/auth/src/CredentialsLoader.php
new file mode 100644
index 0000000..d5d59b6
--- /dev/null
+++ b/vendor/google/auth/src/CredentialsLoader.php
@@ -0,0 +1,319 @@
+|null JSON key | null
+ */
+ public static function fromEnv()
+ {
+ $path = self::getEnv(self::ENV_VAR);
+ if (empty($path)) {
+ return null;
+ }
+ if (!file_exists($path)) {
+ $cause = 'file ' . $path . ' does not exist';
+ throw new \DomainException(self::unableToReadEnv($cause));
+ }
+ $jsonKey = file_get_contents($path);
+
+ return json_decode((string) $jsonKey, true);
+ }
+
+ /**
+ * Load a JSON key from a well known path.
+ *
+ * The well known path is OS dependent:
+ *
+ * * windows: %APPDATA%/gcloud/application_default_credentials.json
+ * * others: $HOME/.config/gcloud/application_default_credentials.json
+ *
+ * If the file does not exist, this returns null.
+ *
+ * @return array|null JSON key | null
+ */
+ public static function fromWellKnownFile()
+ {
+ $rootEnv = self::isOnWindows() ? 'APPDATA' : 'HOME';
+ $path = [self::getEnv($rootEnv)];
+ if (!self::isOnWindows()) {
+ $path[] = self::NON_WINDOWS_WELL_KNOWN_PATH_BASE;
+ }
+ $path[] = self::WELL_KNOWN_PATH;
+ $path = implode(DIRECTORY_SEPARATOR, $path);
+ if (!file_exists($path)) {
+ return null;
+ }
+ $jsonKey = file_get_contents($path);
+ return json_decode((string) $jsonKey, true);
+ }
+
+ /**
+ * Create a new Credentials instance.
+ *
+ * @deprecated This method is being deprecated because of a potential security risk.
+ *
+ * This method does not validate the credential configuration. The security
+ * risk occurs when a credential configuration is accepted from a source
+ * that is not under your control and used without validation on your side.
+ *
+ * If you know that you will be loading credential configurations of a
+ * specific type, it is recommended to use a credential-type-specific
+ * method.
+ * This will ensure that an unexpected credential type with potential for
+ * malicious intent is not loaded unintentionally. You might still have to do
+ * validation for certain credential types. Please follow the recommendation
+ * for that method. For example, if you want to load only service accounts,
+ * you can create the {@see ServiceAccountCredentials} explicitly:
+ *
+ * ```
+ * use Google\Auth\Credentials\ServiceAccountCredentials;
+ * $creds = new ServiceAccountCredentials($scopes, $json);
+ * ```
+ *
+ * If you are loading your credential configuration from an untrusted source and have
+ * not mitigated the risks (e.g. by validating the configuration yourself), make
+ * these changes as soon as possible to prevent security risks to your environment.
+ *
+ * Regardless of the method used, it is always your responsibility to validate
+ * configurations received from external sources.
+ *
+ * @see https://cloud.google.com/docs/authentication/external/externally-sourced-credentials
+ *
+ * @param string|string[] $scope
+ * @param array $jsonKey
+ * @param string|string[] $defaultScope
+ * @return ServiceAccountCredentials|UserRefreshCredentials|ImpersonatedServiceAccountCredentials|ExternalAccountCredentials
+ */
+ public static function makeCredentials(
+ $scope,
+ array $jsonKey,
+ $defaultScope = null
+ ) {
+ if (!array_key_exists('type', $jsonKey)) {
+ throw new \InvalidArgumentException('json key is missing the type field');
+ }
+
+ if ($jsonKey['type'] == 'service_account') {
+ // Do not pass $defaultScope to ServiceAccountCredentials
+ return new ServiceAccountCredentials($scope, $jsonKey);
+ }
+
+ if ($jsonKey['type'] == 'authorized_user') {
+ $anyScope = $scope ?: $defaultScope;
+ return new UserRefreshCredentials($anyScope, $jsonKey);
+ }
+
+ if ($jsonKey['type'] == 'impersonated_service_account') {
+ $anyScope = $scope ?: $defaultScope;
+ return new ImpersonatedServiceAccountCredentials($anyScope, $jsonKey);
+ }
+
+ if ($jsonKey['type'] == 'external_account') {
+ $anyScope = $scope ?: $defaultScope;
+ return new ExternalAccountCredentials($anyScope, $jsonKey);
+ }
+
+ throw new \InvalidArgumentException('invalid value in the type field');
+ }
+
+ /**
+ * Create an authorized HTTP Client from an instance of FetchAuthTokenInterface.
+ *
+ * @param FetchAuthTokenInterface $fetcher is used to fetch the auth token
+ * @param array $httpClientOptions (optional) Array of request options to apply.
+ * @param callable|null $httpHandler (optional) http client to fetch the token.
+ * @param callable|null $tokenCallback (optional) function to be called when a new token is fetched.
+ * @return \GuzzleHttp\Client
+ */
+ public static function makeHttpClient(
+ FetchAuthTokenInterface $fetcher,
+ array $httpClientOptions = [],
+ ?callable $httpHandler = null,
+ ?callable $tokenCallback = null
+ ) {
+ $middleware = new Middleware\AuthTokenMiddleware(
+ $fetcher,
+ $httpHandler,
+ $tokenCallback
+ );
+ $stack = \GuzzleHttp\HandlerStack::create();
+ $stack->push($middleware);
+
+ return new \GuzzleHttp\Client([
+ 'handler' => $stack,
+ 'auth' => 'google_auth',
+ ] + $httpClientOptions);
+ }
+
+ /**
+ * Create a new instance of InsecureCredentials.
+ *
+ * @return InsecureCredentials
+ */
+ public static function makeInsecureCredentials()
+ {
+ return new InsecureCredentials();
+ }
+
+ /**
+ * Fetch a quota project from the environment variable
+ * GOOGLE_CLOUD_QUOTA_PROJECT. Return null if
+ * GOOGLE_CLOUD_QUOTA_PROJECT is not specified.
+ *
+ * @return string|null
+ */
+ public static function quotaProjectFromEnv()
+ {
+ return self::getEnv(self::QUOTA_PROJECT_ENV_VAR) ?: null;
+ }
+
+ /**
+ * Gets a callable which returns the default device certification.
+ *
+ * @throws UnexpectedValueException
+ * @return callable|null
+ */
+ public static function getDefaultClientCertSource()
+ {
+ if (!$clientCertSourceJson = self::loadDefaultClientCertSourceFile()) {
+ return null;
+ }
+ $clientCertSourceCmd = $clientCertSourceJson['cert_provider_command'];
+
+ return function () use ($clientCertSourceCmd) {
+ $cmd = array_map('escapeshellarg', $clientCertSourceCmd);
+ exec(implode(' ', $cmd), $output, $returnVar);
+
+ if (0 === $returnVar) {
+ return implode(PHP_EOL, $output);
+ }
+ throw new RuntimeException(
+ '"cert_provider_command" failed with a nonzero exit code'
+ );
+ };
+ }
+
+ /**
+ * Determines whether or not the default device certificate should be loaded.
+ *
+ * @return bool
+ */
+ public static function shouldLoadClientCertSource()
+ {
+ return filter_var(self::getEnv(self::MTLS_CERT_ENV_VAR), FILTER_VALIDATE_BOOLEAN);
+ }
+
+ /**
+ * @return array{cert_provider_command:string[]}|null
+ */
+ private static function loadDefaultClientCertSourceFile()
+ {
+ $rootEnv = self::isOnWindows() ? 'APPDATA' : 'HOME';
+ $path = sprintf('%s/%s', self::getEnv($rootEnv), self::MTLS_WELL_KNOWN_PATH);
+ if (!file_exists($path)) {
+ return null;
+ }
+ $jsonKey = file_get_contents($path);
+ $clientCertSourceJson = json_decode((string) $jsonKey, true);
+ if (!$clientCertSourceJson) {
+ throw new UnexpectedValueException('Invalid client cert source JSON');
+ }
+ if (!isset($clientCertSourceJson['cert_provider_command'])) {
+ throw new UnexpectedValueException(
+ 'cert source requires "cert_provider_command"'
+ );
+ }
+ if (!is_array($clientCertSourceJson['cert_provider_command'])) {
+ throw new UnexpectedValueException(
+ 'cert source expects "cert_provider_command" to be an array'
+ );
+ }
+ return $clientCertSourceJson;
+ }
+
+ /**
+ * Get the universe domain from the credential. Defaults to "googleapis.com"
+ * for all credential types which do not support universe domain.
+ *
+ * @return string
+ */
+ public function getUniverseDomain(): string
+ {
+ return self::DEFAULT_UNIVERSE_DOMAIN;
+ }
+
+ private static function getEnv(string $env): mixed
+ {
+ return getenv($env) ?: $_ENV[$env] ?? null;
+ }
+}
diff --git a/vendor/google/auth/src/ExecutableHandler/ExecutableHandler.php b/vendor/google/auth/src/ExecutableHandler/ExecutableHandler.php
new file mode 100644
index 0000000..8f5e13f
--- /dev/null
+++ b/vendor/google/auth/src/ExecutableHandler/ExecutableHandler.php
@@ -0,0 +1,83 @@
+ */
+ private array $env = [];
+
+ private ?string $output = null;
+
+ /**
+ * @param array $env
+ */
+ public function __construct(
+ array $env = [],
+ int $timeoutMs = self::DEFAULT_EXECUTABLE_TIMEOUT_MILLIS,
+ ) {
+ if (!class_exists(Process::class)) {
+ throw new RuntimeException(sprintf(
+ 'The "symfony/process" package is required to use %s.',
+ self::class
+ ));
+ }
+ $this->env = $env;
+ $this->timeoutMs = $timeoutMs;
+ }
+
+ /**
+ * @param string $command
+ * @return int
+ */
+ public function __invoke(string $command): int
+ {
+ $process = Process::fromShellCommandline(
+ $command,
+ null,
+ $this->env,
+ null,
+ ($this->timeoutMs / 1000)
+ );
+
+ try {
+ $process->run();
+ } catch (ProcessTimedOutException $e) {
+ throw new ExecutableResponseError(
+ 'The executable failed to finish within the timeout specified.',
+ 'TIMEOUT_EXCEEDED'
+ );
+ }
+
+ $this->output = $process->getOutput() . $process->getErrorOutput();
+
+ return $process->getExitCode();
+ }
+
+ public function getOutput(): ?string
+ {
+ return $this->output;
+ }
+}
diff --git a/vendor/google/auth/src/ExecutableHandler/ExecutableResponseError.php b/vendor/google/auth/src/ExecutableHandler/ExecutableResponseError.php
new file mode 100644
index 0000000..4410902
--- /dev/null
+++ b/vendor/google/auth/src/ExecutableHandler/ExecutableResponseError.php
@@ -0,0 +1,27 @@
+|null $cacheConfig Configuration for the cache
+ * @param CacheItemPoolInterface $cache
+ */
+ public function __construct(
+ FetchAuthTokenInterface $fetcher,
+ ?array $cacheConfig = null,
+ ?CacheItemPoolInterface $cache = null
+ ) {
+ $this->fetcher = $fetcher;
+ $this->cache = $cache;
+ $this->cacheConfig = array_merge([
+ 'lifetime' => 1500,
+ 'prefix' => '',
+ 'cacheUniverseDomain' => $fetcher instanceof Credentials\GCECredentials,
+ ], (array) $cacheConfig);
+ }
+
+ /**
+ * @return FetchAuthTokenInterface
+ */
+ public function getFetcher()
+ {
+ return $this->fetcher;
+ }
+
+ /**
+ * Implements FetchAuthTokenInterface#fetchAuthToken.
+ *
+ * Checks the cache for a valid auth token and fetches the auth tokens
+ * from the supplied fetcher.
+ *
+ * @param callable|null $httpHandler callback which delivers psr7 request
+ * @return array the response
+ * @throws \Exception
+ */
+ public function fetchAuthToken(?callable $httpHandler = null)
+ {
+ if ($cached = $this->fetchAuthTokenFromCache()) {
+ return $cached;
+ }
+
+ $auth_token = $this->fetcher->fetchAuthToken($httpHandler);
+
+ $this->saveAuthTokenInCache($auth_token);
+
+ return $auth_token;
+ }
+
+ /**
+ * @return string
+ */
+ public function getCacheKey()
+ {
+ return $this->getFullCacheKey($this->fetcher->getCacheKey());
+ }
+
+ /**
+ * @return array|null
+ */
+ public function getLastReceivedToken()
+ {
+ return $this->fetcher->getLastReceivedToken();
+ }
+
+ /**
+ * Get the client name from the fetcher.
+ *
+ * @param callable|null $httpHandler An HTTP handler to deliver PSR7 requests.
+ * @return string
+ */
+ public function getClientName(?callable $httpHandler = null)
+ {
+ if (!$this->fetcher instanceof SignBlobInterface) {
+ throw new \RuntimeException(
+ 'Credentials fetcher does not implement ' .
+ 'Google\Auth\SignBlobInterface'
+ );
+ }
+
+ return $this->fetcher->getClientName($httpHandler);
+ }
+
+ /**
+ * Sign a blob using the fetcher.
+ *
+ * @param string $stringToSign The string to sign.
+ * @param bool $forceOpenSsl Require use of OpenSSL for local signing. Does
+ * not apply to signing done using external services. **Defaults to**
+ * `false`.
+ * @return string The resulting signature.
+ * @throws \RuntimeException If the fetcher does not implement
+ * `Google\Auth\SignBlobInterface`.
+ */
+ public function signBlob($stringToSign, $forceOpenSsl = false)
+ {
+ if (!$this->fetcher instanceof SignBlobInterface) {
+ throw new \RuntimeException(
+ 'Credentials fetcher does not implement ' .
+ 'Google\Auth\SignBlobInterface'
+ );
+ }
+
+ // Pass the access token from cache for credentials that sign blobs
+ // using the IAM API. This saves a call to fetch an access token when a
+ // cached token exists.
+ if ($this->fetcher instanceof Credentials\GCECredentials
+ || $this->fetcher instanceof Credentials\ImpersonatedServiceAccountCredentials
+ ) {
+ $cached = $this->fetchAuthTokenFromCache();
+ $accessToken = $cached['access_token'] ?? null;
+ return $this->fetcher->signBlob($stringToSign, $forceOpenSsl, $accessToken);
+ }
+
+ return $this->fetcher->signBlob($stringToSign, $forceOpenSsl);
+ }
+
+ /**
+ * Get the quota project used for this API request from the credentials
+ * fetcher.
+ *
+ * @return string|null
+ */
+ public function getQuotaProject()
+ {
+ if ($this->fetcher instanceof GetQuotaProjectInterface) {
+ return $this->fetcher->getQuotaProject();
+ }
+
+ return null;
+ }
+
+ /**
+ * Get the Project ID from the fetcher.
+ *
+ * @param callable|null $httpHandler Callback which delivers psr7 request
+ * @return string|null
+ * @throws \RuntimeException If the fetcher does not implement
+ * `Google\Auth\ProvidesProjectIdInterface`.
+ */
+ public function getProjectId(?callable $httpHandler = null)
+ {
+ if (!$this->fetcher instanceof ProjectIdProviderInterface) {
+ throw new \RuntimeException(
+ 'Credentials fetcher does not implement ' .
+ 'Google\Auth\ProvidesProjectIdInterface'
+ );
+ }
+
+ // Pass the access token from cache for credentials that require an
+ // access token to fetch the project ID. This saves a call to fetch an
+ // access token when a cached token exists.
+ if ($this->fetcher instanceof Credentials\ExternalAccountCredentials) {
+ $cached = $this->fetchAuthTokenFromCache();
+ $accessToken = $cached['access_token'] ?? null;
+ return $this->fetcher->getProjectId($httpHandler, $accessToken);
+ }
+
+ return $this->fetcher->getProjectId($httpHandler);
+ }
+
+ /*
+ * Get the Universe Domain from the fetcher.
+ *
+ * @return string
+ */
+ public function getUniverseDomain(): string
+ {
+ if ($this->fetcher instanceof GetUniverseDomainInterface) {
+ if ($this->cacheConfig['cacheUniverseDomain']) {
+ return $this->getCachedUniverseDomain($this->fetcher);
+ }
+ return $this->fetcher->getUniverseDomain();
+ }
+
+ return GetUniverseDomainInterface::DEFAULT_UNIVERSE_DOMAIN;
+ }
+
+ /**
+ * Updates metadata with the authorization token.
+ *
+ * @param array $metadata metadata hashmap
+ * @param string $authUri optional auth uri
+ * @param callable|null $httpHandler callback which delivers psr7 request
+ * @return array updated metadata hashmap
+ * @throws \RuntimeException If the fetcher does not implement
+ * `Google\Auth\UpdateMetadataInterface`.
+ */
+ public function updateMetadata(
+ $metadata,
+ $authUri = null,
+ ?callable $httpHandler = null
+ ) {
+ if (!$this->fetcher instanceof UpdateMetadataInterface) {
+ throw new \RuntimeException(
+ 'Credentials fetcher does not implement ' .
+ 'Google\Auth\UpdateMetadataInterface'
+ );
+ }
+
+ $cached = $this->fetchAuthTokenFromCache($authUri);
+ if ($cached) {
+ // Set the access token in the `Authorization` metadata header so
+ // the downstream call to updateMetadata know they don't need to
+ // fetch another token.
+ if (isset($cached['access_token'])) {
+ $metadata[self::AUTH_METADATA_KEY] = [
+ 'Bearer ' . $cached['access_token']
+ ];
+ } elseif (isset($cached['id_token'])) {
+ $metadata[self::AUTH_METADATA_KEY] = [
+ 'Bearer ' . $cached['id_token']
+ ];
+ }
+ }
+
+ $newMetadata = $this->fetcher->updateMetadata(
+ $metadata,
+ $authUri,
+ $httpHandler
+ );
+
+ if (!$cached && $token = $this->fetcher->getLastReceivedToken()) {
+ $this->saveAuthTokenInCache($token, $authUri);
+ }
+
+ return $newMetadata;
+ }
+
+ /**
+ * @param string|null $authUri
+ * @return array|null
+ */
+ private function fetchAuthTokenFromCache($authUri = null)
+ {
+ // Use the cached value if its available.
+ //
+ // TODO: correct caching; update the call to setCachedValue to set the expiry
+ // to the value returned with the auth token.
+ //
+ // TODO: correct caching; enable the cache to be cleared.
+
+ // if $authUri is set, use it as the cache key
+ $cacheKey = $authUri
+ ? $this->getFullCacheKey($authUri)
+ : $this->fetcher->getCacheKey();
+
+ $cached = $this->getCachedValue($cacheKey);
+ if (is_array($cached)) {
+ if (empty($cached['expires_at'])) {
+ // If there is no expiration data, assume token is not expired.
+ // (for JwtAccess and ID tokens)
+ return $cached;
+ }
+ if ((time() + $this->eagerRefreshThresholdSeconds) < $cached['expires_at']) {
+ // access token is not expired
+ return $cached;
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * @param array $authToken
+ * @param string|null $authUri
+ * @return void
+ */
+ private function saveAuthTokenInCache($authToken, $authUri = null)
+ {
+ if (isset($authToken['access_token']) ||
+ isset($authToken['id_token'])) {
+ // if $authUri is set, use it as the cache key
+ $cacheKey = $authUri
+ ? $this->getFullCacheKey($authUri)
+ : $this->fetcher->getCacheKey();
+
+ $this->setCachedValue($cacheKey, $authToken);
+ }
+ }
+
+ private function getCachedUniverseDomain(GetUniverseDomainInterface $fetcher): string
+ {
+ $cacheKey = $this->getFullCacheKey($fetcher->getCacheKey() . 'universe_domain'); // @phpstan-ignore-line
+ if ($universeDomain = $this->getCachedValue($cacheKey)) {
+ return $universeDomain;
+ }
+
+ $universeDomain = $fetcher->getUniverseDomain();
+ $this->setCachedValue($cacheKey, $universeDomain);
+ return $universeDomain;
+ }
+}
diff --git a/vendor/google/auth/src/FetchAuthTokenInterface.php b/vendor/google/auth/src/FetchAuthTokenInterface.php
new file mode 100644
index 0000000..fbbd8b0
--- /dev/null
+++ b/vendor/google/auth/src/FetchAuthTokenInterface.php
@@ -0,0 +1,54 @@
+ a hash of auth tokens
+ */
+ public function fetchAuthToken(?callable $httpHandler = null);
+
+ /**
+ * Obtains a key that can used to cache the results of #fetchAuthToken.
+ *
+ * If the value is empty, the auth token is not cached.
+ *
+ * @return string a key that may be used to cache the auth token.
+ */
+ public function getCacheKey();
+
+ /**
+ * Returns an associative array with the token and
+ * expiration time.
+ *
+ * @return null|array {
+ * The last received access token.
+ *
+ * @type string $access_token The access token string.
+ * @type int $expires_at The time the token expires as a UNIX timestamp.
+ * }
+ */
+ public function getLastReceivedToken();
+}
diff --git a/vendor/google/auth/src/GCECache.php b/vendor/google/auth/src/GCECache.php
new file mode 100644
index 0000000..d3dcd8c
--- /dev/null
+++ b/vendor/google/auth/src/GCECache.php
@@ -0,0 +1,82 @@
+ $cacheConfig Configuration for the cache
+ * @param CacheItemPoolInterface $cache
+ */
+ public function __construct(
+ ?array $cacheConfig = null,
+ ?CacheItemPoolInterface $cache = null
+ ) {
+ $this->cache = $cache;
+ $this->cacheConfig = array_merge([
+ 'lifetime' => 1500,
+ 'prefix' => '',
+ ], (array) $cacheConfig);
+ }
+
+ /**
+ * Caches the result of onGce so the metadata server is not called multiple
+ * times.
+ *
+ * @param callable|null $httpHandler callback which delivers psr7 request
+ * @return bool True if this a GCEInstance, false otherwise
+ */
+ public function onGce(?callable $httpHandler = null)
+ {
+ if (is_null($this->cache)) {
+ return GCECredentials::onGce($httpHandler);
+ }
+
+ $cacheKey = self::GCE_CACHE_KEY;
+ $onGce = $this->getCachedValue($cacheKey);
+
+ if (is_null($onGce)) {
+ $onGce = GCECredentials::onGce($httpHandler);
+ $this->setCachedValue($cacheKey, $onGce);
+ }
+
+ return $onGce;
+ }
+}
diff --git a/vendor/google/auth/src/GetQuotaProjectInterface.php b/vendor/google/auth/src/GetQuotaProjectInterface.php
new file mode 100644
index 0000000..517f062
--- /dev/null
+++ b/vendor/google/auth/src/GetQuotaProjectInterface.php
@@ -0,0 +1,33 @@
+client = $client;
+ $this->logger = $logger;
+ }
+
+ /**
+ * Accepts a PSR-7 request and an array of options and returns a PSR-7 response.
+ *
+ * @param RequestInterface $request
+ * @param array $options
+ * @return ResponseInterface
+ */
+ public function __invoke(RequestInterface $request, array $options = [])
+ {
+ $requestEvent = null;
+
+ if ($this->logger) {
+ $requestEvent = $this->requestLog($request, $options);
+ }
+
+ $response = $this->client->send($request, $options);
+
+ if ($this->logger) {
+ $this->responseLog($response, $requestEvent);
+ }
+
+ return $response;
+ }
+
+ /**
+ * Accepts a PSR-7 request and an array of options and returns a PromiseInterface
+ *
+ * @param RequestInterface $request
+ * @param array $options
+ *
+ * @return \GuzzleHttp\Promise\PromiseInterface
+ */
+ public function async(RequestInterface $request, array $options = [])
+ {
+ $requestEvent = null;
+
+ if ($this->logger) {
+ $requestEvent = $this->requestLog($request, $options);
+ }
+
+ $promise = $this->client->sendAsync($request, $options);
+
+ if ($this->logger) {
+ $promise->then(function (ResponseInterface $response) use ($requestEvent) {
+ $this->responseLog($response, $requestEvent);
+ return $response;
+ });
+ }
+
+ return $promise;
+ }
+
+ /**
+ * @internal
+ * @param RequestInterface $request
+ * @param array $options
+ */
+ public function requestLog(RequestInterface $request, array $options): RpcLogEvent
+ {
+ $requestEvent = new RpcLogEvent();
+
+ $requestEvent->method = $request->getMethod();
+ $requestEvent->url = (string) $request->getUri();
+ $requestEvent->headers = $request->getHeaders();
+ $requestEvent->payload = $request->getBody()->getContents();
+ $requestEvent->retryAttempt = $options['retryAttempt'] ?? null;
+ $requestEvent->serviceName = $options['serviceName'] ?? null;
+ $requestEvent->processId = (int) getmypid();
+ $requestEvent->requestId = $options['requestId'] ?? crc32((string) spl_object_id($request) . getmypid());
+
+ $this->logRequest($requestEvent);
+
+ return $requestEvent;
+ }
+
+ /**
+ * @internal
+ */
+ public function responseLog(ResponseInterface $response, RpcLogEvent $requestEvent): void
+ {
+ $responseEvent = new RpcLogEvent($requestEvent->milliseconds);
+
+ $responseEvent->headers = $response->getHeaders();
+ $responseEvent->payload = $response->getBody()->getContents();
+ $responseEvent->status = $response->getStatusCode();
+ $responseEvent->processId = $requestEvent->processId;
+ $responseEvent->requestId = $requestEvent->requestId;
+
+ $this->logResponse($responseEvent);
+ }
+}
diff --git a/vendor/google/auth/src/HttpHandler/Guzzle7HttpHandler.php b/vendor/google/auth/src/HttpHandler/Guzzle7HttpHandler.php
new file mode 100644
index 0000000..e84f660
--- /dev/null
+++ b/vendor/google/auth/src/HttpHandler/Guzzle7HttpHandler.php
@@ -0,0 +1,21 @@
+remove('http_errors');
+ $stack->unshift(Middleware::httpErrors($bodySummarizer), 'http_errors');
+ }
+ $client = new Client(['handler' => $stack]);
+ }
+
+ $logger = ($logger === false)
+ ? null
+ : $logger ?? ApplicationDefaultCredentials::getDefaultLogger();
+
+ $version = null;
+ if (defined('GuzzleHttp\ClientInterface::MAJOR_VERSION')) {
+ $version = ClientInterface::MAJOR_VERSION;
+ } elseif (defined('GuzzleHttp\ClientInterface::VERSION')) {
+ $version = (int) substr(ClientInterface::VERSION, 0, 1);
+ }
+
+ switch ($version) {
+ case 6:
+ return new Guzzle6HttpHandler($client, $logger);
+ case 7:
+ return new Guzzle7HttpHandler($client, $logger);
+ default:
+ throw new \Exception('Version not supported');
+ }
+ }
+}
diff --git a/vendor/google/auth/src/Iam.php b/vendor/google/auth/src/Iam.php
new file mode 100644
index 0000000..b32ac60
--- /dev/null
+++ b/vendor/google/auth/src/Iam.php
@@ -0,0 +1,155 @@
+httpHandler = $httpHandler
+ ?: HttpHandlerFactory::build(HttpClientCache::getHttpClient());
+ $this->universeDomain = $universeDomain;
+ }
+
+ /**
+ * Sign a string using the IAM signBlob API.
+ *
+ * Note that signing using IAM requires your service account to have the
+ * `iam.serviceAccounts.signBlob` permission, part of the "Service Account
+ * Token Creator" IAM role.
+ *
+ * @param string $email The service account email.
+ * @param string $accessToken An access token from the service account.
+ * @param string $stringToSign The string to be signed.
+ * @param array $delegates [optional] A list of service account emails to
+ * add to the delegate chain. If omitted, the value of `$email` will
+ * be used.
+ * @return string The signed string, base64-encoded.
+ */
+ public function signBlob($email, $accessToken, $stringToSign, array $delegates = [])
+ {
+ $name = sprintf(self::SERVICE_ACCOUNT_NAME, $email);
+ $apiRoot = str_replace('UNIVERSE_DOMAIN', $this->universeDomain, self::IAM_API_ROOT_TEMPLATE);
+ $uri = $apiRoot . '/' . sprintf(self::SIGN_BLOB_PATH, $name);
+
+ if ($delegates) {
+ foreach ($delegates as &$delegate) {
+ $delegate = sprintf(self::SERVICE_ACCOUNT_NAME, $delegate);
+ }
+ } else {
+ $delegates = [$name];
+ }
+
+ $body = [
+ 'delegates' => $delegates,
+ 'payload' => base64_encode($stringToSign),
+ ];
+
+ $headers = [
+ 'Authorization' => 'Bearer ' . $accessToken
+ ];
+
+ $request = new Psr7\Request(
+ 'POST',
+ $uri,
+ $headers,
+ Utils::streamFor(json_encode($body))
+ );
+
+ $res = ($this->httpHandler)($request);
+ $body = json_decode((string) $res->getBody(), true);
+
+ return $body['signedBlob'];
+ }
+
+ /**
+ * Sign a string using the IAM signBlob API.
+ *
+ * Note that signing using IAM requires your service account to have the
+ * `iam.serviceAccounts.signBlob` permission, part of the "Service Account
+ * Token Creator" IAM role.
+ *
+ * @param string $clientEmail The service account email.
+ * @param string $targetAudience The audience for the ID token.
+ * @param string $bearerToken The token to authenticate the IAM request.
+ * @param array $headers [optional] Additional headers to send with the request.
+ *
+ * @return string The signed string, base64-encoded.
+ */
+ public function generateIdToken(
+ string $clientEmail,
+ string $targetAudience,
+ string $bearerToken,
+ array $headers = []
+ ): string {
+ $name = sprintf(self::SERVICE_ACCOUNT_NAME, $clientEmail);
+ $apiRoot = str_replace('UNIVERSE_DOMAIN', $this->universeDomain, self::IAM_API_ROOT_TEMPLATE);
+ $uri = $apiRoot . '/' . sprintf(self::GENERATE_ID_TOKEN_PATH, $name);
+
+ $headers['Authorization'] = 'Bearer ' . $bearerToken;
+
+ $body = [
+ 'audience' => $targetAudience,
+ 'includeEmail' => true,
+ 'useEmailAzp' => true,
+ ];
+
+ $request = new Psr7\Request(
+ 'POST',
+ $uri,
+ $headers,
+ Utils::streamFor(json_encode($body))
+ );
+
+ $res = ($this->httpHandler)($request);
+ $body = json_decode((string) $res->getBody(), true);
+
+ return $body['token'];
+ }
+}
diff --git a/vendor/google/auth/src/IamSignerTrait.php b/vendor/google/auth/src/IamSignerTrait.php
new file mode 100644
index 0000000..da3c909
--- /dev/null
+++ b/vendor/google/auth/src/IamSignerTrait.php
@@ -0,0 +1,72 @@
+iam;
+ if (!$signer) {
+ $signer = $this instanceof GetUniverseDomainInterface
+ ? new Iam($httpHandler, $this->getUniverseDomain())
+ : new Iam($httpHandler);
+ }
+
+ $email = $this->getClientName($httpHandler);
+
+ if (is_null($accessToken)) {
+ $previousToken = $this->getLastReceivedToken();
+ $accessToken = $previousToken
+ ? $previousToken['access_token']
+ : $this->fetchAuthToken($httpHandler)['access_token'];
+ }
+
+ return $signer->signBlob($email, $accessToken, $stringToSign);
+ }
+}
diff --git a/vendor/google/auth/src/Logging/LoggingTrait.php b/vendor/google/auth/src/Logging/LoggingTrait.php
new file mode 100644
index 0000000..0b8330d
--- /dev/null
+++ b/vendor/google/auth/src/Logging/LoggingTrait.php
@@ -0,0 +1,138 @@
+ $event->timestamp,
+ 'severity' => strtoupper(LogLevel::DEBUG),
+ 'processId' => $event->processId ?? null,
+ 'requestId' => $event->requestId ?? null,
+ 'rpcName' => $event->rpcName ?? null,
+ ];
+
+ $debugEvent = array_filter($debugEvent, fn ($value) => !is_null($value));
+
+ $jsonPayload = [
+ 'request.method' => $event->method,
+ 'request.url' => $event->url,
+ 'request.headers' => $event->headers,
+ 'request.payload' => $this->truncatePayload($event->payload),
+ 'request.jwt' => $this->getJwtToken($event->headers ?? []),
+ 'retryAttempt' => $event->retryAttempt
+ ];
+
+ // Remove null values
+ $debugEvent['jsonPayload'] = array_filter($jsonPayload, fn ($value) => !is_null($value));
+
+ $stringifiedEvent = json_encode($debugEvent, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
+
+ // There was an error stringifying the event, return to not break execution
+ if ($stringifiedEvent === false) {
+ return;
+ }
+
+ $this->logger->debug($stringifiedEvent);
+ }
+
+ /**
+ * @param RpcLogEvent $event
+ */
+ private function logResponse(RpcLogEvent $event): void
+ {
+ $debugEvent = [
+ 'timestamp' => $event->timestamp,
+ 'severity' => strtoupper(LogLevel::DEBUG),
+ 'processId' => $event->processId ?? null,
+ 'requestId' => $event->requestId ?? null,
+ 'jsonPayload' => [
+ 'response.status' => $event->status,
+ 'response.headers' => $event->headers,
+ 'response.payload' => $this->truncatePayload($event->payload),
+ 'latencyMillis' => $event->latency,
+ ]
+ ];
+
+ // Remove null values
+ $debugEvent = array_filter($debugEvent, fn ($value) => !is_null($value));
+ $debugEvent['jsonPayload'] = array_filter(
+ $debugEvent['jsonPayload'],
+ fn ($value) => !is_null($value)
+ );
+
+ $stringifiedEvent = json_encode($debugEvent, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
+
+ // There was an error stringifying the event, return to not break execution
+ if ($stringifiedEvent !== false) {
+ $this->logger->debug($stringifiedEvent);
+ }
+ }
+
+ /**
+ * @param array $headers
+ * @return null|array
+ */
+ private function getJwtToken(array $headers): null|array
+ {
+ if (empty($headers)) {
+ return null;
+ }
+
+ $tokenHeader = $headers['Authorization'] ?? '';
+ $token = str_replace('Bearer ', '', $tokenHeader);
+
+ if (substr_count($token, '.') !== 2) {
+ return null;
+ }
+
+ [$header, $token, $_] = explode('.', $token);
+
+ return [
+ 'header' => base64_decode($header),
+ 'token' => base64_decode($token)
+ ];
+ }
+
+ /**
+ * @param null|string $payload
+ * @return string
+ */
+ private function truncatePayload(null|string $payload): null|string
+ {
+ $maxLength = 500;
+
+ if (is_null($payload) || strlen($payload) <= $maxLength) {
+ return $payload;
+ }
+
+ return substr($payload, 0, $maxLength) . '...';
+ }
+}
diff --git a/vendor/google/auth/src/Logging/RpcLogEvent.php b/vendor/google/auth/src/Logging/RpcLogEvent.php
new file mode 100644
index 0000000..50e89fe
--- /dev/null
+++ b/vendor/google/auth/src/Logging/RpcLogEvent.php
@@ -0,0 +1,136 @@
+
+ */
+ public null|array $headers = null;
+
+ /**
+ * An array representation of JSON for the response or request
+ *
+ * @var null|string
+ */
+ public null|string $payload = null;
+
+ /**
+ * Status code for REST or gRPC methods
+ *
+ * @var null|int|string
+ */
+ public null|int|string $status = null;
+
+ /**
+ * The latency in milliseconds
+ *
+ * @var null|int
+ */
+ public null|int $latency = null;
+
+ /**
+ * The retry attempt number
+ *
+ * @var null|int
+ */
+ public null|int $retryAttempt = null;
+
+ /**
+ * The name of the gRPC method being called
+ *
+ * @var null|string
+ */
+ public null|string $rpcName = null;
+
+ /**
+ * The Service Name of the gRPC
+ *
+ * @var null|string $serviceName
+ */
+ public null|string $serviceName = null;
+
+ /**
+ * The Process ID for tracing logs
+ *
+ * @var null|int $processId
+ */
+ public null|int $processId = null;
+
+ /**
+ * The Request id for tracing logs
+ *
+ * @var null|int $requestId;
+ */
+ public null|int $requestId = null;
+
+ /**
+ * Creates an object with all the fields required for logging
+ * Passing a string representation of a timestamp calculates the difference between
+ * these two times and sets the latency field with the result.
+ *
+ * @param null|float $startTime (Optional) Parameter to calculate the latency
+ */
+ public function __construct(null|float $startTime = null)
+ {
+ $this->timestamp = date(DATE_RFC3339);
+
+ // Takes the micro time and convets it to millis
+ $this->milliseconds = round(microtime(true) * 1000);
+
+ if ($startTime) {
+ $this->latency = (int) round($this->milliseconds - $startTime);
+ }
+ }
+}
diff --git a/vendor/google/auth/src/Logging/StdOutLogger.php b/vendor/google/auth/src/Logging/StdOutLogger.php
new file mode 100644
index 0000000..27b1f0e
--- /dev/null
+++ b/vendor/google/auth/src/Logging/StdOutLogger.php
@@ -0,0 +1,85 @@
+
+ */
+ private array $levelMapping = [
+ LogLevel::EMERGENCY => 7,
+ LogLevel::ALERT => 6,
+ LogLevel::CRITICAL => 5,
+ LogLevel::ERROR => 4,
+ LogLevel::WARNING => 3,
+ LogLevel::NOTICE => 2,
+ LogLevel::INFO => 1,
+ LogLevel::DEBUG => 0,
+ ];
+ private int $level;
+
+ /**
+ * Constructs a basic PSR-3 logger class that logs into StdOut for GCP Logging
+ *
+ * @param string $level The level of the logger instance.
+ */
+ public function __construct(string $level = LogLevel::DEBUG)
+ {
+ $this->level = $this->getLevelFromName($level);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function log($level, string|Stringable $message, array $context = []): void
+ {
+ if ($this->getLevelFromName($level) < $this->level) {
+ return;
+ }
+
+ print($message . "\n");
+ }
+
+ /**
+ * @param string $levelName
+ * @return int
+ * @throws InvalidArgumentException
+ */
+ private function getLevelFromName(string $levelName): int
+ {
+ if (!array_key_exists($levelName, $this->levelMapping)) {
+ throw new InvalidArgumentException('The level supplied to the Logger is not valid');
+ }
+
+ return $this->levelMapping[$levelName];
+ }
+}
diff --git a/vendor/google/auth/src/MetricsTrait.php b/vendor/google/auth/src/MetricsTrait.php
new file mode 100644
index 0000000..8d5c03c
--- /dev/null
+++ b/vendor/google/auth/src/MetricsTrait.php
@@ -0,0 +1,120 @@
+ $metadata The metadata to update and return.
+ * @return array The updated metadata.
+ */
+ protected function applyServiceApiUsageMetrics($metadata)
+ {
+ if ($credType = $this->getCredType()) {
+ // Add service api usage observability metrics info into metadata
+ // We expect upstream libries to have the metadata key populated already
+ $value = 'cred-type/' . $credType;
+ if (!isset($metadata[self::$metricMetadataKey])) {
+ // This case will happen only when someone invokes the updateMetadata
+ // method on the credentials fetcher themselves.
+ $metadata[self::$metricMetadataKey] = [$value];
+ } elseif (is_array($metadata[self::$metricMetadataKey])) {
+ $metadata[self::$metricMetadataKey][0] .= ' ' . $value;
+ } else {
+ $metadata[self::$metricMetadataKey] .= ' ' . $value;
+ }
+ }
+
+ return $metadata;
+ }
+
+ /**
+ * @param array $metadata The metadata to update and return.
+ * @param string $authRequestType The auth request type. Possible values are
+ * `'at'`, `'it'`, `'mds'`.
+ * @return array The updated metadata.
+ */
+ protected function applyTokenEndpointMetrics($metadata, $authRequestType)
+ {
+ $metricsHeader = self::getMetricsHeader($this->getCredType(), $authRequestType);
+ if (!isset($metadata[self::$metricMetadataKey])) {
+ $metadata[self::$metricMetadataKey] = $metricsHeader;
+ }
+ return $metadata;
+ }
+
+ protected static function getVersion(): string
+ {
+ if (is_null(self::$version)) {
+ $versionFilePath = __DIR__ . '/../VERSION';
+ self::$version = trim((string) file_get_contents($versionFilePath));
+ }
+ return self::$version;
+ }
+
+ protected function getCredType(): string
+ {
+ return '';
+ }
+}
diff --git a/vendor/google/auth/src/Middleware/AuthTokenMiddleware.php b/vendor/google/auth/src/Middleware/AuthTokenMiddleware.php
new file mode 100644
index 0000000..b8f2c51
--- /dev/null
+++ b/vendor/google/auth/src/Middleware/AuthTokenMiddleware.php
@@ -0,0 +1,163 @@
+'
+ */
+class AuthTokenMiddleware
+{
+ /**
+ * @var callable
+ */
+ private $httpHandler;
+
+ /**
+ * It must be an implementation of FetchAuthTokenInterface.
+ * It may also implement UpdateMetadataInterface allowing direct
+ * retrieval of auth related headers
+ * @var FetchAuthTokenInterface
+ */
+ private $fetcher;
+
+ /**
+ * @var ?callable
+ */
+ private $tokenCallback;
+
+ /**
+ * Creates a new AuthTokenMiddleware.
+ *
+ * @param FetchAuthTokenInterface $fetcher is used to fetch the auth token
+ * @param callable|null $httpHandler (optional) callback which delivers psr7 request
+ * @param callable|null $tokenCallback (optional) function to be called when a new token is fetched.
+ */
+ public function __construct(
+ FetchAuthTokenInterface $fetcher,
+ ?callable $httpHandler = null,
+ ?callable $tokenCallback = null
+ ) {
+ $this->fetcher = $fetcher;
+ $this->httpHandler = $httpHandler;
+ $this->tokenCallback = $tokenCallback;
+ }
+
+ /**
+ * Updates the request with an Authorization header when auth is 'google_auth'.
+ *
+ * use Google\Auth\Middleware\AuthTokenMiddleware;
+ * use Google\Auth\OAuth2;
+ * use GuzzleHttp\Client;
+ * use GuzzleHttp\HandlerStack;
+ *
+ * $config = [...];
+ * $oauth2 = new OAuth2($config)
+ * $middleware = new AuthTokenMiddleware($oauth2);
+ * $stack = HandlerStack::create();
+ * $stack->push($middleware);
+ *
+ * $client = new Client([
+ * 'handler' => $stack,
+ * 'base_uri' => 'https://www.googleapis.com/taskqueue/v1beta2/projects/',
+ * 'auth' => 'google_auth' // authorize all requests
+ * ]);
+ *
+ * $res = $client->get('myproject/taskqueues/myqueue');
+ *
+ * @param callable $handler
+ * @return \Closure
+ */
+ public function __invoke(callable $handler)
+ {
+ return function (RequestInterface $request, array $options) use ($handler) {
+ // Requests using "auth"="google_auth" will be authorized.
+ if (!isset($options['auth']) || $options['auth'] !== 'google_auth') {
+ return $handler($request, $options);
+ }
+
+ $request = $this->addAuthHeaders($request);
+
+ if ($quotaProject = $this->getQuotaProject()) {
+ $request = $request->withHeader(
+ GetQuotaProjectInterface::X_GOOG_USER_PROJECT_HEADER,
+ $quotaProject
+ );
+ }
+
+ return $handler($request, $options);
+ };
+ }
+
+ /**
+ * Adds auth related headers to the request.
+ *
+ * @param RequestInterface $request
+ * @return RequestInterface
+ */
+ private function addAuthHeaders(RequestInterface $request)
+ {
+ if (!$this->fetcher instanceof UpdateMetadataInterface ||
+ ($this->fetcher instanceof FetchAuthTokenCache &&
+ !$this->fetcher->getFetcher() instanceof UpdateMetadataInterface)
+ ) {
+ $token = $this->fetcher->fetchAuthToken();
+ $request = $request->withHeader(
+ 'authorization',
+ 'Bearer ' . ($token['access_token'] ?? $token['id_token'] ?? '')
+ );
+ } else {
+ $headers = $this->fetcher->updateMetadata($request->getHeaders(), null, $this->httpHandler);
+ $request = Utils::modifyRequest($request, ['set_headers' => $headers]);
+ }
+
+ if ($this->tokenCallback && ($token = $this->fetcher->getLastReceivedToken())) {
+ if (array_key_exists('access_token', $token)) {
+ call_user_func($this->tokenCallback, $this->fetcher->getCacheKey(), $token['access_token']);
+ }
+ }
+
+ return $request;
+ }
+
+ /**
+ * @return string|null
+ */
+ private function getQuotaProject()
+ {
+ if ($this->fetcher instanceof GetQuotaProjectInterface) {
+ return $this->fetcher->getQuotaProject();
+ }
+
+ return null;
+ }
+}
diff --git a/vendor/google/auth/src/Middleware/ProxyAuthTokenMiddleware.php b/vendor/google/auth/src/Middleware/ProxyAuthTokenMiddleware.php
new file mode 100644
index 0000000..2c44871
--- /dev/null
+++ b/vendor/google/auth/src/Middleware/ProxyAuthTokenMiddleware.php
@@ -0,0 +1,155 @@
+'
+ */
+class ProxyAuthTokenMiddleware
+{
+ /**
+ * @var callable
+ */
+ private $httpHandler;
+
+ /**
+ * @var FetchAuthTokenInterface
+ */
+ private $fetcher;
+
+ /**
+ * @var ?callable
+ */
+ private $tokenCallback;
+
+ /**
+ * Creates a new ProxyAuthTokenMiddleware.
+ *
+ * @param FetchAuthTokenInterface $fetcher is used to fetch the auth token
+ * @param callable|null $httpHandler (optional) callback which delivers psr7 request
+ * @param callable|null $tokenCallback (optional) function to be called when a new token is fetched.
+ */
+ public function __construct(
+ FetchAuthTokenInterface $fetcher,
+ ?callable $httpHandler = null,
+ ?callable $tokenCallback = null
+ ) {
+ $this->fetcher = $fetcher;
+ $this->httpHandler = $httpHandler;
+ $this->tokenCallback = $tokenCallback;
+ }
+
+ /**
+ * Updates the request with an Authorization header when auth is 'google_auth'.
+ *
+ * use Google\Auth\Middleware\ProxyAuthTokenMiddleware;
+ * use Google\Auth\OAuth2;
+ * use GuzzleHttp\Client;
+ * use GuzzleHttp\HandlerStack;
+ *
+ * $config = [...];
+ * $oauth2 = new OAuth2($config)
+ * $middleware = new ProxyAuthTokenMiddleware($oauth2);
+ * $stack = HandlerStack::create();
+ * $stack->push($middleware);
+ *
+ * $client = new Client([
+ * 'handler' => $stack,
+ * 'base_uri' => 'https://www.googleapis.com/taskqueue/v1beta2/projects/',
+ * 'proxy_auth' => 'google_auth' // authorize all requests
+ * ]);
+ *
+ * $res = $client->get('myproject/taskqueues/myqueue');
+ *
+ * @param callable $handler
+ * @return \Closure
+ */
+ public function __invoke(callable $handler)
+ {
+ return function (RequestInterface $request, array $options) use ($handler) {
+ // Requests using "proxy_auth"="google_auth" will be authorized.
+ if (!isset($options['proxy_auth']) || $options['proxy_auth'] !== 'google_auth') {
+ return $handler($request, $options);
+ }
+
+ $request = $request->withHeader('proxy-authorization', 'Bearer ' . $this->fetchToken());
+
+ if ($quotaProject = $this->getQuotaProject()) {
+ $request = $request->withHeader(
+ GetQuotaProjectInterface::X_GOOG_USER_PROJECT_HEADER,
+ $quotaProject
+ );
+ }
+
+ return $handler($request, $options);
+ };
+ }
+
+ /**
+ * Call fetcher to fetch the token.
+ *
+ * @return string|null
+ */
+ private function fetchToken()
+ {
+ $auth_tokens = $this->fetcher->fetchAuthToken($this->httpHandler);
+
+ if (array_key_exists('access_token', $auth_tokens)) {
+ // notify the callback if applicable
+ if ($this->tokenCallback) {
+ call_user_func(
+ $this->tokenCallback,
+ $this->fetcher->getCacheKey(),
+ $auth_tokens['access_token']
+ );
+ }
+
+ return $auth_tokens['access_token'];
+ }
+
+ if (array_key_exists('id_token', $auth_tokens)) {
+ return $auth_tokens['id_token'];
+ }
+
+ return null;
+ }
+
+ /**
+ * @return string|null;
+ */
+ private function getQuotaProject()
+ {
+ if ($this->fetcher instanceof GetQuotaProjectInterface) {
+ return $this->fetcher->getQuotaProject();
+ }
+
+ return null;
+ }
+}
diff --git a/vendor/google/auth/src/Middleware/ScopedAccessTokenMiddleware.php b/vendor/google/auth/src/Middleware/ScopedAccessTokenMiddleware.php
new file mode 100644
index 0000000..f2f85cc
--- /dev/null
+++ b/vendor/google/auth/src/Middleware/ScopedAccessTokenMiddleware.php
@@ -0,0 +1,165 @@
+'
+ */
+class ScopedAccessTokenMiddleware
+{
+ use CacheTrait;
+
+ const DEFAULT_CACHE_LIFETIME = 1500;
+
+ /**
+ * @var callable
+ */
+ private $tokenFunc;
+
+ /**
+ * @var array|string
+ */
+ private $scopes;
+
+ /**
+ * Creates a new ScopedAccessTokenMiddleware.
+ *
+ * @param callable $tokenFunc a token generator function
+ * @param array|string $scopes the token authentication scopes
+ * @param array|null $cacheConfig configuration for the cache when it's present
+ * @param CacheItemPoolInterface|null $cache an implementation of CacheItemPoolInterface
+ */
+ public function __construct(
+ callable $tokenFunc,
+ $scopes,
+ ?array $cacheConfig = null,
+ ?CacheItemPoolInterface $cache = null
+ ) {
+ $this->tokenFunc = $tokenFunc;
+ if (!(is_string($scopes) || is_array($scopes))) {
+ throw new \InvalidArgumentException(
+ 'wants scope should be string or array'
+ );
+ }
+ $this->scopes = $scopes;
+
+ if (!is_null($cache)) {
+ $this->cache = $cache;
+ $this->cacheConfig = array_merge([
+ 'lifetime' => self::DEFAULT_CACHE_LIFETIME,
+ 'prefix' => '',
+ ], $cacheConfig);
+ }
+ }
+
+ /**
+ * Updates the request with an Authorization header when auth is 'scoped'.
+ *
+ * E.g this could be used to authenticate using the AppEngine
+ * AppIdentityService.
+ *
+ * use google\appengine\api\app_identity\AppIdentityService;
+ * use Google\Auth\Middleware\ScopedAccessTokenMiddleware;
+ * use GuzzleHttp\Client;
+ * use GuzzleHttp\HandlerStack;
+ *
+ * $scope = 'https://www.googleapis.com/auth/taskqueue'
+ * $middleware = new ScopedAccessTokenMiddleware(
+ * 'AppIdentityService::getAccessToken',
+ * $scope,
+ * [ 'prefix' => 'Google\Auth\ScopedAccessToken::' ],
+ * $cache = new Memcache()
+ * );
+ * $stack = HandlerStack::create();
+ * $stack->push($middleware);
+ *
+ * $client = new Client([
+ * 'handler' => $stack,
+ * 'base_url' => 'https://www.googleapis.com/taskqueue/v1beta2/projects/',
+ * 'auth' => 'scoped' // authorize all requests
+ * ]);
+ *
+ * $res = $client->get('myproject/taskqueues/myqueue');
+ *
+ * @param callable $handler
+ * @return \Closure
+ */
+ public function __invoke(callable $handler)
+ {
+ return function (RequestInterface $request, array $options) use ($handler) {
+ // Requests using "auth"="scoped" will be authorized.
+ if (!isset($options['auth']) || $options['auth'] !== 'scoped') {
+ return $handler($request, $options);
+ }
+
+ $request = $request->withHeader('authorization', 'Bearer ' . $this->fetchToken());
+
+ return $handler($request, $options);
+ };
+ }
+
+ /**
+ * @return string
+ */
+ private function getCacheKey()
+ {
+ $key = null;
+
+ if (is_string($this->scopes)) {
+ $key .= $this->scopes;
+ } elseif (is_array($this->scopes)) {
+ $key .= implode(':', $this->scopes);
+ }
+
+ return $key;
+ }
+
+ /**
+ * Determine if token is available in the cache, if not call tokenFunc to
+ * fetch it.
+ *
+ * @return string
+ */
+ private function fetchToken()
+ {
+ $cacheKey = $this->getCacheKey();
+ $cached = $this->getCachedValue($cacheKey);
+
+ if (!empty($cached)) {
+ return $cached;
+ }
+
+ $token = call_user_func($this->tokenFunc, $this->scopes);
+ $this->setCachedValue($cacheKey, $token);
+
+ return $token;
+ }
+}
diff --git a/vendor/google/auth/src/Middleware/SimpleMiddleware.php b/vendor/google/auth/src/Middleware/SimpleMiddleware.php
new file mode 100644
index 0000000..6940430
--- /dev/null
+++ b/vendor/google/auth/src/Middleware/SimpleMiddleware.php
@@ -0,0 +1,92 @@
+
+ */
+ private $config;
+
+ /**
+ * Create a new Simple plugin.
+ *
+ * The configuration array expects one option
+ * - key: required, otherwise InvalidArgumentException is thrown
+ *
+ * @param array $config Configuration array
+ */
+ public function __construct(array $config)
+ {
+ if (!isset($config['key'])) {
+ throw new \InvalidArgumentException('requires a key to have been set');
+ }
+
+ $this->config = array_merge(['key' => null], $config);
+ }
+
+ /**
+ * Updates the request query with the developer key if auth is set to simple.
+ *
+ * use Google\Auth\Middleware\SimpleMiddleware;
+ * use GuzzleHttp\Client;
+ * use GuzzleHttp\HandlerStack;
+ *
+ * $my_key = 'is not the same as yours';
+ * $middleware = new SimpleMiddleware(['key' => $my_key]);
+ * $stack = HandlerStack::create();
+ * $stack->push($middleware);
+ *
+ * $client = new Client([
+ * 'handler' => $stack,
+ * 'base_uri' => 'https://www.googleapis.com/discovery/v1/',
+ * 'auth' => 'simple'
+ * ]);
+ *
+ * $res = $client->get('drive/v2/rest');
+ *
+ * @param callable $handler
+ * @return \Closure
+ */
+ public function __invoke(callable $handler)
+ {
+ return function (RequestInterface $request, array $options) use ($handler) {
+ // Requests using "auth"="scoped" will be authorized.
+ if (!isset($options['auth']) || $options['auth'] !== 'simple') {
+ return $handler($request, $options);
+ }
+
+ $query = Query::parse($request->getUri()->getQuery());
+ $params = array_merge($query, $this->config);
+ $uri = $request->getUri()->withQuery(Query::build($params));
+ $request = $request->withUri($uri);
+
+ return $handler($request, $options);
+ };
+ }
+}
diff --git a/vendor/google/auth/src/OAuth2.php b/vendor/google/auth/src/OAuth2.php
new file mode 100644
index 0000000..ced3464
--- /dev/null
+++ b/vendor/google/auth/src/OAuth2.php
@@ -0,0 +1,1828 @@
+
+ */
+ public static $knownSigningAlgorithms = [
+ 'HS256',
+ 'HS512',
+ 'HS384',
+ 'RS256',
+ ];
+
+ /**
+ * The well known grant types.
+ *
+ * @var array
+ */
+ public static $knownGrantTypes = [
+ 'authorization_code',
+ 'refresh_token',
+ 'password',
+ 'client_credentials',
+ ];
+
+ /**
+ * - authorizationUri
+ * The authorization server's HTTP endpoint capable of
+ * authenticating the end-user and obtaining authorization.
+ *
+ * @var ?UriInterface
+ */
+ private $authorizationUri;
+
+ /**
+ * - tokenCredentialUri
+ * The authorization server's HTTP endpoint capable of issuing
+ * tokens and refreshing expired tokens.
+ *
+ * @var UriInterface
+ */
+ private $tokenCredentialUri;
+
+ /**
+ * The redirection URI used in the initial request.
+ *
+ * @var ?string
+ */
+ private $redirectUri;
+
+ /**
+ * A unique identifier issued to the client to identify itself to the
+ * authorization server.
+ *
+ * @var string
+ */
+ private $clientId;
+
+ /**
+ * A shared symmetric secret issued by the authorization server, which is
+ * used to authenticate the client.
+ *
+ * @var string
+ */
+ private $clientSecret;
+
+ /**
+ * The resource owner's username.
+ *
+ * @var ?string
+ */
+ private $username;
+
+ /**
+ * The resource owner's password.
+ *
+ * @var ?string
+ */
+ private $password;
+
+ /**
+ * The scope of the access request, expressed either as an Array or as a
+ * space-delimited string.
+ *
+ * @var ?array
+ */
+ private $scope;
+
+ /**
+ * An arbitrary string designed to allow the client to maintain state.
+ *
+ * @var string
+ */
+ private $state;
+
+ /**
+ * The authorization code issued to this client.
+ *
+ * Only used by the authorization code access grant type.
+ *
+ * @var ?string
+ */
+ private $code;
+
+ /**
+ * The issuer ID when using assertion profile.
+ *
+ * @var ?string
+ */
+ private $issuer;
+
+ /**
+ * The target audience for assertions.
+ *
+ * @var string
+ */
+ private $audience;
+
+ /**
+ * The target sub when issuing assertions.
+ *
+ * @var string
+ */
+ private $sub;
+
+ /**
+ * The number of seconds assertions are valid for.
+ *
+ * @var int
+ */
+ private $expiry;
+
+ /**
+ * The signing key when using assertion profile.
+ *
+ * @var ?string
+ */
+ private $signingKey;
+
+ /**
+ * The signing key id when using assertion profile. Param kid in jwt header
+ *
+ * @var string
+ */
+ private $signingKeyId;
+
+ /**
+ * The signing algorithm when using an assertion profile.
+ *
+ * @var ?string
+ */
+ private $signingAlgorithm;
+
+ /**
+ * The refresh token associated with the access token to be refreshed.
+ *
+ * @var ?string
+ */
+ private $refreshToken;
+
+ /**
+ * The current access token.
+ *
+ * @var string
+ */
+ private $accessToken;
+
+ /**
+ * The current ID token.
+ *
+ * @var string
+ */
+ private $idToken;
+
+ /**
+ * The scopes granted to the current access token
+ *
+ * @var string
+ */
+ private $grantedScope;
+
+ /**
+ * The lifetime in seconds of the current access token.
+ *
+ * @var ?int
+ */
+ private $expiresIn;
+
+ /**
+ * The expiration time of the access token as a number of seconds since the
+ * unix epoch.
+ *
+ * @var ?int
+ */
+ private $expiresAt;
+
+ /**
+ * The issue time of the access token as a number of seconds since the unix
+ * epoch.
+ *
+ * @var ?int
+ */
+ private $issuedAt;
+
+ /**
+ * The current grant type.
+ *
+ * @var ?string
+ */
+ private $grantType;
+
+ /**
+ * When using an extension grant type, this is the set of parameters used by
+ * that extension.
+ *
+ * @var array
+ */
+ private $extensionParams;
+
+ /**
+ * When using the toJwt function, these claims will be added to the JWT
+ * payload.
+ *
+ * @var array
+ */
+ private $additionalClaims;
+
+ /**
+ * The code verifier for PKCE for OAuth 2.0. When set, the authorization
+ * URI will contain the Code Challenge and Code Challenge Method querystring
+ * parameters, and the token URI will contain the Code Verifier parameter.
+ *
+ * @see https://datatracker.ietf.org/doc/html/rfc7636
+ * @var ?string
+ */
+ private $codeVerifier;
+
+ /**
+ * For STS requests.
+ * A URI that indicates the target service or resource where the client
+ * intends to use the requested security token.
+ */
+ private ?string $resource;
+
+ /**
+ * For STS requests.
+ * A fetcher for the "subject_token", which is a security token that
+ * represents the identity of the party on behalf of whom the request is
+ * being made.
+ */
+ private ?ExternalAccountCredentialSourceInterface $subjectTokenFetcher;
+
+ /**
+ * For STS requests.
+ * An identifier, that indicates the type of the security token in the
+ * subjectToken parameter.
+ */
+ private ?string $subjectTokenType;
+
+ /**
+ * For STS requests.
+ * A security token that represents the identity of the acting party.
+ */
+ private ?string $actorToken;
+
+ /**
+ * For STS requests.
+ * An identifier that indicates the type of the security token in the
+ * actorToken parameter.
+ */
+ private ?string $actorTokenType;
+
+ /**
+ * From STS response.
+ * An identifier for the representation of the issued security token.
+ */
+ private ?string $issuedTokenType = null;
+
+ /**
+ * From STS response.
+ * An identifier for the representation of the issued security token.
+ *
+ * @var array
+ */
+ private array $additionalOptions;
+
+ /**
+ * Create a new OAuthCredentials.
+ *
+ * The configuration array accepts various options
+ *
+ * - authorizationUri
+ * The authorization server's HTTP endpoint capable of
+ * authenticating the end-user and obtaining authorization.
+ *
+ * - tokenCredentialUri
+ * The authorization server's HTTP endpoint capable of issuing
+ * tokens and refreshing expired tokens.
+ *
+ * - clientId
+ * A unique identifier issued to the client to identify itself to the
+ * authorization server.
+ *
+ * - clientSecret
+ * A shared symmetric secret issued by the authorization server,
+ * which is used to authenticate the client.
+ *
+ * - scope
+ * The scope of the access request, expressed either as an Array
+ * or as a space-delimited String.
+ *
+ * - state
+ * An arbitrary string designed to allow the client to maintain state.
+ *
+ * - redirectUri
+ * The redirection URI used in the initial request.
+ *
+ * - username
+ * The resource owner's username.
+ *
+ * - password
+ * The resource owner's password.
+ *
+ * - issuer
+ * Issuer ID when using assertion profile
+ *
+ * - audience
+ * Target audience for assertions
+ *
+ * - expiry
+ * Number of seconds assertions are valid for
+ *
+ * - signingKey
+ * Signing key when using assertion profile
+ *
+ * - signingKeyId
+ * Signing key id when using assertion profile
+ *
+ * - refreshToken
+ * The refresh token associated with the access token
+ * to be refreshed.
+ *
+ * - accessToken
+ * The current access token for this client.
+ *
+ * - idToken
+ * The current ID token for this client.
+ *
+ * - extensionParams
+ * When using an extension grant type, this is the set of parameters used
+ * by that extension.
+ *
+ * - codeVerifier
+ * The code verifier for PKCE for OAuth 2.0.
+ *
+ * - resource
+ * The target service or resource where the client ntends to use the
+ * requested security token.
+ *
+ * - subjectTokenFetcher
+ * A fetcher for the "subject_token", which is a security token that
+ * represents the identity of the party on behalf of whom the request is
+ * being made.
+ *
+ * - subjectTokenType
+ * An identifier that indicates the type of the security token in the
+ * subjectToken parameter.
+ *
+ * - actorToken
+ * A security token that represents the identity of the acting party.
+ *
+ * - actorTokenType
+ * An identifier for the representation of the issued security token.
+ *
+ * @param array $config Configuration array
+ */
+ public function __construct(array $config)
+ {
+ $opts = array_merge([
+ 'expiry' => self::DEFAULT_EXPIRY_SECONDS,
+ 'extensionParams' => [],
+ 'authorizationUri' => null,
+ 'redirectUri' => null,
+ 'tokenCredentialUri' => null,
+ 'state' => null,
+ 'username' => null,
+ 'password' => null,
+ 'clientId' => null,
+ 'clientSecret' => null,
+ 'issuer' => null,
+ 'sub' => null,
+ 'audience' => null,
+ 'signingKey' => null,
+ 'signingKeyId' => null,
+ 'signingAlgorithm' => null,
+ 'scope' => null,
+ 'additionalClaims' => [],
+ 'codeVerifier' => null,
+ 'resource' => null,
+ 'subjectTokenFetcher' => null,
+ 'subjectTokenType' => null,
+ 'actorToken' => null,
+ 'actorTokenType' => null,
+ 'additionalOptions' => [],
+ ], $config);
+
+ $this->setAuthorizationUri($opts['authorizationUri']);
+ $this->setRedirectUri($opts['redirectUri']);
+ $this->setTokenCredentialUri($opts['tokenCredentialUri']);
+ $this->setState($opts['state']);
+ $this->setUsername($opts['username']);
+ $this->setPassword($opts['password']);
+ $this->setClientId($opts['clientId']);
+ $this->setClientSecret($opts['clientSecret']);
+ $this->setIssuer($opts['issuer']);
+ $this->setSub($opts['sub']);
+ $this->setExpiry($opts['expiry']);
+ $this->setAudience($opts['audience']);
+ $this->setSigningKey($opts['signingKey']);
+ $this->setSigningKeyId($opts['signingKeyId']);
+ $this->setSigningAlgorithm($opts['signingAlgorithm']);
+ $this->setScope($opts['scope']);
+ $this->setExtensionParams($opts['extensionParams']);
+ $this->setAdditionalClaims($opts['additionalClaims']);
+ $this->setCodeVerifier($opts['codeVerifier']);
+
+ // for STS
+ $this->resource = $opts['resource'];
+ $this->subjectTokenFetcher = $opts['subjectTokenFetcher'];
+ $this->subjectTokenType = $opts['subjectTokenType'];
+ $this->actorToken = $opts['actorToken'];
+ $this->actorTokenType = $opts['actorTokenType'];
+ $this->additionalOptions = $opts['additionalOptions'];
+
+ $this->updateToken($opts);
+ }
+
+ /**
+ * Verifies the idToken if present.
+ *
+ * - if none is present, return null
+ * - if present, but invalid, raises DomainException.
+ * - otherwise returns the payload in the idtoken as a PHP object.
+ *
+ * The behavior of this method varies depending on the version of
+ * `firebase/php-jwt` you are using. In versions 6.0 and above, you cannot
+ * provide multiple $allowed_algs, and instead must provide an array of Key
+ * objects as the $publicKey.
+ *
+ * @param string|Key|Key[] $publicKey The public key to use to authenticate the token
+ * @param string|array $allowed_algs algorithm or array of supported verification algorithms.
+ * Providing more than one algorithm will throw an exception.
+ * @throws \DomainException if the token is missing an audience.
+ * @throws \DomainException if the audience does not match the one set in
+ * the OAuth2 class instance.
+ * @throws \UnexpectedValueException If the token is invalid
+ * @throws \InvalidArgumentException If more than one value for allowed_algs is supplied
+ * @throws \Firebase\JWT\SignatureInvalidException If the signature is invalid.
+ * @throws \Firebase\JWT\BeforeValidException If the token is not yet valid.
+ * @throws \Firebase\JWT\ExpiredException If the token has expired.
+ * @return null|object
+ */
+ public function verifyIdToken($publicKey = null, $allowed_algs = [])
+ {
+ $idToken = $this->getIdToken();
+ if (is_null($idToken)) {
+ return null;
+ }
+
+ $resp = $this->jwtDecode($idToken, $publicKey, $allowed_algs);
+ if (!property_exists($resp, 'aud')) {
+ throw new \DomainException('No audience found the id token');
+ }
+ if ($resp->aud != $this->getAudience()) {
+ throw new \DomainException('Wrong audience present in the id token');
+ }
+
+ return $resp;
+ }
+
+ /**
+ * Obtains the encoded jwt from the instance data.
+ *
+ * @param array $config array optional configuration parameters
+ * @return string
+ */
+ public function toJwt(array $config = [])
+ {
+ if (is_null($this->getSigningKey())) {
+ throw new \DomainException('No signing key available');
+ }
+ if (is_null($this->getSigningAlgorithm())) {
+ throw new \DomainException('No signing algorithm specified');
+ }
+ $now = time();
+
+ $opts = array_merge([
+ 'skew' => self::DEFAULT_SKEW_SECONDS,
+ ], $config);
+
+ $assertion = [
+ 'iss' => $this->getIssuer(),
+ 'exp' => ($now + $this->getExpiry()),
+ 'iat' => ($now - $opts['skew']),
+ ];
+ foreach ($assertion as $k => $v) {
+ if (is_null($v)) {
+ throw new \DomainException($k . ' should not be null');
+ }
+ }
+ if (!(is_null($this->getAudience()))) {
+ $assertion['aud'] = $this->getAudience();
+ }
+
+ if (!(is_null($this->getScope()))) {
+ $assertion['scope'] = $this->getScope();
+ }
+
+ if (empty($assertion['scope']) && empty($assertion['aud'])) {
+ throw new \DomainException('one of scope or aud should not be null');
+ }
+
+ if (!(is_null($this->getSub()))) {
+ $assertion['sub'] = $this->getSub();
+ }
+ $assertion += $this->getAdditionalClaims();
+
+ return JWT::encode(
+ $assertion,
+ $this->getSigningKey(),
+ $this->getSigningAlgorithm(),
+ $this->getSigningKeyId()
+ );
+ }
+
+ /**
+ * Generates a request for token credentials.
+ *
+ * @param callable|null $httpHandler callback which delivers psr7 request
+ * @param array $headers [optional] Additional headers to pass to
+ * the token endpoint request.
+ * @return RequestInterface the authorization Url.
+ */
+ public function generateCredentialsRequest(?callable $httpHandler = null, array $headers = [])
+ {
+ $uri = $this->getTokenCredentialUri();
+ if (is_null($uri)) {
+ throw new \DomainException('No token credential URI was set.');
+ }
+
+ $grantType = $this->getGrantType();
+ $params = ['grant_type' => $grantType];
+ switch ($grantType) {
+ case 'authorization_code':
+ $params['code'] = $this->getCode();
+ $params['redirect_uri'] = $this->getRedirectUri();
+ if ($this->codeVerifier) {
+ $params['code_verifier'] = $this->codeVerifier;
+ }
+ $this->addClientCredentials($params);
+ break;
+ case 'password':
+ $params['username'] = $this->getUsername();
+ $params['password'] = $this->getPassword();
+ $this->addClientCredentials($params);
+ break;
+ case 'refresh_token':
+ $params['refresh_token'] = $this->getRefreshToken();
+ if (isset($this->getAdditionalClaims()['target_audience'])) {
+ $params['target_audience'] = $this->getAdditionalClaims()['target_audience'];
+ }
+ $this->addClientCredentials($params);
+ break;
+ case self::JWT_URN:
+ $params['assertion'] = $this->toJwt();
+ break;
+ case self::STS_URN:
+ $token = $this->subjectTokenFetcher->fetchSubjectToken($httpHandler);
+ $params['subject_token'] = $token;
+ $params['subject_token_type'] = $this->subjectTokenType;
+ $params += array_filter([
+ 'resource' => $this->resource,
+ 'audience' => $this->audience,
+ 'scope' => $this->getScope(),
+ 'requested_token_type' => self::STS_REQUESTED_TOKEN_TYPE,
+ 'actor_token' => $this->actorToken,
+ 'actor_token_type' => $this->actorTokenType,
+ ]);
+ if ($this->additionalOptions) {
+ $params['options'] = json_encode($this->additionalOptions);
+ }
+ break;
+ default:
+ if (!is_null($this->getRedirectUri())) {
+ # Grant type was supposed to be 'authorization_code', as there
+ # is a redirect URI.
+ throw new \DomainException('Missing authorization code');
+ }
+ unset($params['grant_type']);
+ if (!is_null($grantType)) {
+ $params['grant_type'] = $grantType;
+ }
+ $params = array_merge($params, $this->getExtensionParams());
+ }
+
+ $headers = [
+ 'Cache-Control' => 'no-store',
+ 'Content-Type' => 'application/x-www-form-urlencoded',
+ ] + $headers;
+
+ return new Request(
+ 'POST',
+ $uri,
+ $headers,
+ Query::build($params)
+ );
+ }
+
+ /**
+ * Fetches the auth tokens based on the current state.
+ *
+ * @param callable|null $httpHandler callback which delivers psr7 request
+ * @param array $headers [optional] If present, add these headers to the token
+ * endpoint request.
+ * @return array the response
+ */
+ public function fetchAuthToken(?callable $httpHandler = null, array $headers = [])
+ {
+ if (is_null($httpHandler)) {
+ $httpHandler = HttpHandlerFactory::build(HttpClientCache::getHttpClient());
+ }
+
+ $response = $httpHandler($this->generateCredentialsRequest($httpHandler, $headers));
+ $credentials = $this->parseTokenResponse($response);
+ $this->updateToken($credentials);
+ if (isset($credentials['scope'])) {
+ $this->setGrantedScope($credentials['scope']);
+ }
+
+ return $credentials;
+ }
+
+ /**
+ * @deprecated
+ *
+ * Obtains a key that can used to cache the results of #fetchAuthToken.
+ *
+ * The key is derived from the scopes.
+ *
+ * @return ?string a key that may be used to cache the auth token.
+ */
+ public function getCacheKey()
+ {
+ if (is_array($this->scope)) {
+ return implode(':', $this->scope);
+ }
+
+ if ($this->audience) {
+ return $this->audience;
+ }
+
+ // If scope has not set, return null to indicate no caching.
+ return null;
+ }
+
+ /**
+ * Gets this instance's SubjectTokenFetcher
+ *
+ * @return null|ExternalAccountCredentialSourceInterface
+ */
+ public function getSubjectTokenFetcher(): ?ExternalAccountCredentialSourceInterface
+ {
+ return $this->subjectTokenFetcher;
+ }
+
+ /**
+ * Parses the fetched tokens.
+ *
+ * @param ResponseInterface $resp the response.
+ * @return array the tokens parsed from the response body.
+ * @throws \Exception
+ */
+ public function parseTokenResponse(ResponseInterface $resp)
+ {
+ $body = (string) $resp->getBody();
+ if ($resp->hasHeader('Content-Type') &&
+ $resp->getHeaderLine('Content-Type') == 'application/x-www-form-urlencoded'
+ ) {
+ $res = [];
+ parse_str($body, $res);
+
+ return $res;
+ }
+
+ // Assume it's JSON; if it's not throw an exception
+ if (null === $res = json_decode($body, true)) {
+ throw new \Exception('Invalid JSON response');
+ }
+
+ return $res;
+ }
+
+ /**
+ * Updates an OAuth 2.0 client.
+ *
+ * Example:
+ * ```
+ * $oauth->updateToken([
+ * 'refresh_token' => 'n4E9O119d',
+ * 'access_token' => 'FJQbwq9',
+ * 'expires_in' => 3600
+ * ]);
+ * ```
+ *
+ * @param array $config
+ * The configuration parameters related to the token.
+ *
+ * - refresh_token
+ * The refresh token associated with the access token
+ * to be refreshed.
+ *
+ * - access_token
+ * The current access token for this client.
+ *
+ * - id_token
+ * The current ID token for this client.
+ *
+ * - expires_in
+ * The time in seconds until access token expiration.
+ *
+ * - expires_at
+ * The time as an integer number of seconds since the Epoch
+ *
+ * - issued_at
+ * The timestamp that the token was issued at.
+ * @return void
+ */
+ public function updateToken(array $config)
+ {
+ $opts = array_merge([
+ 'extensionParams' => [],
+ 'access_token' => null,
+ 'id_token' => null,
+ 'expires_in' => null,
+ 'expires_at' => null,
+ 'issued_at' => null,
+ 'scope' => null,
+ ], $config);
+
+ $this->setExpiresAt($opts['expires_at']);
+ $this->setExpiresIn($opts['expires_in']);
+ // By default, the token is issued at `Time.now` when `expiresIn` is set,
+ // but this can be used to supply a more precise time.
+ if (!is_null($opts['issued_at'])) {
+ $this->setIssuedAt($opts['issued_at']);
+ }
+
+ $this->setAccessToken($opts['access_token']);
+ $this->setIdToken($opts['id_token']);
+
+ // The refresh token should only be updated if a value is explicitly
+ // passed in, as some access token responses do not include a refresh
+ // token.
+ if (array_key_exists('refresh_token', $opts)) {
+ $this->setRefreshToken($opts['refresh_token']);
+ }
+
+ // Required for STS response. An identifier for the representation of
+ // the issued security token.
+ if (array_key_exists('issued_token_type', $opts)) {
+ $this->issuedTokenType = $opts['issued_token_type'];
+ }
+ }
+
+ /**
+ * Builds the authorization Uri that the user should be redirected to.
+ *
+ * @param array $config configuration options that customize the return url.
+ * @return UriInterface the authorization Url.
+ * @throws InvalidArgumentException
+ */
+ public function buildFullAuthorizationUri(array $config = [])
+ {
+ if (is_null($this->getAuthorizationUri())) {
+ throw new InvalidArgumentException(
+ 'requires an authorizationUri to have been set'
+ );
+ }
+
+ $params = array_merge([
+ 'response_type' => 'code',
+ 'access_type' => 'offline',
+ 'client_id' => $this->clientId,
+ 'redirect_uri' => $this->redirectUri,
+ 'state' => $this->state,
+ 'scope' => $this->getScope(),
+ ], $config);
+
+ // Validate the auth_params
+ if (is_null($params['client_id'])) {
+ throw new InvalidArgumentException(
+ 'missing the required client identifier'
+ );
+ }
+ if (is_null($params['redirect_uri'])) {
+ throw new InvalidArgumentException('missing the required redirect URI');
+ }
+ if (!empty($params['prompt']) && !empty($params['approval_prompt'])) {
+ throw new InvalidArgumentException(
+ 'prompt and approval_prompt are mutually exclusive'
+ );
+ }
+ if ($this->codeVerifier) {
+ $params['code_challenge'] = $this->getCodeChallenge($this->codeVerifier);
+ $params['code_challenge_method'] = $this->getCodeChallengeMethod();
+ }
+
+ // Construct the uri object; return it if it is valid.
+ $result = clone $this->authorizationUri;
+ $existingParams = Query::parse($result->getQuery());
+
+ $result = $result->withQuery(
+ Query::build(array_merge($existingParams, $params))
+ );
+
+ if ($result->getScheme() != 'https') {
+ throw new InvalidArgumentException(
+ 'Authorization endpoint must be protected by TLS'
+ );
+ }
+
+ return $result;
+ }
+
+ /**
+ * @return string|null
+ */
+ public function getCodeVerifier(): ?string
+ {
+ return $this->codeVerifier;
+ }
+
+ /**
+ * A cryptographically random string that is used to correlate the
+ * authorization request to the token request.
+ *
+ * The code verifier for PKCE for OAuth 2.0. When set, the authorization
+ * URI will contain the Code Challenge and Code Challenge Method querystring
+ * parameters, and the token URI will contain the Code Verifier parameter.
+ *
+ * @see https://datatracker.ietf.org/doc/html/rfc7636
+ *
+ * @param string|null $codeVerifier
+ */
+ public function setCodeVerifier(?string $codeVerifier): void
+ {
+ $this->codeVerifier = $codeVerifier;
+ }
+
+ /**
+ * Generates a random 128-character string for the "code_verifier" parameter
+ * in PKCE for OAuth 2.0. This is a cryptographically random string that is
+ * determined using random_int, hashed using "hash" and sha256, and base64
+ * encoded.
+ *
+ * When this method is called, the code verifier is set on the object.
+ *
+ * @return string
+ */
+ public function generateCodeVerifier(): string
+ {
+ return $this->codeVerifier = $this->generateRandomString(128);
+ }
+
+ private function getCodeChallenge(string $randomString): string
+ {
+ return rtrim(strtr(base64_encode(hash('sha256', $randomString, true)), '+/', '-_'), '=');
+ }
+
+ private function getCodeChallengeMethod(): string
+ {
+ return 'S256';
+ }
+
+ private function generateRandomString(int $length): string
+ {
+ $validChars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._~';
+ $validCharsLen = strlen($validChars);
+ $str = '';
+ $i = 0;
+ while ($i++ < $length) {
+ $str .= $validChars[random_int(0, $validCharsLen - 1)];
+ }
+ return $str;
+ }
+
+ /**
+ * Sets the authorization server's HTTP endpoint capable of authenticating
+ * the end-user and obtaining authorization.
+ *
+ * @param string $uri
+ * @return void
+ */
+ public function setAuthorizationUri($uri)
+ {
+ $this->authorizationUri = $this->coerceUri($uri);
+ }
+
+ /**
+ * Gets the authorization server's HTTP endpoint capable of authenticating
+ * the end-user and obtaining authorization.
+ *
+ * @return ?UriInterface
+ */
+ public function getAuthorizationUri()
+ {
+ return $this->authorizationUri;
+ }
+
+ /**
+ * Gets the authorization server's HTTP endpoint capable of issuing tokens
+ * and refreshing expired tokens.
+ *
+ * @return ?UriInterface
+ */
+ public function getTokenCredentialUri()
+ {
+ return $this->tokenCredentialUri;
+ }
+
+ /**
+ * Sets the authorization server's HTTP endpoint capable of issuing tokens
+ * and refreshing expired tokens.
+ *
+ * @param string $uri
+ * @return void
+ */
+ public function setTokenCredentialUri($uri)
+ {
+ $this->tokenCredentialUri = $this->coerceUri($uri);
+ }
+
+ /**
+ * Gets the redirection URI used in the initial request.
+ *
+ * @return ?string
+ */
+ public function getRedirectUri()
+ {
+ return $this->redirectUri;
+ }
+
+ /**
+ * Sets the redirection URI used in the initial request.
+ *
+ * @param ?string $uri
+ * @return void
+ */
+ public function setRedirectUri($uri)
+ {
+ if (is_null($uri)) {
+ $this->redirectUri = null;
+
+ return;
+ }
+ // redirect URI must be absolute
+ if (!$this->isAbsoluteUri($uri)) {
+ // "postmessage" is a reserved URI string in Google-land
+ // @see https://developers.google.com/identity/sign-in/web/server-side-flow
+ if ('postmessage' !== (string) $uri) {
+ throw new InvalidArgumentException(
+ 'Redirect URI must be absolute'
+ );
+ }
+ }
+ $this->redirectUri = (string) $uri;
+ }
+
+ /**
+ * Gets the scope of the access requests as a space-delimited String.
+ *
+ * @return ?string
+ */
+ public function getScope()
+ {
+ if (is_null($this->scope)) {
+ return $this->scope;
+ }
+
+ return implode(' ', $this->scope);
+ }
+
+ /**
+ * Gets the subject token type
+ *
+ * @return ?string
+ */
+ public function getSubjectTokenType(): ?string
+ {
+ return $this->subjectTokenType;
+ }
+
+ /**
+ * Sets the scope of the access request, expressed either as an Array or as
+ * a space-delimited String.
+ *
+ * @param string|array|null $scope
+ * @return void
+ * @throws InvalidArgumentException
+ */
+ public function setScope($scope)
+ {
+ if (is_null($scope)) {
+ $this->scope = null;
+ } elseif (is_string($scope)) {
+ $this->scope = explode(' ', $scope);
+ } elseif (is_array($scope)) {
+ foreach ($scope as $s) {
+ $pos = strpos($s, ' ');
+ if ($pos !== false) {
+ throw new InvalidArgumentException(
+ 'array scope values should not contain spaces'
+ );
+ }
+ }
+ $this->scope = $scope;
+ } else {
+ throw new InvalidArgumentException(
+ 'scopes should be a string or array of strings'
+ );
+ }
+ }
+
+ /**
+ * Gets the current grant type.
+ *
+ * @return ?string
+ */
+ public function getGrantType()
+ {
+ if (!is_null($this->grantType)) {
+ return $this->grantType;
+ }
+
+ // Returns the inferred grant type, based on the current object instance
+ // state.
+ if (!is_null($this->code)) {
+ return 'authorization_code';
+ }
+
+ if (!is_null($this->refreshToken)) {
+ return 'refresh_token';
+ }
+
+ if (!is_null($this->username) && !is_null($this->password)) {
+ return 'password';
+ }
+
+ if (!is_null($this->issuer) && !is_null($this->signingKey)) {
+ return self::JWT_URN;
+ }
+
+ if (!is_null($this->subjectTokenFetcher) && !is_null($this->subjectTokenType)) {
+ return self::STS_URN;
+ }
+
+ return null;
+ }
+
+ /**
+ * Sets the current grant type.
+ *
+ * @param string $grantType
+ * @return void
+ * @throws InvalidArgumentException
+ */
+ public function setGrantType($grantType)
+ {
+ if (in_array($grantType, self::$knownGrantTypes)) {
+ $this->grantType = $grantType;
+ } else {
+ // validate URI
+ if (!$this->isAbsoluteUri($grantType)) {
+ throw new InvalidArgumentException(
+ 'invalid grant type'
+ );
+ }
+ $this->grantType = (string) $grantType;
+ }
+ }
+
+ /**
+ * Gets an arbitrary string designed to allow the client to maintain state.
+ *
+ * @return string
+ */
+ public function getState()
+ {
+ return $this->state;
+ }
+
+ /**
+ * Sets an arbitrary string designed to allow the client to maintain state.
+ *
+ * @param string $state
+ * @return void
+ */
+ public function setState($state)
+ {
+ $this->state = $state;
+ }
+
+ /**
+ * Gets the authorization code issued to this client.
+ *
+ * @return string
+ */
+ public function getCode()
+ {
+ return $this->code;
+ }
+
+ /**
+ * Sets the authorization code issued to this client.
+ *
+ * @param string $code
+ * @return void
+ */
+ public function setCode($code)
+ {
+ $this->code = $code;
+ }
+
+ /**
+ * Gets the resource owner's username.
+ *
+ * @return string
+ */
+ public function getUsername()
+ {
+ return $this->username;
+ }
+
+ /**
+ * Sets the resource owner's username.
+ *
+ * @param string $username
+ * @return void
+ */
+ public function setUsername($username)
+ {
+ $this->username = $username;
+ }
+
+ /**
+ * Gets the resource owner's password.
+ *
+ * @return string
+ */
+ public function getPassword()
+ {
+ return $this->password;
+ }
+
+ /**
+ * Sets the resource owner's password.
+ *
+ * @param string $password
+ * @return void
+ */
+ public function setPassword($password)
+ {
+ $this->password = $password;
+ }
+
+ /**
+ * Sets a unique identifier issued to the client to identify itself to the
+ * authorization server.
+ *
+ * @return string
+ */
+ public function getClientId()
+ {
+ return $this->clientId;
+ }
+
+ /**
+ * Sets a unique identifier issued to the client to identify itself to the
+ * authorization server.
+ *
+ * @param string $clientId
+ * @return void
+ */
+ public function setClientId($clientId)
+ {
+ $this->clientId = $clientId;
+ }
+
+ /**
+ * Gets a shared symmetric secret issued by the authorization server, which
+ * is used to authenticate the client.
+ *
+ * @return string
+ */
+ public function getClientSecret()
+ {
+ return $this->clientSecret;
+ }
+
+ /**
+ * Sets a shared symmetric secret issued by the authorization server, which
+ * is used to authenticate the client.
+ *
+ * @param string $clientSecret
+ * @return void
+ */
+ public function setClientSecret($clientSecret)
+ {
+ $this->clientSecret = $clientSecret;
+ }
+
+ /**
+ * Gets the Issuer ID when using assertion profile.
+ *
+ * @return ?string
+ */
+ public function getIssuer()
+ {
+ return $this->issuer;
+ }
+
+ /**
+ * Sets the Issuer ID when using assertion profile.
+ *
+ * @param string $issuer
+ * @return void
+ */
+ public function setIssuer($issuer)
+ {
+ $this->issuer = $issuer;
+ }
+
+ /**
+ * Gets the target sub when issuing assertions.
+ *
+ * @return ?string
+ */
+ public function getSub()
+ {
+ return $this->sub;
+ }
+
+ /**
+ * Sets the target sub when issuing assertions.
+ *
+ * @param string $sub
+ * @return void
+ */
+ public function setSub($sub)
+ {
+ $this->sub = $sub;
+ }
+
+ /**
+ * Gets the target audience when issuing assertions.
+ *
+ * @return ?string
+ */
+ public function getAudience()
+ {
+ return $this->audience;
+ }
+
+ /**
+ * Sets the target audience when issuing assertions.
+ *
+ * @param string $audience
+ * @return void
+ */
+ public function setAudience($audience)
+ {
+ $this->audience = $audience;
+ }
+
+ /**
+ * Gets the signing key when using an assertion profile.
+ *
+ * @return ?string
+ */
+ public function getSigningKey()
+ {
+ return $this->signingKey;
+ }
+
+ /**
+ * Sets the signing key when using an assertion profile.
+ *
+ * @param string $signingKey
+ * @return void
+ */
+ public function setSigningKey($signingKey)
+ {
+ $this->signingKey = $signingKey;
+ }
+
+ /**
+ * Gets the signing key id when using an assertion profile.
+ *
+ * @return ?string
+ */
+ public function getSigningKeyId()
+ {
+ return $this->signingKeyId;
+ }
+
+ /**
+ * Sets the signing key id when using an assertion profile.
+ *
+ * @param string $signingKeyId
+ * @return void
+ */
+ public function setSigningKeyId($signingKeyId)
+ {
+ $this->signingKeyId = $signingKeyId;
+ }
+
+ /**
+ * Gets the signing algorithm when using an assertion profile.
+ *
+ * @return ?string
+ */
+ public function getSigningAlgorithm()
+ {
+ return $this->signingAlgorithm;
+ }
+
+ /**
+ * Sets the signing algorithm when using an assertion profile.
+ *
+ * @param ?string $signingAlgorithm
+ * @return void
+ */
+ public function setSigningAlgorithm($signingAlgorithm)
+ {
+ if (is_null($signingAlgorithm)) {
+ $this->signingAlgorithm = null;
+ } elseif (!in_array($signingAlgorithm, self::$knownSigningAlgorithms)) {
+ throw new InvalidArgumentException('unknown signing algorithm');
+ } else {
+ $this->signingAlgorithm = $signingAlgorithm;
+ }
+ }
+
+ /**
+ * Gets the set of parameters used by extension when using an extension
+ * grant type.
+ *
+ * @return array
+ */
+ public function getExtensionParams()
+ {
+ return $this->extensionParams;
+ }
+
+ /**
+ * Sets the set of parameters used by extension when using an extension
+ * grant type.
+ *
+ * @param array $extensionParams
+ * @return void
+ */
+ public function setExtensionParams($extensionParams)
+ {
+ $this->extensionParams = $extensionParams;
+ }
+
+ /**
+ * Gets the number of seconds assertions are valid for.
+ *
+ * @return int
+ */
+ public function getExpiry()
+ {
+ return $this->expiry;
+ }
+
+ /**
+ * Sets the number of seconds assertions are valid for.
+ *
+ * @param int $expiry
+ * @return void
+ */
+ public function setExpiry($expiry)
+ {
+ $this->expiry = $expiry;
+ }
+
+ /**
+ * Gets the lifetime of the access token in seconds.
+ *
+ * @return int
+ */
+ public function getExpiresIn()
+ {
+ return $this->expiresIn;
+ }
+
+ /**
+ * Sets the lifetime of the access token in seconds.
+ *
+ * @param ?int $expiresIn
+ * @return void
+ */
+ public function setExpiresIn($expiresIn)
+ {
+ if (is_null($expiresIn)) {
+ $this->expiresIn = null;
+ $this->issuedAt = null;
+ } else {
+ $this->issuedAt = time();
+ $this->expiresIn = (int) $expiresIn;
+ }
+ }
+
+ /**
+ * Gets the time the current access token expires at.
+ *
+ * @return ?int
+ */
+ public function getExpiresAt()
+ {
+ if (!is_null($this->expiresAt)) {
+ return $this->expiresAt;
+ }
+
+ if (!is_null($this->issuedAt) && !is_null($this->expiresIn)) {
+ return $this->issuedAt + $this->expiresIn;
+ }
+
+ return null;
+ }
+
+ /**
+ * Returns true if the acccess token has expired.
+ *
+ * @return bool
+ */
+ public function isExpired()
+ {
+ $expiration = $this->getExpiresAt();
+ $now = time();
+
+ return !is_null($expiration) && $now >= $expiration;
+ }
+
+ /**
+ * Sets the time the current access token expires at.
+ *
+ * @param int $expiresAt
+ * @return void
+ */
+ public function setExpiresAt($expiresAt)
+ {
+ $this->expiresAt = $expiresAt;
+ }
+
+ /**
+ * Gets the time the current access token was issued at.
+ *
+ * @return ?int
+ */
+ public function getIssuedAt()
+ {
+ return $this->issuedAt;
+ }
+
+ /**
+ * Sets the time the current access token was issued at.
+ *
+ * @param int $issuedAt
+ * @return void
+ */
+ public function setIssuedAt($issuedAt)
+ {
+ $this->issuedAt = $issuedAt;
+ }
+
+ /**
+ * Gets the current access token.
+ *
+ * @return ?string
+ */
+ public function getAccessToken()
+ {
+ return $this->accessToken;
+ }
+
+ /**
+ * Sets the current access token.
+ *
+ * @param string $accessToken
+ * @return void
+ */
+ public function setAccessToken($accessToken)
+ {
+ $this->accessToken = $accessToken;
+ }
+
+ /**
+ * Gets the current ID token.
+ *
+ * @return ?string
+ */
+ public function getIdToken()
+ {
+ return $this->idToken;
+ }
+
+ /**
+ * Sets the current ID token.
+ *
+ * @param string $idToken
+ * @return void
+ */
+ public function setIdToken($idToken)
+ {
+ $this->idToken = $idToken;
+ }
+
+ /**
+ * Get the granted space-separated scopes (if they exist) for the last
+ * fetched token.
+ *
+ * @return string|null
+ */
+ public function getGrantedScope()
+ {
+ return $this->grantedScope;
+ }
+
+ /**
+ * Sets the current ID token.
+ *
+ * @param string $grantedScope
+ * @return void
+ */
+ public function setGrantedScope($grantedScope)
+ {
+ $this->grantedScope = $grantedScope;
+ }
+
+ /**
+ * Gets the refresh token associated with the current access token.
+ *
+ * @return ?string
+ */
+ public function getRefreshToken()
+ {
+ return $this->refreshToken;
+ }
+
+ /**
+ * Sets the refresh token associated with the current access token.
+ *
+ * @param string $refreshToken
+ * @return void
+ */
+ public function setRefreshToken($refreshToken)
+ {
+ $this->refreshToken = $refreshToken;
+ }
+
+ /**
+ * Sets additional claims to be included in the JWT token
+ *
+ * @param array $additionalClaims
+ * @return void
+ */
+ public function setAdditionalClaims(array $additionalClaims)
+ {
+ $this->additionalClaims = $additionalClaims;
+ }
+
+ /**
+ * Gets the additional claims to be included in the JWT token.
+ *
+ * @return array
+ */
+ public function getAdditionalClaims()
+ {
+ return $this->additionalClaims;
+ }
+
+ /**
+ * Gets the additional claims to be included in the JWT token.
+ *
+ * @return ?string
+ */
+ public function getIssuedTokenType()
+ {
+ return $this->issuedTokenType;
+ }
+
+ /**
+ * The expiration of the last received token.
+ *
+ * @return array|null
+ */
+ public function getLastReceivedToken()
+ {
+ if ($token = $this->getAccessToken()) {
+ // the bare necessity of an auth token
+ $authToken = [
+ 'access_token' => $token,
+ 'expires_at' => $this->getExpiresAt(),
+ ];
+ } elseif ($idToken = $this->getIdToken()) {
+ $authToken = [
+ 'id_token' => $idToken,
+ 'expires_at' => $this->getExpiresAt(),
+ ];
+ } else {
+ return null;
+ }
+
+ if ($expiresIn = $this->getExpiresIn()) {
+ $authToken['expires_in'] = $expiresIn;
+ }
+ if ($issuedAt = $this->getIssuedAt()) {
+ $authToken['issued_at'] = $issuedAt;
+ }
+ if ($refreshToken = $this->getRefreshToken()) {
+ $authToken['refresh_token'] = $refreshToken;
+ }
+
+ return $authToken;
+ }
+
+ /**
+ * Get the client ID.
+ *
+ * Alias of {@see OAuth2::getClientId()}.
+ *
+ * @param callable|null $httpHandler
+ * @return string
+ * @access private
+ */
+ public function getClientName(?callable $httpHandler = null)
+ {
+ return $this->getClientId();
+ }
+
+ /**
+ * @todo handle uri as array
+ *
+ * @param ?string $uri
+ * @return null|UriInterface
+ */
+ private function coerceUri($uri)
+ {
+ if (is_null($uri)) {
+ return null;
+ }
+
+ return Utils::uriFor($uri);
+ }
+
+ /**
+ * @param string $idToken
+ * @param Key|Key[]|string|string[] $publicKey
+ * @param string|string[] $allowedAlgs
+ * @return object
+ */
+ private function jwtDecode($idToken, $publicKey, $allowedAlgs)
+ {
+ $keys = $this->getFirebaseJwtKeys($publicKey, $allowedAlgs);
+
+ // Default exception if none are caught. We are using the same exception
+ // class and message from firebase/php-jwt to preserve backwards
+ // compatibility.
+ $e = new \InvalidArgumentException('Key may not be empty');
+ foreach ($keys as $key) {
+ try {
+ return JWT::decode($idToken, $key);
+ } catch (\Exception $e) {
+ // try next alg
+ }
+ }
+ throw $e;
+ }
+
+ /**
+ * @param Key|Key[]|string|string[] $publicKey
+ * @param string|string[] $allowedAlgs
+ * @return Key[]
+ */
+ private function getFirebaseJwtKeys($publicKey, $allowedAlgs)
+ {
+ // If $publicKey is instance of Key, return it
+ if ($publicKey instanceof Key) {
+ return [$publicKey];
+ }
+
+ // If $allowedAlgs is empty, $publicKey must be Key or Key[].
+ if (empty($allowedAlgs)) {
+ $keys = [];
+ foreach ((array) $publicKey as $kid => $pubKey) {
+ if (!$pubKey instanceof Key) {
+ throw new \InvalidArgumentException(sprintf(
+ 'When allowed algorithms is empty, the public key must'
+ . 'be an instance of %s or an array of %s objects',
+ Key::class,
+ Key::class
+ ));
+ }
+ $keys[$kid] = $pubKey;
+ }
+ return $keys;
+ }
+
+ $allowedAlg = null;
+ if (is_string($allowedAlgs)) {
+ $allowedAlg = $allowedAlgs;
+ } elseif (is_array($allowedAlgs)) {
+ if (count($allowedAlgs) > 1) {
+ throw new \InvalidArgumentException(
+ 'To have multiple allowed algorithms, You must provide an'
+ . ' array of Firebase\JWT\Key objects.'
+ . ' See https://github.com/firebase/php-jwt for more information.'
+ );
+ }
+ $allowedAlg = array_pop($allowedAlgs);
+ } else {
+ throw new \InvalidArgumentException('allowed algorithms must be a string or array.');
+ }
+
+ if (is_array($publicKey)) {
+ // When publicKey is greater than 1, create keys with the single alg.
+ $keys = [];
+ foreach ($publicKey as $kid => $pubKey) {
+ if ($pubKey instanceof Key) {
+ $keys[$kid] = $pubKey;
+ } else {
+ $keys[$kid] = new Key($pubKey, $allowedAlg);
+ }
+ }
+ return $keys;
+ }
+
+ return [new Key($publicKey, $allowedAlg)];
+ }
+
+ /**
+ * Determines if the URI is absolute based on its scheme and host or path
+ * (RFC 3986).
+ *
+ * @param string $uri
+ * @return bool
+ */
+ private function isAbsoluteUri($uri)
+ {
+ $uri = $this->coerceUri($uri);
+
+ return $uri->getScheme() && ($uri->getHost() || $uri->getPath());
+ }
+
+ /**
+ * @param array $params
+ * @return array
+ */
+ private function addClientCredentials(&$params)
+ {
+ $clientId = $this->getClientId();
+ $clientSecret = $this->getClientSecret();
+
+ if ($clientId && $clientSecret) {
+ $params['client_id'] = $clientId;
+ $params['client_secret'] = $clientSecret;
+ }
+
+ return $params;
+ }
+}
diff --git a/vendor/google/auth/src/ProjectIdProviderInterface.php b/vendor/google/auth/src/ProjectIdProviderInterface.php
new file mode 100644
index 0000000..8d10c29
--- /dev/null
+++ b/vendor/google/auth/src/ProjectIdProviderInterface.php
@@ -0,0 +1,32 @@
+auth->getSigningKey();
+
+ $signedString = '';
+ if (class_exists(phpseclib3\Crypt\RSA::class) && !$forceOpenssl) {
+ $key = PublicKeyLoader::load($privateKey);
+ $rsa = $key->withHash('sha256')->withPadding(RSA::SIGNATURE_PKCS1);
+
+ $signedString = $rsa->sign($stringToSign);
+ } elseif (extension_loaded('openssl')) {
+ openssl_sign($stringToSign, $signedString, $privateKey, 'sha256WithRSAEncryption');
+ } else {
+ // @codeCoverageIgnoreStart
+ throw new \RuntimeException('OpenSSL is not installed.');
+ }
+ // @codeCoverageIgnoreEnd
+
+ return base64_encode($signedString);
+ }
+}
diff --git a/vendor/google/auth/src/SignBlobInterface.php b/vendor/google/auth/src/SignBlobInterface.php
new file mode 100644
index 0000000..b3c2b05
--- /dev/null
+++ b/vendor/google/auth/src/SignBlobInterface.php
@@ -0,0 +1,44 @@
+ $metadata metadata hashmap
+ * @param string $authUri optional auth uri
+ * @param callable|null $httpHandler callback which delivers psr7 request
+ * @return array updated metadata hashmap
+ */
+ public function updateMetadata(
+ $metadata,
+ $authUri = null,
+ ?callable $httpHandler = null
+ );
+}
diff --git a/vendor/google/auth/src/UpdateMetadataTrait.php b/vendor/google/auth/src/UpdateMetadataTrait.php
new file mode 100644
index 0000000..486ec72
--- /dev/null
+++ b/vendor/google/auth/src/UpdateMetadataTrait.php
@@ -0,0 +1,74 @@
+ $metadata metadata hashmap
+ * @param string $authUri optional auth uri
+ * @param callable|null $httpHandler callback which delivers psr7 request
+ * @return array updated metadata hashmap
+ */
+ public function updateMetadata(
+ $metadata,
+ $authUri = null,
+ ?callable $httpHandler = null
+ ) {
+ $metadata_copy = $metadata;
+
+ // We do need to set the service api usage metrics irrespective even if
+ // the auth token is set because invoking this method with auth tokens
+ // would mean the intention is to just explicitly set the metrics metadata.
+ $metadata_copy = $this->applyServiceApiUsageMetrics($metadata_copy);
+
+ if (isset($metadata_copy[self::AUTH_METADATA_KEY])) {
+ // Auth metadata has already been set
+ return $metadata_copy;
+ }
+ $result = $this->fetchAuthToken($httpHandler);
+ if (isset($result['access_token'])) {
+ $metadata_copy[self::AUTH_METADATA_KEY] = ['Bearer ' . $result['access_token']];
+ } elseif (isset($result['id_token'])) {
+ $metadata_copy[self::AUTH_METADATA_KEY] = ['Bearer ' . $result['id_token']];
+ }
+ return $metadata_copy;
+ }
+}
diff --git a/vendor/google/cloud-dialogflow/.gitattributes b/vendor/google/cloud-dialogflow/.gitattributes
new file mode 100644
index 0000000..3e957a6
--- /dev/null
+++ b/vendor/google/cloud-dialogflow/.gitattributes
@@ -0,0 +1,7 @@
+/*.xml.dist export-ignore
+/tests export-ignore
+/.github export-ignore
+/samples export-ignore
+/.OwlBot.yaml export-ignore
+/owlbot.py export-ignore
+/src/**/gapic_metadata.json export-ignore
diff --git a/vendor/google/cloud-dialogflow/.owlbot/create_conversation_model_sample_fix.patch b/vendor/google/cloud-dialogflow/.owlbot/create_conversation_model_sample_fix.patch
new file mode 100644
index 0000000..400f5af
--- /dev/null
+++ b/vendor/google/cloud-dialogflow/.owlbot/create_conversation_model_sample_fix.patch
@@ -0,0 +1,21 @@
+diff --git a/Dialogflow/samples/V2/ConversationModelsClient/create_conversation_model.php b/Dialogflow/samples/V2/ConversationModelsClient/create_conversation_model.php
+index 6f11d9f9524..a7a4ddb6fa8 100644
+--- a/Dialogflow/samples/V2/ConversationModelsClient/create_conversation_model.php
++++ b/Dialogflow/samples/V2/ConversationModelsClient/create_conversation_model.php
+@@ -26,6 +26,7 @@ require_once __DIR__ . '/../../../vendor/autoload.php';
+ use Google\ApiCore\ApiException;
+ use Google\ApiCore\OperationResponse;
+ use Google\Cloud\Dialogflow\V2\ConversationModel;
++use Google\Cloud\Dialogflow\V2\ConversationDatasetsClient;
+ use Google\Cloud\Dialogflow\V2\ConversationModelsClient;
+ use Google\Cloud\Dialogflow\V2\InputDataset;
+ use Google\Rpc\Status;
+@@ -93,7 +94,7 @@ function create_conversation_model_sample(
+ function callSample(): void
+ {
+ $conversationModelDisplayName = '[DISPLAY_NAME]';
+- $formattedConversationModelDatasetsDataset = ConversationModelsClient::conversationDatasetName(
++ $formattedConversationModelDatasetsDataset = ConversationDatasetsClient::conversationDatasetName(
+ '[PROJECT]',
+ '[LOCATION]',
+ '[CONVERSATION_DATASET]'
diff --git a/vendor/google/cloud-dialogflow/CODE_OF_CONDUCT.md b/vendor/google/cloud-dialogflow/CODE_OF_CONDUCT.md
new file mode 100644
index 0000000..c372780
--- /dev/null
+++ b/vendor/google/cloud-dialogflow/CODE_OF_CONDUCT.md
@@ -0,0 +1,43 @@
+# Contributor Code of Conduct
+
+As contributors and maintainers of this project,
+and in the interest of fostering an open and welcoming community,
+we pledge to respect all people who contribute through reporting issues,
+posting feature requests, updating documentation,
+submitting pull requests or patches, and other activities.
+
+We are committed to making participation in this project
+a harassment-free experience for everyone,
+regardless of level of experience, gender, gender identity and expression,
+sexual orientation, disability, personal appearance,
+body size, race, ethnicity, age, religion, or nationality.
+
+Examples of unacceptable behavior by participants include:
+
+* The use of sexualized language or imagery
+* Personal attacks
+* Trolling or insulting/derogatory comments
+* Public or private harassment
+* Publishing other's private information,
+such as physical or electronic
+addresses, without explicit permission
+* Other unethical or unprofessional conduct.
+
+Project maintainers have the right and responsibility to remove, edit, or reject
+comments, commits, code, wiki edits, issues, and other contributions
+that are not aligned to this Code of Conduct.
+By adopting this Code of Conduct,
+project maintainers commit themselves to fairly and consistently
+applying these principles to every aspect of managing this project.
+Project maintainers who do not follow or enforce the Code of Conduct
+may be permanently removed from the project team.
+
+This code of conduct applies both within project spaces and in public spaces
+when an individual is representing the project or its community.
+
+Instances of abusive, harassing, or otherwise unacceptable behavior
+may be reported by opening an issue
+or contacting one or more of the project maintainers.
+
+This Code of Conduct is adapted from the [Contributor Covenant](http://contributor-covenant.org), version 1.2.0,
+available at [http://contributor-covenant.org/version/1/2/0/](http://contributor-covenant.org/version/1/2/0/)
\ No newline at end of file
diff --git a/vendor/google/cloud-dialogflow/CONTRIBUTING.md b/vendor/google/cloud-dialogflow/CONTRIBUTING.md
new file mode 100644
index 0000000..76ea811
--- /dev/null
+++ b/vendor/google/cloud-dialogflow/CONTRIBUTING.md
@@ -0,0 +1,10 @@
+# How to Contribute
+
+We'd love to accept your patches and contributions to this project. We accept
+and review pull requests against the main
+[Google Cloud PHP](https://github.com/googleapis/google-cloud-php)
+repository, which contains all of our client libraries. You will also need to
+sign a Contributor License Agreement. For more details about how to contribute,
+see the
+[CONTRIBUTING.md](https://github.com/googleapis/google-cloud-php/blob/main/CONTRIBUTING.md)
+file in the main Google Cloud PHP repository.
diff --git a/vendor/google/cloud-dialogflow/LICENSE b/vendor/google/cloud-dialogflow/LICENSE
new file mode 100644
index 0000000..8f71f43
--- /dev/null
+++ b/vendor/google/cloud-dialogflow/LICENSE
@@ -0,0 +1,202 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "{}"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright {yyyy} {name of copyright owner}
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
diff --git a/vendor/google/cloud-dialogflow/README.md b/vendor/google/cloud-dialogflow/README.md
new file mode 100644
index 0000000..3be307e
--- /dev/null
+++ b/vendor/google/cloud-dialogflow/README.md
@@ -0,0 +1,73 @@
+# Google Cloud Dialogflow for PHP
+
+> Idiomatic PHP client for [Google Cloud Dialogflow](https://cloud.google.com/dialogflow-enterprise/).
+
+[](https://packagist.org/packages/google/cloud-dialogflow) [](https://packagist.org/packages/google/cloud-dialogflow)
+
+* [API documentation](https://cloud.google.com/php/docs/reference/cloud-dialogflow/latest)
+
+**NOTE:** This repository is part of [Google Cloud PHP](https://github.com/googleapis/google-cloud-php). Any
+support requests, bug reports, or development contributions should be directed to
+that project.
+
+Dialogflow Enterprise Edition is the enterprise tier of Dialogflow which is a natural language understanding platform
+that makes it easy for you to design and integrate a conversational user interface into your mobile app, web application,
+device, bot, and so on. Using Dialogflow you can provide users new and engaging ways to interact with your product using
+both voice recognition and text input.
+
+### Installation
+
+To begin, install the preferred dependency manager for PHP, [Composer](https://getcomposer.org/).
+
+Now install this component:
+
+```sh
+$ composer require google/cloud-dialogflow
+```
+
+This component supports both REST over HTTP/1.1 and gRPC. In order to take advantage of the benefits offered by gRPC (such as streaming methods)
+please see our [gRPC installation guide](https://cloud.google.com/php/grpc).
+
+### Authentication
+
+Please see our [Authentication guide](https://github.com/googleapis/google-cloud-php/blob/main/AUTHENTICATION.md) for more information
+on authenticating your client. Once authenticated, you'll be ready to start making requests.
+
+### Sample
+
+```php
+require 'vendor/autoload.php';
+
+use Google\Cloud\Dialogflow\V2\EntityTypesClient;
+
+$entityTypesClient = new EntityTypesClient();
+$projectId = '[MY_PROJECT_ID]';
+$entityTypeId = '[ENTITY_TYPE_ID]';
+$formattedEntityTypeName = $entityTypesClient->entityTypeName($projectId, $entityTypeId);
+
+$entityType = $entityTypesClient->getEntityType($formattedEntityTypeName);
+foreach ($entityType->getEntities() as $entity) {
+ print(PHP_EOL);
+ printf('Entity value: %s' . PHP_EOL, $entity->getValue());
+ print('Synonyms: ');
+ foreach ($entity->getSynonyms() as $synonym) {
+ print($synonym . "\t");
+ }
+ print(PHP_EOL);
+}
+```
+
+### Debugging
+
+Please see our [Debugging guide](https://github.com/googleapis/google-cloud-php/blob/main/DEBUG.md)
+for more information about the debugging tools.
+
+### Version
+
+This component is considered GA (generally available). As such, it will not introduce backwards-incompatible changes in
+any minor or patch releases. We will address issues and requests with the highest priority.
+
+### Next Steps
+
+1. Understand the [official documentation](https://cloud.google.com/dialogflow-enterprise/docs/).
+2. Take a look at [in-depth usage samples](https://github.com/GoogleCloudPlatform/php-docs-samples/tree/master/dialogflow).
diff --git a/vendor/google/cloud-dialogflow/SECURITY.md b/vendor/google/cloud-dialogflow/SECURITY.md
new file mode 100644
index 0000000..8b58ae9
--- /dev/null
+++ b/vendor/google/cloud-dialogflow/SECURITY.md
@@ -0,0 +1,7 @@
+# Security Policy
+
+To report a security issue, please use [g.co/vulnz](https://g.co/vulnz).
+
+The Google Security Team will respond within 5 working days of your report on g.co/vulnz.
+
+We use g.co/vulnz for our intake, and do coordination and disclosure here using GitHub Security Advisory to privately discuss and fix the issue.
diff --git a/vendor/google/cloud-dialogflow/VERSION b/vendor/google/cloud-dialogflow/VERSION
new file mode 100644
index 0000000..ccbccc3
--- /dev/null
+++ b/vendor/google/cloud-dialogflow/VERSION
@@ -0,0 +1 @@
+2.2.0
diff --git a/vendor/google/cloud-dialogflow/composer.json b/vendor/google/cloud-dialogflow/composer.json
new file mode 100644
index 0000000..988f49a
--- /dev/null
+++ b/vendor/google/cloud-dialogflow/composer.json
@@ -0,0 +1,31 @@
+{
+ "name": "google/cloud-dialogflow",
+ "description": "Google Cloud Dialogflow Client for PHP",
+ "license": "Apache-2.0",
+ "minimum-stability": "stable",
+ "autoload": {
+ "psr-4": {
+ "Google\\Cloud\\Dialogflow\\": "src",
+ "GPBMetadata\\Google\\Cloud\\Dialogflow\\": "metadata"
+ }
+ },
+ "extra": {
+ "component": {
+ "id": "cloud-dialogflow",
+ "path": "Dialogflow",
+ "entry": null,
+ "target": "googleapis/google-cloud-php-dialogflow.git"
+ }
+ },
+ "require": {
+ "php": "^8.1",
+ "google/gax": "^1.38.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^9.0",
+ "google/cloud-core": "^1.52.7"
+ },
+ "suggest": {
+ "ext-grpc": "Enables use of gRPC, a universal high-performance RPC framework created by Google."
+ }
+}
diff --git a/vendor/google/cloud-dialogflow/metadata/V2/Agent.php b/vendor/google/cloud-dialogflow/metadata/V2/Agent.php
new file mode 100644
index 0000000..4a07bdf
Binary files /dev/null and b/vendor/google/cloud-dialogflow/metadata/V2/Agent.php differ
diff --git a/vendor/google/cloud-dialogflow/metadata/V2/AnswerRecord.php b/vendor/google/cloud-dialogflow/metadata/V2/AnswerRecord.php
new file mode 100644
index 0000000..fb3c80f
Binary files /dev/null and b/vendor/google/cloud-dialogflow/metadata/V2/AnswerRecord.php differ
diff --git a/vendor/google/cloud-dialogflow/metadata/V2/AudioConfig.php b/vendor/google/cloud-dialogflow/metadata/V2/AudioConfig.php
new file mode 100644
index 0000000..e2b2c7a
Binary files /dev/null and b/vendor/google/cloud-dialogflow/metadata/V2/AudioConfig.php differ
diff --git a/vendor/google/cloud-dialogflow/metadata/V2/Context.php b/vendor/google/cloud-dialogflow/metadata/V2/Context.php
new file mode 100644
index 0000000..cabe397
--- /dev/null
+++ b/vendor/google/cloud-dialogflow/metadata/V2/Context.php
@@ -0,0 +1,70 @@
+internalAddGeneratedFile(
+ '
+"
+(google/cloud/dialogflow/v2/context.protogoogle.cloud.dialogflow.v2google/api/client.protogoogle/api/field_behavior.protogoogle/api/resource.protogoogle/protobuf/empty.proto google/protobuf/field_mask.protogoogle/protobuf/struct.proto"
+Context
+name ( BA
+lifespan_count (BA0
+
+parameters (2.google.protobuf.StructBA:A
+!dialogflow.googleapis.com/Context>projects/{project}/agent/sessions/{session}/contexts/{context}fprojects/{project}/agent/environments/{environment}/users/{user}/sessions/{session}/contexts/{context}Sprojects/{project}/locations/{location}/agent/sessions/{session}/contexts/{context}{projects/{project}/locations/{location}/agent/environments/{environment}/users/{user}/sessions/{session}/contexts/{context}"
+ListContextsRequest9
+parent ( B)AA#!dialogflow.googleapis.com/Context
+ page_size (BA
+
+page_token ( BA"f
+ListContextsResponse5
+contexts (2#.google.cloud.dialogflow.v2.Context
+next_page_token ( "L
+GetContextRequest7
+name ( B)AA#
+!dialogflow.googleapis.com/Context"
+CreateContextRequest9
+parent ( B)AA#!dialogflow.googleapis.com/Context9
+context (2#.google.cloud.dialogflow.v2.ContextBA"
+UpdateContextRequest9
+context (2#.google.cloud.dialogflow.v2.ContextBA4
+update_mask (2.google.protobuf.FieldMaskBA"O
+DeleteContextRequest7
+name ( B)AA#
+!dialogflow.googleapis.com/Context"U
+DeleteAllContextsRequest9
+parent ( B)AA#!dialogflow.googleapis.com/Context2
+Contexts
+ListContexts/.google.cloud.dialogflow.v2.ListContextsRequest0.google.cloud.dialogflow.v2.ListContextsResponse"Aparent1/v2/{parent=projects/*/agent/sessions/*}/contextsZJH/v2/{parent=projects/*/agent/environments/*/users/*/sessions/*}/contextsZ?=/v2/{parent=projects/*/locations/*/agent/sessions/*}/contextsZVT/v2/{parent=projects/*/locations/*/agent/environments/*/users/*/sessions/*}/contexts
+
+GetContext-.google.cloud.dialogflow.v2.GetContextRequest#.google.cloud.dialogflow.v2.Context"Aname1/v2/{name=projects/*/agent/sessions/*/contexts/*}ZJH/v2/{name=projects/*/agent/environments/*/users/*/sessions/*/contexts/*}Z?=/v2/{name=projects/*/locations/*/agent/sessions/*/contexts/*}ZVT/v2/{name=projects/*/locations/*/agent/environments/*/users/*/sessions/*/contexts/*}
+
CreateContext0.google.cloud.dialogflow.v2.CreateContextRequest#.google.cloud.dialogflow.v2.Context"Aparent,context"1/v2/{parent=projects/*/agent/sessions/*}/contexts:contextZS"H/v2/{parent=projects/*/agent/environments/*/users/*/sessions/*}/contexts:contextZH"=/v2/{parent=projects/*/locations/*/agent/sessions/*}/contexts:contextZ_"T/v2/{parent=projects/*/locations/*/agent/environments/*/users/*/sessions/*}/contexts:context
+
UpdateContext0.google.cloud.dialogflow.v2.UpdateContextRequest#.google.cloud.dialogflow.v2.Context"Acontext,update_mask29/v2/{context.name=projects/*/agent/sessions/*/contexts/*}:contextZ[2P/v2/{context.name=projects/*/agent/environments/*/users/*/sessions/*/contexts/*}:contextZP2E/v2/{context.name=projects/*/locations/*/agent/sessions/*/contexts/*}:contextZg2\\/v2/{context.name=projects/*/locations/*/agent/environments/*/users/*/sessions/*/contexts/*}:context
+
DeleteContext0.google.cloud.dialogflow.v2.DeleteContextRequest.google.protobuf.Empty"Aname*1/v2/{name=projects/*/agent/sessions/*/contexts/*}ZJ*H/v2/{name=projects/*/agent/environments/*/users/*/sessions/*/contexts/*}Z?*=/v2/{name=projects/*/locations/*/agent/sessions/*/contexts/*}ZV*T/v2/{name=projects/*/locations/*/agent/environments/*/users/*/sessions/*/contexts/*}
+DeleteAllContexts4.google.cloud.dialogflow.v2.DeleteAllContextsRequest.google.protobuf.Empty"Aparent*1/v2/{parent=projects/*/agent/sessions/*}/contextsZJ*H/v2/{parent=projects/*/agent/environments/*/users/*/sessions/*}/contextsZ?*=/v2/{parent=projects/*/locations/*/agent/sessions/*}/contextsZV*T/v2/{parent=projects/*/locations/*/agent/environments/*/users/*/sessions/*}/contextsxAdialogflow.googleapis.comAYhttps://www.googleapis.com/auth/cloud-platform,https://www.googleapis.com/auth/dialogflowB
+com.google.cloud.dialogflow.v2BContextProtoPZ>cloud.google.com/go/dialogflow/apiv2/dialogflowpb;dialogflowpbDFGoogle.Cloud.Dialogflow.V2bproto3'
+ , true);
+
+ static::$is_initialized = true;
+ }
+}
+
diff --git a/vendor/google/cloud-dialogflow/metadata/V2/Conversation.php b/vendor/google/cloud-dialogflow/metadata/V2/Conversation.php
new file mode 100644
index 0000000..5068ac2
Binary files /dev/null and b/vendor/google/cloud-dialogflow/metadata/V2/Conversation.php differ
diff --git a/vendor/google/cloud-dialogflow/metadata/V2/ConversationDataset.php b/vendor/google/cloud-dialogflow/metadata/V2/ConversationDataset.php
new file mode 100644
index 0000000..1d9e200
Binary files /dev/null and b/vendor/google/cloud-dialogflow/metadata/V2/ConversationDataset.php differ
diff --git a/vendor/google/cloud-dialogflow/metadata/V2/ConversationEvent.php b/vendor/google/cloud-dialogflow/metadata/V2/ConversationEvent.php
new file mode 100644
index 0000000..7e7b2b9
Binary files /dev/null and b/vendor/google/cloud-dialogflow/metadata/V2/ConversationEvent.php differ
diff --git a/vendor/google/cloud-dialogflow/metadata/V2/ConversationModel.php b/vendor/google/cloud-dialogflow/metadata/V2/ConversationModel.php
new file mode 100644
index 0000000..7bc132a
Binary files /dev/null and b/vendor/google/cloud-dialogflow/metadata/V2/ConversationModel.php differ
diff --git a/vendor/google/cloud-dialogflow/metadata/V2/ConversationProfile.php b/vendor/google/cloud-dialogflow/metadata/V2/ConversationProfile.php
new file mode 100644
index 0000000..f1e997f
Binary files /dev/null and b/vendor/google/cloud-dialogflow/metadata/V2/ConversationProfile.php differ
diff --git a/vendor/google/cloud-dialogflow/metadata/V2/Document.php b/vendor/google/cloud-dialogflow/metadata/V2/Document.php
new file mode 100644
index 0000000..207e55a
Binary files /dev/null and b/vendor/google/cloud-dialogflow/metadata/V2/Document.php differ
diff --git a/vendor/google/cloud-dialogflow/metadata/V2/EncryptionSpec.php b/vendor/google/cloud-dialogflow/metadata/V2/EncryptionSpec.php
new file mode 100644
index 0000000..8e17a39
--- /dev/null
+++ b/vendor/google/cloud-dialogflow/metadata/V2/EncryptionSpec.php
@@ -0,0 +1,48 @@
+internalAddGeneratedFile(
+ '
+
+0google/cloud/dialogflow/v2/encryption_spec.protogoogle.cloud.dialogflow.v2google/api/client.protogoogle/api/field_behavior.protogoogle/api/resource.proto#google/longrunning/operations.proto"Z
+GetEncryptionSpecRequest>
+name ( B0AA*
+(dialogflow.googleapis.com/EncryptionSpec"
+EncryptionSpec
+name ( BA
+kms_key ( BA:A
+(dialogflow.googleapis.com/EncryptionSpec6projects/{project}/locations/{location}/encryptionSpec*encryptionSpecs2encryptionSpec"k
+InitializeEncryptionSpecRequestH
+encryption_spec (2*.google.cloud.dialogflow.v2.EncryptionSpecBA""
+ InitializeEncryptionSpecResponse"u
+ InitializeEncryptionSpecMetadataQ
+request (2;.google.cloud.dialogflow.v2.InitializeEncryptionSpecRequestBA2
+EncryptionSpecService
+GetEncryptionSpec4.google.cloud.dialogflow.v2.GetEncryptionSpecRequest*.google.cloud.dialogflow.v2.EncryptionSpec"?Aname20/v2/{name=projects/*/locations/*/encryptionSpec}
+InitializeEncryptionSpec;.google.cloud.dialogflow.v2.InitializeEncryptionSpecRequest.google.longrunning.Operation"AD
+ InitializeEncryptionSpecResponse InitializeEncryptionSpecMetadataAencryption_specP"K/v2/{encryption_spec.name=projects/*/locations/*/encryptionSpec}:initialize:*xAdialogflow.googleapis.comAYhttps://www.googleapis.com/auth/cloud-platform,https://www.googleapis.com/auth/dialogflowB
+com.google.cloud.dialogflow.v2BEncryptionSpecProtoPZ>cloud.google.com/go/dialogflow/apiv2/dialogflowpb;dialogflowpbDFGoogle.Cloud.Dialogflow.V2bproto3'
+ , true);
+
+ static::$is_initialized = true;
+ }
+}
+
diff --git a/vendor/google/cloud-dialogflow/metadata/V2/EntityType.php b/vendor/google/cloud-dialogflow/metadata/V2/EntityType.php
new file mode 100644
index 0000000..4c6b3d2
Binary files /dev/null and b/vendor/google/cloud-dialogflow/metadata/V2/EntityType.php differ
diff --git a/vendor/google/cloud-dialogflow/metadata/V2/Environment.php b/vendor/google/cloud-dialogflow/metadata/V2/Environment.php
new file mode 100644
index 0000000..6f2ebb1
Binary files /dev/null and b/vendor/google/cloud-dialogflow/metadata/V2/Environment.php differ
diff --git a/vendor/google/cloud-dialogflow/metadata/V2/Fulfillment.php b/vendor/google/cloud-dialogflow/metadata/V2/Fulfillment.php
new file mode 100644
index 0000000..0fe45f2
Binary files /dev/null and b/vendor/google/cloud-dialogflow/metadata/V2/Fulfillment.php differ
diff --git a/vendor/google/cloud-dialogflow/metadata/V2/Gcs.php b/vendor/google/cloud-dialogflow/metadata/V2/Gcs.php
new file mode 100644
index 0000000..17288a5
--- /dev/null
+++ b/vendor/google/cloud-dialogflow/metadata/V2/Gcs.php
@@ -0,0 +1,33 @@
+internalAddGeneratedFile(
+ '
+
+$google/cloud/dialogflow/v2/gcs.protogoogle.cloud.dialogflow.v2"
+
+GcsSources
+uris ( BA"
+GcsDestination
+uri ( B
+com.google.cloud.dialogflow.v2BGcsProtoPZ>cloud.google.com/go/dialogflow/apiv2/dialogflowpb;dialogflowpbDFGoogle.Cloud.Dialogflow.V2bproto3'
+ , true);
+
+ static::$is_initialized = true;
+ }
+}
+
diff --git a/vendor/google/cloud-dialogflow/metadata/V2/Generator.php b/vendor/google/cloud-dialogflow/metadata/V2/Generator.php
new file mode 100644
index 0000000..353fab3
Binary files /dev/null and b/vendor/google/cloud-dialogflow/metadata/V2/Generator.php differ
diff --git a/vendor/google/cloud-dialogflow/metadata/V2/HumanAgentAssistantEvent.php b/vendor/google/cloud-dialogflow/metadata/V2/HumanAgentAssistantEvent.php
new file mode 100644
index 0000000..b3a1cbe
--- /dev/null
+++ b/vendor/google/cloud-dialogflow/metadata/V2/HumanAgentAssistantEvent.php
@@ -0,0 +1,32 @@
+internalAddGeneratedFile(
+ '
+
+cloud.google.com/go/dialogflow/apiv2/dialogflowpb;dialogflowpbDFGoogle.Cloud.Dialogflow.V2bproto3'
+ , true);
+
+ static::$is_initialized = true;
+ }
+}
+
diff --git a/vendor/google/cloud-dialogflow/metadata/V2/Intent.php b/vendor/google/cloud-dialogflow/metadata/V2/Intent.php
new file mode 100644
index 0000000..3b9d4d8
Binary files /dev/null and b/vendor/google/cloud-dialogflow/metadata/V2/Intent.php differ
diff --git a/vendor/google/cloud-dialogflow/metadata/V2/KnowledgeBase.php b/vendor/google/cloud-dialogflow/metadata/V2/KnowledgeBase.php
new file mode 100644
index 0000000..0473fd3
--- /dev/null
+++ b/vendor/google/cloud-dialogflow/metadata/V2/KnowledgeBase.php
@@ -0,0 +1,66 @@
+internalAddGeneratedFile(
+ '
+
+/google/cloud/dialogflow/v2/knowledge_base.protogoogle.cloud.dialogflow.v2google/api/client.protogoogle/api/field_behavior.protogoogle/api/resource.protogoogle/protobuf/empty.proto google/protobuf/field_mask.proto"
+
KnowledgeBase
+name (
+display_name ( BA
+
language_code ( :A
+\'dialogflow.googleapis.com/KnowledgeBase2projects/{project}/knowledgeBases/{knowledge_base}Gprojects/{project}/locations/{location}/knowledgeBases/{knowledge_base}"
+ListKnowledgeBasesRequest?
+parent ( B/AA)\'dialogflow.googleapis.com/KnowledgeBase
+ page_size (
+
+page_token (
+filter ( "y
+ListKnowledgeBasesResponseB
+knowledge_bases (2).google.cloud.dialogflow.v2.KnowledgeBase
+next_page_token ( "X
+GetKnowledgeBaseRequest=
+name ( B/AA)
+\'dialogflow.googleapis.com/KnowledgeBase"
+CreateKnowledgeBaseRequest?
+parent ( B/AA)\'dialogflow.googleapis.com/KnowledgeBaseF
+knowledge_base (2).google.cloud.dialogflow.v2.KnowledgeBaseBA"o
+DeleteKnowledgeBaseRequest=
+name ( B/AA)
+\'dialogflow.googleapis.com/KnowledgeBase
+force (BA"
+UpdateKnowledgeBaseRequestF
+knowledge_base (2).google.cloud.dialogflow.v2.KnowledgeBaseBA4
+update_mask (2.google.protobuf.FieldMaskBA2
+KnowledgeBases
+ListKnowledgeBases5.google.cloud.dialogflow.v2.ListKnowledgeBasesRequest6.google.cloud.dialogflow.v2.ListKnowledgeBasesResponse"Aparent&/v2/{parent=projects/*}/knowledgeBasesZ42/v2/{parent=projects/*/locations/*}/knowledgeBasesZ.,/v2/{parent=projects/*/agent}/knowledgeBases
+GetKnowledgeBase3.google.cloud.dialogflow.v2.GetKnowledgeBaseRequest).google.cloud.dialogflow.v2.KnowledgeBase"Aname&/v2/{name=projects/*/knowledgeBases/*}Z42/v2/{name=projects/*/locations/*/knowledgeBases/*}Z.,/v2/{name=projects/*/agent/knowledgeBases/*}
+CreateKnowledgeBase6.google.cloud.dialogflow.v2.CreateKnowledgeBaseRequest).google.cloud.dialogflow.v2.KnowledgeBase"Aparent,knowledge_base"&/v2/{parent=projects/*}/knowledgeBases:knowledge_baseZD"2/v2/{parent=projects/*/locations/*}/knowledgeBases:knowledge_baseZ>",/v2/{parent=projects/*/agent}/knowledgeBases:knowledge_base
+DeleteKnowledgeBase6.google.cloud.dialogflow.v2.DeleteKnowledgeBaseRequest.google.protobuf.Empty"Aname*&/v2/{name=projects/*/knowledgeBases/*}Z4*2/v2/{name=projects/*/locations/*/knowledgeBases/*}Z.*,/v2/{name=projects/*/agent/knowledgeBases/*}
+UpdateKnowledgeBase6.google.cloud.dialogflow.v2.UpdateKnowledgeBaseRequest).google.cloud.dialogflow.v2.KnowledgeBase"Aknowledge_base,update_mask25/v2/{knowledge_base.name=projects/*/knowledgeBases/*}:knowledge_baseZS2A/v2/{knowledge_base.name=projects/*/locations/*/knowledgeBases/*}:knowledge_baseZM2;/v2/{knowledge_base.name=projects/*/agent/knowledgeBases/*}:knowledge_basexAdialogflow.googleapis.comAYhttps://www.googleapis.com/auth/cloud-platform,https://www.googleapis.com/auth/dialogflowB
+com.google.cloud.dialogflow.v2BKnowledgeBaseProtoPZ>cloud.google.com/go/dialogflow/apiv2/dialogflowpb;dialogflowpbDFGoogle.Cloud.Dialogflow.V2bproto3'
+ , true);
+
+ static::$is_initialized = true;
+ }
+}
+
diff --git a/vendor/google/cloud-dialogflow/metadata/V2/Participant.php b/vendor/google/cloud-dialogflow/metadata/V2/Participant.php
new file mode 100644
index 0000000..ddccc26
Binary files /dev/null and b/vendor/google/cloud-dialogflow/metadata/V2/Participant.php differ
diff --git a/vendor/google/cloud-dialogflow/metadata/V2/Session.php b/vendor/google/cloud-dialogflow/metadata/V2/Session.php
new file mode 100644
index 0000000..65e8326
Binary files /dev/null and b/vendor/google/cloud-dialogflow/metadata/V2/Session.php differ
diff --git a/vendor/google/cloud-dialogflow/metadata/V2/SessionEntityType.php b/vendor/google/cloud-dialogflow/metadata/V2/SessionEntityType.php
new file mode 100644
index 0000000..8df38c1
Binary files /dev/null and b/vendor/google/cloud-dialogflow/metadata/V2/SessionEntityType.php differ
diff --git a/vendor/google/cloud-dialogflow/metadata/V2/ValidationResult.php b/vendor/google/cloud-dialogflow/metadata/V2/ValidationResult.php
new file mode 100644
index 0000000..481fcd0
Binary files /dev/null and b/vendor/google/cloud-dialogflow/metadata/V2/ValidationResult.php differ
diff --git a/vendor/google/cloud-dialogflow/metadata/V2/Version.php b/vendor/google/cloud-dialogflow/metadata/V2/Version.php
new file mode 100644
index 0000000..135ff8b
Binary files /dev/null and b/vendor/google/cloud-dialogflow/metadata/V2/Version.php differ
diff --git a/vendor/google/cloud-dialogflow/metadata/V2/Webhook.php b/vendor/google/cloud-dialogflow/metadata/V2/Webhook.php
new file mode 100644
index 0000000..df90db7
--- /dev/null
+++ b/vendor/google/cloud-dialogflow/metadata/V2/Webhook.php
@@ -0,0 +1,50 @@
+internalAddGeneratedFile(
+ '
+
+(google/cloud/dialogflow/v2/webhook.protogoogle.cloud.dialogflow.v2\'google/cloud/dialogflow/v2/intent.proto(google/cloud/dialogflow/v2/session.proto4google/cloud/dialogflow/v2/session_entity_type.protogoogle/protobuf/struct.proto"
+WebhookRequest
+session (
+response_id ( =
+query_result (2\'.google.cloud.dialogflow.v2.QueryResult_
+original_detect_intent_request (27.google.cloud.dialogflow.v2.OriginalDetectIntentRequest"
+WebhookResponse
+fulfillment_text ( H
+fulfillment_messages (2*.google.cloud.dialogflow.v2.Intent.Message
+source ( (
+payload (2.google.protobuf.Struct<
+output_contexts (2#.google.cloud.dialogflow.v2.ContextD
+followup_event_input (2&.google.cloud.dialogflow.v2.EventInputK
+session_entity_types
+ (2-.google.cloud.dialogflow.v2.SessionEntityType"h
+OriginalDetectIntentRequest
+source (
+version ( (
+payload (2.google.protobuf.StructB
+com.google.cloud.dialogflow.v2BWebhookProtoPZ>cloud.google.com/go/dialogflow/apiv2/dialogflowpb;dialogflowpbDFGoogle.Cloud.Dialogflow.V2bproto3'
+ , true);
+
+ static::$is_initialized = true;
+ }
+}
+
diff --git a/vendor/google/cloud-dialogflow/src/V2/Agent.php b/vendor/google/cloud-dialogflow/src/V2/Agent.php
new file mode 100644
index 0000000..13164b2
--- /dev/null
+++ b/vendor/google/cloud-dialogflow/src/V2/Agent.php
@@ -0,0 +1,543 @@
+google.cloud.dialogflow.v2.Agent
+ */
+class Agent extends \Google\Protobuf\Internal\Message
+{
+ /**
+ * Required. The project of this agent.
+ * Format: `projects/`.
+ *
+ * Generated from protobuf field string parent = 1 [(.google.api.field_behavior) = REQUIRED, (.google.api.resource_reference) = {
+ */
+ protected $parent = '';
+ /**
+ * Required. The name of this agent.
+ *
+ * Generated from protobuf field string display_name = 2 [(.google.api.field_behavior) = REQUIRED];
+ */
+ protected $display_name = '';
+ /**
+ * Required. The default language of the agent as a language tag. See
+ * [Language
+ * Support](https://cloud.google.com/dialogflow/docs/reference/language)
+ * for a list of the currently supported language codes. This field cannot be
+ * set by the `Update` method.
+ *
+ * Generated from protobuf field string default_language_code = 3 [(.google.api.field_behavior) = REQUIRED];
+ */
+ protected $default_language_code = '';
+ /**
+ * Optional. The list of all languages supported by this agent (except for the
+ * `default_language_code`).
+ *
+ * Generated from protobuf field repeated string supported_language_codes = 4 [(.google.api.field_behavior) = OPTIONAL];
+ */
+ private $supported_language_codes;
+ /**
+ * Required. The time zone of this agent from the
+ * [time zone database](https://www.iana.org/time-zones), e.g.,
+ * America/New_York, Europe/Paris.
+ *
+ * Generated from protobuf field string time_zone = 5 [(.google.api.field_behavior) = REQUIRED];
+ */
+ protected $time_zone = '';
+ /**
+ * Optional. The description of this agent.
+ * The maximum length is 500 characters. If exceeded, the request is rejected.
+ *
+ * Generated from protobuf field string description = 6 [(.google.api.field_behavior) = OPTIONAL];
+ */
+ protected $description = '';
+ /**
+ * Optional. The URI of the agent's avatar.
+ * Avatars are used throughout the Dialogflow console and in the self-hosted
+ * [Web
+ * Demo](https://cloud.google.com/dialogflow/docs/integrations/web-demo)
+ * integration.
+ *
+ * Generated from protobuf field string avatar_uri = 7 [(.google.api.field_behavior) = OPTIONAL];
+ */
+ protected $avatar_uri = '';
+ /**
+ * Optional. Determines whether this agent should log conversation queries.
+ *
+ * Generated from protobuf field bool enable_logging = 8 [(.google.api.field_behavior) = OPTIONAL];
+ */
+ protected $enable_logging = false;
+ /**
+ * Optional. Determines how intents are detected from user queries.
+ *
+ * Generated from protobuf field .google.cloud.dialogflow.v2.Agent.MatchMode match_mode = 9 [deprecated = true, (.google.api.field_behavior) = OPTIONAL];
+ * @deprecated
+ */
+ protected $match_mode = 0;
+ /**
+ * Optional. To filter out false positive results and still get variety in
+ * matched natural language inputs for your agent, you can tune the machine
+ * learning classification threshold. If the returned score value is less than
+ * the threshold value, then a fallback intent will be triggered or, if there
+ * are no fallback intents defined, no intent will be triggered. The score
+ * values range from 0.0 (completely uncertain) to 1.0 (completely certain).
+ * If set to 0.0, the default of 0.3 is used.
+ *
+ * Generated from protobuf field float classification_threshold = 10 [(.google.api.field_behavior) = OPTIONAL];
+ */
+ protected $classification_threshold = 0.0;
+ /**
+ * Optional. API version displayed in Dialogflow console. If not specified,
+ * V2 API is assumed. Clients are free to query different service endpoints
+ * for different API versions. However, bots connectors and webhook calls will
+ * follow the specified API version.
+ *
+ * Generated from protobuf field .google.cloud.dialogflow.v2.Agent.ApiVersion api_version = 14 [(.google.api.field_behavior) = OPTIONAL];
+ */
+ protected $api_version = 0;
+ /**
+ * Optional. The agent tier. If not specified, TIER_STANDARD is assumed.
+ *
+ * Generated from protobuf field .google.cloud.dialogflow.v2.Agent.Tier tier = 15 [(.google.api.field_behavior) = OPTIONAL];
+ */
+ protected $tier = 0;
+
+ /**
+ * Constructor.
+ *
+ * @param array $data {
+ * Optional. Data for populating the Message object.
+ *
+ * @type string $parent
+ * Required. The project of this agent.
+ * Format: `projects/`.
+ * @type string $display_name
+ * Required. The name of this agent.
+ * @type string $default_language_code
+ * Required. The default language of the agent as a language tag. See
+ * [Language
+ * Support](https://cloud.google.com/dialogflow/docs/reference/language)
+ * for a list of the currently supported language codes. This field cannot be
+ * set by the `Update` method.
+ * @type array|\Google\Protobuf\Internal\RepeatedField $supported_language_codes
+ * Optional. The list of all languages supported by this agent (except for the
+ * `default_language_code`).
+ * @type string $time_zone
+ * Required. The time zone of this agent from the
+ * [time zone database](https://www.iana.org/time-zones), e.g.,
+ * America/New_York, Europe/Paris.
+ * @type string $description
+ * Optional. The description of this agent.
+ * The maximum length is 500 characters. If exceeded, the request is rejected.
+ * @type string $avatar_uri
+ * Optional. The URI of the agent's avatar.
+ * Avatars are used throughout the Dialogflow console and in the self-hosted
+ * [Web
+ * Demo](https://cloud.google.com/dialogflow/docs/integrations/web-demo)
+ * integration.
+ * @type bool $enable_logging
+ * Optional. Determines whether this agent should log conversation queries.
+ * @type int $match_mode
+ * Optional. Determines how intents are detected from user queries.
+ * @type float $classification_threshold
+ * Optional. To filter out false positive results and still get variety in
+ * matched natural language inputs for your agent, you can tune the machine
+ * learning classification threshold. If the returned score value is less than
+ * the threshold value, then a fallback intent will be triggered or, if there
+ * are no fallback intents defined, no intent will be triggered. The score
+ * values range from 0.0 (completely uncertain) to 1.0 (completely certain).
+ * If set to 0.0, the default of 0.3 is used.
+ * @type int $api_version
+ * Optional. API version displayed in Dialogflow console. If not specified,
+ * V2 API is assumed. Clients are free to query different service endpoints
+ * for different API versions. However, bots connectors and webhook calls will
+ * follow the specified API version.
+ * @type int $tier
+ * Optional. The agent tier. If not specified, TIER_STANDARD is assumed.
+ * }
+ */
+ public function __construct($data = NULL) {
+ \GPBMetadata\Google\Cloud\Dialogflow\V2\Agent::initOnce();
+ parent::__construct($data);
+ }
+
+ /**
+ * Required. The project of this agent.
+ * Format: `projects/`.
+ *
+ * Generated from protobuf field string parent = 1 [(.google.api.field_behavior) = REQUIRED, (.google.api.resource_reference) = {
+ * @return string
+ */
+ public function getParent()
+ {
+ return $this->parent;
+ }
+
+ /**
+ * Required. The project of this agent.
+ * Format: `projects/`.
+ *
+ * Generated from protobuf field string parent = 1 [(.google.api.field_behavior) = REQUIRED, (.google.api.resource_reference) = {
+ * @param string $var
+ * @return $this
+ */
+ public function setParent($var)
+ {
+ GPBUtil::checkString($var, True);
+ $this->parent = $var;
+
+ return $this;
+ }
+
+ /**
+ * Required. The name of this agent.
+ *
+ * Generated from protobuf field string display_name = 2 [(.google.api.field_behavior) = REQUIRED];
+ * @return string
+ */
+ public function getDisplayName()
+ {
+ return $this->display_name;
+ }
+
+ /**
+ * Required. The name of this agent.
+ *
+ * Generated from protobuf field string display_name = 2 [(.google.api.field_behavior) = REQUIRED];
+ * @param string $var
+ * @return $this
+ */
+ public function setDisplayName($var)
+ {
+ GPBUtil::checkString($var, True);
+ $this->display_name = $var;
+
+ return $this;
+ }
+
+ /**
+ * Required. The default language of the agent as a language tag. See
+ * [Language
+ * Support](https://cloud.google.com/dialogflow/docs/reference/language)
+ * for a list of the currently supported language codes. This field cannot be
+ * set by the `Update` method.
+ *
+ * Generated from protobuf field string default_language_code = 3 [(.google.api.field_behavior) = REQUIRED];
+ * @return string
+ */
+ public function getDefaultLanguageCode()
+ {
+ return $this->default_language_code;
+ }
+
+ /**
+ * Required. The default language of the agent as a language tag. See
+ * [Language
+ * Support](https://cloud.google.com/dialogflow/docs/reference/language)
+ * for a list of the currently supported language codes. This field cannot be
+ * set by the `Update` method.
+ *
+ * Generated from protobuf field string default_language_code = 3 [(.google.api.field_behavior) = REQUIRED];
+ * @param string $var
+ * @return $this
+ */
+ public function setDefaultLanguageCode($var)
+ {
+ GPBUtil::checkString($var, True);
+ $this->default_language_code = $var;
+
+ return $this;
+ }
+
+ /**
+ * Optional. The list of all languages supported by this agent (except for the
+ * `default_language_code`).
+ *
+ * Generated from protobuf field repeated string supported_language_codes = 4 [(.google.api.field_behavior) = OPTIONAL];
+ * @return \Google\Protobuf\Internal\RepeatedField
+ */
+ public function getSupportedLanguageCodes()
+ {
+ return $this->supported_language_codes;
+ }
+
+ /**
+ * Optional. The list of all languages supported by this agent (except for the
+ * `default_language_code`).
+ *
+ * Generated from protobuf field repeated string supported_language_codes = 4 [(.google.api.field_behavior) = OPTIONAL];
+ * @param array|\Google\Protobuf\Internal\RepeatedField $var
+ * @return $this
+ */
+ public function setSupportedLanguageCodes($var)
+ {
+ $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::STRING);
+ $this->supported_language_codes = $arr;
+
+ return $this;
+ }
+
+ /**
+ * Required. The time zone of this agent from the
+ * [time zone database](https://www.iana.org/time-zones), e.g.,
+ * America/New_York, Europe/Paris.
+ *
+ * Generated from protobuf field string time_zone = 5 [(.google.api.field_behavior) = REQUIRED];
+ * @return string
+ */
+ public function getTimeZone()
+ {
+ return $this->time_zone;
+ }
+
+ /**
+ * Required. The time zone of this agent from the
+ * [time zone database](https://www.iana.org/time-zones), e.g.,
+ * America/New_York, Europe/Paris.
+ *
+ * Generated from protobuf field string time_zone = 5 [(.google.api.field_behavior) = REQUIRED];
+ * @param string $var
+ * @return $this
+ */
+ public function setTimeZone($var)
+ {
+ GPBUtil::checkString($var, True);
+ $this->time_zone = $var;
+
+ return $this;
+ }
+
+ /**
+ * Optional. The description of this agent.
+ * The maximum length is 500 characters. If exceeded, the request is rejected.
+ *
+ * Generated from protobuf field string description = 6 [(.google.api.field_behavior) = OPTIONAL];
+ * @return string
+ */
+ public function getDescription()
+ {
+ return $this->description;
+ }
+
+ /**
+ * Optional. The description of this agent.
+ * The maximum length is 500 characters. If exceeded, the request is rejected.
+ *
+ * Generated from protobuf field string description = 6 [(.google.api.field_behavior) = OPTIONAL];
+ * @param string $var
+ * @return $this
+ */
+ public function setDescription($var)
+ {
+ GPBUtil::checkString($var, True);
+ $this->description = $var;
+
+ return $this;
+ }
+
+ /**
+ * Optional. The URI of the agent's avatar.
+ * Avatars are used throughout the Dialogflow console and in the self-hosted
+ * [Web
+ * Demo](https://cloud.google.com/dialogflow/docs/integrations/web-demo)
+ * integration.
+ *
+ * Generated from protobuf field string avatar_uri = 7 [(.google.api.field_behavior) = OPTIONAL];
+ * @return string
+ */
+ public function getAvatarUri()
+ {
+ return $this->avatar_uri;
+ }
+
+ /**
+ * Optional. The URI of the agent's avatar.
+ * Avatars are used throughout the Dialogflow console and in the self-hosted
+ * [Web
+ * Demo](https://cloud.google.com/dialogflow/docs/integrations/web-demo)
+ * integration.
+ *
+ * Generated from protobuf field string avatar_uri = 7 [(.google.api.field_behavior) = OPTIONAL];
+ * @param string $var
+ * @return $this
+ */
+ public function setAvatarUri($var)
+ {
+ GPBUtil::checkString($var, True);
+ $this->avatar_uri = $var;
+
+ return $this;
+ }
+
+ /**
+ * Optional. Determines whether this agent should log conversation queries.
+ *
+ * Generated from protobuf field bool enable_logging = 8 [(.google.api.field_behavior) = OPTIONAL];
+ * @return bool
+ */
+ public function getEnableLogging()
+ {
+ return $this->enable_logging;
+ }
+
+ /**
+ * Optional. Determines whether this agent should log conversation queries.
+ *
+ * Generated from protobuf field bool enable_logging = 8 [(.google.api.field_behavior) = OPTIONAL];
+ * @param bool $var
+ * @return $this
+ */
+ public function setEnableLogging($var)
+ {
+ GPBUtil::checkBool($var);
+ $this->enable_logging = $var;
+
+ return $this;
+ }
+
+ /**
+ * Optional. Determines how intents are detected from user queries.
+ *
+ * Generated from protobuf field .google.cloud.dialogflow.v2.Agent.MatchMode match_mode = 9 [deprecated = true, (.google.api.field_behavior) = OPTIONAL];
+ * @return int
+ * @deprecated
+ */
+ public function getMatchMode()
+ {
+ if ($this->match_mode !== 0) {
+ @trigger_error('match_mode is deprecated.', E_USER_DEPRECATED);
+ }
+ return $this->match_mode;
+ }
+
+ /**
+ * Optional. Determines how intents are detected from user queries.
+ *
+ * Generated from protobuf field .google.cloud.dialogflow.v2.Agent.MatchMode match_mode = 9 [deprecated = true, (.google.api.field_behavior) = OPTIONAL];
+ * @param int $var
+ * @return $this
+ * @deprecated
+ */
+ public function setMatchMode($var)
+ {
+ @trigger_error('match_mode is deprecated.', E_USER_DEPRECATED);
+ GPBUtil::checkEnum($var, \Google\Cloud\Dialogflow\V2\Agent\MatchMode::class);
+ $this->match_mode = $var;
+
+ return $this;
+ }
+
+ /**
+ * Optional. To filter out false positive results and still get variety in
+ * matched natural language inputs for your agent, you can tune the machine
+ * learning classification threshold. If the returned score value is less than
+ * the threshold value, then a fallback intent will be triggered or, if there
+ * are no fallback intents defined, no intent will be triggered. The score
+ * values range from 0.0 (completely uncertain) to 1.0 (completely certain).
+ * If set to 0.0, the default of 0.3 is used.
+ *
+ * Generated from protobuf field float classification_threshold = 10 [(.google.api.field_behavior) = OPTIONAL];
+ * @return float
+ */
+ public function getClassificationThreshold()
+ {
+ return $this->classification_threshold;
+ }
+
+ /**
+ * Optional. To filter out false positive results and still get variety in
+ * matched natural language inputs for your agent, you can tune the machine
+ * learning classification threshold. If the returned score value is less than
+ * the threshold value, then a fallback intent will be triggered or, if there
+ * are no fallback intents defined, no intent will be triggered. The score
+ * values range from 0.0 (completely uncertain) to 1.0 (completely certain).
+ * If set to 0.0, the default of 0.3 is used.
+ *
+ * Generated from protobuf field float classification_threshold = 10 [(.google.api.field_behavior) = OPTIONAL];
+ * @param float $var
+ * @return $this
+ */
+ public function setClassificationThreshold($var)
+ {
+ GPBUtil::checkFloat($var);
+ $this->classification_threshold = $var;
+
+ return $this;
+ }
+
+ /**
+ * Optional. API version displayed in Dialogflow console. If not specified,
+ * V2 API is assumed. Clients are free to query different service endpoints
+ * for different API versions. However, bots connectors and webhook calls will
+ * follow the specified API version.
+ *
+ * Generated from protobuf field .google.cloud.dialogflow.v2.Agent.ApiVersion api_version = 14 [(.google.api.field_behavior) = OPTIONAL];
+ * @return int
+ */
+ public function getApiVersion()
+ {
+ return $this->api_version;
+ }
+
+ /**
+ * Optional. API version displayed in Dialogflow console. If not specified,
+ * V2 API is assumed. Clients are free to query different service endpoints
+ * for different API versions. However, bots connectors and webhook calls will
+ * follow the specified API version.
+ *
+ * Generated from protobuf field .google.cloud.dialogflow.v2.Agent.ApiVersion api_version = 14 [(.google.api.field_behavior) = OPTIONAL];
+ * @param int $var
+ * @return $this
+ */
+ public function setApiVersion($var)
+ {
+ GPBUtil::checkEnum($var, \Google\Cloud\Dialogflow\V2\Agent\ApiVersion::class);
+ $this->api_version = $var;
+
+ return $this;
+ }
+
+ /**
+ * Optional. The agent tier. If not specified, TIER_STANDARD is assumed.
+ *
+ * Generated from protobuf field .google.cloud.dialogflow.v2.Agent.Tier tier = 15 [(.google.api.field_behavior) = OPTIONAL];
+ * @return int
+ */
+ public function getTier()
+ {
+ return $this->tier;
+ }
+
+ /**
+ * Optional. The agent tier. If not specified, TIER_STANDARD is assumed.
+ *
+ * Generated from protobuf field .google.cloud.dialogflow.v2.Agent.Tier tier = 15 [(.google.api.field_behavior) = OPTIONAL];
+ * @param int $var
+ * @return $this
+ */
+ public function setTier($var)
+ {
+ GPBUtil::checkEnum($var, \Google\Cloud\Dialogflow\V2\Agent\Tier::class);
+ $this->tier = $var;
+
+ return $this;
+ }
+
+}
+
diff --git a/vendor/google/cloud-dialogflow/src/V2/Agent/ApiVersion.php b/vendor/google/cloud-dialogflow/src/V2/Agent/ApiVersion.php
new file mode 100644
index 0000000..d81f985
--- /dev/null
+++ b/vendor/google/cloud-dialogflow/src/V2/Agent/ApiVersion.php
@@ -0,0 +1,69 @@
+google.cloud.dialogflow.v2.Agent.ApiVersion
+ */
+class ApiVersion
+{
+ /**
+ * Not specified.
+ *
+ * Generated from protobuf enum API_VERSION_UNSPECIFIED = 0;
+ */
+ const API_VERSION_UNSPECIFIED = 0;
+ /**
+ * Legacy V1 API.
+ *
+ * Generated from protobuf enum API_VERSION_V1 = 1;
+ */
+ const API_VERSION_V1 = 1;
+ /**
+ * V2 API.
+ *
+ * Generated from protobuf enum API_VERSION_V2 = 2;
+ */
+ const API_VERSION_V2 = 2;
+ /**
+ * V2beta1 API.
+ *
+ * Generated from protobuf enum API_VERSION_V2_BETA_1 = 3;
+ */
+ const API_VERSION_V2_BETA_1 = 3;
+
+ private static $valueToName = [
+ self::API_VERSION_UNSPECIFIED => 'API_VERSION_UNSPECIFIED',
+ self::API_VERSION_V1 => 'API_VERSION_V1',
+ self::API_VERSION_V2 => 'API_VERSION_V2',
+ self::API_VERSION_V2_BETA_1 => 'API_VERSION_V2_BETA_1',
+ ];
+
+ public static function name($value)
+ {
+ if (!isset(self::$valueToName[$value])) {
+ throw new UnexpectedValueException(sprintf(
+ 'Enum %s has no name defined for value %s', __CLASS__, $value));
+ }
+ return self::$valueToName[$value];
+ }
+
+
+ public static function value($name)
+ {
+ $const = __CLASS__ . '::' . strtoupper($name);
+ if (!defined($const)) {
+ throw new UnexpectedValueException(sprintf(
+ 'Enum %s has no value defined for name %s', __CLASS__, $name));
+ }
+ return constant($const);
+ }
+}
+
+
diff --git a/vendor/google/cloud-dialogflow/src/V2/Agent/MatchMode.php b/vendor/google/cloud-dialogflow/src/V2/Agent/MatchMode.php
new file mode 100644
index 0000000..7401d69
--- /dev/null
+++ b/vendor/google/cloud-dialogflow/src/V2/Agent/MatchMode.php
@@ -0,0 +1,64 @@
+google.cloud.dialogflow.v2.Agent.MatchMode
+ */
+class MatchMode
+{
+ /**
+ * Not specified.
+ *
+ * Generated from protobuf enum MATCH_MODE_UNSPECIFIED = 0;
+ */
+ const MATCH_MODE_UNSPECIFIED = 0;
+ /**
+ * Best for agents with a small number of examples in intents and/or wide
+ * use of templates syntax and composite entities.
+ *
+ * Generated from protobuf enum MATCH_MODE_HYBRID = 1;
+ */
+ const MATCH_MODE_HYBRID = 1;
+ /**
+ * Can be used for agents with a large number of examples in intents,
+ * especially the ones using @sys.any or very large custom entities.
+ *
+ * Generated from protobuf enum MATCH_MODE_ML_ONLY = 2;
+ */
+ const MATCH_MODE_ML_ONLY = 2;
+
+ private static $valueToName = [
+ self::MATCH_MODE_UNSPECIFIED => 'MATCH_MODE_UNSPECIFIED',
+ self::MATCH_MODE_HYBRID => 'MATCH_MODE_HYBRID',
+ self::MATCH_MODE_ML_ONLY => 'MATCH_MODE_ML_ONLY',
+ ];
+
+ public static function name($value)
+ {
+ if (!isset(self::$valueToName[$value])) {
+ throw new UnexpectedValueException(sprintf(
+ 'Enum %s has no name defined for value %s', __CLASS__, $value));
+ }
+ return self::$valueToName[$value];
+ }
+
+
+ public static function value($name)
+ {
+ $const = __CLASS__ . '::' . strtoupper($name);
+ if (!defined($const)) {
+ throw new UnexpectedValueException(sprintf(
+ 'Enum %s has no value defined for name %s', __CLASS__, $name));
+ }
+ return constant($const);
+ }
+}
+
+
diff --git a/vendor/google/cloud-dialogflow/src/V2/Agent/Tier.php b/vendor/google/cloud-dialogflow/src/V2/Agent/Tier.php
new file mode 100644
index 0000000..79b2318
--- /dev/null
+++ b/vendor/google/cloud-dialogflow/src/V2/Agent/Tier.php
@@ -0,0 +1,70 @@
+google.cloud.dialogflow.v2.Agent.Tier
+ */
+class Tier
+{
+ /**
+ * Not specified. This value should never be used.
+ *
+ * Generated from protobuf enum TIER_UNSPECIFIED = 0;
+ */
+ const TIER_UNSPECIFIED = 0;
+ /**
+ * Trial Edition, previously known as Standard Edition.
+ *
+ * Generated from protobuf enum TIER_STANDARD = 1;
+ */
+ const TIER_STANDARD = 1;
+ /**
+ * Essentials Edition, previously known as Enterprise Essential Edition.
+ *
+ * Generated from protobuf enum TIER_ENTERPRISE = 2;
+ */
+ const TIER_ENTERPRISE = 2;
+ /**
+ * Essentials Edition (same as TIER_ENTERPRISE), previously known as
+ * Enterprise Plus Edition.
+ *
+ * Generated from protobuf enum TIER_ENTERPRISE_PLUS = 3 [deprecated = true];
+ */
+ const TIER_ENTERPRISE_PLUS = 3;
+
+ private static $valueToName = [
+ self::TIER_UNSPECIFIED => 'TIER_UNSPECIFIED',
+ self::TIER_STANDARD => 'TIER_STANDARD',
+ self::TIER_ENTERPRISE => 'TIER_ENTERPRISE',
+ self::TIER_ENTERPRISE_PLUS => 'TIER_ENTERPRISE_PLUS',
+ ];
+
+ public static function name($value)
+ {
+ if (!isset(self::$valueToName[$value])) {
+ throw new UnexpectedValueException(sprintf(
+ 'Enum %s has no name defined for value %s', __CLASS__, $value));
+ }
+ return self::$valueToName[$value];
+ }
+
+
+ public static function value($name)
+ {
+ $const = __CLASS__ . '::' . strtoupper($name);
+ if (!defined($const)) {
+ throw new UnexpectedValueException(sprintf(
+ 'Enum %s has no value defined for name %s', __CLASS__, $name));
+ }
+ return constant($const);
+ }
+}
+
+
diff --git a/vendor/google/cloud-dialogflow/src/V2/AgentAssistantFeedback.php b/vendor/google/cloud-dialogflow/src/V2/AgentAssistantFeedback.php
new file mode 100644
index 0000000..1b8743f
--- /dev/null
+++ b/vendor/google/cloud-dialogflow/src/V2/AgentAssistantFeedback.php
@@ -0,0 +1,331 @@
+google.cloud.dialogflow.v2.AgentAssistantFeedback
+ */
+class AgentAssistantFeedback extends \Google\Protobuf\Internal\Message
+{
+ /**
+ * Optional. Whether or not the suggested answer is relevant.
+ * For example:
+ * * Query: "Can I change my mailing address?"
+ * * Suggested document says: "Items must be returned/exchanged within 60
+ * days of the purchase date."
+ * * [answer_relevance][google.cloud.dialogflow.v2.AgentAssistantFeedback.answer_relevance]: [AnswerRelevance.IRRELEVANT][google.cloud.dialogflow.v2.AgentAssistantFeedback.AnswerRelevance.IRRELEVANT]
+ *
+ * Generated from protobuf field .google.cloud.dialogflow.v2.AgentAssistantFeedback.AnswerRelevance answer_relevance = 1 [(.google.api.field_behavior) = OPTIONAL];
+ */
+ protected $answer_relevance = 0;
+ /**
+ * Optional. Whether or not the information in the document is correct.
+ * For example:
+ * * Query: "Can I return the package in 2 days once received?"
+ * * Suggested document says: "Items must be returned/exchanged within 60
+ * days of the purchase date."
+ * * Ground truth: "No return or exchange is allowed."
+ * * [document_correctness][google.cloud.dialogflow.v2.AgentAssistantFeedback.document_correctness]: [INCORRECT][google.cloud.dialogflow.v2.AgentAssistantFeedback.DocumentCorrectness.INCORRECT]
+ *
+ * Generated from protobuf field .google.cloud.dialogflow.v2.AgentAssistantFeedback.DocumentCorrectness document_correctness = 2 [(.google.api.field_behavior) = OPTIONAL];
+ */
+ protected $document_correctness = 0;
+ /**
+ * Optional. Whether or not the suggested document is efficient. For example,
+ * if the document is poorly written, hard to understand, hard to use or
+ * too long to find useful information,
+ * [document_efficiency][google.cloud.dialogflow.v2.AgentAssistantFeedback.document_efficiency]
+ * is
+ * [DocumentEfficiency.INEFFICIENT][google.cloud.dialogflow.v2.AgentAssistantFeedback.DocumentEfficiency.INEFFICIENT].
+ *
+ * Generated from protobuf field .google.cloud.dialogflow.v2.AgentAssistantFeedback.DocumentEfficiency document_efficiency = 3 [(.google.api.field_behavior) = OPTIONAL];
+ */
+ protected $document_efficiency = 0;
+ /**
+ * Optional. Feedback for conversation summarization.
+ *
+ * Generated from protobuf field .google.cloud.dialogflow.v2.AgentAssistantFeedback.SummarizationFeedback summarization_feedback = 4 [(.google.api.field_behavior) = OPTIONAL];
+ */
+ protected $summarization_feedback = null;
+ /**
+ * Optional. Feedback for knowledge search.
+ *
+ * Generated from protobuf field .google.cloud.dialogflow.v2.AgentAssistantFeedback.KnowledgeSearchFeedback knowledge_search_feedback = 5 [(.google.api.field_behavior) = OPTIONAL];
+ */
+ protected $knowledge_search_feedback = null;
+ /**
+ * Optional. Feedback for knowledge assist.
+ *
+ * Generated from protobuf field .google.cloud.dialogflow.v2.AgentAssistantFeedback.KnowledgeAssistFeedback knowledge_assist_feedback = 6 [(.google.api.field_behavior) = OPTIONAL];
+ */
+ protected $knowledge_assist_feedback = null;
+
+ /**
+ * Constructor.
+ *
+ * @param array $data {
+ * Optional. Data for populating the Message object.
+ *
+ * @type int $answer_relevance
+ * Optional. Whether or not the suggested answer is relevant.
+ * For example:
+ * * Query: "Can I change my mailing address?"
+ * * Suggested document says: "Items must be returned/exchanged within 60
+ * days of the purchase date."
+ * * [answer_relevance][google.cloud.dialogflow.v2.AgentAssistantFeedback.answer_relevance]: [AnswerRelevance.IRRELEVANT][google.cloud.dialogflow.v2.AgentAssistantFeedback.AnswerRelevance.IRRELEVANT]
+ * @type int $document_correctness
+ * Optional. Whether or not the information in the document is correct.
+ * For example:
+ * * Query: "Can I return the package in 2 days once received?"
+ * * Suggested document says: "Items must be returned/exchanged within 60
+ * days of the purchase date."
+ * * Ground truth: "No return or exchange is allowed."
+ * * [document_correctness][google.cloud.dialogflow.v2.AgentAssistantFeedback.document_correctness]: [INCORRECT][google.cloud.dialogflow.v2.AgentAssistantFeedback.DocumentCorrectness.INCORRECT]
+ * @type int $document_efficiency
+ * Optional. Whether or not the suggested document is efficient. For example,
+ * if the document is poorly written, hard to understand, hard to use or
+ * too long to find useful information,
+ * [document_efficiency][google.cloud.dialogflow.v2.AgentAssistantFeedback.document_efficiency]
+ * is
+ * [DocumentEfficiency.INEFFICIENT][google.cloud.dialogflow.v2.AgentAssistantFeedback.DocumentEfficiency.INEFFICIENT].
+ * @type \Google\Cloud\Dialogflow\V2\AgentAssistantFeedback\SummarizationFeedback $summarization_feedback
+ * Optional. Feedback for conversation summarization.
+ * @type \Google\Cloud\Dialogflow\V2\AgentAssistantFeedback\KnowledgeSearchFeedback $knowledge_search_feedback
+ * Optional. Feedback for knowledge search.
+ * @type \Google\Cloud\Dialogflow\V2\AgentAssistantFeedback\KnowledgeAssistFeedback $knowledge_assist_feedback
+ * Optional. Feedback for knowledge assist.
+ * }
+ */
+ public function __construct($data = NULL) {
+ \GPBMetadata\Google\Cloud\Dialogflow\V2\AnswerRecord::initOnce();
+ parent::__construct($data);
+ }
+
+ /**
+ * Optional. Whether or not the suggested answer is relevant.
+ * For example:
+ * * Query: "Can I change my mailing address?"
+ * * Suggested document says: "Items must be returned/exchanged within 60
+ * days of the purchase date."
+ * * [answer_relevance][google.cloud.dialogflow.v2.AgentAssistantFeedback.answer_relevance]: [AnswerRelevance.IRRELEVANT][google.cloud.dialogflow.v2.AgentAssistantFeedback.AnswerRelevance.IRRELEVANT]
+ *
+ * Generated from protobuf field .google.cloud.dialogflow.v2.AgentAssistantFeedback.AnswerRelevance answer_relevance = 1 [(.google.api.field_behavior) = OPTIONAL];
+ * @return int
+ */
+ public function getAnswerRelevance()
+ {
+ return $this->answer_relevance;
+ }
+
+ /**
+ * Optional. Whether or not the suggested answer is relevant.
+ * For example:
+ * * Query: "Can I change my mailing address?"
+ * * Suggested document says: "Items must be returned/exchanged within 60
+ * days of the purchase date."
+ * * [answer_relevance][google.cloud.dialogflow.v2.AgentAssistantFeedback.answer_relevance]: [AnswerRelevance.IRRELEVANT][google.cloud.dialogflow.v2.AgentAssistantFeedback.AnswerRelevance.IRRELEVANT]
+ *
+ * Generated from protobuf field .google.cloud.dialogflow.v2.AgentAssistantFeedback.AnswerRelevance answer_relevance = 1 [(.google.api.field_behavior) = OPTIONAL];
+ * @param int $var
+ * @return $this
+ */
+ public function setAnswerRelevance($var)
+ {
+ GPBUtil::checkEnum($var, \Google\Cloud\Dialogflow\V2\AgentAssistantFeedback\AnswerRelevance::class);
+ $this->answer_relevance = $var;
+
+ return $this;
+ }
+
+ /**
+ * Optional. Whether or not the information in the document is correct.
+ * For example:
+ * * Query: "Can I return the package in 2 days once received?"
+ * * Suggested document says: "Items must be returned/exchanged within 60
+ * days of the purchase date."
+ * * Ground truth: "No return or exchange is allowed."
+ * * [document_correctness][google.cloud.dialogflow.v2.AgentAssistantFeedback.document_correctness]: [INCORRECT][google.cloud.dialogflow.v2.AgentAssistantFeedback.DocumentCorrectness.INCORRECT]
+ *
+ * Generated from protobuf field .google.cloud.dialogflow.v2.AgentAssistantFeedback.DocumentCorrectness document_correctness = 2 [(.google.api.field_behavior) = OPTIONAL];
+ * @return int
+ */
+ public function getDocumentCorrectness()
+ {
+ return $this->document_correctness;
+ }
+
+ /**
+ * Optional. Whether or not the information in the document is correct.
+ * For example:
+ * * Query: "Can I return the package in 2 days once received?"
+ * * Suggested document says: "Items must be returned/exchanged within 60
+ * days of the purchase date."
+ * * Ground truth: "No return or exchange is allowed."
+ * * [document_correctness][google.cloud.dialogflow.v2.AgentAssistantFeedback.document_correctness]: [INCORRECT][google.cloud.dialogflow.v2.AgentAssistantFeedback.DocumentCorrectness.INCORRECT]
+ *
+ * Generated from protobuf field .google.cloud.dialogflow.v2.AgentAssistantFeedback.DocumentCorrectness document_correctness = 2 [(.google.api.field_behavior) = OPTIONAL];
+ * @param int $var
+ * @return $this
+ */
+ public function setDocumentCorrectness($var)
+ {
+ GPBUtil::checkEnum($var, \Google\Cloud\Dialogflow\V2\AgentAssistantFeedback\DocumentCorrectness::class);
+ $this->document_correctness = $var;
+
+ return $this;
+ }
+
+ /**
+ * Optional. Whether or not the suggested document is efficient. For example,
+ * if the document is poorly written, hard to understand, hard to use or
+ * too long to find useful information,
+ * [document_efficiency][google.cloud.dialogflow.v2.AgentAssistantFeedback.document_efficiency]
+ * is
+ * [DocumentEfficiency.INEFFICIENT][google.cloud.dialogflow.v2.AgentAssistantFeedback.DocumentEfficiency.INEFFICIENT].
+ *
+ * Generated from protobuf field .google.cloud.dialogflow.v2.AgentAssistantFeedback.DocumentEfficiency document_efficiency = 3 [(.google.api.field_behavior) = OPTIONAL];
+ * @return int
+ */
+ public function getDocumentEfficiency()
+ {
+ return $this->document_efficiency;
+ }
+
+ /**
+ * Optional. Whether or not the suggested document is efficient. For example,
+ * if the document is poorly written, hard to understand, hard to use or
+ * too long to find useful information,
+ * [document_efficiency][google.cloud.dialogflow.v2.AgentAssistantFeedback.document_efficiency]
+ * is
+ * [DocumentEfficiency.INEFFICIENT][google.cloud.dialogflow.v2.AgentAssistantFeedback.DocumentEfficiency.INEFFICIENT].
+ *
+ * Generated from protobuf field .google.cloud.dialogflow.v2.AgentAssistantFeedback.DocumentEfficiency document_efficiency = 3 [(.google.api.field_behavior) = OPTIONAL];
+ * @param int $var
+ * @return $this
+ */
+ public function setDocumentEfficiency($var)
+ {
+ GPBUtil::checkEnum($var, \Google\Cloud\Dialogflow\V2\AgentAssistantFeedback\DocumentEfficiency::class);
+ $this->document_efficiency = $var;
+
+ return $this;
+ }
+
+ /**
+ * Optional. Feedback for conversation summarization.
+ *
+ * Generated from protobuf field .google.cloud.dialogflow.v2.AgentAssistantFeedback.SummarizationFeedback summarization_feedback = 4 [(.google.api.field_behavior) = OPTIONAL];
+ * @return \Google\Cloud\Dialogflow\V2\AgentAssistantFeedback\SummarizationFeedback|null
+ */
+ public function getSummarizationFeedback()
+ {
+ return $this->summarization_feedback;
+ }
+
+ public function hasSummarizationFeedback()
+ {
+ return isset($this->summarization_feedback);
+ }
+
+ public function clearSummarizationFeedback()
+ {
+ unset($this->summarization_feedback);
+ }
+
+ /**
+ * Optional. Feedback for conversation summarization.
+ *
+ * Generated from protobuf field .google.cloud.dialogflow.v2.AgentAssistantFeedback.SummarizationFeedback summarization_feedback = 4 [(.google.api.field_behavior) = OPTIONAL];
+ * @param \Google\Cloud\Dialogflow\V2\AgentAssistantFeedback\SummarizationFeedback $var
+ * @return $this
+ */
+ public function setSummarizationFeedback($var)
+ {
+ GPBUtil::checkMessage($var, \Google\Cloud\Dialogflow\V2\AgentAssistantFeedback\SummarizationFeedback::class);
+ $this->summarization_feedback = $var;
+
+ return $this;
+ }
+
+ /**
+ * Optional. Feedback for knowledge search.
+ *
+ * Generated from protobuf field .google.cloud.dialogflow.v2.AgentAssistantFeedback.KnowledgeSearchFeedback knowledge_search_feedback = 5 [(.google.api.field_behavior) = OPTIONAL];
+ * @return \Google\Cloud\Dialogflow\V2\AgentAssistantFeedback\KnowledgeSearchFeedback|null
+ */
+ public function getKnowledgeSearchFeedback()
+ {
+ return $this->knowledge_search_feedback;
+ }
+
+ public function hasKnowledgeSearchFeedback()
+ {
+ return isset($this->knowledge_search_feedback);
+ }
+
+ public function clearKnowledgeSearchFeedback()
+ {
+ unset($this->knowledge_search_feedback);
+ }
+
+ /**
+ * Optional. Feedback for knowledge search.
+ *
+ * Generated from protobuf field .google.cloud.dialogflow.v2.AgentAssistantFeedback.KnowledgeSearchFeedback knowledge_search_feedback = 5 [(.google.api.field_behavior) = OPTIONAL];
+ * @param \Google\Cloud\Dialogflow\V2\AgentAssistantFeedback\KnowledgeSearchFeedback $var
+ * @return $this
+ */
+ public function setKnowledgeSearchFeedback($var)
+ {
+ GPBUtil::checkMessage($var, \Google\Cloud\Dialogflow\V2\AgentAssistantFeedback\KnowledgeSearchFeedback::class);
+ $this->knowledge_search_feedback = $var;
+
+ return $this;
+ }
+
+ /**
+ * Optional. Feedback for knowledge assist.
+ *
+ * Generated from protobuf field .google.cloud.dialogflow.v2.AgentAssistantFeedback.KnowledgeAssistFeedback knowledge_assist_feedback = 6 [(.google.api.field_behavior) = OPTIONAL];
+ * @return \Google\Cloud\Dialogflow\V2\AgentAssistantFeedback\KnowledgeAssistFeedback|null
+ */
+ public function getKnowledgeAssistFeedback()
+ {
+ return $this->knowledge_assist_feedback;
+ }
+
+ public function hasKnowledgeAssistFeedback()
+ {
+ return isset($this->knowledge_assist_feedback);
+ }
+
+ public function clearKnowledgeAssistFeedback()
+ {
+ unset($this->knowledge_assist_feedback);
+ }
+
+ /**
+ * Optional. Feedback for knowledge assist.
+ *
+ * Generated from protobuf field .google.cloud.dialogflow.v2.AgentAssistantFeedback.KnowledgeAssistFeedback knowledge_assist_feedback = 6 [(.google.api.field_behavior) = OPTIONAL];
+ * @param \Google\Cloud\Dialogflow\V2\AgentAssistantFeedback\KnowledgeAssistFeedback $var
+ * @return $this
+ */
+ public function setKnowledgeAssistFeedback($var)
+ {
+ GPBUtil::checkMessage($var, \Google\Cloud\Dialogflow\V2\AgentAssistantFeedback\KnowledgeAssistFeedback::class);
+ $this->knowledge_assist_feedback = $var;
+
+ return $this;
+ }
+
+}
+
diff --git a/vendor/google/cloud-dialogflow/src/V2/AgentAssistantFeedback/AnswerRelevance.php b/vendor/google/cloud-dialogflow/src/V2/AgentAssistantFeedback/AnswerRelevance.php
new file mode 100644
index 0000000..3f3827b
--- /dev/null
+++ b/vendor/google/cloud-dialogflow/src/V2/AgentAssistantFeedback/AnswerRelevance.php
@@ -0,0 +1,62 @@
+google.cloud.dialogflow.v2.AgentAssistantFeedback.AnswerRelevance
+ */
+class AnswerRelevance
+{
+ /**
+ * Answer relevance unspecified.
+ *
+ * Generated from protobuf enum ANSWER_RELEVANCE_UNSPECIFIED = 0;
+ */
+ const ANSWER_RELEVANCE_UNSPECIFIED = 0;
+ /**
+ * Answer is irrelevant to query.
+ *
+ * Generated from protobuf enum IRRELEVANT = 1;
+ */
+ const IRRELEVANT = 1;
+ /**
+ * Answer is relevant to query.
+ *
+ * Generated from protobuf enum RELEVANT = 2;
+ */
+ const RELEVANT = 2;
+
+ private static $valueToName = [
+ self::ANSWER_RELEVANCE_UNSPECIFIED => 'ANSWER_RELEVANCE_UNSPECIFIED',
+ self::IRRELEVANT => 'IRRELEVANT',
+ self::RELEVANT => 'RELEVANT',
+ ];
+
+ public static function name($value)
+ {
+ if (!isset(self::$valueToName[$value])) {
+ throw new UnexpectedValueException(sprintf(
+ 'Enum %s has no name defined for value %s', __CLASS__, $value));
+ }
+ return self::$valueToName[$value];
+ }
+
+
+ public static function value($name)
+ {
+ $const = __CLASS__ . '::' . strtoupper($name);
+ if (!defined($const)) {
+ throw new UnexpectedValueException(sprintf(
+ 'Enum %s has no value defined for name %s', __CLASS__, $name));
+ }
+ return constant($const);
+ }
+}
+
+
diff --git a/vendor/google/cloud-dialogflow/src/V2/AgentAssistantFeedback/DocumentCorrectness.php b/vendor/google/cloud-dialogflow/src/V2/AgentAssistantFeedback/DocumentCorrectness.php
new file mode 100644
index 0000000..0b0f089
--- /dev/null
+++ b/vendor/google/cloud-dialogflow/src/V2/AgentAssistantFeedback/DocumentCorrectness.php
@@ -0,0 +1,62 @@
+google.cloud.dialogflow.v2.AgentAssistantFeedback.DocumentCorrectness
+ */
+class DocumentCorrectness
+{
+ /**
+ * Document correctness unspecified.
+ *
+ * Generated from protobuf enum DOCUMENT_CORRECTNESS_UNSPECIFIED = 0;
+ */
+ const DOCUMENT_CORRECTNESS_UNSPECIFIED = 0;
+ /**
+ * Information in document is incorrect.
+ *
+ * Generated from protobuf enum INCORRECT = 1;
+ */
+ const INCORRECT = 1;
+ /**
+ * Information in document is correct.
+ *
+ * Generated from protobuf enum CORRECT = 2;
+ */
+ const CORRECT = 2;
+
+ private static $valueToName = [
+ self::DOCUMENT_CORRECTNESS_UNSPECIFIED => 'DOCUMENT_CORRECTNESS_UNSPECIFIED',
+ self::INCORRECT => 'INCORRECT',
+ self::CORRECT => 'CORRECT',
+ ];
+
+ public static function name($value)
+ {
+ if (!isset(self::$valueToName[$value])) {
+ throw new UnexpectedValueException(sprintf(
+ 'Enum %s has no name defined for value %s', __CLASS__, $value));
+ }
+ return self::$valueToName[$value];
+ }
+
+
+ public static function value($name)
+ {
+ $const = __CLASS__ . '::' . strtoupper($name);
+ if (!defined($const)) {
+ throw new UnexpectedValueException(sprintf(
+ 'Enum %s has no value defined for name %s', __CLASS__, $name));
+ }
+ return constant($const);
+ }
+}
+
+
diff --git a/vendor/google/cloud-dialogflow/src/V2/AgentAssistantFeedback/DocumentEfficiency.php b/vendor/google/cloud-dialogflow/src/V2/AgentAssistantFeedback/DocumentEfficiency.php
new file mode 100644
index 0000000..d164799
--- /dev/null
+++ b/vendor/google/cloud-dialogflow/src/V2/AgentAssistantFeedback/DocumentEfficiency.php
@@ -0,0 +1,62 @@
+google.cloud.dialogflow.v2.AgentAssistantFeedback.DocumentEfficiency
+ */
+class DocumentEfficiency
+{
+ /**
+ * Document efficiency unspecified.
+ *
+ * Generated from protobuf enum DOCUMENT_EFFICIENCY_UNSPECIFIED = 0;
+ */
+ const DOCUMENT_EFFICIENCY_UNSPECIFIED = 0;
+ /**
+ * Document is inefficient.
+ *
+ * Generated from protobuf enum INEFFICIENT = 1;
+ */
+ const INEFFICIENT = 1;
+ /**
+ * Document is efficient.
+ *
+ * Generated from protobuf enum EFFICIENT = 2;
+ */
+ const EFFICIENT = 2;
+
+ private static $valueToName = [
+ self::DOCUMENT_EFFICIENCY_UNSPECIFIED => 'DOCUMENT_EFFICIENCY_UNSPECIFIED',
+ self::INEFFICIENT => 'INEFFICIENT',
+ self::EFFICIENT => 'EFFICIENT',
+ ];
+
+ public static function name($value)
+ {
+ if (!isset(self::$valueToName[$value])) {
+ throw new UnexpectedValueException(sprintf(
+ 'Enum %s has no name defined for value %s', __CLASS__, $value));
+ }
+ return self::$valueToName[$value];
+ }
+
+
+ public static function value($name)
+ {
+ $const = __CLASS__ . '::' . strtoupper($name);
+ if (!defined($const)) {
+ throw new UnexpectedValueException(sprintf(
+ 'Enum %s has no value defined for name %s', __CLASS__, $name));
+ }
+ return constant($const);
+ }
+}
+
+
diff --git a/vendor/google/cloud-dialogflow/src/V2/AgentAssistantFeedback/KnowledgeAssistFeedback.php b/vendor/google/cloud-dialogflow/src/V2/AgentAssistantFeedback/KnowledgeAssistFeedback.php
new file mode 100644
index 0000000..f3dc6a3
--- /dev/null
+++ b/vendor/google/cloud-dialogflow/src/V2/AgentAssistantFeedback/KnowledgeAssistFeedback.php
@@ -0,0 +1,130 @@
+google.cloud.dialogflow.v2.AgentAssistantFeedback.KnowledgeAssistFeedback
+ */
+class KnowledgeAssistFeedback extends \Google\Protobuf\Internal\Message
+{
+ /**
+ * Whether the suggested answer was copied by the human agent.
+ * If the value is set to be true,
+ * [AnswerFeedback.clicked][google.cloud.dialogflow.v2.AnswerFeedback.clicked]
+ * will be updated to be true.
+ *
+ * Generated from protobuf field bool answer_copied = 1;
+ */
+ protected $answer_copied = false;
+ /**
+ * The URIs clicked by the human agent. The value is appended for each
+ * UpdateAnswerRecordRequest.
+ * If the value is not empty,
+ * [AnswerFeedback.clicked][google.cloud.dialogflow.v2.AnswerFeedback.clicked]
+ * will be updated to be true.
+ *
+ * Generated from protobuf field repeated string clicked_uris = 2;
+ */
+ private $clicked_uris;
+
+ /**
+ * Constructor.
+ *
+ * @param array $data {
+ * Optional. Data for populating the Message object.
+ *
+ * @type bool $answer_copied
+ * Whether the suggested answer was copied by the human agent.
+ * If the value is set to be true,
+ * [AnswerFeedback.clicked][google.cloud.dialogflow.v2.AnswerFeedback.clicked]
+ * will be updated to be true.
+ * @type array|\Google\Protobuf\Internal\RepeatedField $clicked_uris
+ * The URIs clicked by the human agent. The value is appended for each
+ * UpdateAnswerRecordRequest.
+ * If the value is not empty,
+ * [AnswerFeedback.clicked][google.cloud.dialogflow.v2.AnswerFeedback.clicked]
+ * will be updated to be true.
+ * }
+ */
+ public function __construct($data = NULL) {
+ \GPBMetadata\Google\Cloud\Dialogflow\V2\AnswerRecord::initOnce();
+ parent::__construct($data);
+ }
+
+ /**
+ * Whether the suggested answer was copied by the human agent.
+ * If the value is set to be true,
+ * [AnswerFeedback.clicked][google.cloud.dialogflow.v2.AnswerFeedback.clicked]
+ * will be updated to be true.
+ *
+ * Generated from protobuf field bool answer_copied = 1;
+ * @return bool
+ */
+ public function getAnswerCopied()
+ {
+ return $this->answer_copied;
+ }
+
+ /**
+ * Whether the suggested answer was copied by the human agent.
+ * If the value is set to be true,
+ * [AnswerFeedback.clicked][google.cloud.dialogflow.v2.AnswerFeedback.clicked]
+ * will be updated to be true.
+ *
+ * Generated from protobuf field bool answer_copied = 1;
+ * @param bool $var
+ * @return $this
+ */
+ public function setAnswerCopied($var)
+ {
+ GPBUtil::checkBool($var);
+ $this->answer_copied = $var;
+
+ return $this;
+ }
+
+ /**
+ * The URIs clicked by the human agent. The value is appended for each
+ * UpdateAnswerRecordRequest.
+ * If the value is not empty,
+ * [AnswerFeedback.clicked][google.cloud.dialogflow.v2.AnswerFeedback.clicked]
+ * will be updated to be true.
+ *
+ * Generated from protobuf field repeated string clicked_uris = 2;
+ * @return \Google\Protobuf\Internal\RepeatedField
+ */
+ public function getClickedUris()
+ {
+ return $this->clicked_uris;
+ }
+
+ /**
+ * The URIs clicked by the human agent. The value is appended for each
+ * UpdateAnswerRecordRequest.
+ * If the value is not empty,
+ * [AnswerFeedback.clicked][google.cloud.dialogflow.v2.AnswerFeedback.clicked]
+ * will be updated to be true.
+ *
+ * Generated from protobuf field repeated string clicked_uris = 2;
+ * @param array|\Google\Protobuf\Internal\RepeatedField $var
+ * @return $this
+ */
+ public function setClickedUris($var)
+ {
+ $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::STRING);
+ $this->clicked_uris = $arr;
+
+ return $this;
+ }
+
+}
+
+
diff --git a/vendor/google/cloud-dialogflow/src/V2/AgentAssistantFeedback/KnowledgeSearchFeedback.php b/vendor/google/cloud-dialogflow/src/V2/AgentAssistantFeedback/KnowledgeSearchFeedback.php
new file mode 100644
index 0000000..16c54ca
--- /dev/null
+++ b/vendor/google/cloud-dialogflow/src/V2/AgentAssistantFeedback/KnowledgeSearchFeedback.php
@@ -0,0 +1,130 @@
+google.cloud.dialogflow.v2.AgentAssistantFeedback.KnowledgeSearchFeedback
+ */
+class KnowledgeSearchFeedback extends \Google\Protobuf\Internal\Message
+{
+ /**
+ * Whether the answer was copied by the human agent or not.
+ * If the value is set to be true,
+ * [AnswerFeedback.clicked][google.cloud.dialogflow.v2.AnswerFeedback.clicked]
+ * will be updated to be true.
+ *
+ * Generated from protobuf field bool answer_copied = 1;
+ */
+ protected $answer_copied = false;
+ /**
+ * The URIs clicked by the human agent. The value is appended for each
+ * [UpdateAnswerRecordRequest][google.cloud.dialogflow.v2.UpdateAnswerRecordRequest].
+ * If the value is not empty,
+ * [AnswerFeedback.clicked][google.cloud.dialogflow.v2.AnswerFeedback.clicked]
+ * will be updated to be true.
+ *
+ * Generated from protobuf field repeated string clicked_uris = 2;
+ */
+ private $clicked_uris;
+
+ /**
+ * Constructor.
+ *
+ * @param array $data {
+ * Optional. Data for populating the Message object.
+ *
+ * @type bool $answer_copied
+ * Whether the answer was copied by the human agent or not.
+ * If the value is set to be true,
+ * [AnswerFeedback.clicked][google.cloud.dialogflow.v2.AnswerFeedback.clicked]
+ * will be updated to be true.
+ * @type array|\Google\Protobuf\Internal\RepeatedField $clicked_uris
+ * The URIs clicked by the human agent. The value is appended for each
+ * [UpdateAnswerRecordRequest][google.cloud.dialogflow.v2.UpdateAnswerRecordRequest].
+ * If the value is not empty,
+ * [AnswerFeedback.clicked][google.cloud.dialogflow.v2.AnswerFeedback.clicked]
+ * will be updated to be true.
+ * }
+ */
+ public function __construct($data = NULL) {
+ \GPBMetadata\Google\Cloud\Dialogflow\V2\AnswerRecord::initOnce();
+ parent::__construct($data);
+ }
+
+ /**
+ * Whether the answer was copied by the human agent or not.
+ * If the value is set to be true,
+ * [AnswerFeedback.clicked][google.cloud.dialogflow.v2.AnswerFeedback.clicked]
+ * will be updated to be true.
+ *
+ * Generated from protobuf field bool answer_copied = 1;
+ * @return bool
+ */
+ public function getAnswerCopied()
+ {
+ return $this->answer_copied;
+ }
+
+ /**
+ * Whether the answer was copied by the human agent or not.
+ * If the value is set to be true,
+ * [AnswerFeedback.clicked][google.cloud.dialogflow.v2.AnswerFeedback.clicked]
+ * will be updated to be true.
+ *
+ * Generated from protobuf field bool answer_copied = 1;
+ * @param bool $var
+ * @return $this
+ */
+ public function setAnswerCopied($var)
+ {
+ GPBUtil::checkBool($var);
+ $this->answer_copied = $var;
+
+ return $this;
+ }
+
+ /**
+ * The URIs clicked by the human agent. The value is appended for each
+ * [UpdateAnswerRecordRequest][google.cloud.dialogflow.v2.UpdateAnswerRecordRequest].
+ * If the value is not empty,
+ * [AnswerFeedback.clicked][google.cloud.dialogflow.v2.AnswerFeedback.clicked]
+ * will be updated to be true.
+ *
+ * Generated from protobuf field repeated string clicked_uris = 2;
+ * @return \Google\Protobuf\Internal\RepeatedField
+ */
+ public function getClickedUris()
+ {
+ return $this->clicked_uris;
+ }
+
+ /**
+ * The URIs clicked by the human agent. The value is appended for each
+ * [UpdateAnswerRecordRequest][google.cloud.dialogflow.v2.UpdateAnswerRecordRequest].
+ * If the value is not empty,
+ * [AnswerFeedback.clicked][google.cloud.dialogflow.v2.AnswerFeedback.clicked]
+ * will be updated to be true.
+ *
+ * Generated from protobuf field repeated string clicked_uris = 2;
+ * @param array|\Google\Protobuf\Internal\RepeatedField $var
+ * @return $this
+ */
+ public function setClickedUris($var)
+ {
+ $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::STRING);
+ $this->clicked_uris = $arr;
+
+ return $this;
+ }
+
+}
+
+
diff --git a/vendor/google/cloud-dialogflow/src/V2/AgentAssistantFeedback/SummarizationFeedback.php b/vendor/google/cloud-dialogflow/src/V2/AgentAssistantFeedback/SummarizationFeedback.php
new file mode 100644
index 0000000..21ba9cc
--- /dev/null
+++ b/vendor/google/cloud-dialogflow/src/V2/AgentAssistantFeedback/SummarizationFeedback.php
@@ -0,0 +1,190 @@
+google.cloud.dialogflow.v2.AgentAssistantFeedback.SummarizationFeedback
+ */
+class SummarizationFeedback extends \Google\Protobuf\Internal\Message
+{
+ /**
+ * Timestamp when composing of the summary starts.
+ *
+ * Generated from protobuf field .google.protobuf.Timestamp start_time = 1;
+ */
+ protected $start_time = null;
+ /**
+ * Timestamp when the summary was submitted.
+ *
+ * Generated from protobuf field .google.protobuf.Timestamp submit_time = 2;
+ */
+ protected $submit_time = null;
+ /**
+ * Text of actual submitted summary.
+ *
+ * Generated from protobuf field string summary_text = 3;
+ */
+ protected $summary_text = '';
+ /**
+ * Optional. Actual text sections of submitted summary.
+ *
+ * Generated from protobuf field map text_sections = 4 [(.google.api.field_behavior) = OPTIONAL];
+ */
+ private $text_sections;
+
+ /**
+ * Constructor.
+ *
+ * @param array $data {
+ * Optional. Data for populating the Message object.
+ *
+ * @type \Google\Protobuf\Timestamp $start_time
+ * Timestamp when composing of the summary starts.
+ * @type \Google\Protobuf\Timestamp $submit_time
+ * Timestamp when the summary was submitted.
+ * @type string $summary_text
+ * Text of actual submitted summary.
+ * @type array|\Google\Protobuf\Internal\MapField $text_sections
+ * Optional. Actual text sections of submitted summary.
+ * }
+ */
+ public function __construct($data = NULL) {
+ \GPBMetadata\Google\Cloud\Dialogflow\V2\AnswerRecord::initOnce();
+ parent::__construct($data);
+ }
+
+ /**
+ * Timestamp when composing of the summary starts.
+ *
+ * Generated from protobuf field .google.protobuf.Timestamp start_time = 1;
+ * @return \Google\Protobuf\Timestamp|null
+ */
+ public function getStartTime()
+ {
+ return $this->start_time;
+ }
+
+ public function hasStartTime()
+ {
+ return isset($this->start_time);
+ }
+
+ public function clearStartTime()
+ {
+ unset($this->start_time);
+ }
+
+ /**
+ * Timestamp when composing of the summary starts.
+ *
+ * Generated from protobuf field .google.protobuf.Timestamp start_time = 1;
+ * @param \Google\Protobuf\Timestamp $var
+ * @return $this
+ */
+ public function setStartTime($var)
+ {
+ GPBUtil::checkMessage($var, \Google\Protobuf\Timestamp::class);
+ $this->start_time = $var;
+
+ return $this;
+ }
+
+ /**
+ * Timestamp when the summary was submitted.
+ *
+ * Generated from protobuf field .google.protobuf.Timestamp submit_time = 2;
+ * @return \Google\Protobuf\Timestamp|null
+ */
+ public function getSubmitTime()
+ {
+ return $this->submit_time;
+ }
+
+ public function hasSubmitTime()
+ {
+ return isset($this->submit_time);
+ }
+
+ public function clearSubmitTime()
+ {
+ unset($this->submit_time);
+ }
+
+ /**
+ * Timestamp when the summary was submitted.
+ *
+ * Generated from protobuf field .google.protobuf.Timestamp submit_time = 2;
+ * @param \Google\Protobuf\Timestamp $var
+ * @return $this
+ */
+ public function setSubmitTime($var)
+ {
+ GPBUtil::checkMessage($var, \Google\Protobuf\Timestamp::class);
+ $this->submit_time = $var;
+
+ return $this;
+ }
+
+ /**
+ * Text of actual submitted summary.
+ *
+ * Generated from protobuf field string summary_text = 3;
+ * @return string
+ */
+ public function getSummaryText()
+ {
+ return $this->summary_text;
+ }
+
+ /**
+ * Text of actual submitted summary.
+ *
+ * Generated from protobuf field string summary_text = 3;
+ * @param string $var
+ * @return $this
+ */
+ public function setSummaryText($var)
+ {
+ GPBUtil::checkString($var, True);
+ $this->summary_text = $var;
+
+ return $this;
+ }
+
+ /**
+ * Optional. Actual text sections of submitted summary.
+ *
+ * Generated from protobuf field map text_sections = 4 [(.google.api.field_behavior) = OPTIONAL];
+ * @return \Google\Protobuf\Internal\MapField
+ */
+ public function getTextSections()
+ {
+ return $this->text_sections;
+ }
+
+ /**
+ * Optional. Actual text sections of submitted summary.
+ *
+ * Generated from protobuf field map text_sections = 4 [(.google.api.field_behavior) = OPTIONAL];
+ * @param array|\Google\Protobuf\Internal\MapField $var
+ * @return $this
+ */
+ public function setTextSections($var)
+ {
+ $arr = GPBUtil::checkMapField($var, \Google\Protobuf\Internal\GPBType::STRING, \Google\Protobuf\Internal\GPBType::STRING);
+ $this->text_sections = $arr;
+
+ return $this;
+ }
+
+}
+
+
diff --git a/vendor/google/cloud-dialogflow/src/V2/AgentAssistantRecord.php b/vendor/google/cloud-dialogflow/src/V2/AgentAssistantRecord.php
new file mode 100644
index 0000000..d36c798
--- /dev/null
+++ b/vendor/google/cloud-dialogflow/src/V2/AgentAssistantRecord.php
@@ -0,0 +1,141 @@
+google.cloud.dialogflow.v2.AgentAssistantRecord
+ */
+class AgentAssistantRecord extends \Google\Protobuf\Internal\Message
+{
+ protected $answer;
+
+ /**
+ * Constructor.
+ *
+ * @param array $data {
+ * Optional. Data for populating the Message object.
+ *
+ * @type \Google\Cloud\Dialogflow\V2\ArticleAnswer $article_suggestion_answer
+ * Output only. The article suggestion answer.
+ * @type \Google\Cloud\Dialogflow\V2\FaqAnswer $faq_answer
+ * Output only. The FAQ answer.
+ * @type \Google\Cloud\Dialogflow\V2\DialogflowAssistAnswer $dialogflow_assist_answer
+ * Output only. Dialogflow assist answer.
+ * }
+ */
+ public function __construct($data = NULL) {
+ \GPBMetadata\Google\Cloud\Dialogflow\V2\AnswerRecord::initOnce();
+ parent::__construct($data);
+ }
+
+ /**
+ * Output only. The article suggestion answer.
+ *
+ * Generated from protobuf field .google.cloud.dialogflow.v2.ArticleAnswer article_suggestion_answer = 5 [(.google.api.field_behavior) = OUTPUT_ONLY];
+ * @return \Google\Cloud\Dialogflow\V2\ArticleAnswer|null
+ */
+ public function getArticleSuggestionAnswer()
+ {
+ return $this->readOneof(5);
+ }
+
+ public function hasArticleSuggestionAnswer()
+ {
+ return $this->hasOneof(5);
+ }
+
+ /**
+ * Output only. The article suggestion answer.
+ *
+ * Generated from protobuf field .google.cloud.dialogflow.v2.ArticleAnswer article_suggestion_answer = 5 [(.google.api.field_behavior) = OUTPUT_ONLY];
+ * @param \Google\Cloud\Dialogflow\V2\ArticleAnswer $var
+ * @return $this
+ */
+ public function setArticleSuggestionAnswer($var)
+ {
+ GPBUtil::checkMessage($var, \Google\Cloud\Dialogflow\V2\ArticleAnswer::class);
+ $this->writeOneof(5, $var);
+
+ return $this;
+ }
+
+ /**
+ * Output only. The FAQ answer.
+ *
+ * Generated from protobuf field .google.cloud.dialogflow.v2.FaqAnswer faq_answer = 6 [(.google.api.field_behavior) = OUTPUT_ONLY];
+ * @return \Google\Cloud\Dialogflow\V2\FaqAnswer|null
+ */
+ public function getFaqAnswer()
+ {
+ return $this->readOneof(6);
+ }
+
+ public function hasFaqAnswer()
+ {
+ return $this->hasOneof(6);
+ }
+
+ /**
+ * Output only. The FAQ answer.
+ *
+ * Generated from protobuf field .google.cloud.dialogflow.v2.FaqAnswer faq_answer = 6 [(.google.api.field_behavior) = OUTPUT_ONLY];
+ * @param \Google\Cloud\Dialogflow\V2\FaqAnswer $var
+ * @return $this
+ */
+ public function setFaqAnswer($var)
+ {
+ GPBUtil::checkMessage($var, \Google\Cloud\Dialogflow\V2\FaqAnswer::class);
+ $this->writeOneof(6, $var);
+
+ return $this;
+ }
+
+ /**
+ * Output only. Dialogflow assist answer.
+ *
+ * Generated from protobuf field .google.cloud.dialogflow.v2.DialogflowAssistAnswer dialogflow_assist_answer = 7 [(.google.api.field_behavior) = OUTPUT_ONLY];
+ * @return \Google\Cloud\Dialogflow\V2\DialogflowAssistAnswer|null
+ */
+ public function getDialogflowAssistAnswer()
+ {
+ return $this->readOneof(7);
+ }
+
+ public function hasDialogflowAssistAnswer()
+ {
+ return $this->hasOneof(7);
+ }
+
+ /**
+ * Output only. Dialogflow assist answer.
+ *
+ * Generated from protobuf field .google.cloud.dialogflow.v2.DialogflowAssistAnswer dialogflow_assist_answer = 7 [(.google.api.field_behavior) = OUTPUT_ONLY];
+ * @param \Google\Cloud\Dialogflow\V2\DialogflowAssistAnswer $var
+ * @return $this
+ */
+ public function setDialogflowAssistAnswer($var)
+ {
+ GPBUtil::checkMessage($var, \Google\Cloud\Dialogflow\V2\DialogflowAssistAnswer::class);
+ $this->writeOneof(7, $var);
+
+ return $this;
+ }
+
+ /**
+ * @return string
+ */
+ public function getAnswer()
+ {
+ return $this->whichOneof("answer");
+ }
+
+}
+
diff --git a/vendor/google/cloud-dialogflow/src/V2/AnalyzeContentRequest.php b/vendor/google/cloud-dialogflow/src/V2/AnalyzeContentRequest.php
new file mode 100644
index 0000000..253b3d3
--- /dev/null
+++ b/vendor/google/cloud-dialogflow/src/V2/AnalyzeContentRequest.php
@@ -0,0 +1,521 @@
+google.cloud.dialogflow.v2.AnalyzeContentRequest
+ */
+class AnalyzeContentRequest extends \Google\Protobuf\Internal\Message
+{
+ /**
+ * Required. The name of the participant this text comes from.
+ * Format: `projects//locations//conversations//participants/`.
+ *
+ * Generated from protobuf field string participant = 1 [(.google.api.field_behavior) = REQUIRED, (.google.api.resource_reference) = {
+ */
+ protected $participant = '';
+ /**
+ * Speech synthesis configuration.
+ * The speech synthesis settings for a virtual agent that may be configured
+ * for the associated conversation profile are not used when calling
+ * AnalyzeContent. If this configuration is not supplied, speech synthesis
+ * is disabled.
+ *
+ * Generated from protobuf field .google.cloud.dialogflow.v2.OutputAudioConfig reply_audio_config = 5;
+ */
+ protected $reply_audio_config = null;
+ /**
+ * Parameters for a Dialogflow virtual-agent query.
+ *
+ * Generated from protobuf field .google.cloud.dialogflow.v2.QueryParameters query_params = 9;
+ */
+ protected $query_params = null;
+ /**
+ * Parameters for a human assist query.
+ *
+ * Generated from protobuf field .google.cloud.dialogflow.v2.AssistQueryParameters assist_query_params = 14;
+ */
+ protected $assist_query_params = null;
+ /**
+ * Additional parameters to be put into Dialogflow CX session parameters. To
+ * remove a parameter from the session, clients should explicitly set the
+ * parameter value to null.
+ * Note: this field should only be used if you are connecting to a Dialogflow
+ * CX agent.
+ *
+ * Generated from protobuf field .google.protobuf.Struct cx_parameters = 18;
+ */
+ protected $cx_parameters = null;
+ /**
+ * A unique identifier for this request. Restricted to 36 ASCII characters.
+ * A random UUID is recommended.
+ * This request is only idempotent if a `request_id` is provided.
+ *
+ * Generated from protobuf field string request_id = 11;
+ */
+ protected $request_id = '';
+ protected $input;
+
+ /**
+ * @param string $participant Required. The name of the participant this text comes from.
+ * Format: `projects//locations//conversations//participants/`. Please see
+ * {@see ParticipantsClient::participantName()} for help formatting this field.
+ * @param \Google\Cloud\Dialogflow\V2\TextInput $textInput The natural language text to be processed.
+ *
+ * @return \Google\Cloud\Dialogflow\V2\AnalyzeContentRequest
+ *
+ * @experimental
+ */
+ public static function build(string $participant, \Google\Cloud\Dialogflow\V2\TextInput $textInput): self
+ {
+ return (new self())
+ ->setParticipant($participant)
+ ->setTextInput($textInput);
+ }
+
+ /**
+ * @param string $participant Required. The name of the participant this text comes from.
+ * Format: `projects//locations//conversations//participants/`. Please see
+ * {@see ParticipantsClient::participantName()} for help formatting this field.
+ * @param \Google\Cloud\Dialogflow\V2\EventInput $eventInput An input event to send to Dialogflow.
+ *
+ * @return \Google\Cloud\Dialogflow\V2\AnalyzeContentRequest
+ *
+ * @experimental
+ */
+ public static function buildFromParticipantEventInput(string $participant, \Google\Cloud\Dialogflow\V2\EventInput $eventInput): self
+ {
+ return (new self())
+ ->setParticipant($participant)
+ ->setEventInput($eventInput);
+ }
+
+ /**
+ * @param string $participant Required. The name of the participant this text comes from.
+ * Format: `projects//locations//conversations//participants/`. Please see
+ * {@see ParticipantsClient::participantName()} for help formatting this field.
+ * @param \Google\Cloud\Dialogflow\V2\AudioInput $audioInput The natural language speech audio to be processed.
+ *
+ * @return \Google\Cloud\Dialogflow\V2\AnalyzeContentRequest
+ *
+ * @experimental
+ */
+ public static function buildFromParticipantAudioInput(string $participant, \Google\Cloud\Dialogflow\V2\AudioInput $audioInput): self
+ {
+ return (new self())
+ ->setParticipant($participant)
+ ->setAudioInput($audioInput);
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param array $data {
+ * Optional. Data for populating the Message object.
+ *
+ * @type string $participant
+ * Required. The name of the participant this text comes from.
+ * Format: `projects//locations//conversations//participants/`.
+ * @type \Google\Cloud\Dialogflow\V2\TextInput $text_input
+ * The natural language text to be processed.
+ * @type \Google\Cloud\Dialogflow\V2\AudioInput $audio_input
+ * The natural language speech audio to be processed.
+ * @type \Google\Cloud\Dialogflow\V2\EventInput $event_input
+ * An input event to send to Dialogflow.
+ * @type \Google\Cloud\Dialogflow\V2\SuggestionInput $suggestion_input
+ * An input representing the selection of a suggestion.
+ * @type \Google\Cloud\Dialogflow\V2\OutputAudioConfig $reply_audio_config
+ * Speech synthesis configuration.
+ * The speech synthesis settings for a virtual agent that may be configured
+ * for the associated conversation profile are not used when calling
+ * AnalyzeContent. If this configuration is not supplied, speech synthesis
+ * is disabled.
+ * @type \Google\Cloud\Dialogflow\V2\QueryParameters $query_params
+ * Parameters for a Dialogflow virtual-agent query.
+ * @type \Google\Cloud\Dialogflow\V2\AssistQueryParameters $assist_query_params
+ * Parameters for a human assist query.
+ * @type \Google\Protobuf\Struct $cx_parameters
+ * Additional parameters to be put into Dialogflow CX session parameters. To
+ * remove a parameter from the session, clients should explicitly set the
+ * parameter value to null.
+ * Note: this field should only be used if you are connecting to a Dialogflow
+ * CX agent.
+ * @type string $request_id
+ * A unique identifier for this request. Restricted to 36 ASCII characters.
+ * A random UUID is recommended.
+ * This request is only idempotent if a `request_id` is provided.
+ * }
+ */
+ public function __construct($data = NULL) {
+ \GPBMetadata\Google\Cloud\Dialogflow\V2\Participant::initOnce();
+ parent::__construct($data);
+ }
+
+ /**
+ * Required. The name of the participant this text comes from.
+ * Format: `projects//locations//conversations//participants/`.
+ *
+ * Generated from protobuf field string participant = 1 [(.google.api.field_behavior) = REQUIRED, (.google.api.resource_reference) = {
+ * @return string
+ */
+ public function getParticipant()
+ {
+ return $this->participant;
+ }
+
+ /**
+ * Required. The name of the participant this text comes from.
+ * Format: `projects//locations//conversations//participants/`.
+ *
+ * Generated from protobuf field string participant = 1 [(.google.api.field_behavior) = REQUIRED, (.google.api.resource_reference) = {
+ * @param string $var
+ * @return $this
+ */
+ public function setParticipant($var)
+ {
+ GPBUtil::checkString($var, True);
+ $this->participant = $var;
+
+ return $this;
+ }
+
+ /**
+ * The natural language text to be processed.
+ *
+ * Generated from protobuf field .google.cloud.dialogflow.v2.TextInput text_input = 6;
+ * @return \Google\Cloud\Dialogflow\V2\TextInput|null
+ */
+ public function getTextInput()
+ {
+ return $this->readOneof(6);
+ }
+
+ public function hasTextInput()
+ {
+ return $this->hasOneof(6);
+ }
+
+ /**
+ * The natural language text to be processed.
+ *
+ * Generated from protobuf field .google.cloud.dialogflow.v2.TextInput text_input = 6;
+ * @param \Google\Cloud\Dialogflow\V2\TextInput $var
+ * @return $this
+ */
+ public function setTextInput($var)
+ {
+ GPBUtil::checkMessage($var, \Google\Cloud\Dialogflow\V2\TextInput::class);
+ $this->writeOneof(6, $var);
+
+ return $this;
+ }
+
+ /**
+ * The natural language speech audio to be processed.
+ *
+ * Generated from protobuf field .google.cloud.dialogflow.v2.AudioInput audio_input = 7;
+ * @return \Google\Cloud\Dialogflow\V2\AudioInput|null
+ */
+ public function getAudioInput()
+ {
+ return $this->readOneof(7);
+ }
+
+ public function hasAudioInput()
+ {
+ return $this->hasOneof(7);
+ }
+
+ /**
+ * The natural language speech audio to be processed.
+ *
+ * Generated from protobuf field .google.cloud.dialogflow.v2.AudioInput audio_input = 7;
+ * @param \Google\Cloud\Dialogflow\V2\AudioInput $var
+ * @return $this
+ */
+ public function setAudioInput($var)
+ {
+ GPBUtil::checkMessage($var, \Google\Cloud\Dialogflow\V2\AudioInput::class);
+ $this->writeOneof(7, $var);
+
+ return $this;
+ }
+
+ /**
+ * An input event to send to Dialogflow.
+ *
+ * Generated from protobuf field .google.cloud.dialogflow.v2.EventInput event_input = 8;
+ * @return \Google\Cloud\Dialogflow\V2\EventInput|null
+ */
+ public function getEventInput()
+ {
+ return $this->readOneof(8);
+ }
+
+ public function hasEventInput()
+ {
+ return $this->hasOneof(8);
+ }
+
+ /**
+ * An input event to send to Dialogflow.
+ *
+ * Generated from protobuf field .google.cloud.dialogflow.v2.EventInput event_input = 8;
+ * @param \Google\Cloud\Dialogflow\V2\EventInput $var
+ * @return $this
+ */
+ public function setEventInput($var)
+ {
+ GPBUtil::checkMessage($var, \Google\Cloud\Dialogflow\V2\EventInput::class);
+ $this->writeOneof(8, $var);
+
+ return $this;
+ }
+
+ /**
+ * An input representing the selection of a suggestion.
+ *
+ * Generated from protobuf field .google.cloud.dialogflow.v2.SuggestionInput suggestion_input = 12;
+ * @return \Google\Cloud\Dialogflow\V2\SuggestionInput|null
+ */
+ public function getSuggestionInput()
+ {
+ return $this->readOneof(12);
+ }
+
+ public function hasSuggestionInput()
+ {
+ return $this->hasOneof(12);
+ }
+
+ /**
+ * An input representing the selection of a suggestion.
+ *
+ * Generated from protobuf field .google.cloud.dialogflow.v2.SuggestionInput suggestion_input = 12;
+ * @param \Google\Cloud\Dialogflow\V2\SuggestionInput $var
+ * @return $this
+ */
+ public function setSuggestionInput($var)
+ {
+ GPBUtil::checkMessage($var, \Google\Cloud\Dialogflow\V2\SuggestionInput::class);
+ $this->writeOneof(12, $var);
+
+ return $this;
+ }
+
+ /**
+ * Speech synthesis configuration.
+ * The speech synthesis settings for a virtual agent that may be configured
+ * for the associated conversation profile are not used when calling
+ * AnalyzeContent. If this configuration is not supplied, speech synthesis
+ * is disabled.
+ *
+ * Generated from protobuf field .google.cloud.dialogflow.v2.OutputAudioConfig reply_audio_config = 5;
+ * @return \Google\Cloud\Dialogflow\V2\OutputAudioConfig|null
+ */
+ public function getReplyAudioConfig()
+ {
+ return $this->reply_audio_config;
+ }
+
+ public function hasReplyAudioConfig()
+ {
+ return isset($this->reply_audio_config);
+ }
+
+ public function clearReplyAudioConfig()
+ {
+ unset($this->reply_audio_config);
+ }
+
+ /**
+ * Speech synthesis configuration.
+ * The speech synthesis settings for a virtual agent that may be configured
+ * for the associated conversation profile are not used when calling
+ * AnalyzeContent. If this configuration is not supplied, speech synthesis
+ * is disabled.
+ *
+ * Generated from protobuf field .google.cloud.dialogflow.v2.OutputAudioConfig reply_audio_config = 5;
+ * @param \Google\Cloud\Dialogflow\V2\OutputAudioConfig $var
+ * @return $this
+ */
+ public function setReplyAudioConfig($var)
+ {
+ GPBUtil::checkMessage($var, \Google\Cloud\Dialogflow\V2\OutputAudioConfig::class);
+ $this->reply_audio_config = $var;
+
+ return $this;
+ }
+
+ /**
+ * Parameters for a Dialogflow virtual-agent query.
+ *
+ * Generated from protobuf field .google.cloud.dialogflow.v2.QueryParameters query_params = 9;
+ * @return \Google\Cloud\Dialogflow\V2\QueryParameters|null
+ */
+ public function getQueryParams()
+ {
+ return $this->query_params;
+ }
+
+ public function hasQueryParams()
+ {
+ return isset($this->query_params);
+ }
+
+ public function clearQueryParams()
+ {
+ unset($this->query_params);
+ }
+
+ /**
+ * Parameters for a Dialogflow virtual-agent query.
+ *
+ * Generated from protobuf field .google.cloud.dialogflow.v2.QueryParameters query_params = 9;
+ * @param \Google\Cloud\Dialogflow\V2\QueryParameters $var
+ * @return $this
+ */
+ public function setQueryParams($var)
+ {
+ GPBUtil::checkMessage($var, \Google\Cloud\Dialogflow\V2\QueryParameters::class);
+ $this->query_params = $var;
+
+ return $this;
+ }
+
+ /**
+ * Parameters for a human assist query.
+ *
+ * Generated from protobuf field .google.cloud.dialogflow.v2.AssistQueryParameters assist_query_params = 14;
+ * @return \Google\Cloud\Dialogflow\V2\AssistQueryParameters|null
+ */
+ public function getAssistQueryParams()
+ {
+ return $this->assist_query_params;
+ }
+
+ public function hasAssistQueryParams()
+ {
+ return isset($this->assist_query_params);
+ }
+
+ public function clearAssistQueryParams()
+ {
+ unset($this->assist_query_params);
+ }
+
+ /**
+ * Parameters for a human assist query.
+ *
+ * Generated from protobuf field .google.cloud.dialogflow.v2.AssistQueryParameters assist_query_params = 14;
+ * @param \Google\Cloud\Dialogflow\V2\AssistQueryParameters $var
+ * @return $this
+ */
+ public function setAssistQueryParams($var)
+ {
+ GPBUtil::checkMessage($var, \Google\Cloud\Dialogflow\V2\AssistQueryParameters::class);
+ $this->assist_query_params = $var;
+
+ return $this;
+ }
+
+ /**
+ * Additional parameters to be put into Dialogflow CX session parameters. To
+ * remove a parameter from the session, clients should explicitly set the
+ * parameter value to null.
+ * Note: this field should only be used if you are connecting to a Dialogflow
+ * CX agent.
+ *
+ * Generated from protobuf field .google.protobuf.Struct cx_parameters = 18;
+ * @return \Google\Protobuf\Struct|null
+ */
+ public function getCxParameters()
+ {
+ return $this->cx_parameters;
+ }
+
+ public function hasCxParameters()
+ {
+ return isset($this->cx_parameters);
+ }
+
+ public function clearCxParameters()
+ {
+ unset($this->cx_parameters);
+ }
+
+ /**
+ * Additional parameters to be put into Dialogflow CX session parameters. To
+ * remove a parameter from the session, clients should explicitly set the
+ * parameter value to null.
+ * Note: this field should only be used if you are connecting to a Dialogflow
+ * CX agent.
+ *
+ * Generated from protobuf field .google.protobuf.Struct cx_parameters = 18;
+ * @param \Google\Protobuf\Struct $var
+ * @return $this
+ */
+ public function setCxParameters($var)
+ {
+ GPBUtil::checkMessage($var, \Google\Protobuf\Struct::class);
+ $this->cx_parameters = $var;
+
+ return $this;
+ }
+
+ /**
+ * A unique identifier for this request. Restricted to 36 ASCII characters.
+ * A random UUID is recommended.
+ * This request is only idempotent if a `request_id` is provided.
+ *
+ * Generated from protobuf field string request_id = 11;
+ * @return string
+ */
+ public function getRequestId()
+ {
+ return $this->request_id;
+ }
+
+ /**
+ * A unique identifier for this request. Restricted to 36 ASCII characters.
+ * A random UUID is recommended.
+ * This request is only idempotent if a `request_id` is provided.
+ *
+ * Generated from protobuf field string request_id = 11;
+ * @param string $var
+ * @return $this
+ */
+ public function setRequestId($var)
+ {
+ GPBUtil::checkString($var, True);
+ $this->request_id = $var;
+
+ return $this;
+ }
+
+ /**
+ * @return string
+ */
+ public function getInput()
+ {
+ return $this->whichOneof("input");
+ }
+
+}
+
diff --git a/vendor/google/cloud-dialogflow/src/V2/AnalyzeContentResponse.php b/vendor/google/cloud-dialogflow/src/V2/AnalyzeContentResponse.php
new file mode 100644
index 0000000..0302ea4
--- /dev/null
+++ b/vendor/google/cloud-dialogflow/src/V2/AnalyzeContentResponse.php
@@ -0,0 +1,432 @@
+google.cloud.dialogflow.v2.AnalyzeContentResponse
+ */
+class AnalyzeContentResponse extends \Google\Protobuf\Internal\Message
+{
+ /**
+ * The output text content.
+ * This field is set if the automated agent responded with text to show to
+ * the user.
+ *
+ * Generated from protobuf field string reply_text = 1;
+ */
+ protected $reply_text = '';
+ /**
+ * The audio data bytes encoded as specified in the request.
+ * This field is set if:
+ * - `reply_audio_config` was specified in the request, or
+ * - The automated agent responded with audio to play to the user. In such
+ * case, `reply_audio.config` contains settings used to synthesize the
+ * speech.
+ * In some scenarios, multiple output audio fields may be present in the
+ * response structure. In these cases, only the top-most-level audio output
+ * has content.
+ *
+ * Generated from protobuf field .google.cloud.dialogflow.v2.OutputAudio reply_audio = 2;
+ */
+ protected $reply_audio = null;
+ /**
+ * Only set if a Dialogflow automated agent has responded.
+ * Note that in [AutomatedAgentReply.DetectIntentResponse][],
+ * [Sessions.DetectIntentResponse.output_audio][]
+ * and [Sessions.DetectIntentResponse.output_audio_config][]
+ * are always empty, use
+ * [reply_audio][google.cloud.dialogflow.v2.AnalyzeContentResponse.reply_audio]
+ * instead.
+ *
+ * Generated from protobuf field .google.cloud.dialogflow.v2.AutomatedAgentReply automated_agent_reply = 3;
+ */
+ protected $automated_agent_reply = null;
+ /**
+ * Message analyzed by CCAI.
+ *
+ * Generated from protobuf field .google.cloud.dialogflow.v2.Message message = 5;
+ */
+ protected $message = null;
+ /**
+ * The suggestions for most recent human agent. The order is the same as
+ * [HumanAgentAssistantConfig.SuggestionConfig.feature_configs][google.cloud.dialogflow.v2.HumanAgentAssistantConfig.SuggestionConfig.feature_configs]
+ * of
+ * [HumanAgentAssistantConfig.human_agent_suggestion_config][google.cloud.dialogflow.v2.HumanAgentAssistantConfig.human_agent_suggestion_config].
+ * Note that any failure of Agent Assist features will not lead to the overall
+ * failure of an AnalyzeContent API call. Instead, the features will
+ * fail silently with the error field set in the corresponding
+ * SuggestionResult.
+ *
+ * Generated from protobuf field repeated .google.cloud.dialogflow.v2.SuggestionResult human_agent_suggestion_results = 6;
+ */
+ private $human_agent_suggestion_results;
+ /**
+ * The suggestions for end user. The order is the same as
+ * [HumanAgentAssistantConfig.SuggestionConfig.feature_configs][google.cloud.dialogflow.v2.HumanAgentAssistantConfig.SuggestionConfig.feature_configs]
+ * of
+ * [HumanAgentAssistantConfig.end_user_suggestion_config][google.cloud.dialogflow.v2.HumanAgentAssistantConfig.end_user_suggestion_config].
+ * Same as human_agent_suggestion_results, any failure of Agent Assist
+ * features will not lead to the overall failure of an AnalyzeContent API
+ * call. Instead, the features will fail silently with the error field set in
+ * the corresponding SuggestionResult.
+ *
+ * Generated from protobuf field repeated .google.cloud.dialogflow.v2.SuggestionResult end_user_suggestion_results = 7;
+ */
+ private $end_user_suggestion_results;
+ /**
+ * Indicates the parameters of DTMF.
+ *
+ * Generated from protobuf field .google.cloud.dialogflow.v2.DtmfParameters dtmf_parameters = 9;
+ */
+ protected $dtmf_parameters = null;
+
+ /**
+ * Constructor.
+ *
+ * @param array $data {
+ * Optional. Data for populating the Message object.
+ *
+ * @type string $reply_text
+ * The output text content.
+ * This field is set if the automated agent responded with text to show to
+ * the user.
+ * @type \Google\Cloud\Dialogflow\V2\OutputAudio $reply_audio
+ * The audio data bytes encoded as specified in the request.
+ * This field is set if:
+ * - `reply_audio_config` was specified in the request, or
+ * - The automated agent responded with audio to play to the user. In such
+ * case, `reply_audio.config` contains settings used to synthesize the
+ * speech.
+ * In some scenarios, multiple output audio fields may be present in the
+ * response structure. In these cases, only the top-most-level audio output
+ * has content.
+ * @type \Google\Cloud\Dialogflow\V2\AutomatedAgentReply $automated_agent_reply
+ * Only set if a Dialogflow automated agent has responded.
+ * Note that in [AutomatedAgentReply.DetectIntentResponse][],
+ * [Sessions.DetectIntentResponse.output_audio][]
+ * and [Sessions.DetectIntentResponse.output_audio_config][]
+ * are always empty, use
+ * [reply_audio][google.cloud.dialogflow.v2.AnalyzeContentResponse.reply_audio]
+ * instead.
+ * @type \Google\Cloud\Dialogflow\V2\Message $message
+ * Message analyzed by CCAI.
+ * @type array<\Google\Cloud\Dialogflow\V2\SuggestionResult>|\Google\Protobuf\Internal\RepeatedField $human_agent_suggestion_results
+ * The suggestions for most recent human agent. The order is the same as
+ * [HumanAgentAssistantConfig.SuggestionConfig.feature_configs][google.cloud.dialogflow.v2.HumanAgentAssistantConfig.SuggestionConfig.feature_configs]
+ * of
+ * [HumanAgentAssistantConfig.human_agent_suggestion_config][google.cloud.dialogflow.v2.HumanAgentAssistantConfig.human_agent_suggestion_config].
+ * Note that any failure of Agent Assist features will not lead to the overall
+ * failure of an AnalyzeContent API call. Instead, the features will
+ * fail silently with the error field set in the corresponding
+ * SuggestionResult.
+ * @type array<\Google\Cloud\Dialogflow\V2\SuggestionResult>|\Google\Protobuf\Internal\RepeatedField $end_user_suggestion_results
+ * The suggestions for end user. The order is the same as
+ * [HumanAgentAssistantConfig.SuggestionConfig.feature_configs][google.cloud.dialogflow.v2.HumanAgentAssistantConfig.SuggestionConfig.feature_configs]
+ * of
+ * [HumanAgentAssistantConfig.end_user_suggestion_config][google.cloud.dialogflow.v2.HumanAgentAssistantConfig.end_user_suggestion_config].
+ * Same as human_agent_suggestion_results, any failure of Agent Assist
+ * features will not lead to the overall failure of an AnalyzeContent API
+ * call. Instead, the features will fail silently with the error field set in
+ * the corresponding SuggestionResult.
+ * @type \Google\Cloud\Dialogflow\V2\DtmfParameters $dtmf_parameters
+ * Indicates the parameters of DTMF.
+ * }
+ */
+ public function __construct($data = NULL) {
+ \GPBMetadata\Google\Cloud\Dialogflow\V2\Participant::initOnce();
+ parent::__construct($data);
+ }
+
+ /**
+ * The output text content.
+ * This field is set if the automated agent responded with text to show to
+ * the user.
+ *
+ * Generated from protobuf field string reply_text = 1;
+ * @return string
+ */
+ public function getReplyText()
+ {
+ return $this->reply_text;
+ }
+
+ /**
+ * The output text content.
+ * This field is set if the automated agent responded with text to show to
+ * the user.
+ *
+ * Generated from protobuf field string reply_text = 1;
+ * @param string $var
+ * @return $this
+ */
+ public function setReplyText($var)
+ {
+ GPBUtil::checkString($var, True);
+ $this->reply_text = $var;
+
+ return $this;
+ }
+
+ /**
+ * The audio data bytes encoded as specified in the request.
+ * This field is set if:
+ * - `reply_audio_config` was specified in the request, or
+ * - The automated agent responded with audio to play to the user. In such
+ * case, `reply_audio.config` contains settings used to synthesize the
+ * speech.
+ * In some scenarios, multiple output audio fields may be present in the
+ * response structure. In these cases, only the top-most-level audio output
+ * has content.
+ *
+ * Generated from protobuf field .google.cloud.dialogflow.v2.OutputAudio reply_audio = 2;
+ * @return \Google\Cloud\Dialogflow\V2\OutputAudio|null
+ */
+ public function getReplyAudio()
+ {
+ return $this->reply_audio;
+ }
+
+ public function hasReplyAudio()
+ {
+ return isset($this->reply_audio);
+ }
+
+ public function clearReplyAudio()
+ {
+ unset($this->reply_audio);
+ }
+
+ /**
+ * The audio data bytes encoded as specified in the request.
+ * This field is set if:
+ * - `reply_audio_config` was specified in the request, or
+ * - The automated agent responded with audio to play to the user. In such
+ * case, `reply_audio.config` contains settings used to synthesize the
+ * speech.
+ * In some scenarios, multiple output audio fields may be present in the
+ * response structure. In these cases, only the top-most-level audio output
+ * has content.
+ *
+ * Generated from protobuf field .google.cloud.dialogflow.v2.OutputAudio reply_audio = 2;
+ * @param \Google\Cloud\Dialogflow\V2\OutputAudio $var
+ * @return $this
+ */
+ public function setReplyAudio($var)
+ {
+ GPBUtil::checkMessage($var, \Google\Cloud\Dialogflow\V2\OutputAudio::class);
+ $this->reply_audio = $var;
+
+ return $this;
+ }
+
+ /**
+ * Only set if a Dialogflow automated agent has responded.
+ * Note that in [AutomatedAgentReply.DetectIntentResponse][],
+ * [Sessions.DetectIntentResponse.output_audio][]
+ * and [Sessions.DetectIntentResponse.output_audio_config][]
+ * are always empty, use
+ * [reply_audio][google.cloud.dialogflow.v2.AnalyzeContentResponse.reply_audio]
+ * instead.
+ *
+ * Generated from protobuf field .google.cloud.dialogflow.v2.AutomatedAgentReply automated_agent_reply = 3;
+ * @return \Google\Cloud\Dialogflow\V2\AutomatedAgentReply|null
+ */
+ public function getAutomatedAgentReply()
+ {
+ return $this->automated_agent_reply;
+ }
+
+ public function hasAutomatedAgentReply()
+ {
+ return isset($this->automated_agent_reply);
+ }
+
+ public function clearAutomatedAgentReply()
+ {
+ unset($this->automated_agent_reply);
+ }
+
+ /**
+ * Only set if a Dialogflow automated agent has responded.
+ * Note that in [AutomatedAgentReply.DetectIntentResponse][],
+ * [Sessions.DetectIntentResponse.output_audio][]
+ * and [Sessions.DetectIntentResponse.output_audio_config][]
+ * are always empty, use
+ * [reply_audio][google.cloud.dialogflow.v2.AnalyzeContentResponse.reply_audio]
+ * instead.
+ *
+ * Generated from protobuf field .google.cloud.dialogflow.v2.AutomatedAgentReply automated_agent_reply = 3;
+ * @param \Google\Cloud\Dialogflow\V2\AutomatedAgentReply $var
+ * @return $this
+ */
+ public function setAutomatedAgentReply($var)
+ {
+ GPBUtil::checkMessage($var, \Google\Cloud\Dialogflow\V2\AutomatedAgentReply::class);
+ $this->automated_agent_reply = $var;
+
+ return $this;
+ }
+
+ /**
+ * Message analyzed by CCAI.
+ *
+ * Generated from protobuf field .google.cloud.dialogflow.v2.Message message = 5;
+ * @return \Google\Cloud\Dialogflow\V2\Message|null
+ */
+ public function getMessage()
+ {
+ return $this->message;
+ }
+
+ public function hasMessage()
+ {
+ return isset($this->message);
+ }
+
+ public function clearMessage()
+ {
+ unset($this->message);
+ }
+
+ /**
+ * Message analyzed by CCAI.
+ *
+ * Generated from protobuf field .google.cloud.dialogflow.v2.Message message = 5;
+ * @param \Google\Cloud\Dialogflow\V2\Message $var
+ * @return $this
+ */
+ public function setMessage($var)
+ {
+ GPBUtil::checkMessage($var, \Google\Cloud\Dialogflow\V2\Message::class);
+ $this->message = $var;
+
+ return $this;
+ }
+
+ /**
+ * The suggestions for most recent human agent. The order is the same as
+ * [HumanAgentAssistantConfig.SuggestionConfig.feature_configs][google.cloud.dialogflow.v2.HumanAgentAssistantConfig.SuggestionConfig.feature_configs]
+ * of
+ * [HumanAgentAssistantConfig.human_agent_suggestion_config][google.cloud.dialogflow.v2.HumanAgentAssistantConfig.human_agent_suggestion_config].
+ * Note that any failure of Agent Assist features will not lead to the overall
+ * failure of an AnalyzeContent API call. Instead, the features will
+ * fail silently with the error field set in the corresponding
+ * SuggestionResult.
+ *
+ * Generated from protobuf field repeated .google.cloud.dialogflow.v2.SuggestionResult human_agent_suggestion_results = 6;
+ * @return \Google\Protobuf\Internal\RepeatedField
+ */
+ public function getHumanAgentSuggestionResults()
+ {
+ return $this->human_agent_suggestion_results;
+ }
+
+ /**
+ * The suggestions for most recent human agent. The order is the same as
+ * [HumanAgentAssistantConfig.SuggestionConfig.feature_configs][google.cloud.dialogflow.v2.HumanAgentAssistantConfig.SuggestionConfig.feature_configs]
+ * of
+ * [HumanAgentAssistantConfig.human_agent_suggestion_config][google.cloud.dialogflow.v2.HumanAgentAssistantConfig.human_agent_suggestion_config].
+ * Note that any failure of Agent Assist features will not lead to the overall
+ * failure of an AnalyzeContent API call. Instead, the features will
+ * fail silently with the error field set in the corresponding
+ * SuggestionResult.
+ *
+ * Generated from protobuf field repeated .google.cloud.dialogflow.v2.SuggestionResult human_agent_suggestion_results = 6;
+ * @param array<\Google\Cloud\Dialogflow\V2\SuggestionResult>|\Google\Protobuf\Internal\RepeatedField $var
+ * @return $this
+ */
+ public function setHumanAgentSuggestionResults($var)
+ {
+ $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Cloud\Dialogflow\V2\SuggestionResult::class);
+ $this->human_agent_suggestion_results = $arr;
+
+ return $this;
+ }
+
+ /**
+ * The suggestions for end user. The order is the same as
+ * [HumanAgentAssistantConfig.SuggestionConfig.feature_configs][google.cloud.dialogflow.v2.HumanAgentAssistantConfig.SuggestionConfig.feature_configs]
+ * of
+ * [HumanAgentAssistantConfig.end_user_suggestion_config][google.cloud.dialogflow.v2.HumanAgentAssistantConfig.end_user_suggestion_config].
+ * Same as human_agent_suggestion_results, any failure of Agent Assist
+ * features will not lead to the overall failure of an AnalyzeContent API
+ * call. Instead, the features will fail silently with the error field set in
+ * the corresponding SuggestionResult.
+ *
+ * Generated from protobuf field repeated .google.cloud.dialogflow.v2.SuggestionResult end_user_suggestion_results = 7;
+ * @return \Google\Protobuf\Internal\RepeatedField
+ */
+ public function getEndUserSuggestionResults()
+ {
+ return $this->end_user_suggestion_results;
+ }
+
+ /**
+ * The suggestions for end user. The order is the same as
+ * [HumanAgentAssistantConfig.SuggestionConfig.feature_configs][google.cloud.dialogflow.v2.HumanAgentAssistantConfig.SuggestionConfig.feature_configs]
+ * of
+ * [HumanAgentAssistantConfig.end_user_suggestion_config][google.cloud.dialogflow.v2.HumanAgentAssistantConfig.end_user_suggestion_config].
+ * Same as human_agent_suggestion_results, any failure of Agent Assist
+ * features will not lead to the overall failure of an AnalyzeContent API
+ * call. Instead, the features will fail silently with the error field set in
+ * the corresponding SuggestionResult.
+ *
+ * Generated from protobuf field repeated .google.cloud.dialogflow.v2.SuggestionResult end_user_suggestion_results = 7;
+ * @param array<\Google\Cloud\Dialogflow\V2\SuggestionResult>|\Google\Protobuf\Internal\RepeatedField $var
+ * @return $this
+ */
+ public function setEndUserSuggestionResults($var)
+ {
+ $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Cloud\Dialogflow\V2\SuggestionResult::class);
+ $this->end_user_suggestion_results = $arr;
+
+ return $this;
+ }
+
+ /**
+ * Indicates the parameters of DTMF.
+ *
+ * Generated from protobuf field .google.cloud.dialogflow.v2.DtmfParameters dtmf_parameters = 9;
+ * @return \Google\Cloud\Dialogflow\V2\DtmfParameters|null
+ */
+ public function getDtmfParameters()
+ {
+ return $this->dtmf_parameters;
+ }
+
+ public function hasDtmfParameters()
+ {
+ return isset($this->dtmf_parameters);
+ }
+
+ public function clearDtmfParameters()
+ {
+ unset($this->dtmf_parameters);
+ }
+
+ /**
+ * Indicates the parameters of DTMF.
+ *
+ * Generated from protobuf field .google.cloud.dialogflow.v2.DtmfParameters dtmf_parameters = 9;
+ * @param \Google\Cloud\Dialogflow\V2\DtmfParameters $var
+ * @return $this
+ */
+ public function setDtmfParameters($var)
+ {
+ GPBUtil::checkMessage($var, \Google\Cloud\Dialogflow\V2\DtmfParameters::class);
+ $this->dtmf_parameters = $var;
+
+ return $this;
+ }
+
+}
+
diff --git a/vendor/google/cloud-dialogflow/src/V2/AnnotatedMessagePart.php b/vendor/google/cloud-dialogflow/src/V2/AnnotatedMessagePart.php
new file mode 100644
index 0000000..932abff
--- /dev/null
+++ b/vendor/google/cloud-dialogflow/src/V2/AnnotatedMessagePart.php
@@ -0,0 +1,195 @@
+google.cloud.dialogflow.v2.AnnotatedMessagePart
+ */
+class AnnotatedMessagePart extends \Google\Protobuf\Internal\Message
+{
+ /**
+ * A part of a message possibly annotated with an entity.
+ *
+ * Generated from protobuf field string text = 1;
+ */
+ protected $text = '';
+ /**
+ * The [Dialogflow system entity
+ * type](https://cloud.google.com/dialogflow/docs/reference/system-entities)
+ * of this message part. If this is empty, Dialogflow could not annotate the
+ * phrase part with a system entity.
+ *
+ * Generated from protobuf field string entity_type = 2;
+ */
+ protected $entity_type = '';
+ /**
+ * The [Dialogflow system entity formatted value
+ * ](https://cloud.google.com/dialogflow/docs/reference/system-entities) of
+ * this message part. For example for a system entity of type
+ * `@sys.unit-currency`, this may contain:
+ *
+ * {
+ * "amount": 5,
+ * "currency": "USD"
+ * }
+ *
+ *
+ * Generated from protobuf field .google.protobuf.Value formatted_value = 3;
+ */
+ protected $formatted_value = null;
+
+ /**
+ * Constructor.
+ *
+ * @param array $data {
+ * Optional. Data for populating the Message object.
+ *
+ * @type string $text
+ * A part of a message possibly annotated with an entity.
+ * @type string $entity_type
+ * The [Dialogflow system entity
+ * type](https://cloud.google.com/dialogflow/docs/reference/system-entities)
+ * of this message part. If this is empty, Dialogflow could not annotate the
+ * phrase part with a system entity.
+ * @type \Google\Protobuf\Value $formatted_value
+ * The [Dialogflow system entity formatted value
+ * ](https://cloud.google.com/dialogflow/docs/reference/system-entities) of
+ * this message part. For example for a system entity of type
+ * `@sys.unit-currency`, this may contain:
+ *
+ * {
+ * "amount": 5,
+ * "currency": "USD"
+ * }
+ *
+ * }
+ */
+ public function __construct($data = NULL) {
+ \GPBMetadata\Google\Cloud\Dialogflow\V2\Participant::initOnce();
+ parent::__construct($data);
+ }
+
+ /**
+ * A part of a message possibly annotated with an entity.
+ *
+ * Generated from protobuf field string text = 1;
+ * @return string
+ */
+ public function getText()
+ {
+ return $this->text;
+ }
+
+ /**
+ * A part of a message possibly annotated with an entity.
+ *
+ * Generated from protobuf field string text = 1;
+ * @param string $var
+ * @return $this
+ */
+ public function setText($var)
+ {
+ GPBUtil::checkString($var, True);
+ $this->text = $var;
+
+ return $this;
+ }
+
+ /**
+ * The [Dialogflow system entity
+ * type](https://cloud.google.com/dialogflow/docs/reference/system-entities)
+ * of this message part. If this is empty, Dialogflow could not annotate the
+ * phrase part with a system entity.
+ *
+ * Generated from protobuf field string entity_type = 2;
+ * @return string
+ */
+ public function getEntityType()
+ {
+ return $this->entity_type;
+ }
+
+ /**
+ * The [Dialogflow system entity
+ * type](https://cloud.google.com/dialogflow/docs/reference/system-entities)
+ * of this message part. If this is empty, Dialogflow could not annotate the
+ * phrase part with a system entity.
+ *
+ * Generated from protobuf field string entity_type = 2;
+ * @param string $var
+ * @return $this
+ */
+ public function setEntityType($var)
+ {
+ GPBUtil::checkString($var, True);
+ $this->entity_type = $var;
+
+ return $this;
+ }
+
+ /**
+ * The [Dialogflow system entity formatted value
+ * ](https://cloud.google.com/dialogflow/docs/reference/system-entities) of
+ * this message part. For example for a system entity of type
+ * `@sys.unit-currency`, this may contain:
+ *
+ * {
+ * "amount": 5,
+ * "currency": "USD"
+ * }
+ *
+ *
+ * Generated from protobuf field .google.protobuf.Value formatted_value = 3;
+ * @return \Google\Protobuf\Value|null
+ */
+ public function getFormattedValue()
+ {
+ return $this->formatted_value;
+ }
+
+ public function hasFormattedValue()
+ {
+ return isset($this->formatted_value);
+ }
+
+ public function clearFormattedValue()
+ {
+ unset($this->formatted_value);
+ }
+
+ /**
+ * The [Dialogflow system entity formatted value
+ * ](https://cloud.google.com/dialogflow/docs/reference/system-entities) of
+ * this message part. For example for a system entity of type
+ * `@sys.unit-currency`, this may contain:
+ *
+ * {
+ * "amount": 5,
+ * "currency": "USD"
+ * }
+ *
+ *
+ * Generated from protobuf field .google.protobuf.Value formatted_value = 3;
+ * @param \Google\Protobuf\Value $var
+ * @return $this
+ */
+ public function setFormattedValue($var)
+ {
+ GPBUtil::checkMessage($var, \Google\Protobuf\Value::class);
+ $this->formatted_value = $var;
+
+ return $this;
+ }
+
+}
+
diff --git a/vendor/google/cloud-dialogflow/src/V2/AnswerFeedback.php b/vendor/google/cloud-dialogflow/src/V2/AnswerFeedback.php
new file mode 100644
index 0000000..6063491
--- /dev/null
+++ b/vendor/google/cloud-dialogflow/src/V2/AnswerFeedback.php
@@ -0,0 +1,282 @@
+google.cloud.dialogflow.v2.AnswerFeedback
+ */
+class AnswerFeedback extends \Google\Protobuf\Internal\Message
+{
+ /**
+ * The correctness level of the specific answer.
+ *
+ * Generated from protobuf field .google.cloud.dialogflow.v2.AnswerFeedback.CorrectnessLevel correctness_level = 1;
+ */
+ protected $correctness_level = 0;
+ /**
+ * Indicates whether the answer/item was clicked by the human agent
+ * or not. Default to false.
+ * For knowledge search and knowledge assist, the answer record is considered
+ * to be clicked if the answer was copied or any URI was clicked.
+ *
+ * Generated from protobuf field bool clicked = 3;
+ */
+ protected $clicked = false;
+ /**
+ * Time when the answer/item was clicked.
+ *
+ * Generated from protobuf field .google.protobuf.Timestamp click_time = 5;
+ */
+ protected $click_time = null;
+ /**
+ * Indicates whether the answer/item was displayed to the human
+ * agent in the agent desktop UI. Default to false.
+ *
+ * Generated from protobuf field bool displayed = 4;
+ */
+ protected $displayed = false;
+ /**
+ * Time when the answer/item was displayed.
+ *
+ * Generated from protobuf field .google.protobuf.Timestamp display_time = 6;
+ */
+ protected $display_time = null;
+ protected $detail_feedback;
+
+ /**
+ * Constructor.
+ *
+ * @param array $data {
+ * Optional. Data for populating the Message object.
+ *
+ * @type int $correctness_level
+ * The correctness level of the specific answer.
+ * @type \Google\Cloud\Dialogflow\V2\AgentAssistantFeedback $agent_assistant_detail_feedback
+ * Detail feedback of agent assist suggestions.
+ * @type bool $clicked
+ * Indicates whether the answer/item was clicked by the human agent
+ * or not. Default to false.
+ * For knowledge search and knowledge assist, the answer record is considered
+ * to be clicked if the answer was copied or any URI was clicked.
+ * @type \Google\Protobuf\Timestamp $click_time
+ * Time when the answer/item was clicked.
+ * @type bool $displayed
+ * Indicates whether the answer/item was displayed to the human
+ * agent in the agent desktop UI. Default to false.
+ * @type \Google\Protobuf\Timestamp $display_time
+ * Time when the answer/item was displayed.
+ * }
+ */
+ public function __construct($data = NULL) {
+ \GPBMetadata\Google\Cloud\Dialogflow\V2\AnswerRecord::initOnce();
+ parent::__construct($data);
+ }
+
+ /**
+ * The correctness level of the specific answer.
+ *
+ * Generated from protobuf field .google.cloud.dialogflow.v2.AnswerFeedback.CorrectnessLevel correctness_level = 1;
+ * @return int
+ */
+ public function getCorrectnessLevel()
+ {
+ return $this->correctness_level;
+ }
+
+ /**
+ * The correctness level of the specific answer.
+ *
+ * Generated from protobuf field .google.cloud.dialogflow.v2.AnswerFeedback.CorrectnessLevel correctness_level = 1;
+ * @param int $var
+ * @return $this
+ */
+ public function setCorrectnessLevel($var)
+ {
+ GPBUtil::checkEnum($var, \Google\Cloud\Dialogflow\V2\AnswerFeedback\CorrectnessLevel::class);
+ $this->correctness_level = $var;
+
+ return $this;
+ }
+
+ /**
+ * Detail feedback of agent assist suggestions.
+ *
+ * Generated from protobuf field .google.cloud.dialogflow.v2.AgentAssistantFeedback agent_assistant_detail_feedback = 2;
+ * @return \Google\Cloud\Dialogflow\V2\AgentAssistantFeedback|null
+ */
+ public function getAgentAssistantDetailFeedback()
+ {
+ return $this->readOneof(2);
+ }
+
+ public function hasAgentAssistantDetailFeedback()
+ {
+ return $this->hasOneof(2);
+ }
+
+ /**
+ * Detail feedback of agent assist suggestions.
+ *
+ * Generated from protobuf field .google.cloud.dialogflow.v2.AgentAssistantFeedback agent_assistant_detail_feedback = 2;
+ * @param \Google\Cloud\Dialogflow\V2\AgentAssistantFeedback $var
+ * @return $this
+ */
+ public function setAgentAssistantDetailFeedback($var)
+ {
+ GPBUtil::checkMessage($var, \Google\Cloud\Dialogflow\V2\AgentAssistantFeedback::class);
+ $this->writeOneof(2, $var);
+
+ return $this;
+ }
+
+ /**
+ * Indicates whether the answer/item was clicked by the human agent
+ * or not. Default to false.
+ * For knowledge search and knowledge assist, the answer record is considered
+ * to be clicked if the answer was copied or any URI was clicked.
+ *
+ * Generated from protobuf field bool clicked = 3;
+ * @return bool
+ */
+ public function getClicked()
+ {
+ return $this->clicked;
+ }
+
+ /**
+ * Indicates whether the answer/item was clicked by the human agent
+ * or not. Default to false.
+ * For knowledge search and knowledge assist, the answer record is considered
+ * to be clicked if the answer was copied or any URI was clicked.
+ *
+ * Generated from protobuf field bool clicked = 3;
+ * @param bool $var
+ * @return $this
+ */
+ public function setClicked($var)
+ {
+ GPBUtil::checkBool($var);
+ $this->clicked = $var;
+
+ return $this;
+ }
+
+ /**
+ * Time when the answer/item was clicked.
+ *
+ * Generated from protobuf field .google.protobuf.Timestamp click_time = 5;
+ * @return \Google\Protobuf\Timestamp|null
+ */
+ public function getClickTime()
+ {
+ return $this->click_time;
+ }
+
+ public function hasClickTime()
+ {
+ return isset($this->click_time);
+ }
+
+ public function clearClickTime()
+ {
+ unset($this->click_time);
+ }
+
+ /**
+ * Time when the answer/item was clicked.
+ *
+ * Generated from protobuf field .google.protobuf.Timestamp click_time = 5;
+ * @param \Google\Protobuf\Timestamp $var
+ * @return $this
+ */
+ public function setClickTime($var)
+ {
+ GPBUtil::checkMessage($var, \Google\Protobuf\Timestamp::class);
+ $this->click_time = $var;
+
+ return $this;
+ }
+
+ /**
+ * Indicates whether the answer/item was displayed to the human
+ * agent in the agent desktop UI. Default to false.
+ *
+ * Generated from protobuf field bool displayed = 4;
+ * @return bool
+ */
+ public function getDisplayed()
+ {
+ return $this->displayed;
+ }
+
+ /**
+ * Indicates whether the answer/item was displayed to the human
+ * agent in the agent desktop UI. Default to false.
+ *
+ * Generated from protobuf field bool displayed = 4;
+ * @param bool $var
+ * @return $this
+ */
+ public function setDisplayed($var)
+ {
+ GPBUtil::checkBool($var);
+ $this->displayed = $var;
+
+ return $this;
+ }
+
+ /**
+ * Time when the answer/item was displayed.
+ *
+ * Generated from protobuf field .google.protobuf.Timestamp display_time = 6;
+ * @return \Google\Protobuf\Timestamp|null
+ */
+ public function getDisplayTime()
+ {
+ return $this->display_time;
+ }
+
+ public function hasDisplayTime()
+ {
+ return isset($this->display_time);
+ }
+
+ public function clearDisplayTime()
+ {
+ unset($this->display_time);
+ }
+
+ /**
+ * Time when the answer/item was displayed.
+ *
+ * Generated from protobuf field .google.protobuf.Timestamp display_time = 6;
+ * @param \Google\Protobuf\Timestamp $var
+ * @return $this
+ */
+ public function setDisplayTime($var)
+ {
+ GPBUtil::checkMessage($var, \Google\Protobuf\Timestamp::class);
+ $this->display_time = $var;
+
+ return $this;
+ }
+
+ /**
+ * @return string
+ */
+ public function getDetailFeedback()
+ {
+ return $this->whichOneof("detail_feedback");
+ }
+
+}
+
diff --git a/vendor/google/cloud-dialogflow/src/V2/AnswerFeedback/CorrectnessLevel.php b/vendor/google/cloud-dialogflow/src/V2/AnswerFeedback/CorrectnessLevel.php
new file mode 100644
index 0000000..d67105a
--- /dev/null
+++ b/vendor/google/cloud-dialogflow/src/V2/AnswerFeedback/CorrectnessLevel.php
@@ -0,0 +1,69 @@
+google.cloud.dialogflow.v2.AnswerFeedback.CorrectnessLevel
+ */
+class CorrectnessLevel
+{
+ /**
+ * Correctness level unspecified.
+ *
+ * Generated from protobuf enum CORRECTNESS_LEVEL_UNSPECIFIED = 0;
+ */
+ const CORRECTNESS_LEVEL_UNSPECIFIED = 0;
+ /**
+ * Answer is totally wrong.
+ *
+ * Generated from protobuf enum NOT_CORRECT = 1;
+ */
+ const NOT_CORRECT = 1;
+ /**
+ * Answer is partially correct.
+ *
+ * Generated from protobuf enum PARTIALLY_CORRECT = 2;
+ */
+ const PARTIALLY_CORRECT = 2;
+ /**
+ * Answer is fully correct.
+ *
+ * Generated from protobuf enum FULLY_CORRECT = 3;
+ */
+ const FULLY_CORRECT = 3;
+
+ private static $valueToName = [
+ self::CORRECTNESS_LEVEL_UNSPECIFIED => 'CORRECTNESS_LEVEL_UNSPECIFIED',
+ self::NOT_CORRECT => 'NOT_CORRECT',
+ self::PARTIALLY_CORRECT => 'PARTIALLY_CORRECT',
+ self::FULLY_CORRECT => 'FULLY_CORRECT',
+ ];
+
+ public static function name($value)
+ {
+ if (!isset(self::$valueToName[$value])) {
+ throw new UnexpectedValueException(sprintf(
+ 'Enum %s has no name defined for value %s', __CLASS__, $value));
+ }
+ return self::$valueToName[$value];
+ }
+
+
+ public static function value($name)
+ {
+ $const = __CLASS__ . '::' . strtoupper($name);
+ if (!defined($const)) {
+ throw new UnexpectedValueException(sprintf(
+ 'Enum %s has no value defined for name %s', __CLASS__, $name));
+ }
+ return constant($const);
+ }
+}
+
+
diff --git a/vendor/google/cloud-dialogflow/src/V2/AnswerRecord.php b/vendor/google/cloud-dialogflow/src/V2/AnswerRecord.php
new file mode 100644
index 0000000..d173d57
--- /dev/null
+++ b/vendor/google/cloud-dialogflow/src/V2/AnswerRecord.php
@@ -0,0 +1,190 @@
+google.cloud.dialogflow.v2.AnswerRecord
+ */
+class AnswerRecord extends \Google\Protobuf\Internal\Message
+{
+ /**
+ * The unique identifier of this answer record.
+ * Format: `projects//locations//answerRecords/`.
+ *
+ * Generated from protobuf field string name = 1;
+ */
+ protected $name = '';
+ /**
+ * Required. The AnswerFeedback for this record. You can set this with
+ * [AnswerRecords.UpdateAnswerRecord][google.cloud.dialogflow.v2.AnswerRecords.UpdateAnswerRecord]
+ * in order to give us feedback about this answer.
+ *
+ * Generated from protobuf field .google.cloud.dialogflow.v2.AnswerFeedback answer_feedback = 2 [(.google.api.field_behavior) = REQUIRED];
+ */
+ protected $answer_feedback = null;
+ protected $record;
+
+ /**
+ * Constructor.
+ *
+ * @param array $data {
+ * Optional. Data for populating the Message object.
+ *
+ * @type string $name
+ * The unique identifier of this answer record.
+ * Format: `projects//locations//answerRecords/`.
+ * @type \Google\Cloud\Dialogflow\V2\AnswerFeedback $answer_feedback
+ * Required. The AnswerFeedback for this record. You can set this with
+ * [AnswerRecords.UpdateAnswerRecord][google.cloud.dialogflow.v2.AnswerRecords.UpdateAnswerRecord]
+ * in order to give us feedback about this answer.
+ * @type \Google\Cloud\Dialogflow\V2\AgentAssistantRecord $agent_assistant_record
+ * Output only. The record for human agent assistant.
+ * }
+ */
+ public function __construct($data = NULL) {
+ \GPBMetadata\Google\Cloud\Dialogflow\V2\AnswerRecord::initOnce();
+ parent::__construct($data);
+ }
+
+ /**
+ * The unique identifier of this answer record.
+ * Format: `projects//locations//answerRecords/`.
+ *
+ * Generated from protobuf field string name = 1;
+ * @return string
+ */
+ public function getName()
+ {
+ return $this->name;
+ }
+
+ /**
+ * The unique identifier of this answer record.
+ * Format: `projects//locations//answerRecords/`.
+ *
+ * Generated from protobuf field string name = 1;
+ * @param string $var
+ * @return $this
+ */
+ public function setName($var)
+ {
+ GPBUtil::checkString($var, True);
+ $this->name = $var;
+
+ return $this;
+ }
+
+ /**
+ * Required. The AnswerFeedback for this record. You can set this with
+ * [AnswerRecords.UpdateAnswerRecord][google.cloud.dialogflow.v2.AnswerRecords.UpdateAnswerRecord]
+ * in order to give us feedback about this answer.
+ *
+ * Generated from protobuf field .google.cloud.dialogflow.v2.AnswerFeedback answer_feedback = 2 [(.google.api.field_behavior) = REQUIRED];
+ * @return \Google\Cloud\Dialogflow\V2\AnswerFeedback|null
+ */
+ public function getAnswerFeedback()
+ {
+ return $this->answer_feedback;
+ }
+
+ public function hasAnswerFeedback()
+ {
+ return isset($this->answer_feedback);
+ }
+
+ public function clearAnswerFeedback()
+ {
+ unset($this->answer_feedback);
+ }
+
+ /**
+ * Required. The AnswerFeedback for this record. You can set this with
+ * [AnswerRecords.UpdateAnswerRecord][google.cloud.dialogflow.v2.AnswerRecords.UpdateAnswerRecord]
+ * in order to give us feedback about this answer.
+ *
+ * Generated from protobuf field .google.cloud.dialogflow.v2.AnswerFeedback answer_feedback = 2 [(.google.api.field_behavior) = REQUIRED];
+ * @param \Google\Cloud\Dialogflow\V2\AnswerFeedback $var
+ * @return $this
+ */
+ public function setAnswerFeedback($var)
+ {
+ GPBUtil::checkMessage($var, \Google\Cloud\Dialogflow\V2\AnswerFeedback::class);
+ $this->answer_feedback = $var;
+
+ return $this;
+ }
+
+ /**
+ * Output only. The record for human agent assistant.
+ *
+ * Generated from protobuf field .google.cloud.dialogflow.v2.AgentAssistantRecord agent_assistant_record = 4 [(.google.api.field_behavior) = OUTPUT_ONLY];
+ * @return \Google\Cloud\Dialogflow\V2\AgentAssistantRecord|null
+ */
+ public function getAgentAssistantRecord()
+ {
+ return $this->readOneof(4);
+ }
+
+ public function hasAgentAssistantRecord()
+ {
+ return $this->hasOneof(4);
+ }
+
+ /**
+ * Output only. The record for human agent assistant.
+ *
+ * Generated from protobuf field .google.cloud.dialogflow.v2.AgentAssistantRecord agent_assistant_record = 4 [(.google.api.field_behavior) = OUTPUT_ONLY];
+ * @param \Google\Cloud\Dialogflow\V2\AgentAssistantRecord $var
+ * @return $this
+ */
+ public function setAgentAssistantRecord($var)
+ {
+ GPBUtil::checkMessage($var, \Google\Cloud\Dialogflow\V2\AgentAssistantRecord::class);
+ $this->writeOneof(4, $var);
+
+ return $this;
+ }
+
+ /**
+ * @return string
+ */
+ public function getRecord()
+ {
+ return $this->whichOneof("record");
+ }
+
+}
+
diff --git a/vendor/google/cloud-dialogflow/src/V2/ArticleAnswer.php b/vendor/google/cloud-dialogflow/src/V2/ArticleAnswer.php
new file mode 100644
index 0000000..ecbdd73
--- /dev/null
+++ b/vendor/google/cloud-dialogflow/src/V2/ArticleAnswer.php
@@ -0,0 +1,261 @@
+google.cloud.dialogflow.v2.ArticleAnswer
+ */
+class ArticleAnswer extends \Google\Protobuf\Internal\Message
+{
+ /**
+ * The article title.
+ *
+ * Generated from protobuf field string title = 1;
+ */
+ protected $title = '';
+ /**
+ * The article URI.
+ *
+ * Generated from protobuf field string uri = 2;
+ */
+ protected $uri = '';
+ /**
+ * Article snippets.
+ *
+ * Generated from protobuf field repeated string snippets = 3;
+ */
+ private $snippets;
+ /**
+ * Article match confidence.
+ * The system's confidence score that this article is a good match for this
+ * conversation, as a value from 0.0 (completely uncertain) to 1.0
+ * (completely certain).
+ *
+ * Generated from protobuf field float confidence = 4;
+ */
+ protected $confidence = 0.0;
+ /**
+ * A map that contains metadata about the answer and the
+ * document from which it originates.
+ *
+ * Generated from protobuf field map metadata = 5;
+ */
+ private $metadata;
+ /**
+ * The name of answer record, in the format of
+ * "projects//locations//answerRecords/"
+ *
+ * Generated from protobuf field string answer_record = 6;
+ */
+ protected $answer_record = '';
+
+ /**
+ * Constructor.
+ *
+ * @param array $data {
+ * Optional. Data for populating the Message object.
+ *
+ * @type string $title
+ * The article title.
+ * @type string $uri
+ * The article URI.
+ * @type array|\Google\Protobuf\Internal\RepeatedField $snippets
+ * Article snippets.
+ * @type float $confidence
+ * Article match confidence.
+ * The system's confidence score that this article is a good match for this
+ * conversation, as a value from 0.0 (completely uncertain) to 1.0
+ * (completely certain).
+ * @type array|\Google\Protobuf\Internal\MapField $metadata
+ * A map that contains metadata about the answer and the
+ * document from which it originates.
+ * @type string $answer_record
+ * The name of answer record, in the format of
+ * "projects//locations//answerRecords/"
+ * }
+ */
+ public function __construct($data = NULL) {
+ \GPBMetadata\Google\Cloud\Dialogflow\V2\Participant::initOnce();
+ parent::__construct($data);
+ }
+
+ /**
+ * The article title.
+ *
+ * Generated from protobuf field string title = 1;
+ * @return string
+ */
+ public function getTitle()
+ {
+ return $this->title;
+ }
+
+ /**
+ * The article title.
+ *
+ * Generated from protobuf field string title = 1;
+ * @param string $var
+ * @return $this
+ */
+ public function setTitle($var)
+ {
+ GPBUtil::checkString($var, True);
+ $this->title = $var;
+
+ return $this;
+ }
+
+ /**
+ * The article URI.
+ *
+ * Generated from protobuf field string uri = 2;
+ * @return string
+ */
+ public function getUri()
+ {
+ return $this->uri;
+ }
+
+ /**
+ * The article URI.
+ *
+ * Generated from protobuf field string uri = 2;
+ * @param string $var
+ * @return $this
+ */
+ public function setUri($var)
+ {
+ GPBUtil::checkString($var, True);
+ $this->uri = $var;
+
+ return $this;
+ }
+
+ /**
+ * Article snippets.
+ *
+ * Generated from protobuf field repeated string snippets = 3;
+ * @return \Google\Protobuf\Internal\RepeatedField
+ */
+ public function getSnippets()
+ {
+ return $this->snippets;
+ }
+
+ /**
+ * Article snippets.
+ *
+ * Generated from protobuf field repeated string snippets = 3;
+ * @param array|\Google\Protobuf\Internal\RepeatedField $var
+ * @return $this
+ */
+ public function setSnippets($var)
+ {
+ $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::STRING);
+ $this->snippets = $arr;
+
+ return $this;
+ }
+
+ /**
+ * Article match confidence.
+ * The system's confidence score that this article is a good match for this
+ * conversation, as a value from 0.0 (completely uncertain) to 1.0
+ * (completely certain).
+ *
+ * Generated from protobuf field float confidence = 4;
+ * @return float
+ */
+ public function getConfidence()
+ {
+ return $this->confidence;
+ }
+
+ /**
+ * Article match confidence.
+ * The system's confidence score that this article is a good match for this
+ * conversation, as a value from 0.0 (completely uncertain) to 1.0
+ * (completely certain).
+ *
+ * Generated from protobuf field float confidence = 4;
+ * @param float $var
+ * @return $this
+ */
+ public function setConfidence($var)
+ {
+ GPBUtil::checkFloat($var);
+ $this->confidence = $var;
+
+ return $this;
+ }
+
+ /**
+ * A map that contains metadata about the answer and the
+ * document from which it originates.
+ *
+ * Generated from protobuf field map metadata = 5;
+ * @return \Google\Protobuf\Internal\MapField
+ */
+ public function getMetadata()
+ {
+ return $this->metadata;
+ }
+
+ /**
+ * A map that contains metadata about the answer and the
+ * document from which it originates.
+ *
+ * Generated from protobuf field map metadata = 5;
+ * @param array|\Google\Protobuf\Internal\MapField $var
+ * @return $this
+ */
+ public function setMetadata($var)
+ {
+ $arr = GPBUtil::checkMapField($var, \Google\Protobuf\Internal\GPBType::STRING, \Google\Protobuf\Internal\GPBType::STRING);
+ $this->metadata = $arr;
+
+ return $this;
+ }
+
+ /**
+ * The name of answer record, in the format of
+ * "projects//locations//answerRecords/"
+ *
+ * Generated from protobuf field string answer_record = 6;
+ * @return string
+ */
+ public function getAnswerRecord()
+ {
+ return $this->answer_record;
+ }
+
+ /**
+ * The name of answer record, in the format of
+ * "projects//locations//answerRecords/"
+ *
+ * Generated from protobuf field string answer_record = 6;
+ * @param string $var
+ * @return $this
+ */
+ public function setAnswerRecord($var)
+ {
+ GPBUtil::checkString($var, True);
+ $this->answer_record = $var;
+
+ return $this;
+ }
+
+}
+
diff --git a/vendor/google/cloud-dialogflow/src/V2/ArticleSuggestionModelMetadata.php b/vendor/google/cloud-dialogflow/src/V2/ArticleSuggestionModelMetadata.php
new file mode 100644
index 0000000..615d7a2
--- /dev/null
+++ b/vendor/google/cloud-dialogflow/src/V2/ArticleSuggestionModelMetadata.php
@@ -0,0 +1,71 @@
+google.cloud.dialogflow.v2.ArticleSuggestionModelMetadata
+ */
+class ArticleSuggestionModelMetadata extends \Google\Protobuf\Internal\Message
+{
+ /**
+ * Optional. Type of the article suggestion model. If not provided, model_type
+ * is used.
+ *
+ * Generated from protobuf field .google.cloud.dialogflow.v2.ConversationModel.ModelType training_model_type = 3 [(.google.api.field_behavior) = OPTIONAL];
+ */
+ protected $training_model_type = 0;
+
+ /**
+ * Constructor.
+ *
+ * @param array $data {
+ * Optional. Data for populating the Message object.
+ *
+ * @type int $training_model_type
+ * Optional. Type of the article suggestion model. If not provided, model_type
+ * is used.
+ * }
+ */
+ public function __construct($data = NULL) {
+ \GPBMetadata\Google\Cloud\Dialogflow\V2\ConversationModel::initOnce();
+ parent::__construct($data);
+ }
+
+ /**
+ * Optional. Type of the article suggestion model. If not provided, model_type
+ * is used.
+ *
+ * Generated from protobuf field .google.cloud.dialogflow.v2.ConversationModel.ModelType training_model_type = 3 [(.google.api.field_behavior) = OPTIONAL];
+ * @return int
+ */
+ public function getTrainingModelType()
+ {
+ return $this->training_model_type;
+ }
+
+ /**
+ * Optional. Type of the article suggestion model. If not provided, model_type
+ * is used.
+ *
+ * Generated from protobuf field .google.cloud.dialogflow.v2.ConversationModel.ModelType training_model_type = 3 [(.google.api.field_behavior) = OPTIONAL];
+ * @param int $var
+ * @return $this
+ */
+ public function setTrainingModelType($var)
+ {
+ GPBUtil::checkEnum($var, \Google\Cloud\Dialogflow\V2\ConversationModel\ModelType::class);
+ $this->training_model_type = $var;
+
+ return $this;
+ }
+
+}
+
diff --git a/vendor/google/cloud-dialogflow/src/V2/AssistQueryParameters.php b/vendor/google/cloud-dialogflow/src/V2/AssistQueryParameters.php
new file mode 100644
index 0000000..2deb569
--- /dev/null
+++ b/vendor/google/cloud-dialogflow/src/V2/AssistQueryParameters.php
@@ -0,0 +1,131 @@
+google.cloud.dialogflow.v2.AssistQueryParameters
+ */
+class AssistQueryParameters extends \Google\Protobuf\Internal\Message
+{
+ /**
+ * Key-value filters on the metadata of documents returned by article
+ * suggestion. If specified, article suggestion only returns suggested
+ * documents that match all filters in their
+ * [Document.metadata][google.cloud.dialogflow.v2.Document.metadata]. Multiple
+ * values for a metadata key should be concatenated by comma. For example,
+ * filters to match all documents that have 'US' or 'CA' in their market
+ * metadata values and 'agent' in their user metadata values will be
+ * ```
+ * documents_metadata_filters {
+ * key: "market"
+ * value: "US,CA"
+ * }
+ * documents_metadata_filters {
+ * key: "user"
+ * value: "agent"
+ * }
+ * ```
+ *
+ * Generated from protobuf field map documents_metadata_filters = 1;
+ */
+ private $documents_metadata_filters;
+
+ /**
+ * Constructor.
+ *
+ * @param array $data {
+ * Optional. Data for populating the Message object.
+ *
+ * @type array|\Google\Protobuf\Internal\MapField $documents_metadata_filters
+ * Key-value filters on the metadata of documents returned by article
+ * suggestion. If specified, article suggestion only returns suggested
+ * documents that match all filters in their
+ * [Document.metadata][google.cloud.dialogflow.v2.Document.metadata]. Multiple
+ * values for a metadata key should be concatenated by comma. For example,
+ * filters to match all documents that have 'US' or 'CA' in their market
+ * metadata values and 'agent' in their user metadata values will be
+ * ```
+ * documents_metadata_filters {
+ * key: "market"
+ * value: "US,CA"
+ * }
+ * documents_metadata_filters {
+ * key: "user"
+ * value: "agent"
+ * }
+ * ```
+ * }
+ */
+ public function __construct($data = NULL) {
+ \GPBMetadata\Google\Cloud\Dialogflow\V2\Participant::initOnce();
+ parent::__construct($data);
+ }
+
+ /**
+ * Key-value filters on the metadata of documents returned by article
+ * suggestion. If specified, article suggestion only returns suggested
+ * documents that match all filters in their
+ * [Document.metadata][google.cloud.dialogflow.v2.Document.metadata]. Multiple
+ * values for a metadata key should be concatenated by comma. For example,
+ * filters to match all documents that have 'US' or 'CA' in their market
+ * metadata values and 'agent' in their user metadata values will be
+ * ```
+ * documents_metadata_filters {
+ * key: "market"
+ * value: "US,CA"
+ * }
+ * documents_metadata_filters {
+ * key: "user"
+ * value: "agent"
+ * }
+ * ```
+ *
+ * Generated from protobuf field map documents_metadata_filters = 1;
+ * @return \Google\Protobuf\Internal\MapField
+ */
+ public function getDocumentsMetadataFilters()
+ {
+ return $this->documents_metadata_filters;
+ }
+
+ /**
+ * Key-value filters on the metadata of documents returned by article
+ * suggestion. If specified, article suggestion only returns suggested
+ * documents that match all filters in their
+ * [Document.metadata][google.cloud.dialogflow.v2.Document.metadata]. Multiple
+ * values for a metadata key should be concatenated by comma. For example,
+ * filters to match all documents that have 'US' or 'CA' in their market
+ * metadata values and 'agent' in their user metadata values will be
+ * ```
+ * documents_metadata_filters {
+ * key: "market"
+ * value: "US,CA"
+ * }
+ * documents_metadata_filters {
+ * key: "user"
+ * value: "agent"
+ * }
+ * ```
+ *
+ * Generated from protobuf field map documents_metadata_filters = 1;
+ * @param array|\Google\Protobuf\Internal\MapField $var
+ * @return $this
+ */
+ public function setDocumentsMetadataFilters($var)
+ {
+ $arr = GPBUtil::checkMapField($var, \Google\Protobuf\Internal\GPBType::STRING, \Google\Protobuf\Internal\GPBType::STRING);
+ $this->documents_metadata_filters = $arr;
+
+ return $this;
+ }
+
+}
+
diff --git a/vendor/google/cloud-dialogflow/src/V2/AudioEncoding.php b/vendor/google/cloud-dialogflow/src/V2/AudioEncoding.php
new file mode 100644
index 0000000..e630d14
--- /dev/null
+++ b/vendor/google/cloud-dialogflow/src/V2/AudioEncoding.php
@@ -0,0 +1,125 @@
+google.cloud.dialogflow.v2.AudioEncoding
+ */
+class AudioEncoding
+{
+ /**
+ * Not specified.
+ *
+ * Generated from protobuf enum AUDIO_ENCODING_UNSPECIFIED = 0;
+ */
+ const AUDIO_ENCODING_UNSPECIFIED = 0;
+ /**
+ * Uncompressed 16-bit signed little-endian samples (Linear PCM).
+ *
+ * Generated from protobuf enum AUDIO_ENCODING_LINEAR_16 = 1;
+ */
+ const AUDIO_ENCODING_LINEAR_16 = 1;
+ /**
+ * [`FLAC`](https://xiph.org/flac/documentation.html) (Free Lossless Audio
+ * Codec) is the recommended encoding because it is lossless (therefore
+ * recognition is not compromised) and requires only about half the
+ * bandwidth of `LINEAR16`. `FLAC` stream encoding supports 16-bit and
+ * 24-bit samples, however, not all fields in `STREAMINFO` are supported.
+ *
+ * Generated from protobuf enum AUDIO_ENCODING_FLAC = 2;
+ */
+ const AUDIO_ENCODING_FLAC = 2;
+ /**
+ * 8-bit samples that compand 14-bit audio samples using G.711 PCMU/mu-law.
+ *
+ * Generated from protobuf enum AUDIO_ENCODING_MULAW = 3;
+ */
+ const AUDIO_ENCODING_MULAW = 3;
+ /**
+ * Adaptive Multi-Rate Narrowband codec. `sample_rate_hertz` must be 8000.
+ *
+ * Generated from protobuf enum AUDIO_ENCODING_AMR = 4;
+ */
+ const AUDIO_ENCODING_AMR = 4;
+ /**
+ * Adaptive Multi-Rate Wideband codec. `sample_rate_hertz` must be 16000.
+ *
+ * Generated from protobuf enum AUDIO_ENCODING_AMR_WB = 5;
+ */
+ const AUDIO_ENCODING_AMR_WB = 5;
+ /**
+ * Opus encoded audio frames in Ogg container
+ * ([OggOpus](https://wiki.xiph.org/OggOpus)).
+ * `sample_rate_hertz` must be 16000.
+ *
+ * Generated from protobuf enum AUDIO_ENCODING_OGG_OPUS = 6;
+ */
+ const AUDIO_ENCODING_OGG_OPUS = 6;
+ /**
+ * Although the use of lossy encodings is not recommended, if a very low
+ * bitrate encoding is required, `OGG_OPUS` is highly preferred over
+ * Speex encoding. The [Speex](https://speex.org/) encoding supported by
+ * Dialogflow API has a header byte in each block, as in MIME type
+ * `audio/x-speex-with-header-byte`.
+ * It is a variant of the RTP Speex encoding defined in
+ * [RFC 5574](https://tools.ietf.org/html/rfc5574).
+ * The stream is a sequence of blocks, one block per RTP packet. Each block
+ * starts with a byte containing the length of the block, in bytes, followed
+ * by one or more frames of Speex data, padded to an integral number of
+ * bytes (octets) as specified in RFC 5574. In other words, each RTP header
+ * is replaced with a single byte containing the block length. Only Speex
+ * wideband is supported. `sample_rate_hertz` must be 16000.
+ *
+ * Generated from protobuf enum AUDIO_ENCODING_SPEEX_WITH_HEADER_BYTE = 7;
+ */
+ const AUDIO_ENCODING_SPEEX_WITH_HEADER_BYTE = 7;
+ /**
+ * 8-bit samples that compand 13-bit audio samples using G.711 PCMU/a-law.
+ *
+ * Generated from protobuf enum AUDIO_ENCODING_ALAW = 8;
+ */
+ const AUDIO_ENCODING_ALAW = 8;
+
+ private static $valueToName = [
+ self::AUDIO_ENCODING_UNSPECIFIED => 'AUDIO_ENCODING_UNSPECIFIED',
+ self::AUDIO_ENCODING_LINEAR_16 => 'AUDIO_ENCODING_LINEAR_16',
+ self::AUDIO_ENCODING_FLAC => 'AUDIO_ENCODING_FLAC',
+ self::AUDIO_ENCODING_MULAW => 'AUDIO_ENCODING_MULAW',
+ self::AUDIO_ENCODING_AMR => 'AUDIO_ENCODING_AMR',
+ self::AUDIO_ENCODING_AMR_WB => 'AUDIO_ENCODING_AMR_WB',
+ self::AUDIO_ENCODING_OGG_OPUS => 'AUDIO_ENCODING_OGG_OPUS',
+ self::AUDIO_ENCODING_SPEEX_WITH_HEADER_BYTE => 'AUDIO_ENCODING_SPEEX_WITH_HEADER_BYTE',
+ self::AUDIO_ENCODING_ALAW => 'AUDIO_ENCODING_ALAW',
+ ];
+
+ public static function name($value)
+ {
+ if (!isset(self::$valueToName[$value])) {
+ throw new UnexpectedValueException(sprintf(
+ 'Enum %s has no name defined for value %s', __CLASS__, $value));
+ }
+ return self::$valueToName[$value];
+ }
+
+
+ public static function value($name)
+ {
+ $const = __CLASS__ . '::' . strtoupper($name);
+ if (!defined($const)) {
+ throw new UnexpectedValueException(sprintf(
+ 'Enum %s has no value defined for name %s', __CLASS__, $name));
+ }
+ return constant($const);
+ }
+}
+
diff --git a/vendor/google/cloud-dialogflow/src/V2/AudioInput.php b/vendor/google/cloud-dialogflow/src/V2/AudioInput.php
new file mode 100644
index 0000000..f4591eb
--- /dev/null
+++ b/vendor/google/cloud-dialogflow/src/V2/AudioInput.php
@@ -0,0 +1,123 @@
+google.cloud.dialogflow.v2.AudioInput
+ */
+class AudioInput extends \Google\Protobuf\Internal\Message
+{
+ /**
+ * Required. Instructs the speech recognizer how to process the speech audio.
+ *
+ * Generated from protobuf field .google.cloud.dialogflow.v2.InputAudioConfig config = 1 [(.google.api.field_behavior) = REQUIRED];
+ */
+ protected $config = null;
+ /**
+ * Required. The natural language speech audio to be processed.
+ * A single request can contain up to 2 minutes of speech audio data.
+ * The transcribed text cannot contain more than 256 bytes for virtual agent
+ * interactions.
+ *
+ * Generated from protobuf field bytes audio = 2 [(.google.api.field_behavior) = REQUIRED];
+ */
+ protected $audio = '';
+
+ /**
+ * Constructor.
+ *
+ * @param array $data {
+ * Optional. Data for populating the Message object.
+ *
+ * @type \Google\Cloud\Dialogflow\V2\InputAudioConfig $config
+ * Required. Instructs the speech recognizer how to process the speech audio.
+ * @type string $audio
+ * Required. The natural language speech audio to be processed.
+ * A single request can contain up to 2 minutes of speech audio data.
+ * The transcribed text cannot contain more than 256 bytes for virtual agent
+ * interactions.
+ * }
+ */
+ public function __construct($data = NULL) {
+ \GPBMetadata\Google\Cloud\Dialogflow\V2\Participant::initOnce();
+ parent::__construct($data);
+ }
+
+ /**
+ * Required. Instructs the speech recognizer how to process the speech audio.
+ *
+ * Generated from protobuf field .google.cloud.dialogflow.v2.InputAudioConfig config = 1 [(.google.api.field_behavior) = REQUIRED];
+ * @return \Google\Cloud\Dialogflow\V2\InputAudioConfig|null
+ */
+ public function getConfig()
+ {
+ return $this->config;
+ }
+
+ public function hasConfig()
+ {
+ return isset($this->config);
+ }
+
+ public function clearConfig()
+ {
+ unset($this->config);
+ }
+
+ /**
+ * Required. Instructs the speech recognizer how to process the speech audio.
+ *
+ * Generated from protobuf field .google.cloud.dialogflow.v2.InputAudioConfig config = 1 [(.google.api.field_behavior) = REQUIRED];
+ * @param \Google\Cloud\Dialogflow\V2\InputAudioConfig $var
+ * @return $this
+ */
+ public function setConfig($var)
+ {
+ GPBUtil::checkMessage($var, \Google\Cloud\Dialogflow\V2\InputAudioConfig::class);
+ $this->config = $var;
+
+ return $this;
+ }
+
+ /**
+ * Required. The natural language speech audio to be processed.
+ * A single request can contain up to 2 minutes of speech audio data.
+ * The transcribed text cannot contain more than 256 bytes for virtual agent
+ * interactions.
+ *
+ * Generated from protobuf field bytes audio = 2 [(.google.api.field_behavior) = REQUIRED];
+ * @return string
+ */
+ public function getAudio()
+ {
+ return $this->audio;
+ }
+
+ /**
+ * Required. The natural language speech audio to be processed.
+ * A single request can contain up to 2 minutes of speech audio data.
+ * The transcribed text cannot contain more than 256 bytes for virtual agent
+ * interactions.
+ *
+ * Generated from protobuf field bytes audio = 2 [(.google.api.field_behavior) = REQUIRED];
+ * @param string $var
+ * @return $this
+ */
+ public function setAudio($var)
+ {
+ GPBUtil::checkString($var, False);
+ $this->audio = $var;
+
+ return $this;
+ }
+
+}
+
diff --git a/vendor/google/cloud-dialogflow/src/V2/AutomatedAgentConfig.php b/vendor/google/cloud-dialogflow/src/V2/AutomatedAgentConfig.php
new file mode 100644
index 0000000..9c86f69
--- /dev/null
+++ b/vendor/google/cloud-dialogflow/src/V2/AutomatedAgentConfig.php
@@ -0,0 +1,175 @@
+google.cloud.dialogflow.v2.AutomatedAgentConfig
+ */
+class AutomatedAgentConfig extends \Google\Protobuf\Internal\Message
+{
+ /**
+ * Required. ID of the Dialogflow agent environment to use.
+ * This project needs to either be the same project as the conversation or you
+ * need to grant `service-@gcp-sa-dialogflow.iam.gserviceaccount.com` the `Dialogflow API
+ * Service Agent` role in this project.
+ * - For ES agents, use format: `projects//locations//agent/environments/`. If environment is not
+ * specified, the default `draft` environment is used. Refer to
+ * [DetectIntentRequest](/dialogflow/docs/reference/rpc/google.cloud.dialogflow.v2#google.cloud.dialogflow.v2.DetectIntentRequest)
+ * for more details.
+ * - For CX agents, use format `projects//locations//agents//environments/`. If environment is not specified, the default `draft` environment
+ * is used.
+ *
+ * Generated from protobuf field string agent = 1 [(.google.api.field_behavior) = REQUIRED, (.google.api.resource_reference) = {
+ */
+ protected $agent = '';
+ /**
+ * Optional. Configure lifetime of the Dialogflow session.
+ * By default, a Dialogflow CX session remains active and its data is stored
+ * for 30 minutes after the last request is sent for the session.
+ * This value should be no longer than 1 day.
+ *
+ * Generated from protobuf field .google.protobuf.Duration session_ttl = 3 [(.google.api.field_behavior) = OPTIONAL];
+ */
+ protected $session_ttl = null;
+
+ /**
+ * Constructor.
+ *
+ * @param array $data {
+ * Optional. Data for populating the Message object.
+ *
+ * @type string $agent
+ * Required. ID of the Dialogflow agent environment to use.
+ * This project needs to either be the same project as the conversation or you
+ * need to grant `service-@gcp-sa-dialogflow.iam.gserviceaccount.com` the `Dialogflow API
+ * Service Agent` role in this project.
+ * - For ES agents, use format: `projects//locations//agent/environments/