diff --git a/composer.json b/composer.json
index 536eac42eeeea918a2cf2976959894478fc58503..c702535fef03c549f0733789b0b7661a9586a74c 100755
--- a/composer.json
+++ b/composer.json
@@ -16,10 +16,13 @@
     	}
     },
     "require": {
-        "slim/slim": "^3.10",
+        "slim/slim": "^3.12",
         "respect/validation": "^1.1",
-        "setasign/fpdi-tcpdf": "^2.0.0",
-        "phpmailer/phpmailer": "^6.0",
-        "firebase/php-jwt": "^5.0"
+        "setasign/fpdi-tcpdf": "^2.3.0",
+        "phpmailer/phpmailer": "^6.1",
+        "firebase/php-jwt": "^5.2"
+    },
+    "require-dev": {
+        "phpunit/phpunit": "^9"
     }
 }
diff --git a/test/unitTests/app/user/UserControllerTest.php b/test/unitTests/app/user/UserControllerTest.php
index 6b0ff348619a55f1cd633ec666e0d49660de8cfc..df54e621e8656b5780a4b9e44b9c7199a8ffa259 100755
--- a/test/unitTests/app/user/UserControllerTest.php
+++ b/test/unitTests/app/user/UserControllerTest.php
@@ -77,7 +77,7 @@ class UserControllerTest extends TestCase
         ];
 
         $fullRequest = \httpRequestCustom::addContentInBody($aArgs, $request);
-        $response     = $userController->updatePassword($fullRequest, new \Slim\Http\Response(), ['id' => self::$userId]);
+        $response     = $userController->updatePassword($fullRequest, new \Slim\Http\Response(), ['id' => $GLOBALS['id']]);
         $responseBody = json_decode((string)$response->getBody());
         
         $this->assertEmpty($responseBody);
@@ -90,7 +90,7 @@ class UserControllerTest extends TestCase
         ];
 
         $fullRequest = \httpRequestCustom::addContentInBody($aArgs, $request);
-        $response     = $userController->updatePassword($fullRequest, new \Slim\Http\Response(), ['id' => self::$userId]);
+        $response     = $userController->updatePassword($fullRequest, new \Slim\Http\Response(), ['id' => $GLOBALS['id']]);
         $responseBody = json_decode((string)$response->getBody());
         
         $this->assertSame('Wrong Password', $responseBody->errors);
@@ -103,7 +103,7 @@ class UserControllerTest extends TestCase
         ];
 
         $fullRequest = \httpRequestCustom::addContentInBody($aArgs, $request);
-        $response     = $userController->updatePassword($fullRequest, new \Slim\Http\Response(), ['id' => self::$userId]);
+        $response     = $userController->updatePassword($fullRequest, new \Slim\Http\Response(), ['id' => $GLOBALS['id']]);
         $responseBody = json_decode((string)$response->getBody());
         
         $this->assertSame('Password does not match security criteria', $responseBody->errors);
@@ -116,10 +116,22 @@ class UserControllerTest extends TestCase
         ];
 
         $fullRequest = \httpRequestCustom::addContentInBody($aArgs, $request);
-        $response     = $userController->updatePassword($fullRequest, new \Slim\Http\Response(), ['id' => self::$userId]);
+        $response     = $userController->updatePassword($fullRequest, new \Slim\Http\Response(), ['id' => $GLOBALS['id']]);
         $responseBody = json_decode((string)$response->getBody());
         
         $this->assertSame('Body newPassword and passwordConfirmation must be identical', $responseBody->errors);
+
+        $aArgs = [
+            'currentPassword'          => 'maarch2',
+            'newPassword'              => 'maarch',
+            'passwordConfirmation'     => 'maarch'
+        ];
+
+        $fullRequest = \httpRequestCustom::addContentInBody($aArgs, $request);
+        $response     = $userController->updatePassword($fullRequest, new \Slim\Http\Response(), ['id' => $GLOBALS['id']]);
+        $responseBody = json_decode((string)$response->getBody());
+        
+        $this->assertEmpty($responseBody);
     }
 
     public function testGet()
diff --git a/vendor/bin/php-parse b/vendor/bin/php-parse
new file mode 120000
index 0000000000000000000000000000000000000000..062d66a3ed39a3a63233fabdbdd918d3c625f613
--- /dev/null
+++ b/vendor/bin/php-parse
@@ -0,0 +1 @@
+../nikic/php-parser/bin/php-parse
\ No newline at end of file
diff --git a/vendor/bin/phpunit b/vendor/bin/phpunit
new file mode 120000
index 0000000000000000000000000000000000000000..2c48930310589e25e38ac71f5439db0eb1887daf
--- /dev/null
+++ b/vendor/bin/phpunit
@@ -0,0 +1 @@
+../phpunit/phpunit/phpunit
\ No newline at end of file
diff --git a/vendor/christian-riesen/otp/.gitignore b/vendor/christian-riesen/otp/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..0f64e29a7839b367c983a2879171c0b3adfb18f2
--- /dev/null
+++ b/vendor/christian-riesen/otp/.gitignore
@@ -0,0 +1,7 @@
+.svn
+/.buildpath
+/.project
+/.settings
+/composer.lock
+/vendor/
+/.idea
\ No newline at end of file
diff --git a/vendor/christian-riesen/otp/.travis.yml b/vendor/christian-riesen/otp/.travis.yml
new file mode 100644
index 0000000000000000000000000000000000000000..4be393d1340cad3547a23b538207a3bb17c3268e
--- /dev/null
+++ b/vendor/christian-riesen/otp/.travis.yml
@@ -0,0 +1,27 @@
+language: php
+
+sudo: false
+
+php:
+    - 5.4
+    - 5.5
+    - 5.6
+    - 7.0
+    - 7.1
+    - 7.2
+    - hhvm
+    - nightly
+
+matrix:
+    allow_failures:
+        - nightly
+
+before_script:
+    - composer install
+
+before_script:
+    - composer install --no-interaction
+    - mkdir -p build/logs
+
+script:
+    - vendor/bin/phpunit --coverage-text
diff --git a/vendor/christian-riesen/otp/LICENSE b/vendor/christian-riesen/otp/LICENSE
new file mode 100644
index 0000000000000000000000000000000000000000..70894746461d0a425fb81bfcb202466297169f2f
--- /dev/null
+++ b/vendor/christian-riesen/otp/LICENSE
@@ -0,0 +1,20 @@
+Copyright (c) Christian Riesen http://christianriesen.com
+
+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/christian-riesen/otp/README.md b/vendor/christian-riesen/otp/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..516b10475fec3b17bb5a6e8b129be71222c9eaf7
--- /dev/null
+++ b/vendor/christian-riesen/otp/README.md
@@ -0,0 +1,101 @@
+One Time Passwords
+==================
+
+[![Build Status](https://secure.travis-ci.org/ChristianRiesen/otp.png)](http://travis-ci.org/ChristianRiesen/otp)
+
+Did you like this? Flattr it:
+
+[![Flattr otp](http://api.flattr.com/button/flattr-badge-large.png)](https://flattr.com/thing/719284/ChristianRiesenotp-on-GitHub)
+
+Installation
+------------
+
+Use [composer](http://getcomposer.org/) and require the library in your `composer.json`
+
+    {
+        "require": {
+            "christian-riesen/otp": "^2.0",
+        }
+    }
+
+Usage
+-----
+
+```php
+<?php
+
+use Otp\Otp;
+use Otp\GoogleAuthenticator;
+use ParagonIE\ConstantTime\Encoding;
+
+// Get a Pseudo Secret
+// Defaults to 16 characters
+$secret = GoogleAuthenticator::generateRandom();
+
+// Url for the QR code
+// Using totp method
+$url = GoogleAuthenticator::getQrCodeUrl('totp', 'Label like user@host.com', $secret);
+
+// Save the secret with the users account
+// Display QR Code to the user
+
+// Now how to check
+$otp = new Otp();
+
+// $key is a 6 digit number, coming from the User
+// Assuming this is present and sanitized
+// Allows for a 1 code time drift by default
+// Third parameter can alter that behavior
+if ($otp->checkTotp(Encoding::base32DecodeUpper($secret), $key)) {
+    // Correct key
+    // IMPORTANT! Note this key as being used
+    // so nobody could launch a replay attack.
+    // Cache that for the next minutes and you
+    // should be good.
+} else {
+    // Wrong key
+}
+
+// Just to create a key for display (testing)
+$key = $otp->totp(Encoding::base32DecodeUpper($secret));
+
+```
+
+Sample script in `example` folder. Requires sessions to work (for secret storage).
+
+Class Otp
+---------
+
+Implements hotp according to [RFC4226](https://tools.ietf.org/html/rfc4226) and totp according to [RFC6238](https://tools.ietf.org/html/rfc6238) (only sha1, sha256 and sha512 algorithms). Once you have a secret, you can use it directly in this class to create the passwords themselves (mainly for debugging use) or use the check functions to safely check the validity of the keys. The `checkTotp` function also includes a helper to battle timedrift.
+
+Class GoogleAuthenticator
+-------------------------
+
+Static function class to generate a correct url for the QR code, so you can easy scan it with your device. Google Authenticator is avaiaible as application for iPhone and Android. This removes the burden to create such an app from the developers of websites by using this set of classes.
+
+There are also older open source versions of the Google Authenticator app for both [iPhone](https://github.com/google/google-authenticator) and [Android](https://github.com/google/google-authenticator-android).
+
+About
+=====
+
+Requirements
+------------
+
+PHP >= 5.4.0
+
+Uses [paragonie/random_compat](https://github.com/paragonie/random_compat) and [paragonie/constant_time_encoding](https://github.com/paragonie/constant_time_encoding).
+
+If you want to run the tests, PHPUnit >= 4.8.35 is required.
+
+Author
+------
+
+Christian Riesen <chris.riesen@gmail.com> http://christianriesen.com
+
+Acknowledgements
+----------------
+
+The classes have been inspired by many different places that were talking about otp and Google Authenticator. Thank you all for your help.
+
+Project setup ideas blantently taken from https://github.com/Seldaek/monolog
+
diff --git a/vendor/christian-riesen/otp/composer.json b/vendor/christian-riesen/otp/composer.json
new file mode 100644
index 0000000000000000000000000000000000000000..1512a4f2a3dd9d21e41ed0fd9627badc88c8faf9
--- /dev/null
+++ b/vendor/christian-riesen/otp/composer.json
@@ -0,0 +1,40 @@
+{
+    "name": "christian-riesen/otp",
+    "type": "library",
+    "description": "One Time Passwords, hotp and totp according to RFC4226 and RFC6238",
+    "keywords": ["otp","hotp","totp","googleauthenticator","rfc4226","rfc6238"],
+    "homepage": "https://github.com/ChristianRiesen/otp",
+    "license": "MIT",
+    "authors": [
+        {
+            "name": "Christian Riesen",
+            "email": "chris.riesen@gmail.com",
+            "homepage": "http://christianriesen.com",
+            "role": "Developer"
+        }
+    ],
+    "require": {
+        "php": ">=5.4.0",
+        "paragonie/constant_time_encoding": "^1|^2",
+        "paragonie/random_compat": ">=1",
+        "symfony/polyfill-php56": "^1"
+    },
+    "require-dev": {
+        "phpunit/phpunit": "^4.8.35 || ^5.7.11 || ^6.0.5"
+    },
+    "autoload": {
+        "psr-4": {
+            "Otp\\": "src/"
+        }
+    },
+    "autoload-dev": {
+        "psr-4": {
+            "Otp\\Tests\\": "tests/"
+        }
+    },
+    "extra": {
+        "branch-alias": {
+            "dev-master": "2.x-dev"
+        }
+    }
+}
diff --git a/vendor/christian-riesen/otp/example/index.php b/vendor/christian-riesen/otp/example/index.php
new file mode 100644
index 0000000000000000000000000000000000000000..e5e9b7f2796381e97c01aecd04556b6fc5f075a5
--- /dev/null
+++ b/vendor/christian-riesen/otp/example/index.php
@@ -0,0 +1,100 @@
+<?php
+
+session_start(); // using it as storage temporary
+
+require_once __DIR__ . '/../vendor/autoload.php';
+
+use Otp\Otp;
+use Otp\GoogleAuthenticator;
+use ParagonIE\ConstantTime\Encoding;
+
+// Getting a secret, either by generating or from storage
+// DON'T use sessions as storage for this in production!!!
+$secret = 0;
+
+if (isset($_SESSION['otpsecret'])) {
+	$secret = $_SESSION['otpsecret'];
+}
+
+if (strlen($secret) != 16) {
+	$secret = GoogleAuthenticator::generateRandom();
+	$_SESSION['otpsecret'] = $secret;
+}
+
+// The secret is now an easy stored Base32 string.
+// To use it in totp though we need to decode it into the original
+$otp = new Otp();
+
+$currentTotp = $otp->totp(Encoding::base32DecodeUpper($secret));
+
+$qrCode = GoogleAuthenticator::getQrCodeUrl('totp', 'otpsample@cr', $secret);
+$keyUri = GoogleAuthenticator::getKeyUri('totp', 'otpsample@cr', $secret);
+
+?><html>
+<head>
+<title>One Time Passwords Example</title>
+</head>
+<body>
+
+<h1>One Time Passwords Example</h1>
+
+Secret is <?php echo $secret; ?>. This is saved with the users credentials.
+<br />
+<br />
+<hr />
+
+QR Code for totp:<br />
+<img src="<?php echo $qrCode; ?>" />
+<br />
+This QR Code contains the Key URI: <?php echo $keyUri; ?>
+<br />
+<hr />
+
+Current totp would be <?php echo $currentTotp; ?><br />
+<br />
+<hr />
+
+Because of timedrift, you could technically enter a code before or after it
+would actually be used. This form uses the checkTotp function. To test this,
+open this page, wait until the key changes once or twice (not more) on your
+Google Authenticator, then hit submit. Even though the key is "wrong" because of
+small time differences, you can still use it.
+<form action="" method="post">
+<input type="text" name="otpkey" value="<?php echo $currentTotp; ?>" /><br />
+<input type="submit">
+</form>
+
+<br />
+Output:<br />
+<br />
+
+
+<?php
+
+if (isset($_POST['otpkey'])) {
+	// Sanatizing, this should take care of it
+	$key = preg_replace('/[^0-9]/', '', $_POST['otpkey']);
+	
+	// Standard is 6 for keys, but can be changed with setDigits on $otp
+	if (strlen($key) == 6) {
+		// Remember that the secret is a base32 string that needs decoding
+		// to use it here!
+		if ($otp->checkTotp(Encoding::base32DecodeUpper($secret), $key)) {
+			echo 'Key correct!';
+			// Add here something that makes note of this key and will not allow
+			// the use of it, for this user for the next 2 minutes. This way you
+			// prevent a replay attack. Otherwise your OTP is missing one of the
+			// key features it can bring in security to your application!
+		} else {
+			echo 'Wrong key!';
+		}
+		
+	} else {
+		echo 'Key not the correct size';
+	}
+}
+
+?>
+
+</body>
+</html>
diff --git a/vendor/christian-riesen/otp/phpunit.xml.dist b/vendor/christian-riesen/otp/phpunit.xml.dist
new file mode 100644
index 0000000000000000000000000000000000000000..3d6cd8cedfd690a295cf07374ccf10b7ca702843
--- /dev/null
+++ b/vendor/christian-riesen/otp/phpunit.xml.dist
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<phpunit
+        backupGlobals="false"
+        backupStaticAttributes="false"
+        convertErrorsToExceptions="true"
+        convertNoticesToExceptions="true"
+        convertWarningsToExceptions="true"
+        processIsolation="false"
+        stopOnFailure="false"
+        syntaxCheck="false"
+        bootstrap="tests/bootstrap.php"
+        colors="true">
+    <testsuites>
+        <testsuite name="Otp Test Suite">
+            <directory suffix="Test.php">tests/</directory>
+        </testsuite>
+    </testsuites>
+
+    <filter>
+        <whitelist>
+            <directory suffix=".php">src/</directory>
+        </whitelist>
+    </filter>
+
+    <logging>
+        <log type="coverage-html" target="build/coverage" title="Otp"
+             charset="UTF-8" yui="true" highlight="true"
+             lowUpperBound="35" highLowerBound="70"/>
+        <log type="coverage-clover" target="build/logs/clover.xml"/>
+        <log type="junit" target="build/logs/junit.xml" logIncompleteSkipped="false"/>
+    </logging>
+</phpunit>
+
diff --git a/vendor/christian-riesen/otp/src/GoogleAuthenticator.php b/vendor/christian-riesen/otp/src/GoogleAuthenticator.php
new file mode 100644
index 0000000000000000000000000000000000000000..4a4b9e1cbd3ced9070ee82aae193575a55529137
--- /dev/null
+++ b/vendor/christian-riesen/otp/src/GoogleAuthenticator.php
@@ -0,0 +1,203 @@
+<?php
+
+namespace Otp;
+
+use ParagonIE\ConstantTime\Encoding;
+
+/**
+ * Google Authenticator
+ *
+ * Can be easy used with Google Authenticator
+ * @link https://code.google.com/p/google-authenticator/
+ *
+ * @author Christian Riesen <chris.riesen@gmail.com>
+ * @link http://christianriesen.com
+ * @license MIT License see LICENSE file
+ */
+
+class GoogleAuthenticator
+{
+    protected static $allowedTypes = array('hotp', 'totp');
+
+    protected static $height = 200;
+    protected static $width = 200;
+
+    /**
+     * Returns the Key URI
+     *
+     * Format of encoded url is here:
+     * https://code.google.com/p/google-authenticator/wiki/KeyUriFormat
+     * Should be done in a better fashion
+     *
+     * @param string $type totp or hotp
+     * @param string $label Label to display this as to the user
+     * @param string $secret Base32 encoded secret
+     * @param integer $counter Required by hotp, otherwise ignored
+     * @param array $options Optional fields that will be set if present
+     *
+     * @return string Key URI
+     */
+    public static function getKeyUri($type, $label, $secret, $counter = null, $options = array())
+    {
+        // two types only..
+        if (!in_array($type, self::$allowedTypes)) {
+            throw new \InvalidArgumentException('Type has to be of allowed types list');
+        }
+
+        // Label can't be empty
+        $label = trim($label);
+
+        if (strlen($label) < 1) {
+            throw new \InvalidArgumentException('Label has to be one or more printable characters');
+        }
+
+        if (substr_count($label, ':') > 2) {
+        	throw new \InvalidArgumentException('Account name contains illegal colon characters');
+        }
+
+        // Secret needs to be here
+        if (strlen($secret) < 1) {
+            throw new \InvalidArgumentException('No secret present');
+        }
+
+        // check for counter on hotp
+        if ($type == 'hotp' && is_null($counter)) {
+            throw new \InvalidArgumentException('Counter required for hotp');
+        }
+
+        // This is the base, these are at least required
+        $otpauth = 'otpauth://' . $type . '/' . rawurlencode($label) . '?secret=' . rawurlencode($secret);
+
+        if ($type == 'hotp' && !is_null($counter)) {
+            $otpauth .= '&counter=' . intval($counter);
+        }
+
+        // Now check the options array
+
+        // algorithm (currently ignored by Authenticator)
+        // Defaults to SHA1
+        if (array_key_exists('algorithm', $options)) {
+            $otpauth .= '&algorithm=' . rawurlencode($options['algorithm']);
+        }
+
+        // digits (currently ignored by Authenticator)
+        // Defaults to 6
+        if (array_key_exists('digits', $options) && intval($options['digits']) !== 6 && intval($options['digits']) !== 8) {
+        	throw new \InvalidArgumentException('Digits can only have the values 6 or 8, ' . $options['digits'] . ' given');
+        } elseif (array_key_exists('digits', $options)) {
+            $otpauth .= '&digits=' . intval($options['digits']);
+        }
+
+        // period, only for totp (currently ignored by Authenticator)
+        // Defaults to 30
+        if ($type == 'totp' && array_key_exists('period', $options)) {
+            $otpauth .= '&period=' . rawurlencode($options['period']);
+        }
+
+        // issuer
+        // Defaults to none
+        if (array_key_exists('issuer', $options)) {
+            $otpauth .= '&issuer=' . rawurlencode($options['issuer']);
+        }
+
+        // image (to accepts images for freeotp)
+        if (array_key_exists('image', $options)) {
+            $otpauth .= '&image=' . $options['image'];
+        }
+
+        return $otpauth;
+    }
+
+    /**
+     * Returns the QR code url
+     *
+     * Format of encoded url is here:
+     * https://code.google.com/p/google-authenticator/wiki/KeyUriFormat
+     * Should be done in a better fashion
+     *
+     * @param string $type totp or hotp
+     * @param string $label Label to display this as to the user
+     * @param string $secret Base32 encoded secret
+     * @param integer $counter Required by hotp, otherwise ignored
+     * @param array $options Optional fields that will be set if present
+     *
+     * @return string URL to the QR code
+     */
+    public static function getQrCodeUrl($type, $label, $secret, $counter = null, $options = array())
+    {
+        // Width and height can be overwritten
+        $width = self::$width;
+
+        if (array_key_exists('width', $options) && is_numeric($options['width'])) {
+            $width = $options['width'];
+        }
+
+        $height = self::$height;
+
+        if (array_key_exists('height', $options) && is_numeric($options['height'])) {
+            $height = $options['height'];
+        }
+
+        $otpauth = self::getKeyUri($type, $label, $secret, $counter, $options);
+
+        $url = 'https://chart.googleapis.com/chart?chs=' . $width . 'x'
+             . $height . '&cht=qr&chld=M|0&chl=' . urlencode($otpauth);
+
+        return $url;
+    }
+
+    /**
+     * Creates a pseudo random Base32 string
+     *
+     * This could decode into anything. It's located here as a small helper
+     * where code that might need base32 usually also needs something like this.
+     *
+     * @param integer $length Exact length of output string
+     *
+     * @return string Base32 encoded random
+     */
+    public static function generateRandom($length = 16)
+    {
+        $keys = array_merge(range('A','Z'), range(2,7)); // No padding char
+
+        $string = '';
+
+        for ($i = 0; $i < $length; $i++) {
+            $string .= $keys[random_int(0, 31)];
+        }
+
+        return $string;
+    }
+
+    /**
+     * Create recovery codes
+     *
+     * A pure helper function to make your life easier. Generates a list of codes, guaranteed to be unique in the set
+     *
+     * @param integer $count How many codes to return
+     * @param integer $length How long each code should be
+     *
+     * @return array Array of codes
+     */
+    public static function generateRecoveryCodes($count = 1, $length = 9)
+    {
+        $count = intval($count);
+        $length = intval($length);
+        $codes = [];
+
+        do {
+            // Generate codes
+            $code = '';
+            for ($i = 1; $i <= $length; $i++) {
+                $code .= random_int(0, 9);
+            }
+
+            // To make sure no duplicates get in
+            if (!in_array($code, $codes)) {
+                $codes[] = $code;
+            }
+        } while (count($codes) < $count);
+
+        return $codes;
+    }
+}
diff --git a/vendor/christian-riesen/otp/src/Otp.php b/vendor/christian-riesen/otp/src/Otp.php
new file mode 100644
index 0000000000000000000000000000000000000000..638cd4d69992e4d44fe1468c82ee5c5243470362
--- /dev/null
+++ b/vendor/christian-riesen/otp/src/Otp.php
@@ -0,0 +1,334 @@
+<?php
+
+namespace Otp;
+
+/**
+ * One Time Passwords
+ *
+ * Implements HOTP and TOTP
+ *
+ * HMAC-Based One-time Password(HOTP) algorithm specified in RFC 4226
+ * @link https://tools.ietf.org/html/rfc4226
+ *
+ * Time-based One-time Password (TOTP) algorithm specified in RFC 6238
+ * @link https://tools.ietf.org/html/rfc6238
+ *
+ * As a note: This code is only 2038 proof on 64 bit PHP installations with 
+ * PHP >= 5.6.3!
+ *
+ * Can be easy used with Google Authenticator
+ * @link https://code.google.com/p/google-authenticator/
+ *
+ * @author Christian Riesen <chris.riesen@gmail.com>
+ * @link http://christianriesen.com
+ * @license MIT License see LICENSE file
+ */
+
+class Otp implements OtpInterface
+{
+    /**
+     * The digits the code can have
+     *
+     * Either 6 or 8.
+     * Authenticator does only support 6.
+     *
+     * @var integer
+     */
+    protected $digits = 6;
+    
+    /**
+     * Time in seconds one counter period is long
+     *
+     * @var integer
+     */
+    protected $period = 30;
+    
+    /**
+     * Possible algorithms
+     *
+     * @var array
+     */
+    protected $allowedAlgorithms = array('sha1', 'sha256', 'sha512');
+    
+    /**
+     * Currently used algorithm
+     *
+     * @var string
+     */
+    protected $algorithm = 'sha1';
+
+    /**
+     * Time offset between system time and GMT in seconds
+     *
+     * @var integer
+     */
+    protected $totpOffset = 0;
+    
+    /* (non-PHPdoc)
+     * @see Otp.OtpInterface::hotp()
+    */
+    public function hotp($secret, $counter)
+    {
+        if (!is_numeric($counter) || $counter < 0) {
+            throw new \InvalidArgumentException('Invalid counter supplied');
+        }
+        
+        $hash = hash_hmac(
+                $this->algorithm,
+                $this->getBinaryCounter($counter),
+                $secret,
+                true
+        );
+    
+        return str_pad($this->truncate($hash), $this->digits, '0', STR_PAD_LEFT);
+    }
+    
+    /* (non-PHPdoc)
+     * @see Otp.OtpInterface::totp()
+    */
+    public function totp($secret, $timecounter = null)
+    {
+        if (is_null($timecounter)) {
+            $timecounter = $this->getTimecounter();
+        }
+    
+        return $this->hotp($secret, $timecounter);
+    }
+    
+    /* (non-PHPdoc)
+     * @see Otp.OtpInterface::checkHotp()
+    */
+    public function checkHotp($secret, $counter, $key)
+    {
+        return hash_equals($this->hotp($secret, $counter), $key);
+    }
+
+
+    /* (non-PHPdoc)
+     * @see Otp.OtpInterface::checkHotpResync()
+    */
+    public function checkHotpResync($secret, $counter, $key, $counterwindow = 2)
+    {
+        if (!is_numeric($counter) || $counter < 0) {
+            throw new \InvalidArgumentException('Invalid counter supplied');
+        }
+
+        if(!is_numeric($counterwindow) || $counterwindow < 0){
+            throw new \InvalidArgumentException('Invalid counterwindow supplied');
+        }
+
+        for($c = 0; $c <= $counterwindow; $c = $c + 1) {
+            if(hash_equals($this->hotp($secret, $counter + $c), $key)){
+                return $counter + $c;
+            }
+        }
+        return false;
+    }
+    
+    /* (non-PHPdoc)
+     * @see Otp.OtpInterface::checkTotp()
+    */
+    public function checkTotp($secret, $key, $timedrift = 1)
+    {
+        if (!is_numeric($timedrift) || $timedrift < 0) {
+            throw new \InvalidArgumentException('Invalid timedrift supplied');
+        }
+        // Counter comes from time now
+        // Also we check the current timestamp as well as previous and future ones
+        // according to $timerange
+        $timecounter = $this->getTimecounter();
+    
+        $start = $timecounter - ($timedrift);
+        $end = $timecounter + ($timedrift);
+    
+        // We first try the current, as it is the most likely to work
+        if (hash_equals($this->totp($secret, $timecounter), $key)) {
+            return true;
+        } elseif ($timedrift == 0) {
+            // When timedrift is 0, this is the end of the checks
+            return false;
+        }
+    
+        // Well, that didn't work, so try the others
+        for ($t = $start; $t <= $end; $t = $t + 1) {
+            if ($t == $timecounter) {
+                // Already tried that one
+                continue;
+            }
+                
+            if (hash_equals($this->totp($secret, $t), $key)) {
+                return true;
+            }
+        }
+    
+        // if none worked, then return false
+        return false;
+    }
+    
+    /**
+     * Changing the used algorithm for hashing
+     *
+     * Can only be one of the algorithms in the allowedAlgorithms property.
+     *
+     * @param string $algorithm
+     * @throws \InvalidArgumentException
+     * @return \Otp\Otp
+     */
+    public function setAlgorithm($algorithm)
+    {
+        if (!in_array($algorithm, $this->allowedAlgorithms)) {
+            throw new \InvalidArgumentException('Not an allowed algorithm: ' . $algorithm);
+        }
+        
+        $this->algorithm = $algorithm;
+        
+        return $this;
+    }
+    
+    /**
+     * Get the algorithms name (lowercase)
+     *
+     * @return string
+     */
+    public function getAlgorithm()
+    {
+        return $this->algorithm;
+    }
+    
+    /**
+     * Setting period lenght for totp
+     *
+     * @param integer $period
+     * @throws \InvalidArgumentException
+     * @return \Otp\Otp
+     */
+    public function setPeriod($period)
+    {
+        if (!is_int($period)) {
+            throw new \InvalidArgumentException('Period must be an integer');
+        }
+        
+        $this->period = $period;
+        
+        return $this;
+    }
+    
+    /**
+     * Returns the set period value
+     *
+     * @return integer
+     */
+    public function getPeriod()
+    {
+        return $this->period;
+    }
+    
+    /**
+     * Setting number of otp digits
+     *
+     * @param integer $digits Number of digits for the otp (6 or 8)
+     * @throws \InvalidArgumentException
+     * @return \Otp\Otp
+     */
+    public function setDigits($digits)
+    {
+        if (!in_array($digits, array(6, 8))) {
+            throw new \InvalidArgumentException('Digits must be 6 or 8');
+        }
+        
+        $this->digits = $digits;
+        
+        return $this;
+    }
+    
+    /**
+     * Returns number of digits in the otp
+     *
+     * @return integer
+     */
+    public function getDigits()
+    {
+        return $this->digits;
+    }
+
+    /**
+     * Set offset between system time and GMT
+     *
+     * @param integer $offset GMT - time()
+     * @throws \InvalidArgumentException
+     * @return \Otp\Otp
+     */
+    public function setTotpOffset($offset)
+    {
+        if (!is_int($offset)) {
+            throw new \InvalidArgumentException('Offset must be an integer');
+        }
+        
+        $this->totpOffset = $offset;
+        
+        return $this;
+    }
+    
+    /**
+     * Returns offset between system time and GMT in seconds
+     *
+     * @return integer
+     */
+    public function getTotpOffset()
+    {
+        return $this->totpOffset;
+    }
+    
+    /**
+     * Generates a binary counter for hashing
+     *
+     * Warning: use 64 bit PHP >= 5.6.3 to be "2038 safe".
+     *
+     * @param integer $counter Counter in integer form
+     * @return string Binary string
+     */
+    private function getBinaryCounter($counter)
+    {
+        // on 64 bit, PHP >= 5.6.3 this is "2038 safe"
+        if (8 === PHP_INT_SIZE && PHP_VERSION_ID >= 50603) {
+            return pack('J', $counter);
+        }
+
+        // keep old behavior for 32 bit PHP or PHP < 5.6.3
+        return pack('N*', 0) . pack('N*', $counter);
+    }
+    
+    /**
+     * Generating time counter
+     *
+     * This is the time divided by 30 by default.
+     *
+     * @return integer Time counter
+     */
+    private function getTimecounter()
+    {
+        return floor((time() + $this->totpOffset) / $this->period);
+    }
+    
+    /**
+     * Creates the basic number for otp from hash
+     *
+     * This number is left padded with zeros to the required length by the
+     * calling function.
+     *
+     * @param string $hash hmac hash
+     * @return number
+     */
+    private function truncate($hash)
+    {
+        $offset = ord($hash[strlen($hash)-1]) & 0xf;
+        
+        return (
+            ((ord($hash[$offset+0]) & 0x7f) << 24 ) |
+            ((ord($hash[$offset+1]) & 0xff) << 16 ) |
+            ((ord($hash[$offset+2]) & 0xff) << 8 ) |
+            (ord($hash[$offset+3]) & 0xff)
+            ) % pow(10, $this->digits);
+    }
+}
+
diff --git a/vendor/christian-riesen/otp/src/OtpInterface.php b/vendor/christian-riesen/otp/src/OtpInterface.php
new file mode 100644
index 0000000000000000000000000000000000000000..e241d5d2c65287d7c34fbe4efc6aaa4918b23a3f
--- /dev/null
+++ b/vendor/christian-riesen/otp/src/OtpInterface.php
@@ -0,0 +1,77 @@
+<?php
+
+namespace Otp;
+
+/**
+ * Interface for HOTP and TOTP
+ *
+ * HMAC-Based One-time Password(HOTP) algorithm specified in RFC 4226
+ * @link https://tools.ietf.org/html/rfc4226
+ *
+ * Time-based One-time Password (TOTP) algorithm specified in RFC 6238
+ * @link https://tools.ietf.org/html/rfc6238
+ *
+ * @author Christian Riesen <chris.riesen@gmail.com>
+ * @link http://christianriesen.com
+ * @license MIT License see LICENSE file
+ */
+
+interface OtpInterface
+{
+    /**
+     * Returns OTP using the HOTP algorithm (counter based)
+     *
+     * @param string  $secret  Base32 Secret String
+     * @param integer $counter Counter
+     *
+     * @return string One Time Password
+     */
+    function hotp($secret, $counter);
+
+    /**
+     * Returns OTP using the TOTP algorithm (time based)
+     *
+     * @param string  $secret      Base32 Secret String
+     * @param integer $timecounter Optional: Uses current time if null
+     *
+     * @return string One Time Password
+     */
+    function totp($secret, $timecounter = null);
+
+    /**
+     * Checks Hotp against a key
+     *
+     * This is a helper function, but is here to ensure the Totp can be checked
+     * in the same manner.
+     *
+     * @param string  $secret  Base32 Secret String
+     * @param integer $counter Counter
+     * @param string  $key     User supplied key
+     *
+     * @return boolean True if key is correct
+     */
+    function checkHotp($secret, $counter, $key);
+
+    /**
+     * Checks Hotp against a key for a provided counter window
+     *
+     * @param string  $secret        Base32 Secret String
+     * @param integer $counter       Counter
+     * @param string  $key           User supplied key
+     * @param integer $counterwindow (optional) Size of the look-ahead window. Default value is 2
+     *
+     * @return int|boolean the counter if key is correct else false
+     */
+    function checkHotpResync($secret, $counter, $key, $counterwindow = 2);
+
+    /**
+     * Checks Totp agains a key
+     *
+     * @param string  $secret    Base32 Secret String
+     * @param integer $key       User supplied key
+     * @param integer $timedrift How large a drift to use beyond exact match
+     *
+     * @return boolean True if key is correct within time drift
+     */
+    function checkTotp($secret, $key, $timedrift = 1);
+}
diff --git a/vendor/christian-riesen/otp/tests/GoogleAuthenticatorTest.php b/vendor/christian-riesen/otp/tests/GoogleAuthenticatorTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..a299ab2862b5d6aba194fd3e585ee8f9619b10e8
--- /dev/null
+++ b/vendor/christian-riesen/otp/tests/GoogleAuthenticatorTest.php
@@ -0,0 +1,112 @@
+<?php
+
+namespace Otp\Tests;
+
+use Otp\GoogleAuthenticator;
+use PHPUnit\Framework\TestCase;
+
+/**
+ * GoogleAuthenticator test case.
+ */
+class GoogleAuthenticatorTest extends TestCase
+{
+	/**
+	 * Tests getQrCodeUrl
+	 */
+	public function testGetQrCodeUrl()
+	{
+		$secret = 'MEP3EYVA6XNFNVNM'; // testing secret
+		
+		// Standard totp case
+		$this->assertEquals(
+			'https://chart.googleapis.com/chart?chs=200x200&cht=qr&chld=M|0&chl=otpauth%3A%2F%2Ftotp%2Fuser%2540host.com%3Fsecret%3DMEP3EYVA6XNFNVNM',
+			GoogleAuthenticator::getQrCodeUrl('totp', 'user@host.com', $secret)
+		);
+		
+		// hotp (include a counter)
+		$this->assertEquals(
+			'https://chart.googleapis.com/chart?chs=200x200&cht=qr&chld=M|0&chl=otpauth%3A%2F%2Fhotp%2Fuser%2540host.com%3Fsecret%3DMEP3EYVA6XNFNVNM%26counter%3D1234',
+			GoogleAuthenticator::getQrCodeUrl('hotp', 'user@host.com', $secret, 1234)
+		);
+		
+		// totp, this time with a parameter for chaning the size of the QR
+		$this->assertEquals(
+				'https://chart.googleapis.com/chart?chs=300x300&cht=qr&chld=M|0&chl=otpauth%3A%2F%2Ftotp%2Fuser%2540host.com%3Fsecret%3DMEP3EYVA6XNFNVNM',
+				GoogleAuthenticator::getQrCodeUrl('totp', 'user@host.com', $secret, null, array('height' => 300, 'width' => 300))
+		);
+		
+	}
+
+	/**
+	 * Tests getKeyUri
+	 */
+	public function testGetKeyUri()
+	{
+		$secret = 'MEP3EYVA6XNFNVNM'; // testing secret
+		
+		// Standard totp case
+		$this->assertEquals(
+			'otpauth://totp/user%40host.com?secret=MEP3EYVA6XNFNVNM',
+			GoogleAuthenticator::getKeyUri('totp', 'user@host.com', $secret)
+		);
+
+		// hotp (include a counter)
+		$this->assertEquals(
+			'otpauth://hotp/user%40host.com?secret=MEP3EYVA6XNFNVNM&counter=1234',
+			GoogleAuthenticator::getKeyUri('hotp', 'user@host.com', $secret, 1234)
+		);
+
+		// totp/hotp with an issuer in the label
+		$this->assertEquals(
+			'otpauth://hotp/issuer%3Auser%40host.com?secret=MEP3EYVA6XNFNVNM&counter=1234',
+			GoogleAuthenticator::getKeyUri('hotp', 'issuer:user@host.com', $secret, 1234)
+		);
+
+		// totp/hotp with an issuer and spaces in the label
+		$this->assertEquals(
+			'otpauth://hotp/an%20issuer%3A%20user%40host.com?secret=MEP3EYVA6XNFNVNM&counter=1234',
+			GoogleAuthenticator::getKeyUri('hotp', 'an issuer: user@host.com', $secret, 1234)
+		);
+
+		// totp/hotp with an issuer as option
+		$this->assertEquals(
+			'otpauth://hotp/an%20issuer%3Auser%40host.com?secret=MEP3EYVA6XNFNVNM&counter=1234&issuer=an%20issuer',
+			GoogleAuthenticator::getKeyUri('hotp', 'an issuer:user@host.com', $secret, 1234, array('issuer' => 'an issuer'))
+		);
+	}
+	
+	/**
+	 * Tests generateRandom
+	 */
+	public function testGenerateRandom()
+	{
+	    // contains numbers 2-7 and letters A-Z in large letters, 16 chars long
+	    $this->assertRegExp('/[2-7A-Z]{16}/', GoogleAuthenticator::generateRandom());
+	
+	    // Can be told to make a longer secret
+	    $this->assertRegExp('/[2-7A-Z]{18}/', GoogleAuthenticator::generateRandom(18));
+	}
+
+	/**
+	 * Test generateRecoveryCodes
+	 */
+	public function testGenerateRecoveryCodes()
+	{
+		// Default settings
+		$codes = GoogleAuthenticator::generateRecoveryCodes();
+
+		$this->assertCount(1, $codes);
+		$this->assertRegExp('/[0-9]{9}/', $codes[0]);
+
+		// More codes, longer
+		$codes = GoogleAuthenticator::generateRecoveryCodes(4, 20);
+		$this->assertCount(4, $codes);
+		$this->assertRegExp('/[0-9]{9}/', $codes[0]);
+		$this->assertRegExp('/[0-9]{9}/', $codes[1]);
+		$this->assertRegExp('/[0-9]{9}/', $codes[2]);
+		$this->assertRegExp('/[0-9]{9}/', $codes[3]);
+
+		// To check for uniqueness
+		$this->assertSame($codes, array_unique($codes));
+	}
+}
diff --git a/vendor/christian-riesen/otp/tests/OtpTest.php b/vendor/christian-riesen/otp/tests/OtpTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..599febb7b0c3177fcc46edfe87370b59db7c0b32
--- /dev/null
+++ b/vendor/christian-riesen/otp/tests/OtpTest.php
@@ -0,0 +1,235 @@
+<?php
+
+namespace Otp\Tests;
+
+use Otp\Otp;
+use PHPUnit\Framework\TestCase;
+
+/**
+ * Otp test case.
+ */
+class OtpTest extends TestCase
+{
+	/**
+	 *
+	 * @var Otp
+	 */
+	private $Otp;
+	
+	private $secret = "12345678901234567890";
+
+	/**
+	 * Prepares the environment before running a test.
+	 */
+	protected function setUp()
+	{
+		parent::setUp();
+		
+		$this->Otp = new Otp();
+	
+	}
+	
+	/**
+	 * Cleans up the environment after running a test.
+	 */
+	protected function tearDown()
+	{
+		$this->Otp = null;
+		
+		parent::tearDown();
+	}
+
+	/**
+	 * Invalid counter values for tests
+	 */
+	public function hotpTestValues()
+	{
+		return [
+				 ['755224', 0], ['287082', 1], ['359152', 2],
+				 ['969429', 3], ['338314', 4], ['254676', 5],
+   				 ['287922', 6], ['162583', 7], ['399871', 8],
+   				 ['520489', 9]
+			   ];
+	}
+
+	/**
+	 * Invalid counter values for tests
+	 */
+	public function totpTestValues()
+	{
+		// https://www.rfc-editor.org/errata_search.php?rfc=6238
+		$secretSha1   = '12345678901234567890';
+		$secretSha256 = '12345678901234567890123456789012';
+		$secretSha512 = '1234567890123456789012345678901234567890123456789012345678901234';
+
+		return [
+			['sha1',   $secretSha1,   '94287082', 59],
+			['sha1',   $secretSha1,   '07081804', 1111111109],
+			['sha1',   $secretSha1,   '14050471', 1111111111],
+			['sha1',   $secretSha1,   '89005924', 1234567890],
+			['sha1',   $secretSha1,   '69279037', 2000000000],
+			['sha1',   $secretSha1,   '65353130', 20000000000],
+			['sha256', $secretSha256, '46119246', 59],
+			['sha256', $secretSha256, '68084774', 1111111109],
+			['sha256', $secretSha256, '67062674', 1111111111],
+			['sha256', $secretSha256, '91819424', 1234567890],
+			['sha256', $secretSha256, '90698825', 2000000000],
+			['sha256', $secretSha256, '77737706', 20000000000],
+			['sha512', $secretSha512, '90693936', 59],
+			['sha512', $secretSha512, '25091201', 1111111109],
+			['sha512', $secretSha512, '99943326', 1111111111],
+			['sha512', $secretSha512, '93441116', 1234567890],
+			['sha512', $secretSha512, '38618901', 2000000000],
+			['sha512', $secretSha512, '47863826', 20000000000],
+		];
+	}
+
+	/**
+	 * Invalid counter values for tests
+	 */
+	public function invalidCounterValues()
+	{
+		return [
+				 ['a'], [-1]
+			   ];
+	}
+
+	/**
+	 * Invalid counter values for tests
+	 */
+	public function hotpResyncDefaultTestValues()
+	{
+		return [
+				 ['755224', 0], ['287082', 1], ['359152', 2]
+			   ];
+	}
+
+	/**
+	 * Invalid counter values for tests
+	 */
+	public function hotpResyncWindowTestValues()
+	{
+		return [
+				 ['969429', 0, 3], ['338314', 0, 4],
+				 ['287922', 3, 3], ['162583', 3, 4]
+			   ];
+	}
+
+	/**
+	 * Invalid counter values for tests
+	 */
+	public function hotpResyncFailureTestValues()
+	{
+		return [
+				 ['287922', 7], ['162583', 8], ['399871', 9]
+			   ];
+	}
+	
+	/**
+	 * Tests Otp->hotp()
+	 *
+	 * Using test vectors from RFC
+	 * https://tools.ietf.org/html/rfc4226
+	 *
+	 * @dataProvider hotpTestValues
+	 */
+	public function testHotpRfc($key, $counter)
+	{
+		$secret = $this->secret;
+	
+		$this->assertEquals($key, $this->Otp->hotp($secret, $counter));
+	}
+		
+	/**
+	 * Tests TOTP general construction
+	 *
+	 * Still uses the hotp function, but since totp is a bit more special, has
+	 * its own tests
+	 * Using test vectors from RFC
+	 * https://tools.ietf.org/html/rfc6238
+	 *
+	 * @dataProvider totpTestValues
+	 */
+	public function testTotpRfc($algo, $secret, $key, $time)
+	{
+		// Test vectors are in 8 digits
+		$this->Otp->setDigits(8);
+		
+		// The time presented in the test vector has to be first divided through 30
+		// to count as the key
+
+		$this->Otp->setAlgorithm($algo);
+		$this->assertEquals($key, $this->Otp->hotp($secret, floor($time/30)), "$algo with $time");
+	}
+
+	/**
+	 * @dataProvider invalidCounterValues
+	 * @expectedException InvalidArgumentException
+	 * @expectedExceptionMessage Invalid counter supplied
+	 */
+	public function testHotpInvalidCounter($counter)
+	{
+		$this->Otp->hotp($this->secret, $counter);
+	}
+
+	/**
+	 * Tests Otp->checkHotpResync() with default counter window
+	 *
+	 * @dataProvider hotpResyncDefaultTestValues
+	 */
+	public function testHotpResyncDefault($key, $counter)
+	{
+		$secret = $this->secret;
+
+		// test with default counter window
+		$this->assertSame($counter, $this->Otp->checkHotpResync($secret, $counter, $key));
+	}
+
+
+	/**
+	 * Tests Otp->checkHotpResync() with a provided counter window
+	 *
+	 * @dataProvider hotpResyncWindowTestValues
+	 */
+	public function testHotpResyncWindow($key, $counter, $counterwindow)
+	{
+		$secret = $this->secret;
+
+		// test with provided counter window
+		$this->assertSame(($counter + $counterwindow), $this->Otp->checkHotpResync($secret, $counter, $key, $counterwindow));
+	}
+
+	/**
+	 * Tests Otp->checkHotpResync() with mismatching key and counter
+	 *
+	 * @dataProvider hotpResyncFailureTestValues
+	 */
+	public function testHotpResyncFailures($key, $counter)
+	{
+		$secret = $this->secret;
+
+		// test failures
+		$this->assertFalse($this->Otp->checkHotpResync($secret, $counter, $key));
+	}
+
+	/**
+	 * @dataProvider invalidCounterValues
+	 * @expectedException InvalidArgumentException
+	 * @expectedExceptionMessage Invalid counter supplied
+	 */
+	public function testHotpResyncInvalidCounter($counter)
+	{
+		$this->Otp->checkHotpResync($this->secret, $counter, '755224');
+	}
+
+	/**
+	 * @dataProvider invalidCounterValues
+	 * @expectedException InvalidArgumentException
+	 * @expectedExceptionMessage Invalid counterwindow supplied
+	 */
+	public function testHotpResyncInvalidCounterWindow($counterwindow)
+	{
+		$this->Otp->checkHotpResync($this->secret, 0, '755224', $counterwindow);
+	}
+
+}
diff --git a/vendor/christian-riesen/otp/tests/bootstrap.php b/vendor/christian-riesen/otp/tests/bootstrap.php
new file mode 100644
index 0000000000000000000000000000000000000000..353cb7a4942f826334251b225751b563eeade855
--- /dev/null
+++ b/vendor/christian-riesen/otp/tests/bootstrap.php
@@ -0,0 +1,5 @@
+<?php
+
+$loader = require __DIR__ . '/../vendor/autoload.php';
+$loader->add("Otp", __DIR__);
+$loader->register();
\ No newline at end of file
diff --git a/vendor/composer/autoload_classmap.php b/vendor/composer/autoload_classmap.php
index 2b89e59e2ec40957625501b69581560d109741ff..fe8c2a19309ed92a79a6dd89fa3a037ca75b5005 100644
--- a/vendor/composer/autoload_classmap.php
+++ b/vendor/composer/autoload_classmap.php
@@ -8,7 +8,622 @@ $baseDir = dirname($vendorDir);
 return array(
     'Datamatrix' => $vendorDir . '/tecnickcom/tcpdf/include/barcodes/datamatrix.php',
     'PDF417' => $vendorDir . '/tecnickcom/tcpdf/include/barcodes/pdf417.php',
+    'PHPUnit\\Exception' => $vendorDir . '/phpunit/phpunit/src/Exception.php',
+    'PHPUnit\\Framework\\ActualValueIsNotAnObjectException' => $vendorDir . '/phpunit/phpunit/src/Framework/Exception/ActualValueIsNotAnObjectException.php',
+    'PHPUnit\\Framework\\Assert' => $vendorDir . '/phpunit/phpunit/src/Framework/Assert.php',
+    'PHPUnit\\Framework\\AssertionFailedError' => $vendorDir . '/phpunit/phpunit/src/Framework/Exception/AssertionFailedError.php',
+    'PHPUnit\\Framework\\CodeCoverageException' => $vendorDir . '/phpunit/phpunit/src/Framework/Exception/CodeCoverageException.php',
+    'PHPUnit\\Framework\\ComparisonMethodDoesNotAcceptParameterTypeException' => $vendorDir . '/phpunit/phpunit/src/Framework/Exception/ComparisonMethodDoesNotAcceptParameterTypeException.php',
+    'PHPUnit\\Framework\\ComparisonMethodDoesNotDeclareBoolReturnTypeException' => $vendorDir . '/phpunit/phpunit/src/Framework/Exception/ComparisonMethodDoesNotDeclareBoolReturnTypeException.php',
+    'PHPUnit\\Framework\\ComparisonMethodDoesNotDeclareExactlyOneParameterException' => $vendorDir . '/phpunit/phpunit/src/Framework/Exception/ComparisonMethodDoesNotDeclareExactlyOneParameterException.php',
+    'PHPUnit\\Framework\\ComparisonMethodDoesNotDeclareParameterTypeException' => $vendorDir . '/phpunit/phpunit/src/Framework/Exception/ComparisonMethodDoesNotDeclareParameterTypeException.php',
+    'PHPUnit\\Framework\\ComparisonMethodDoesNotExistException' => $vendorDir . '/phpunit/phpunit/src/Framework/Exception/ComparisonMethodDoesNotExistException.php',
+    'PHPUnit\\Framework\\Constraint\\ArrayHasKey' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Traversable/ArrayHasKey.php',
+    'PHPUnit\\Framework\\Constraint\\BinaryOperator' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Operator/BinaryOperator.php',
+    'PHPUnit\\Framework\\Constraint\\Callback' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Callback.php',
+    'PHPUnit\\Framework\\Constraint\\ClassHasAttribute' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Object/ClassHasAttribute.php',
+    'PHPUnit\\Framework\\Constraint\\ClassHasStaticAttribute' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Object/ClassHasStaticAttribute.php',
+    'PHPUnit\\Framework\\Constraint\\Constraint' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Constraint.php',
+    'PHPUnit\\Framework\\Constraint\\Count' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Cardinality/Count.php',
+    'PHPUnit\\Framework\\Constraint\\DirectoryExists' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Filesystem/DirectoryExists.php',
+    'PHPUnit\\Framework\\Constraint\\Exception' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Exception/Exception.php',
+    'PHPUnit\\Framework\\Constraint\\ExceptionCode' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Exception/ExceptionCode.php',
+    'PHPUnit\\Framework\\Constraint\\ExceptionMessage' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Exception/ExceptionMessage.php',
+    'PHPUnit\\Framework\\Constraint\\ExceptionMessageRegularExpression' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Exception/ExceptionMessageRegularExpression.php',
+    'PHPUnit\\Framework\\Constraint\\FileExists' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Filesystem/FileExists.php',
+    'PHPUnit\\Framework\\Constraint\\GreaterThan' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Cardinality/GreaterThan.php',
+    'PHPUnit\\Framework\\Constraint\\IsAnything' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/IsAnything.php',
+    'PHPUnit\\Framework\\Constraint\\IsEmpty' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Cardinality/IsEmpty.php',
+    'PHPUnit\\Framework\\Constraint\\IsEqual' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Equality/IsEqual.php',
+    'PHPUnit\\Framework\\Constraint\\IsEqualCanonicalizing' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Equality/IsEqualCanonicalizing.php',
+    'PHPUnit\\Framework\\Constraint\\IsEqualIgnoringCase' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Equality/IsEqualIgnoringCase.php',
+    'PHPUnit\\Framework\\Constraint\\IsEqualWithDelta' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Equality/IsEqualWithDelta.php',
+    'PHPUnit\\Framework\\Constraint\\IsFalse' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Boolean/IsFalse.php',
+    'PHPUnit\\Framework\\Constraint\\IsFinite' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Math/IsFinite.php',
+    'PHPUnit\\Framework\\Constraint\\IsIdentical' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/IsIdentical.php',
+    'PHPUnit\\Framework\\Constraint\\IsInfinite' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Math/IsInfinite.php',
+    'PHPUnit\\Framework\\Constraint\\IsInstanceOf' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Type/IsInstanceOf.php',
+    'PHPUnit\\Framework\\Constraint\\IsJson' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/String/IsJson.php',
+    'PHPUnit\\Framework\\Constraint\\IsNan' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Math/IsNan.php',
+    'PHPUnit\\Framework\\Constraint\\IsNull' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Type/IsNull.php',
+    'PHPUnit\\Framework\\Constraint\\IsReadable' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Filesystem/IsReadable.php',
+    'PHPUnit\\Framework\\Constraint\\IsTrue' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Boolean/IsTrue.php',
+    'PHPUnit\\Framework\\Constraint\\IsType' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Type/IsType.php',
+    'PHPUnit\\Framework\\Constraint\\IsWritable' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Filesystem/IsWritable.php',
+    'PHPUnit\\Framework\\Constraint\\JsonMatches' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/JsonMatches.php',
+    'PHPUnit\\Framework\\Constraint\\JsonMatchesErrorMessageProvider' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/JsonMatchesErrorMessageProvider.php',
+    'PHPUnit\\Framework\\Constraint\\LessThan' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Cardinality/LessThan.php',
+    'PHPUnit\\Framework\\Constraint\\LogicalAnd' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Operator/LogicalAnd.php',
+    'PHPUnit\\Framework\\Constraint\\LogicalNot' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Operator/LogicalNot.php',
+    'PHPUnit\\Framework\\Constraint\\LogicalOr' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Operator/LogicalOr.php',
+    'PHPUnit\\Framework\\Constraint\\LogicalXor' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Operator/LogicalXor.php',
+    'PHPUnit\\Framework\\Constraint\\ObjectEquals' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Object/ObjectEquals.php',
+    'PHPUnit\\Framework\\Constraint\\ObjectHasAttribute' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Object/ObjectHasAttribute.php',
+    'PHPUnit\\Framework\\Constraint\\Operator' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Operator/Operator.php',
+    'PHPUnit\\Framework\\Constraint\\RegularExpression' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/String/RegularExpression.php',
+    'PHPUnit\\Framework\\Constraint\\SameSize' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Cardinality/SameSize.php',
+    'PHPUnit\\Framework\\Constraint\\StringContains' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/String/StringContains.php',
+    'PHPUnit\\Framework\\Constraint\\StringEndsWith' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/String/StringEndsWith.php',
+    'PHPUnit\\Framework\\Constraint\\StringMatchesFormatDescription' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/String/StringMatchesFormatDescription.php',
+    'PHPUnit\\Framework\\Constraint\\StringStartsWith' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/String/StringStartsWith.php',
+    'PHPUnit\\Framework\\Constraint\\TraversableContains' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Traversable/TraversableContains.php',
+    'PHPUnit\\Framework\\Constraint\\TraversableContainsEqual' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Traversable/TraversableContainsEqual.php',
+    'PHPUnit\\Framework\\Constraint\\TraversableContainsIdentical' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Traversable/TraversableContainsIdentical.php',
+    'PHPUnit\\Framework\\Constraint\\TraversableContainsOnly' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Traversable/TraversableContainsOnly.php',
+    'PHPUnit\\Framework\\Constraint\\UnaryOperator' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Operator/UnaryOperator.php',
+    'PHPUnit\\Framework\\CoveredCodeNotExecutedException' => $vendorDir . '/phpunit/phpunit/src/Framework/Exception/CoveredCodeNotExecutedException.php',
+    'PHPUnit\\Framework\\DataProviderTestSuite' => $vendorDir . '/phpunit/phpunit/src/Framework/DataProviderTestSuite.php',
+    'PHPUnit\\Framework\\Error' => $vendorDir . '/phpunit/phpunit/src/Framework/Exception/Error.php',
+    'PHPUnit\\Framework\\ErrorTestCase' => $vendorDir . '/phpunit/phpunit/src/Framework/ErrorTestCase.php',
+    'PHPUnit\\Framework\\Error\\Deprecated' => $vendorDir . '/phpunit/phpunit/src/Framework/Error/Deprecated.php',
+    'PHPUnit\\Framework\\Error\\Error' => $vendorDir . '/phpunit/phpunit/src/Framework/Error/Error.php',
+    'PHPUnit\\Framework\\Error\\Notice' => $vendorDir . '/phpunit/phpunit/src/Framework/Error/Notice.php',
+    'PHPUnit\\Framework\\Error\\Warning' => $vendorDir . '/phpunit/phpunit/src/Framework/Error/Warning.php',
+    'PHPUnit\\Framework\\Exception' => $vendorDir . '/phpunit/phpunit/src/Framework/Exception/Exception.php',
+    'PHPUnit\\Framework\\ExceptionWrapper' => $vendorDir . '/phpunit/phpunit/src/Framework/ExceptionWrapper.php',
+    'PHPUnit\\Framework\\ExecutionOrderDependency' => $vendorDir . '/phpunit/phpunit/src/Framework/ExecutionOrderDependency.php',
+    'PHPUnit\\Framework\\ExpectationFailedException' => $vendorDir . '/phpunit/phpunit/src/Framework/Exception/ExpectationFailedException.php',
+    'PHPUnit\\Framework\\IncompleteTest' => $vendorDir . '/phpunit/phpunit/src/Framework/IncompleteTest.php',
+    'PHPUnit\\Framework\\IncompleteTestCase' => $vendorDir . '/phpunit/phpunit/src/Framework/IncompleteTestCase.php',
+    'PHPUnit\\Framework\\IncompleteTestError' => $vendorDir . '/phpunit/phpunit/src/Framework/Exception/IncompleteTestError.php',
+    'PHPUnit\\Framework\\InvalidArgumentException' => $vendorDir . '/phpunit/phpunit/src/Framework/Exception/InvalidArgumentException.php',
+    'PHPUnit\\Framework\\InvalidCoversTargetException' => $vendorDir . '/phpunit/phpunit/src/Framework/Exception/InvalidCoversTargetException.php',
+    'PHPUnit\\Framework\\InvalidDataProviderException' => $vendorDir . '/phpunit/phpunit/src/Framework/Exception/InvalidDataProviderException.php',
+    'PHPUnit\\Framework\\InvalidParameterGroupException' => $vendorDir . '/phpunit/phpunit/src/Framework/InvalidParameterGroupException.php',
+    'PHPUnit\\Framework\\MissingCoversAnnotationException' => $vendorDir . '/phpunit/phpunit/src/Framework/Exception/MissingCoversAnnotationException.php',
+    'PHPUnit\\Framework\\MockObject\\Api' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Api/Api.php',
+    'PHPUnit\\Framework\\MockObject\\BadMethodCallException' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Exception/BadMethodCallException.php',
+    'PHPUnit\\Framework\\MockObject\\Builder\\Identity' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Builder/Identity.php',
+    'PHPUnit\\Framework\\MockObject\\Builder\\InvocationMocker' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Builder/InvocationMocker.php',
+    'PHPUnit\\Framework\\MockObject\\Builder\\InvocationStubber' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Builder/InvocationStubber.php',
+    'PHPUnit\\Framework\\MockObject\\Builder\\MethodNameMatch' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Builder/MethodNameMatch.php',
+    'PHPUnit\\Framework\\MockObject\\Builder\\ParametersMatch' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Builder/ParametersMatch.php',
+    'PHPUnit\\Framework\\MockObject\\Builder\\Stub' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Builder/Stub.php',
+    'PHPUnit\\Framework\\MockObject\\CannotUseAddMethodsException' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Exception/CannotUseAddMethodsException.php',
+    'PHPUnit\\Framework\\MockObject\\CannotUseOnlyMethodsException' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Exception/CannotUseOnlyMethodsException.php',
+    'PHPUnit\\Framework\\MockObject\\ClassAlreadyExistsException' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Exception/ClassAlreadyExistsException.php',
+    'PHPUnit\\Framework\\MockObject\\ClassIsFinalException' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Exception/ClassIsFinalException.php',
+    'PHPUnit\\Framework\\MockObject\\ConfigurableMethod' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/ConfigurableMethod.php',
+    'PHPUnit\\Framework\\MockObject\\ConfigurableMethodsAlreadyInitializedException' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Exception/ConfigurableMethodsAlreadyInitializedException.php',
+    'PHPUnit\\Framework\\MockObject\\DuplicateMethodException' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Exception/DuplicateMethodException.php',
+    'PHPUnit\\Framework\\MockObject\\Exception' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Exception/Exception.php',
+    'PHPUnit\\Framework\\MockObject\\Generator' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Generator.php',
+    'PHPUnit\\Framework\\MockObject\\IncompatibleReturnValueException' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Exception/IncompatibleReturnValueException.php',
+    'PHPUnit\\Framework\\MockObject\\InvalidMethodNameException' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Exception/InvalidMethodNameException.php',
+    'PHPUnit\\Framework\\MockObject\\Invocation' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Invocation.php',
+    'PHPUnit\\Framework\\MockObject\\InvocationHandler' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/InvocationHandler.php',
+    'PHPUnit\\Framework\\MockObject\\MatchBuilderNotFoundException' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Exception/MatchBuilderNotFoundException.php',
+    'PHPUnit\\Framework\\MockObject\\Matcher' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Matcher.php',
+    'PHPUnit\\Framework\\MockObject\\MatcherAlreadyRegisteredException' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Exception/MatcherAlreadyRegisteredException.php',
+    'PHPUnit\\Framework\\MockObject\\Method' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Api/Method.php',
+    'PHPUnit\\Framework\\MockObject\\MethodCannotBeConfiguredException' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Exception/MethodCannotBeConfiguredException.php',
+    'PHPUnit\\Framework\\MockObject\\MethodNameAlreadyConfiguredException' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Exception/MethodNameAlreadyConfiguredException.php',
+    'PHPUnit\\Framework\\MockObject\\MethodNameConstraint' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/MethodNameConstraint.php',
+    'PHPUnit\\Framework\\MockObject\\MethodNameNotConfiguredException' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Exception/MethodNameNotConfiguredException.php',
+    'PHPUnit\\Framework\\MockObject\\MethodParametersAlreadyConfiguredException' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Exception/MethodParametersAlreadyConfiguredException.php',
+    'PHPUnit\\Framework\\MockObject\\MockBuilder' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/MockBuilder.php',
+    'PHPUnit\\Framework\\MockObject\\MockClass' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/MockClass.php',
+    'PHPUnit\\Framework\\MockObject\\MockMethod' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/MockMethod.php',
+    'PHPUnit\\Framework\\MockObject\\MockMethodSet' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/MockMethodSet.php',
+    'PHPUnit\\Framework\\MockObject\\MockObject' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/MockObject.php',
+    'PHPUnit\\Framework\\MockObject\\MockTrait' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/MockTrait.php',
+    'PHPUnit\\Framework\\MockObject\\MockType' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/MockType.php',
+    'PHPUnit\\Framework\\MockObject\\MockedCloneMethod' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Api/MockedCloneMethod.php',
+    'PHPUnit\\Framework\\MockObject\\OriginalConstructorInvocationRequiredException' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Exception/OriginalConstructorInvocationRequiredException.php',
+    'PHPUnit\\Framework\\MockObject\\ReflectionException' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Exception/ReflectionException.php',
+    'PHPUnit\\Framework\\MockObject\\ReturnValueNotConfiguredException' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Exception/ReturnValueNotConfiguredException.php',
+    'PHPUnit\\Framework\\MockObject\\Rule\\AnyInvokedCount' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Rule/AnyInvokedCount.php',
+    'PHPUnit\\Framework\\MockObject\\Rule\\AnyParameters' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Rule/AnyParameters.php',
+    'PHPUnit\\Framework\\MockObject\\Rule\\ConsecutiveParameters' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Rule/ConsecutiveParameters.php',
+    'PHPUnit\\Framework\\MockObject\\Rule\\InvocationOrder' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Rule/InvocationOrder.php',
+    'PHPUnit\\Framework\\MockObject\\Rule\\InvokedAtIndex' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Rule/InvokedAtIndex.php',
+    'PHPUnit\\Framework\\MockObject\\Rule\\InvokedAtLeastCount' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Rule/InvokedAtLeastCount.php',
+    'PHPUnit\\Framework\\MockObject\\Rule\\InvokedAtLeastOnce' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Rule/InvokedAtLeastOnce.php',
+    'PHPUnit\\Framework\\MockObject\\Rule\\InvokedAtMostCount' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Rule/InvokedAtMostCount.php',
+    'PHPUnit\\Framework\\MockObject\\Rule\\InvokedCount' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Rule/InvokedCount.php',
+    'PHPUnit\\Framework\\MockObject\\Rule\\MethodName' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Rule/MethodName.php',
+    'PHPUnit\\Framework\\MockObject\\Rule\\Parameters' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Rule/Parameters.php',
+    'PHPUnit\\Framework\\MockObject\\Rule\\ParametersRule' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Rule/ParametersRule.php',
+    'PHPUnit\\Framework\\MockObject\\RuntimeException' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Exception/RuntimeException.php',
+    'PHPUnit\\Framework\\MockObject\\SoapExtensionNotAvailableException' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Exception/SoapExtensionNotAvailableException.php',
+    'PHPUnit\\Framework\\MockObject\\Stub' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Stub.php',
+    'PHPUnit\\Framework\\MockObject\\Stub\\ConsecutiveCalls' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Stub/ConsecutiveCalls.php',
+    'PHPUnit\\Framework\\MockObject\\Stub\\Exception' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Stub/Exception.php',
+    'PHPUnit\\Framework\\MockObject\\Stub\\ReturnArgument' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Stub/ReturnArgument.php',
+    'PHPUnit\\Framework\\MockObject\\Stub\\ReturnCallback' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Stub/ReturnCallback.php',
+    'PHPUnit\\Framework\\MockObject\\Stub\\ReturnReference' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Stub/ReturnReference.php',
+    'PHPUnit\\Framework\\MockObject\\Stub\\ReturnSelf' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Stub/ReturnSelf.php',
+    'PHPUnit\\Framework\\MockObject\\Stub\\ReturnStub' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Stub/ReturnStub.php',
+    'PHPUnit\\Framework\\MockObject\\Stub\\ReturnValueMap' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Stub/ReturnValueMap.php',
+    'PHPUnit\\Framework\\MockObject\\Stub\\Stub' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Stub/Stub.php',
+    'PHPUnit\\Framework\\MockObject\\UnknownClassException' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Exception/UnknownClassException.php',
+    'PHPUnit\\Framework\\MockObject\\UnknownTraitException' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Exception/UnknownTraitException.php',
+    'PHPUnit\\Framework\\MockObject\\UnknownTypeException' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Exception/UnknownTypeException.php',
+    'PHPUnit\\Framework\\MockObject\\UnmockedCloneMethod' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Api/UnmockedCloneMethod.php',
+    'PHPUnit\\Framework\\MockObject\\Verifiable' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Verifiable.php',
+    'PHPUnit\\Framework\\NoChildTestSuiteException' => $vendorDir . '/phpunit/phpunit/src/Framework/Exception/NoChildTestSuiteException.php',
+    'PHPUnit\\Framework\\OutputError' => $vendorDir . '/phpunit/phpunit/src/Framework/Exception/OutputError.php',
+    'PHPUnit\\Framework\\PHPTAssertionFailedError' => $vendorDir . '/phpunit/phpunit/src/Framework/Exception/PHPTAssertionFailedError.php',
+    'PHPUnit\\Framework\\Reorderable' => $vendorDir . '/phpunit/phpunit/src/Framework/Reorderable.php',
+    'PHPUnit\\Framework\\RiskyTestError' => $vendorDir . '/phpunit/phpunit/src/Framework/Exception/RiskyTestError.php',
+    'PHPUnit\\Framework\\SelfDescribing' => $vendorDir . '/phpunit/phpunit/src/Framework/SelfDescribing.php',
+    'PHPUnit\\Framework\\SkippedTest' => $vendorDir . '/phpunit/phpunit/src/Framework/SkippedTest.php',
+    'PHPUnit\\Framework\\SkippedTestCase' => $vendorDir . '/phpunit/phpunit/src/Framework/SkippedTestCase.php',
+    'PHPUnit\\Framework\\SkippedTestError' => $vendorDir . '/phpunit/phpunit/src/Framework/Exception/SkippedTestError.php',
+    'PHPUnit\\Framework\\SkippedTestSuiteError' => $vendorDir . '/phpunit/phpunit/src/Framework/Exception/SkippedTestSuiteError.php',
+    'PHPUnit\\Framework\\SyntheticError' => $vendorDir . '/phpunit/phpunit/src/Framework/Exception/SyntheticError.php',
+    'PHPUnit\\Framework\\SyntheticSkippedError' => $vendorDir . '/phpunit/phpunit/src/Framework/Exception/SyntheticSkippedError.php',
+    'PHPUnit\\Framework\\Test' => $vendorDir . '/phpunit/phpunit/src/Framework/Test.php',
+    'PHPUnit\\Framework\\TestBuilder' => $vendorDir . '/phpunit/phpunit/src/Framework/TestBuilder.php',
+    'PHPUnit\\Framework\\TestCase' => $vendorDir . '/phpunit/phpunit/src/Framework/TestCase.php',
+    'PHPUnit\\Framework\\TestFailure' => $vendorDir . '/phpunit/phpunit/src/Framework/TestFailure.php',
+    'PHPUnit\\Framework\\TestListener' => $vendorDir . '/phpunit/phpunit/src/Framework/TestListener.php',
+    'PHPUnit\\Framework\\TestListenerDefaultImplementation' => $vendorDir . '/phpunit/phpunit/src/Framework/TestListenerDefaultImplementation.php',
+    'PHPUnit\\Framework\\TestResult' => $vendorDir . '/phpunit/phpunit/src/Framework/TestResult.php',
+    'PHPUnit\\Framework\\TestSuite' => $vendorDir . '/phpunit/phpunit/src/Framework/TestSuite.php',
+    'PHPUnit\\Framework\\TestSuiteIterator' => $vendorDir . '/phpunit/phpunit/src/Framework/TestSuiteIterator.php',
+    'PHPUnit\\Framework\\UnintentionallyCoveredCodeError' => $vendorDir . '/phpunit/phpunit/src/Framework/Exception/UnintentionallyCoveredCodeError.php',
+    'PHPUnit\\Framework\\Warning' => $vendorDir . '/phpunit/phpunit/src/Framework/Exception/Warning.php',
+    'PHPUnit\\Framework\\WarningTestCase' => $vendorDir . '/phpunit/phpunit/src/Framework/WarningTestCase.php',
+    'PHPUnit\\Runner\\AfterIncompleteTestHook' => $vendorDir . '/phpunit/phpunit/src/Runner/Hook/AfterIncompleteTestHook.php',
+    'PHPUnit\\Runner\\AfterLastTestHook' => $vendorDir . '/phpunit/phpunit/src/Runner/Hook/AfterLastTestHook.php',
+    'PHPUnit\\Runner\\AfterRiskyTestHook' => $vendorDir . '/phpunit/phpunit/src/Runner/Hook/AfterRiskyTestHook.php',
+    'PHPUnit\\Runner\\AfterSkippedTestHook' => $vendorDir . '/phpunit/phpunit/src/Runner/Hook/AfterSkippedTestHook.php',
+    'PHPUnit\\Runner\\AfterSuccessfulTestHook' => $vendorDir . '/phpunit/phpunit/src/Runner/Hook/AfterSuccessfulTestHook.php',
+    'PHPUnit\\Runner\\AfterTestErrorHook' => $vendorDir . '/phpunit/phpunit/src/Runner/Hook/AfterTestErrorHook.php',
+    'PHPUnit\\Runner\\AfterTestFailureHook' => $vendorDir . '/phpunit/phpunit/src/Runner/Hook/AfterTestFailureHook.php',
+    'PHPUnit\\Runner\\AfterTestHook' => $vendorDir . '/phpunit/phpunit/src/Runner/Hook/AfterTestHook.php',
+    'PHPUnit\\Runner\\AfterTestWarningHook' => $vendorDir . '/phpunit/phpunit/src/Runner/Hook/AfterTestWarningHook.php',
+    'PHPUnit\\Runner\\BaseTestRunner' => $vendorDir . '/phpunit/phpunit/src/Runner/BaseTestRunner.php',
+    'PHPUnit\\Runner\\BeforeFirstTestHook' => $vendorDir . '/phpunit/phpunit/src/Runner/Hook/BeforeFirstTestHook.php',
+    'PHPUnit\\Runner\\BeforeTestHook' => $vendorDir . '/phpunit/phpunit/src/Runner/Hook/BeforeTestHook.php',
+    'PHPUnit\\Runner\\DefaultTestResultCache' => $vendorDir . '/phpunit/phpunit/src/Runner/DefaultTestResultCache.php',
+    'PHPUnit\\Runner\\Exception' => $vendorDir . '/phpunit/phpunit/src/Runner/Exception.php',
+    'PHPUnit\\Runner\\Extension\\ExtensionHandler' => $vendorDir . '/phpunit/phpunit/src/Runner/Extension/ExtensionHandler.php',
+    'PHPUnit\\Runner\\Extension\\PharLoader' => $vendorDir . '/phpunit/phpunit/src/Runner/Extension/PharLoader.php',
+    'PHPUnit\\Runner\\Filter\\ExcludeGroupFilterIterator' => $vendorDir . '/phpunit/phpunit/src/Runner/Filter/ExcludeGroupFilterIterator.php',
+    'PHPUnit\\Runner\\Filter\\Factory' => $vendorDir . '/phpunit/phpunit/src/Runner/Filter/Factory.php',
+    'PHPUnit\\Runner\\Filter\\GroupFilterIterator' => $vendorDir . '/phpunit/phpunit/src/Runner/Filter/GroupFilterIterator.php',
+    'PHPUnit\\Runner\\Filter\\IncludeGroupFilterIterator' => $vendorDir . '/phpunit/phpunit/src/Runner/Filter/IncludeGroupFilterIterator.php',
+    'PHPUnit\\Runner\\Filter\\NameFilterIterator' => $vendorDir . '/phpunit/phpunit/src/Runner/Filter/NameFilterIterator.php',
+    'PHPUnit\\Runner\\Hook' => $vendorDir . '/phpunit/phpunit/src/Runner/Hook/Hook.php',
+    'PHPUnit\\Runner\\NullTestResultCache' => $vendorDir . '/phpunit/phpunit/src/Runner/NullTestResultCache.php',
+    'PHPUnit\\Runner\\PhptTestCase' => $vendorDir . '/phpunit/phpunit/src/Runner/PhptTestCase.php',
+    'PHPUnit\\Runner\\ResultCacheExtension' => $vendorDir . '/phpunit/phpunit/src/Runner/ResultCacheExtension.php',
+    'PHPUnit\\Runner\\StandardTestSuiteLoader' => $vendorDir . '/phpunit/phpunit/src/Runner/StandardTestSuiteLoader.php',
+    'PHPUnit\\Runner\\TestHook' => $vendorDir . '/phpunit/phpunit/src/Runner/Hook/TestHook.php',
+    'PHPUnit\\Runner\\TestListenerAdapter' => $vendorDir . '/phpunit/phpunit/src/Runner/Hook/TestListenerAdapter.php',
+    'PHPUnit\\Runner\\TestResultCache' => $vendorDir . '/phpunit/phpunit/src/Runner/TestResultCache.php',
+    'PHPUnit\\Runner\\TestSuiteLoader' => $vendorDir . '/phpunit/phpunit/src/Runner/TestSuiteLoader.php',
+    'PHPUnit\\Runner\\TestSuiteSorter' => $vendorDir . '/phpunit/phpunit/src/Runner/TestSuiteSorter.php',
+    'PHPUnit\\Runner\\Version' => $vendorDir . '/phpunit/phpunit/src/Runner/Version.php',
+    'PHPUnit\\TextUI\\CliArguments\\Builder' => $vendorDir . '/phpunit/phpunit/src/TextUI/CliArguments/Builder.php',
+    'PHPUnit\\TextUI\\CliArguments\\Configuration' => $vendorDir . '/phpunit/phpunit/src/TextUI/CliArguments/Configuration.php',
+    'PHPUnit\\TextUI\\CliArguments\\Exception' => $vendorDir . '/phpunit/phpunit/src/TextUI/CliArguments/Exception.php',
+    'PHPUnit\\TextUI\\CliArguments\\Mapper' => $vendorDir . '/phpunit/phpunit/src/TextUI/CliArguments/Mapper.php',
+    'PHPUnit\\TextUI\\Command' => $vendorDir . '/phpunit/phpunit/src/TextUI/Command.php',
+    'PHPUnit\\TextUI\\DefaultResultPrinter' => $vendorDir . '/phpunit/phpunit/src/TextUI/DefaultResultPrinter.php',
+    'PHPUnit\\TextUI\\Exception' => $vendorDir . '/phpunit/phpunit/src/TextUI/Exception/Exception.php',
+    'PHPUnit\\TextUI\\Help' => $vendorDir . '/phpunit/phpunit/src/TextUI/Help.php',
+    'PHPUnit\\TextUI\\ReflectionException' => $vendorDir . '/phpunit/phpunit/src/TextUI/Exception/ReflectionException.php',
+    'PHPUnit\\TextUI\\ResultPrinter' => $vendorDir . '/phpunit/phpunit/src/TextUI/ResultPrinter.php',
+    'PHPUnit\\TextUI\\RuntimeException' => $vendorDir . '/phpunit/phpunit/src/TextUI/Exception/RuntimeException.php',
+    'PHPUnit\\TextUI\\TestDirectoryNotFoundException' => $vendorDir . '/phpunit/phpunit/src/TextUI/Exception/TestDirectoryNotFoundException.php',
+    'PHPUnit\\TextUI\\TestFileNotFoundException' => $vendorDir . '/phpunit/phpunit/src/TextUI/Exception/TestFileNotFoundException.php',
+    'PHPUnit\\TextUI\\TestRunner' => $vendorDir . '/phpunit/phpunit/src/TextUI/TestRunner.php',
+    'PHPUnit\\TextUI\\TestSuiteMapper' => $vendorDir . '/phpunit/phpunit/src/TextUI/TestSuiteMapper.php',
+    'PHPUnit\\TextUI\\XmlConfiguration\\CodeCoverage\\CodeCoverage' => $vendorDir . '/phpunit/phpunit/src/TextUI/XmlConfiguration/CodeCoverage/CodeCoverage.php',
+    'PHPUnit\\TextUI\\XmlConfiguration\\CodeCoverage\\FilterMapper' => $vendorDir . '/phpunit/phpunit/src/TextUI/XmlConfiguration/CodeCoverage/FilterMapper.php',
+    'PHPUnit\\TextUI\\XmlConfiguration\\CodeCoverage\\Filter\\Directory' => $vendorDir . '/phpunit/phpunit/src/TextUI/XmlConfiguration/CodeCoverage/Filter/Directory.php',
+    'PHPUnit\\TextUI\\XmlConfiguration\\CodeCoverage\\Filter\\DirectoryCollection' => $vendorDir . '/phpunit/phpunit/src/TextUI/XmlConfiguration/CodeCoverage/Filter/DirectoryCollection.php',
+    'PHPUnit\\TextUI\\XmlConfiguration\\CodeCoverage\\Filter\\DirectoryCollectionIterator' => $vendorDir . '/phpunit/phpunit/src/TextUI/XmlConfiguration/CodeCoverage/Filter/DirectoryCollectionIterator.php',
+    'PHPUnit\\TextUI\\XmlConfiguration\\CodeCoverage\\Report\\Clover' => $vendorDir . '/phpunit/phpunit/src/TextUI/XmlConfiguration/CodeCoverage/Report/Clover.php',
+    'PHPUnit\\TextUI\\XmlConfiguration\\CodeCoverage\\Report\\Cobertura' => $vendorDir . '/phpunit/phpunit/src/TextUI/XmlConfiguration/CodeCoverage/Report/Cobertura.php',
+    'PHPUnit\\TextUI\\XmlConfiguration\\CodeCoverage\\Report\\Crap4j' => $vendorDir . '/phpunit/phpunit/src/TextUI/XmlConfiguration/CodeCoverage/Report/Crap4j.php',
+    'PHPUnit\\TextUI\\XmlConfiguration\\CodeCoverage\\Report\\Html' => $vendorDir . '/phpunit/phpunit/src/TextUI/XmlConfiguration/CodeCoverage/Report/Html.php',
+    'PHPUnit\\TextUI\\XmlConfiguration\\CodeCoverage\\Report\\Php' => $vendorDir . '/phpunit/phpunit/src/TextUI/XmlConfiguration/CodeCoverage/Report/Php.php',
+    'PHPUnit\\TextUI\\XmlConfiguration\\CodeCoverage\\Report\\Text' => $vendorDir . '/phpunit/phpunit/src/TextUI/XmlConfiguration/CodeCoverage/Report/Text.php',
+    'PHPUnit\\TextUI\\XmlConfiguration\\CodeCoverage\\Report\\Xml' => $vendorDir . '/phpunit/phpunit/src/TextUI/XmlConfiguration/CodeCoverage/Report/Xml.php',
+    'PHPUnit\\TextUI\\XmlConfiguration\\Configuration' => $vendorDir . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Configuration.php',
+    'PHPUnit\\TextUI\\XmlConfiguration\\Constant' => $vendorDir . '/phpunit/phpunit/src/TextUI/XmlConfiguration/PHP/Constant.php',
+    'PHPUnit\\TextUI\\XmlConfiguration\\ConstantCollection' => $vendorDir . '/phpunit/phpunit/src/TextUI/XmlConfiguration/PHP/ConstantCollection.php',
+    'PHPUnit\\TextUI\\XmlConfiguration\\ConstantCollectionIterator' => $vendorDir . '/phpunit/phpunit/src/TextUI/XmlConfiguration/PHP/ConstantCollectionIterator.php',
+    'PHPUnit\\TextUI\\XmlConfiguration\\ConvertLogTypes' => $vendorDir . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/ConvertLogTypes.php',
+    'PHPUnit\\TextUI\\XmlConfiguration\\CoverageCloverToReport' => $vendorDir . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/CoverageCloverToReport.php',
+    'PHPUnit\\TextUI\\XmlConfiguration\\CoverageCrap4jToReport' => $vendorDir . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/CoverageCrap4jToReport.php',
+    'PHPUnit\\TextUI\\XmlConfiguration\\CoverageHtmlToReport' => $vendorDir . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/CoverageHtmlToReport.php',
+    'PHPUnit\\TextUI\\XmlConfiguration\\CoveragePhpToReport' => $vendorDir . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/CoveragePhpToReport.php',
+    'PHPUnit\\TextUI\\XmlConfiguration\\CoverageTextToReport' => $vendorDir . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/CoverageTextToReport.php',
+    'PHPUnit\\TextUI\\XmlConfiguration\\CoverageXmlToReport' => $vendorDir . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/CoverageXmlToReport.php',
+    'PHPUnit\\TextUI\\XmlConfiguration\\Directory' => $vendorDir . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Filesystem/Directory.php',
+    'PHPUnit\\TextUI\\XmlConfiguration\\DirectoryCollection' => $vendorDir . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Filesystem/DirectoryCollection.php',
+    'PHPUnit\\TextUI\\XmlConfiguration\\DirectoryCollectionIterator' => $vendorDir . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Filesystem/DirectoryCollectionIterator.php',
+    'PHPUnit\\TextUI\\XmlConfiguration\\Exception' => $vendorDir . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Exception.php',
+    'PHPUnit\\TextUI\\XmlConfiguration\\Extension' => $vendorDir . '/phpunit/phpunit/src/TextUI/XmlConfiguration/PHPUnit/Extension.php',
+    'PHPUnit\\TextUI\\XmlConfiguration\\ExtensionCollection' => $vendorDir . '/phpunit/phpunit/src/TextUI/XmlConfiguration/PHPUnit/ExtensionCollection.php',
+    'PHPUnit\\TextUI\\XmlConfiguration\\ExtensionCollectionIterator' => $vendorDir . '/phpunit/phpunit/src/TextUI/XmlConfiguration/PHPUnit/ExtensionCollectionIterator.php',
+    'PHPUnit\\TextUI\\XmlConfiguration\\File' => $vendorDir . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Filesystem/File.php',
+    'PHPUnit\\TextUI\\XmlConfiguration\\FileCollection' => $vendorDir . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Filesystem/FileCollection.php',
+    'PHPUnit\\TextUI\\XmlConfiguration\\FileCollectionIterator' => $vendorDir . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Filesystem/FileCollectionIterator.php',
+    'PHPUnit\\TextUI\\XmlConfiguration\\Generator' => $vendorDir . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Generator.php',
+    'PHPUnit\\TextUI\\XmlConfiguration\\Group' => $vendorDir . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Group/Group.php',
+    'PHPUnit\\TextUI\\XmlConfiguration\\GroupCollection' => $vendorDir . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Group/GroupCollection.php',
+    'PHPUnit\\TextUI\\XmlConfiguration\\GroupCollectionIterator' => $vendorDir . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Group/GroupCollectionIterator.php',
+    'PHPUnit\\TextUI\\XmlConfiguration\\Groups' => $vendorDir . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Group/Groups.php',
+    'PHPUnit\\TextUI\\XmlConfiguration\\IniSetting' => $vendorDir . '/phpunit/phpunit/src/TextUI/XmlConfiguration/PHP/IniSetting.php',
+    'PHPUnit\\TextUI\\XmlConfiguration\\IniSettingCollection' => $vendorDir . '/phpunit/phpunit/src/TextUI/XmlConfiguration/PHP/IniSettingCollection.php',
+    'PHPUnit\\TextUI\\XmlConfiguration\\IniSettingCollectionIterator' => $vendorDir . '/phpunit/phpunit/src/TextUI/XmlConfiguration/PHP/IniSettingCollectionIterator.php',
+    'PHPUnit\\TextUI\\XmlConfiguration\\IntroduceCoverageElement' => $vendorDir . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/IntroduceCoverageElement.php',
+    'PHPUnit\\TextUI\\XmlConfiguration\\Loader' => $vendorDir . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Loader.php',
+    'PHPUnit\\TextUI\\XmlConfiguration\\LogToReportMigration' => $vendorDir . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/LogToReportMigration.php',
+    'PHPUnit\\TextUI\\XmlConfiguration\\Logging\\Junit' => $vendorDir . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Logging/Junit.php',
+    'PHPUnit\\TextUI\\XmlConfiguration\\Logging\\Logging' => $vendorDir . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Logging/Logging.php',
+    'PHPUnit\\TextUI\\XmlConfiguration\\Logging\\TeamCity' => $vendorDir . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Logging/TeamCity.php',
+    'PHPUnit\\TextUI\\XmlConfiguration\\Logging\\TestDox\\Html' => $vendorDir . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Logging/TestDox/Html.php',
+    'PHPUnit\\TextUI\\XmlConfiguration\\Logging\\TestDox\\Text' => $vendorDir . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Logging/TestDox/Text.php',
+    'PHPUnit\\TextUI\\XmlConfiguration\\Logging\\TestDox\\Xml' => $vendorDir . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Logging/TestDox/Xml.php',
+    'PHPUnit\\TextUI\\XmlConfiguration\\Logging\\Text' => $vendorDir . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Logging/Text.php',
+    'PHPUnit\\TextUI\\XmlConfiguration\\Migration' => $vendorDir . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/Migration.php',
+    'PHPUnit\\TextUI\\XmlConfiguration\\MigrationBuilder' => $vendorDir . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/MigrationBuilder.php',
+    'PHPUnit\\TextUI\\XmlConfiguration\\MigrationBuilderException' => $vendorDir . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/MigrationBuilderException.php',
+    'PHPUnit\\TextUI\\XmlConfiguration\\MigrationException' => $vendorDir . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/MigrationException.php',
+    'PHPUnit\\TextUI\\XmlConfiguration\\Migrator' => $vendorDir . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrator.php',
+    'PHPUnit\\TextUI\\XmlConfiguration\\MoveAttributesFromFilterWhitelistToCoverage' => $vendorDir . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/MoveAttributesFromFilterWhitelistToCoverage.php',
+    'PHPUnit\\TextUI\\XmlConfiguration\\MoveAttributesFromRootToCoverage' => $vendorDir . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/MoveAttributesFromRootToCoverage.php',
+    'PHPUnit\\TextUI\\XmlConfiguration\\MoveWhitelistDirectoriesToCoverage' => $vendorDir . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/MoveWhitelistDirectoriesToCoverage.php',
+    'PHPUnit\\TextUI\\XmlConfiguration\\MoveWhitelistExcludesToCoverage' => $vendorDir . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/MoveWhitelistExcludesToCoverage.php',
+    'PHPUnit\\TextUI\\XmlConfiguration\\PHPUnit' => $vendorDir . '/phpunit/phpunit/src/TextUI/XmlConfiguration/PHPUnit/PHPUnit.php',
+    'PHPUnit\\TextUI\\XmlConfiguration\\Php' => $vendorDir . '/phpunit/phpunit/src/TextUI/XmlConfiguration/PHP/Php.php',
+    'PHPUnit\\TextUI\\XmlConfiguration\\PhpHandler' => $vendorDir . '/phpunit/phpunit/src/TextUI/XmlConfiguration/PHP/PhpHandler.php',
+    'PHPUnit\\TextUI\\XmlConfiguration\\RemoveCacheTokensAttribute' => $vendorDir . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/RemoveCacheTokensAttribute.php',
+    'PHPUnit\\TextUI\\XmlConfiguration\\RemoveEmptyFilter' => $vendorDir . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/RemoveEmptyFilter.php',
+    'PHPUnit\\TextUI\\XmlConfiguration\\RemoveLogTypes' => $vendorDir . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/RemoveLogTypes.php',
+    'PHPUnit\\TextUI\\XmlConfiguration\\TestDirectory' => $vendorDir . '/phpunit/phpunit/src/TextUI/XmlConfiguration/TestSuite/TestDirectory.php',
+    'PHPUnit\\TextUI\\XmlConfiguration\\TestDirectoryCollection' => $vendorDir . '/phpunit/phpunit/src/TextUI/XmlConfiguration/TestSuite/TestDirectoryCollection.php',
+    'PHPUnit\\TextUI\\XmlConfiguration\\TestDirectoryCollectionIterator' => $vendorDir . '/phpunit/phpunit/src/TextUI/XmlConfiguration/TestSuite/TestDirectoryCollectionIterator.php',
+    'PHPUnit\\TextUI\\XmlConfiguration\\TestFile' => $vendorDir . '/phpunit/phpunit/src/TextUI/XmlConfiguration/TestSuite/TestFile.php',
+    'PHPUnit\\TextUI\\XmlConfiguration\\TestFileCollection' => $vendorDir . '/phpunit/phpunit/src/TextUI/XmlConfiguration/TestSuite/TestFileCollection.php',
+    'PHPUnit\\TextUI\\XmlConfiguration\\TestFileCollectionIterator' => $vendorDir . '/phpunit/phpunit/src/TextUI/XmlConfiguration/TestSuite/TestFileCollectionIterator.php',
+    'PHPUnit\\TextUI\\XmlConfiguration\\TestSuite' => $vendorDir . '/phpunit/phpunit/src/TextUI/XmlConfiguration/TestSuite/TestSuite.php',
+    'PHPUnit\\TextUI\\XmlConfiguration\\TestSuiteCollection' => $vendorDir . '/phpunit/phpunit/src/TextUI/XmlConfiguration/TestSuite/TestSuiteCollection.php',
+    'PHPUnit\\TextUI\\XmlConfiguration\\TestSuiteCollectionIterator' => $vendorDir . '/phpunit/phpunit/src/TextUI/XmlConfiguration/TestSuite/TestSuiteCollectionIterator.php',
+    'PHPUnit\\TextUI\\XmlConfiguration\\UpdateSchemaLocationTo93' => $vendorDir . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/UpdateSchemaLocationTo93.php',
+    'PHPUnit\\TextUI\\XmlConfiguration\\Variable' => $vendorDir . '/phpunit/phpunit/src/TextUI/XmlConfiguration/PHP/Variable.php',
+    'PHPUnit\\TextUI\\XmlConfiguration\\VariableCollection' => $vendorDir . '/phpunit/phpunit/src/TextUI/XmlConfiguration/PHP/VariableCollection.php',
+    'PHPUnit\\TextUI\\XmlConfiguration\\VariableCollectionIterator' => $vendorDir . '/phpunit/phpunit/src/TextUI/XmlConfiguration/PHP/VariableCollectionIterator.php',
+    'PHPUnit\\Util\\Annotation\\DocBlock' => $vendorDir . '/phpunit/phpunit/src/Util/Annotation/DocBlock.php',
+    'PHPUnit\\Util\\Annotation\\Registry' => $vendorDir . '/phpunit/phpunit/src/Util/Annotation/Registry.php',
+    'PHPUnit\\Util\\Blacklist' => $vendorDir . '/phpunit/phpunit/src/Util/Blacklist.php',
+    'PHPUnit\\Util\\Color' => $vendorDir . '/phpunit/phpunit/src/Util/Color.php',
+    'PHPUnit\\Util\\ErrorHandler' => $vendorDir . '/phpunit/phpunit/src/Util/ErrorHandler.php',
+    'PHPUnit\\Util\\Exception' => $vendorDir . '/phpunit/phpunit/src/Util/Exception.php',
+    'PHPUnit\\Util\\ExcludeList' => $vendorDir . '/phpunit/phpunit/src/Util/ExcludeList.php',
+    'PHPUnit\\Util\\FileLoader' => $vendorDir . '/phpunit/phpunit/src/Util/FileLoader.php',
+    'PHPUnit\\Util\\Filesystem' => $vendorDir . '/phpunit/phpunit/src/Util/Filesystem.php',
+    'PHPUnit\\Util\\Filter' => $vendorDir . '/phpunit/phpunit/src/Util/Filter.php',
+    'PHPUnit\\Util\\GlobalState' => $vendorDir . '/phpunit/phpunit/src/Util/GlobalState.php',
+    'PHPUnit\\Util\\InvalidDataSetException' => $vendorDir . '/phpunit/phpunit/src/Util/InvalidDataSetException.php',
+    'PHPUnit\\Util\\Json' => $vendorDir . '/phpunit/phpunit/src/Util/Json.php',
+    'PHPUnit\\Util\\Log\\JUnit' => $vendorDir . '/phpunit/phpunit/src/Util/Log/JUnit.php',
+    'PHPUnit\\Util\\Log\\TeamCity' => $vendorDir . '/phpunit/phpunit/src/Util/Log/TeamCity.php',
+    'PHPUnit\\Util\\PHP\\AbstractPhpProcess' => $vendorDir . '/phpunit/phpunit/src/Util/PHP/AbstractPhpProcess.php',
+    'PHPUnit\\Util\\PHP\\DefaultPhpProcess' => $vendorDir . '/phpunit/phpunit/src/Util/PHP/DefaultPhpProcess.php',
+    'PHPUnit\\Util\\PHP\\WindowsPhpProcess' => $vendorDir . '/phpunit/phpunit/src/Util/PHP/WindowsPhpProcess.php',
+    'PHPUnit\\Util\\Printer' => $vendorDir . '/phpunit/phpunit/src/Util/Printer.php',
+    'PHPUnit\\Util\\RegularExpression' => $vendorDir . '/phpunit/phpunit/src/Util/RegularExpression.php',
+    'PHPUnit\\Util\\Test' => $vendorDir . '/phpunit/phpunit/src/Util/Test.php',
+    'PHPUnit\\Util\\TestDox\\CliTestDoxPrinter' => $vendorDir . '/phpunit/phpunit/src/Util/TestDox/CliTestDoxPrinter.php',
+    'PHPUnit\\Util\\TestDox\\HtmlResultPrinter' => $vendorDir . '/phpunit/phpunit/src/Util/TestDox/HtmlResultPrinter.php',
+    'PHPUnit\\Util\\TestDox\\NamePrettifier' => $vendorDir . '/phpunit/phpunit/src/Util/TestDox/NamePrettifier.php',
+    'PHPUnit\\Util\\TestDox\\ResultPrinter' => $vendorDir . '/phpunit/phpunit/src/Util/TestDox/ResultPrinter.php',
+    'PHPUnit\\Util\\TestDox\\TestDoxPrinter' => $vendorDir . '/phpunit/phpunit/src/Util/TestDox/TestDoxPrinter.php',
+    'PHPUnit\\Util\\TestDox\\TextResultPrinter' => $vendorDir . '/phpunit/phpunit/src/Util/TestDox/TextResultPrinter.php',
+    'PHPUnit\\Util\\TestDox\\XmlResultPrinter' => $vendorDir . '/phpunit/phpunit/src/Util/TestDox/XmlResultPrinter.php',
+    'PHPUnit\\Util\\TextTestListRenderer' => $vendorDir . '/phpunit/phpunit/src/Util/TextTestListRenderer.php',
+    'PHPUnit\\Util\\Type' => $vendorDir . '/phpunit/phpunit/src/Util/Type.php',
+    'PHPUnit\\Util\\VersionComparisonOperator' => $vendorDir . '/phpunit/phpunit/src/Util/VersionComparisonOperator.php',
+    'PHPUnit\\Util\\XdebugFilterScriptGenerator' => $vendorDir . '/phpunit/phpunit/src/Util/XdebugFilterScriptGenerator.php',
+    'PHPUnit\\Util\\Xml' => $vendorDir . '/phpunit/phpunit/src/Util/Xml.php',
+    'PHPUnit\\Util\\XmlTestListRenderer' => $vendorDir . '/phpunit/phpunit/src/Util/XmlTestListRenderer.php',
+    'PHPUnit\\Util\\Xml\\Exception' => $vendorDir . '/phpunit/phpunit/src/Util/Xml/Exception.php',
+    'PHPUnit\\Util\\Xml\\FailedSchemaDetectionResult' => $vendorDir . '/phpunit/phpunit/src/Util/Xml/FailedSchemaDetectionResult.php',
+    'PHPUnit\\Util\\Xml\\Loader' => $vendorDir . '/phpunit/phpunit/src/Util/Xml/Loader.php',
+    'PHPUnit\\Util\\Xml\\SchemaDetectionResult' => $vendorDir . '/phpunit/phpunit/src/Util/Xml/SchemaDetectionResult.php',
+    'PHPUnit\\Util\\Xml\\SchemaDetector' => $vendorDir . '/phpunit/phpunit/src/Util/Xml/SchemaDetector.php',
+    'PHPUnit\\Util\\Xml\\SchemaFinder' => $vendorDir . '/phpunit/phpunit/src/Util/Xml/SchemaFinder.php',
+    'PHPUnit\\Util\\Xml\\SnapshotNodeList' => $vendorDir . '/phpunit/phpunit/src/Util/Xml/SnapshotNodeList.php',
+    'PHPUnit\\Util\\Xml\\SuccessfulSchemaDetectionResult' => $vendorDir . '/phpunit/phpunit/src/Util/Xml/SuccessfulSchemaDetectionResult.php',
+    'PHPUnit\\Util\\Xml\\ValidationResult' => $vendorDir . '/phpunit/phpunit/src/Util/Xml/ValidationResult.php',
+    'PHPUnit\\Util\\Xml\\Validator' => $vendorDir . '/phpunit/phpunit/src/Util/Xml/Validator.php',
+    'PharIo\\Manifest\\Application' => $vendorDir . '/phar-io/manifest/src/values/Application.php',
+    'PharIo\\Manifest\\ApplicationName' => $vendorDir . '/phar-io/manifest/src/values/ApplicationName.php',
+    'PharIo\\Manifest\\Author' => $vendorDir . '/phar-io/manifest/src/values/Author.php',
+    'PharIo\\Manifest\\AuthorCollection' => $vendorDir . '/phar-io/manifest/src/values/AuthorCollection.php',
+    'PharIo\\Manifest\\AuthorCollectionIterator' => $vendorDir . '/phar-io/manifest/src/values/AuthorCollectionIterator.php',
+    'PharIo\\Manifest\\AuthorElement' => $vendorDir . '/phar-io/manifest/src/xml/AuthorElement.php',
+    'PharIo\\Manifest\\AuthorElementCollection' => $vendorDir . '/phar-io/manifest/src/xml/AuthorElementCollection.php',
+    'PharIo\\Manifest\\BundledComponent' => $vendorDir . '/phar-io/manifest/src/values/BundledComponent.php',
+    'PharIo\\Manifest\\BundledComponentCollection' => $vendorDir . '/phar-io/manifest/src/values/BundledComponentCollection.php',
+    'PharIo\\Manifest\\BundledComponentCollectionIterator' => $vendorDir . '/phar-io/manifest/src/values/BundledComponentCollectionIterator.php',
+    'PharIo\\Manifest\\BundlesElement' => $vendorDir . '/phar-io/manifest/src/xml/BundlesElement.php',
+    'PharIo\\Manifest\\ComponentElement' => $vendorDir . '/phar-io/manifest/src/xml/ComponentElement.php',
+    'PharIo\\Manifest\\ComponentElementCollection' => $vendorDir . '/phar-io/manifest/src/xml/ComponentElementCollection.php',
+    'PharIo\\Manifest\\ContainsElement' => $vendorDir . '/phar-io/manifest/src/xml/ContainsElement.php',
+    'PharIo\\Manifest\\CopyrightElement' => $vendorDir . '/phar-io/manifest/src/xml/CopyrightElement.php',
+    'PharIo\\Manifest\\CopyrightInformation' => $vendorDir . '/phar-io/manifest/src/values/CopyrightInformation.php',
+    'PharIo\\Manifest\\ElementCollection' => $vendorDir . '/phar-io/manifest/src/xml/ElementCollection.php',
+    'PharIo\\Manifest\\ElementCollectionException' => $vendorDir . '/phar-io/manifest/src/exceptions/ElementCollectionException.php',
+    'PharIo\\Manifest\\Email' => $vendorDir . '/phar-io/manifest/src/values/Email.php',
+    'PharIo\\Manifest\\Exception' => $vendorDir . '/phar-io/manifest/src/exceptions/Exception.php',
+    'PharIo\\Manifest\\ExtElement' => $vendorDir . '/phar-io/manifest/src/xml/ExtElement.php',
+    'PharIo\\Manifest\\ExtElementCollection' => $vendorDir . '/phar-io/manifest/src/xml/ExtElementCollection.php',
+    'PharIo\\Manifest\\Extension' => $vendorDir . '/phar-io/manifest/src/values/Extension.php',
+    'PharIo\\Manifest\\ExtensionElement' => $vendorDir . '/phar-io/manifest/src/xml/ExtensionElement.php',
+    'PharIo\\Manifest\\InvalidApplicationNameException' => $vendorDir . '/phar-io/manifest/src/exceptions/InvalidApplicationNameException.php',
+    'PharIo\\Manifest\\InvalidEmailException' => $vendorDir . '/phar-io/manifest/src/exceptions/InvalidEmailException.php',
+    'PharIo\\Manifest\\InvalidUrlException' => $vendorDir . '/phar-io/manifest/src/exceptions/InvalidUrlException.php',
+    'PharIo\\Manifest\\Library' => $vendorDir . '/phar-io/manifest/src/values/Library.php',
+    'PharIo\\Manifest\\License' => $vendorDir . '/phar-io/manifest/src/values/License.php',
+    'PharIo\\Manifest\\LicenseElement' => $vendorDir . '/phar-io/manifest/src/xml/LicenseElement.php',
+    'PharIo\\Manifest\\Manifest' => $vendorDir . '/phar-io/manifest/src/values/Manifest.php',
+    'PharIo\\Manifest\\ManifestDocument' => $vendorDir . '/phar-io/manifest/src/xml/ManifestDocument.php',
+    'PharIo\\Manifest\\ManifestDocumentException' => $vendorDir . '/phar-io/manifest/src/exceptions/ManifestDocumentException.php',
+    'PharIo\\Manifest\\ManifestDocumentLoadingException' => $vendorDir . '/phar-io/manifest/src/exceptions/ManifestDocumentLoadingException.php',
+    'PharIo\\Manifest\\ManifestDocumentMapper' => $vendorDir . '/phar-io/manifest/src/ManifestDocumentMapper.php',
+    'PharIo\\Manifest\\ManifestDocumentMapperException' => $vendorDir . '/phar-io/manifest/src/exceptions/ManifestDocumentMapperException.php',
+    'PharIo\\Manifest\\ManifestElement' => $vendorDir . '/phar-io/manifest/src/xml/ManifestElement.php',
+    'PharIo\\Manifest\\ManifestElementException' => $vendorDir . '/phar-io/manifest/src/exceptions/ManifestElementException.php',
+    'PharIo\\Manifest\\ManifestLoader' => $vendorDir . '/phar-io/manifest/src/ManifestLoader.php',
+    'PharIo\\Manifest\\ManifestLoaderException' => $vendorDir . '/phar-io/manifest/src/exceptions/ManifestLoaderException.php',
+    'PharIo\\Manifest\\ManifestSerializer' => $vendorDir . '/phar-io/manifest/src/ManifestSerializer.php',
+    'PharIo\\Manifest\\PhpElement' => $vendorDir . '/phar-io/manifest/src/xml/PhpElement.php',
+    'PharIo\\Manifest\\PhpExtensionRequirement' => $vendorDir . '/phar-io/manifest/src/values/PhpExtensionRequirement.php',
+    'PharIo\\Manifest\\PhpVersionRequirement' => $vendorDir . '/phar-io/manifest/src/values/PhpVersionRequirement.php',
+    'PharIo\\Manifest\\Requirement' => $vendorDir . '/phar-io/manifest/src/values/Requirement.php',
+    'PharIo\\Manifest\\RequirementCollection' => $vendorDir . '/phar-io/manifest/src/values/RequirementCollection.php',
+    'PharIo\\Manifest\\RequirementCollectionIterator' => $vendorDir . '/phar-io/manifest/src/values/RequirementCollectionIterator.php',
+    'PharIo\\Manifest\\RequiresElement' => $vendorDir . '/phar-io/manifest/src/xml/RequiresElement.php',
+    'PharIo\\Manifest\\Type' => $vendorDir . '/phar-io/manifest/src/values/Type.php',
+    'PharIo\\Manifest\\Url' => $vendorDir . '/phar-io/manifest/src/values/Url.php',
+    'PharIo\\Version\\AbstractVersionConstraint' => $vendorDir . '/phar-io/version/src/constraints/AbstractVersionConstraint.php',
+    'PharIo\\Version\\AndVersionConstraintGroup' => $vendorDir . '/phar-io/version/src/constraints/AndVersionConstraintGroup.php',
+    'PharIo\\Version\\AnyVersionConstraint' => $vendorDir . '/phar-io/version/src/constraints/AnyVersionConstraint.php',
+    'PharIo\\Version\\ExactVersionConstraint' => $vendorDir . '/phar-io/version/src/constraints/ExactVersionConstraint.php',
+    'PharIo\\Version\\Exception' => $vendorDir . '/phar-io/version/src/exceptions/Exception.php',
+    'PharIo\\Version\\GreaterThanOrEqualToVersionConstraint' => $vendorDir . '/phar-io/version/src/constraints/GreaterThanOrEqualToVersionConstraint.php',
+    'PharIo\\Version\\InvalidPreReleaseSuffixException' => $vendorDir . '/phar-io/version/src/exceptions/InvalidPreReleaseSuffixException.php',
+    'PharIo\\Version\\InvalidVersionException' => $vendorDir . '/phar-io/version/src/exceptions/InvalidVersionException.php',
+    'PharIo\\Version\\NoPreReleaseSuffixException' => $vendorDir . '/phar-io/version/src/exceptions/NoPreReleaseSuffixException.php',
+    'PharIo\\Version\\OrVersionConstraintGroup' => $vendorDir . '/phar-io/version/src/constraints/OrVersionConstraintGroup.php',
+    'PharIo\\Version\\PreReleaseSuffix' => $vendorDir . '/phar-io/version/src/PreReleaseSuffix.php',
+    'PharIo\\Version\\SpecificMajorAndMinorVersionConstraint' => $vendorDir . '/phar-io/version/src/constraints/SpecificMajorAndMinorVersionConstraint.php',
+    'PharIo\\Version\\SpecificMajorVersionConstraint' => $vendorDir . '/phar-io/version/src/constraints/SpecificMajorVersionConstraint.php',
+    'PharIo\\Version\\UnsupportedVersionConstraintException' => $vendorDir . '/phar-io/version/src/exceptions/UnsupportedVersionConstraintException.php',
+    'PharIo\\Version\\Version' => $vendorDir . '/phar-io/version/src/Version.php',
+    'PharIo\\Version\\VersionConstraint' => $vendorDir . '/phar-io/version/src/constraints/VersionConstraint.php',
+    'PharIo\\Version\\VersionConstraintParser' => $vendorDir . '/phar-io/version/src/VersionConstraintParser.php',
+    'PharIo\\Version\\VersionConstraintValue' => $vendorDir . '/phar-io/version/src/VersionConstraintValue.php',
+    'PharIo\\Version\\VersionNumber' => $vendorDir . '/phar-io/version/src/VersionNumber.php',
     'QRcode' => $vendorDir . '/tecnickcom/tcpdf/include/barcodes/qrcode.php',
+    'SebastianBergmann\\CliParser\\AmbiguousOptionException' => $vendorDir . '/sebastian/cli-parser/src/exceptions/AmbiguousOptionException.php',
+    'SebastianBergmann\\CliParser\\Exception' => $vendorDir . '/sebastian/cli-parser/src/exceptions/Exception.php',
+    'SebastianBergmann\\CliParser\\OptionDoesNotAllowArgumentException' => $vendorDir . '/sebastian/cli-parser/src/exceptions/OptionDoesNotAllowArgumentException.php',
+    'SebastianBergmann\\CliParser\\Parser' => $vendorDir . '/sebastian/cli-parser/src/Parser.php',
+    'SebastianBergmann\\CliParser\\RequiredOptionArgumentMissingException' => $vendorDir . '/sebastian/cli-parser/src/exceptions/RequiredOptionArgumentMissingException.php',
+    'SebastianBergmann\\CliParser\\UnknownOptionException' => $vendorDir . '/sebastian/cli-parser/src/exceptions/UnknownOptionException.php',
+    'SebastianBergmann\\CodeCoverage\\BranchAndPathCoverageNotSupportedException' => $vendorDir . '/phpunit/php-code-coverage/src/Exception/BranchAndPathCoverageNotSupportedException.php',
+    'SebastianBergmann\\CodeCoverage\\CodeCoverage' => $vendorDir . '/phpunit/php-code-coverage/src/CodeCoverage.php',
+    'SebastianBergmann\\CodeCoverage\\CrapIndex' => $vendorDir . '/phpunit/php-code-coverage/src/CrapIndex.php',
+    'SebastianBergmann\\CodeCoverage\\DeadCodeDetectionNotSupportedException' => $vendorDir . '/phpunit/php-code-coverage/src/Exception/DeadCodeDetectionNotSupportedException.php',
+    'SebastianBergmann\\CodeCoverage\\Directory' => $vendorDir . '/phpunit/php-code-coverage/src/Directory.php',
+    'SebastianBergmann\\CodeCoverage\\DirectoryCouldNotBeCreatedException' => $vendorDir . '/phpunit/php-code-coverage/src/Exception/DirectoryCouldNotBeCreatedException.php',
+    'SebastianBergmann\\CodeCoverage\\Driver\\Driver' => $vendorDir . '/phpunit/php-code-coverage/src/Driver/Driver.php',
+    'SebastianBergmann\\CodeCoverage\\Driver\\PathExistsButIsNotDirectoryException' => $vendorDir . '/phpunit/php-code-coverage/src/Exception/PathExistsButIsNotDirectoryException.php',
+    'SebastianBergmann\\CodeCoverage\\Driver\\PcovDriver' => $vendorDir . '/phpunit/php-code-coverage/src/Driver/PcovDriver.php',
+    'SebastianBergmann\\CodeCoverage\\Driver\\PcovNotAvailableException' => $vendorDir . '/phpunit/php-code-coverage/src/Exception/PcovNotAvailableException.php',
+    'SebastianBergmann\\CodeCoverage\\Driver\\PhpdbgDriver' => $vendorDir . '/phpunit/php-code-coverage/src/Driver/PhpdbgDriver.php',
+    'SebastianBergmann\\CodeCoverage\\Driver\\PhpdbgNotAvailableException' => $vendorDir . '/phpunit/php-code-coverage/src/Exception/PhpdbgNotAvailableException.php',
+    'SebastianBergmann\\CodeCoverage\\Driver\\Selector' => $vendorDir . '/phpunit/php-code-coverage/src/Driver/Selector.php',
+    'SebastianBergmann\\CodeCoverage\\Driver\\WriteOperationFailedException' => $vendorDir . '/phpunit/php-code-coverage/src/Exception/WriteOperationFailedException.php',
+    'SebastianBergmann\\CodeCoverage\\Driver\\WrongXdebugVersionException' => $vendorDir . '/phpunit/php-code-coverage/src/Exception/WrongXdebugVersionException.php',
+    'SebastianBergmann\\CodeCoverage\\Driver\\Xdebug2Driver' => $vendorDir . '/phpunit/php-code-coverage/src/Driver/Xdebug2Driver.php',
+    'SebastianBergmann\\CodeCoverage\\Driver\\Xdebug2NotEnabledException' => $vendorDir . '/phpunit/php-code-coverage/src/Exception/Xdebug2NotEnabledException.php',
+    'SebastianBergmann\\CodeCoverage\\Driver\\Xdebug3Driver' => $vendorDir . '/phpunit/php-code-coverage/src/Driver/Xdebug3Driver.php',
+    'SebastianBergmann\\CodeCoverage\\Driver\\Xdebug3NotEnabledException' => $vendorDir . '/phpunit/php-code-coverage/src/Exception/Xdebug3NotEnabledException.php',
+    'SebastianBergmann\\CodeCoverage\\Driver\\XdebugNotAvailableException' => $vendorDir . '/phpunit/php-code-coverage/src/Exception/XdebugNotAvailableException.php',
+    'SebastianBergmann\\CodeCoverage\\Exception' => $vendorDir . '/phpunit/php-code-coverage/src/Exception/Exception.php',
+    'SebastianBergmann\\CodeCoverage\\Filter' => $vendorDir . '/phpunit/php-code-coverage/src/Filter.php',
+    'SebastianBergmann\\CodeCoverage\\InvalidArgumentException' => $vendorDir . '/phpunit/php-code-coverage/src/Exception/InvalidArgumentException.php',
+    'SebastianBergmann\\CodeCoverage\\NoCodeCoverageDriverAvailableException' => $vendorDir . '/phpunit/php-code-coverage/src/Exception/NoCodeCoverageDriverAvailableException.php',
+    'SebastianBergmann\\CodeCoverage\\NoCodeCoverageDriverWithPathCoverageSupportAvailableException' => $vendorDir . '/phpunit/php-code-coverage/src/Exception/NoCodeCoverageDriverWithPathCoverageSupportAvailableException.php',
+    'SebastianBergmann\\CodeCoverage\\Node\\AbstractNode' => $vendorDir . '/phpunit/php-code-coverage/src/Node/AbstractNode.php',
+    'SebastianBergmann\\CodeCoverage\\Node\\Builder' => $vendorDir . '/phpunit/php-code-coverage/src/Node/Builder.php',
+    'SebastianBergmann\\CodeCoverage\\Node\\Directory' => $vendorDir . '/phpunit/php-code-coverage/src/Node/Directory.php',
+    'SebastianBergmann\\CodeCoverage\\Node\\File' => $vendorDir . '/phpunit/php-code-coverage/src/Node/File.php',
+    'SebastianBergmann\\CodeCoverage\\Node\\Iterator' => $vendorDir . '/phpunit/php-code-coverage/src/Node/Iterator.php',
+    'SebastianBergmann\\CodeCoverage\\ParserException' => $vendorDir . '/phpunit/php-code-coverage/src/Exception/ParserException.php',
+    'SebastianBergmann\\CodeCoverage\\Percentage' => $vendorDir . '/phpunit/php-code-coverage/src/Percentage.php',
+    'SebastianBergmann\\CodeCoverage\\ProcessedCodeCoverageData' => $vendorDir . '/phpunit/php-code-coverage/src/ProcessedCodeCoverageData.php',
+    'SebastianBergmann\\CodeCoverage\\RawCodeCoverageData' => $vendorDir . '/phpunit/php-code-coverage/src/RawCodeCoverageData.php',
+    'SebastianBergmann\\CodeCoverage\\ReflectionException' => $vendorDir . '/phpunit/php-code-coverage/src/Exception/ReflectionException.php',
+    'SebastianBergmann\\CodeCoverage\\ReportAlreadyFinalizedException' => $vendorDir . '/phpunit/php-code-coverage/src/Exception/ReportAlreadyFinalizedException.php',
+    'SebastianBergmann\\CodeCoverage\\Report\\Clover' => $vendorDir . '/phpunit/php-code-coverage/src/Report/Clover.php',
+    'SebastianBergmann\\CodeCoverage\\Report\\Cobertura' => $vendorDir . '/phpunit/php-code-coverage/src/Report/Cobertura.php',
+    'SebastianBergmann\\CodeCoverage\\Report\\Crap4j' => $vendorDir . '/phpunit/php-code-coverage/src/Report/Crap4j.php',
+    'SebastianBergmann\\CodeCoverage\\Report\\Html\\Dashboard' => $vendorDir . '/phpunit/php-code-coverage/src/Report/Html/Renderer/Dashboard.php',
+    'SebastianBergmann\\CodeCoverage\\Report\\Html\\Directory' => $vendorDir . '/phpunit/php-code-coverage/src/Report/Html/Renderer/Directory.php',
+    'SebastianBergmann\\CodeCoverage\\Report\\Html\\Facade' => $vendorDir . '/phpunit/php-code-coverage/src/Report/Html/Facade.php',
+    'SebastianBergmann\\CodeCoverage\\Report\\Html\\File' => $vendorDir . '/phpunit/php-code-coverage/src/Report/Html/Renderer/File.php',
+    'SebastianBergmann\\CodeCoverage\\Report\\Html\\Renderer' => $vendorDir . '/phpunit/php-code-coverage/src/Report/Html/Renderer.php',
+    'SebastianBergmann\\CodeCoverage\\Report\\PHP' => $vendorDir . '/phpunit/php-code-coverage/src/Report/PHP.php',
+    'SebastianBergmann\\CodeCoverage\\Report\\Text' => $vendorDir . '/phpunit/php-code-coverage/src/Report/Text.php',
+    'SebastianBergmann\\CodeCoverage\\Report\\Xml\\BuildInformation' => $vendorDir . '/phpunit/php-code-coverage/src/Report/Xml/BuildInformation.php',
+    'SebastianBergmann\\CodeCoverage\\Report\\Xml\\Coverage' => $vendorDir . '/phpunit/php-code-coverage/src/Report/Xml/Coverage.php',
+    'SebastianBergmann\\CodeCoverage\\Report\\Xml\\Directory' => $vendorDir . '/phpunit/php-code-coverage/src/Report/Xml/Directory.php',
+    'SebastianBergmann\\CodeCoverage\\Report\\Xml\\Facade' => $vendorDir . '/phpunit/php-code-coverage/src/Report/Xml/Facade.php',
+    'SebastianBergmann\\CodeCoverage\\Report\\Xml\\File' => $vendorDir . '/phpunit/php-code-coverage/src/Report/Xml/File.php',
+    'SebastianBergmann\\CodeCoverage\\Report\\Xml\\Method' => $vendorDir . '/phpunit/php-code-coverage/src/Report/Xml/Method.php',
+    'SebastianBergmann\\CodeCoverage\\Report\\Xml\\Node' => $vendorDir . '/phpunit/php-code-coverage/src/Report/Xml/Node.php',
+    'SebastianBergmann\\CodeCoverage\\Report\\Xml\\Project' => $vendorDir . '/phpunit/php-code-coverage/src/Report/Xml/Project.php',
+    'SebastianBergmann\\CodeCoverage\\Report\\Xml\\Report' => $vendorDir . '/phpunit/php-code-coverage/src/Report/Xml/Report.php',
+    'SebastianBergmann\\CodeCoverage\\Report\\Xml\\Source' => $vendorDir . '/phpunit/php-code-coverage/src/Report/Xml/Source.php',
+    'SebastianBergmann\\CodeCoverage\\Report\\Xml\\Tests' => $vendorDir . '/phpunit/php-code-coverage/src/Report/Xml/Tests.php',
+    'SebastianBergmann\\CodeCoverage\\Report\\Xml\\Totals' => $vendorDir . '/phpunit/php-code-coverage/src/Report/Xml/Totals.php',
+    'SebastianBergmann\\CodeCoverage\\Report\\Xml\\Unit' => $vendorDir . '/phpunit/php-code-coverage/src/Report/Xml/Unit.php',
+    'SebastianBergmann\\CodeCoverage\\StaticAnalysisCacheNotConfiguredException' => $vendorDir . '/phpunit/php-code-coverage/src/Exception/StaticAnalysisCacheNotConfiguredException.php',
+    'SebastianBergmann\\CodeCoverage\\StaticAnalysis\\Cache' => $vendorDir . '/phpunit/php-code-coverage/src/StaticAnalysis/Cache.php',
+    'SebastianBergmann\\CodeCoverage\\StaticAnalysis\\CacheWarmer' => $vendorDir . '/phpunit/php-code-coverage/src/StaticAnalysis/CacheWarmer.php',
+    'SebastianBergmann\\CodeCoverage\\StaticAnalysis\\CachingCoveredFileAnalyser' => $vendorDir . '/phpunit/php-code-coverage/src/StaticAnalysis/CachingCoveredFileAnalyser.php',
+    'SebastianBergmann\\CodeCoverage\\StaticAnalysis\\CachingUncoveredFileAnalyser' => $vendorDir . '/phpunit/php-code-coverage/src/StaticAnalysis/CachingUncoveredFileAnalyser.php',
+    'SebastianBergmann\\CodeCoverage\\StaticAnalysis\\CodeUnitFindingVisitor' => $vendorDir . '/phpunit/php-code-coverage/src/StaticAnalysis/CodeUnitFindingVisitor.php',
+    'SebastianBergmann\\CodeCoverage\\StaticAnalysis\\CoveredFileAnalyser' => $vendorDir . '/phpunit/php-code-coverage/src/StaticAnalysis/CoveredFileAnalyser.php',
+    'SebastianBergmann\\CodeCoverage\\StaticAnalysis\\ExecutableLinesFindingVisitor' => $vendorDir . '/phpunit/php-code-coverage/src/StaticAnalysis/ExecutableLinesFindingVisitor.php',
+    'SebastianBergmann\\CodeCoverage\\StaticAnalysis\\IgnoredLinesFindingVisitor' => $vendorDir . '/phpunit/php-code-coverage/src/StaticAnalysis/IgnoredLinesFindingVisitor.php',
+    'SebastianBergmann\\CodeCoverage\\StaticAnalysis\\ParsingCoveredFileAnalyser' => $vendorDir . '/phpunit/php-code-coverage/src/StaticAnalysis/ParsingCoveredFileAnalyser.php',
+    'SebastianBergmann\\CodeCoverage\\StaticAnalysis\\ParsingUncoveredFileAnalyser' => $vendorDir . '/phpunit/php-code-coverage/src/StaticAnalysis/ParsingUncoveredFileAnalyser.php',
+    'SebastianBergmann\\CodeCoverage\\StaticAnalysis\\UncoveredFileAnalyser' => $vendorDir . '/phpunit/php-code-coverage/src/StaticAnalysis/UncoveredFileAnalyser.php',
+    'SebastianBergmann\\CodeCoverage\\TestIdMissingException' => $vendorDir . '/phpunit/php-code-coverage/src/Exception/TestIdMissingException.php',
+    'SebastianBergmann\\CodeCoverage\\UnintentionallyCoveredCodeException' => $vendorDir . '/phpunit/php-code-coverage/src/Exception/UnintentionallyCoveredCodeException.php',
+    'SebastianBergmann\\CodeCoverage\\Version' => $vendorDir . '/phpunit/php-code-coverage/src/Version.php',
+    'SebastianBergmann\\CodeCoverage\\XmlException' => $vendorDir . '/phpunit/php-code-coverage/src/Exception/XmlException.php',
+    'SebastianBergmann\\CodeUnitReverseLookup\\Wizard' => $vendorDir . '/sebastian/code-unit-reverse-lookup/src/Wizard.php',
+    'SebastianBergmann\\CodeUnit\\ClassMethodUnit' => $vendorDir . '/sebastian/code-unit/src/ClassMethodUnit.php',
+    'SebastianBergmann\\CodeUnit\\ClassUnit' => $vendorDir . '/sebastian/code-unit/src/ClassUnit.php',
+    'SebastianBergmann\\CodeUnit\\CodeUnit' => $vendorDir . '/sebastian/code-unit/src/CodeUnit.php',
+    'SebastianBergmann\\CodeUnit\\CodeUnitCollection' => $vendorDir . '/sebastian/code-unit/src/CodeUnitCollection.php',
+    'SebastianBergmann\\CodeUnit\\CodeUnitCollectionIterator' => $vendorDir . '/sebastian/code-unit/src/CodeUnitCollectionIterator.php',
+    'SebastianBergmann\\CodeUnit\\Exception' => $vendorDir . '/sebastian/code-unit/src/exceptions/Exception.php',
+    'SebastianBergmann\\CodeUnit\\FunctionUnit' => $vendorDir . '/sebastian/code-unit/src/FunctionUnit.php',
+    'SebastianBergmann\\CodeUnit\\InterfaceMethodUnit' => $vendorDir . '/sebastian/code-unit/src/InterfaceMethodUnit.php',
+    'SebastianBergmann\\CodeUnit\\InterfaceUnit' => $vendorDir . '/sebastian/code-unit/src/InterfaceUnit.php',
+    'SebastianBergmann\\CodeUnit\\InvalidCodeUnitException' => $vendorDir . '/sebastian/code-unit/src/exceptions/InvalidCodeUnitException.php',
+    'SebastianBergmann\\CodeUnit\\Mapper' => $vendorDir . '/sebastian/code-unit/src/Mapper.php',
+    'SebastianBergmann\\CodeUnit\\NoTraitException' => $vendorDir . '/sebastian/code-unit/src/exceptions/NoTraitException.php',
+    'SebastianBergmann\\CodeUnit\\ReflectionException' => $vendorDir . '/sebastian/code-unit/src/exceptions/ReflectionException.php',
+    'SebastianBergmann\\CodeUnit\\TraitMethodUnit' => $vendorDir . '/sebastian/code-unit/src/TraitMethodUnit.php',
+    'SebastianBergmann\\CodeUnit\\TraitUnit' => $vendorDir . '/sebastian/code-unit/src/TraitUnit.php',
+    'SebastianBergmann\\Comparator\\ArrayComparator' => $vendorDir . '/sebastian/comparator/src/ArrayComparator.php',
+    'SebastianBergmann\\Comparator\\Comparator' => $vendorDir . '/sebastian/comparator/src/Comparator.php',
+    'SebastianBergmann\\Comparator\\ComparisonFailure' => $vendorDir . '/sebastian/comparator/src/ComparisonFailure.php',
+    'SebastianBergmann\\Comparator\\DOMNodeComparator' => $vendorDir . '/sebastian/comparator/src/DOMNodeComparator.php',
+    'SebastianBergmann\\Comparator\\DateTimeComparator' => $vendorDir . '/sebastian/comparator/src/DateTimeComparator.php',
+    'SebastianBergmann\\Comparator\\DoubleComparator' => $vendorDir . '/sebastian/comparator/src/DoubleComparator.php',
+    'SebastianBergmann\\Comparator\\Exception' => $vendorDir . '/sebastian/comparator/src/exceptions/Exception.php',
+    'SebastianBergmann\\Comparator\\ExceptionComparator' => $vendorDir . '/sebastian/comparator/src/ExceptionComparator.php',
+    'SebastianBergmann\\Comparator\\Factory' => $vendorDir . '/sebastian/comparator/src/Factory.php',
+    'SebastianBergmann\\Comparator\\MockObjectComparator' => $vendorDir . '/sebastian/comparator/src/MockObjectComparator.php',
+    'SebastianBergmann\\Comparator\\NumericComparator' => $vendorDir . '/sebastian/comparator/src/NumericComparator.php',
+    'SebastianBergmann\\Comparator\\ObjectComparator' => $vendorDir . '/sebastian/comparator/src/ObjectComparator.php',
+    'SebastianBergmann\\Comparator\\ResourceComparator' => $vendorDir . '/sebastian/comparator/src/ResourceComparator.php',
+    'SebastianBergmann\\Comparator\\RuntimeException' => $vendorDir . '/sebastian/comparator/src/exceptions/RuntimeException.php',
+    'SebastianBergmann\\Comparator\\ScalarComparator' => $vendorDir . '/sebastian/comparator/src/ScalarComparator.php',
+    'SebastianBergmann\\Comparator\\SplObjectStorageComparator' => $vendorDir . '/sebastian/comparator/src/SplObjectStorageComparator.php',
+    'SebastianBergmann\\Comparator\\TypeComparator' => $vendorDir . '/sebastian/comparator/src/TypeComparator.php',
+    'SebastianBergmann\\Complexity\\Calculator' => $vendorDir . '/sebastian/complexity/src/Calculator.php',
+    'SebastianBergmann\\Complexity\\Complexity' => $vendorDir . '/sebastian/complexity/src/Complexity/Complexity.php',
+    'SebastianBergmann\\Complexity\\ComplexityCalculatingVisitor' => $vendorDir . '/sebastian/complexity/src/Visitor/ComplexityCalculatingVisitor.php',
+    'SebastianBergmann\\Complexity\\ComplexityCollection' => $vendorDir . '/sebastian/complexity/src/Complexity/ComplexityCollection.php',
+    'SebastianBergmann\\Complexity\\ComplexityCollectionIterator' => $vendorDir . '/sebastian/complexity/src/Complexity/ComplexityCollectionIterator.php',
+    'SebastianBergmann\\Complexity\\CyclomaticComplexityCalculatingVisitor' => $vendorDir . '/sebastian/complexity/src/Visitor/CyclomaticComplexityCalculatingVisitor.php',
+    'SebastianBergmann\\Complexity\\Exception' => $vendorDir . '/sebastian/complexity/src/Exception/Exception.php',
+    'SebastianBergmann\\Complexity\\RuntimeException' => $vendorDir . '/sebastian/complexity/src/Exception/RuntimeException.php',
+    'SebastianBergmann\\Diff\\Chunk' => $vendorDir . '/sebastian/diff/src/Chunk.php',
+    'SebastianBergmann\\Diff\\ConfigurationException' => $vendorDir . '/sebastian/diff/src/Exception/ConfigurationException.php',
+    'SebastianBergmann\\Diff\\Diff' => $vendorDir . '/sebastian/diff/src/Diff.php',
+    'SebastianBergmann\\Diff\\Differ' => $vendorDir . '/sebastian/diff/src/Differ.php',
+    'SebastianBergmann\\Diff\\Exception' => $vendorDir . '/sebastian/diff/src/Exception/Exception.php',
+    'SebastianBergmann\\Diff\\InvalidArgumentException' => $vendorDir . '/sebastian/diff/src/Exception/InvalidArgumentException.php',
+    'SebastianBergmann\\Diff\\Line' => $vendorDir . '/sebastian/diff/src/Line.php',
+    'SebastianBergmann\\Diff\\LongestCommonSubsequenceCalculator' => $vendorDir . '/sebastian/diff/src/LongestCommonSubsequenceCalculator.php',
+    'SebastianBergmann\\Diff\\MemoryEfficientLongestCommonSubsequenceCalculator' => $vendorDir . '/sebastian/diff/src/MemoryEfficientLongestCommonSubsequenceCalculator.php',
+    'SebastianBergmann\\Diff\\Output\\AbstractChunkOutputBuilder' => $vendorDir . '/sebastian/diff/src/Output/AbstractChunkOutputBuilder.php',
+    'SebastianBergmann\\Diff\\Output\\DiffOnlyOutputBuilder' => $vendorDir . '/sebastian/diff/src/Output/DiffOnlyOutputBuilder.php',
+    'SebastianBergmann\\Diff\\Output\\DiffOutputBuilderInterface' => $vendorDir . '/sebastian/diff/src/Output/DiffOutputBuilderInterface.php',
+    'SebastianBergmann\\Diff\\Output\\StrictUnifiedDiffOutputBuilder' => $vendorDir . '/sebastian/diff/src/Output/StrictUnifiedDiffOutputBuilder.php',
+    'SebastianBergmann\\Diff\\Output\\UnifiedDiffOutputBuilder' => $vendorDir . '/sebastian/diff/src/Output/UnifiedDiffOutputBuilder.php',
+    'SebastianBergmann\\Diff\\Parser' => $vendorDir . '/sebastian/diff/src/Parser.php',
+    'SebastianBergmann\\Diff\\TimeEfficientLongestCommonSubsequenceCalculator' => $vendorDir . '/sebastian/diff/src/TimeEfficientLongestCommonSubsequenceCalculator.php',
+    'SebastianBergmann\\Environment\\Console' => $vendorDir . '/sebastian/environment/src/Console.php',
+    'SebastianBergmann\\Environment\\OperatingSystem' => $vendorDir . '/sebastian/environment/src/OperatingSystem.php',
+    'SebastianBergmann\\Environment\\Runtime' => $vendorDir . '/sebastian/environment/src/Runtime.php',
+    'SebastianBergmann\\Exporter\\Exporter' => $vendorDir . '/sebastian/exporter/src/Exporter.php',
+    'SebastianBergmann\\FileIterator\\Facade' => $vendorDir . '/phpunit/php-file-iterator/src/Facade.php',
+    'SebastianBergmann\\FileIterator\\Factory' => $vendorDir . '/phpunit/php-file-iterator/src/Factory.php',
+    'SebastianBergmann\\FileIterator\\Iterator' => $vendorDir . '/phpunit/php-file-iterator/src/Iterator.php',
+    'SebastianBergmann\\GlobalState\\CodeExporter' => $vendorDir . '/sebastian/global-state/src/CodeExporter.php',
+    'SebastianBergmann\\GlobalState\\Exception' => $vendorDir . '/sebastian/global-state/src/exceptions/Exception.php',
+    'SebastianBergmann\\GlobalState\\ExcludeList' => $vendorDir . '/sebastian/global-state/src/ExcludeList.php',
+    'SebastianBergmann\\GlobalState\\Restorer' => $vendorDir . '/sebastian/global-state/src/Restorer.php',
+    'SebastianBergmann\\GlobalState\\RuntimeException' => $vendorDir . '/sebastian/global-state/src/exceptions/RuntimeException.php',
+    'SebastianBergmann\\GlobalState\\Snapshot' => $vendorDir . '/sebastian/global-state/src/Snapshot.php',
+    'SebastianBergmann\\Invoker\\Exception' => $vendorDir . '/phpunit/php-invoker/src/exceptions/Exception.php',
+    'SebastianBergmann\\Invoker\\Invoker' => $vendorDir . '/phpunit/php-invoker/src/Invoker.php',
+    'SebastianBergmann\\Invoker\\ProcessControlExtensionNotLoadedException' => $vendorDir . '/phpunit/php-invoker/src/exceptions/ProcessControlExtensionNotLoadedException.php',
+    'SebastianBergmann\\Invoker\\TimeoutException' => $vendorDir . '/phpunit/php-invoker/src/exceptions/TimeoutException.php',
+    'SebastianBergmann\\LinesOfCode\\Counter' => $vendorDir . '/sebastian/lines-of-code/src/Counter.php',
+    'SebastianBergmann\\LinesOfCode\\Exception' => $vendorDir . '/sebastian/lines-of-code/src/Exception/Exception.php',
+    'SebastianBergmann\\LinesOfCode\\IllogicalValuesException' => $vendorDir . '/sebastian/lines-of-code/src/Exception/IllogicalValuesException.php',
+    'SebastianBergmann\\LinesOfCode\\LineCountingVisitor' => $vendorDir . '/sebastian/lines-of-code/src/LineCountingVisitor.php',
+    'SebastianBergmann\\LinesOfCode\\LinesOfCode' => $vendorDir . '/sebastian/lines-of-code/src/LinesOfCode.php',
+    'SebastianBergmann\\LinesOfCode\\NegativeValueException' => $vendorDir . '/sebastian/lines-of-code/src/Exception/NegativeValueException.php',
+    'SebastianBergmann\\LinesOfCode\\RuntimeException' => $vendorDir . '/sebastian/lines-of-code/src/Exception/RuntimeException.php',
+    'SebastianBergmann\\ObjectEnumerator\\Enumerator' => $vendorDir . '/sebastian/object-enumerator/src/Enumerator.php',
+    'SebastianBergmann\\ObjectEnumerator\\Exception' => $vendorDir . '/sebastian/object-enumerator/src/Exception.php',
+    'SebastianBergmann\\ObjectEnumerator\\InvalidArgumentException' => $vendorDir . '/sebastian/object-enumerator/src/InvalidArgumentException.php',
+    'SebastianBergmann\\ObjectReflector\\Exception' => $vendorDir . '/sebastian/object-reflector/src/Exception.php',
+    'SebastianBergmann\\ObjectReflector\\InvalidArgumentException' => $vendorDir . '/sebastian/object-reflector/src/InvalidArgumentException.php',
+    'SebastianBergmann\\ObjectReflector\\ObjectReflector' => $vendorDir . '/sebastian/object-reflector/src/ObjectReflector.php',
+    'SebastianBergmann\\RecursionContext\\Context' => $vendorDir . '/sebastian/recursion-context/src/Context.php',
+    'SebastianBergmann\\RecursionContext\\Exception' => $vendorDir . '/sebastian/recursion-context/src/Exception.php',
+    'SebastianBergmann\\RecursionContext\\InvalidArgumentException' => $vendorDir . '/sebastian/recursion-context/src/InvalidArgumentException.php',
+    'SebastianBergmann\\ResourceOperations\\ResourceOperations' => $vendorDir . '/sebastian/resource-operations/src/ResourceOperations.php',
+    'SebastianBergmann\\Template\\Exception' => $vendorDir . '/phpunit/php-text-template/src/exceptions/Exception.php',
+    'SebastianBergmann\\Template\\InvalidArgumentException' => $vendorDir . '/phpunit/php-text-template/src/exceptions/InvalidArgumentException.php',
+    'SebastianBergmann\\Template\\RuntimeException' => $vendorDir . '/phpunit/php-text-template/src/exceptions/RuntimeException.php',
+    'SebastianBergmann\\Template\\Template' => $vendorDir . '/phpunit/php-text-template/src/Template.php',
+    'SebastianBergmann\\Timer\\Duration' => $vendorDir . '/phpunit/php-timer/src/Duration.php',
+    'SebastianBergmann\\Timer\\Exception' => $vendorDir . '/phpunit/php-timer/src/exceptions/Exception.php',
+    'SebastianBergmann\\Timer\\NoActiveTimerException' => $vendorDir . '/phpunit/php-timer/src/exceptions/NoActiveTimerException.php',
+    'SebastianBergmann\\Timer\\ResourceUsageFormatter' => $vendorDir . '/phpunit/php-timer/src/ResourceUsageFormatter.php',
+    'SebastianBergmann\\Timer\\TimeSinceStartOfRequestNotAvailableException' => $vendorDir . '/phpunit/php-timer/src/exceptions/TimeSinceStartOfRequestNotAvailableException.php',
+    'SebastianBergmann\\Timer\\Timer' => $vendorDir . '/phpunit/php-timer/src/Timer.php',
+    'SebastianBergmann\\Type\\CallableType' => $vendorDir . '/sebastian/type/src/CallableType.php',
+    'SebastianBergmann\\Type\\Exception' => $vendorDir . '/sebastian/type/src/exception/Exception.php',
+    'SebastianBergmann\\Type\\GenericObjectType' => $vendorDir . '/sebastian/type/src/GenericObjectType.php',
+    'SebastianBergmann\\Type\\IterableType' => $vendorDir . '/sebastian/type/src/IterableType.php',
+    'SebastianBergmann\\Type\\MixedType' => $vendorDir . '/sebastian/type/src/MixedType.php',
+    'SebastianBergmann\\Type\\NullType' => $vendorDir . '/sebastian/type/src/NullType.php',
+    'SebastianBergmann\\Type\\ObjectType' => $vendorDir . '/sebastian/type/src/ObjectType.php',
+    'SebastianBergmann\\Type\\ReflectionMapper' => $vendorDir . '/sebastian/type/src/ReflectionMapper.php',
+    'SebastianBergmann\\Type\\RuntimeException' => $vendorDir . '/sebastian/type/src/exception/RuntimeException.php',
+    'SebastianBergmann\\Type\\SimpleType' => $vendorDir . '/sebastian/type/src/SimpleType.php',
+    'SebastianBergmann\\Type\\StaticType' => $vendorDir . '/sebastian/type/src/StaticType.php',
+    'SebastianBergmann\\Type\\Type' => $vendorDir . '/sebastian/type/src/Type.php',
+    'SebastianBergmann\\Type\\TypeName' => $vendorDir . '/sebastian/type/src/TypeName.php',
+    'SebastianBergmann\\Type\\UnionType' => $vendorDir . '/sebastian/type/src/UnionType.php',
+    'SebastianBergmann\\Type\\UnknownType' => $vendorDir . '/sebastian/type/src/UnknownType.php',
+    'SebastianBergmann\\Type\\VoidType' => $vendorDir . '/sebastian/type/src/VoidType.php',
+    'SebastianBergmann\\Version' => $vendorDir . '/sebastian/version/src/Version.php',
     'TCPDF' => $vendorDir . '/tecnickcom/tcpdf/tcpdf.php',
     'TCPDF2DBarcode' => $vendorDir . '/tecnickcom/tcpdf/tcpdf_barcodes_2d.php',
     'TCPDFBarcode' => $vendorDir . '/tecnickcom/tcpdf/tcpdf_barcodes_1d.php',
@@ -20,4 +635,12 @@ return array(
     'TCPDF_IMPORT' => $vendorDir . '/tecnickcom/tcpdf/tcpdf_import.php',
     'TCPDF_PARSER' => $vendorDir . '/tecnickcom/tcpdf/tcpdf_parser.php',
     'TCPDF_STATIC' => $vendorDir . '/tecnickcom/tcpdf/include/tcpdf_static.php',
+    'TheSeer\\Tokenizer\\Exception' => $vendorDir . '/theseer/tokenizer/src/Exception.php',
+    'TheSeer\\Tokenizer\\NamespaceUri' => $vendorDir . '/theseer/tokenizer/src/NamespaceUri.php',
+    'TheSeer\\Tokenizer\\NamespaceUriException' => $vendorDir . '/theseer/tokenizer/src/NamespaceUriException.php',
+    'TheSeer\\Tokenizer\\Token' => $vendorDir . '/theseer/tokenizer/src/Token.php',
+    'TheSeer\\Tokenizer\\TokenCollection' => $vendorDir . '/theseer/tokenizer/src/TokenCollection.php',
+    'TheSeer\\Tokenizer\\TokenCollectionException' => $vendorDir . '/theseer/tokenizer/src/TokenCollectionException.php',
+    'TheSeer\\Tokenizer\\Tokenizer' => $vendorDir . '/theseer/tokenizer/src/Tokenizer.php',
+    'TheSeer\\Tokenizer\\XMLSerializer' => $vendorDir . '/theseer/tokenizer/src/XMLSerializer.php',
 );
diff --git a/vendor/composer/autoload_files.php b/vendor/composer/autoload_files.php
index 190695196a16fe36edc2309fe01581fb703a9a45..0ce15f86142f719263eeca980c0db2f71af128e0 100644
--- a/vendor/composer/autoload_files.php
+++ b/vendor/composer/autoload_files.php
@@ -6,6 +6,10 @@ $vendorDir = dirname(dirname(__FILE__));
 $baseDir = dirname($vendorDir);
 
 return array(
+    'ec07570ca5a812141189b1fa81503674' => $vendorDir . '/phpunit/phpunit/src/Framework/Assert/Functions.php',
+    '320cde22f66dd4f5d3fd621d3e88b98f' => $vendorDir . '/symfony/polyfill-ctype/bootstrap.php',
+    '6124b4c8570aa390c21fafd04a26c69f' => $vendorDir . '/myclabs/deep-copy/src/DeepCopy/deep_copy.php',
     '253c157292f75eb38082b5acb06f3f01' => $vendorDir . '/nikic/fast-route/src/functions.php',
     '0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => $vendorDir . '/symfony/polyfill-mbstring/bootstrap.php',
+    'bd9634f2d41831496de0d3dfe4c94881' => $vendorDir . '/symfony/polyfill-php56/bootstrap.php',
 );
diff --git a/vendor/composer/autoload_psr4.php b/vendor/composer/autoload_psr4.php
index 202d663a19a00e6d51d0a9fc18065ee97b60280c..220bf9876b6cf162ad3e1031a2bb25955e0d0ff2 100644
--- a/vendor/composer/autoload_psr4.php
+++ b/vendor/composer/autoload_psr4.php
@@ -7,24 +7,34 @@ $baseDir = dirname($vendorDir);
 
 return array(
     'setasign\\Fpdi\\' => array($vendorDir . '/setasign/fpdi/src'),
+    'phpDocumentor\\Reflection\\' => array($vendorDir . '/phpdocumentor/reflection-common/src', $vendorDir . '/phpdocumentor/reflection-docblock/src', $vendorDir . '/phpdocumentor/type-resolver/src'),
     'Workflow\\' => array($baseDir . '/src/app/workflow'),
+    'Webmozart\\Assert\\' => array($vendorDir . '/webmozart/assert/src'),
     'User\\' => array($baseDir . '/src/app/user'),
+    'Symfony\\Polyfill\\Util\\' => array($vendorDir . '/symfony/polyfill-util'),
+    'Symfony\\Polyfill\\Php56\\' => array($vendorDir . '/symfony/polyfill-php56'),
     'Symfony\\Polyfill\\Mbstring\\' => array($vendorDir . '/symfony/polyfill-mbstring'),
+    'Symfony\\Polyfill\\Ctype\\' => array($vendorDir . '/symfony/polyfill-ctype'),
     'SrcCore\\' => array($baseDir . '/src/core'),
     'Slim\\' => array($vendorDir . '/slim/slim/Slim'),
     'Search\\' => array($baseDir . '/src/app/search'),
     'Respect\\Validation\\' => array($vendorDir . '/respect/validation/library'),
     'Psr\\Http\\Message\\' => array($vendorDir . '/psr/http-message/src'),
     'Psr\\Container\\' => array($vendorDir . '/psr/container/src'),
+    'Prophecy\\' => array($vendorDir . '/phpspec/prophecy/src/Prophecy'),
+    'PhpParser\\' => array($vendorDir . '/nikic/php-parser/lib/PhpParser'),
+    'ParagonIE\\ConstantTime\\' => array($vendorDir . '/paragonie/constant_time_encoding/src'),
     'PHPMailer\\PHPMailer\\' => array($vendorDir . '/phpmailer/phpmailer/src'),
-    'Interop\\Container\\' => array($vendorDir . '/container-interop/container-interop/src/Interop/Container'),
+    'Otp\\' => array($vendorDir . '/christian-riesen/otp/src'),
     'History\\' => array($baseDir . '/src/app/history'),
     'Group\\' => array($baseDir . '/src/app/group'),
     'Firebase\\JWT\\' => array($vendorDir . '/firebase/php-jwt/src'),
     'FastRoute\\' => array($vendorDir . '/nikic/fast-route/src'),
     'Email\\' => array($baseDir . '/src/app/email'),
     'Document\\' => array($baseDir . '/src/app/document'),
+    'Doctrine\\Instantiator\\' => array($vendorDir . '/doctrine/instantiator/src/Doctrine/Instantiator'),
     'Docserver\\' => array($baseDir . '/src/app/docserver'),
+    'DeepCopy\\' => array($vendorDir . '/myclabs/deep-copy/src/DeepCopy'),
     'Convert\\' => array($baseDir . '/src/app/convert'),
     'Configuration\\' => array($baseDir . '/src/app/configuration'),
     'Attachment\\' => array($baseDir . '/src/app/attachment'),
diff --git a/vendor/composer/autoload_real.php b/vendor/composer/autoload_real.php
index a1cb1ce02690bcfe1b25c2ccf7fb76185be9f1c8..f499e861cdef5c7fde05b896ec1d787001a7cb6c 100644
--- a/vendor/composer/autoload_real.php
+++ b/vendor/composer/autoload_real.php
@@ -13,6 +13,9 @@ class ComposerAutoloaderInit637514d10f1ed5d4c55a005a428a3656
         }
     }
 
+    /**
+     * @return \Composer\Autoload\ClassLoader
+     */
     public static function getLoader()
     {
         if (null !== self::$loader) {
diff --git a/vendor/composer/autoload_static.php b/vendor/composer/autoload_static.php
index f411d06d9b8e2918df0bc9b7e45ab9406e803ece..2c149047ba27098d53d25d8a437ab313d0ce684a 100644
--- a/vendor/composer/autoload_static.php
+++ b/vendor/composer/autoload_static.php
@@ -7,8 +7,12 @@ namespace Composer\Autoload;
 class ComposerStaticInit637514d10f1ed5d4c55a005a428a3656
 {
     public static $files = array (
+        'ec07570ca5a812141189b1fa81503674' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Assert/Functions.php',
+        '320cde22f66dd4f5d3fd621d3e88b98f' => __DIR__ . '/..' . '/symfony/polyfill-ctype/bootstrap.php',
+        '6124b4c8570aa390c21fafd04a26c69f' => __DIR__ . '/..' . '/myclabs/deep-copy/src/DeepCopy/deep_copy.php',
         '253c157292f75eb38082b5acb06f3f01' => __DIR__ . '/..' . '/nikic/fast-route/src/functions.php',
         '0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => __DIR__ . '/..' . '/symfony/polyfill-mbstring/bootstrap.php',
+        'bd9634f2d41831496de0d3dfe4c94881' => __DIR__ . '/..' . '/symfony/polyfill-php56/bootstrap.php',
     );
 
     public static $prefixLengthsPsr4 = array (
@@ -16,9 +20,14 @@ class ComposerStaticInit637514d10f1ed5d4c55a005a428a3656
         array (
             'setasign\\Fpdi\\' => 14,
         ),
+        'p' => 
+        array (
+            'phpDocumentor\\Reflection\\' => 25,
+        ),
         'W' => 
         array (
             'Workflow\\' => 9,
+            'Webmozart\\Assert\\' => 17,
         ),
         'U' => 
         array (
@@ -26,7 +35,10 @@ class ComposerStaticInit637514d10f1ed5d4c55a005a428a3656
         ),
         'S' => 
         array (
+            'Symfony\\Polyfill\\Util\\' => 22,
+            'Symfony\\Polyfill\\Php56\\' => 23,
             'Symfony\\Polyfill\\Mbstring\\' => 26,
+            'Symfony\\Polyfill\\Ctype\\' => 23,
             'SrcCore\\' => 8,
             'Slim\\' => 5,
             'Search\\' => 7,
@@ -39,11 +51,14 @@ class ComposerStaticInit637514d10f1ed5d4c55a005a428a3656
         array (
             'Psr\\Http\\Message\\' => 17,
             'Psr\\Container\\' => 14,
+            'Prophecy\\' => 9,
+            'PhpParser\\' => 10,
+            'ParagonIE\\ConstantTime\\' => 23,
             'PHPMailer\\PHPMailer\\' => 20,
         ),
-        'I' => 
+        'O' => 
         array (
-            'Interop\\Container\\' => 18,
+            'Otp\\' => 4,
         ),
         'H' => 
         array (
@@ -65,7 +80,9 @@ class ComposerStaticInit637514d10f1ed5d4c55a005a428a3656
         'D' => 
         array (
             'Document\\' => 9,
+            'Doctrine\\Instantiator\\' => 22,
             'Docserver\\' => 10,
+            'DeepCopy\\' => 9,
         ),
         'C' => 
         array (
@@ -83,18 +100,40 @@ class ComposerStaticInit637514d10f1ed5d4c55a005a428a3656
         array (
             0 => __DIR__ . '/..' . '/setasign/fpdi/src',
         ),
+        'phpDocumentor\\Reflection\\' => 
+        array (
+            0 => __DIR__ . '/..' . '/phpdocumentor/reflection-common/src',
+            1 => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src',
+            2 => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src',
+        ),
         'Workflow\\' => 
         array (
             0 => __DIR__ . '/../..' . '/src/app/workflow',
         ),
+        'Webmozart\\Assert\\' => 
+        array (
+            0 => __DIR__ . '/..' . '/webmozart/assert/src',
+        ),
         'User\\' => 
         array (
             0 => __DIR__ . '/../..' . '/src/app/user',
         ),
+        'Symfony\\Polyfill\\Util\\' => 
+        array (
+            0 => __DIR__ . '/..' . '/symfony/polyfill-util',
+        ),
+        'Symfony\\Polyfill\\Php56\\' => 
+        array (
+            0 => __DIR__ . '/..' . '/symfony/polyfill-php56',
+        ),
         'Symfony\\Polyfill\\Mbstring\\' => 
         array (
             0 => __DIR__ . '/..' . '/symfony/polyfill-mbstring',
         ),
+        'Symfony\\Polyfill\\Ctype\\' => 
+        array (
+            0 => __DIR__ . '/..' . '/symfony/polyfill-ctype',
+        ),
         'SrcCore\\' => 
         array (
             0 => __DIR__ . '/../..' . '/src/core',
@@ -119,13 +158,25 @@ class ComposerStaticInit637514d10f1ed5d4c55a005a428a3656
         array (
             0 => __DIR__ . '/..' . '/psr/container/src',
         ),
+        'Prophecy\\' => 
+        array (
+            0 => __DIR__ . '/..' . '/phpspec/prophecy/src/Prophecy',
+        ),
+        'PhpParser\\' => 
+        array (
+            0 => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser',
+        ),
+        'ParagonIE\\ConstantTime\\' => 
+        array (
+            0 => __DIR__ . '/..' . '/paragonie/constant_time_encoding/src',
+        ),
         'PHPMailer\\PHPMailer\\' => 
         array (
             0 => __DIR__ . '/..' . '/phpmailer/phpmailer/src',
         ),
-        'Interop\\Container\\' => 
+        'Otp\\' => 
         array (
-            0 => __DIR__ . '/..' . '/container-interop/container-interop/src/Interop/Container',
+            0 => __DIR__ . '/..' . '/christian-riesen/otp/src',
         ),
         'History\\' => 
         array (
@@ -151,10 +202,18 @@ class ComposerStaticInit637514d10f1ed5d4c55a005a428a3656
         array (
             0 => __DIR__ . '/../..' . '/src/app/document',
         ),
+        'Doctrine\\Instantiator\\' => 
+        array (
+            0 => __DIR__ . '/..' . '/doctrine/instantiator/src/Doctrine/Instantiator',
+        ),
         'Docserver\\' => 
         array (
             0 => __DIR__ . '/../..' . '/src/app/docserver',
         ),
+        'DeepCopy\\' => 
+        array (
+            0 => __DIR__ . '/..' . '/myclabs/deep-copy/src/DeepCopy',
+        ),
         'Convert\\' => 
         array (
             0 => __DIR__ . '/../..' . '/src/app/convert',
@@ -182,7 +241,622 @@ class ComposerStaticInit637514d10f1ed5d4c55a005a428a3656
     public static $classMap = array (
         'Datamatrix' => __DIR__ . '/..' . '/tecnickcom/tcpdf/include/barcodes/datamatrix.php',
         'PDF417' => __DIR__ . '/..' . '/tecnickcom/tcpdf/include/barcodes/pdf417.php',
+        'PHPUnit\\Exception' => __DIR__ . '/..' . '/phpunit/phpunit/src/Exception.php',
+        'PHPUnit\\Framework\\ActualValueIsNotAnObjectException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Exception/ActualValueIsNotAnObjectException.php',
+        'PHPUnit\\Framework\\Assert' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Assert.php',
+        'PHPUnit\\Framework\\AssertionFailedError' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Exception/AssertionFailedError.php',
+        'PHPUnit\\Framework\\CodeCoverageException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Exception/CodeCoverageException.php',
+        'PHPUnit\\Framework\\ComparisonMethodDoesNotAcceptParameterTypeException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Exception/ComparisonMethodDoesNotAcceptParameterTypeException.php',
+        'PHPUnit\\Framework\\ComparisonMethodDoesNotDeclareBoolReturnTypeException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Exception/ComparisonMethodDoesNotDeclareBoolReturnTypeException.php',
+        'PHPUnit\\Framework\\ComparisonMethodDoesNotDeclareExactlyOneParameterException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Exception/ComparisonMethodDoesNotDeclareExactlyOneParameterException.php',
+        'PHPUnit\\Framework\\ComparisonMethodDoesNotDeclareParameterTypeException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Exception/ComparisonMethodDoesNotDeclareParameterTypeException.php',
+        'PHPUnit\\Framework\\ComparisonMethodDoesNotExistException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Exception/ComparisonMethodDoesNotExistException.php',
+        'PHPUnit\\Framework\\Constraint\\ArrayHasKey' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Traversable/ArrayHasKey.php',
+        'PHPUnit\\Framework\\Constraint\\BinaryOperator' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Operator/BinaryOperator.php',
+        'PHPUnit\\Framework\\Constraint\\Callback' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Callback.php',
+        'PHPUnit\\Framework\\Constraint\\ClassHasAttribute' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Object/ClassHasAttribute.php',
+        'PHPUnit\\Framework\\Constraint\\ClassHasStaticAttribute' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Object/ClassHasStaticAttribute.php',
+        'PHPUnit\\Framework\\Constraint\\Constraint' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Constraint.php',
+        'PHPUnit\\Framework\\Constraint\\Count' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Cardinality/Count.php',
+        'PHPUnit\\Framework\\Constraint\\DirectoryExists' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Filesystem/DirectoryExists.php',
+        'PHPUnit\\Framework\\Constraint\\Exception' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Exception/Exception.php',
+        'PHPUnit\\Framework\\Constraint\\ExceptionCode' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Exception/ExceptionCode.php',
+        'PHPUnit\\Framework\\Constraint\\ExceptionMessage' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Exception/ExceptionMessage.php',
+        'PHPUnit\\Framework\\Constraint\\ExceptionMessageRegularExpression' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Exception/ExceptionMessageRegularExpression.php',
+        'PHPUnit\\Framework\\Constraint\\FileExists' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Filesystem/FileExists.php',
+        'PHPUnit\\Framework\\Constraint\\GreaterThan' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Cardinality/GreaterThan.php',
+        'PHPUnit\\Framework\\Constraint\\IsAnything' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/IsAnything.php',
+        'PHPUnit\\Framework\\Constraint\\IsEmpty' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Cardinality/IsEmpty.php',
+        'PHPUnit\\Framework\\Constraint\\IsEqual' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Equality/IsEqual.php',
+        'PHPUnit\\Framework\\Constraint\\IsEqualCanonicalizing' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Equality/IsEqualCanonicalizing.php',
+        'PHPUnit\\Framework\\Constraint\\IsEqualIgnoringCase' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Equality/IsEqualIgnoringCase.php',
+        'PHPUnit\\Framework\\Constraint\\IsEqualWithDelta' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Equality/IsEqualWithDelta.php',
+        'PHPUnit\\Framework\\Constraint\\IsFalse' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Boolean/IsFalse.php',
+        'PHPUnit\\Framework\\Constraint\\IsFinite' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Math/IsFinite.php',
+        'PHPUnit\\Framework\\Constraint\\IsIdentical' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/IsIdentical.php',
+        'PHPUnit\\Framework\\Constraint\\IsInfinite' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Math/IsInfinite.php',
+        'PHPUnit\\Framework\\Constraint\\IsInstanceOf' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Type/IsInstanceOf.php',
+        'PHPUnit\\Framework\\Constraint\\IsJson' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/String/IsJson.php',
+        'PHPUnit\\Framework\\Constraint\\IsNan' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Math/IsNan.php',
+        'PHPUnit\\Framework\\Constraint\\IsNull' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Type/IsNull.php',
+        'PHPUnit\\Framework\\Constraint\\IsReadable' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Filesystem/IsReadable.php',
+        'PHPUnit\\Framework\\Constraint\\IsTrue' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Boolean/IsTrue.php',
+        'PHPUnit\\Framework\\Constraint\\IsType' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Type/IsType.php',
+        'PHPUnit\\Framework\\Constraint\\IsWritable' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Filesystem/IsWritable.php',
+        'PHPUnit\\Framework\\Constraint\\JsonMatches' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/JsonMatches.php',
+        'PHPUnit\\Framework\\Constraint\\JsonMatchesErrorMessageProvider' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/JsonMatchesErrorMessageProvider.php',
+        'PHPUnit\\Framework\\Constraint\\LessThan' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Cardinality/LessThan.php',
+        'PHPUnit\\Framework\\Constraint\\LogicalAnd' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Operator/LogicalAnd.php',
+        'PHPUnit\\Framework\\Constraint\\LogicalNot' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Operator/LogicalNot.php',
+        'PHPUnit\\Framework\\Constraint\\LogicalOr' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Operator/LogicalOr.php',
+        'PHPUnit\\Framework\\Constraint\\LogicalXor' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Operator/LogicalXor.php',
+        'PHPUnit\\Framework\\Constraint\\ObjectEquals' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Object/ObjectEquals.php',
+        'PHPUnit\\Framework\\Constraint\\ObjectHasAttribute' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Object/ObjectHasAttribute.php',
+        'PHPUnit\\Framework\\Constraint\\Operator' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Operator/Operator.php',
+        'PHPUnit\\Framework\\Constraint\\RegularExpression' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/String/RegularExpression.php',
+        'PHPUnit\\Framework\\Constraint\\SameSize' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Cardinality/SameSize.php',
+        'PHPUnit\\Framework\\Constraint\\StringContains' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/String/StringContains.php',
+        'PHPUnit\\Framework\\Constraint\\StringEndsWith' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/String/StringEndsWith.php',
+        'PHPUnit\\Framework\\Constraint\\StringMatchesFormatDescription' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/String/StringMatchesFormatDescription.php',
+        'PHPUnit\\Framework\\Constraint\\StringStartsWith' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/String/StringStartsWith.php',
+        'PHPUnit\\Framework\\Constraint\\TraversableContains' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Traversable/TraversableContains.php',
+        'PHPUnit\\Framework\\Constraint\\TraversableContainsEqual' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Traversable/TraversableContainsEqual.php',
+        'PHPUnit\\Framework\\Constraint\\TraversableContainsIdentical' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Traversable/TraversableContainsIdentical.php',
+        'PHPUnit\\Framework\\Constraint\\TraversableContainsOnly' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Traversable/TraversableContainsOnly.php',
+        'PHPUnit\\Framework\\Constraint\\UnaryOperator' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Operator/UnaryOperator.php',
+        'PHPUnit\\Framework\\CoveredCodeNotExecutedException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Exception/CoveredCodeNotExecutedException.php',
+        'PHPUnit\\Framework\\DataProviderTestSuite' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/DataProviderTestSuite.php',
+        'PHPUnit\\Framework\\Error' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Exception/Error.php',
+        'PHPUnit\\Framework\\ErrorTestCase' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/ErrorTestCase.php',
+        'PHPUnit\\Framework\\Error\\Deprecated' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Error/Deprecated.php',
+        'PHPUnit\\Framework\\Error\\Error' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Error/Error.php',
+        'PHPUnit\\Framework\\Error\\Notice' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Error/Notice.php',
+        'PHPUnit\\Framework\\Error\\Warning' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Error/Warning.php',
+        'PHPUnit\\Framework\\Exception' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Exception/Exception.php',
+        'PHPUnit\\Framework\\ExceptionWrapper' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/ExceptionWrapper.php',
+        'PHPUnit\\Framework\\ExecutionOrderDependency' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/ExecutionOrderDependency.php',
+        'PHPUnit\\Framework\\ExpectationFailedException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Exception/ExpectationFailedException.php',
+        'PHPUnit\\Framework\\IncompleteTest' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/IncompleteTest.php',
+        'PHPUnit\\Framework\\IncompleteTestCase' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/IncompleteTestCase.php',
+        'PHPUnit\\Framework\\IncompleteTestError' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Exception/IncompleteTestError.php',
+        'PHPUnit\\Framework\\InvalidArgumentException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Exception/InvalidArgumentException.php',
+        'PHPUnit\\Framework\\InvalidCoversTargetException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Exception/InvalidCoversTargetException.php',
+        'PHPUnit\\Framework\\InvalidDataProviderException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Exception/InvalidDataProviderException.php',
+        'PHPUnit\\Framework\\InvalidParameterGroupException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/InvalidParameterGroupException.php',
+        'PHPUnit\\Framework\\MissingCoversAnnotationException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Exception/MissingCoversAnnotationException.php',
+        'PHPUnit\\Framework\\MockObject\\Api' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Api/Api.php',
+        'PHPUnit\\Framework\\MockObject\\BadMethodCallException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Exception/BadMethodCallException.php',
+        'PHPUnit\\Framework\\MockObject\\Builder\\Identity' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Builder/Identity.php',
+        'PHPUnit\\Framework\\MockObject\\Builder\\InvocationMocker' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Builder/InvocationMocker.php',
+        'PHPUnit\\Framework\\MockObject\\Builder\\InvocationStubber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Builder/InvocationStubber.php',
+        'PHPUnit\\Framework\\MockObject\\Builder\\MethodNameMatch' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Builder/MethodNameMatch.php',
+        'PHPUnit\\Framework\\MockObject\\Builder\\ParametersMatch' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Builder/ParametersMatch.php',
+        'PHPUnit\\Framework\\MockObject\\Builder\\Stub' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Builder/Stub.php',
+        'PHPUnit\\Framework\\MockObject\\CannotUseAddMethodsException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Exception/CannotUseAddMethodsException.php',
+        'PHPUnit\\Framework\\MockObject\\CannotUseOnlyMethodsException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Exception/CannotUseOnlyMethodsException.php',
+        'PHPUnit\\Framework\\MockObject\\ClassAlreadyExistsException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Exception/ClassAlreadyExistsException.php',
+        'PHPUnit\\Framework\\MockObject\\ClassIsFinalException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Exception/ClassIsFinalException.php',
+        'PHPUnit\\Framework\\MockObject\\ConfigurableMethod' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/ConfigurableMethod.php',
+        'PHPUnit\\Framework\\MockObject\\ConfigurableMethodsAlreadyInitializedException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Exception/ConfigurableMethodsAlreadyInitializedException.php',
+        'PHPUnit\\Framework\\MockObject\\DuplicateMethodException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Exception/DuplicateMethodException.php',
+        'PHPUnit\\Framework\\MockObject\\Exception' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Exception/Exception.php',
+        'PHPUnit\\Framework\\MockObject\\Generator' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Generator.php',
+        'PHPUnit\\Framework\\MockObject\\IncompatibleReturnValueException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Exception/IncompatibleReturnValueException.php',
+        'PHPUnit\\Framework\\MockObject\\InvalidMethodNameException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Exception/InvalidMethodNameException.php',
+        'PHPUnit\\Framework\\MockObject\\Invocation' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Invocation.php',
+        'PHPUnit\\Framework\\MockObject\\InvocationHandler' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/InvocationHandler.php',
+        'PHPUnit\\Framework\\MockObject\\MatchBuilderNotFoundException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Exception/MatchBuilderNotFoundException.php',
+        'PHPUnit\\Framework\\MockObject\\Matcher' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Matcher.php',
+        'PHPUnit\\Framework\\MockObject\\MatcherAlreadyRegisteredException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Exception/MatcherAlreadyRegisteredException.php',
+        'PHPUnit\\Framework\\MockObject\\Method' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Api/Method.php',
+        'PHPUnit\\Framework\\MockObject\\MethodCannotBeConfiguredException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Exception/MethodCannotBeConfiguredException.php',
+        'PHPUnit\\Framework\\MockObject\\MethodNameAlreadyConfiguredException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Exception/MethodNameAlreadyConfiguredException.php',
+        'PHPUnit\\Framework\\MockObject\\MethodNameConstraint' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/MethodNameConstraint.php',
+        'PHPUnit\\Framework\\MockObject\\MethodNameNotConfiguredException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Exception/MethodNameNotConfiguredException.php',
+        'PHPUnit\\Framework\\MockObject\\MethodParametersAlreadyConfiguredException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Exception/MethodParametersAlreadyConfiguredException.php',
+        'PHPUnit\\Framework\\MockObject\\MockBuilder' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/MockBuilder.php',
+        'PHPUnit\\Framework\\MockObject\\MockClass' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/MockClass.php',
+        'PHPUnit\\Framework\\MockObject\\MockMethod' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/MockMethod.php',
+        'PHPUnit\\Framework\\MockObject\\MockMethodSet' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/MockMethodSet.php',
+        'PHPUnit\\Framework\\MockObject\\MockObject' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/MockObject.php',
+        'PHPUnit\\Framework\\MockObject\\MockTrait' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/MockTrait.php',
+        'PHPUnit\\Framework\\MockObject\\MockType' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/MockType.php',
+        'PHPUnit\\Framework\\MockObject\\MockedCloneMethod' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Api/MockedCloneMethod.php',
+        'PHPUnit\\Framework\\MockObject\\OriginalConstructorInvocationRequiredException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Exception/OriginalConstructorInvocationRequiredException.php',
+        'PHPUnit\\Framework\\MockObject\\ReflectionException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Exception/ReflectionException.php',
+        'PHPUnit\\Framework\\MockObject\\ReturnValueNotConfiguredException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Exception/ReturnValueNotConfiguredException.php',
+        'PHPUnit\\Framework\\MockObject\\Rule\\AnyInvokedCount' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Rule/AnyInvokedCount.php',
+        'PHPUnit\\Framework\\MockObject\\Rule\\AnyParameters' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Rule/AnyParameters.php',
+        'PHPUnit\\Framework\\MockObject\\Rule\\ConsecutiveParameters' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Rule/ConsecutiveParameters.php',
+        'PHPUnit\\Framework\\MockObject\\Rule\\InvocationOrder' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Rule/InvocationOrder.php',
+        'PHPUnit\\Framework\\MockObject\\Rule\\InvokedAtIndex' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Rule/InvokedAtIndex.php',
+        'PHPUnit\\Framework\\MockObject\\Rule\\InvokedAtLeastCount' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Rule/InvokedAtLeastCount.php',
+        'PHPUnit\\Framework\\MockObject\\Rule\\InvokedAtLeastOnce' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Rule/InvokedAtLeastOnce.php',
+        'PHPUnit\\Framework\\MockObject\\Rule\\InvokedAtMostCount' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Rule/InvokedAtMostCount.php',
+        'PHPUnit\\Framework\\MockObject\\Rule\\InvokedCount' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Rule/InvokedCount.php',
+        'PHPUnit\\Framework\\MockObject\\Rule\\MethodName' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Rule/MethodName.php',
+        'PHPUnit\\Framework\\MockObject\\Rule\\Parameters' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Rule/Parameters.php',
+        'PHPUnit\\Framework\\MockObject\\Rule\\ParametersRule' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Rule/ParametersRule.php',
+        'PHPUnit\\Framework\\MockObject\\RuntimeException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Exception/RuntimeException.php',
+        'PHPUnit\\Framework\\MockObject\\SoapExtensionNotAvailableException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Exception/SoapExtensionNotAvailableException.php',
+        'PHPUnit\\Framework\\MockObject\\Stub' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Stub.php',
+        'PHPUnit\\Framework\\MockObject\\Stub\\ConsecutiveCalls' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Stub/ConsecutiveCalls.php',
+        'PHPUnit\\Framework\\MockObject\\Stub\\Exception' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Stub/Exception.php',
+        'PHPUnit\\Framework\\MockObject\\Stub\\ReturnArgument' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Stub/ReturnArgument.php',
+        'PHPUnit\\Framework\\MockObject\\Stub\\ReturnCallback' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Stub/ReturnCallback.php',
+        'PHPUnit\\Framework\\MockObject\\Stub\\ReturnReference' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Stub/ReturnReference.php',
+        'PHPUnit\\Framework\\MockObject\\Stub\\ReturnSelf' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Stub/ReturnSelf.php',
+        'PHPUnit\\Framework\\MockObject\\Stub\\ReturnStub' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Stub/ReturnStub.php',
+        'PHPUnit\\Framework\\MockObject\\Stub\\ReturnValueMap' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Stub/ReturnValueMap.php',
+        'PHPUnit\\Framework\\MockObject\\Stub\\Stub' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Stub/Stub.php',
+        'PHPUnit\\Framework\\MockObject\\UnknownClassException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Exception/UnknownClassException.php',
+        'PHPUnit\\Framework\\MockObject\\UnknownTraitException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Exception/UnknownTraitException.php',
+        'PHPUnit\\Framework\\MockObject\\UnknownTypeException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Exception/UnknownTypeException.php',
+        'PHPUnit\\Framework\\MockObject\\UnmockedCloneMethod' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Api/UnmockedCloneMethod.php',
+        'PHPUnit\\Framework\\MockObject\\Verifiable' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Verifiable.php',
+        'PHPUnit\\Framework\\NoChildTestSuiteException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Exception/NoChildTestSuiteException.php',
+        'PHPUnit\\Framework\\OutputError' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Exception/OutputError.php',
+        'PHPUnit\\Framework\\PHPTAssertionFailedError' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Exception/PHPTAssertionFailedError.php',
+        'PHPUnit\\Framework\\Reorderable' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Reorderable.php',
+        'PHPUnit\\Framework\\RiskyTestError' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Exception/RiskyTestError.php',
+        'PHPUnit\\Framework\\SelfDescribing' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/SelfDescribing.php',
+        'PHPUnit\\Framework\\SkippedTest' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/SkippedTest.php',
+        'PHPUnit\\Framework\\SkippedTestCase' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/SkippedTestCase.php',
+        'PHPUnit\\Framework\\SkippedTestError' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Exception/SkippedTestError.php',
+        'PHPUnit\\Framework\\SkippedTestSuiteError' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Exception/SkippedTestSuiteError.php',
+        'PHPUnit\\Framework\\SyntheticError' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Exception/SyntheticError.php',
+        'PHPUnit\\Framework\\SyntheticSkippedError' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Exception/SyntheticSkippedError.php',
+        'PHPUnit\\Framework\\Test' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Test.php',
+        'PHPUnit\\Framework\\TestBuilder' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/TestBuilder.php',
+        'PHPUnit\\Framework\\TestCase' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/TestCase.php',
+        'PHPUnit\\Framework\\TestFailure' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/TestFailure.php',
+        'PHPUnit\\Framework\\TestListener' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/TestListener.php',
+        'PHPUnit\\Framework\\TestListenerDefaultImplementation' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/TestListenerDefaultImplementation.php',
+        'PHPUnit\\Framework\\TestResult' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/TestResult.php',
+        'PHPUnit\\Framework\\TestSuite' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/TestSuite.php',
+        'PHPUnit\\Framework\\TestSuiteIterator' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/TestSuiteIterator.php',
+        'PHPUnit\\Framework\\UnintentionallyCoveredCodeError' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Exception/UnintentionallyCoveredCodeError.php',
+        'PHPUnit\\Framework\\Warning' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Exception/Warning.php',
+        'PHPUnit\\Framework\\WarningTestCase' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/WarningTestCase.php',
+        'PHPUnit\\Runner\\AfterIncompleteTestHook' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/Hook/AfterIncompleteTestHook.php',
+        'PHPUnit\\Runner\\AfterLastTestHook' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/Hook/AfterLastTestHook.php',
+        'PHPUnit\\Runner\\AfterRiskyTestHook' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/Hook/AfterRiskyTestHook.php',
+        'PHPUnit\\Runner\\AfterSkippedTestHook' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/Hook/AfterSkippedTestHook.php',
+        'PHPUnit\\Runner\\AfterSuccessfulTestHook' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/Hook/AfterSuccessfulTestHook.php',
+        'PHPUnit\\Runner\\AfterTestErrorHook' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/Hook/AfterTestErrorHook.php',
+        'PHPUnit\\Runner\\AfterTestFailureHook' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/Hook/AfterTestFailureHook.php',
+        'PHPUnit\\Runner\\AfterTestHook' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/Hook/AfterTestHook.php',
+        'PHPUnit\\Runner\\AfterTestWarningHook' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/Hook/AfterTestWarningHook.php',
+        'PHPUnit\\Runner\\BaseTestRunner' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/BaseTestRunner.php',
+        'PHPUnit\\Runner\\BeforeFirstTestHook' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/Hook/BeforeFirstTestHook.php',
+        'PHPUnit\\Runner\\BeforeTestHook' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/Hook/BeforeTestHook.php',
+        'PHPUnit\\Runner\\DefaultTestResultCache' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/DefaultTestResultCache.php',
+        'PHPUnit\\Runner\\Exception' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/Exception.php',
+        'PHPUnit\\Runner\\Extension\\ExtensionHandler' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/Extension/ExtensionHandler.php',
+        'PHPUnit\\Runner\\Extension\\PharLoader' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/Extension/PharLoader.php',
+        'PHPUnit\\Runner\\Filter\\ExcludeGroupFilterIterator' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/Filter/ExcludeGroupFilterIterator.php',
+        'PHPUnit\\Runner\\Filter\\Factory' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/Filter/Factory.php',
+        'PHPUnit\\Runner\\Filter\\GroupFilterIterator' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/Filter/GroupFilterIterator.php',
+        'PHPUnit\\Runner\\Filter\\IncludeGroupFilterIterator' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/Filter/IncludeGroupFilterIterator.php',
+        'PHPUnit\\Runner\\Filter\\NameFilterIterator' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/Filter/NameFilterIterator.php',
+        'PHPUnit\\Runner\\Hook' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/Hook/Hook.php',
+        'PHPUnit\\Runner\\NullTestResultCache' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/NullTestResultCache.php',
+        'PHPUnit\\Runner\\PhptTestCase' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/PhptTestCase.php',
+        'PHPUnit\\Runner\\ResultCacheExtension' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/ResultCacheExtension.php',
+        'PHPUnit\\Runner\\StandardTestSuiteLoader' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/StandardTestSuiteLoader.php',
+        'PHPUnit\\Runner\\TestHook' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/Hook/TestHook.php',
+        'PHPUnit\\Runner\\TestListenerAdapter' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/Hook/TestListenerAdapter.php',
+        'PHPUnit\\Runner\\TestResultCache' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/TestResultCache.php',
+        'PHPUnit\\Runner\\TestSuiteLoader' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/TestSuiteLoader.php',
+        'PHPUnit\\Runner\\TestSuiteSorter' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/TestSuiteSorter.php',
+        'PHPUnit\\Runner\\Version' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/Version.php',
+        'PHPUnit\\TextUI\\CliArguments\\Builder' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/CliArguments/Builder.php',
+        'PHPUnit\\TextUI\\CliArguments\\Configuration' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/CliArguments/Configuration.php',
+        'PHPUnit\\TextUI\\CliArguments\\Exception' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/CliArguments/Exception.php',
+        'PHPUnit\\TextUI\\CliArguments\\Mapper' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/CliArguments/Mapper.php',
+        'PHPUnit\\TextUI\\Command' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Command.php',
+        'PHPUnit\\TextUI\\DefaultResultPrinter' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/DefaultResultPrinter.php',
+        'PHPUnit\\TextUI\\Exception' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Exception/Exception.php',
+        'PHPUnit\\TextUI\\Help' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Help.php',
+        'PHPUnit\\TextUI\\ReflectionException' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Exception/ReflectionException.php',
+        'PHPUnit\\TextUI\\ResultPrinter' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/ResultPrinter.php',
+        'PHPUnit\\TextUI\\RuntimeException' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Exception/RuntimeException.php',
+        'PHPUnit\\TextUI\\TestDirectoryNotFoundException' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Exception/TestDirectoryNotFoundException.php',
+        'PHPUnit\\TextUI\\TestFileNotFoundException' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Exception/TestFileNotFoundException.php',
+        'PHPUnit\\TextUI\\TestRunner' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/TestRunner.php',
+        'PHPUnit\\TextUI\\TestSuiteMapper' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/TestSuiteMapper.php',
+        'PHPUnit\\TextUI\\XmlConfiguration\\CodeCoverage\\CodeCoverage' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/XmlConfiguration/CodeCoverage/CodeCoverage.php',
+        'PHPUnit\\TextUI\\XmlConfiguration\\CodeCoverage\\FilterMapper' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/XmlConfiguration/CodeCoverage/FilterMapper.php',
+        'PHPUnit\\TextUI\\XmlConfiguration\\CodeCoverage\\Filter\\Directory' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/XmlConfiguration/CodeCoverage/Filter/Directory.php',
+        'PHPUnit\\TextUI\\XmlConfiguration\\CodeCoverage\\Filter\\DirectoryCollection' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/XmlConfiguration/CodeCoverage/Filter/DirectoryCollection.php',
+        'PHPUnit\\TextUI\\XmlConfiguration\\CodeCoverage\\Filter\\DirectoryCollectionIterator' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/XmlConfiguration/CodeCoverage/Filter/DirectoryCollectionIterator.php',
+        'PHPUnit\\TextUI\\XmlConfiguration\\CodeCoverage\\Report\\Clover' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/XmlConfiguration/CodeCoverage/Report/Clover.php',
+        'PHPUnit\\TextUI\\XmlConfiguration\\CodeCoverage\\Report\\Cobertura' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/XmlConfiguration/CodeCoverage/Report/Cobertura.php',
+        'PHPUnit\\TextUI\\XmlConfiguration\\CodeCoverage\\Report\\Crap4j' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/XmlConfiguration/CodeCoverage/Report/Crap4j.php',
+        'PHPUnit\\TextUI\\XmlConfiguration\\CodeCoverage\\Report\\Html' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/XmlConfiguration/CodeCoverage/Report/Html.php',
+        'PHPUnit\\TextUI\\XmlConfiguration\\CodeCoverage\\Report\\Php' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/XmlConfiguration/CodeCoverage/Report/Php.php',
+        'PHPUnit\\TextUI\\XmlConfiguration\\CodeCoverage\\Report\\Text' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/XmlConfiguration/CodeCoverage/Report/Text.php',
+        'PHPUnit\\TextUI\\XmlConfiguration\\CodeCoverage\\Report\\Xml' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/XmlConfiguration/CodeCoverage/Report/Xml.php',
+        'PHPUnit\\TextUI\\XmlConfiguration\\Configuration' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Configuration.php',
+        'PHPUnit\\TextUI\\XmlConfiguration\\Constant' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/XmlConfiguration/PHP/Constant.php',
+        'PHPUnit\\TextUI\\XmlConfiguration\\ConstantCollection' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/XmlConfiguration/PHP/ConstantCollection.php',
+        'PHPUnit\\TextUI\\XmlConfiguration\\ConstantCollectionIterator' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/XmlConfiguration/PHP/ConstantCollectionIterator.php',
+        'PHPUnit\\TextUI\\XmlConfiguration\\ConvertLogTypes' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/ConvertLogTypes.php',
+        'PHPUnit\\TextUI\\XmlConfiguration\\CoverageCloverToReport' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/CoverageCloverToReport.php',
+        'PHPUnit\\TextUI\\XmlConfiguration\\CoverageCrap4jToReport' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/CoverageCrap4jToReport.php',
+        'PHPUnit\\TextUI\\XmlConfiguration\\CoverageHtmlToReport' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/CoverageHtmlToReport.php',
+        'PHPUnit\\TextUI\\XmlConfiguration\\CoveragePhpToReport' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/CoveragePhpToReport.php',
+        'PHPUnit\\TextUI\\XmlConfiguration\\CoverageTextToReport' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/CoverageTextToReport.php',
+        'PHPUnit\\TextUI\\XmlConfiguration\\CoverageXmlToReport' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/CoverageXmlToReport.php',
+        'PHPUnit\\TextUI\\XmlConfiguration\\Directory' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Filesystem/Directory.php',
+        'PHPUnit\\TextUI\\XmlConfiguration\\DirectoryCollection' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Filesystem/DirectoryCollection.php',
+        'PHPUnit\\TextUI\\XmlConfiguration\\DirectoryCollectionIterator' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Filesystem/DirectoryCollectionIterator.php',
+        'PHPUnit\\TextUI\\XmlConfiguration\\Exception' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Exception.php',
+        'PHPUnit\\TextUI\\XmlConfiguration\\Extension' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/XmlConfiguration/PHPUnit/Extension.php',
+        'PHPUnit\\TextUI\\XmlConfiguration\\ExtensionCollection' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/XmlConfiguration/PHPUnit/ExtensionCollection.php',
+        'PHPUnit\\TextUI\\XmlConfiguration\\ExtensionCollectionIterator' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/XmlConfiguration/PHPUnit/ExtensionCollectionIterator.php',
+        'PHPUnit\\TextUI\\XmlConfiguration\\File' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Filesystem/File.php',
+        'PHPUnit\\TextUI\\XmlConfiguration\\FileCollection' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Filesystem/FileCollection.php',
+        'PHPUnit\\TextUI\\XmlConfiguration\\FileCollectionIterator' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Filesystem/FileCollectionIterator.php',
+        'PHPUnit\\TextUI\\XmlConfiguration\\Generator' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Generator.php',
+        'PHPUnit\\TextUI\\XmlConfiguration\\Group' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Group/Group.php',
+        'PHPUnit\\TextUI\\XmlConfiguration\\GroupCollection' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Group/GroupCollection.php',
+        'PHPUnit\\TextUI\\XmlConfiguration\\GroupCollectionIterator' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Group/GroupCollectionIterator.php',
+        'PHPUnit\\TextUI\\XmlConfiguration\\Groups' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Group/Groups.php',
+        'PHPUnit\\TextUI\\XmlConfiguration\\IniSetting' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/XmlConfiguration/PHP/IniSetting.php',
+        'PHPUnit\\TextUI\\XmlConfiguration\\IniSettingCollection' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/XmlConfiguration/PHP/IniSettingCollection.php',
+        'PHPUnit\\TextUI\\XmlConfiguration\\IniSettingCollectionIterator' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/XmlConfiguration/PHP/IniSettingCollectionIterator.php',
+        'PHPUnit\\TextUI\\XmlConfiguration\\IntroduceCoverageElement' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/IntroduceCoverageElement.php',
+        'PHPUnit\\TextUI\\XmlConfiguration\\Loader' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Loader.php',
+        'PHPUnit\\TextUI\\XmlConfiguration\\LogToReportMigration' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/LogToReportMigration.php',
+        'PHPUnit\\TextUI\\XmlConfiguration\\Logging\\Junit' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Logging/Junit.php',
+        'PHPUnit\\TextUI\\XmlConfiguration\\Logging\\Logging' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Logging/Logging.php',
+        'PHPUnit\\TextUI\\XmlConfiguration\\Logging\\TeamCity' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Logging/TeamCity.php',
+        'PHPUnit\\TextUI\\XmlConfiguration\\Logging\\TestDox\\Html' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Logging/TestDox/Html.php',
+        'PHPUnit\\TextUI\\XmlConfiguration\\Logging\\TestDox\\Text' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Logging/TestDox/Text.php',
+        'PHPUnit\\TextUI\\XmlConfiguration\\Logging\\TestDox\\Xml' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Logging/TestDox/Xml.php',
+        'PHPUnit\\TextUI\\XmlConfiguration\\Logging\\Text' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Logging/Text.php',
+        'PHPUnit\\TextUI\\XmlConfiguration\\Migration' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/Migration.php',
+        'PHPUnit\\TextUI\\XmlConfiguration\\MigrationBuilder' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/MigrationBuilder.php',
+        'PHPUnit\\TextUI\\XmlConfiguration\\MigrationBuilderException' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/MigrationBuilderException.php',
+        'PHPUnit\\TextUI\\XmlConfiguration\\MigrationException' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/MigrationException.php',
+        'PHPUnit\\TextUI\\XmlConfiguration\\Migrator' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrator.php',
+        'PHPUnit\\TextUI\\XmlConfiguration\\MoveAttributesFromFilterWhitelistToCoverage' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/MoveAttributesFromFilterWhitelistToCoverage.php',
+        'PHPUnit\\TextUI\\XmlConfiguration\\MoveAttributesFromRootToCoverage' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/MoveAttributesFromRootToCoverage.php',
+        'PHPUnit\\TextUI\\XmlConfiguration\\MoveWhitelistDirectoriesToCoverage' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/MoveWhitelistDirectoriesToCoverage.php',
+        'PHPUnit\\TextUI\\XmlConfiguration\\MoveWhitelistExcludesToCoverage' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/MoveWhitelistExcludesToCoverage.php',
+        'PHPUnit\\TextUI\\XmlConfiguration\\PHPUnit' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/XmlConfiguration/PHPUnit/PHPUnit.php',
+        'PHPUnit\\TextUI\\XmlConfiguration\\Php' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/XmlConfiguration/PHP/Php.php',
+        'PHPUnit\\TextUI\\XmlConfiguration\\PhpHandler' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/XmlConfiguration/PHP/PhpHandler.php',
+        'PHPUnit\\TextUI\\XmlConfiguration\\RemoveCacheTokensAttribute' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/RemoveCacheTokensAttribute.php',
+        'PHPUnit\\TextUI\\XmlConfiguration\\RemoveEmptyFilter' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/RemoveEmptyFilter.php',
+        'PHPUnit\\TextUI\\XmlConfiguration\\RemoveLogTypes' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/RemoveLogTypes.php',
+        'PHPUnit\\TextUI\\XmlConfiguration\\TestDirectory' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/XmlConfiguration/TestSuite/TestDirectory.php',
+        'PHPUnit\\TextUI\\XmlConfiguration\\TestDirectoryCollection' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/XmlConfiguration/TestSuite/TestDirectoryCollection.php',
+        'PHPUnit\\TextUI\\XmlConfiguration\\TestDirectoryCollectionIterator' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/XmlConfiguration/TestSuite/TestDirectoryCollectionIterator.php',
+        'PHPUnit\\TextUI\\XmlConfiguration\\TestFile' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/XmlConfiguration/TestSuite/TestFile.php',
+        'PHPUnit\\TextUI\\XmlConfiguration\\TestFileCollection' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/XmlConfiguration/TestSuite/TestFileCollection.php',
+        'PHPUnit\\TextUI\\XmlConfiguration\\TestFileCollectionIterator' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/XmlConfiguration/TestSuite/TestFileCollectionIterator.php',
+        'PHPUnit\\TextUI\\XmlConfiguration\\TestSuite' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/XmlConfiguration/TestSuite/TestSuite.php',
+        'PHPUnit\\TextUI\\XmlConfiguration\\TestSuiteCollection' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/XmlConfiguration/TestSuite/TestSuiteCollection.php',
+        'PHPUnit\\TextUI\\XmlConfiguration\\TestSuiteCollectionIterator' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/XmlConfiguration/TestSuite/TestSuiteCollectionIterator.php',
+        'PHPUnit\\TextUI\\XmlConfiguration\\UpdateSchemaLocationTo93' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/UpdateSchemaLocationTo93.php',
+        'PHPUnit\\TextUI\\XmlConfiguration\\Variable' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/XmlConfiguration/PHP/Variable.php',
+        'PHPUnit\\TextUI\\XmlConfiguration\\VariableCollection' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/XmlConfiguration/PHP/VariableCollection.php',
+        'PHPUnit\\TextUI\\XmlConfiguration\\VariableCollectionIterator' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/XmlConfiguration/PHP/VariableCollectionIterator.php',
+        'PHPUnit\\Util\\Annotation\\DocBlock' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/Annotation/DocBlock.php',
+        'PHPUnit\\Util\\Annotation\\Registry' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/Annotation/Registry.php',
+        'PHPUnit\\Util\\Blacklist' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/Blacklist.php',
+        'PHPUnit\\Util\\Color' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/Color.php',
+        'PHPUnit\\Util\\ErrorHandler' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/ErrorHandler.php',
+        'PHPUnit\\Util\\Exception' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/Exception.php',
+        'PHPUnit\\Util\\ExcludeList' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/ExcludeList.php',
+        'PHPUnit\\Util\\FileLoader' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/FileLoader.php',
+        'PHPUnit\\Util\\Filesystem' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/Filesystem.php',
+        'PHPUnit\\Util\\Filter' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/Filter.php',
+        'PHPUnit\\Util\\GlobalState' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/GlobalState.php',
+        'PHPUnit\\Util\\InvalidDataSetException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/InvalidDataSetException.php',
+        'PHPUnit\\Util\\Json' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/Json.php',
+        'PHPUnit\\Util\\Log\\JUnit' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/Log/JUnit.php',
+        'PHPUnit\\Util\\Log\\TeamCity' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/Log/TeamCity.php',
+        'PHPUnit\\Util\\PHP\\AbstractPhpProcess' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/PHP/AbstractPhpProcess.php',
+        'PHPUnit\\Util\\PHP\\DefaultPhpProcess' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/PHP/DefaultPhpProcess.php',
+        'PHPUnit\\Util\\PHP\\WindowsPhpProcess' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/PHP/WindowsPhpProcess.php',
+        'PHPUnit\\Util\\Printer' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/Printer.php',
+        'PHPUnit\\Util\\RegularExpression' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/RegularExpression.php',
+        'PHPUnit\\Util\\Test' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/Test.php',
+        'PHPUnit\\Util\\TestDox\\CliTestDoxPrinter' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/TestDox/CliTestDoxPrinter.php',
+        'PHPUnit\\Util\\TestDox\\HtmlResultPrinter' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/TestDox/HtmlResultPrinter.php',
+        'PHPUnit\\Util\\TestDox\\NamePrettifier' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/TestDox/NamePrettifier.php',
+        'PHPUnit\\Util\\TestDox\\ResultPrinter' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/TestDox/ResultPrinter.php',
+        'PHPUnit\\Util\\TestDox\\TestDoxPrinter' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/TestDox/TestDoxPrinter.php',
+        'PHPUnit\\Util\\TestDox\\TextResultPrinter' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/TestDox/TextResultPrinter.php',
+        'PHPUnit\\Util\\TestDox\\XmlResultPrinter' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/TestDox/XmlResultPrinter.php',
+        'PHPUnit\\Util\\TextTestListRenderer' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/TextTestListRenderer.php',
+        'PHPUnit\\Util\\Type' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/Type.php',
+        'PHPUnit\\Util\\VersionComparisonOperator' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/VersionComparisonOperator.php',
+        'PHPUnit\\Util\\XdebugFilterScriptGenerator' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/XdebugFilterScriptGenerator.php',
+        'PHPUnit\\Util\\Xml' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/Xml.php',
+        'PHPUnit\\Util\\XmlTestListRenderer' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/XmlTestListRenderer.php',
+        'PHPUnit\\Util\\Xml\\Exception' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/Xml/Exception.php',
+        'PHPUnit\\Util\\Xml\\FailedSchemaDetectionResult' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/Xml/FailedSchemaDetectionResult.php',
+        'PHPUnit\\Util\\Xml\\Loader' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/Xml/Loader.php',
+        'PHPUnit\\Util\\Xml\\SchemaDetectionResult' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/Xml/SchemaDetectionResult.php',
+        'PHPUnit\\Util\\Xml\\SchemaDetector' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/Xml/SchemaDetector.php',
+        'PHPUnit\\Util\\Xml\\SchemaFinder' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/Xml/SchemaFinder.php',
+        'PHPUnit\\Util\\Xml\\SnapshotNodeList' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/Xml/SnapshotNodeList.php',
+        'PHPUnit\\Util\\Xml\\SuccessfulSchemaDetectionResult' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/Xml/SuccessfulSchemaDetectionResult.php',
+        'PHPUnit\\Util\\Xml\\ValidationResult' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/Xml/ValidationResult.php',
+        'PHPUnit\\Util\\Xml\\Validator' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/Xml/Validator.php',
+        'PharIo\\Manifest\\Application' => __DIR__ . '/..' . '/phar-io/manifest/src/values/Application.php',
+        'PharIo\\Manifest\\ApplicationName' => __DIR__ . '/..' . '/phar-io/manifest/src/values/ApplicationName.php',
+        'PharIo\\Manifest\\Author' => __DIR__ . '/..' . '/phar-io/manifest/src/values/Author.php',
+        'PharIo\\Manifest\\AuthorCollection' => __DIR__ . '/..' . '/phar-io/manifest/src/values/AuthorCollection.php',
+        'PharIo\\Manifest\\AuthorCollectionIterator' => __DIR__ . '/..' . '/phar-io/manifest/src/values/AuthorCollectionIterator.php',
+        'PharIo\\Manifest\\AuthorElement' => __DIR__ . '/..' . '/phar-io/manifest/src/xml/AuthorElement.php',
+        'PharIo\\Manifest\\AuthorElementCollection' => __DIR__ . '/..' . '/phar-io/manifest/src/xml/AuthorElementCollection.php',
+        'PharIo\\Manifest\\BundledComponent' => __DIR__ . '/..' . '/phar-io/manifest/src/values/BundledComponent.php',
+        'PharIo\\Manifest\\BundledComponentCollection' => __DIR__ . '/..' . '/phar-io/manifest/src/values/BundledComponentCollection.php',
+        'PharIo\\Manifest\\BundledComponentCollectionIterator' => __DIR__ . '/..' . '/phar-io/manifest/src/values/BundledComponentCollectionIterator.php',
+        'PharIo\\Manifest\\BundlesElement' => __DIR__ . '/..' . '/phar-io/manifest/src/xml/BundlesElement.php',
+        'PharIo\\Manifest\\ComponentElement' => __DIR__ . '/..' . '/phar-io/manifest/src/xml/ComponentElement.php',
+        'PharIo\\Manifest\\ComponentElementCollection' => __DIR__ . '/..' . '/phar-io/manifest/src/xml/ComponentElementCollection.php',
+        'PharIo\\Manifest\\ContainsElement' => __DIR__ . '/..' . '/phar-io/manifest/src/xml/ContainsElement.php',
+        'PharIo\\Manifest\\CopyrightElement' => __DIR__ . '/..' . '/phar-io/manifest/src/xml/CopyrightElement.php',
+        'PharIo\\Manifest\\CopyrightInformation' => __DIR__ . '/..' . '/phar-io/manifest/src/values/CopyrightInformation.php',
+        'PharIo\\Manifest\\ElementCollection' => __DIR__ . '/..' . '/phar-io/manifest/src/xml/ElementCollection.php',
+        'PharIo\\Manifest\\ElementCollectionException' => __DIR__ . '/..' . '/phar-io/manifest/src/exceptions/ElementCollectionException.php',
+        'PharIo\\Manifest\\Email' => __DIR__ . '/..' . '/phar-io/manifest/src/values/Email.php',
+        'PharIo\\Manifest\\Exception' => __DIR__ . '/..' . '/phar-io/manifest/src/exceptions/Exception.php',
+        'PharIo\\Manifest\\ExtElement' => __DIR__ . '/..' . '/phar-io/manifest/src/xml/ExtElement.php',
+        'PharIo\\Manifest\\ExtElementCollection' => __DIR__ . '/..' . '/phar-io/manifest/src/xml/ExtElementCollection.php',
+        'PharIo\\Manifest\\Extension' => __DIR__ . '/..' . '/phar-io/manifest/src/values/Extension.php',
+        'PharIo\\Manifest\\ExtensionElement' => __DIR__ . '/..' . '/phar-io/manifest/src/xml/ExtensionElement.php',
+        'PharIo\\Manifest\\InvalidApplicationNameException' => __DIR__ . '/..' . '/phar-io/manifest/src/exceptions/InvalidApplicationNameException.php',
+        'PharIo\\Manifest\\InvalidEmailException' => __DIR__ . '/..' . '/phar-io/manifest/src/exceptions/InvalidEmailException.php',
+        'PharIo\\Manifest\\InvalidUrlException' => __DIR__ . '/..' . '/phar-io/manifest/src/exceptions/InvalidUrlException.php',
+        'PharIo\\Manifest\\Library' => __DIR__ . '/..' . '/phar-io/manifest/src/values/Library.php',
+        'PharIo\\Manifest\\License' => __DIR__ . '/..' . '/phar-io/manifest/src/values/License.php',
+        'PharIo\\Manifest\\LicenseElement' => __DIR__ . '/..' . '/phar-io/manifest/src/xml/LicenseElement.php',
+        'PharIo\\Manifest\\Manifest' => __DIR__ . '/..' . '/phar-io/manifest/src/values/Manifest.php',
+        'PharIo\\Manifest\\ManifestDocument' => __DIR__ . '/..' . '/phar-io/manifest/src/xml/ManifestDocument.php',
+        'PharIo\\Manifest\\ManifestDocumentException' => __DIR__ . '/..' . '/phar-io/manifest/src/exceptions/ManifestDocumentException.php',
+        'PharIo\\Manifest\\ManifestDocumentLoadingException' => __DIR__ . '/..' . '/phar-io/manifest/src/exceptions/ManifestDocumentLoadingException.php',
+        'PharIo\\Manifest\\ManifestDocumentMapper' => __DIR__ . '/..' . '/phar-io/manifest/src/ManifestDocumentMapper.php',
+        'PharIo\\Manifest\\ManifestDocumentMapperException' => __DIR__ . '/..' . '/phar-io/manifest/src/exceptions/ManifestDocumentMapperException.php',
+        'PharIo\\Manifest\\ManifestElement' => __DIR__ . '/..' . '/phar-io/manifest/src/xml/ManifestElement.php',
+        'PharIo\\Manifest\\ManifestElementException' => __DIR__ . '/..' . '/phar-io/manifest/src/exceptions/ManifestElementException.php',
+        'PharIo\\Manifest\\ManifestLoader' => __DIR__ . '/..' . '/phar-io/manifest/src/ManifestLoader.php',
+        'PharIo\\Manifest\\ManifestLoaderException' => __DIR__ . '/..' . '/phar-io/manifest/src/exceptions/ManifestLoaderException.php',
+        'PharIo\\Manifest\\ManifestSerializer' => __DIR__ . '/..' . '/phar-io/manifest/src/ManifestSerializer.php',
+        'PharIo\\Manifest\\PhpElement' => __DIR__ . '/..' . '/phar-io/manifest/src/xml/PhpElement.php',
+        'PharIo\\Manifest\\PhpExtensionRequirement' => __DIR__ . '/..' . '/phar-io/manifest/src/values/PhpExtensionRequirement.php',
+        'PharIo\\Manifest\\PhpVersionRequirement' => __DIR__ . '/..' . '/phar-io/manifest/src/values/PhpVersionRequirement.php',
+        'PharIo\\Manifest\\Requirement' => __DIR__ . '/..' . '/phar-io/manifest/src/values/Requirement.php',
+        'PharIo\\Manifest\\RequirementCollection' => __DIR__ . '/..' . '/phar-io/manifest/src/values/RequirementCollection.php',
+        'PharIo\\Manifest\\RequirementCollectionIterator' => __DIR__ . '/..' . '/phar-io/manifest/src/values/RequirementCollectionIterator.php',
+        'PharIo\\Manifest\\RequiresElement' => __DIR__ . '/..' . '/phar-io/manifest/src/xml/RequiresElement.php',
+        'PharIo\\Manifest\\Type' => __DIR__ . '/..' . '/phar-io/manifest/src/values/Type.php',
+        'PharIo\\Manifest\\Url' => __DIR__ . '/..' . '/phar-io/manifest/src/values/Url.php',
+        'PharIo\\Version\\AbstractVersionConstraint' => __DIR__ . '/..' . '/phar-io/version/src/constraints/AbstractVersionConstraint.php',
+        'PharIo\\Version\\AndVersionConstraintGroup' => __DIR__ . '/..' . '/phar-io/version/src/constraints/AndVersionConstraintGroup.php',
+        'PharIo\\Version\\AnyVersionConstraint' => __DIR__ . '/..' . '/phar-io/version/src/constraints/AnyVersionConstraint.php',
+        'PharIo\\Version\\ExactVersionConstraint' => __DIR__ . '/..' . '/phar-io/version/src/constraints/ExactVersionConstraint.php',
+        'PharIo\\Version\\Exception' => __DIR__ . '/..' . '/phar-io/version/src/exceptions/Exception.php',
+        'PharIo\\Version\\GreaterThanOrEqualToVersionConstraint' => __DIR__ . '/..' . '/phar-io/version/src/constraints/GreaterThanOrEqualToVersionConstraint.php',
+        'PharIo\\Version\\InvalidPreReleaseSuffixException' => __DIR__ . '/..' . '/phar-io/version/src/exceptions/InvalidPreReleaseSuffixException.php',
+        'PharIo\\Version\\InvalidVersionException' => __DIR__ . '/..' . '/phar-io/version/src/exceptions/InvalidVersionException.php',
+        'PharIo\\Version\\NoPreReleaseSuffixException' => __DIR__ . '/..' . '/phar-io/version/src/exceptions/NoPreReleaseSuffixException.php',
+        'PharIo\\Version\\OrVersionConstraintGroup' => __DIR__ . '/..' . '/phar-io/version/src/constraints/OrVersionConstraintGroup.php',
+        'PharIo\\Version\\PreReleaseSuffix' => __DIR__ . '/..' . '/phar-io/version/src/PreReleaseSuffix.php',
+        'PharIo\\Version\\SpecificMajorAndMinorVersionConstraint' => __DIR__ . '/..' . '/phar-io/version/src/constraints/SpecificMajorAndMinorVersionConstraint.php',
+        'PharIo\\Version\\SpecificMajorVersionConstraint' => __DIR__ . '/..' . '/phar-io/version/src/constraints/SpecificMajorVersionConstraint.php',
+        'PharIo\\Version\\UnsupportedVersionConstraintException' => __DIR__ . '/..' . '/phar-io/version/src/exceptions/UnsupportedVersionConstraintException.php',
+        'PharIo\\Version\\Version' => __DIR__ . '/..' . '/phar-io/version/src/Version.php',
+        'PharIo\\Version\\VersionConstraint' => __DIR__ . '/..' . '/phar-io/version/src/constraints/VersionConstraint.php',
+        'PharIo\\Version\\VersionConstraintParser' => __DIR__ . '/..' . '/phar-io/version/src/VersionConstraintParser.php',
+        'PharIo\\Version\\VersionConstraintValue' => __DIR__ . '/..' . '/phar-io/version/src/VersionConstraintValue.php',
+        'PharIo\\Version\\VersionNumber' => __DIR__ . '/..' . '/phar-io/version/src/VersionNumber.php',
         'QRcode' => __DIR__ . '/..' . '/tecnickcom/tcpdf/include/barcodes/qrcode.php',
+        'SebastianBergmann\\CliParser\\AmbiguousOptionException' => __DIR__ . '/..' . '/sebastian/cli-parser/src/exceptions/AmbiguousOptionException.php',
+        'SebastianBergmann\\CliParser\\Exception' => __DIR__ . '/..' . '/sebastian/cli-parser/src/exceptions/Exception.php',
+        'SebastianBergmann\\CliParser\\OptionDoesNotAllowArgumentException' => __DIR__ . '/..' . '/sebastian/cli-parser/src/exceptions/OptionDoesNotAllowArgumentException.php',
+        'SebastianBergmann\\CliParser\\Parser' => __DIR__ . '/..' . '/sebastian/cli-parser/src/Parser.php',
+        'SebastianBergmann\\CliParser\\RequiredOptionArgumentMissingException' => __DIR__ . '/..' . '/sebastian/cli-parser/src/exceptions/RequiredOptionArgumentMissingException.php',
+        'SebastianBergmann\\CliParser\\UnknownOptionException' => __DIR__ . '/..' . '/sebastian/cli-parser/src/exceptions/UnknownOptionException.php',
+        'SebastianBergmann\\CodeCoverage\\BranchAndPathCoverageNotSupportedException' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Exception/BranchAndPathCoverageNotSupportedException.php',
+        'SebastianBergmann\\CodeCoverage\\CodeCoverage' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/CodeCoverage.php',
+        'SebastianBergmann\\CodeCoverage\\CrapIndex' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/CrapIndex.php',
+        'SebastianBergmann\\CodeCoverage\\DeadCodeDetectionNotSupportedException' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Exception/DeadCodeDetectionNotSupportedException.php',
+        'SebastianBergmann\\CodeCoverage\\Directory' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Directory.php',
+        'SebastianBergmann\\CodeCoverage\\DirectoryCouldNotBeCreatedException' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Exception/DirectoryCouldNotBeCreatedException.php',
+        'SebastianBergmann\\CodeCoverage\\Driver\\Driver' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Driver/Driver.php',
+        'SebastianBergmann\\CodeCoverage\\Driver\\PathExistsButIsNotDirectoryException' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Exception/PathExistsButIsNotDirectoryException.php',
+        'SebastianBergmann\\CodeCoverage\\Driver\\PcovDriver' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Driver/PcovDriver.php',
+        'SebastianBergmann\\CodeCoverage\\Driver\\PcovNotAvailableException' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Exception/PcovNotAvailableException.php',
+        'SebastianBergmann\\CodeCoverage\\Driver\\PhpdbgDriver' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Driver/PhpdbgDriver.php',
+        'SebastianBergmann\\CodeCoverage\\Driver\\PhpdbgNotAvailableException' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Exception/PhpdbgNotAvailableException.php',
+        'SebastianBergmann\\CodeCoverage\\Driver\\Selector' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Driver/Selector.php',
+        'SebastianBergmann\\CodeCoverage\\Driver\\WriteOperationFailedException' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Exception/WriteOperationFailedException.php',
+        'SebastianBergmann\\CodeCoverage\\Driver\\WrongXdebugVersionException' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Exception/WrongXdebugVersionException.php',
+        'SebastianBergmann\\CodeCoverage\\Driver\\Xdebug2Driver' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Driver/Xdebug2Driver.php',
+        'SebastianBergmann\\CodeCoverage\\Driver\\Xdebug2NotEnabledException' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Exception/Xdebug2NotEnabledException.php',
+        'SebastianBergmann\\CodeCoverage\\Driver\\Xdebug3Driver' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Driver/Xdebug3Driver.php',
+        'SebastianBergmann\\CodeCoverage\\Driver\\Xdebug3NotEnabledException' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Exception/Xdebug3NotEnabledException.php',
+        'SebastianBergmann\\CodeCoverage\\Driver\\XdebugNotAvailableException' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Exception/XdebugNotAvailableException.php',
+        'SebastianBergmann\\CodeCoverage\\Exception' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Exception/Exception.php',
+        'SebastianBergmann\\CodeCoverage\\Filter' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Filter.php',
+        'SebastianBergmann\\CodeCoverage\\InvalidArgumentException' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Exception/InvalidArgumentException.php',
+        'SebastianBergmann\\CodeCoverage\\NoCodeCoverageDriverAvailableException' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Exception/NoCodeCoverageDriverAvailableException.php',
+        'SebastianBergmann\\CodeCoverage\\NoCodeCoverageDriverWithPathCoverageSupportAvailableException' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Exception/NoCodeCoverageDriverWithPathCoverageSupportAvailableException.php',
+        'SebastianBergmann\\CodeCoverage\\Node\\AbstractNode' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Node/AbstractNode.php',
+        'SebastianBergmann\\CodeCoverage\\Node\\Builder' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Node/Builder.php',
+        'SebastianBergmann\\CodeCoverage\\Node\\Directory' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Node/Directory.php',
+        'SebastianBergmann\\CodeCoverage\\Node\\File' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Node/File.php',
+        'SebastianBergmann\\CodeCoverage\\Node\\Iterator' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Node/Iterator.php',
+        'SebastianBergmann\\CodeCoverage\\ParserException' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Exception/ParserException.php',
+        'SebastianBergmann\\CodeCoverage\\Percentage' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Percentage.php',
+        'SebastianBergmann\\CodeCoverage\\ProcessedCodeCoverageData' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/ProcessedCodeCoverageData.php',
+        'SebastianBergmann\\CodeCoverage\\RawCodeCoverageData' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/RawCodeCoverageData.php',
+        'SebastianBergmann\\CodeCoverage\\ReflectionException' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Exception/ReflectionException.php',
+        'SebastianBergmann\\CodeCoverage\\ReportAlreadyFinalizedException' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Exception/ReportAlreadyFinalizedException.php',
+        'SebastianBergmann\\CodeCoverage\\Report\\Clover' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Report/Clover.php',
+        'SebastianBergmann\\CodeCoverage\\Report\\Cobertura' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Report/Cobertura.php',
+        'SebastianBergmann\\CodeCoverage\\Report\\Crap4j' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Report/Crap4j.php',
+        'SebastianBergmann\\CodeCoverage\\Report\\Html\\Dashboard' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Report/Html/Renderer/Dashboard.php',
+        'SebastianBergmann\\CodeCoverage\\Report\\Html\\Directory' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Report/Html/Renderer/Directory.php',
+        'SebastianBergmann\\CodeCoverage\\Report\\Html\\Facade' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Report/Html/Facade.php',
+        'SebastianBergmann\\CodeCoverage\\Report\\Html\\File' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Report/Html/Renderer/File.php',
+        'SebastianBergmann\\CodeCoverage\\Report\\Html\\Renderer' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Report/Html/Renderer.php',
+        'SebastianBergmann\\CodeCoverage\\Report\\PHP' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Report/PHP.php',
+        'SebastianBergmann\\CodeCoverage\\Report\\Text' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Report/Text.php',
+        'SebastianBergmann\\CodeCoverage\\Report\\Xml\\BuildInformation' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Report/Xml/BuildInformation.php',
+        'SebastianBergmann\\CodeCoverage\\Report\\Xml\\Coverage' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Report/Xml/Coverage.php',
+        'SebastianBergmann\\CodeCoverage\\Report\\Xml\\Directory' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Report/Xml/Directory.php',
+        'SebastianBergmann\\CodeCoverage\\Report\\Xml\\Facade' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Report/Xml/Facade.php',
+        'SebastianBergmann\\CodeCoverage\\Report\\Xml\\File' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Report/Xml/File.php',
+        'SebastianBergmann\\CodeCoverage\\Report\\Xml\\Method' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Report/Xml/Method.php',
+        'SebastianBergmann\\CodeCoverage\\Report\\Xml\\Node' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Report/Xml/Node.php',
+        'SebastianBergmann\\CodeCoverage\\Report\\Xml\\Project' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Report/Xml/Project.php',
+        'SebastianBergmann\\CodeCoverage\\Report\\Xml\\Report' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Report/Xml/Report.php',
+        'SebastianBergmann\\CodeCoverage\\Report\\Xml\\Source' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Report/Xml/Source.php',
+        'SebastianBergmann\\CodeCoverage\\Report\\Xml\\Tests' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Report/Xml/Tests.php',
+        'SebastianBergmann\\CodeCoverage\\Report\\Xml\\Totals' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Report/Xml/Totals.php',
+        'SebastianBergmann\\CodeCoverage\\Report\\Xml\\Unit' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Report/Xml/Unit.php',
+        'SebastianBergmann\\CodeCoverage\\StaticAnalysisCacheNotConfiguredException' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Exception/StaticAnalysisCacheNotConfiguredException.php',
+        'SebastianBergmann\\CodeCoverage\\StaticAnalysis\\Cache' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/StaticAnalysis/Cache.php',
+        'SebastianBergmann\\CodeCoverage\\StaticAnalysis\\CacheWarmer' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/StaticAnalysis/CacheWarmer.php',
+        'SebastianBergmann\\CodeCoverage\\StaticAnalysis\\CachingCoveredFileAnalyser' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/StaticAnalysis/CachingCoveredFileAnalyser.php',
+        'SebastianBergmann\\CodeCoverage\\StaticAnalysis\\CachingUncoveredFileAnalyser' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/StaticAnalysis/CachingUncoveredFileAnalyser.php',
+        'SebastianBergmann\\CodeCoverage\\StaticAnalysis\\CodeUnitFindingVisitor' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/StaticAnalysis/CodeUnitFindingVisitor.php',
+        'SebastianBergmann\\CodeCoverage\\StaticAnalysis\\CoveredFileAnalyser' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/StaticAnalysis/CoveredFileAnalyser.php',
+        'SebastianBergmann\\CodeCoverage\\StaticAnalysis\\ExecutableLinesFindingVisitor' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/StaticAnalysis/ExecutableLinesFindingVisitor.php',
+        'SebastianBergmann\\CodeCoverage\\StaticAnalysis\\IgnoredLinesFindingVisitor' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/StaticAnalysis/IgnoredLinesFindingVisitor.php',
+        'SebastianBergmann\\CodeCoverage\\StaticAnalysis\\ParsingCoveredFileAnalyser' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/StaticAnalysis/ParsingCoveredFileAnalyser.php',
+        'SebastianBergmann\\CodeCoverage\\StaticAnalysis\\ParsingUncoveredFileAnalyser' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/StaticAnalysis/ParsingUncoveredFileAnalyser.php',
+        'SebastianBergmann\\CodeCoverage\\StaticAnalysis\\UncoveredFileAnalyser' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/StaticAnalysis/UncoveredFileAnalyser.php',
+        'SebastianBergmann\\CodeCoverage\\TestIdMissingException' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Exception/TestIdMissingException.php',
+        'SebastianBergmann\\CodeCoverage\\UnintentionallyCoveredCodeException' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Exception/UnintentionallyCoveredCodeException.php',
+        'SebastianBergmann\\CodeCoverage\\Version' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Version.php',
+        'SebastianBergmann\\CodeCoverage\\XmlException' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Exception/XmlException.php',
+        'SebastianBergmann\\CodeUnitReverseLookup\\Wizard' => __DIR__ . '/..' . '/sebastian/code-unit-reverse-lookup/src/Wizard.php',
+        'SebastianBergmann\\CodeUnit\\ClassMethodUnit' => __DIR__ . '/..' . '/sebastian/code-unit/src/ClassMethodUnit.php',
+        'SebastianBergmann\\CodeUnit\\ClassUnit' => __DIR__ . '/..' . '/sebastian/code-unit/src/ClassUnit.php',
+        'SebastianBergmann\\CodeUnit\\CodeUnit' => __DIR__ . '/..' . '/sebastian/code-unit/src/CodeUnit.php',
+        'SebastianBergmann\\CodeUnit\\CodeUnitCollection' => __DIR__ . '/..' . '/sebastian/code-unit/src/CodeUnitCollection.php',
+        'SebastianBergmann\\CodeUnit\\CodeUnitCollectionIterator' => __DIR__ . '/..' . '/sebastian/code-unit/src/CodeUnitCollectionIterator.php',
+        'SebastianBergmann\\CodeUnit\\Exception' => __DIR__ . '/..' . '/sebastian/code-unit/src/exceptions/Exception.php',
+        'SebastianBergmann\\CodeUnit\\FunctionUnit' => __DIR__ . '/..' . '/sebastian/code-unit/src/FunctionUnit.php',
+        'SebastianBergmann\\CodeUnit\\InterfaceMethodUnit' => __DIR__ . '/..' . '/sebastian/code-unit/src/InterfaceMethodUnit.php',
+        'SebastianBergmann\\CodeUnit\\InterfaceUnit' => __DIR__ . '/..' . '/sebastian/code-unit/src/InterfaceUnit.php',
+        'SebastianBergmann\\CodeUnit\\InvalidCodeUnitException' => __DIR__ . '/..' . '/sebastian/code-unit/src/exceptions/InvalidCodeUnitException.php',
+        'SebastianBergmann\\CodeUnit\\Mapper' => __DIR__ . '/..' . '/sebastian/code-unit/src/Mapper.php',
+        'SebastianBergmann\\CodeUnit\\NoTraitException' => __DIR__ . '/..' . '/sebastian/code-unit/src/exceptions/NoTraitException.php',
+        'SebastianBergmann\\CodeUnit\\ReflectionException' => __DIR__ . '/..' . '/sebastian/code-unit/src/exceptions/ReflectionException.php',
+        'SebastianBergmann\\CodeUnit\\TraitMethodUnit' => __DIR__ . '/..' . '/sebastian/code-unit/src/TraitMethodUnit.php',
+        'SebastianBergmann\\CodeUnit\\TraitUnit' => __DIR__ . '/..' . '/sebastian/code-unit/src/TraitUnit.php',
+        'SebastianBergmann\\Comparator\\ArrayComparator' => __DIR__ . '/..' . '/sebastian/comparator/src/ArrayComparator.php',
+        'SebastianBergmann\\Comparator\\Comparator' => __DIR__ . '/..' . '/sebastian/comparator/src/Comparator.php',
+        'SebastianBergmann\\Comparator\\ComparisonFailure' => __DIR__ . '/..' . '/sebastian/comparator/src/ComparisonFailure.php',
+        'SebastianBergmann\\Comparator\\DOMNodeComparator' => __DIR__ . '/..' . '/sebastian/comparator/src/DOMNodeComparator.php',
+        'SebastianBergmann\\Comparator\\DateTimeComparator' => __DIR__ . '/..' . '/sebastian/comparator/src/DateTimeComparator.php',
+        'SebastianBergmann\\Comparator\\DoubleComparator' => __DIR__ . '/..' . '/sebastian/comparator/src/DoubleComparator.php',
+        'SebastianBergmann\\Comparator\\Exception' => __DIR__ . '/..' . '/sebastian/comparator/src/exceptions/Exception.php',
+        'SebastianBergmann\\Comparator\\ExceptionComparator' => __DIR__ . '/..' . '/sebastian/comparator/src/ExceptionComparator.php',
+        'SebastianBergmann\\Comparator\\Factory' => __DIR__ . '/..' . '/sebastian/comparator/src/Factory.php',
+        'SebastianBergmann\\Comparator\\MockObjectComparator' => __DIR__ . '/..' . '/sebastian/comparator/src/MockObjectComparator.php',
+        'SebastianBergmann\\Comparator\\NumericComparator' => __DIR__ . '/..' . '/sebastian/comparator/src/NumericComparator.php',
+        'SebastianBergmann\\Comparator\\ObjectComparator' => __DIR__ . '/..' . '/sebastian/comparator/src/ObjectComparator.php',
+        'SebastianBergmann\\Comparator\\ResourceComparator' => __DIR__ . '/..' . '/sebastian/comparator/src/ResourceComparator.php',
+        'SebastianBergmann\\Comparator\\RuntimeException' => __DIR__ . '/..' . '/sebastian/comparator/src/exceptions/RuntimeException.php',
+        'SebastianBergmann\\Comparator\\ScalarComparator' => __DIR__ . '/..' . '/sebastian/comparator/src/ScalarComparator.php',
+        'SebastianBergmann\\Comparator\\SplObjectStorageComparator' => __DIR__ . '/..' . '/sebastian/comparator/src/SplObjectStorageComparator.php',
+        'SebastianBergmann\\Comparator\\TypeComparator' => __DIR__ . '/..' . '/sebastian/comparator/src/TypeComparator.php',
+        'SebastianBergmann\\Complexity\\Calculator' => __DIR__ . '/..' . '/sebastian/complexity/src/Calculator.php',
+        'SebastianBergmann\\Complexity\\Complexity' => __DIR__ . '/..' . '/sebastian/complexity/src/Complexity/Complexity.php',
+        'SebastianBergmann\\Complexity\\ComplexityCalculatingVisitor' => __DIR__ . '/..' . '/sebastian/complexity/src/Visitor/ComplexityCalculatingVisitor.php',
+        'SebastianBergmann\\Complexity\\ComplexityCollection' => __DIR__ . '/..' . '/sebastian/complexity/src/Complexity/ComplexityCollection.php',
+        'SebastianBergmann\\Complexity\\ComplexityCollectionIterator' => __DIR__ . '/..' . '/sebastian/complexity/src/Complexity/ComplexityCollectionIterator.php',
+        'SebastianBergmann\\Complexity\\CyclomaticComplexityCalculatingVisitor' => __DIR__ . '/..' . '/sebastian/complexity/src/Visitor/CyclomaticComplexityCalculatingVisitor.php',
+        'SebastianBergmann\\Complexity\\Exception' => __DIR__ . '/..' . '/sebastian/complexity/src/Exception/Exception.php',
+        'SebastianBergmann\\Complexity\\RuntimeException' => __DIR__ . '/..' . '/sebastian/complexity/src/Exception/RuntimeException.php',
+        'SebastianBergmann\\Diff\\Chunk' => __DIR__ . '/..' . '/sebastian/diff/src/Chunk.php',
+        'SebastianBergmann\\Diff\\ConfigurationException' => __DIR__ . '/..' . '/sebastian/diff/src/Exception/ConfigurationException.php',
+        'SebastianBergmann\\Diff\\Diff' => __DIR__ . '/..' . '/sebastian/diff/src/Diff.php',
+        'SebastianBergmann\\Diff\\Differ' => __DIR__ . '/..' . '/sebastian/diff/src/Differ.php',
+        'SebastianBergmann\\Diff\\Exception' => __DIR__ . '/..' . '/sebastian/diff/src/Exception/Exception.php',
+        'SebastianBergmann\\Diff\\InvalidArgumentException' => __DIR__ . '/..' . '/sebastian/diff/src/Exception/InvalidArgumentException.php',
+        'SebastianBergmann\\Diff\\Line' => __DIR__ . '/..' . '/sebastian/diff/src/Line.php',
+        'SebastianBergmann\\Diff\\LongestCommonSubsequenceCalculator' => __DIR__ . '/..' . '/sebastian/diff/src/LongestCommonSubsequenceCalculator.php',
+        'SebastianBergmann\\Diff\\MemoryEfficientLongestCommonSubsequenceCalculator' => __DIR__ . '/..' . '/sebastian/diff/src/MemoryEfficientLongestCommonSubsequenceCalculator.php',
+        'SebastianBergmann\\Diff\\Output\\AbstractChunkOutputBuilder' => __DIR__ . '/..' . '/sebastian/diff/src/Output/AbstractChunkOutputBuilder.php',
+        'SebastianBergmann\\Diff\\Output\\DiffOnlyOutputBuilder' => __DIR__ . '/..' . '/sebastian/diff/src/Output/DiffOnlyOutputBuilder.php',
+        'SebastianBergmann\\Diff\\Output\\DiffOutputBuilderInterface' => __DIR__ . '/..' . '/sebastian/diff/src/Output/DiffOutputBuilderInterface.php',
+        'SebastianBergmann\\Diff\\Output\\StrictUnifiedDiffOutputBuilder' => __DIR__ . '/..' . '/sebastian/diff/src/Output/StrictUnifiedDiffOutputBuilder.php',
+        'SebastianBergmann\\Diff\\Output\\UnifiedDiffOutputBuilder' => __DIR__ . '/..' . '/sebastian/diff/src/Output/UnifiedDiffOutputBuilder.php',
+        'SebastianBergmann\\Diff\\Parser' => __DIR__ . '/..' . '/sebastian/diff/src/Parser.php',
+        'SebastianBergmann\\Diff\\TimeEfficientLongestCommonSubsequenceCalculator' => __DIR__ . '/..' . '/sebastian/diff/src/TimeEfficientLongestCommonSubsequenceCalculator.php',
+        'SebastianBergmann\\Environment\\Console' => __DIR__ . '/..' . '/sebastian/environment/src/Console.php',
+        'SebastianBergmann\\Environment\\OperatingSystem' => __DIR__ . '/..' . '/sebastian/environment/src/OperatingSystem.php',
+        'SebastianBergmann\\Environment\\Runtime' => __DIR__ . '/..' . '/sebastian/environment/src/Runtime.php',
+        'SebastianBergmann\\Exporter\\Exporter' => __DIR__ . '/..' . '/sebastian/exporter/src/Exporter.php',
+        'SebastianBergmann\\FileIterator\\Facade' => __DIR__ . '/..' . '/phpunit/php-file-iterator/src/Facade.php',
+        'SebastianBergmann\\FileIterator\\Factory' => __DIR__ . '/..' . '/phpunit/php-file-iterator/src/Factory.php',
+        'SebastianBergmann\\FileIterator\\Iterator' => __DIR__ . '/..' . '/phpunit/php-file-iterator/src/Iterator.php',
+        'SebastianBergmann\\GlobalState\\CodeExporter' => __DIR__ . '/..' . '/sebastian/global-state/src/CodeExporter.php',
+        'SebastianBergmann\\GlobalState\\Exception' => __DIR__ . '/..' . '/sebastian/global-state/src/exceptions/Exception.php',
+        'SebastianBergmann\\GlobalState\\ExcludeList' => __DIR__ . '/..' . '/sebastian/global-state/src/ExcludeList.php',
+        'SebastianBergmann\\GlobalState\\Restorer' => __DIR__ . '/..' . '/sebastian/global-state/src/Restorer.php',
+        'SebastianBergmann\\GlobalState\\RuntimeException' => __DIR__ . '/..' . '/sebastian/global-state/src/exceptions/RuntimeException.php',
+        'SebastianBergmann\\GlobalState\\Snapshot' => __DIR__ . '/..' . '/sebastian/global-state/src/Snapshot.php',
+        'SebastianBergmann\\Invoker\\Exception' => __DIR__ . '/..' . '/phpunit/php-invoker/src/exceptions/Exception.php',
+        'SebastianBergmann\\Invoker\\Invoker' => __DIR__ . '/..' . '/phpunit/php-invoker/src/Invoker.php',
+        'SebastianBergmann\\Invoker\\ProcessControlExtensionNotLoadedException' => __DIR__ . '/..' . '/phpunit/php-invoker/src/exceptions/ProcessControlExtensionNotLoadedException.php',
+        'SebastianBergmann\\Invoker\\TimeoutException' => __DIR__ . '/..' . '/phpunit/php-invoker/src/exceptions/TimeoutException.php',
+        'SebastianBergmann\\LinesOfCode\\Counter' => __DIR__ . '/..' . '/sebastian/lines-of-code/src/Counter.php',
+        'SebastianBergmann\\LinesOfCode\\Exception' => __DIR__ . '/..' . '/sebastian/lines-of-code/src/Exception/Exception.php',
+        'SebastianBergmann\\LinesOfCode\\IllogicalValuesException' => __DIR__ . '/..' . '/sebastian/lines-of-code/src/Exception/IllogicalValuesException.php',
+        'SebastianBergmann\\LinesOfCode\\LineCountingVisitor' => __DIR__ . '/..' . '/sebastian/lines-of-code/src/LineCountingVisitor.php',
+        'SebastianBergmann\\LinesOfCode\\LinesOfCode' => __DIR__ . '/..' . '/sebastian/lines-of-code/src/LinesOfCode.php',
+        'SebastianBergmann\\LinesOfCode\\NegativeValueException' => __DIR__ . '/..' . '/sebastian/lines-of-code/src/Exception/NegativeValueException.php',
+        'SebastianBergmann\\LinesOfCode\\RuntimeException' => __DIR__ . '/..' . '/sebastian/lines-of-code/src/Exception/RuntimeException.php',
+        'SebastianBergmann\\ObjectEnumerator\\Enumerator' => __DIR__ . '/..' . '/sebastian/object-enumerator/src/Enumerator.php',
+        'SebastianBergmann\\ObjectEnumerator\\Exception' => __DIR__ . '/..' . '/sebastian/object-enumerator/src/Exception.php',
+        'SebastianBergmann\\ObjectEnumerator\\InvalidArgumentException' => __DIR__ . '/..' . '/sebastian/object-enumerator/src/InvalidArgumentException.php',
+        'SebastianBergmann\\ObjectReflector\\Exception' => __DIR__ . '/..' . '/sebastian/object-reflector/src/Exception.php',
+        'SebastianBergmann\\ObjectReflector\\InvalidArgumentException' => __DIR__ . '/..' . '/sebastian/object-reflector/src/InvalidArgumentException.php',
+        'SebastianBergmann\\ObjectReflector\\ObjectReflector' => __DIR__ . '/..' . '/sebastian/object-reflector/src/ObjectReflector.php',
+        'SebastianBergmann\\RecursionContext\\Context' => __DIR__ . '/..' . '/sebastian/recursion-context/src/Context.php',
+        'SebastianBergmann\\RecursionContext\\Exception' => __DIR__ . '/..' . '/sebastian/recursion-context/src/Exception.php',
+        'SebastianBergmann\\RecursionContext\\InvalidArgumentException' => __DIR__ . '/..' . '/sebastian/recursion-context/src/InvalidArgumentException.php',
+        'SebastianBergmann\\ResourceOperations\\ResourceOperations' => __DIR__ . '/..' . '/sebastian/resource-operations/src/ResourceOperations.php',
+        'SebastianBergmann\\Template\\Exception' => __DIR__ . '/..' . '/phpunit/php-text-template/src/exceptions/Exception.php',
+        'SebastianBergmann\\Template\\InvalidArgumentException' => __DIR__ . '/..' . '/phpunit/php-text-template/src/exceptions/InvalidArgumentException.php',
+        'SebastianBergmann\\Template\\RuntimeException' => __DIR__ . '/..' . '/phpunit/php-text-template/src/exceptions/RuntimeException.php',
+        'SebastianBergmann\\Template\\Template' => __DIR__ . '/..' . '/phpunit/php-text-template/src/Template.php',
+        'SebastianBergmann\\Timer\\Duration' => __DIR__ . '/..' . '/phpunit/php-timer/src/Duration.php',
+        'SebastianBergmann\\Timer\\Exception' => __DIR__ . '/..' . '/phpunit/php-timer/src/exceptions/Exception.php',
+        'SebastianBergmann\\Timer\\NoActiveTimerException' => __DIR__ . '/..' . '/phpunit/php-timer/src/exceptions/NoActiveTimerException.php',
+        'SebastianBergmann\\Timer\\ResourceUsageFormatter' => __DIR__ . '/..' . '/phpunit/php-timer/src/ResourceUsageFormatter.php',
+        'SebastianBergmann\\Timer\\TimeSinceStartOfRequestNotAvailableException' => __DIR__ . '/..' . '/phpunit/php-timer/src/exceptions/TimeSinceStartOfRequestNotAvailableException.php',
+        'SebastianBergmann\\Timer\\Timer' => __DIR__ . '/..' . '/phpunit/php-timer/src/Timer.php',
+        'SebastianBergmann\\Type\\CallableType' => __DIR__ . '/..' . '/sebastian/type/src/CallableType.php',
+        'SebastianBergmann\\Type\\Exception' => __DIR__ . '/..' . '/sebastian/type/src/exception/Exception.php',
+        'SebastianBergmann\\Type\\GenericObjectType' => __DIR__ . '/..' . '/sebastian/type/src/GenericObjectType.php',
+        'SebastianBergmann\\Type\\IterableType' => __DIR__ . '/..' . '/sebastian/type/src/IterableType.php',
+        'SebastianBergmann\\Type\\MixedType' => __DIR__ . '/..' . '/sebastian/type/src/MixedType.php',
+        'SebastianBergmann\\Type\\NullType' => __DIR__ . '/..' . '/sebastian/type/src/NullType.php',
+        'SebastianBergmann\\Type\\ObjectType' => __DIR__ . '/..' . '/sebastian/type/src/ObjectType.php',
+        'SebastianBergmann\\Type\\ReflectionMapper' => __DIR__ . '/..' . '/sebastian/type/src/ReflectionMapper.php',
+        'SebastianBergmann\\Type\\RuntimeException' => __DIR__ . '/..' . '/sebastian/type/src/exception/RuntimeException.php',
+        'SebastianBergmann\\Type\\SimpleType' => __DIR__ . '/..' . '/sebastian/type/src/SimpleType.php',
+        'SebastianBergmann\\Type\\StaticType' => __DIR__ . '/..' . '/sebastian/type/src/StaticType.php',
+        'SebastianBergmann\\Type\\Type' => __DIR__ . '/..' . '/sebastian/type/src/Type.php',
+        'SebastianBergmann\\Type\\TypeName' => __DIR__ . '/..' . '/sebastian/type/src/TypeName.php',
+        'SebastianBergmann\\Type\\UnionType' => __DIR__ . '/..' . '/sebastian/type/src/UnionType.php',
+        'SebastianBergmann\\Type\\UnknownType' => __DIR__ . '/..' . '/sebastian/type/src/UnknownType.php',
+        'SebastianBergmann\\Type\\VoidType' => __DIR__ . '/..' . '/sebastian/type/src/VoidType.php',
+        'SebastianBergmann\\Version' => __DIR__ . '/..' . '/sebastian/version/src/Version.php',
         'TCPDF' => __DIR__ . '/..' . '/tecnickcom/tcpdf/tcpdf.php',
         'TCPDF2DBarcode' => __DIR__ . '/..' . '/tecnickcom/tcpdf/tcpdf_barcodes_2d.php',
         'TCPDFBarcode' => __DIR__ . '/..' . '/tecnickcom/tcpdf/tcpdf_barcodes_1d.php',
@@ -194,6 +868,14 @@ class ComposerStaticInit637514d10f1ed5d4c55a005a428a3656
         'TCPDF_IMPORT' => __DIR__ . '/..' . '/tecnickcom/tcpdf/tcpdf_import.php',
         'TCPDF_PARSER' => __DIR__ . '/..' . '/tecnickcom/tcpdf/tcpdf_parser.php',
         'TCPDF_STATIC' => __DIR__ . '/..' . '/tecnickcom/tcpdf/include/tcpdf_static.php',
+        'TheSeer\\Tokenizer\\Exception' => __DIR__ . '/..' . '/theseer/tokenizer/src/Exception.php',
+        'TheSeer\\Tokenizer\\NamespaceUri' => __DIR__ . '/..' . '/theseer/tokenizer/src/NamespaceUri.php',
+        'TheSeer\\Tokenizer\\NamespaceUriException' => __DIR__ . '/..' . '/theseer/tokenizer/src/NamespaceUriException.php',
+        'TheSeer\\Tokenizer\\Token' => __DIR__ . '/..' . '/theseer/tokenizer/src/Token.php',
+        'TheSeer\\Tokenizer\\TokenCollection' => __DIR__ . '/..' . '/theseer/tokenizer/src/TokenCollection.php',
+        'TheSeer\\Tokenizer\\TokenCollectionException' => __DIR__ . '/..' . '/theseer/tokenizer/src/TokenCollectionException.php',
+        'TheSeer\\Tokenizer\\Tokenizer' => __DIR__ . '/..' . '/theseer/tokenizer/src/Tokenizer.php',
+        'TheSeer\\Tokenizer\\XMLSerializer' => __DIR__ . '/..' . '/theseer/tokenizer/src/XMLSerializer.php',
     );
 
     public static function getInitializer(ClassLoader $loader)
diff --git a/vendor/composer/installed.json b/vendor/composer/installed.json
index 5580051759cea041d90e82271b6f1ce51c9660ec..0591631c26cdede978339a8b0532a7440f4f2621 100644
--- a/vendor/composer/installed.json
+++ b/vendor/composer/installed.json
@@ -1,60 +1,153 @@
 [
     {
-        "name": "container-interop/container-interop",
-        "version": "1.2.0",
-        "version_normalized": "1.2.0.0",
+        "name": "christian-riesen/otp",
+        "version": "2.6.2",
+        "version_normalized": "2.6.2.0",
         "source": {
             "type": "git",
-            "url": "https://github.com/container-interop/container-interop.git",
-            "reference": "79cbf1341c22ec75643d841642dd5d6acd83bdb8"
+            "url": "https://github.com/ChristianRiesen/otp.git",
+            "reference": "67d3351e9614458f937b4f058791f7e695c9a0c7"
         },
         "dist": {
             "type": "zip",
-            "url": "https://api.github.com/repos/container-interop/container-interop/zipball/79cbf1341c22ec75643d841642dd5d6acd83bdb8",
-            "reference": "79cbf1341c22ec75643d841642dd5d6acd83bdb8",
+            "url": "https://api.github.com/repos/ChristianRiesen/otp/zipball/67d3351e9614458f937b4f058791f7e695c9a0c7",
+            "reference": "67d3351e9614458f937b4f058791f7e695c9a0c7",
             "shasum": ""
         },
         "require": {
-            "psr/container": "^1.0"
+            "paragonie/constant_time_encoding": "^1|^2",
+            "paragonie/random_compat": ">=1",
+            "php": ">=5.4.0",
+            "symfony/polyfill-php56": "^1"
+        },
+        "require-dev": {
+            "phpunit/phpunit": "^4.8.35 || ^5.7.11 || ^6.0.5"
+        },
+        "time": "2019-01-25T10:00:06+00:00",
+        "type": "library",
+        "extra": {
+            "branch-alias": {
+                "dev-master": "2.x-dev"
+            }
+        },
+        "installation-source": "dist",
+        "autoload": {
+            "psr-4": {
+                "Otp\\": "src/"
+            }
+        },
+        "notification-url": "https://packagist.org/downloads/",
+        "license": [
+            "MIT"
+        ],
+        "authors": [
+            {
+                "name": "Christian Riesen",
+                "email": "chris.riesen@gmail.com",
+                "homepage": "http://christianriesen.com",
+                "role": "Developer"
+            }
+        ],
+        "description": "One Time Passwords, hotp and totp according to RFC4226 and RFC6238",
+        "homepage": "https://github.com/ChristianRiesen/otp",
+        "keywords": [
+            "googleauthenticator",
+            "hotp",
+            "otp",
+            "rfc4226",
+            "rfc6238",
+            "totp"
+        ]
+    },
+    {
+        "name": "doctrine/instantiator",
+        "version": "1.4.0",
+        "version_normalized": "1.4.0.0",
+        "source": {
+            "type": "git",
+            "url": "https://github.com/doctrine/instantiator.git",
+            "reference": "d56bf6102915de5702778fe20f2de3b2fe570b5b"
+        },
+        "dist": {
+            "type": "zip",
+            "url": "https://api.github.com/repos/doctrine/instantiator/zipball/d56bf6102915de5702778fe20f2de3b2fe570b5b",
+            "reference": "d56bf6102915de5702778fe20f2de3b2fe570b5b",
+            "shasum": ""
+        },
+        "require": {
+            "php": "^7.1 || ^8.0"
         },
-        "time": "2017-02-14T19:40:03+00:00",
+        "require-dev": {
+            "doctrine/coding-standard": "^8.0",
+            "ext-pdo": "*",
+            "ext-phar": "*",
+            "phpbench/phpbench": "^0.13 || 1.0.0-alpha2",
+            "phpstan/phpstan": "^0.12",
+            "phpstan/phpstan-phpunit": "^0.12",
+            "phpunit/phpunit": "^7.0 || ^8.0 || ^9.0"
+        },
+        "time": "2020-11-10T18:47:58+00:00",
         "type": "library",
         "installation-source": "dist",
         "autoload": {
             "psr-4": {
-                "Interop\\Container\\": "src/Interop/Container/"
+                "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/"
             }
         },
         "notification-url": "https://packagist.org/downloads/",
         "license": [
             "MIT"
         ],
-        "description": "Promoting the interoperability of container objects (DIC, SL, etc.)",
-        "homepage": "https://github.com/container-interop/container-interop",
-        "abandoned": "psr/container"
+        "authors": [
+            {
+                "name": "Marco Pivetta",
+                "email": "ocramius@gmail.com",
+                "homepage": "https://ocramius.github.io/"
+            }
+        ],
+        "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors",
+        "homepage": "https://www.doctrine-project.org/projects/instantiator.html",
+        "keywords": [
+            "constructor",
+            "instantiate"
+        ],
+        "funding": [
+            {
+                "url": "https://www.doctrine-project.org/sponsorship.html",
+                "type": "custom"
+            },
+            {
+                "url": "https://www.patreon.com/phpdoctrine",
+                "type": "patreon"
+            },
+            {
+                "url": "https://tidelift.com/funding/github/packagist/doctrine%2Finstantiator",
+                "type": "tidelift"
+            }
+        ]
     },
     {
         "name": "firebase/php-jwt",
-        "version": "v5.0.0",
-        "version_normalized": "5.0.0.0",
+        "version": "v5.2.0",
+        "version_normalized": "5.2.0.0",
         "source": {
             "type": "git",
             "url": "https://github.com/firebase/php-jwt.git",
-            "reference": "9984a4d3a32ae7673d6971ea00bae9d0a1abba0e"
+            "reference": "feb0e820b8436873675fd3aca04f3728eb2185cb"
         },
         "dist": {
             "type": "zip",
-            "url": "https://api.github.com/repos/firebase/php-jwt/zipball/9984a4d3a32ae7673d6971ea00bae9d0a1abba0e",
-            "reference": "9984a4d3a32ae7673d6971ea00bae9d0a1abba0e",
+            "url": "https://api.github.com/repos/firebase/php-jwt/zipball/feb0e820b8436873675fd3aca04f3728eb2185cb",
+            "reference": "feb0e820b8436873675fd3aca04f3728eb2185cb",
             "shasum": ""
         },
         "require": {
             "php": ">=5.3.0"
         },
         "require-dev": {
-            "phpunit/phpunit": " 4.8.35"
+            "phpunit/phpunit": ">=4.8 <=9"
         },
-        "time": "2017-06-27T22:17:23+00:00",
+        "time": "2020-03-25T18:49:23+00:00",
         "type": "library",
         "installation-source": "dist",
         "autoload": {
@@ -79,7 +172,67 @@
             }
         ],
         "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"
+        "homepage": "https://github.com/firebase/php-jwt",
+        "keywords": [
+            "jwt",
+            "php"
+        ]
+    },
+    {
+        "name": "myclabs/deep-copy",
+        "version": "1.10.2",
+        "version_normalized": "1.10.2.0",
+        "source": {
+            "type": "git",
+            "url": "https://github.com/myclabs/DeepCopy.git",
+            "reference": "776f831124e9c62e1a2c601ecc52e776d8bb7220"
+        },
+        "dist": {
+            "type": "zip",
+            "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/776f831124e9c62e1a2c601ecc52e776d8bb7220",
+            "reference": "776f831124e9c62e1a2c601ecc52e776d8bb7220",
+            "shasum": ""
+        },
+        "require": {
+            "php": "^7.1 || ^8.0"
+        },
+        "replace": {
+            "myclabs/deep-copy": "self.version"
+        },
+        "require-dev": {
+            "doctrine/collections": "^1.0",
+            "doctrine/common": "^2.6",
+            "phpunit/phpunit": "^7.1"
+        },
+        "time": "2020-11-13T09:40:50+00:00",
+        "type": "library",
+        "installation-source": "dist",
+        "autoload": {
+            "psr-4": {
+                "DeepCopy\\": "src/DeepCopy/"
+            },
+            "files": [
+                "src/DeepCopy/deep_copy.php"
+            ]
+        },
+        "notification-url": "https://packagist.org/downloads/",
+        "license": [
+            "MIT"
+        ],
+        "description": "Create deep copies (clones) of your objects",
+        "keywords": [
+            "clone",
+            "copy",
+            "duplicate",
+            "object",
+            "object graph"
+        ],
+        "funding": [
+            {
+                "url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy",
+                "type": "tidelift"
+            }
+        ]
     },
     {
         "name": "nikic/fast-route",
@@ -130,106 +283,87 @@
         ]
     },
     {
-        "name": "phpmailer/phpmailer",
-        "version": "v6.0.7",
-        "version_normalized": "6.0.7.0",
+        "name": "nikic/php-parser",
+        "version": "v4.10.4",
+        "version_normalized": "4.10.4.0",
         "source": {
             "type": "git",
-            "url": "https://github.com/PHPMailer/PHPMailer.git",
-            "reference": "0c41a36d4508d470e376498c1c0c527aa36a2d59"
+            "url": "https://github.com/nikic/PHP-Parser.git",
+            "reference": "c6d052fc58cb876152f89f532b95a8d7907e7f0e"
         },
         "dist": {
             "type": "zip",
-            "url": "https://api.github.com/repos/PHPMailer/PHPMailer/zipball/0c41a36d4508d470e376498c1c0c527aa36a2d59",
-            "reference": "0c41a36d4508d470e376498c1c0c527aa36a2d59",
+            "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/c6d052fc58cb876152f89f532b95a8d7907e7f0e",
+            "reference": "c6d052fc58cb876152f89f532b95a8d7907e7f0e",
             "shasum": ""
         },
         "require": {
-            "ext-ctype": "*",
-            "ext-filter": "*",
-            "php": ">=5.5.0"
+            "ext-tokenizer": "*",
+            "php": ">=7.0"
         },
         "require-dev": {
-            "doctrine/annotations": "1.2.*",
-            "friendsofphp/php-cs-fixer": "^2.2",
-            "phpdocumentor/phpdocumentor": "2.*",
-            "phpunit/phpunit": "^4.8 || ^5.7",
-            "zendframework/zend-eventmanager": "3.0.*",
-            "zendframework/zend-i18n": "2.7.3",
-            "zendframework/zend-serializer": "2.7.*"
-        },
-        "suggest": {
-            "ext-mbstring": "Needed to send email in multibyte encoding charset",
-            "hayageek/oauth2-yahoo": "Needed for Yahoo XOAUTH2 authentication",
-            "league/oauth2-google": "Needed for Google XOAUTH2 authentication",
-            "psr/log": "For optional PSR-3 debug logging",
-            "stevenmaguire/oauth2-microsoft": "Needed for Microsoft XOAUTH2 authentication",
-            "symfony/polyfill-mbstring": "To support UTF-8 if the Mbstring PHP extension is not enabled (^1.2)"
+            "ircmaxell/php-yacc": "^0.0.7",
+            "phpunit/phpunit": "^6.5 || ^7.0 || ^8.0 || ^9.0"
         },
-        "time": "2019-02-01T15:04:28+00:00",
+        "time": "2020-12-20T10:01:03+00:00",
+        "bin": [
+            "bin/php-parse"
+        ],
         "type": "library",
+        "extra": {
+            "branch-alias": {
+                "dev-master": "4.9-dev"
+            }
+        },
         "installation-source": "dist",
         "autoload": {
             "psr-4": {
-                "PHPMailer\\PHPMailer\\": "src/"
+                "PhpParser\\": "lib/PhpParser"
             }
         },
         "notification-url": "https://packagist.org/downloads/",
         "license": [
-            "LGPL-2.1"
+            "BSD-3-Clause"
         ],
         "authors": [
             {
-                "name": "Jim Jagielski",
-                "email": "jimjag@gmail.com"
-            },
-            {
-                "name": "Marcus Bointon",
-                "email": "phpmailer@synchromedia.co.uk"
-            },
-            {
-                "name": "Andy Prevost",
-                "email": "codeworxtech@users.sourceforge.net"
-            },
-            {
-                "name": "Brent R. Matzelle"
+                "name": "Nikita Popov"
             }
         ],
-        "description": "PHPMailer is a full-featured email creation and transfer class for PHP"
+        "description": "A PHP parser written in PHP",
+        "keywords": [
+            "parser",
+            "php"
+        ]
     },
     {
-        "name": "pimple/pimple",
-        "version": "v3.2.3",
-        "version_normalized": "3.2.3.0",
+        "name": "paragonie/constant_time_encoding",
+        "version": "v2.3.0",
+        "version_normalized": "2.3.0.0",
         "source": {
             "type": "git",
-            "url": "https://github.com/silexphp/Pimple.git",
-            "reference": "9e403941ef9d65d20cba7d54e29fe906db42cf32"
+            "url": "https://github.com/paragonie/constant_time_encoding.git",
+            "reference": "47a1cedd2e4d52688eb8c96469c05ebc8fd28fa2"
         },
         "dist": {
             "type": "zip",
-            "url": "https://api.github.com/repos/silexphp/Pimple/zipball/9e403941ef9d65d20cba7d54e29fe906db42cf32",
-            "reference": "9e403941ef9d65d20cba7d54e29fe906db42cf32",
+            "url": "https://api.github.com/repos/paragonie/constant_time_encoding/zipball/47a1cedd2e4d52688eb8c96469c05ebc8fd28fa2",
+            "reference": "47a1cedd2e4d52688eb8c96469c05ebc8fd28fa2",
             "shasum": ""
         },
         "require": {
-            "php": ">=5.3.0",
-            "psr/container": "^1.0"
+            "php": "^7|^8"
         },
         "require-dev": {
-            "symfony/phpunit-bridge": "^3.2"
+            "phpunit/phpunit": "^6|^7",
+            "vimeo/psalm": "^1|^2|^3"
         },
-        "time": "2018-01-21T07:42:36+00:00",
+        "time": "2019-11-06T19:20:29+00:00",
         "type": "library",
-        "extra": {
-            "branch-alias": {
-                "dev-master": "3.2.x-dev"
-            }
-        },
         "installation-source": "dist",
         "autoload": {
-            "psr-0": {
-                "Pimple": "src/"
+            "psr-4": {
+                "ParagonIE\\ConstantTime\\": "src/"
             }
         },
         "notification-url": "https://packagist.org/downloads/",
@@ -238,170 +372,1089 @@
         ],
         "authors": [
             {
-                "name": "Fabien Potencier",
-                "email": "fabien@symfony.com"
+                "name": "Paragon Initiative Enterprises",
+                "email": "security@paragonie.com",
+                "homepage": "https://paragonie.com",
+                "role": "Maintainer"
+            },
+            {
+                "name": "Steve 'Sc00bz' Thomas",
+                "email": "steve@tobtu.com",
+                "homepage": "https://www.tobtu.com",
+                "role": "Original Developer"
             }
         ],
-        "description": "Pimple, a simple Dependency Injection Container",
-        "homepage": "http://pimple.sensiolabs.org",
+        "description": "Constant-time Implementations of RFC 4648 Encoding (Base-64, Base-32, Base-16)",
         "keywords": [
-            "container",
-            "dependency injection"
+            "base16",
+            "base32",
+            "base32_decode",
+            "base32_encode",
+            "base64",
+            "base64_decode",
+            "base64_encode",
+            "bin2hex",
+            "encoding",
+            "hex",
+            "hex2bin",
+            "rfc4648"
         ]
     },
     {
-        "name": "psr/container",
-        "version": "1.0.0",
-        "version_normalized": "1.0.0.0",
+        "name": "paragonie/random_compat",
+        "version": "v9.99.99",
+        "version_normalized": "9.99.99.0",
         "source": {
             "type": "git",
-            "url": "https://github.com/php-fig/container.git",
-            "reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f"
+            "url": "https://github.com/paragonie/random_compat.git",
+            "reference": "84b4dfb120c6f9b4ff7b3685f9b8f1aa365a0c95"
         },
         "dist": {
             "type": "zip",
-            "url": "https://api.github.com/repos/php-fig/container/zipball/b7ce3b176482dbbc1245ebf52b181af44c2cf55f",
-            "reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f",
+            "url": "https://api.github.com/repos/paragonie/random_compat/zipball/84b4dfb120c6f9b4ff7b3685f9b8f1aa365a0c95",
+            "reference": "84b4dfb120c6f9b4ff7b3685f9b8f1aa365a0c95",
             "shasum": ""
         },
         "require": {
-            "php": ">=5.3.0"
+            "php": "^7"
         },
-        "time": "2017-02-14T16:28:37+00:00",
-        "type": "library",
-        "extra": {
-            "branch-alias": {
-                "dev-master": "1.0.x-dev"
-            }
+        "require-dev": {
+            "phpunit/phpunit": "4.*|5.*",
+            "vimeo/psalm": "^1"
         },
-        "installation-source": "dist",
-        "autoload": {
-            "psr-4": {
-                "Psr\\Container\\": "src/"
-            }
+        "suggest": {
+            "ext-libsodium": "Provides a modern crypto API that can be used to generate random bytes."
         },
+        "time": "2018-07-02T15:55:56+00:00",
+        "type": "library",
+        "installation-source": "dist",
         "notification-url": "https://packagist.org/downloads/",
         "license": [
             "MIT"
         ],
         "authors": [
             {
-                "name": "PHP-FIG",
-                "homepage": "http://www.php-fig.org/"
+                "name": "Paragon Initiative Enterprises",
+                "email": "security@paragonie.com",
+                "homepage": "https://paragonie.com"
             }
         ],
-        "description": "Common Container Interface (PHP FIG PSR-11)",
-        "homepage": "https://github.com/php-fig/container",
+        "description": "PHP 5.x polyfill for random_bytes() and random_int() from PHP 7",
         "keywords": [
-            "PSR-11",
-            "container",
-            "container-interface",
-            "container-interop",
-            "psr"
+            "csprng",
+            "polyfill",
+            "pseudorandom",
+            "random"
         ]
     },
     {
-        "name": "psr/http-message",
-        "version": "1.0.1",
-        "version_normalized": "1.0.1.0",
+        "name": "phar-io/manifest",
+        "version": "2.0.1",
+        "version_normalized": "2.0.1.0",
         "source": {
             "type": "git",
-            "url": "https://github.com/php-fig/http-message.git",
-            "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363"
+            "url": "https://github.com/phar-io/manifest.git",
+            "reference": "85265efd3af7ba3ca4b2a2c34dbfc5788dd29133"
         },
         "dist": {
             "type": "zip",
-            "url": "https://api.github.com/repos/php-fig/http-message/zipball/f6561bf28d520154e4b0ec72be95418abe6d9363",
-            "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363",
+            "url": "https://api.github.com/repos/phar-io/manifest/zipball/85265efd3af7ba3ca4b2a2c34dbfc5788dd29133",
+            "reference": "85265efd3af7ba3ca4b2a2c34dbfc5788dd29133",
             "shasum": ""
         },
         "require": {
-            "php": ">=5.3.0"
+            "ext-dom": "*",
+            "ext-phar": "*",
+            "ext-xmlwriter": "*",
+            "phar-io/version": "^3.0.1",
+            "php": "^7.2 || ^8.0"
         },
-        "time": "2016-08-06T14:39:51+00:00",
+        "time": "2020-06-27T14:33:11+00:00",
         "type": "library",
         "extra": {
             "branch-alias": {
-                "dev-master": "1.0.x-dev"
+                "dev-master": "2.0.x-dev"
             }
         },
         "installation-source": "dist",
         "autoload": {
-            "psr-4": {
-                "Psr\\Http\\Message\\": "src/"
-            }
+            "classmap": [
+                "src/"
+            ]
         },
         "notification-url": "https://packagist.org/downloads/",
         "license": [
-            "MIT"
+            "BSD-3-Clause"
         ],
         "authors": [
             {
-                "name": "PHP-FIG",
-                "homepage": "http://www.php-fig.org/"
+                "name": "Arne Blankerts",
+                "email": "arne@blankerts.de",
+                "role": "Developer"
+            },
+            {
+                "name": "Sebastian Heuer",
+                "email": "sebastian@phpeople.de",
+                "role": "Developer"
+            },
+            {
+                "name": "Sebastian Bergmann",
+                "email": "sebastian@phpunit.de",
+                "role": "Developer"
             }
         ],
-        "description": "Common interface for HTTP messages",
-        "homepage": "https://github.com/php-fig/http-message",
-        "keywords": [
-            "http",
-            "http-message",
-            "psr",
-            "psr-7",
-            "request",
-            "response"
-        ]
+        "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)"
     },
     {
-        "name": "respect/validation",
-        "version": "1.1.29",
-        "version_normalized": "1.1.29.0",
+        "name": "phar-io/version",
+        "version": "3.1.0",
+        "version_normalized": "3.1.0.0",
         "source": {
             "type": "git",
-            "url": "https://github.com/Respect/Validation.git",
-            "reference": "f8c90fa36859ca41c766efcf0c476d58913a7767"
+            "url": "https://github.com/phar-io/version.git",
+            "reference": "bae7c545bef187884426f042434e561ab1ddb182"
         },
         "dist": {
             "type": "zip",
-            "url": "https://api.github.com/repos/Respect/Validation/zipball/f8c90fa36859ca41c766efcf0c476d58913a7767",
-            "reference": "f8c90fa36859ca41c766efcf0c476d58913a7767",
+            "url": "https://api.github.com/repos/phar-io/version/zipball/bae7c545bef187884426f042434e561ab1ddb182",
+            "reference": "bae7c545bef187884426f042434e561ab1ddb182",
             "shasum": ""
         },
         "require": {
-            "php": ">=5.4",
-            "symfony/polyfill-mbstring": "^1.2"
+            "php": "^7.2 || ^8.0"
         },
-        "require-dev": {
-            "egulias/email-validator": "~1.2 || ~2.1",
-            "mikey179/vfsstream": "^1.5",
-            "phpunit/phpunit": "~4.0",
-            "symfony/validator": "~2.6.9",
-            "zendframework/zend-validator": "~2.3"
+        "time": "2021-02-23T14:00:09+00:00",
+        "type": "library",
+        "installation-source": "dist",
+        "autoload": {
+            "classmap": [
+                "src/"
+            ]
         },
-        "suggest": {
-            "egulias/email-validator": "Strict (RFC compliant) email validation",
-            "ext-bcmath": "Arbitrary Precision Mathematics",
-            "ext-mbstring": "Multibyte String Functions",
-            "friendsofphp/php-cs-fixer": "Fix PSR2 and other coding style issues",
-            "symfony/validator": "Use Symfony validator through Respect\\Validation",
-            "zendframework/zend-validator": "Use Zend Framework validator through Respect\\Validation"
+        "notification-url": "https://packagist.org/downloads/",
+        "license": [
+            "BSD-3-Clause"
+        ],
+        "authors": [
+            {
+                "name": "Arne Blankerts",
+                "email": "arne@blankerts.de",
+                "role": "Developer"
+            },
+            {
+                "name": "Sebastian Heuer",
+                "email": "sebastian@phpeople.de",
+                "role": "Developer"
+            },
+            {
+                "name": "Sebastian Bergmann",
+                "email": "sebastian@phpunit.de",
+                "role": "Developer"
+            }
+        ],
+        "description": "Library for handling version information and constraints"
+    },
+    {
+        "name": "phpdocumentor/reflection-common",
+        "version": "2.2.0",
+        "version_normalized": "2.2.0.0",
+        "source": {
+            "type": "git",
+            "url": "https://github.com/phpDocumentor/ReflectionCommon.git",
+            "reference": "1d01c49d4ed62f25aa84a747ad35d5a16924662b"
+        },
+        "dist": {
+            "type": "zip",
+            "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/1d01c49d4ed62f25aa84a747ad35d5a16924662b",
+            "reference": "1d01c49d4ed62f25aa84a747ad35d5a16924662b",
+            "shasum": ""
+        },
+        "require": {
+            "php": "^7.2 || ^8.0"
         },
-        "time": "2018-11-04T21:58:45+00:00",
+        "time": "2020-06-27T09:03:43+00:00",
         "type": "library",
         "extra": {
             "branch-alias": {
-                "dev-master": "1.1-dev"
+                "dev-2.x": "2.x-dev"
             }
         },
         "installation-source": "dist",
         "autoload": {
             "psr-4": {
-                "Respect\\Validation\\": "library/"
+                "phpDocumentor\\Reflection\\": "src/"
             }
         },
         "notification-url": "https://packagist.org/downloads/",
         "license": [
-            "BSD-3-Clause"
+            "MIT"
+        ],
+        "authors": [
+            {
+                "name": "Jaap van Otterdijk",
+                "email": "opensource@ijaap.nl"
+            }
+        ],
+        "description": "Common reflection classes used by phpdocumentor to reflect the code structure",
+        "homepage": "http://www.phpdoc.org",
+        "keywords": [
+            "FQSEN",
+            "phpDocumentor",
+            "phpdoc",
+            "reflection",
+            "static analysis"
+        ]
+    },
+    {
+        "name": "phpdocumentor/reflection-docblock",
+        "version": "5.2.2",
+        "version_normalized": "5.2.2.0",
+        "source": {
+            "type": "git",
+            "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git",
+            "reference": "069a785b2141f5bcf49f3e353548dc1cce6df556"
+        },
+        "dist": {
+            "type": "zip",
+            "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/069a785b2141f5bcf49f3e353548dc1cce6df556",
+            "reference": "069a785b2141f5bcf49f3e353548dc1cce6df556",
+            "shasum": ""
+        },
+        "require": {
+            "ext-filter": "*",
+            "php": "^7.2 || ^8.0",
+            "phpdocumentor/reflection-common": "^2.2",
+            "phpdocumentor/type-resolver": "^1.3",
+            "webmozart/assert": "^1.9.1"
+        },
+        "require-dev": {
+            "mockery/mockery": "~1.3.2"
+        },
+        "time": "2020-09-03T19:13:55+00:00",
+        "type": "library",
+        "extra": {
+            "branch-alias": {
+                "dev-master": "5.x-dev"
+            }
+        },
+        "installation-source": "dist",
+        "autoload": {
+            "psr-4": {
+                "phpDocumentor\\Reflection\\": "src"
+            }
+        },
+        "notification-url": "https://packagist.org/downloads/",
+        "license": [
+            "MIT"
+        ],
+        "authors": [
+            {
+                "name": "Mike van Riel",
+                "email": "me@mikevanriel.com"
+            },
+            {
+                "name": "Jaap van Otterdijk",
+                "email": "account@ijaap.nl"
+            }
+        ],
+        "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock."
+    },
+    {
+        "name": "phpdocumentor/type-resolver",
+        "version": "1.4.0",
+        "version_normalized": "1.4.0.0",
+        "source": {
+            "type": "git",
+            "url": "https://github.com/phpDocumentor/TypeResolver.git",
+            "reference": "6a467b8989322d92aa1c8bf2bebcc6e5c2ba55c0"
+        },
+        "dist": {
+            "type": "zip",
+            "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/6a467b8989322d92aa1c8bf2bebcc6e5c2ba55c0",
+            "reference": "6a467b8989322d92aa1c8bf2bebcc6e5c2ba55c0",
+            "shasum": ""
+        },
+        "require": {
+            "php": "^7.2 || ^8.0",
+            "phpdocumentor/reflection-common": "^2.0"
+        },
+        "require-dev": {
+            "ext-tokenizer": "*"
+        },
+        "time": "2020-09-17T18:55:26+00:00",
+        "type": "library",
+        "extra": {
+            "branch-alias": {
+                "dev-1.x": "1.x-dev"
+            }
+        },
+        "installation-source": "dist",
+        "autoload": {
+            "psr-4": {
+                "phpDocumentor\\Reflection\\": "src"
+            }
+        },
+        "notification-url": "https://packagist.org/downloads/",
+        "license": [
+            "MIT"
+        ],
+        "authors": [
+            {
+                "name": "Mike van Riel",
+                "email": "me@mikevanriel.com"
+            }
+        ],
+        "description": "A PSR-5 based resolver of Class names, Types and Structural Element Names"
+    },
+    {
+        "name": "phpmailer/phpmailer",
+        "version": "v6.1.7",
+        "version_normalized": "6.1.7.0",
+        "source": {
+            "type": "git",
+            "url": "https://github.com/PHPMailer/PHPMailer.git",
+            "reference": "2c2370ba3df7034f9eb7b8f387c97b52b2ba5ad0"
+        },
+        "dist": {
+            "type": "zip",
+            "url": "https://api.github.com/repos/PHPMailer/PHPMailer/zipball/2c2370ba3df7034f9eb7b8f387c97b52b2ba5ad0",
+            "reference": "2c2370ba3df7034f9eb7b8f387c97b52b2ba5ad0",
+            "shasum": ""
+        },
+        "require": {
+            "ext-ctype": "*",
+            "ext-filter": "*",
+            "php": ">=5.5.0"
+        },
+        "require-dev": {
+            "doctrine/annotations": "^1.2",
+            "friendsofphp/php-cs-fixer": "^2.2",
+            "phpunit/phpunit": "^4.8 || ^5.7"
+        },
+        "suggest": {
+            "ext-mbstring": "Needed to send email in multibyte encoding charset",
+            "hayageek/oauth2-yahoo": "Needed for Yahoo XOAUTH2 authentication",
+            "league/oauth2-google": "Needed for Google XOAUTH2 authentication",
+            "psr/log": "For optional PSR-3 debug logging",
+            "stevenmaguire/oauth2-microsoft": "Needed for Microsoft XOAUTH2 authentication",
+            "symfony/polyfill-mbstring": "To support UTF-8 if the Mbstring PHP extension is not enabled (^1.2)"
+        },
+        "time": "2020-07-14T18:50:27+00:00",
+        "type": "library",
+        "installation-source": "dist",
+        "autoload": {
+            "psr-4": {
+                "PHPMailer\\PHPMailer\\": "src/"
+            }
+        },
+        "notification-url": "https://packagist.org/downloads/",
+        "license": [
+            "LGPL-2.1-only"
+        ],
+        "authors": [
+            {
+                "name": "Marcus Bointon",
+                "email": "phpmailer@synchromedia.co.uk"
+            },
+            {
+                "name": "Jim Jagielski",
+                "email": "jimjag@gmail.com"
+            },
+            {
+                "name": "Andy Prevost",
+                "email": "codeworxtech@users.sourceforge.net"
+            },
+            {
+                "name": "Brent R. Matzelle"
+            }
+        ],
+        "description": "PHPMailer is a full-featured email creation and transfer class for PHP",
+        "funding": [
+            {
+                "url": "https://github.com/synchro",
+                "type": "github"
+            }
+        ]
+    },
+    {
+        "name": "phpspec/prophecy",
+        "version": "1.13.0",
+        "version_normalized": "1.13.0.0",
+        "source": {
+            "type": "git",
+            "url": "https://github.com/phpspec/prophecy.git",
+            "reference": "be1996ed8adc35c3fd795488a653f4b518be70ea"
+        },
+        "dist": {
+            "type": "zip",
+            "url": "https://api.github.com/repos/phpspec/prophecy/zipball/be1996ed8adc35c3fd795488a653f4b518be70ea",
+            "reference": "be1996ed8adc35c3fd795488a653f4b518be70ea",
+            "shasum": ""
+        },
+        "require": {
+            "doctrine/instantiator": "^1.2",
+            "php": "^7.2 || ~8.0, <8.1",
+            "phpdocumentor/reflection-docblock": "^5.2",
+            "sebastian/comparator": "^3.0 || ^4.0",
+            "sebastian/recursion-context": "^3.0 || ^4.0"
+        },
+        "require-dev": {
+            "phpspec/phpspec": "^6.0",
+            "phpunit/phpunit": "^8.0 || ^9.0"
+        },
+        "time": "2021-03-17T13:42:18+00:00",
+        "type": "library",
+        "extra": {
+            "branch-alias": {
+                "dev-master": "1.11.x-dev"
+            }
+        },
+        "installation-source": "dist",
+        "autoload": {
+            "psr-4": {
+                "Prophecy\\": "src/Prophecy"
+            }
+        },
+        "notification-url": "https://packagist.org/downloads/",
+        "license": [
+            "MIT"
+        ],
+        "authors": [
+            {
+                "name": "Konstantin Kudryashov",
+                "email": "ever.zet@gmail.com",
+                "homepage": "http://everzet.com"
+            },
+            {
+                "name": "Marcello Duarte",
+                "email": "marcello.duarte@gmail.com"
+            }
+        ],
+        "description": "Highly opinionated mocking framework for PHP 5.3+",
+        "homepage": "https://github.com/phpspec/prophecy",
+        "keywords": [
+            "Double",
+            "Dummy",
+            "fake",
+            "mock",
+            "spy",
+            "stub"
+        ]
+    },
+    {
+        "name": "phpunit/php-code-coverage",
+        "version": "9.2.5",
+        "version_normalized": "9.2.5.0",
+        "source": {
+            "type": "git",
+            "url": "https://github.com/sebastianbergmann/php-code-coverage.git",
+            "reference": "f3e026641cc91909d421802dd3ac7827ebfd97e1"
+        },
+        "dist": {
+            "type": "zip",
+            "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/f3e026641cc91909d421802dd3ac7827ebfd97e1",
+            "reference": "f3e026641cc91909d421802dd3ac7827ebfd97e1",
+            "shasum": ""
+        },
+        "require": {
+            "ext-dom": "*",
+            "ext-libxml": "*",
+            "ext-xmlwriter": "*",
+            "nikic/php-parser": "^4.10.2",
+            "php": ">=7.3",
+            "phpunit/php-file-iterator": "^3.0.3",
+            "phpunit/php-text-template": "^2.0.2",
+            "sebastian/code-unit-reverse-lookup": "^2.0.2",
+            "sebastian/complexity": "^2.0",
+            "sebastian/environment": "^5.1.2",
+            "sebastian/lines-of-code": "^1.0.3",
+            "sebastian/version": "^3.0.1",
+            "theseer/tokenizer": "^1.2.0"
+        },
+        "require-dev": {
+            "phpunit/phpunit": "^9.3"
+        },
+        "suggest": {
+            "ext-pcov": "*",
+            "ext-xdebug": "*"
+        },
+        "time": "2020-11-28T06:44:49+00:00",
+        "type": "library",
+        "extra": {
+            "branch-alias": {
+                "dev-master": "9.2-dev"
+            }
+        },
+        "installation-source": "dist",
+        "autoload": {
+            "classmap": [
+                "src/"
+            ]
+        },
+        "notification-url": "https://packagist.org/downloads/",
+        "license": [
+            "BSD-3-Clause"
+        ],
+        "authors": [
+            {
+                "name": "Sebastian Bergmann",
+                "email": "sebastian@phpunit.de",
+                "role": "lead"
+            }
+        ],
+        "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.",
+        "homepage": "https://github.com/sebastianbergmann/php-code-coverage",
+        "keywords": [
+            "coverage",
+            "testing",
+            "xunit"
+        ],
+        "funding": [
+            {
+                "url": "https://github.com/sebastianbergmann",
+                "type": "github"
+            }
+        ]
+    },
+    {
+        "name": "phpunit/php-file-iterator",
+        "version": "3.0.5",
+        "version_normalized": "3.0.5.0",
+        "source": {
+            "type": "git",
+            "url": "https://github.com/sebastianbergmann/php-file-iterator.git",
+            "reference": "aa4be8575f26070b100fccb67faabb28f21f66f8"
+        },
+        "dist": {
+            "type": "zip",
+            "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/aa4be8575f26070b100fccb67faabb28f21f66f8",
+            "reference": "aa4be8575f26070b100fccb67faabb28f21f66f8",
+            "shasum": ""
+        },
+        "require": {
+            "php": ">=7.3"
+        },
+        "require-dev": {
+            "phpunit/phpunit": "^9.3"
+        },
+        "time": "2020-09-28T05:57:25+00:00",
+        "type": "library",
+        "extra": {
+            "branch-alias": {
+                "dev-master": "3.0-dev"
+            }
+        },
+        "installation-source": "dist",
+        "autoload": {
+            "classmap": [
+                "src/"
+            ]
+        },
+        "notification-url": "https://packagist.org/downloads/",
+        "license": [
+            "BSD-3-Clause"
+        ],
+        "authors": [
+            {
+                "name": "Sebastian Bergmann",
+                "email": "sebastian@phpunit.de",
+                "role": "lead"
+            }
+        ],
+        "description": "FilterIterator implementation that filters files based on a list of suffixes.",
+        "homepage": "https://github.com/sebastianbergmann/php-file-iterator/",
+        "keywords": [
+            "filesystem",
+            "iterator"
+        ],
+        "funding": [
+            {
+                "url": "https://github.com/sebastianbergmann",
+                "type": "github"
+            }
+        ]
+    },
+    {
+        "name": "phpunit/php-invoker",
+        "version": "3.1.1",
+        "version_normalized": "3.1.1.0",
+        "source": {
+            "type": "git",
+            "url": "https://github.com/sebastianbergmann/php-invoker.git",
+            "reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67"
+        },
+        "dist": {
+            "type": "zip",
+            "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/5a10147d0aaf65b58940a0b72f71c9ac0423cc67",
+            "reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67",
+            "shasum": ""
+        },
+        "require": {
+            "php": ">=7.3"
+        },
+        "require-dev": {
+            "ext-pcntl": "*",
+            "phpunit/phpunit": "^9.3"
+        },
+        "suggest": {
+            "ext-pcntl": "*"
+        },
+        "time": "2020-09-28T05:58:55+00:00",
+        "type": "library",
+        "extra": {
+            "branch-alias": {
+                "dev-master": "3.1-dev"
+            }
+        },
+        "installation-source": "dist",
+        "autoload": {
+            "classmap": [
+                "src/"
+            ]
+        },
+        "notification-url": "https://packagist.org/downloads/",
+        "license": [
+            "BSD-3-Clause"
+        ],
+        "authors": [
+            {
+                "name": "Sebastian Bergmann",
+                "email": "sebastian@phpunit.de",
+                "role": "lead"
+            }
+        ],
+        "description": "Invoke callables with a timeout",
+        "homepage": "https://github.com/sebastianbergmann/php-invoker/",
+        "keywords": [
+            "process"
+        ],
+        "funding": [
+            {
+                "url": "https://github.com/sebastianbergmann",
+                "type": "github"
+            }
+        ]
+    },
+    {
+        "name": "phpunit/php-text-template",
+        "version": "2.0.4",
+        "version_normalized": "2.0.4.0",
+        "source": {
+            "type": "git",
+            "url": "https://github.com/sebastianbergmann/php-text-template.git",
+            "reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28"
+        },
+        "dist": {
+            "type": "zip",
+            "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28",
+            "reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28",
+            "shasum": ""
+        },
+        "require": {
+            "php": ">=7.3"
+        },
+        "require-dev": {
+            "phpunit/phpunit": "^9.3"
+        },
+        "time": "2020-10-26T05:33:50+00:00",
+        "type": "library",
+        "extra": {
+            "branch-alias": {
+                "dev-master": "2.0-dev"
+            }
+        },
+        "installation-source": "dist",
+        "autoload": {
+            "classmap": [
+                "src/"
+            ]
+        },
+        "notification-url": "https://packagist.org/downloads/",
+        "license": [
+            "BSD-3-Clause"
+        ],
+        "authors": [
+            {
+                "name": "Sebastian Bergmann",
+                "email": "sebastian@phpunit.de",
+                "role": "lead"
+            }
+        ],
+        "description": "Simple template engine.",
+        "homepage": "https://github.com/sebastianbergmann/php-text-template/",
+        "keywords": [
+            "template"
+        ],
+        "funding": [
+            {
+                "url": "https://github.com/sebastianbergmann",
+                "type": "github"
+            }
+        ]
+    },
+    {
+        "name": "phpunit/php-timer",
+        "version": "5.0.3",
+        "version_normalized": "5.0.3.0",
+        "source": {
+            "type": "git",
+            "url": "https://github.com/sebastianbergmann/php-timer.git",
+            "reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2"
+        },
+        "dist": {
+            "type": "zip",
+            "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2",
+            "reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2",
+            "shasum": ""
+        },
+        "require": {
+            "php": ">=7.3"
+        },
+        "require-dev": {
+            "phpunit/phpunit": "^9.3"
+        },
+        "time": "2020-10-26T13:16:10+00:00",
+        "type": "library",
+        "extra": {
+            "branch-alias": {
+                "dev-master": "5.0-dev"
+            }
+        },
+        "installation-source": "dist",
+        "autoload": {
+            "classmap": [
+                "src/"
+            ]
+        },
+        "notification-url": "https://packagist.org/downloads/",
+        "license": [
+            "BSD-3-Clause"
+        ],
+        "authors": [
+            {
+                "name": "Sebastian Bergmann",
+                "email": "sebastian@phpunit.de",
+                "role": "lead"
+            }
+        ],
+        "description": "Utility class for timing",
+        "homepage": "https://github.com/sebastianbergmann/php-timer/",
+        "keywords": [
+            "timer"
+        ],
+        "funding": [
+            {
+                "url": "https://github.com/sebastianbergmann",
+                "type": "github"
+            }
+        ]
+    },
+    {
+        "name": "phpunit/phpunit",
+        "version": "9.5.3",
+        "version_normalized": "9.5.3.0",
+        "source": {
+            "type": "git",
+            "url": "https://github.com/sebastianbergmann/phpunit.git",
+            "reference": "27241ac75fc37ecf862b6e002bf713b6566cbe41"
+        },
+        "dist": {
+            "type": "zip",
+            "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/27241ac75fc37ecf862b6e002bf713b6566cbe41",
+            "reference": "27241ac75fc37ecf862b6e002bf713b6566cbe41",
+            "shasum": ""
+        },
+        "require": {
+            "doctrine/instantiator": "^1.3.1",
+            "ext-dom": "*",
+            "ext-json": "*",
+            "ext-libxml": "*",
+            "ext-mbstring": "*",
+            "ext-xml": "*",
+            "ext-xmlwriter": "*",
+            "myclabs/deep-copy": "^1.10.1",
+            "phar-io/manifest": "^2.0.1",
+            "phar-io/version": "^3.0.2",
+            "php": ">=7.3",
+            "phpspec/prophecy": "^1.12.1",
+            "phpunit/php-code-coverage": "^9.2.3",
+            "phpunit/php-file-iterator": "^3.0.5",
+            "phpunit/php-invoker": "^3.1.1",
+            "phpunit/php-text-template": "^2.0.3",
+            "phpunit/php-timer": "^5.0.2",
+            "sebastian/cli-parser": "^1.0.1",
+            "sebastian/code-unit": "^1.0.6",
+            "sebastian/comparator": "^4.0.5",
+            "sebastian/diff": "^4.0.3",
+            "sebastian/environment": "^5.1.3",
+            "sebastian/exporter": "^4.0.3",
+            "sebastian/global-state": "^5.0.1",
+            "sebastian/object-enumerator": "^4.0.3",
+            "sebastian/resource-operations": "^3.0.3",
+            "sebastian/type": "^2.3",
+            "sebastian/version": "^3.0.2"
+        },
+        "require-dev": {
+            "ext-pdo": "*",
+            "phpspec/prophecy-phpunit": "^2.0.1"
+        },
+        "suggest": {
+            "ext-soap": "*",
+            "ext-xdebug": "*"
+        },
+        "time": "2021-03-17T07:30:34+00:00",
+        "bin": [
+            "phpunit"
+        ],
+        "type": "library",
+        "extra": {
+            "branch-alias": {
+                "dev-master": "9.5-dev"
+            }
+        },
+        "installation-source": "dist",
+        "autoload": {
+            "classmap": [
+                "src/"
+            ],
+            "files": [
+                "src/Framework/Assert/Functions.php"
+            ]
+        },
+        "notification-url": "https://packagist.org/downloads/",
+        "license": [
+            "BSD-3-Clause"
+        ],
+        "authors": [
+            {
+                "name": "Sebastian Bergmann",
+                "email": "sebastian@phpunit.de",
+                "role": "lead"
+            }
+        ],
+        "description": "The PHP Unit Testing framework.",
+        "homepage": "https://phpunit.de/",
+        "keywords": [
+            "phpunit",
+            "testing",
+            "xunit"
+        ],
+        "funding": [
+            {
+                "url": "https://phpunit.de/donate.html",
+                "type": "custom"
+            },
+            {
+                "url": "https://github.com/sebastianbergmann",
+                "type": "github"
+            }
+        ]
+    },
+    {
+        "name": "pimple/pimple",
+        "version": "v3.3.0",
+        "version_normalized": "3.3.0.0",
+        "source": {
+            "type": "git",
+            "url": "https://github.com/silexphp/Pimple.git",
+            "reference": "e55d12f9d6a0e7f9c85992b73df1267f46279930"
+        },
+        "dist": {
+            "type": "zip",
+            "url": "https://api.github.com/repos/silexphp/Pimple/zipball/e55d12f9d6a0e7f9c85992b73df1267f46279930",
+            "reference": "e55d12f9d6a0e7f9c85992b73df1267f46279930",
+            "shasum": ""
+        },
+        "require": {
+            "php": "^7.2.5",
+            "psr/container": "^1.0"
+        },
+        "require-dev": {
+            "symfony/phpunit-bridge": "^3.4|^4.4|^5.0"
+        },
+        "time": "2020-03-03T09:12:48+00:00",
+        "type": "library",
+        "extra": {
+            "branch-alias": {
+                "dev-master": "3.3.x-dev"
+            }
+        },
+        "installation-source": "dist",
+        "autoload": {
+            "psr-0": {
+                "Pimple": "src/"
+            }
+        },
+        "notification-url": "https://packagist.org/downloads/",
+        "license": [
+            "MIT"
+        ],
+        "authors": [
+            {
+                "name": "Fabien Potencier",
+                "email": "fabien@symfony.com"
+            }
+        ],
+        "description": "Pimple, a simple Dependency Injection Container",
+        "homepage": "https://pimple.symfony.com",
+        "keywords": [
+            "container",
+            "dependency injection"
+        ]
+    },
+    {
+        "name": "psr/container",
+        "version": "1.0.0",
+        "version_normalized": "1.0.0.0",
+        "source": {
+            "type": "git",
+            "url": "https://github.com/php-fig/container.git",
+            "reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f"
+        },
+        "dist": {
+            "type": "zip",
+            "url": "https://api.github.com/repos/php-fig/container/zipball/b7ce3b176482dbbc1245ebf52b181af44c2cf55f",
+            "reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f",
+            "shasum": ""
+        },
+        "require": {
+            "php": ">=5.3.0"
+        },
+        "time": "2017-02-14T16:28:37+00:00",
+        "type": "library",
+        "extra": {
+            "branch-alias": {
+                "dev-master": "1.0.x-dev"
+            }
+        },
+        "installation-source": "dist",
+        "autoload": {
+            "psr-4": {
+                "Psr\\Container\\": "src/"
+            }
+        },
+        "notification-url": "https://packagist.org/downloads/",
+        "license": [
+            "MIT"
+        ],
+        "authors": [
+            {
+                "name": "PHP-FIG",
+                "homepage": "http://www.php-fig.org/"
+            }
+        ],
+        "description": "Common Container Interface (PHP FIG PSR-11)",
+        "homepage": "https://github.com/php-fig/container",
+        "keywords": [
+            "PSR-11",
+            "container",
+            "container-interface",
+            "container-interop",
+            "psr"
+        ]
+    },
+    {
+        "name": "psr/http-message",
+        "version": "1.0.1",
+        "version_normalized": "1.0.1.0",
+        "source": {
+            "type": "git",
+            "url": "https://github.com/php-fig/http-message.git",
+            "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363"
+        },
+        "dist": {
+            "type": "zip",
+            "url": "https://api.github.com/repos/php-fig/http-message/zipball/f6561bf28d520154e4b0ec72be95418abe6d9363",
+            "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363",
+            "shasum": ""
+        },
+        "require": {
+            "php": ">=5.3.0"
+        },
+        "time": "2016-08-06T14:39:51+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": "http://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"
+        ]
+    },
+    {
+        "name": "respect/validation",
+        "version": "1.1.31",
+        "version_normalized": "1.1.31.0",
+        "source": {
+            "type": "git",
+            "url": "https://github.com/Respect/Validation.git",
+            "reference": "45d109fc830644fecc1145200d6351ce4f2769d0"
+        },
+        "dist": {
+            "type": "zip",
+            "url": "https://api.github.com/repos/Respect/Validation/zipball/45d109fc830644fecc1145200d6351ce4f2769d0",
+            "reference": "45d109fc830644fecc1145200d6351ce4f2769d0",
+            "shasum": ""
+        },
+        "require": {
+            "php": ">=5.4",
+            "symfony/polyfill-mbstring": "^1.2"
+        },
+        "require-dev": {
+            "egulias/email-validator": "~1.2 || ~2.1",
+            "mikey179/vfsstream": "^1.5",
+            "phpunit/phpunit": "~4.0 || ~5.0",
+            "symfony/validator": "~2.6.9",
+            "zendframework/zend-validator": "~2.3"
+        },
+        "suggest": {
+            "egulias/email-validator": "Strict (RFC compliant) email validation",
+            "ext-bcmath": "Arbitrary Precision Mathematics",
+            "ext-mbstring": "Multibyte String Functions",
+            "friendsofphp/php-cs-fixer": "Fix PSR2 and other coding style issues",
+            "symfony/validator": "Use Symfony validator through Respect\\Validation",
+            "zendframework/zend-validator": "Use Zend Framework validator through Respect\\Validation"
+        },
+        "time": "2019-05-28T06:10:06+00:00",
+        "type": "library",
+        "extra": {
+            "branch-alias": {
+                "dev-master": "1.1-dev"
+            }
+        },
+        "installation-source": "dist",
+        "autoload": {
+            "psr-4": {
+                "Respect\\Validation\\": "library/"
+            }
+        },
+        "notification-url": "https://packagist.org/downloads/",
+        "license": [
+            "BSD-3-Clause"
         ],
         "authors": [
             {
@@ -409,46 +1462,978 @@
                 "homepage": "https://github.com/Respect/Validation/graphs/contributors"
             }
         ],
-        "description": "The most awesome validation engine ever created for PHP",
-        "homepage": "http://respect.github.io/Validation/",
+        "description": "The most awesome validation engine ever created for PHP",
+        "homepage": "http://respect.github.io/Validation/",
+        "keywords": [
+            "respect",
+            "validation",
+            "validator"
+        ]
+    },
+    {
+        "name": "sebastian/cli-parser",
+        "version": "1.0.1",
+        "version_normalized": "1.0.1.0",
+        "source": {
+            "type": "git",
+            "url": "https://github.com/sebastianbergmann/cli-parser.git",
+            "reference": "442e7c7e687e42adc03470c7b668bc4b2402c0b2"
+        },
+        "dist": {
+            "type": "zip",
+            "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/442e7c7e687e42adc03470c7b668bc4b2402c0b2",
+            "reference": "442e7c7e687e42adc03470c7b668bc4b2402c0b2",
+            "shasum": ""
+        },
+        "require": {
+            "php": ">=7.3"
+        },
+        "require-dev": {
+            "phpunit/phpunit": "^9.3"
+        },
+        "time": "2020-09-28T06:08:49+00:00",
+        "type": "library",
+        "extra": {
+            "branch-alias": {
+                "dev-master": "1.0-dev"
+            }
+        },
+        "installation-source": "dist",
+        "autoload": {
+            "classmap": [
+                "src/"
+            ]
+        },
+        "notification-url": "https://packagist.org/downloads/",
+        "license": [
+            "BSD-3-Clause"
+        ],
+        "authors": [
+            {
+                "name": "Sebastian Bergmann",
+                "email": "sebastian@phpunit.de",
+                "role": "lead"
+            }
+        ],
+        "description": "Library for parsing CLI options",
+        "homepage": "https://github.com/sebastianbergmann/cli-parser",
+        "funding": [
+            {
+                "url": "https://github.com/sebastianbergmann",
+                "type": "github"
+            }
+        ]
+    },
+    {
+        "name": "sebastian/code-unit",
+        "version": "1.0.8",
+        "version_normalized": "1.0.8.0",
+        "source": {
+            "type": "git",
+            "url": "https://github.com/sebastianbergmann/code-unit.git",
+            "reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120"
+        },
+        "dist": {
+            "type": "zip",
+            "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/1fc9f64c0927627ef78ba436c9b17d967e68e120",
+            "reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120",
+            "shasum": ""
+        },
+        "require": {
+            "php": ">=7.3"
+        },
+        "require-dev": {
+            "phpunit/phpunit": "^9.3"
+        },
+        "time": "2020-10-26T13:08:54+00:00",
+        "type": "library",
+        "extra": {
+            "branch-alias": {
+                "dev-master": "1.0-dev"
+            }
+        },
+        "installation-source": "dist",
+        "autoload": {
+            "classmap": [
+                "src/"
+            ]
+        },
+        "notification-url": "https://packagist.org/downloads/",
+        "license": [
+            "BSD-3-Clause"
+        ],
+        "authors": [
+            {
+                "name": "Sebastian Bergmann",
+                "email": "sebastian@phpunit.de",
+                "role": "lead"
+            }
+        ],
+        "description": "Collection of value objects that represent the PHP code units",
+        "homepage": "https://github.com/sebastianbergmann/code-unit",
+        "funding": [
+            {
+                "url": "https://github.com/sebastianbergmann",
+                "type": "github"
+            }
+        ]
+    },
+    {
+        "name": "sebastian/code-unit-reverse-lookup",
+        "version": "2.0.3",
+        "version_normalized": "2.0.3.0",
+        "source": {
+            "type": "git",
+            "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git",
+            "reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5"
+        },
+        "dist": {
+            "type": "zip",
+            "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5",
+            "reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5",
+            "shasum": ""
+        },
+        "require": {
+            "php": ">=7.3"
+        },
+        "require-dev": {
+            "phpunit/phpunit": "^9.3"
+        },
+        "time": "2020-09-28T05:30:19+00:00",
+        "type": "library",
+        "extra": {
+            "branch-alias": {
+                "dev-master": "2.0-dev"
+            }
+        },
+        "installation-source": "dist",
+        "autoload": {
+            "classmap": [
+                "src/"
+            ]
+        },
+        "notification-url": "https://packagist.org/downloads/",
+        "license": [
+            "BSD-3-Clause"
+        ],
+        "authors": [
+            {
+                "name": "Sebastian Bergmann",
+                "email": "sebastian@phpunit.de"
+            }
+        ],
+        "description": "Looks up which function or method a line of code belongs to",
+        "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/",
+        "funding": [
+            {
+                "url": "https://github.com/sebastianbergmann",
+                "type": "github"
+            }
+        ]
+    },
+    {
+        "name": "sebastian/comparator",
+        "version": "4.0.6",
+        "version_normalized": "4.0.6.0",
+        "source": {
+            "type": "git",
+            "url": "https://github.com/sebastianbergmann/comparator.git",
+            "reference": "55f4261989e546dc112258c7a75935a81a7ce382"
+        },
+        "dist": {
+            "type": "zip",
+            "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/55f4261989e546dc112258c7a75935a81a7ce382",
+            "reference": "55f4261989e546dc112258c7a75935a81a7ce382",
+            "shasum": ""
+        },
+        "require": {
+            "php": ">=7.3",
+            "sebastian/diff": "^4.0",
+            "sebastian/exporter": "^4.0"
+        },
+        "require-dev": {
+            "phpunit/phpunit": "^9.3"
+        },
+        "time": "2020-10-26T15:49:45+00:00",
+        "type": "library",
+        "extra": {
+            "branch-alias": {
+                "dev-master": "4.0-dev"
+            }
+        },
+        "installation-source": "dist",
+        "autoload": {
+            "classmap": [
+                "src/"
+            ]
+        },
+        "notification-url": "https://packagist.org/downloads/",
+        "license": [
+            "BSD-3-Clause"
+        ],
+        "authors": [
+            {
+                "name": "Sebastian Bergmann",
+                "email": "sebastian@phpunit.de"
+            },
+            {
+                "name": "Jeff Welch",
+                "email": "whatthejeff@gmail.com"
+            },
+            {
+                "name": "Volker Dusch",
+                "email": "github@wallbash.com"
+            },
+            {
+                "name": "Bernhard Schussek",
+                "email": "bschussek@2bepublished.at"
+            }
+        ],
+        "description": "Provides the functionality to compare PHP values for equality",
+        "homepage": "https://github.com/sebastianbergmann/comparator",
+        "keywords": [
+            "comparator",
+            "compare",
+            "equality"
+        ],
+        "funding": [
+            {
+                "url": "https://github.com/sebastianbergmann",
+                "type": "github"
+            }
+        ]
+    },
+    {
+        "name": "sebastian/complexity",
+        "version": "2.0.2",
+        "version_normalized": "2.0.2.0",
+        "source": {
+            "type": "git",
+            "url": "https://github.com/sebastianbergmann/complexity.git",
+            "reference": "739b35e53379900cc9ac327b2147867b8b6efd88"
+        },
+        "dist": {
+            "type": "zip",
+            "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/739b35e53379900cc9ac327b2147867b8b6efd88",
+            "reference": "739b35e53379900cc9ac327b2147867b8b6efd88",
+            "shasum": ""
+        },
+        "require": {
+            "nikic/php-parser": "^4.7",
+            "php": ">=7.3"
+        },
+        "require-dev": {
+            "phpunit/phpunit": "^9.3"
+        },
+        "time": "2020-10-26T15:52:27+00:00",
+        "type": "library",
+        "extra": {
+            "branch-alias": {
+                "dev-master": "2.0-dev"
+            }
+        },
+        "installation-source": "dist",
+        "autoload": {
+            "classmap": [
+                "src/"
+            ]
+        },
+        "notification-url": "https://packagist.org/downloads/",
+        "license": [
+            "BSD-3-Clause"
+        ],
+        "authors": [
+            {
+                "name": "Sebastian Bergmann",
+                "email": "sebastian@phpunit.de",
+                "role": "lead"
+            }
+        ],
+        "description": "Library for calculating the complexity of PHP code units",
+        "homepage": "https://github.com/sebastianbergmann/complexity",
+        "funding": [
+            {
+                "url": "https://github.com/sebastianbergmann",
+                "type": "github"
+            }
+        ]
+    },
+    {
+        "name": "sebastian/diff",
+        "version": "4.0.4",
+        "version_normalized": "4.0.4.0",
+        "source": {
+            "type": "git",
+            "url": "https://github.com/sebastianbergmann/diff.git",
+            "reference": "3461e3fccc7cfdfc2720be910d3bd73c69be590d"
+        },
+        "dist": {
+            "type": "zip",
+            "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/3461e3fccc7cfdfc2720be910d3bd73c69be590d",
+            "reference": "3461e3fccc7cfdfc2720be910d3bd73c69be590d",
+            "shasum": ""
+        },
+        "require": {
+            "php": ">=7.3"
+        },
+        "require-dev": {
+            "phpunit/phpunit": "^9.3",
+            "symfony/process": "^4.2 || ^5"
+        },
+        "time": "2020-10-26T13:10:38+00:00",
+        "type": "library",
+        "extra": {
+            "branch-alias": {
+                "dev-master": "4.0-dev"
+            }
+        },
+        "installation-source": "dist",
+        "autoload": {
+            "classmap": [
+                "src/"
+            ]
+        },
+        "notification-url": "https://packagist.org/downloads/",
+        "license": [
+            "BSD-3-Clause"
+        ],
+        "authors": [
+            {
+                "name": "Sebastian Bergmann",
+                "email": "sebastian@phpunit.de"
+            },
+            {
+                "name": "Kore Nordmann",
+                "email": "mail@kore-nordmann.de"
+            }
+        ],
+        "description": "Diff implementation",
+        "homepage": "https://github.com/sebastianbergmann/diff",
+        "keywords": [
+            "diff",
+            "udiff",
+            "unidiff",
+            "unified diff"
+        ],
+        "funding": [
+            {
+                "url": "https://github.com/sebastianbergmann",
+                "type": "github"
+            }
+        ]
+    },
+    {
+        "name": "sebastian/environment",
+        "version": "5.1.3",
+        "version_normalized": "5.1.3.0",
+        "source": {
+            "type": "git",
+            "url": "https://github.com/sebastianbergmann/environment.git",
+            "reference": "388b6ced16caa751030f6a69e588299fa09200ac"
+        },
+        "dist": {
+            "type": "zip",
+            "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/388b6ced16caa751030f6a69e588299fa09200ac",
+            "reference": "388b6ced16caa751030f6a69e588299fa09200ac",
+            "shasum": ""
+        },
+        "require": {
+            "php": ">=7.3"
+        },
+        "require-dev": {
+            "phpunit/phpunit": "^9.3"
+        },
+        "suggest": {
+            "ext-posix": "*"
+        },
+        "time": "2020-09-28T05:52:38+00:00",
+        "type": "library",
+        "extra": {
+            "branch-alias": {
+                "dev-master": "5.1-dev"
+            }
+        },
+        "installation-source": "dist",
+        "autoload": {
+            "classmap": [
+                "src/"
+            ]
+        },
+        "notification-url": "https://packagist.org/downloads/",
+        "license": [
+            "BSD-3-Clause"
+        ],
+        "authors": [
+            {
+                "name": "Sebastian Bergmann",
+                "email": "sebastian@phpunit.de"
+            }
+        ],
+        "description": "Provides functionality to handle HHVM/PHP environments",
+        "homepage": "http://www.github.com/sebastianbergmann/environment",
+        "keywords": [
+            "Xdebug",
+            "environment",
+            "hhvm"
+        ],
+        "funding": [
+            {
+                "url": "https://github.com/sebastianbergmann",
+                "type": "github"
+            }
+        ]
+    },
+    {
+        "name": "sebastian/exporter",
+        "version": "4.0.3",
+        "version_normalized": "4.0.3.0",
+        "source": {
+            "type": "git",
+            "url": "https://github.com/sebastianbergmann/exporter.git",
+            "reference": "d89cc98761b8cb5a1a235a6b703ae50d34080e65"
+        },
+        "dist": {
+            "type": "zip",
+            "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/d89cc98761b8cb5a1a235a6b703ae50d34080e65",
+            "reference": "d89cc98761b8cb5a1a235a6b703ae50d34080e65",
+            "shasum": ""
+        },
+        "require": {
+            "php": ">=7.3",
+            "sebastian/recursion-context": "^4.0"
+        },
+        "require-dev": {
+            "ext-mbstring": "*",
+            "phpunit/phpunit": "^9.3"
+        },
+        "time": "2020-09-28T05:24:23+00:00",
+        "type": "library",
+        "extra": {
+            "branch-alias": {
+                "dev-master": "4.0-dev"
+            }
+        },
+        "installation-source": "dist",
+        "autoload": {
+            "classmap": [
+                "src/"
+            ]
+        },
+        "notification-url": "https://packagist.org/downloads/",
+        "license": [
+            "BSD-3-Clause"
+        ],
+        "authors": [
+            {
+                "name": "Sebastian Bergmann",
+                "email": "sebastian@phpunit.de"
+            },
+            {
+                "name": "Jeff Welch",
+                "email": "whatthejeff@gmail.com"
+            },
+            {
+                "name": "Volker Dusch",
+                "email": "github@wallbash.com"
+            },
+            {
+                "name": "Adam Harvey",
+                "email": "aharvey@php.net"
+            },
+            {
+                "name": "Bernhard Schussek",
+                "email": "bschussek@gmail.com"
+            }
+        ],
+        "description": "Provides the functionality to export PHP variables for visualization",
+        "homepage": "http://www.github.com/sebastianbergmann/exporter",
+        "keywords": [
+            "export",
+            "exporter"
+        ],
+        "funding": [
+            {
+                "url": "https://github.com/sebastianbergmann",
+                "type": "github"
+            }
+        ]
+    },
+    {
+        "name": "sebastian/global-state",
+        "version": "5.0.2",
+        "version_normalized": "5.0.2.0",
+        "source": {
+            "type": "git",
+            "url": "https://github.com/sebastianbergmann/global-state.git",
+            "reference": "a90ccbddffa067b51f574dea6eb25d5680839455"
+        },
+        "dist": {
+            "type": "zip",
+            "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/a90ccbddffa067b51f574dea6eb25d5680839455",
+            "reference": "a90ccbddffa067b51f574dea6eb25d5680839455",
+            "shasum": ""
+        },
+        "require": {
+            "php": ">=7.3",
+            "sebastian/object-reflector": "^2.0",
+            "sebastian/recursion-context": "^4.0"
+        },
+        "require-dev": {
+            "ext-dom": "*",
+            "phpunit/phpunit": "^9.3"
+        },
+        "suggest": {
+            "ext-uopz": "*"
+        },
+        "time": "2020-10-26T15:55:19+00:00",
+        "type": "library",
+        "extra": {
+            "branch-alias": {
+                "dev-master": "5.0-dev"
+            }
+        },
+        "installation-source": "dist",
+        "autoload": {
+            "classmap": [
+                "src/"
+            ]
+        },
+        "notification-url": "https://packagist.org/downloads/",
+        "license": [
+            "BSD-3-Clause"
+        ],
+        "authors": [
+            {
+                "name": "Sebastian Bergmann",
+                "email": "sebastian@phpunit.de"
+            }
+        ],
+        "description": "Snapshotting of global state",
+        "homepage": "http://www.github.com/sebastianbergmann/global-state",
         "keywords": [
-            "respect",
-            "validation",
-            "validator"
+            "global state"
+        ],
+        "funding": [
+            {
+                "url": "https://github.com/sebastianbergmann",
+                "type": "github"
+            }
+        ]
+    },
+    {
+        "name": "sebastian/lines-of-code",
+        "version": "1.0.3",
+        "version_normalized": "1.0.3.0",
+        "source": {
+            "type": "git",
+            "url": "https://github.com/sebastianbergmann/lines-of-code.git",
+            "reference": "c1c2e997aa3146983ed888ad08b15470a2e22ecc"
+        },
+        "dist": {
+            "type": "zip",
+            "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/c1c2e997aa3146983ed888ad08b15470a2e22ecc",
+            "reference": "c1c2e997aa3146983ed888ad08b15470a2e22ecc",
+            "shasum": ""
+        },
+        "require": {
+            "nikic/php-parser": "^4.6",
+            "php": ">=7.3"
+        },
+        "require-dev": {
+            "phpunit/phpunit": "^9.3"
+        },
+        "time": "2020-11-28T06:42:11+00:00",
+        "type": "library",
+        "extra": {
+            "branch-alias": {
+                "dev-master": "1.0-dev"
+            }
+        },
+        "installation-source": "dist",
+        "autoload": {
+            "classmap": [
+                "src/"
+            ]
+        },
+        "notification-url": "https://packagist.org/downloads/",
+        "license": [
+            "BSD-3-Clause"
+        ],
+        "authors": [
+            {
+                "name": "Sebastian Bergmann",
+                "email": "sebastian@phpunit.de",
+                "role": "lead"
+            }
+        ],
+        "description": "Library for counting the lines of code in PHP source code",
+        "homepage": "https://github.com/sebastianbergmann/lines-of-code",
+        "funding": [
+            {
+                "url": "https://github.com/sebastianbergmann",
+                "type": "github"
+            }
+        ]
+    },
+    {
+        "name": "sebastian/object-enumerator",
+        "version": "4.0.4",
+        "version_normalized": "4.0.4.0",
+        "source": {
+            "type": "git",
+            "url": "https://github.com/sebastianbergmann/object-enumerator.git",
+            "reference": "5c9eeac41b290a3712d88851518825ad78f45c71"
+        },
+        "dist": {
+            "type": "zip",
+            "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/5c9eeac41b290a3712d88851518825ad78f45c71",
+            "reference": "5c9eeac41b290a3712d88851518825ad78f45c71",
+            "shasum": ""
+        },
+        "require": {
+            "php": ">=7.3",
+            "sebastian/object-reflector": "^2.0",
+            "sebastian/recursion-context": "^4.0"
+        },
+        "require-dev": {
+            "phpunit/phpunit": "^9.3"
+        },
+        "time": "2020-10-26T13:12:34+00:00",
+        "type": "library",
+        "extra": {
+            "branch-alias": {
+                "dev-master": "4.0-dev"
+            }
+        },
+        "installation-source": "dist",
+        "autoload": {
+            "classmap": [
+                "src/"
+            ]
+        },
+        "notification-url": "https://packagist.org/downloads/",
+        "license": [
+            "BSD-3-Clause"
+        ],
+        "authors": [
+            {
+                "name": "Sebastian Bergmann",
+                "email": "sebastian@phpunit.de"
+            }
+        ],
+        "description": "Traverses array structures and object graphs to enumerate all referenced objects",
+        "homepage": "https://github.com/sebastianbergmann/object-enumerator/",
+        "funding": [
+            {
+                "url": "https://github.com/sebastianbergmann",
+                "type": "github"
+            }
+        ]
+    },
+    {
+        "name": "sebastian/object-reflector",
+        "version": "2.0.4",
+        "version_normalized": "2.0.4.0",
+        "source": {
+            "type": "git",
+            "url": "https://github.com/sebastianbergmann/object-reflector.git",
+            "reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7"
+        },
+        "dist": {
+            "type": "zip",
+            "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/b4f479ebdbf63ac605d183ece17d8d7fe49c15c7",
+            "reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7",
+            "shasum": ""
+        },
+        "require": {
+            "php": ">=7.3"
+        },
+        "require-dev": {
+            "phpunit/phpunit": "^9.3"
+        },
+        "time": "2020-10-26T13:14:26+00:00",
+        "type": "library",
+        "extra": {
+            "branch-alias": {
+                "dev-master": "2.0-dev"
+            }
+        },
+        "installation-source": "dist",
+        "autoload": {
+            "classmap": [
+                "src/"
+            ]
+        },
+        "notification-url": "https://packagist.org/downloads/",
+        "license": [
+            "BSD-3-Clause"
+        ],
+        "authors": [
+            {
+                "name": "Sebastian Bergmann",
+                "email": "sebastian@phpunit.de"
+            }
+        ],
+        "description": "Allows reflection of object attributes, including inherited and non-public ones",
+        "homepage": "https://github.com/sebastianbergmann/object-reflector/",
+        "funding": [
+            {
+                "url": "https://github.com/sebastianbergmann",
+                "type": "github"
+            }
+        ]
+    },
+    {
+        "name": "sebastian/recursion-context",
+        "version": "4.0.4",
+        "version_normalized": "4.0.4.0",
+        "source": {
+            "type": "git",
+            "url": "https://github.com/sebastianbergmann/recursion-context.git",
+            "reference": "cd9d8cf3c5804de4341c283ed787f099f5506172"
+        },
+        "dist": {
+            "type": "zip",
+            "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/cd9d8cf3c5804de4341c283ed787f099f5506172",
+            "reference": "cd9d8cf3c5804de4341c283ed787f099f5506172",
+            "shasum": ""
+        },
+        "require": {
+            "php": ">=7.3"
+        },
+        "require-dev": {
+            "phpunit/phpunit": "^9.3"
+        },
+        "time": "2020-10-26T13:17:30+00:00",
+        "type": "library",
+        "extra": {
+            "branch-alias": {
+                "dev-master": "4.0-dev"
+            }
+        },
+        "installation-source": "dist",
+        "autoload": {
+            "classmap": [
+                "src/"
+            ]
+        },
+        "notification-url": "https://packagist.org/downloads/",
+        "license": [
+            "BSD-3-Clause"
+        ],
+        "authors": [
+            {
+                "name": "Sebastian Bergmann",
+                "email": "sebastian@phpunit.de"
+            },
+            {
+                "name": "Jeff Welch",
+                "email": "whatthejeff@gmail.com"
+            },
+            {
+                "name": "Adam Harvey",
+                "email": "aharvey@php.net"
+            }
+        ],
+        "description": "Provides functionality to recursively process PHP variables",
+        "homepage": "http://www.github.com/sebastianbergmann/recursion-context",
+        "funding": [
+            {
+                "url": "https://github.com/sebastianbergmann",
+                "type": "github"
+            }
+        ]
+    },
+    {
+        "name": "sebastian/resource-operations",
+        "version": "3.0.3",
+        "version_normalized": "3.0.3.0",
+        "source": {
+            "type": "git",
+            "url": "https://github.com/sebastianbergmann/resource-operations.git",
+            "reference": "0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8"
+        },
+        "dist": {
+            "type": "zip",
+            "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8",
+            "reference": "0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8",
+            "shasum": ""
+        },
+        "require": {
+            "php": ">=7.3"
+        },
+        "require-dev": {
+            "phpunit/phpunit": "^9.0"
+        },
+        "time": "2020-09-28T06:45:17+00:00",
+        "type": "library",
+        "extra": {
+            "branch-alias": {
+                "dev-master": "3.0-dev"
+            }
+        },
+        "installation-source": "dist",
+        "autoload": {
+            "classmap": [
+                "src/"
+            ]
+        },
+        "notification-url": "https://packagist.org/downloads/",
+        "license": [
+            "BSD-3-Clause"
+        ],
+        "authors": [
+            {
+                "name": "Sebastian Bergmann",
+                "email": "sebastian@phpunit.de"
+            }
+        ],
+        "description": "Provides a list of PHP built-in functions that operate on resources",
+        "homepage": "https://www.github.com/sebastianbergmann/resource-operations",
+        "funding": [
+            {
+                "url": "https://github.com/sebastianbergmann",
+                "type": "github"
+            }
+        ]
+    },
+    {
+        "name": "sebastian/type",
+        "version": "2.3.1",
+        "version_normalized": "2.3.1.0",
+        "source": {
+            "type": "git",
+            "url": "https://github.com/sebastianbergmann/type.git",
+            "reference": "81cd61ab7bbf2de744aba0ea61fae32f721df3d2"
+        },
+        "dist": {
+            "type": "zip",
+            "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/81cd61ab7bbf2de744aba0ea61fae32f721df3d2",
+            "reference": "81cd61ab7bbf2de744aba0ea61fae32f721df3d2",
+            "shasum": ""
+        },
+        "require": {
+            "php": ">=7.3"
+        },
+        "require-dev": {
+            "phpunit/phpunit": "^9.3"
+        },
+        "time": "2020-10-26T13:18:59+00:00",
+        "type": "library",
+        "extra": {
+            "branch-alias": {
+                "dev-master": "2.3-dev"
+            }
+        },
+        "installation-source": "dist",
+        "autoload": {
+            "classmap": [
+                "src/"
+            ]
+        },
+        "notification-url": "https://packagist.org/downloads/",
+        "license": [
+            "BSD-3-Clause"
+        ],
+        "authors": [
+            {
+                "name": "Sebastian Bergmann",
+                "email": "sebastian@phpunit.de",
+                "role": "lead"
+            }
+        ],
+        "description": "Collection of value objects that represent the types of the PHP type system",
+        "homepage": "https://github.com/sebastianbergmann/type",
+        "funding": [
+            {
+                "url": "https://github.com/sebastianbergmann",
+                "type": "github"
+            }
+        ]
+    },
+    {
+        "name": "sebastian/version",
+        "version": "3.0.2",
+        "version_normalized": "3.0.2.0",
+        "source": {
+            "type": "git",
+            "url": "https://github.com/sebastianbergmann/version.git",
+            "reference": "c6c1022351a901512170118436c764e473f6de8c"
+        },
+        "dist": {
+            "type": "zip",
+            "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c6c1022351a901512170118436c764e473f6de8c",
+            "reference": "c6c1022351a901512170118436c764e473f6de8c",
+            "shasum": ""
+        },
+        "require": {
+            "php": ">=7.3"
+        },
+        "time": "2020-09-28T06:39:44+00:00",
+        "type": "library",
+        "extra": {
+            "branch-alias": {
+                "dev-master": "3.0-dev"
+            }
+        },
+        "installation-source": "dist",
+        "autoload": {
+            "classmap": [
+                "src/"
+            ]
+        },
+        "notification-url": "https://packagist.org/downloads/",
+        "license": [
+            "BSD-3-Clause"
+        ],
+        "authors": [
+            {
+                "name": "Sebastian Bergmann",
+                "email": "sebastian@phpunit.de",
+                "role": "lead"
+            }
+        ],
+        "description": "Library that helps with managing the version number of Git-hosted PHP projects",
+        "homepage": "https://github.com/sebastianbergmann/version",
+        "funding": [
+            {
+                "url": "https://github.com/sebastianbergmann",
+                "type": "github"
+            }
         ]
     },
     {
         "name": "setasign/fpdi",
-        "version": "v2.1.1",
-        "version_normalized": "2.1.1.0",
+        "version": "v2.3.3",
+        "version_normalized": "2.3.3.0",
         "source": {
             "type": "git",
             "url": "https://github.com/Setasign/FPDI.git",
-            "reference": "356de9cb6b6a826ac952c86aee6599463ea87362"
+            "reference": "50c388860a73191e010810ed57dbed795578e867"
         },
         "dist": {
             "type": "zip",
-            "url": "https://api.github.com/repos/Setasign/FPDI/zipball/356de9cb6b6a826ac952c86aee6599463ea87362",
-            "reference": "356de9cb6b6a826ac952c86aee6599463ea87362",
+            "url": "https://api.github.com/repos/Setasign/FPDI/zipball/50c388860a73191e010810ed57dbed795578e867",
+            "reference": "50c388860a73191e010810ed57dbed795578e867",
             "shasum": ""
         },
         "require": {
             "ext-zlib": "*",
             "php": "^5.6 || ^7.0"
         },
+        "conflict": {
+            "setasign/tfpdf": "<1.31"
+        },
         "require-dev": {
             "phpunit/phpunit": "~5.7",
             "setasign/fpdf": "~1.8",
-            "setasign/tfpdf": "1.25",
+            "setasign/tfpdf": "1.31",
             "tecnickcom/tcpdf": "~6.2"
         },
         "suggest": {
-            "setasign/fpdf": "FPDI will extend this class but as it is also possible to use TCPDF or tFPDF as an alternative. There's no fixed dependency configured.",
-            "setasign/fpdi-fpdf": "Use this package to automatically evaluate dependencies to FPDF.",
-            "setasign/fpdi-tcpdf": "Use this package to automatically evaluate dependencies to TCPDF.",
-            "setasign/fpdi-tfpdf": "Use this package to automatically evaluate dependencies to tFPDF."
+            "setasign/fpdf": "FPDI will extend this class but as it is also possible to use TCPDF or tFPDF as an alternative. There's no fixed dependency configured."
         },
-        "time": "2018-11-06T10:02:00+00:00",
+        "time": "2020-04-28T12:40:35+00:00",
         "type": "library",
         "installation-source": "dist",
         "autoload": {
@@ -478,28 +2463,34 @@
             "fpdf",
             "fpdi",
             "pdf"
+        ],
+        "funding": [
+            {
+                "url": "https://tidelift.com/funding/github/packagist/setasign/fpdi",
+                "type": "tidelift"
+            }
         ]
     },
     {
         "name": "setasign/fpdi-tcpdf",
-        "version": "v2.1.0",
-        "version_normalized": "2.1.0.0",
+        "version": "v2.3.0",
+        "version_normalized": "2.3.0.0",
         "source": {
             "type": "git",
             "url": "https://github.com/Setasign/FPDI-TCPDF.git",
-            "reference": "9ebaf04475c0171d4b43b6eb579120ca02da22e8"
+            "reference": "f6711a95cba64db16e1a63e1b6195827a2150c93"
         },
         "dist": {
             "type": "zip",
-            "url": "https://api.github.com/repos/Setasign/FPDI-TCPDF/zipball/9ebaf04475c0171d4b43b6eb579120ca02da22e8",
-            "reference": "9ebaf04475c0171d4b43b6eb579120ca02da22e8",
+            "url": "https://api.github.com/repos/Setasign/FPDI-TCPDF/zipball/f6711a95cba64db16e1a63e1b6195827a2150c93",
+            "reference": "f6711a95cba64db16e1a63e1b6195827a2150c93",
             "shasum": ""
         },
         "require": {
-            "setasign/fpdi": "^2.1",
-            "tecnickcom/tcpdf": "^6.2"
+            "setasign/fpdi": "^2.3",
+            "tecnickcom/tcpdf": "^6.3.5"
         },
-        "time": "2018-11-06T10:38:50+00:00",
+        "time": "2020-02-19T11:40:30+00:00",
         "type": "library",
         "installation-source": "dist",
         "notification-url": "https://packagist.org/downloads/",
@@ -524,21 +2515,23 @@
     },
     {
         "name": "slim/slim",
-        "version": "3.11.0",
-        "version_normalized": "3.11.0.0",
+        "version": "3.12.3",
+        "version_normalized": "3.12.3.0",
         "source": {
             "type": "git",
             "url": "https://github.com/slimphp/Slim.git",
-            "reference": "d378e70431e78ee92ee32ddde61ecc72edf5dc0a"
+            "reference": "1c9318a84ffb890900901136d620b4f03a59da38"
         },
         "dist": {
             "type": "zip",
-            "url": "https://api.github.com/repos/slimphp/Slim/zipball/d378e70431e78ee92ee32ddde61ecc72edf5dc0a",
-            "reference": "d378e70431e78ee92ee32ddde61ecc72edf5dc0a",
+            "url": "https://api.github.com/repos/slimphp/Slim/zipball/1c9318a84ffb890900901136d620b4f03a59da38",
+            "reference": "1c9318a84ffb890900901136d620b4f03a59da38",
             "shasum": ""
         },
         "require": {
-            "container-interop/container-interop": "^1.2",
+            "ext-json": "*",
+            "ext-libxml": "*",
+            "ext-simplexml": "*",
             "nikic/fast-route": "^1.0",
             "php": ">=5.5.0",
             "pimple/pimple": "^3.0",
@@ -552,7 +2545,7 @@
             "phpunit/phpunit": "^4.0",
             "squizlabs/php_codesniffer": "^2.5"
         },
-        "time": "2018-09-16T10:54:21+00:00",
+        "time": "2019-11-28T17:40:33+00:00",
         "type": "library",
         "installation-source": "dist",
         "autoload": {
@@ -565,25 +2558,25 @@
             "MIT"
         ],
         "authors": [
-            {
-                "name": "Rob Allen",
-                "email": "rob@akrabat.com",
-                "homepage": "http://akrabat.com"
-            },
             {
                 "name": "Josh Lockhart",
                 "email": "hello@joshlockhart.com",
                 "homepage": "https://joshlockhart.com"
             },
-            {
-                "name": "Gabriel Manricks",
-                "email": "gmanricks@me.com",
-                "homepage": "http://gabrielmanricks.com"
-            },
             {
                 "name": "Andrew Smith",
                 "email": "a.smith@silentworks.co.uk",
                 "homepage": "http://silentworks.co.uk"
+            },
+            {
+                "name": "Rob Allen",
+                "email": "rob@akrabat.com",
+                "homepage": "http://akrabat.com"
+            },
+            {
+                "name": "Gabriel Manricks",
+                "email": "gmanricks@me.com",
+                "homepage": "http://gabrielmanricks.com"
             }
         ],
         "description": "Slim is a PHP micro framework that helps you quickly write simple yet powerful web applications and APIs",
@@ -595,19 +2588,97 @@
             "router"
         ]
     },
+    {
+        "name": "symfony/polyfill-ctype",
+        "version": "v1.22.1",
+        "version_normalized": "1.22.1.0",
+        "source": {
+            "type": "git",
+            "url": "https://github.com/symfony/polyfill-ctype.git",
+            "reference": "c6c942b1ac76c82448322025e084cadc56048b4e"
+        },
+        "dist": {
+            "type": "zip",
+            "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/c6c942b1ac76c82448322025e084cadc56048b4e",
+            "reference": "c6c942b1ac76c82448322025e084cadc56048b4e",
+            "shasum": ""
+        },
+        "require": {
+            "php": ">=7.1"
+        },
+        "suggest": {
+            "ext-ctype": "For best performance"
+        },
+        "time": "2021-01-07T16:49:33+00:00",
+        "type": "library",
+        "extra": {
+            "branch-alias": {
+                "dev-main": "1.22-dev"
+            },
+            "thanks": {
+                "name": "symfony/polyfill",
+                "url": "https://github.com/symfony/polyfill"
+            }
+        },
+        "installation-source": "dist",
+        "autoload": {
+            "psr-4": {
+                "Symfony\\Polyfill\\Ctype\\": ""
+            },
+            "files": [
+                "bootstrap.php"
+            ]
+        },
+        "notification-url": "https://packagist.org/downloads/",
+        "license": [
+            "MIT"
+        ],
+        "authors": [
+            {
+                "name": "Gert de Pagter",
+                "email": "BackEndTea@gmail.com"
+            },
+            {
+                "name": "Symfony Community",
+                "homepage": "https://symfony.com/contributors"
+            }
+        ],
+        "description": "Symfony polyfill for ctype functions",
+        "homepage": "https://symfony.com",
+        "keywords": [
+            "compatibility",
+            "ctype",
+            "polyfill",
+            "portable"
+        ],
+        "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"
+            }
+        ]
+    },
     {
         "name": "symfony/polyfill-mbstring",
-        "version": "v1.10.0",
-        "version_normalized": "1.10.0.0",
+        "version": "v1.18.0",
+        "version_normalized": "1.18.0.0",
         "source": {
             "type": "git",
             "url": "https://github.com/symfony/polyfill-mbstring.git",
-            "reference": "c79c051f5b3a46be09205c73b80b346e4153e494"
+            "reference": "a6977d63bf9a0ad4c65cd352709e230876f9904a"
         },
         "dist": {
             "type": "zip",
-            "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/c79c051f5b3a46be09205c73b80b346e4153e494",
-            "reference": "c79c051f5b3a46be09205c73b80b346e4153e494",
+            "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/a6977d63bf9a0ad4c65cd352709e230876f9904a",
+            "reference": "a6977d63bf9a0ad4c65cd352709e230876f9904a",
             "shasum": ""
         },
         "require": {
@@ -616,11 +2687,15 @@
         "suggest": {
             "ext-mbstring": "For best performance"
         },
-        "time": "2018-09-21T13:07:52+00:00",
+        "time": "2020-07-14T12:35:20+00:00",
         "type": "library",
         "extra": {
             "branch-alias": {
-                "dev-master": "1.9-dev"
+                "dev-master": "1.18-dev"
+            },
+            "thanks": {
+                "name": "symfony/polyfill",
+                "url": "https://github.com/symfony/polyfill"
             }
         },
         "installation-source": "dist",
@@ -654,6 +2729,168 @@
             "polyfill",
             "portable",
             "shim"
+        ],
+        "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"
+            }
+        ]
+    },
+    {
+        "name": "symfony/polyfill-php56",
+        "version": "v1.18.0",
+        "version_normalized": "1.18.0.0",
+        "source": {
+            "type": "git",
+            "url": "https://github.com/symfony/polyfill-php56.git",
+            "reference": "13df84e91cd168f247c2f2ec82cc0fa24901c011"
+        },
+        "dist": {
+            "type": "zip",
+            "url": "https://api.github.com/repos/symfony/polyfill-php56/zipball/13df84e91cd168f247c2f2ec82cc0fa24901c011",
+            "reference": "13df84e91cd168f247c2f2ec82cc0fa24901c011",
+            "shasum": ""
+        },
+        "require": {
+            "php": ">=5.3.3",
+            "symfony/polyfill-util": "~1.0"
+        },
+        "time": "2020-07-14T12:35:20+00:00",
+        "type": "library",
+        "extra": {
+            "branch-alias": {
+                "dev-master": "1.18-dev"
+            },
+            "thanks": {
+                "name": "symfony/polyfill",
+                "url": "https://github.com/symfony/polyfill"
+            }
+        },
+        "installation-source": "dist",
+        "autoload": {
+            "psr-4": {
+                "Symfony\\Polyfill\\Php56\\": ""
+            },
+            "files": [
+                "bootstrap.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": "Symfony polyfill backporting some PHP 5.6+ features to lower PHP versions",
+        "homepage": "https://symfony.com",
+        "keywords": [
+            "compatibility",
+            "polyfill",
+            "portable",
+            "shim"
+        ],
+        "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"
+            }
+        ]
+    },
+    {
+        "name": "symfony/polyfill-util",
+        "version": "v1.18.0",
+        "version_normalized": "1.18.0.0",
+        "source": {
+            "type": "git",
+            "url": "https://github.com/symfony/polyfill-util.git",
+            "reference": "46b910c71e9828f8ec2aa7a0314de1130d9b295a"
+        },
+        "dist": {
+            "type": "zip",
+            "url": "https://api.github.com/repos/symfony/polyfill-util/zipball/46b910c71e9828f8ec2aa7a0314de1130d9b295a",
+            "reference": "46b910c71e9828f8ec2aa7a0314de1130d9b295a",
+            "shasum": ""
+        },
+        "require": {
+            "php": ">=5.3.3"
+        },
+        "time": "2020-07-14T12:35:20+00:00",
+        "type": "library",
+        "extra": {
+            "branch-alias": {
+                "dev-master": "1.18-dev"
+            },
+            "thanks": {
+                "name": "symfony/polyfill",
+                "url": "https://github.com/symfony/polyfill"
+            }
+        },
+        "installation-source": "dist",
+        "autoload": {
+            "psr-4": {
+                "Symfony\\Polyfill\\Util\\": ""
+            }
+        },
+        "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": "Symfony utilities for portability of PHP codes",
+        "homepage": "https://symfony.com",
+        "keywords": [
+            "compat",
+            "compatibility",
+            "polyfill",
+            "shim"
+        ],
+        "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"
+            }
         ]
     },
     {
@@ -719,5 +2956,109 @@
             "pdf417",
             "qrcode"
         ]
+    },
+    {
+        "name": "theseer/tokenizer",
+        "version": "1.2.0",
+        "version_normalized": "1.2.0.0",
+        "source": {
+            "type": "git",
+            "url": "https://github.com/theseer/tokenizer.git",
+            "reference": "75a63c33a8577608444246075ea0af0d052e452a"
+        },
+        "dist": {
+            "type": "zip",
+            "url": "https://api.github.com/repos/theseer/tokenizer/zipball/75a63c33a8577608444246075ea0af0d052e452a",
+            "reference": "75a63c33a8577608444246075ea0af0d052e452a",
+            "shasum": ""
+        },
+        "require": {
+            "ext-dom": "*",
+            "ext-tokenizer": "*",
+            "ext-xmlwriter": "*",
+            "php": "^7.2 || ^8.0"
+        },
+        "time": "2020-07-12T23:59:07+00:00",
+        "type": "library",
+        "installation-source": "dist",
+        "autoload": {
+            "classmap": [
+                "src/"
+            ]
+        },
+        "notification-url": "https://packagist.org/downloads/",
+        "license": [
+            "BSD-3-Clause"
+        ],
+        "authors": [
+            {
+                "name": "Arne Blankerts",
+                "email": "arne@blankerts.de",
+                "role": "Developer"
+            }
+        ],
+        "description": "A small library for converting tokenized PHP source code into XML and potentially other formats",
+        "funding": [
+            {
+                "url": "https://github.com/theseer",
+                "type": "github"
+            }
+        ]
+    },
+    {
+        "name": "webmozart/assert",
+        "version": "1.10.0",
+        "version_normalized": "1.10.0.0",
+        "source": {
+            "type": "git",
+            "url": "https://github.com/webmozarts/assert.git",
+            "reference": "6964c76c7804814a842473e0c8fd15bab0f18e25"
+        },
+        "dist": {
+            "type": "zip",
+            "url": "https://api.github.com/repos/webmozarts/assert/zipball/6964c76c7804814a842473e0c8fd15bab0f18e25",
+            "reference": "6964c76c7804814a842473e0c8fd15bab0f18e25",
+            "shasum": ""
+        },
+        "require": {
+            "php": "^7.2 || ^8.0",
+            "symfony/polyfill-ctype": "^1.8"
+        },
+        "conflict": {
+            "phpstan/phpstan": "<0.12.20",
+            "vimeo/psalm": "<4.6.1 || 4.6.2"
+        },
+        "require-dev": {
+            "phpunit/phpunit": "^8.5.13"
+        },
+        "time": "2021-03-09T10:59:23+00:00",
+        "type": "library",
+        "extra": {
+            "branch-alias": {
+                "dev-master": "1.10-dev"
+            }
+        },
+        "installation-source": "dist",
+        "autoload": {
+            "psr-4": {
+                "Webmozart\\Assert\\": "src/"
+            }
+        },
+        "notification-url": "https://packagist.org/downloads/",
+        "license": [
+            "MIT"
+        ],
+        "authors": [
+            {
+                "name": "Bernhard Schussek",
+                "email": "bschussek@gmail.com"
+            }
+        ],
+        "description": "Assertions to validate method input/output with nice error messages.",
+        "keywords": [
+            "assert",
+            "check",
+            "validate"
+        ]
     }
 ]
diff --git a/vendor/container-interop/container-interop/.gitignore b/vendor/container-interop/container-interop/.gitignore
deleted file mode 100644
index b2395aa05541e1e90c84bdc3ce67115c8b84c385..0000000000000000000000000000000000000000
--- a/vendor/container-interop/container-interop/.gitignore
+++ /dev/null
@@ -1,3 +0,0 @@
-composer.lock
-composer.phar
-/vendor/
diff --git a/vendor/container-interop/container-interop/README.md b/vendor/container-interop/container-interop/README.md
deleted file mode 100644
index cdd7a44c8ee8f3da7b6b57bb4542272e9f25501b..0000000000000000000000000000000000000000
--- a/vendor/container-interop/container-interop/README.md
+++ /dev/null
@@ -1,148 +0,0 @@
-# Container Interoperability
-
-[![Latest Stable Version](https://poser.pugx.org/container-interop/container-interop/v/stable.png)](https://packagist.org/packages/container-interop/container-interop)
-[![Total Downloads](https://poser.pugx.org/container-interop/container-interop/downloads.svg)](https://packagist.org/packages/container-interop/container-interop)
-
-## Deprecation warning!
-
-Starting Feb. 13th 2017, container-interop is officially deprecated in favor of [PSR-11](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-11-container.md).
-Container-interop has been the test-bed of PSR-11. From v1.2, container-interop directly extends PSR-11 interfaces.
-Therefore, all containers implementing container-interop are now *de-facto* compatible with PSR-11.
-
-- Projects implementing container-interop interfaces are encouraged to directly implement PSR-11 interfaces instead.
-- Projects consuming container-interop interfaces are very strongly encouraged to directly type-hint on PSR-11 interfaces, in order to be compatible with PSR-11 containers that are not compatible with container-interop.
-
-Regarding the delegate lookup feature, that is present in container-interop and not in PSR-11, the feature is actually a design pattern. It is therefore not deprecated. Documentation regarding this design pattern will be migrated from this repository into a separate website in the future.
-
-## About
-
-*container-interop* tries to identify and standardize features in *container* objects (service locators,
-dependency injection containers, etc.) to achieve interoperability.
-
-Through discussions and trials, we try to create a standard, made of common interfaces but also recommendations.
-
-If PHP projects that provide container implementations begin to adopt these common standards, then PHP
-applications and projects that use containers can depend on the common interfaces instead of specific
-implementations. This facilitates a high-level of interoperability and flexibility that allows users to consume
-*any* container implementation that can be adapted to these interfaces.
-
-The work done in this project is not officially endorsed by the [PHP-FIG](http://www.php-fig.org/), but it is being
-worked on by members of PHP-FIG and other good developers. We adhere to the spirit and ideals of PHP-FIG, and hope
-this project will pave the way for one or more future PSRs.
-
-
-## Installation
-
-You can install this package through Composer:
-
-```json
-composer require container-interop/container-interop
-```
-
-The packages adheres to the [SemVer](http://semver.org/) specification, and there will be full backward compatibility
-between minor versions.
-
-## Standards
-
-### Available
-
-- [`ContainerInterface`](src/Interop/Container/ContainerInterface.php).
-[Description](docs/ContainerInterface.md) [Meta Document](docs/ContainerInterface-meta.md).
-Describes the interface of a container that exposes methods to read its entries.
-- [*Delegate lookup feature*](docs/Delegate-lookup.md).
-[Meta Document](docs/Delegate-lookup-meta.md).
-Describes the ability for a container to delegate the lookup of its dependencies to a third-party container. This
-feature lets several containers work together in a single application.
-
-### Proposed
-
-View open [request for comments](https://github.com/container-interop/container-interop/labels/RFC)
-
-## Compatible projects
-
-### Projects implementing `ContainerInterface`
-
-- [Acclimate](https://github.com/jeremeamia/acclimate-container): Adapters for
-  Aura.Di, Laravel, Nette DI, Pimple, Symfony DI, ZF2 Service manager, ZF2
-  Dependency injection and any container using `ArrayAccess`
-- [Aura.Di](https://github.com/auraphp/Aura.Di)
-- [auryn-container-interop](https://github.com/elazar/auryn-container-interop)
-- [Burlap](https://github.com/codeeverything/burlap)
-- [Chernozem](https://github.com/pyrsmk/Chernozem)
-- [Data Manager](https://github.com/chrismichaels84/data-manager)
-- [Disco](https://github.com/bitexpert/disco)
-- [InDI](https://github.com/idealogica/indi)
-- [League/Container](http://container.thephpleague.com/)
-- [Mouf](http://mouf-php.com)
-- [Njasm Container](https://github.com/njasm/container)
-- [PHP-DI](http://php-di.org)
-- [Picotainer](https://github.com/thecodingmachine/picotainer)
-- [PimpleInterop](https://github.com/moufmouf/pimple-interop)
-- [Pimple3-ContainerInterop](https://github.com/Sam-Burns/pimple3-containerinterop) (using Pimple v3)
-- [SitePoint Container](https://github.com/sitepoint/Container)
-- [Thruster Container](https://github.com/ThrusterIO/container) (PHP7 only)
-- [Ultra-Lite Container](https://github.com/ultra-lite/container)
-- [Unbox](https://github.com/mindplay-dk/unbox)
-- [XStatic](https://github.com/jeremeamia/xstatic)
-- [Zend\ServiceManager](https://github.com/zendframework/zend-servicemanager)
-- [Zit](https://github.com/inxilpro/Zit)
-
-### Projects implementing the *delegate lookup* feature
-
-- [Aura.Di](https://github.com/auraphp/Aura.Di)
-- [Burlap](https://github.com/codeeverything/burlap)
-- [Chernozem](https://github.com/pyrsmk/Chernozem)
-- [InDI](https://github.com/idealogica/indi)
-- [League/Container](http://container.thephpleague.com/)
-- [Mouf](http://mouf-php.com)
-- [Picotainer](https://github.com/thecodingmachine/picotainer)
-- [PHP-DI](http://php-di.org)
-- [PimpleInterop](https://github.com/moufmouf/pimple-interop)
-- [Ultra-Lite Container](https://github.com/ultra-lite/container)
-
-### Middlewares implementing `ContainerInterface`
-
-- [Alias-Container](https://github.com/thecodingmachine/alias-container): add
-  aliases support to any container
-- [Prefixer-Container](https://github.com/thecodingmachine/prefixer-container):
-  dynamically prefix identifiers
-- [Lazy-Container](https://github.com/snapshotpl/lazy-container): lazy services
-
-### Projects using `ContainerInterface`
-
-The list below contains only a sample of all the projects consuming `ContainerInterface`. For a more complete list have a look [here](http://packanalyst.com/class?q=Interop%5CContainer%5CContainerInterface).
-
-| | Downloads |
-| --- | --- |
-| [Adroit](https://github.com/bitexpert/adroit) | ![](https://img.shields.io/packagist/dt/bitexpert/adroit.svg) |
-| [Behat](https://github.com/Behat/Behat/pull/974) | ![](https://img.shields.io/packagist/dt/behat/behat.svg) |
-| [blast-facades](https://github.com/phpthinktank/blast-facades): Minimize complexity and represent dependencies as facades. | ![](https://img.shields.io/packagist/dt/blast/facades.svg) |
-| [interop.silex.di](https://github.com/thecodingmachine/interop.silex.di): an extension to [Silex](http://silex.sensiolabs.org/) that adds support for any *container-interop* compatible container | ![](https://img.shields.io/packagist/dt/mouf/interop.silex.di.svg) |
-| [mindplay/walkway](https://github.com/mindplay-dk/walkway): a modular request router | ![](https://img.shields.io/packagist/dt/mindplay/walkway.svg) |
-| [mindplay/middleman](https://github.com/mindplay-dk/middleman): minimalist PSR-7 middleware dispatcher | ![](https://img.shields.io/packagist/dt/mindplay/middleman.svg) |
-| [PHP-DI/Invoker](https://github.com/PHP-DI/Invoker): extensible and configurable invoker/dispatcher | ![](https://img.shields.io/packagist/dt/php-di/invoker.svg) |
-| [Prophiler](https://github.com/fabfuel/prophiler) | ![](https://img.shields.io/packagist/dt/fabfuel/prophiler.svg) |
-| [Silly](https://github.com/mnapoli/silly): CLI micro-framework | ![](https://img.shields.io/packagist/dt/mnapoli/silly.svg) |
-| [Slim v3](https://github.com/slimphp/Slim) | ![](https://img.shields.io/packagist/dt/slim/slim.svg) |
-| [Splash](http://mouf-php.com/packages/mouf/mvc.splash-common/version/8.0-dev/README.md) | ![](https://img.shields.io/packagist/dt/mouf/mvc.splash-common.svg) |
-| [Woohoo Labs. Harmony](https://github.com/woohoolabs/harmony): a flexible micro-framework | ![](https://img.shields.io/packagist/dt/woohoolabs/harmony.svg) |
-| [zend-expressive](https://github.com/zendframework/zend-expressive) | ![](https://img.shields.io/packagist/dt/zendframework/zend-expressive.svg) |
-
-
-## Workflow
-
-Everyone is welcome to join and contribute.
-
-The general workflow looks like this:
-
-1. Someone opens a discussion (GitHub issue) to suggest an interface
-1. Feedback is gathered
-1. The interface is added to a development branch
-1. We release alpha versions so that the interface can be experimented with
-1. Discussions and edits ensue until the interface is deemed stable by a general consensus
-1. A new minor version of the package is released
-
-We try to not break BC by creating new interfaces instead of editing existing ones.
-
-While we currently work on interfaces, we are open to anything that might help towards interoperability, may that
-be code, best practices, etc.
diff --git a/vendor/container-interop/container-interop/composer.json b/vendor/container-interop/container-interop/composer.json
deleted file mode 100644
index 855f766723a07230761813b80e9c843efb2acb81..0000000000000000000000000000000000000000
--- a/vendor/container-interop/container-interop/composer.json
+++ /dev/null
@@ -1,15 +0,0 @@
-{
-    "name": "container-interop/container-interop",
-    "type": "library",
-    "description": "Promoting the interoperability of container objects (DIC, SL, etc.)",
-    "homepage": "https://github.com/container-interop/container-interop",
-    "license": "MIT",
-    "autoload": {
-        "psr-4": {
-            "Interop\\Container\\": "src/Interop/Container/"
-        }
-    },
-    "require": {
-        "psr/container": "^1.0"
-    }
-}
diff --git a/vendor/container-interop/container-interop/docs/ContainerInterface-meta.md b/vendor/container-interop/container-interop/docs/ContainerInterface-meta.md
deleted file mode 100644
index 59f3d5599faf8a035dee448b0df230719cc61444..0000000000000000000000000000000000000000
--- a/vendor/container-interop/container-interop/docs/ContainerInterface-meta.md
+++ /dev/null
@@ -1,114 +0,0 @@
-# ContainerInterface Meta Document
-
-## Introduction
-
-This document describes the process and discussions that lead to the `ContainerInterface`.
-Its goal is to explain the reasons behind each decision.
-
-## Goal
-
-The goal set by `ContainerInterface` is to standardize how frameworks and libraries make use of a
-container to obtain objects and parameters.
-
-By standardizing such a behavior, frameworks and libraries using the `ContainerInterface`
-could work with any compatible container.
-That would allow end users to choose their own container based on their own preferences.
-
-It is important to distinguish the two usages of a container:
-
-- configuring entries
-- fetching entries
-
-Most of the time, those two sides are not used by the same party.
-While it is often end users who tend to configure entries, it is generally the framework that fetch
-entries to build the application.
-
-This is why this interface focuses only on how entries can be fetched from a container.
-
-## Interface name
-
-The interface name has been thoroughly discussed and was decided by a vote.
-
-The list of options considered with their respective votes are:
-
-- `ContainerInterface`: +8
-- `ProviderInterface`: +2
-- `LocatorInterface`: 0
-- `ReadableContainerInterface`: -5
-- `ServiceLocatorInterface`: -6
-- `ObjectFactory`: -6
-- `ObjectStore`: -8
-- `ConsumerInterface`: -9
-
-[Full results of the vote](https://github.com/container-interop/container-interop/wiki/%231-interface-name:-Vote)
-
-The complete discussion can be read in [the issue #1](https://github.com/container-interop/container-interop/issues/1).
-
-## Interface methods
-
-The choice of which methods the interface would contain was made after a statistical analysis of existing containers.
-The results of this analysis are available [in this document](https://gist.github.com/mnapoli/6159681).
-
-The summary of the analysis showed that:
-
-- all containers offer a method to get an entry by its id
-- a large majority name such method `get()`
-- for all containers, the `get()` method has 1 mandatory parameter of type string
-- some containers have an optional additional argument for `get()`, but it doesn't have the same purpose between containers
-- a large majority of the containers offer a method to test if it can return an entry by its id
-- a majority name such method `has()`
-- for all containers offering `has()`, the method has exactly 1 parameter of type string
-- a large majority of the containers throw an exception rather than returning null when an entry is not found in `get()`
-- a large majority of the containers don't implement `ArrayAccess`
-
-The question of whether to include methods to define entries has been discussed in
-[issue #1](https://github.com/container-interop/container-interop/issues/1).
-It has been judged that such methods do not belong in the interface described here because it is out of its scope
-(see the "Goal" section).
-
-As a result, the `ContainerInterface` contains two methods:
-
-- `get()`, returning anything, with one mandatory string parameter. Should throw an exception if the entry is not found.
-- `has()`, returning a boolean, with one mandatory string parameter.
-
-### Number of parameters in `get()` method
-
-While `ContainerInterface` only defines one mandatory parameter in `get()`, it is not incompatible with
-existing containers that have additional optional parameters. PHP allows an implementation to offer more parameters
-as long as they are optional, because the implementation *does* satisfy the interface.
-
-This issue has been discussed in [issue #6](https://github.com/container-interop/container-interop/issues/6).
-
-### Type of the `$id` parameter
-
-The type of the `$id` parameter in `get()` and `has()` has been discussed in
-[issue #6](https://github.com/container-interop/container-interop/issues/6).
-While `string` is used in all the containers that were analyzed, it was suggested that allowing
-anything (such as objects) could allow containers to offer a more advanced query API.
-
-An example given was to use the container as an object builder. The `$id` parameter would then be an
-object that would describe how to create an instance.
-
-The conclusion of the discussion was that this was beyond the scope of getting entries from a container without
-knowing how the container provided them, and it was more fit for a factory.
-
-## Contributors
-
-Are listed here all people that contributed in the discussions or votes, by alphabetical order:
-
-- [Amy Stephen](https://github.com/AmyStephen)
-- [David Négrier](https://github.com/moufmouf)
-- [Don Gilbert](https://github.com/dongilbert)
-- [Jason Judge](https://github.com/judgej)
-- [Jeremy Lindblom](https://github.com/jeremeamia)
-- [Marco Pivetta](https://github.com/Ocramius)
-- [Matthieu Napoli](https://github.com/mnapoli)
-- [Paul M. Jones](https://github.com/pmjones)
-- [Stephan Hochdörfer](https://github.com/shochdoerfer)
-- [Taylor Otwell](https://github.com/taylorotwell)
-
-## Relevant links
-
-- [`ContainerInterface.php`](https://github.com/container-interop/container-interop/blob/master/src/Interop/Container/ContainerInterface.php)
-- [List of all issues](https://github.com/container-interop/container-interop/issues?labels=ContainerInterface&milestone=&page=1&state=closed)
-- [Vote for the interface name](https://github.com/container-interop/container-interop/wiki/%231-interface-name:-Vote)
diff --git a/vendor/container-interop/container-interop/docs/ContainerInterface.md b/vendor/container-interop/container-interop/docs/ContainerInterface.md
deleted file mode 100644
index bda973d6fce146745741f07beb07b40ba4b88076..0000000000000000000000000000000000000000
--- a/vendor/container-interop/container-interop/docs/ContainerInterface.md
+++ /dev/null
@@ -1,158 +0,0 @@
-Container interface
-===================
-
-This document describes a common interface for dependency injection containers.
-
-The goal set by `ContainerInterface` is to standardize how frameworks and libraries make use of a
-container to obtain objects and parameters (called *entries* in the rest of this document).
-
-The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD",
-"SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be
-interpreted as described in [RFC 2119][].
-
-The word `implementor` in this document is to be interpreted as someone
-implementing the `ContainerInterface` in a dependency injection-related library or framework.
-Users of dependency injections containers (DIC) are referred to as `user`.
-
-[RFC 2119]: http://tools.ietf.org/html/rfc2119
-
-1. Specification
------------------
-
-### 1.1 Basics
-
-- The `Interop\Container\ContainerInterface` exposes two methods : `get` and `has`.
-
-- `get` takes one mandatory parameter: an entry identifier. It MUST be a string.
-  A call to `get` can return anything (a *mixed* value), or throws an exception if the identifier
-  is not known to the container. Two successive calls to `get` with the same
-  identifier SHOULD return the same value. However, depending on the `implementor`
-  design and/or `user` configuration, different values might be returned, so
-  `user` SHOULD NOT rely on getting the same value on 2 successive calls.
-  While `ContainerInterface` only defines one mandatory parameter in `get()`, implementations
-  MAY accept additional optional parameters.
-
-- `has` takes one unique parameter: an entry identifier. It MUST return `true`
-  if an entry identifier is known to the container and `false` if it is not.
-  `has($id)` returning true does not mean that `get($id)` will not throw an exception.
-  It does however mean that `get($id)` will not throw a `NotFoundException`.
-
-### 1.2 Exceptions
-
-Exceptions directly thrown by the container MUST implement the
-[`Interop\Container\Exception\ContainerException`](../src/Interop/Container/Exception/ContainerException.php).
-
-A call to the `get` method with a non-existing id SHOULD throw a
-[`Interop\Container\Exception\NotFoundException`](../src/Interop/Container/Exception/NotFoundException.php).
-
-### 1.3 Additional features
-
-This section describes additional features that MAY be added to a container. Containers are not
-required to implement these features to respect the ContainerInterface.
-
-#### 1.3.1 Delegate lookup feature
-
-The goal of the *delegate lookup* feature is to allow several containers to share entries.
-Containers implementing this feature can perform dependency lookups in other containers.
-
-Containers implementing this feature will offer a greater lever of interoperability
-with other containers. Implementation of this feature is therefore RECOMMENDED.
-
-A container implementing this feature:
-
-- MUST implement the `ContainerInterface`
-- MUST provide a way to register a delegate container (using a constructor parameter, or a setter,
-  or any possible way). The delegate container MUST implement the `ContainerInterface`.
-
-When a container is configured to use a delegate container for dependencies:
-
-- Calls to the `get` method should only return an entry if the entry is part of the container.
-  If the entry is not part of the container, an exception should be thrown
-  (as requested by the `ContainerInterface`).
-- Calls to the `has` method should only return `true` if the entry is part of the container.
-  If the entry is not part of the container, `false` should be returned.
-- If the fetched entry has dependencies, **instead** of performing
-  the dependency lookup in the container, the lookup is performed on the *delegate container*.
-
-Important! By default, the lookup SHOULD be performed on the delegate container **only**, not on the container itself.
-
-It is however allowed for containers to provide exception cases for special entries, and a way to lookup
-into the same container (or another container) instead of the delegate container.
-
-2. Package
-----------
-
-The interfaces and classes described as well as relevant exception are provided as part of the
-[container-interop/container-interop](https://packagist.org/packages/container-interop/container-interop) package.
-
-3. `Interop\Container\ContainerInterface`
------------------------------------------
-
-```php
-<?php
-namespace Interop\Container;
-
-use Interop\Container\Exception\ContainerException;
-use Interop\Container\Exception\NotFoundException;
-
-/**
- * Describes the interface of a container that exposes methods to read its entries.
- */
-interface ContainerInterface
-{
-    /**
-     * Finds an entry of the container by its identifier and returns it.
-     *
-     * @param string $id Identifier of the entry to look for.
-     *
-     * @throws NotFoundException  No entry was found for this identifier.
-     * @throws ContainerException Error while retrieving the entry.
-     *
-     * @return mixed Entry.
-     */
-    public function get($id);
-
-    /**
-     * Returns true if the container can return an entry for the given identifier.
-     * Returns false otherwise.
-     *
-     * `has($id)` returning true does not mean that `get($id)` will not throw an exception.
-     * It does however mean that `get($id)` will not throw a `NotFoundException`.
-     *
-     * @param string $id Identifier of the entry to look for.
-     *
-     * @return boolean
-     */
-    public function has($id);
-}
-```
-
-4. `Interop\Container\Exception\ContainerException`
----------------------------------------------------
-
-```php
-<?php
-namespace Interop\Container\Exception;
-
-/**
- * Base interface representing a generic exception in a container.
- */
-interface ContainerException
-{
-}
-```
-
-5. `Interop\Container\Exception\NotFoundException`
----------------------------------------------------
-
-```php
-<?php
-namespace Interop\Container\Exception;
-
-/**
- * No entry was found in the container.
- */
-interface NotFoundException extends ContainerException
-{
-}
-```
diff --git a/vendor/container-interop/container-interop/docs/Delegate-lookup-meta.md b/vendor/container-interop/container-interop/docs/Delegate-lookup-meta.md
deleted file mode 100644
index 6048b73e290e31e5e9ce49a82f9b9c306944a85d..0000000000000000000000000000000000000000
--- a/vendor/container-interop/container-interop/docs/Delegate-lookup-meta.md
+++ /dev/null
@@ -1,259 +0,0 @@
-Delegate lookup feature Meta Document
-=====================================
-
-1. Summary
-----------
-
-This document describes the *delegate lookup feature*.
-Containers are not required to implement this feature to respect the `ContainerInterface`.
-However, containers implementing this feature will offer a greater lever of interoperability
-with other containers, allowing multiple containers to share entries in the same application.
-Implementation of this feature is therefore recommanded.
-
-2. Why Bother?
---------------
-
-The [`ContainerInterface`](../src/Interop/Container/ContainerInterface.php) ([meta doc](ContainerInterface.md))
-standardizes how frameworks and libraries make use of a container to obtain objects and parameters.
-
-By standardizing such a behavior, frameworks and libraries relying on the `ContainerInterface`
-could work with any compatible container.
-That would allow end users to choose their own container based on their own preferences.
-
-The `ContainerInterface` is also enough if we want to have several containers side-by-side in the same
-application. For instance, this is what the [CompositeContainer](https://github.com/jeremeamia/acclimate-container/blob/master/src/CompositeContainer.php) 
-class of [Acclimate](https://github.com/jeremeamia/acclimate-container) is designed for:
-
-![Side by side containers](images/side_by_side_containers.png)
-
-However, an instance in container 1 cannot reference an instance in container 2.
-
-It would be better if an instance of container 1 could reference an instance in container 2,
-and the opposite should be true. 
-
-![Interoperating containers](images/interoperating_containers.png)
-
-In the sample above, entry 1 in container 1 is referencing entry 3 in container 2.
-
-3. Scope
---------
-
-### 3.1 Goals
-
-The goal of the *delegate lookup* feature is to allow several containers to share entries.
-
-4. Approaches
--------------
-
-### 4.1 Chosen Approach
-
-Containers implementing this feature can perform dependency lookups in other containers.
-
-A container implementing this feature:
-
-- must implement the `ContainerInterface`
-- must provide a way to register a *delegate container* (using a constructor parameter, or a setter, or any
-possible way). The *delegate container* must implement the `ContainerInterface`.
-
-When a *delegate container* is configured on a container:
-
-- Calls to the `get` method should only return an entry if the entry is part of the container.
-If the entry is not part of the container, an exception should be thrown (as required in the `ContainerInterface`).
-- Calls to the `has` method should only return *true* if the entry is part of the container.
-If the entry is not part of the container, *false* should be returned.
- - Finally, the important part: if the entry we are fetching has dependencies,
-**instead** of perfoming the dependency lookup in the container, the lookup is performed on the *delegate container*.
-
-Important! By default, the lookup should be performed on the delegate container **only**, not on the container itself.
-
-It is however allowed for containers to provide exception cases for special entries, and a way to lookup into 
-the same container (or another container) instead of the delegate container.
-
-### 4.2 Typical usage
-
-The *delegate container* will usually be a composite container. A composite container is a container that
-contains several other containers. When performing a lookup on a composite container, the inner containers are 
-queried until one container returns an entry.
-An inner container implementing the *delegate lookup feature* will return entries it contains, but if these
-entries have dependencies, the dependencies lookup calls will be performed on the composite container, giving
-a chance to all containers to answer.
-
-Interestingly enough, the order in which containers are added in the composite container matters. Indeed,
-the first containers to be added in the composite container can "override" the entries of containers with
-lower priority.
-
-![Containers priority](images/priority.png)
-
-In the example above, "container 2" contains a controller "myController" and the controller is referencing an 
-"entityManager" entry. "Container 1" contains also an entry named "entityManager".
-Without the *delegate lookup* feature, when requesting the "myController" instance to container 2, it would take 
-in charge the instanciation of both entries.
-
-However, using the *delegate lookup* feature, here is what happens when we ask the composite container for the 
-"myController" instance:
-
-- The composite container asks container 1 if if contains the "myController" instance. The answer is no.
-- The composite container asks container 2 if if contains the "myController" instance. The answer is yes.
-- The composite container performs a `get` call on container 2 for the "myController" instance.
-- Container 2 sees that "myController" has a dependency on "entityManager".
-- Container 2 delegates the lookup of "entityManager" to the composite container.
-- The composite container asks container 1 if if contains the "entityManager" instance. The answer is yes.
-- The composite container performs a `get` call on container 1 for the "entityManager" instance.
-
-In the end, we get a controller instanciated by container 2 that references an entityManager instanciated
-by container 1.
-
-### 4.3 Alternative: the fallback strategy
-
-The first proposed approach we tried was to perform all the lookups in the "local" container,
-and if a lookup fails in the container, to use the delegate container. In this scenario, the
-delegate container is used in "fallback" mode.
-
-This strategy has been described in @moufmouf blog post: http://mouf-php.com/container-interop-whats-next (solution 1).
-It was also discussed [here](https://github.com/container-interop/container-interop/pull/8#issuecomment-33570697) and
-[here](https://github.com/container-interop/container-interop/pull/20#issuecomment-56599631).
-
-Problems with this strategy:
-
-- Heavy problem regarding infinite loops
-- Unable to overload a container entry with the delegate container entry
-
-### 4.4 Alternative: force implementing an interface
-
-The first proposed approach was to develop a `ParentAwareContainerInterface` interface.
-It was proposed here: https://github.com/container-interop/container-interop/pull/8
-
-The interface would have had the behaviour of the delegate lookup feature but would have forced the addition of
-a `setParentContainter` method:
-
-```php
-interface ParentAwareContainerInterface extends ReadableContainerInterface {
-    /**
-     * Sets the parent container associated to that container. This container will call
-     * the parent container to fetch dependencies.
-     *
-     * @param ContainerInterface $container
-     */
-    public function setParentContainer(ContainerInterface $container);
-}
-```
-
-The interface idea was first questioned by @Ocramius [here](https://github.com/container-interop/container-interop/pull/8#issuecomment-51721777).
-@Ocramius expressed the idea that an interface should not contain setters, otherwise, it is forcing implementation
-details on the class implementing the interface. 
-Then @mnapoli made a proposal for a "convention" [here](https://github.com/container-interop/container-interop/pull/8#issuecomment-51841079),
-this idea was further discussed until all participants in the discussion agreed to remove the interface idea
-and replace it with a "standard" feature.
-
-**Pros:**
-
-If we had had an interface, we could have delegated the registration of the delegate/composite container to the
-the delegate/composite container itself.
-For instance:
-
-```php
-$containerA = new ContainerA();
-$containerB = new ContainerB();
-
-$compositeContainer = new CompositeContainer([$containerA, $containerB]);
-
-// The call to 'setParentContainer' is delegated to the CompositeContainer
-// It is not the responsibility of the user anymore.
-class CompositeContainer {
-	...
-	
-	public function __construct($containers) {
-		foreach ($containers as $container) {
-			if ($container instanceof ParentAwareContainerInterface) {
-				$container->setParentContainer($this);
-			}
-		}
-		...
-	}
-}
-
-``` 
-
-**Cons:**
-
-Cons have been extensively discussed [here](https://github.com/container-interop/container-interop/pull/8#issuecomment-51721777).
-Basically, forcing a setter into an interface is a bad idea. Setters are similar to constructor arguments,
-and it's a bad idea to standardize a constructor: how the delegate container is configured into a container is an implementation detail. This outweights the benefits of the interface.
-
-### 4.4 Alternative: no exception case for delegate lookups
-
-Originally, the proposed wording for delegate lookup calls was:
-
-> Important! The lookup MUST be performed on the delegate container **only**, not on the container itself.
-
-This was later replaced by:
-
-> Important! By default, the lookup SHOULD be performed on the delegate container **only**, not on the container itself.
->
-> It is however allowed for containers to provide exception cases for special entries, and a way to lookup 
-> into the same container (or another container) instead of the delegate container.
-
-Exception cases have been allowed to avoid breaking dependencies with some services that must be provided
-by the container (on @njasm proposal). This was proposed here: https://github.com/container-interop/container-interop/pull/20#issuecomment-56597235
-
-### 4.5 Alternative: having one of the containers act as the composite container
-
-In real-life scenarios, we usually have a big framework (Symfony 2, Zend Framework 2, etc...) and we want to
-add another DI container to this container. Most of the time, the "big" framework will be responsible for
-creating the controller's instances, using it's own DI container. Until *container-interop* is fully adopted,
-the "big" framework will not be aware of the existence of a composite container that it should use instead
-of its own container.
-
-For this real-life use cases, @mnapoli and @moufmouf proposed to extend the "big" framework's DI container
-to make it act as a composite container.
-
-This has been discussed [here](https://github.com/container-interop/container-interop/pull/8#issuecomment-40367194) 
-and [here](http://mouf-php.com/container-interop-whats-next#solution4).
-
-This was implemented in Symfony 2 using:
-
-- [interop.symfony.di](https://github.com/thecodingmachine/interop.symfony.di/tree/v0.1.0)
-- [framework interop](https://github.com/mnapoli/framework-interop/)
-
-This was implemented in Silex using:
-
-- [interop.silex.di](https://github.com/thecodingmachine/interop.silex.di)
-
-Having a container act as the composite container is not part of the delegate lookup standard because it is
-simply a temporary design pattern used to make existing frameworks that do not support yet ContainerInterop
-play nice with other DI containers.
-
-
-5. Implementations
-------------------
-
-The following projects already implement the delegate lookup feature:
-
-- [Mouf](http://mouf-php.com), through the [`setDelegateLookupContainer` method](https://github.com/thecodingmachine/mouf/blob/2.0/src/Mouf/MoufManager.php#L2120)
-- [PHP-DI](http://php-di.org/), through the [`$wrapperContainer` parameter of the constructor](https://github.com/mnapoli/PHP-DI/blob/master/src/DI/Container.php#L72)
-- [pimple-interop](https://github.com/moufmouf/pimple-interop), through the [`$container` parameter of the constructor](https://github.com/moufmouf/pimple-interop/blob/master/src/Interop/Container/Pimple/PimpleInterop.php#L62)
-
-6. People
----------
-
-Are listed here all people that contributed in the discussions, by alphabetical order:
-
-- [Alexandru Pătrănescu](https://github.com/drealecs)
-- [Ben Peachey](https://github.com/potherca)
-- [David Négrier](https://github.com/moufmouf)
-- [Jeremy Lindblom](https://github.com/jeremeamia)
-- [Marco Pivetta](https://github.com/Ocramius)
-- [Matthieu Napoli](https://github.com/mnapoli)
-- [Nelson J Morais](https://github.com/njasm)
-- [Phil Sturgeon](https://github.com/philsturgeon)
-- [Stephan Hochdörfer](https://github.com/shochdoerfer)
-
-7. Relevant Links
------------------
-
-_**Note:** Order descending chronologically._
-
-- [Pull request on the delegate lookup feature](https://github.com/container-interop/container-interop/pull/20)
-- [Pull request on the interface idea](https://github.com/container-interop/container-interop/pull/8)
-- [Original article exposing the delegate lookup idea along many others](http://mouf-php.com/container-interop-whats-next)
-
diff --git a/vendor/container-interop/container-interop/docs/Delegate-lookup.md b/vendor/container-interop/container-interop/docs/Delegate-lookup.md
deleted file mode 100644
index f64a8f785a84d2573ebc23a137f92360a07098a2..0000000000000000000000000000000000000000
--- a/vendor/container-interop/container-interop/docs/Delegate-lookup.md
+++ /dev/null
@@ -1,60 +0,0 @@
-Delegate lookup feature
-=======================
-
-This document describes a standard for dependency injection containers.
-
-The goal set by the *delegate lookup* feature is to allow several containers to share entries.
-Containers implementing this feature can perform dependency lookups in other containers.
-
-Containers implementing this feature will offer a greater lever of interoperability
-with other containers. Implementation of this feature is therefore RECOMMENDED.
-
-The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD",
-"SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be
-interpreted as described in [RFC 2119][].
-
-The word `implementor` in this document is to be interpreted as someone
-implementing the delegate lookup feature in a dependency injection-related library or framework.
-Users of dependency injections containers (DIC) are referred to as `user`.
-
-[RFC 2119]: http://tools.ietf.org/html/rfc2119
-
-1. Vocabulary
--------------
-
-In a dependency injection container, the container is used to fetch entries.
-Entries can have dependencies on other entries. Usually, these other entries are fetched by the container.
-
-The *delegate lookup* feature is the ability for a container to fetch dependencies in
-another container. In the rest of the document, the word "container" will reference the container
-implemented by the implementor. The word "delegate container" will reference the container we are
-fetching the dependencies from.
-
-2. Specification
-----------------
-
-A container implementing the *delegate lookup* feature:
-
-- MUST implement the [`ContainerInterface`](ContainerInterface.md)
-- MUST provide a way to register a delegate container (using a constructor parameter, or a setter,
-  or any possible way). The delegate container MUST implement the [`ContainerInterface`](ContainerInterface.md).
-
-When a container is configured to use a delegate container for dependencies:
-
-- Calls to the `get` method should only return an entry if the entry is part of the container.
-  If the entry is not part of the container, an exception should be thrown
-  (as requested by the [`ContainerInterface`](ContainerInterface.md)).
-- Calls to the `has` method should only return `true` if the entry is part of the container.
-  If the entry is not part of the container, `false` should be returned.
-- If the fetched entry has dependencies, **instead** of performing
-  the dependency lookup in the container, the lookup is performed on the *delegate container*.
-
-Important: By default, the dependency lookups SHOULD be performed on the delegate container **only**, not on the container itself.
-
-It is however allowed for containers to provide exception cases for special entries, and a way to lookup
-into the same container (or another container) instead of the delegate container.
-
-3. Package / Interface
-----------------------
-
-This feature is not tied to any code, interface or package.
diff --git a/vendor/container-interop/container-interop/docs/images/interoperating_containers.png b/vendor/container-interop/container-interop/docs/images/interoperating_containers.png
deleted file mode 100644
index 1d3fdd0ddbea28d77c08cfb65834ec11357be5fb..0000000000000000000000000000000000000000
Binary files a/vendor/container-interop/container-interop/docs/images/interoperating_containers.png and /dev/null differ
diff --git a/vendor/container-interop/container-interop/docs/images/priority.png b/vendor/container-interop/container-interop/docs/images/priority.png
deleted file mode 100644
index d02cb7d1f1ed29c6fa87a269cdd8955e0e907a4c..0000000000000000000000000000000000000000
Binary files a/vendor/container-interop/container-interop/docs/images/priority.png and /dev/null differ
diff --git a/vendor/container-interop/container-interop/docs/images/side_by_side_containers.png b/vendor/container-interop/container-interop/docs/images/side_by_side_containers.png
deleted file mode 100644
index 87884bc2927069abb7f66dfa3e5e71e9c95865a9..0000000000000000000000000000000000000000
Binary files a/vendor/container-interop/container-interop/docs/images/side_by_side_containers.png and /dev/null differ
diff --git a/vendor/container-interop/container-interop/src/Interop/Container/ContainerInterface.php b/vendor/container-interop/container-interop/src/Interop/Container/ContainerInterface.php
deleted file mode 100644
index a75468f6a43565a838e51f945605af815a9f1fa6..0000000000000000000000000000000000000000
--- a/vendor/container-interop/container-interop/src/Interop/Container/ContainerInterface.php
+++ /dev/null
@@ -1,15 +0,0 @@
-<?php
-/**
- * @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
- */
-
-namespace Interop\Container;
-
-use Psr\Container\ContainerInterface as PsrContainerInterface;
-
-/**
- * Describes the interface of a container that exposes methods to read its entries.
- */
-interface ContainerInterface extends PsrContainerInterface
-{
-}
diff --git a/vendor/container-interop/container-interop/src/Interop/Container/Exception/ContainerException.php b/vendor/container-interop/container-interop/src/Interop/Container/Exception/ContainerException.php
deleted file mode 100644
index 3964061a2478a6cb484e7e3a5d396238070bb184..0000000000000000000000000000000000000000
--- a/vendor/container-interop/container-interop/src/Interop/Container/Exception/ContainerException.php
+++ /dev/null
@@ -1,15 +0,0 @@
-<?php
-/**
- * @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
- */
-
-namespace Interop\Container\Exception;
-
-use Psr\Container\ContainerExceptionInterface as PsrContainerException;
-
-/**
- * Base interface representing a generic exception in a container.
- */
-interface ContainerException extends PsrContainerException
-{
-}
diff --git a/vendor/container-interop/container-interop/src/Interop/Container/Exception/NotFoundException.php b/vendor/container-interop/container-interop/src/Interop/Container/Exception/NotFoundException.php
deleted file mode 100644
index 031b3ab4e3496d5d2db4530d67b620ba13154ece..0000000000000000000000000000000000000000
--- a/vendor/container-interop/container-interop/src/Interop/Container/Exception/NotFoundException.php
+++ /dev/null
@@ -1,15 +0,0 @@
-<?php
-/**
- * @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
- */
-
-namespace Interop\Container\Exception;
-
-use Psr\Container\NotFoundExceptionInterface as PsrNotFoundException;
-
-/**
- * No entry was found in the container.
- */
-interface NotFoundException extends ContainerException, PsrNotFoundException
-{
-}
diff --git a/vendor/doctrine/instantiator/.doctrine-project.json b/vendor/doctrine/instantiator/.doctrine-project.json
new file mode 100644
index 0000000000000000000000000000000000000000..eb4f4555e69dcda9e1dc197507deb9305a18930d
--- /dev/null
+++ b/vendor/doctrine/instantiator/.doctrine-project.json
@@ -0,0 +1,41 @@
+{
+    "active": true,
+    "name": "Instantiator",
+    "slug": "instantiator",
+    "docsSlug": "doctrine-instantiator",
+    "codePath": "/src",
+    "versions": [
+        {
+            "name": "1.4",
+            "branchName": "master",
+            "slug": "latest",
+            "upcoming": true
+        },
+        {
+            "name": "1.3",
+            "branchName": "1.3.x",
+            "slug": "1.3",
+            "aliases": [
+                "current",
+                "stable"
+            ],
+            "maintained": true,
+            "current": true
+        },
+        {
+            "name": "1.2",
+            "branchName": "1.2.x",
+            "slug": "1.2"
+        },
+        {
+            "name": "1.1",
+            "branchName": "1.1.x",
+            "slug": "1.1"
+        },
+        {
+            "name": "1.0",
+            "branchName": "1.0.x",
+            "slug": "1.0"
+        }
+    ]
+}
diff --git a/vendor/doctrine/instantiator/.github/FUNDING.yml b/vendor/doctrine/instantiator/.github/FUNDING.yml
new file mode 100644
index 0000000000000000000000000000000000000000..9a35064fe5681bfb160cdbcd5975f705fe611136
--- /dev/null
+++ b/vendor/doctrine/instantiator/.github/FUNDING.yml
@@ -0,0 +1,3 @@
+patreon: phpdoctrine
+tidelift: packagist/doctrine%2Finstantiator
+custom: https://www.doctrine-project.org/sponsorship.html
diff --git a/vendor/doctrine/instantiator/.github/workflows/coding-standards.yml b/vendor/doctrine/instantiator/.github/workflows/coding-standards.yml
new file mode 100644
index 0000000000000000000000000000000000000000..92981b1ed0bb3dbdf53386c7bdc3252c7b2d8968
--- /dev/null
+++ b/vendor/doctrine/instantiator/.github/workflows/coding-standards.yml
@@ -0,0 +1,48 @@
+
+name: "Coding Standards"
+
+on:
+  pull_request:
+    branches:
+      - "*.x"
+  push:
+    branches:
+      - "*.x"
+
+env:
+  COMPOSER_ROOT_VERSION: "1.4"
+
+jobs:
+  coding-standards:
+    name: "Coding Standards"
+    runs-on: "ubuntu-20.04"
+
+    strategy:
+      matrix:
+        php-version:
+          - "7.4"
+
+    steps:
+      - name: "Checkout"
+        uses: "actions/checkout@v2"
+
+      - name: "Install PHP"
+        uses: "shivammathur/setup-php@v2"
+        with:
+          coverage: "none"
+          php-version: "${{ matrix.php-version }}"
+          tools: "cs2pr"
+
+      - name: "Cache dependencies installed with Composer"
+        uses: "actions/cache@v2"
+        with:
+          path: "~/.composer/cache"
+          key: "php-${{ matrix.php-version }}-composer-locked-${{ hashFiles('composer.lock') }}"
+          restore-keys: "php-${{ matrix.php-version }}-composer-locked-"
+
+      - name: "Install dependencies with Composer"
+        run: "composer install --no-interaction --no-progress"
+
+      # https://github.com/doctrine/.github/issues/3
+      - name: "Run PHP_CodeSniffer"
+        run: "vendor/bin/phpcs -q --no-colors --report=checkstyle | cs2pr"
diff --git a/vendor/doctrine/instantiator/.github/workflows/continuous-integration.yml b/vendor/doctrine/instantiator/.github/workflows/continuous-integration.yml
new file mode 100644
index 0000000000000000000000000000000000000000..493374f4fe88dfba08105fd3451033e1442f155c
--- /dev/null
+++ b/vendor/doctrine/instantiator/.github/workflows/continuous-integration.yml
@@ -0,0 +1,91 @@
+
+name: "Continuous Integration"
+
+on:
+  pull_request:
+    branches:
+      - "*.x"
+  push:
+    branches:
+      - "*.x"
+
+env:
+  fail-fast: true
+  COMPOSER_ROOT_VERSION: "1.4"
+
+jobs:
+  phpunit:
+    name: "PHPUnit with SQLite"
+    runs-on: "ubuntu-20.04"
+
+    strategy:
+      matrix:
+        php-version:
+          - "7.1"
+          - "7.2"
+          - "7.3"
+          - "7.4"
+          - "8.0"
+
+    steps:
+      - name: "Checkout"
+        uses: "actions/checkout@v2"
+        with:
+          fetch-depth: 2
+
+      - name: "Install PHP with XDebug"
+        uses: "shivammathur/setup-php@v2"
+        if: "${{ matrix.php-version == '7.1' }}"
+        with:
+          php-version: "${{ matrix.php-version }}"
+          coverage: "xdebug"
+          ini-values: "zend.assertions=1"
+
+      - name: "Install PHP with PCOV"
+        uses: "shivammathur/setup-php@v2"
+        if: "${{ matrix.php-version != '7.1' }}"
+        with:
+          php-version: "${{ matrix.php-version }}"
+          coverage: "pcov"
+          ini-values: "zend.assertions=1"
+
+      - name: "Cache dependencies installed with composer"
+        uses: "actions/cache@v2"
+        with:
+          path: "~/.composer/cache"
+          key: "php-${{ matrix.php-version }}-composer-locked-${{ hashFiles('composer.lock') }}"
+          restore-keys: "php-${{ matrix.php-version }}-composer-locked-"
+
+      - name: "Install dependencies with composer"
+        run: "composer update --no-interaction --no-progress"
+
+      - name: "Run PHPUnit"
+        run: "vendor/bin/phpunit --coverage-clover=coverage.xml"
+
+      - name: "Upload coverage file"
+        uses: "actions/upload-artifact@v2"
+        with:
+          name: "phpunit-${{ matrix.php-version }}.coverage"
+          path: "coverage.xml"
+
+  upload_coverage:
+    name: "Upload coverage to Codecov"
+    runs-on: "ubuntu-20.04"
+    needs:
+      - "phpunit"
+
+    steps:
+      - name: "Checkout"
+        uses: "actions/checkout@v2"
+        with:
+          fetch-depth: 2
+
+      - name: "Download coverage files"
+        uses: "actions/download-artifact@v2"
+        with:
+          path: "reports"
+
+      - name: "Upload to Codecov"
+        uses: "codecov/codecov-action@v1"
+        with:
+          directory: reports
diff --git a/vendor/doctrine/instantiator/.github/workflows/phpbench.yml b/vendor/doctrine/instantiator/.github/workflows/phpbench.yml
new file mode 100644
index 0000000000000000000000000000000000000000..9d131e7ff39de773f528b99f436001a9abffce80
--- /dev/null
+++ b/vendor/doctrine/instantiator/.github/workflows/phpbench.yml
@@ -0,0 +1,50 @@
+
+name: "Performance benchmark"
+
+on:
+  pull_request:
+    branches:
+      - "*.x"
+  push:
+    branches:
+      - "*.x"
+
+env:
+  fail-fast: true
+  COMPOSER_ROOT_VERSION: "1.4"
+
+jobs:
+  phpbench:
+    name: "PHPBench"
+    runs-on: "ubuntu-20.04"
+
+    strategy:
+      matrix:
+        php-version:
+          - "7.4"
+
+    steps:
+      - name: "Checkout"
+        uses: "actions/checkout@v2"
+        with:
+          fetch-depth: 2
+
+      - name: "Install PHP"
+        uses: "shivammathur/setup-php@v2"
+        with:
+          php-version: "${{ matrix.php-version }}"
+          coverage: "pcov"
+          ini-values: "zend.assertions=1"
+
+      - name: "Cache dependencies installed with composer"
+        uses: "actions/cache@v2"
+        with:
+          path: "~/.composer/cache"
+          key: "php-${{ matrix.php-version }}-composer-locked-${{ hashFiles('composer.lock') }}"
+          restore-keys: "php-${{ matrix.php-version }}-composer-locked-"
+
+      - name: "Install dependencies with composer"
+        run: "composer update --no-interaction --no-progress"
+
+      - name: "Run PHPBench"
+        run: "php ./vendor/bin/phpbench run --iterations=3 --warmup=1 --report=aggregate"
diff --git a/vendor/doctrine/instantiator/.github/workflows/release-on-milestone-closed.yml b/vendor/doctrine/instantiator/.github/workflows/release-on-milestone-closed.yml
new file mode 100644
index 0000000000000000000000000000000000000000..b7a56f717b73e6e01376630d3bf885be1c87fbff
--- /dev/null
+++ b/vendor/doctrine/instantiator/.github/workflows/release-on-milestone-closed.yml
@@ -0,0 +1,45 @@
+name: "Automatic Releases"
+
+on:
+  milestone:
+    types:
+      - "closed"
+
+jobs:
+  release:
+    name: "Git tag, release & create merge-up PR"
+    runs-on: "ubuntu-20.04"
+
+    steps:
+      - name: "Checkout"
+        uses: "actions/checkout@v2"
+
+      - name: "Release"
+        uses: "laminas/automatic-releases@v1"
+        with:
+          command-name: "laminas:automatic-releases:release"
+        env:
+          "GITHUB_TOKEN": ${{ secrets.GITHUB_TOKEN }}
+          "SIGNING_SECRET_KEY": ${{ secrets.SIGNING_SECRET_KEY }}
+          "GIT_AUTHOR_NAME": ${{ secrets.GIT_AUTHOR_NAME }}
+          "GIT_AUTHOR_EMAIL": ${{ secrets.GIT_AUTHOR_EMAIL }}
+
+      - name: "Create Merge-Up Pull Request"
+        uses: "laminas/automatic-releases@v1"
+        with:
+          command-name: "laminas:automatic-releases:create-merge-up-pull-request"
+        env:
+          "GITHUB_TOKEN": ${{ secrets.GITHUB_TOKEN }}
+          "SIGNING_SECRET_KEY": ${{ secrets.SIGNING_SECRET_KEY }}
+          "GIT_AUTHOR_NAME": ${{ secrets.GIT_AUTHOR_NAME }}
+          "GIT_AUTHOR_EMAIL": ${{ secrets.GIT_AUTHOR_EMAIL }}
+
+      - name: "Create new milestones"
+        uses: "laminas/automatic-releases@v1"
+        with:
+          command-name: "laminas:automatic-releases:create-milestones"
+        env:
+          "GITHUB_TOKEN": ${{ secrets.GITHUB_TOKEN }}
+          "SIGNING_SECRET_KEY": ${{ secrets.SIGNING_SECRET_KEY }}
+          "GIT_AUTHOR_NAME": ${{ secrets.GIT_AUTHOR_NAME }}
+          "GIT_AUTHOR_EMAIL": ${{ secrets.GIT_AUTHOR_EMAIL }}
diff --git a/vendor/doctrine/instantiator/.github/workflows/static-analysis.yml b/vendor/doctrine/instantiator/.github/workflows/static-analysis.yml
new file mode 100644
index 0000000000000000000000000000000000000000..4a58318ec3396ad826037e18c5bd65d2f64f9028
--- /dev/null
+++ b/vendor/doctrine/instantiator/.github/workflows/static-analysis.yml
@@ -0,0 +1,47 @@
+
+name: "Static Analysis"
+
+on:
+  pull_request:
+    branches:
+      - "*.x"
+  push:
+    branches:
+      - "*.x"
+
+env:
+  COMPOSER_ROOT_VERSION: "1.4"
+
+jobs:
+  static-analysis-phpstan:
+    name: "Static Analysis with PHPStan"
+    runs-on: "ubuntu-20.04"
+
+    strategy:
+      matrix:
+        php-version:
+          - "7.4"
+
+    steps:
+      - name: "Checkout code"
+        uses: "actions/checkout@v2"
+
+      - name: "Install PHP"
+        uses: "shivammathur/setup-php@v2"
+        with:
+          coverage: "none"
+          php-version: "${{ matrix.php-version }}"
+          tools: "cs2pr"
+
+      - name: "Cache dependencies installed with composer"
+        uses: "actions/cache@v2"
+        with:
+          path: "~/.composer/cache"
+          key: "php-${{ matrix.php-version }}-composer-locked-${{ hashFiles('composer.lock') }}"
+          restore-keys: "php-${{ matrix.php-version }}-composer-locked-"
+
+      - name: "Install dependencies with composer"
+        run: "composer install --no-interaction --no-progress"
+
+      - name: "Run a static analysis with phpstan/phpstan"
+        run: "vendor/bin/phpstan analyse --error-format=checkstyle | cs2pr"
diff --git a/vendor/doctrine/instantiator/CONTRIBUTING.md b/vendor/doctrine/instantiator/CONTRIBUTING.md
new file mode 100644
index 0000000000000000000000000000000000000000..c1a2c42ee016b25e84530a76bccc98d17cc8e6c1
--- /dev/null
+++ b/vendor/doctrine/instantiator/CONTRIBUTING.md
@@ -0,0 +1,35 @@
+# Contributing
+
+ * Follow the [Doctrine Coding Standard](https://github.com/doctrine/coding-standard)
+ * The project will follow strict [object calisthenics](http://www.slideshare.net/guilhermeblanco/object-calisthenics-applied-to-php)
+ * Any contribution must provide tests for additional introduced conditions
+ * Any un-confirmed issue needs a failing test case before being accepted
+ * Pull requests must be sent from a new hotfix/feature branch, not from `master`.
+
+## Installation
+
+To install the project and run the tests, you need to clone it first:
+
+```sh
+$ git clone git://github.com/doctrine/instantiator.git
+```
+
+You will then need to run a composer installation:
+
+```sh
+$ cd Instantiator
+$ curl -s https://getcomposer.org/installer | php
+$ php composer.phar update
+```
+
+## Testing
+
+The PHPUnit version to be used is the one installed as a dev- dependency via composer:
+
+```sh
+$ ./vendor/bin/phpunit
+```
+
+Accepted coverage for new contributions is 80%. Any contribution not satisfying this requirement 
+won't be merged.
+
diff --git a/vendor/doctrine/instantiator/LICENSE b/vendor/doctrine/instantiator/LICENSE
new file mode 100644
index 0000000000000000000000000000000000000000..4d983d1ac70a22beb32a44c8ae52b43f04444f29
--- /dev/null
+++ b/vendor/doctrine/instantiator/LICENSE
@@ -0,0 +1,19 @@
+Copyright (c) 2014 Doctrine Project
+
+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/doctrine/instantiator/README.md b/vendor/doctrine/instantiator/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..4bc02b6550e483ac1ddfcdbc0568600d53091ac1
--- /dev/null
+++ b/vendor/doctrine/instantiator/README.md
@@ -0,0 +1,38 @@
+# Instantiator
+
+This library provides a way of avoiding usage of constructors when instantiating PHP classes.
+
+[![Build Status](https://travis-ci.org/doctrine/instantiator.svg?branch=master)](https://travis-ci.org/doctrine/instantiator)
+[![Code Coverage](https://codecov.io/gh/doctrine/instantiator/branch/master/graph/badge.svg)](https://codecov.io/gh/doctrine/instantiator/branch/master)
+[![Dependency Status](https://www.versioneye.com/package/php--doctrine--instantiator/badge.svg)](https://www.versioneye.com/package/php--doctrine--instantiator)
+
+[![Latest Stable Version](https://poser.pugx.org/doctrine/instantiator/v/stable.png)](https://packagist.org/packages/doctrine/instantiator)
+[![Latest Unstable Version](https://poser.pugx.org/doctrine/instantiator/v/unstable.png)](https://packagist.org/packages/doctrine/instantiator)
+
+## Installation
+
+The suggested installation method is via [composer](https://getcomposer.org/):
+
+```sh
+php composer.phar require "doctrine/instantiator:~1.0.3"
+```
+
+## Usage
+
+The instantiator is able to create new instances of any class without using the constructor or any API of the class
+itself:
+
+```php
+$instantiator = new \Doctrine\Instantiator\Instantiator();
+
+$instance = $instantiator->instantiate(\My\ClassName\Here::class);
+```
+
+## Contributing
+
+Please read the [CONTRIBUTING.md](CONTRIBUTING.md) contents if you wish to help out!
+
+## Credits
+
+This library was migrated from [ocramius/instantiator](https://github.com/Ocramius/Instantiator), which
+has been donated to the doctrine organization, and which is now deprecated in favour of this package.
diff --git a/vendor/doctrine/instantiator/composer.json b/vendor/doctrine/instantiator/composer.json
new file mode 100644
index 0000000000000000000000000000000000000000..1ce347350b2267ceaa9bbafd7852219e67dbf9ad
--- /dev/null
+++ b/vendor/doctrine/instantiator/composer.json
@@ -0,0 +1,42 @@
+{
+    "name":              "doctrine/instantiator",
+    "description":       "A small, lightweight utility to instantiate objects in PHP without invoking their constructors",
+    "type":              "library",
+    "license":           "MIT",
+    "homepage":          "https://www.doctrine-project.org/projects/instantiator.html",
+    "keywords":          [
+        "instantiate",
+        "constructor"
+    ],
+    "authors": [
+        {
+            "name":     "Marco Pivetta",
+            "email":    "ocramius@gmail.com",
+            "homepage": "https://ocramius.github.io/"
+        }
+    ],
+    "require": {
+        "php": "^7.1 || ^8.0"
+    },
+    "require-dev": {
+        "ext-phar":                  "*",
+        "ext-pdo":                   "*",
+        "doctrine/coding-standard":  "^8.0",
+        "phpbench/phpbench":         "^0.13 || 1.0.0-alpha2",
+        "phpstan/phpstan":           "^0.12",
+        "phpstan/phpstan-phpunit":   "^0.12",
+        "phpunit/phpunit":           "^7.0 || ^8.0 || ^9.0"
+    },
+    "autoload": {
+        "psr-4": {
+            "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/"
+        }
+    },
+    "autoload-dev": {
+        "psr-0": {
+            "DoctrineTest\\InstantiatorPerformance\\": "tests",
+            "DoctrineTest\\InstantiatorTest\\": "tests",
+            "DoctrineTest\\InstantiatorTestAsset\\": "tests"
+        }
+    }
+}
diff --git a/vendor/doctrine/instantiator/docs/en/index.rst b/vendor/doctrine/instantiator/docs/en/index.rst
new file mode 100644
index 0000000000000000000000000000000000000000..0c85da0bc996f7d4aba2ce42b43af718d74fbe81
--- /dev/null
+++ b/vendor/doctrine/instantiator/docs/en/index.rst
@@ -0,0 +1,68 @@
+Introduction
+============
+
+This library provides a way of avoiding usage of constructors when instantiating PHP classes.
+
+Installation
+============
+
+The suggested installation method is via `composer`_:
+
+.. code-block:: console
+
+   $ composer require doctrine/instantiator
+
+Usage
+=====
+
+The instantiator is able to create new instances of any class without
+using the constructor or any API of the class itself:
+
+.. code-block:: php
+
+    <?php
+
+    use Doctrine\Instantiator\Instantiator;
+    use App\Entities\User;
+
+    $instantiator = new Instantiator();
+
+    $user = $instantiator->instantiate(User::class);
+
+Contributing
+============
+
+-  Follow the `Doctrine Coding Standard`_
+-  The project will follow strict `object calisthenics`_
+-  Any contribution must provide tests for additional introduced
+   conditions
+-  Any un-confirmed issue needs a failing test case before being
+   accepted
+-  Pull requests must be sent from a new hotfix/feature branch, not from
+   ``master``.
+
+Testing
+=======
+
+The PHPUnit version to be used is the one installed as a dev- dependency
+via composer:
+
+.. code-block:: console
+
+   $ ./vendor/bin/phpunit
+
+Accepted coverage for new contributions is 80%. Any contribution not
+satisfying this requirement won’t be merged.
+
+Credits
+=======
+
+This library was migrated from `ocramius/instantiator`_, which has been
+donated to the doctrine organization, and which is now deprecated in
+favour of this package.
+
+.. _composer: https://getcomposer.org/
+.. _CONTRIBUTING.md: CONTRIBUTING.md
+.. _ocramius/instantiator: https://github.com/Ocramius/Instantiator
+.. _Doctrine Coding Standard: https://github.com/doctrine/coding-standard
+.. _object calisthenics: http://www.slideshare.net/guilhermeblanco/object-calisthenics-applied-to-php
diff --git a/vendor/doctrine/instantiator/docs/en/sidebar.rst b/vendor/doctrine/instantiator/docs/en/sidebar.rst
new file mode 100644
index 0000000000000000000000000000000000000000..0c36479143d1c6a59a0e66da1129afeff4857efd
--- /dev/null
+++ b/vendor/doctrine/instantiator/docs/en/sidebar.rst
@@ -0,0 +1,4 @@
+.. toctree::
+    :depth: 3
+
+    index
diff --git a/vendor/doctrine/instantiator/phpbench.json b/vendor/doctrine/instantiator/phpbench.json
new file mode 100644
index 0000000000000000000000000000000000000000..fce5dd600d00ea9a45179e519d83bef6b59afe55
--- /dev/null
+++ b/vendor/doctrine/instantiator/phpbench.json
@@ -0,0 +1,4 @@
+{
+    "bootstrap": "vendor/autoload.php",
+    "path": "tests/DoctrineTest/InstantiatorPerformance"
+}
diff --git a/vendor/doctrine/instantiator/phpcs.xml.dist b/vendor/doctrine/instantiator/phpcs.xml.dist
new file mode 100644
index 0000000000000000000000000000000000000000..4e08b1680caac19d286dd55b209118f3c0cef877
--- /dev/null
+++ b/vendor/doctrine/instantiator/phpcs.xml.dist
@@ -0,0 +1,50 @@
+<?xml version="1.0"?>
+<ruleset>
+    <arg name="basepath" value="."/>
+    <arg name="extensions" value="php"/>
+    <arg name="parallel" value="80"/>
+    <arg name="cache" value=".phpcs-cache"/>
+    <arg name="colors"/>
+
+    <!-- Ignore warnings, show progress of the run and show sniff names -->
+    <arg value="nps"/>
+
+    <file>src</file>
+    <file>tests</file>
+
+    <rule ref="Doctrine">
+        <exclude name="SlevomatCodingStandard.TypeHints.DeclareStrictTypes"/>
+        <exclude name="SlevomatCodingStandard.TypeHints.TypeHintDeclaration.MissingParameterTypeHint"/>
+        <exclude name="SlevomatCodingStandard.TypeHints.TypeHintDeclaration.MissingReturnTypeHint"/>
+        <exclude name="SlevomatCodingStandard.Exceptions.ReferenceThrowableOnly.ReferencedGeneralException"/>
+    </rule>
+
+    <!-- Disable the rules that will require PHP 7.4 -->
+    <rule ref="SlevomatCodingStandard.TypeHints.PropertyTypeHint">
+        <properties>
+            <property name="enableNativeTypeHint" value="false"/>
+        </properties>
+    </rule>
+
+    <rule ref="SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint">
+        <exclude-pattern>*/src/*</exclude-pattern>
+    </rule>
+
+    <rule ref="SlevomatCodingStandard.TypeHints.ReturnTypeHint.MissingNativeTypeHint">
+        <exclude-pattern>*/src/*</exclude-pattern>
+    </rule>
+
+    <rule ref="SlevomatCodingStandard.Classes.SuperfluousAbstractClassNaming">
+        <exclude-pattern>tests/DoctrineTest/InstantiatorTestAsset/AbstractClassAsset.php</exclude-pattern>
+    </rule>
+
+    <rule ref="SlevomatCodingStandard.Classes.SuperfluousExceptionNaming">
+        <exclude-pattern>src/Doctrine/Instantiator/Exception/UnexpectedValueException.php</exclude-pattern>
+        <exclude-pattern>src/Doctrine/Instantiator/Exception/InvalidArgumentException.php</exclude-pattern>
+    </rule>
+
+    <rule ref="SlevomatCodingStandard.Classes.SuperfluousInterfaceNaming">
+        <exclude-pattern>src/Doctrine/Instantiator/Exception/ExceptionInterface.php</exclude-pattern>
+        <exclude-pattern>src/Doctrine/Instantiator/InstantiatorInterface.php</exclude-pattern>
+    </rule>
+</ruleset>
diff --git a/vendor/doctrine/instantiator/phpstan.neon.dist b/vendor/doctrine/instantiator/phpstan.neon.dist
new file mode 100644
index 0000000000000000000000000000000000000000..60bec6bf46b5cd5cac394842e49e2bcb985c5834
--- /dev/null
+++ b/vendor/doctrine/instantiator/phpstan.neon.dist
@@ -0,0 +1,15 @@
+includes:
+    - vendor/phpstan/phpstan-phpunit/extension.neon
+    - vendor/phpstan/phpstan-phpunit/rules.neon
+
+parameters:
+    level: max
+    paths:
+        - src
+        - tests
+
+    ignoreErrors:
+        # dynamic properties confuse static analysis
+        -
+            message: '#Access to an undefined property object::\$foo\.#'
+            path: '*/tests/DoctrineTest/InstantiatorTest/InstantiatorTest.php'
diff --git a/vendor/doctrine/instantiator/src/Doctrine/Instantiator/Exception/ExceptionInterface.php b/vendor/doctrine/instantiator/src/Doctrine/Instantiator/Exception/ExceptionInterface.php
new file mode 100644
index 0000000000000000000000000000000000000000..e6a5195f21fe7f660d9a40d9d2caf3ef8ac42c0a
--- /dev/null
+++ b/vendor/doctrine/instantiator/src/Doctrine/Instantiator/Exception/ExceptionInterface.php
@@ -0,0 +1,12 @@
+<?php
+
+namespace Doctrine\Instantiator\Exception;
+
+use Throwable;
+
+/**
+ * Base exception marker interface for the instantiator component
+ */
+interface ExceptionInterface extends Throwable
+{
+}
diff --git a/vendor/doctrine/instantiator/src/Doctrine/Instantiator/Exception/InvalidArgumentException.php b/vendor/doctrine/instantiator/src/Doctrine/Instantiator/Exception/InvalidArgumentException.php
new file mode 100644
index 0000000000000000000000000000000000000000..2ded2ecba6330c4b235f24792c29b9ec0ed16e5b
--- /dev/null
+++ b/vendor/doctrine/instantiator/src/Doctrine/Instantiator/Exception/InvalidArgumentException.php
@@ -0,0 +1,41 @@
+<?php
+
+namespace Doctrine\Instantiator\Exception;
+
+use InvalidArgumentException as BaseInvalidArgumentException;
+use ReflectionClass;
+
+use function interface_exists;
+use function sprintf;
+use function trait_exists;
+
+/**
+ * Exception for invalid arguments provided to the instantiator
+ */
+class InvalidArgumentException extends BaseInvalidArgumentException implements ExceptionInterface
+{
+    public static function fromNonExistingClass(string $className): self
+    {
+        if (interface_exists($className)) {
+            return new self(sprintf('The provided type "%s" is an interface, and can not be instantiated', $className));
+        }
+
+        if (trait_exists($className)) {
+            return new self(sprintf('The provided type "%s" is a trait, and can not be instantiated', $className));
+        }
+
+        return new self(sprintf('The provided class "%s" does not exist', $className));
+    }
+
+    /**
+     * @template T of object
+     * @phpstan-param ReflectionClass<T> $reflectionClass
+     */
+    public static function fromAbstractClass(ReflectionClass $reflectionClass): self
+    {
+        return new self(sprintf(
+            'The provided class "%s" is abstract, and can not be instantiated',
+            $reflectionClass->getName()
+        ));
+    }
+}
diff --git a/vendor/doctrine/instantiator/src/Doctrine/Instantiator/Exception/UnexpectedValueException.php b/vendor/doctrine/instantiator/src/Doctrine/Instantiator/Exception/UnexpectedValueException.php
new file mode 100644
index 0000000000000000000000000000000000000000..19842bb673ce85a675725aacdfe1f9c1f1eb96cb
--- /dev/null
+++ b/vendor/doctrine/instantiator/src/Doctrine/Instantiator/Exception/UnexpectedValueException.php
@@ -0,0 +1,57 @@
+<?php
+
+namespace Doctrine\Instantiator\Exception;
+
+use Exception;
+use ReflectionClass;
+use UnexpectedValueException as BaseUnexpectedValueException;
+
+use function sprintf;
+
+/**
+ * Exception for given parameters causing invalid/unexpected state on instantiation
+ */
+class UnexpectedValueException extends BaseUnexpectedValueException implements ExceptionInterface
+{
+    /**
+     * @template T of object
+     * @phpstan-param ReflectionClass<T> $reflectionClass
+     */
+    public static function fromSerializationTriggeredException(
+        ReflectionClass $reflectionClass,
+        Exception $exception
+    ): self {
+        return new self(
+            sprintf(
+                'An exception was raised while trying to instantiate an instance of "%s" via un-serialization',
+                $reflectionClass->getName()
+            ),
+            0,
+            $exception
+        );
+    }
+
+    /**
+     * @template T of object
+     * @phpstan-param ReflectionClass<T> $reflectionClass
+     */
+    public static function fromUncleanUnSerialization(
+        ReflectionClass $reflectionClass,
+        string $errorString,
+        int $errorCode,
+        string $errorFile,
+        int $errorLine
+    ): self {
+        return new self(
+            sprintf(
+                'Could not produce an instance of "%s" via un-serialization, since an error was triggered '
+                . 'in file "%s" at line "%d"',
+                $reflectionClass->getName(),
+                $errorFile,
+                $errorLine
+            ),
+            0,
+            new Exception($errorString, $errorCode)
+        );
+    }
+}
diff --git a/vendor/doctrine/instantiator/src/Doctrine/Instantiator/Instantiator.php b/vendor/doctrine/instantiator/src/Doctrine/Instantiator/Instantiator.php
new file mode 100644
index 0000000000000000000000000000000000000000..ee4803cbb22969c05e09085aaca03a379a701df7
--- /dev/null
+++ b/vendor/doctrine/instantiator/src/Doctrine/Instantiator/Instantiator.php
@@ -0,0 +1,232 @@
+<?php
+
+namespace Doctrine\Instantiator;
+
+use ArrayIterator;
+use Doctrine\Instantiator\Exception\InvalidArgumentException;
+use Doctrine\Instantiator\Exception\UnexpectedValueException;
+use Exception;
+use ReflectionClass;
+use ReflectionException;
+use Serializable;
+
+use function class_exists;
+use function is_subclass_of;
+use function restore_error_handler;
+use function set_error_handler;
+use function sprintf;
+use function strlen;
+use function unserialize;
+
+final class Instantiator implements InstantiatorInterface
+{
+    /**
+     * Markers used internally by PHP to define whether {@see \unserialize} should invoke
+     * the method {@see \Serializable::unserialize()} when dealing with classes implementing
+     * the {@see \Serializable} interface.
+     */
+    public const SERIALIZATION_FORMAT_USE_UNSERIALIZER   = 'C';
+    public const SERIALIZATION_FORMAT_AVOID_UNSERIALIZER = 'O';
+
+    /**
+     * Used to instantiate specific classes, indexed by class name.
+     *
+     * @var callable[]
+     */
+    private static $cachedInstantiators = [];
+
+    /**
+     * Array of objects that can directly be cloned, indexed by class name.
+     *
+     * @var object[]
+     */
+    private static $cachedCloneables = [];
+
+    /**
+     * {@inheritDoc}
+     */
+    public function instantiate($className)
+    {
+        if (isset(self::$cachedCloneables[$className])) {
+            return clone self::$cachedCloneables[$className];
+        }
+
+        if (isset(self::$cachedInstantiators[$className])) {
+            $factory = self::$cachedInstantiators[$className];
+
+            return $factory();
+        }
+
+        return $this->buildAndCacheFromFactory($className);
+    }
+
+    /**
+     * Builds the requested object and caches it in static properties for performance
+     *
+     * @return object
+     *
+     * @template T of object
+     * @phpstan-param class-string<T> $className
+     *
+     * @phpstan-return T
+     */
+    private function buildAndCacheFromFactory(string $className)
+    {
+        $factory  = self::$cachedInstantiators[$className] = $this->buildFactory($className);
+        $instance = $factory();
+
+        if ($this->isSafeToClone(new ReflectionClass($instance))) {
+            self::$cachedCloneables[$className] = clone $instance;
+        }
+
+        return $instance;
+    }
+
+    /**
+     * Builds a callable capable of instantiating the given $className without
+     * invoking its constructor.
+     *
+     * @throws InvalidArgumentException
+     * @throws UnexpectedValueException
+     * @throws ReflectionException
+     *
+     * @template T of object
+     * @phpstan-param class-string<T> $className
+     *
+     * @phpstan-return callable(): T
+     */
+    private function buildFactory(string $className): callable
+    {
+        $reflectionClass = $this->getReflectionClass($className);
+
+        if ($this->isInstantiableViaReflection($reflectionClass)) {
+            return [$reflectionClass, 'newInstanceWithoutConstructor'];
+        }
+
+        $serializedString = sprintf(
+            '%s:%d:"%s":0:{}',
+            is_subclass_of($className, Serializable::class) ? self::SERIALIZATION_FORMAT_USE_UNSERIALIZER : self::SERIALIZATION_FORMAT_AVOID_UNSERIALIZER,
+            strlen($className),
+            $className
+        );
+
+        $this->checkIfUnSerializationIsSupported($reflectionClass, $serializedString);
+
+        return static function () use ($serializedString) {
+            return unserialize($serializedString);
+        };
+    }
+
+    /**
+     * @throws InvalidArgumentException
+     * @throws ReflectionException
+     *
+     * @template T of object
+     * @phpstan-param class-string<T> $className
+     *
+     * @phpstan-return ReflectionClass<T>
+     */
+    private function getReflectionClass(string $className): ReflectionClass
+    {
+        if (! class_exists($className)) {
+            throw InvalidArgumentException::fromNonExistingClass($className);
+        }
+
+        $reflection = new ReflectionClass($className);
+
+        if ($reflection->isAbstract()) {
+            throw InvalidArgumentException::fromAbstractClass($reflection);
+        }
+
+        return $reflection;
+    }
+
+    /**
+     * @throws UnexpectedValueException
+     *
+     * @template T of object
+     * @phpstan-param ReflectionClass<T> $reflectionClass
+     */
+    private function checkIfUnSerializationIsSupported(ReflectionClass $reflectionClass, string $serializedString): void
+    {
+        set_error_handler(static function (int $code, string $message, string $file, int $line) use ($reflectionClass, &$error): bool {
+            $error = UnexpectedValueException::fromUncleanUnSerialization(
+                $reflectionClass,
+                $message,
+                $code,
+                $file,
+                $line
+            );
+
+            return true;
+        });
+
+        try {
+            $this->attemptInstantiationViaUnSerialization($reflectionClass, $serializedString);
+        } finally {
+            restore_error_handler();
+        }
+
+        if ($error) {
+            throw $error;
+        }
+    }
+
+    /**
+     * @throws UnexpectedValueException
+     *
+     * @template T of object
+     * @phpstan-param ReflectionClass<T> $reflectionClass
+     */
+    private function attemptInstantiationViaUnSerialization(ReflectionClass $reflectionClass, string $serializedString): void
+    {
+        try {
+            unserialize($serializedString);
+        } catch (Exception $exception) {
+            throw UnexpectedValueException::fromSerializationTriggeredException($reflectionClass, $exception);
+        }
+    }
+
+    /**
+     * @template T of object
+     * @phpstan-param ReflectionClass<T> $reflectionClass
+     */
+    private function isInstantiableViaReflection(ReflectionClass $reflectionClass): bool
+    {
+        return ! ($this->hasInternalAncestors($reflectionClass) && $reflectionClass->isFinal());
+    }
+
+    /**
+     * Verifies whether the given class is to be considered internal
+     *
+     * @template T of object
+     * @phpstan-param ReflectionClass<T> $reflectionClass
+     */
+    private function hasInternalAncestors(ReflectionClass $reflectionClass): bool
+    {
+        do {
+            if ($reflectionClass->isInternal()) {
+                return true;
+            }
+
+            $reflectionClass = $reflectionClass->getParentClass();
+        } while ($reflectionClass);
+
+        return false;
+    }
+
+    /**
+     * Checks if a class is cloneable
+     *
+     * Classes implementing `__clone` cannot be safely cloned, as that may cause side-effects.
+     *
+     * @template T of object
+     * @phpstan-param ReflectionClass<T> $reflectionClass
+     */
+    private function isSafeToClone(ReflectionClass $reflectionClass): bool
+    {
+        return $reflectionClass->isCloneable()
+            && ! $reflectionClass->hasMethod('__clone')
+            && ! $reflectionClass->isSubclassOf(ArrayIterator::class);
+    }
+}
diff --git a/vendor/doctrine/instantiator/src/Doctrine/Instantiator/InstantiatorInterface.php b/vendor/doctrine/instantiator/src/Doctrine/Instantiator/InstantiatorInterface.php
new file mode 100644
index 0000000000000000000000000000000000000000..3ffff822147426e4033daaab75daf291924d5a12
--- /dev/null
+++ b/vendor/doctrine/instantiator/src/Doctrine/Instantiator/InstantiatorInterface.php
@@ -0,0 +1,23 @@
+<?php
+
+namespace Doctrine\Instantiator;
+
+use Doctrine\Instantiator\Exception\ExceptionInterface;
+
+/**
+ * Instantiator provides utility methods to build objects without invoking their constructors
+ */
+interface InstantiatorInterface
+{
+    /**
+     * @param string $className
+     *
+     * @return object
+     *
+     * @throws ExceptionInterface
+     *
+     * @template T of object
+     * @phpstan-param class-string<T> $className
+     */
+    public function instantiate($className);
+}
diff --git a/vendor/firebase/php-jwt/README.md b/vendor/firebase/php-jwt/README.md
index b1a7a3a206347e07d448d0a0803a984017810cf3..9c8b5455b693cd5fc2f6de43aef3194946a77bd4 100644
--- a/vendor/firebase/php-jwt/README.md
+++ b/vendor/firebase/php-jwt/README.md
@@ -23,7 +23,7 @@ Example
 use \Firebase\JWT\JWT;
 
 $key = "example_key";
-$token = array(
+$payload = array(
     "iss" => "http://example.org",
     "aud" => "http://example.com",
     "iat" => 1356999524,
@@ -36,7 +36,7 @@ $token = array(
  * https://tools.ietf.org/html/draft-ietf-jose-json-web-algorithms-40
  * for a list of spec-compliant algorithms.
  */
-$jwt = JWT::encode($token, $key);
+$jwt = JWT::encode($payload, $key);
 $decoded = JWT::decode($jwt, $key, array('HS256'));
 
 print_r($decoded);
@@ -93,14 +93,14 @@ ehde/zUxo6UvS7UrBQIDAQAB
 -----END PUBLIC KEY-----
 EOD;
 
-$token = array(
+$payload = array(
     "iss" => "example.org",
     "aud" => "example.com",
     "iat" => 1356999524,
     "nbf" => 1357000000
 );
 
-$jwt = JWT::encode($token, $privateKey, 'RS256');
+$jwt = JWT::encode($payload, $privateKey, 'RS256');
 echo "Encode:\n" . print_r($jwt, true) . "\n";
 
 $decoded = JWT::decode($jwt, $publicKey, array('RS256'));
diff --git a/vendor/firebase/php-jwt/composer.json b/vendor/firebase/php-jwt/composer.json
index b76ffd19106ee17df6c69f37ce159e23604a5692..25d1cfa96ad71085e2456d8f22ee38536778bfa5 100644
--- a/vendor/firebase/php-jwt/composer.json
+++ b/vendor/firebase/php-jwt/composer.json
@@ -2,6 +2,10 @@
     "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",
@@ -24,6 +28,6 @@
         }
     },
     "require-dev": {
-        "phpunit/phpunit": " 4.8.35"
+        "phpunit/phpunit": ">=4.8 <=9"
     }
 }
diff --git a/vendor/firebase/php-jwt/src/BeforeValidException.php b/vendor/firebase/php-jwt/src/BeforeValidException.php
index a6ee2f7c69080d86bfcc1b48d0b60311e789a955..fdf82bd94296dcff62000594bb788153e9d5079b 100644
--- a/vendor/firebase/php-jwt/src/BeforeValidException.php
+++ b/vendor/firebase/php-jwt/src/BeforeValidException.php
@@ -3,5 +3,4 @@ namespace Firebase\JWT;
 
 class BeforeValidException extends \UnexpectedValueException
 {
-
 }
diff --git a/vendor/firebase/php-jwt/src/ExpiredException.php b/vendor/firebase/php-jwt/src/ExpiredException.php
index 3597370a6deb890db93532010a6e1ab84dce110c..7f7d056824841fabf8ab9e5ea1a7453d69b75c70 100644
--- a/vendor/firebase/php-jwt/src/ExpiredException.php
+++ b/vendor/firebase/php-jwt/src/ExpiredException.php
@@ -3,5 +3,4 @@ namespace Firebase\JWT;
 
 class ExpiredException extends \UnexpectedValueException
 {
-
 }
diff --git a/vendor/firebase/php-jwt/src/JWK.php b/vendor/firebase/php-jwt/src/JWK.php
new file mode 100644
index 0000000000000000000000000000000000000000..1d273917403bb0a509d821401b49a2c35f8747e0
--- /dev/null
+++ b/vendor/firebase/php-jwt/src/JWK.php
@@ -0,0 +1,171 @@
+<?php
+
+namespace Firebase\JWT;
+
+use DomainException;
+use UnexpectedValueException;
+
+/**
+ * JSON Web Key implementation, based on this spec:
+ * https://tools.ietf.org/html/draft-ietf-jose-json-web-key-41
+ *
+ * PHP version 5
+ *
+ * @category Authentication
+ * @package  Authentication_JWT
+ * @author   Bui Sy Nguyen <nguyenbs@gmail.com>
+ * @license  http://opensource.org/licenses/BSD-3-Clause 3-clause BSD
+ * @link     https://github.com/firebase/php-jwt
+ */
+class JWK
+{
+    /**
+     * Parse a set of JWK keys
+     *
+     * @param array $jwks The JSON Web Key Set as an associative array
+     *
+     * @return array An associative array that represents the set of keys
+     *
+     * @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)
+    {
+        $keys = array();
+
+        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)) {
+                $keys[$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
+     *
+     * @return resource|array An associative array that represents the key
+     *
+     * @throws InvalidArgumentException     Provided JWK is empty
+     * @throws UnexpectedValueException     Provided JWK was invalid
+     * @throws DomainException              OpenSSL failure
+     *
+     * @uses createPemFromModulusAndExponent
+     */
+    private static function parseKey(array $jwk)
+    {
+        if (empty($jwk)) {
+            throw new InvalidArgumentException('JWK must not be empty');
+        }
+        if (!isset($jwk['kty'])) {
+            throw new UnexpectedValueException('JWK must contain a "kty" parameter');
+        }
+
+        switch ($jwk['kty']) {
+            case 'RSA':
+                if (\array_key_exists('d', $jwk)) {
+                    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 $publicKey;
+            default:
+                // Currently only RSA is supported
+                break;
+        }
+    }
+
+    /**
+     * 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($n, $e)
+    {
+        $modulus = JWT::urlsafeB64Decode($n);
+        $publicExponent = JWT::urlsafeB64Decode($e);
+
+        $components = array(
+            'modulus' => \pack('Ca*a*', 2, self::encodeLength(\strlen($modulus)), $modulus),
+            'publicExponent' => \pack('Ca*a*', 2, self::encodeLength(\strlen($publicExponent)), $publicExponent)
+        );
+
+        $rsaPublicKey = \pack(
+            'Ca*a*a*',
+            48,
+            self::encodeLength(\strlen($components['modulus']) + \strlen($components['publicExponent'])),
+            $components['modulus'],
+            $components['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
+        );
+
+        $rsaPublicKey = "-----BEGIN PUBLIC KEY-----\r\n" .
+            \chunk_split(\base64_encode($rsaPublicKey), 64) .
+            '-----END PUBLIC KEY-----';
+
+        return $rsaPublicKey;
+    }
+
+    /**
+     * 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($length)
+    {
+        if ($length <= 0x7F) {
+            return \chr($length);
+        }
+
+        $temp = \ltrim(\pack('N', $length), \chr(0));
+
+        return \pack('Ca*', 0x80 | \strlen($temp), $temp);
+    }
+}
diff --git a/vendor/firebase/php-jwt/src/JWT.php b/vendor/firebase/php-jwt/src/JWT.php
index 22a67e32b61ab1edd56bc8996fa3f3b9f9a4c4ac..4860028bc620c9707e10c3bfc95a442bfedc25de 100644
--- a/vendor/firebase/php-jwt/src/JWT.php
+++ b/vendor/firebase/php-jwt/src/JWT.php
@@ -1,6 +1,7 @@
 <?php
 
 namespace Firebase\JWT;
+
 use \DomainException;
 use \InvalidArgumentException;
 use \UnexpectedValueException;
@@ -21,6 +22,9 @@ use \DateTime;
  */
 class JWT
 {
+    const ASN1_INTEGER = 0x02;
+    const ASN1_SEQUENCE = 0x10;
+    const ASN1_BIT_STRING = 0x03;
 
     /**
      * When checking nbf, iat or expiration times,
@@ -38,9 +42,10 @@ class JWT
     public static $timestamp = null;
 
     public static $supported_algs = array(
+        'ES256' => array('openssl', 'SHA256'),
         'HS256' => array('hash_hmac', 'SHA256'),
-        'HS512' => array('hash_hmac', 'SHA512'),
         'HS384' => array('hash_hmac', 'SHA384'),
+        'HS512' => array('hash_hmac', 'SHA512'),
         'RS256' => array('openssl', 'SHA256'),
         'RS384' => array('openssl', 'SHA384'),
         'RS512' => array('openssl', 'SHA512'),
@@ -49,11 +54,11 @@ class JWT
     /**
      * Decodes a JWT string into a PHP object.
      *
-     * @param string        $jwt            The JWT
-     * @param string|array  $key            The key, or map of keys.
-     *                                      If the algorithm used is asymmetric, this is the public key
-     * @param array         $allowed_algs   List of supported verification algorithms
-     *                                      Supported algorithms are 'HS256', 'HS384', 'HS512' and 'RS256'
+     * @param string                    $jwt            The JWT
+     * @param string|array|resource     $key            The key, or map of keys.
+     *                                                  If the algorithm used is asymmetric, this is the public key
+     * @param array                     $allowed_algs   List of supported verification algorithms
+     *                                                  Supported algorithms are 'ES256', 'HS256', 'HS384', 'HS512', 'RS256', 'RS384', and 'RS512'
      *
      * @return object The JWT's payload as a PHP object
      *
@@ -68,13 +73,13 @@ class JWT
      */
     public static function decode($jwt, $key, array $allowed_algs = array())
     {
-        $timestamp = is_null(static::$timestamp) ? time() : static::$timestamp;
+        $timestamp = \is_null(static::$timestamp) ? \time() : static::$timestamp;
 
         if (empty($key)) {
             throw new InvalidArgumentException('Key may not be empty');
         }
-        $tks = explode('.', $jwt);
-        if (count($tks) != 3) {
+        $tks = \explode('.', $jwt);
+        if (\count($tks) != 3) {
             throw new UnexpectedValueException('Wrong number of segments');
         }
         list($headb64, $bodyb64, $cryptob64) = $tks;
@@ -93,10 +98,15 @@ class JWT
         if (empty(static::$supported_algs[$header->alg])) {
             throw new UnexpectedValueException('Algorithm not supported');
         }
-        if (!in_array($header->alg, $allowed_algs)) {
+        if (!\in_array($header->alg, $allowed_algs)) {
             throw new UnexpectedValueException('Algorithm not allowed');
         }
-        if (is_array($key) || $key instanceof \ArrayAccess) {
+        if ($header->alg === 'ES256') {
+            // OpenSSL expects an ASN.1 DER sequence for ES256 signatures
+            $sig = self::signatureToDER($sig);
+        }
+
+        if (\is_array($key) || $key instanceof \ArrayAccess) {
             if (isset($header->kid)) {
                 if (!isset($key[$header->kid])) {
                     throw new UnexpectedValueException('"kid" invalid, unable to lookup correct key');
@@ -112,11 +122,11 @@ class JWT
             throw new SignatureInvalidException('Signature verification failed');
         }
 
-        // Check if the nbf if it is defined. This is the time that the
+        // 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) && $payload->nbf > ($timestamp + static::$leeway)) {
             throw new BeforeValidException(
-                'Cannot handle token prior to ' . date(DateTime::ISO8601, $payload->nbf)
+                'Cannot handle token prior to ' . \date(DateTime::ISO8601, $payload->nbf)
             );
         }
 
@@ -125,7 +135,7 @@ class JWT
         // correctly used the nbf claim).
         if (isset($payload->iat) && $payload->iat > ($timestamp + static::$leeway)) {
             throw new BeforeValidException(
-                'Cannot handle token prior to ' . date(DateTime::ISO8601, $payload->iat)
+                'Cannot handle token prior to ' . \date(DateTime::ISO8601, $payload->iat)
             );
         }
 
@@ -144,7 +154,7 @@ class JWT
      * @param string        $key        The secret key.
      *                                  If the algorithm used is asymmetric, this is the private key
      * @param string        $alg        The signing algorithm.
-     *                                  Supported algorithms are 'HS256', 'HS384', 'HS512' and 'RS256'
+     *                                  Supported algorithms are 'ES256', 'HS256', 'HS384', 'HS512', 'RS256', 'RS384', and 'RS512'
      * @param mixed         $keyId
      * @param array         $head       An array with header elements to attach
      *
@@ -159,18 +169,18 @@ class JWT
         if ($keyId !== null) {
             $header['kid'] = $keyId;
         }
-        if ( isset($head) && is_array($head) ) {
-            $header = array_merge($head, $header);
+        if (isset($head) && \is_array($head)) {
+            $header = \array_merge($head, $header);
         }
         $segments = array();
         $segments[] = static::urlsafeB64Encode(static::jsonEncode($header));
         $segments[] = static::urlsafeB64Encode(static::jsonEncode($payload));
-        $signing_input = implode('.', $segments);
+        $signing_input = \implode('.', $segments);
 
         $signature = static::sign($signing_input, $key, $alg);
         $segments[] = static::urlsafeB64Encode($signature);
 
-        return implode('.', $segments);
+        return \implode('.', $segments);
     }
 
     /**
@@ -179,7 +189,7 @@ class JWT
      * @param string            $msg    The message to sign
      * @param string|resource   $key    The secret key
      * @param string            $alg    The signing algorithm.
-     *                                  Supported algorithms are 'HS256', 'HS384', 'HS512' and 'RS256'
+     *                                  Supported algorithms are 'ES256', 'HS256', 'HS384', 'HS512', 'RS256', 'RS384', and 'RS512'
      *
      * @return string An encrypted message
      *
@@ -191,15 +201,18 @@ class JWT
             throw new DomainException('Algorithm not supported');
         }
         list($function, $algorithm) = static::$supported_algs[$alg];
-        switch($function) {
+        switch ($function) {
             case 'hash_hmac':
-                return hash_hmac($algorithm, $msg, $key, true);
+                return \hash_hmac($algorithm, $msg, $key, true);
             case 'openssl':
                 $signature = '';
-                $success = openssl_sign($msg, $signature, $key, $algorithm);
+                $success = \openssl_sign($msg, $signature, $key, $algorithm);
                 if (!$success) {
                     throw new DomainException("OpenSSL unable to sign data");
                 } else {
+                    if ($alg === 'ES256') {
+                        $signature = self::signatureFromDER($signature, 256);
+                    }
                     return $signature;
                 }
         }
@@ -225,9 +238,9 @@ class JWT
         }
 
         list($function, $algorithm) = static::$supported_algs[$alg];
-        switch($function) {
+        switch ($function) {
             case 'openssl':
-                $success = openssl_verify($msg, $signature, $key, $algorithm);
+                $success = \openssl_verify($msg, $signature, $key, $algorithm);
                 if ($success === 1) {
                     return true;
                 } elseif ($success === 0) {
@@ -235,19 +248,19 @@ class JWT
                 }
                 // returns 1 on success, 0 on failure, -1 on error.
                 throw new DomainException(
-                    'OpenSSL error: ' . openssl_error_string()
+                    'OpenSSL error: ' . \openssl_error_string()
                 );
             case 'hash_hmac':
             default:
-                $hash = hash_hmac($algorithm, $msg, $key, true);
-                if (function_exists('hash_equals')) {
-                    return hash_equals($signature, $hash);
+                $hash = \hash_hmac($algorithm, $msg, $key, true);
+                if (\function_exists('hash_equals')) {
+                    return \hash_equals($signature, $hash);
                 }
-                $len = min(static::safeStrlen($signature), static::safeStrlen($hash));
+                $len = \min(static::safeStrlen($signature), static::safeStrlen($hash));
 
                 $status = 0;
                 for ($i = 0; $i < $len; $i++) {
-                    $status |= (ord($signature[$i]) ^ ord($hash[$i]));
+                    $status |= (\ord($signature[$i]) ^ \ord($hash[$i]));
                 }
                 $status |= (static::safeStrlen($signature) ^ static::safeStrlen($hash));
 
@@ -266,23 +279,23 @@ class JWT
      */
     public static function jsonDecode($input)
     {
-        if (version_compare(PHP_VERSION, '5.4.0', '>=') && !(defined('JSON_C_VERSION') && PHP_INT_SIZE > 4)) {
+        if (\version_compare(PHP_VERSION, '5.4.0', '>=') && !(\defined('JSON_C_VERSION') && PHP_INT_SIZE > 4)) {
             /** In PHP >=5.4.0, json_decode() accepts an options parameter, that allows you
              * to specify that large ints (like Steam Transaction IDs) should be treated as
              * strings, rather than the PHP default behaviour of converting them to floats.
              */
-            $obj = json_decode($input, false, 512, JSON_BIGINT_AS_STRING);
+            $obj = \json_decode($input, false, 512, JSON_BIGINT_AS_STRING);
         } else {
             /** Not all servers will support that, however, so for older versions we must
              * manually detect large ints in the JSON string and quote them (thus converting
              *them to strings) before decoding, hence the preg_replace() call.
              */
-            $max_int_length = strlen((string) PHP_INT_MAX) - 1;
-            $json_without_bigints = preg_replace('/:\s*(-?\d{'.$max_int_length.',})/', ': "$1"', $input);
-            $obj = json_decode($json_without_bigints);
+            $max_int_length = \strlen((string) PHP_INT_MAX) - 1;
+            $json_without_bigints = \preg_replace('/:\s*(-?\d{'.$max_int_length.',})/', ': "$1"', $input);
+            $obj = \json_decode($json_without_bigints);
         }
 
-        if (function_exists('json_last_error') && $errno = json_last_error()) {
+        if ($errno = \json_last_error()) {
             static::handleJsonError($errno);
         } elseif ($obj === null && $input !== 'null') {
             throw new DomainException('Null result with non-null input');
@@ -301,8 +314,8 @@ class JWT
      */
     public static function jsonEncode($input)
     {
-        $json = json_encode($input);
-        if (function_exists('json_last_error') && $errno = json_last_error()) {
+        $json = \json_encode($input);
+        if ($errno = \json_last_error()) {
             static::handleJsonError($errno);
         } elseif ($json === 'null' && $input !== null) {
             throw new DomainException('Null result with non-null input');
@@ -319,12 +332,12 @@ class JWT
      */
     public static function urlsafeB64Decode($input)
     {
-        $remainder = strlen($input) % 4;
+        $remainder = \strlen($input) % 4;
         if ($remainder) {
             $padlen = 4 - $remainder;
-            $input .= str_repeat('=', $padlen);
+            $input .= \str_repeat('=', $padlen);
         }
-        return base64_decode(strtr($input, '-_', '+/'));
+        return \base64_decode(\strtr($input, '-_', '+/'));
     }
 
     /**
@@ -336,7 +349,7 @@ class JWT
      */
     public static function urlsafeB64Encode($input)
     {
-        return str_replace('=', '', strtr(base64_encode($input), '+/', '-_'));
+        return \str_replace('=', '', \strtr(\base64_encode($input), '+/', '-_'));
     }
 
     /**
@@ -365,15 +378,135 @@ class JWT
     /**
      * Get the number of bytes in cryptographic strings.
      *
-     * @param string
+     * @param string $str
      *
      * @return int
      */
     private static function safeStrlen($str)
     {
-        if (function_exists('mb_strlen')) {
-            return mb_strlen($str, '8bit');
+        if (\function_exists('mb_strlen')) {
+            return \mb_strlen($str, '8bit');
         }
-        return strlen($str);
+        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($sig)
+    {
+        // Separate the signature into r-value and s-value
+        list($r, $s) = \str_split($sig, (int) (\strlen($sig) / 2));
+
+        // 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($type, $value)
+    {
+        $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($der, $keySize)
+    {
+        // 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 [$offset, $data] the new offset and the decoded object
+     */
+    private static function readDER($der, $offset = 0)
+    {
+        $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 array($pos, $data);
     }
 }
diff --git a/vendor/firebase/php-jwt/src/SignatureInvalidException.php b/vendor/firebase/php-jwt/src/SignatureInvalidException.php
index 27332b21bea329f944e98c3dd349bd8c9bc917f7..87cb34df79b367bd51b7267e7ffd6aace8f7f97b 100644
--- a/vendor/firebase/php-jwt/src/SignatureInvalidException.php
+++ b/vendor/firebase/php-jwt/src/SignatureInvalidException.php
@@ -3,5 +3,4 @@ namespace Firebase\JWT;
 
 class SignatureInvalidException extends \UnexpectedValueException
 {
-
 }
diff --git a/vendor/myclabs/deep-copy/.github/FUNDING.yml b/vendor/myclabs/deep-copy/.github/FUNDING.yml
new file mode 100644
index 0000000000000000000000000000000000000000..b8da664ddcf9e4b4ee7090afff4a540cf277e57e
--- /dev/null
+++ b/vendor/myclabs/deep-copy/.github/FUNDING.yml
@@ -0,0 +1,12 @@
+# These are supported funding model platforms
+
+github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
+patreon: # Replace with a single Patreon username
+open_collective: # Replace with a single Open Collective username
+ko_fi: # Replace with a single Ko-fi username
+tidelift: "packagist/myclabs/deep-copy"
+community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
+liberapay: # Replace with a single Liberapay username
+issuehunt: # Replace with a single IssueHunt username
+otechie: # Replace with a single Otechie username
+custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
diff --git a/vendor/container-interop/container-interop/LICENSE b/vendor/myclabs/deep-copy/LICENSE
similarity index 96%
rename from vendor/container-interop/container-interop/LICENSE
rename to vendor/myclabs/deep-copy/LICENSE
index 7671d9020f64fb337cbf723aeeb6038f4ccde56c..c3e835001c1f40ba78ac45b07054e6fc9cf3ca9b 100644
--- a/vendor/container-interop/container-interop/LICENSE
+++ b/vendor/myclabs/deep-copy/LICENSE
@@ -1,6 +1,6 @@
 The MIT License (MIT)
 
-Copyright (c) 2013 container-interop
+Copyright (c) 2013 My C-Sense
 
 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
diff --git a/vendor/myclabs/deep-copy/README.md b/vendor/myclabs/deep-copy/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..007ad5bb8f38121593637c0512f1cd5bfbf4024f
--- /dev/null
+++ b/vendor/myclabs/deep-copy/README.md
@@ -0,0 +1,375 @@
+# DeepCopy
+
+DeepCopy helps you create deep copies (clones) of your objects. It is designed to handle cycles in the association graph.
+
+[![Build Status](https://travis-ci.org/myclabs/DeepCopy.png?branch=1.x)](https://travis-ci.org/myclabs/DeepCopy)
+[![Coverage Status](https://coveralls.io/repos/myclabs/DeepCopy/badge.png?branch=1.x)](https://coveralls.io/r/myclabs/DeepCopy?branch=1.x)
+[![Scrutinizer Quality Score](https://scrutinizer-ci.com/g/myclabs/DeepCopy/badges/quality-score.png?s=2747100c19b275f93a777e3297c6c12d1b68b934)](https://scrutinizer-ci.com/g/myclabs/DeepCopy/)
+[![Total Downloads](https://poser.pugx.org/myclabs/deep-copy/downloads.svg)](https://packagist.org/packages/myclabs/deep-copy)
+
+## Table of Contents
+
+1. [How](#how)
+1. [Why](#why)
+    1. [Using simply `clone`](#using-simply-clone)
+    1. [Overridding `__clone()`](#overridding-__clone)
+    1. [With `DeepCopy`](#with-deepcopy)
+1. [How it works](#how-it-works)
+1. [Going further](#going-further)
+    1. [Matchers](#matchers)
+        1. [Property name](#property-name)
+        1. [Specific property](#specific-property)
+        1. [Type](#type)
+    1. [Filters](#filters)
+        1. [`SetNullFilter`](#setnullfilter-filter)
+        1. [`KeepFilter`](#keepfilter-filter)
+        1. [`DoctrineCollectionFilter`](#doctrinecollectionfilter-filter)
+        1. [`DoctrineEmptyCollectionFilter`](#doctrineemptycollectionfilter-filter)
+        1. [`DoctrineProxyFilter`](#doctrineproxyfilter-filter)
+        1. [`ReplaceFilter`](#replacefilter-type-filter)
+        1. [`ShallowCopyFilter`](#shallowcopyfilter-type-filter)
+1. [Edge cases](#edge-cases)
+1. [Contributing](#contributing)
+    1. [Tests](#tests)
+
+
+## How?
+
+Install with Composer:
+
+```json
+composer require myclabs/deep-copy
+```
+
+Use simply:
+
+```php
+use DeepCopy\DeepCopy;
+
+$copier = new DeepCopy();
+$myCopy = $copier->copy($myObject);
+```
+
+
+## Why?
+
+- How do you create copies of your objects?
+
+```php
+$myCopy = clone $myObject;
+```
+
+- How do you create **deep** copies of your objects (i.e. copying also all the objects referenced in the properties)?
+
+You use [`__clone()`](http://www.php.net/manual/en/language.oop5.cloning.php#object.clone) and implement the behavior
+yourself.
+
+- But how do you handle **cycles** in the association graph?
+
+Now you're in for a big mess :(
+
+![association graph](doc/graph.png)
+
+
+### Using simply `clone`
+
+![Using clone](doc/clone.png)
+
+
+### Overridding `__clone()`
+
+![Overridding __clone](doc/deep-clone.png)
+
+
+### With `DeepCopy`
+
+![With DeepCopy](doc/deep-copy.png)
+
+
+## How it works
+
+DeepCopy recursively traverses all the object's properties and clones them. To avoid cloning the same object twice it
+keeps a hash map of all instances and thus preserves the object graph.
+
+To use it:
+
+```php
+use function DeepCopy\deep_copy;
+
+$copy = deep_copy($var);
+```
+
+Alternatively, you can create your own `DeepCopy` instance to configure it differently for example:
+
+```php
+use DeepCopy\DeepCopy;
+
+$copier = new DeepCopy(true);
+
+$copy = $copier->copy($var);
+```
+
+You may want to roll your own deep copy function:
+
+```php
+namespace Acme;
+
+use DeepCopy\DeepCopy;
+
+function deep_copy($var)
+{
+    static $copier = null;
+    
+    if (null === $copier) {
+        $copier = new DeepCopy(true);
+    }
+    
+    return $copier->copy($var);
+}
+```
+
+
+## Going further
+
+You can add filters to customize the copy process.
+
+The method to add a filter is `DeepCopy\DeepCopy::addFilter($filter, $matcher)`,
+with `$filter` implementing `DeepCopy\Filter\Filter`
+and `$matcher` implementing `DeepCopy\Matcher\Matcher`.
+
+We provide some generic filters and matchers.
+
+
+### Matchers
+
+  - `DeepCopy\Matcher` applies on a object attribute.
+  - `DeepCopy\TypeMatcher` applies on any element found in graph, including array elements.
+
+
+#### Property name
+
+The `PropertyNameMatcher` will match a property by its name:
+
+```php
+use DeepCopy\Matcher\PropertyNameMatcher;
+
+// Will apply a filter to any property of any objects named "id"
+$matcher = new PropertyNameMatcher('id');
+```
+
+
+#### Specific property
+
+The `PropertyMatcher` will match a specific property of a specific class:
+
+```php
+use DeepCopy\Matcher\PropertyMatcher;
+
+// Will apply a filter to the property "id" of any objects of the class "MyClass"
+$matcher = new PropertyMatcher('MyClass', 'id');
+```
+
+
+#### Type
+
+The `TypeMatcher` will match any element by its type (instance of a class or any value that could be parameter of
+[gettype()](http://php.net/manual/en/function.gettype.php) function):
+
+```php
+use DeepCopy\TypeMatcher\TypeMatcher;
+
+// Will apply a filter to any object that is an instance of Doctrine\Common\Collections\Collection
+$matcher = new TypeMatcher('Doctrine\Common\Collections\Collection');
+```
+
+
+### Filters
+
+- `DeepCopy\Filter` applies a transformation to the object attribute matched by `DeepCopy\Matcher`
+- `DeepCopy\TypeFilter` applies a transformation to any element matched by `DeepCopy\TypeMatcher`
+
+
+#### `SetNullFilter` (filter)
+
+Let's say for example that you are copying a database record (or a Doctrine entity), so you want the copy not to have
+any ID:
+
+```php
+use DeepCopy\DeepCopy;
+use DeepCopy\Filter\SetNullFilter;
+use DeepCopy\Matcher\PropertyNameMatcher;
+
+$object = MyClass::load(123);
+echo $object->id; // 123
+
+$copier = new DeepCopy();
+$copier->addFilter(new SetNullFilter(), new PropertyNameMatcher('id'));
+
+$copy = $copier->copy($object);
+
+echo $copy->id; // null
+```
+
+
+#### `KeepFilter` (filter)
+
+If you want a property to remain untouched (for example, an association to an object):
+
+```php
+use DeepCopy\DeepCopy;
+use DeepCopy\Filter\KeepFilter;
+use DeepCopy\Matcher\PropertyMatcher;
+
+$copier = new DeepCopy();
+$copier->addFilter(new KeepFilter(), new PropertyMatcher('MyClass', 'category'));
+
+$copy = $copier->copy($object);
+// $copy->category has not been touched
+```
+
+
+#### `DoctrineCollectionFilter` (filter)
+
+If you use Doctrine and want to copy an entity, you will need to use the `DoctrineCollectionFilter`:
+
+```php
+use DeepCopy\DeepCopy;
+use DeepCopy\Filter\Doctrine\DoctrineCollectionFilter;
+use DeepCopy\Matcher\PropertyTypeMatcher;
+
+$copier = new DeepCopy();
+$copier->addFilter(new DoctrineCollectionFilter(), new PropertyTypeMatcher('Doctrine\Common\Collections\Collection'));
+
+$copy = $copier->copy($object);
+```
+
+
+#### `DoctrineEmptyCollectionFilter` (filter)
+
+If you use Doctrine and want to copy an entity who contains a `Collection` that you want to be reset, you can use the
+`DoctrineEmptyCollectionFilter`
+
+```php
+use DeepCopy\DeepCopy;
+use DeepCopy\Filter\Doctrine\DoctrineEmptyCollectionFilter;
+use DeepCopy\Matcher\PropertyMatcher;
+
+$copier = new DeepCopy();
+$copier->addFilter(new DoctrineEmptyCollectionFilter(), new PropertyMatcher('MyClass', 'myProperty'));
+
+$copy = $copier->copy($object);
+
+// $copy->myProperty will return an empty collection
+```
+
+
+#### `DoctrineProxyFilter` (filter)
+
+If you use Doctrine and use cloning on lazy loaded entities, you might encounter errors mentioning missing fields on a
+Doctrine proxy class (...\\\_\_CG\_\_\Proxy).
+You can use the `DoctrineProxyFilter` to load the actual entity behind the Doctrine proxy class.
+**Make sure, though, to put this as one of your very first filters in the filter chain so that the entity is loaded
+before other filters are applied!**
+
+```php
+use DeepCopy\DeepCopy;
+use DeepCopy\Filter\Doctrine\DoctrineProxyFilter;
+use DeepCopy\Matcher\Doctrine\DoctrineProxyMatcher;
+
+$copier = new DeepCopy();
+$copier->addFilter(new DoctrineProxyFilter(), new DoctrineProxyMatcher());
+
+$copy = $copier->copy($object);
+
+// $copy should now contain a clone of all entities, including those that were not yet fully loaded.
+```
+
+
+#### `ReplaceFilter` (type filter)
+
+1. If you want to replace the value of a property:
+
+```php
+use DeepCopy\DeepCopy;
+use DeepCopy\Filter\ReplaceFilter;
+use DeepCopy\Matcher\PropertyMatcher;
+
+$copier = new DeepCopy();
+$callback = function ($currentValue) {
+  return $currentValue . ' (copy)'
+};
+$copier->addFilter(new ReplaceFilter($callback), new PropertyMatcher('MyClass', 'title'));
+
+$copy = $copier->copy($object);
+
+// $copy->title will contain the data returned by the callback, e.g. 'The title (copy)'
+```
+
+2. If you want to replace whole element:
+
+```php
+use DeepCopy\DeepCopy;
+use DeepCopy\TypeFilter\ReplaceFilter;
+use DeepCopy\TypeMatcher\TypeMatcher;
+
+$copier = new DeepCopy();
+$callback = function (MyClass $myClass) {
+  return get_class($myClass);
+};
+$copier->addTypeFilter(new ReplaceFilter($callback), new TypeMatcher('MyClass'));
+
+$copy = $copier->copy([new MyClass, 'some string', new MyClass]);
+
+// $copy will contain ['MyClass', 'some string', 'MyClass']
+```
+
+
+The `$callback` parameter of the `ReplaceFilter` constructor accepts any PHP callable.
+
+
+#### `ShallowCopyFilter` (type filter)
+
+Stop *DeepCopy* from recursively copying element, using standard `clone` instead:
+
+```php
+use DeepCopy\DeepCopy;
+use DeepCopy\TypeFilter\ShallowCopyFilter;
+use DeepCopy\TypeMatcher\TypeMatcher;
+use Mockery as m;
+
+$this->deepCopy = new DeepCopy();
+$this->deepCopy->addTypeFilter(
+	new ShallowCopyFilter,
+	new TypeMatcher(m\MockInterface::class)
+);
+
+$myServiceWithMocks = new MyService(m::mock(MyDependency1::class), m::mock(MyDependency2::class));
+// All mocks will be just cloned, not deep copied
+```
+
+
+## Edge cases
+
+The following structures cannot be deep-copied with PHP Reflection. As a result they are shallow cloned and filters are
+not applied. There is two ways for you to handle them:
+
+- Implement your own `__clone()` method
+- Use a filter with a type matcher
+
+
+## Contributing
+
+DeepCopy is distributed under the MIT license.
+
+
+### Tests
+
+Running the tests is simple:
+
+```php
+vendor/bin/phpunit
+```
+
+### Support
+
+Get professional support via [the Tidelift Subscription](https://tidelift.com/subscription/pkg/packagist-myclabs-deep-copy?utm_source=packagist-myclabs-deep-copy&utm_medium=referral&utm_campaign=readme).
diff --git a/vendor/myclabs/deep-copy/composer.json b/vendor/myclabs/deep-copy/composer.json
new file mode 100644
index 0000000000000000000000000000000000000000..45656c916de89ed11c06289eb017bcfb535a33c1
--- /dev/null
+++ b/vendor/myclabs/deep-copy/composer.json
@@ -0,0 +1,38 @@
+{
+    "name": "myclabs/deep-copy",
+    "type": "library",
+    "description": "Create deep copies (clones) of your objects",
+    "keywords": ["clone", "copy", "duplicate", "object", "object graph"],
+    "license": "MIT",
+
+    "autoload": {
+        "psr-4": {
+            "DeepCopy\\": "src/DeepCopy/"
+        },
+        "files": [
+            "src/DeepCopy/deep_copy.php"
+        ]
+    },
+    "autoload-dev": {
+        "psr-4": {
+            "DeepCopy\\": "fixtures/",
+            "DeepCopyTest\\": "tests/DeepCopyTest/"
+        }
+    },
+
+    "require": {
+        "php": "^7.1 || ^8.0"
+    },
+    "require-dev": {
+        "doctrine/collections": "^1.0",
+        "doctrine/common": "^2.6",
+        "phpunit/phpunit": "^7.1"
+    },
+    "replace": {
+        "myclabs/deep-copy": "self.version"
+    },
+
+    "config": {
+        "sort-packages": true
+    }
+}
diff --git a/vendor/myclabs/deep-copy/src/DeepCopy/DeepCopy.php b/vendor/myclabs/deep-copy/src/DeepCopy/DeepCopy.php
new file mode 100644
index 0000000000000000000000000000000000000000..15e5c6893fb3041b772baea87c29940eb77e44ba
--- /dev/null
+++ b/vendor/myclabs/deep-copy/src/DeepCopy/DeepCopy.php
@@ -0,0 +1,298 @@
+<?php
+
+namespace DeepCopy;
+
+use ArrayObject;
+use DateInterval;
+use DateTimeInterface;
+use DateTimeZone;
+use DeepCopy\Exception\CloneException;
+use DeepCopy\Filter\Filter;
+use DeepCopy\Matcher\Matcher;
+use DeepCopy\Reflection\ReflectionHelper;
+use DeepCopy\TypeFilter\Date\DateIntervalFilter;
+use DeepCopy\TypeFilter\Spl\ArrayObjectFilter;
+use DeepCopy\TypeFilter\Spl\SplDoublyLinkedListFilter;
+use DeepCopy\TypeFilter\TypeFilter;
+use DeepCopy\TypeMatcher\TypeMatcher;
+use ReflectionObject;
+use ReflectionProperty;
+use SplDoublyLinkedList;
+
+/**
+ * @final
+ */
+class DeepCopy
+{
+    /**
+     * @var object[] List of objects copied.
+     */
+    private $hashMap = [];
+
+    /**
+     * Filters to apply.
+     *
+     * @var array Array of ['filter' => Filter, 'matcher' => Matcher] pairs.
+     */
+    private $filters = [];
+
+    /**
+     * Type Filters to apply.
+     *
+     * @var array Array of ['filter' => Filter, 'matcher' => Matcher] pairs.
+     */
+    private $typeFilters = [];
+
+    /**
+     * @var bool
+     */
+    private $skipUncloneable = false;
+
+    /**
+     * @var bool
+     */
+    private $useCloneMethod;
+
+    /**
+     * @param bool $useCloneMethod   If set to true, when an object implements the __clone() function, it will be used
+     *                               instead of the regular deep cloning.
+     */
+    public function __construct($useCloneMethod = false)
+    {
+        $this->useCloneMethod = $useCloneMethod;
+
+        $this->addTypeFilter(new ArrayObjectFilter($this), new TypeMatcher(ArrayObject::class));
+        $this->addTypeFilter(new DateIntervalFilter(), new TypeMatcher(DateInterval::class));
+        $this->addTypeFilter(new SplDoublyLinkedListFilter($this), new TypeMatcher(SplDoublyLinkedList::class));
+    }
+
+    /**
+     * If enabled, will not throw an exception when coming across an uncloneable property.
+     *
+     * @param $skipUncloneable
+     *
+     * @return $this
+     */
+    public function skipUncloneable($skipUncloneable = true)
+    {
+        $this->skipUncloneable = $skipUncloneable;
+
+        return $this;
+    }
+
+    /**
+     * Deep copies the given object.
+     *
+     * @param mixed $object
+     *
+     * @return mixed
+     */
+    public function copy($object)
+    {
+        $this->hashMap = [];
+
+        return $this->recursiveCopy($object);
+    }
+
+    public function addFilter(Filter $filter, Matcher $matcher)
+    {
+        $this->filters[] = [
+            'matcher' => $matcher,
+            'filter'  => $filter,
+        ];
+    }
+
+    public function prependFilter(Filter $filter, Matcher $matcher)
+    {
+        array_unshift($this->filters, [
+            'matcher' => $matcher,
+            'filter'  => $filter,
+        ]);
+    }
+
+    public function addTypeFilter(TypeFilter $filter, TypeMatcher $matcher)
+    {
+        $this->typeFilters[] = [
+            'matcher' => $matcher,
+            'filter'  => $filter,
+        ];
+    }
+
+    private function recursiveCopy($var)
+    {
+        // Matches Type Filter
+        if ($filter = $this->getFirstMatchedTypeFilter($this->typeFilters, $var)) {
+            return $filter->apply($var);
+        }
+
+        // Resource
+        if (is_resource($var)) {
+            return $var;
+        }
+
+        // Array
+        if (is_array($var)) {
+            return $this->copyArray($var);
+        }
+
+        // Scalar
+        if (! is_object($var)) {
+            return $var;
+        }
+
+        // Object
+        return $this->copyObject($var);
+    }
+
+    /**
+     * Copy an array
+     * @param array $array
+     * @return array
+     */
+    private function copyArray(array $array)
+    {
+        foreach ($array as $key => $value) {
+            $array[$key] = $this->recursiveCopy($value);
+        }
+
+        return $array;
+    }
+
+    /**
+     * Copies an object.
+     *
+     * @param object $object
+     *
+     * @throws CloneException
+     *
+     * @return object
+     */
+    private function copyObject($object)
+    {
+        $objectHash = spl_object_hash($object);
+
+        if (isset($this->hashMap[$objectHash])) {
+            return $this->hashMap[$objectHash];
+        }
+
+        $reflectedObject = new ReflectionObject($object);
+        $isCloneable = $reflectedObject->isCloneable();
+
+        if (false === $isCloneable) {
+            if ($this->skipUncloneable) {
+                $this->hashMap[$objectHash] = $object;
+
+                return $object;
+            }
+
+            throw new CloneException(
+                sprintf(
+                    'The class "%s" is not cloneable.',
+                    $reflectedObject->getName()
+                )
+            );
+        }
+
+        $newObject = clone $object;
+        $this->hashMap[$objectHash] = $newObject;
+
+        if ($this->useCloneMethod && $reflectedObject->hasMethod('__clone')) {
+            return $newObject;
+        }
+
+        if ($newObject instanceof DateTimeInterface || $newObject instanceof DateTimeZone) {
+            return $newObject;
+        }
+
+        foreach (ReflectionHelper::getProperties($reflectedObject) as $property) {
+            $this->copyObjectProperty($newObject, $property);
+        }
+
+        return $newObject;
+    }
+
+    private function copyObjectProperty($object, ReflectionProperty $property)
+    {
+        // Ignore static properties
+        if ($property->isStatic()) {
+            return;
+        }
+
+        // Apply the filters
+        foreach ($this->filters as $item) {
+            /** @var Matcher $matcher */
+            $matcher = $item['matcher'];
+            /** @var Filter $filter */
+            $filter = $item['filter'];
+
+            if ($matcher->matches($object, $property->getName())) {
+                $filter->apply(
+                    $object,
+                    $property->getName(),
+                    function ($object) {
+                        return $this->recursiveCopy($object);
+                    }
+                );
+
+                // If a filter matches, we stop processing this property
+                return;
+            }
+        }
+
+        $property->setAccessible(true);
+
+        // Ignore uninitialized properties (for PHP >7.4)
+        if (method_exists($property, 'isInitialized') && !$property->isInitialized($object)) {
+            return;
+        }
+
+        $propertyValue = $property->getValue($object);
+
+        // Copy the property
+        $property->setValue($object, $this->recursiveCopy($propertyValue));
+    }
+
+    /**
+     * Returns first filter that matches variable, `null` if no such filter found.
+     *
+     * @param array $filterRecords Associative array with 2 members: 'filter' with value of type {@see TypeFilter} and
+     *                             'matcher' with value of type {@see TypeMatcher}
+     * @param mixed $var
+     *
+     * @return TypeFilter|null
+     */
+    private function getFirstMatchedTypeFilter(array $filterRecords, $var)
+    {
+        $matched = $this->first(
+            $filterRecords,
+            function (array $record) use ($var) {
+                /* @var TypeMatcher $matcher */
+                $matcher = $record['matcher'];
+
+                return $matcher->matches($var);
+            }
+        );
+
+        return isset($matched) ? $matched['filter'] : null;
+    }
+
+    /**
+     * Returns first element that matches predicate, `null` if no such element found.
+     *
+     * @param array    $elements Array of ['filter' => Filter, 'matcher' => Matcher] pairs.
+     * @param callable $predicate Predicate arguments are: element.
+     *
+     * @return array|null Associative array with 2 members: 'filter' with value of type {@see TypeFilter} and 'matcher'
+     *                    with value of type {@see TypeMatcher} or `null`.
+     */
+    private function first(array $elements, callable $predicate)
+    {
+        foreach ($elements as $element) {
+            if (call_user_func($predicate, $element)) {
+                return $element;
+            }
+        }
+
+        return null;
+    }
+}
diff --git a/vendor/myclabs/deep-copy/src/DeepCopy/Exception/CloneException.php b/vendor/myclabs/deep-copy/src/DeepCopy/Exception/CloneException.php
new file mode 100644
index 0000000000000000000000000000000000000000..c046706a2756c5892fa6a6223360937e95aeee23
--- /dev/null
+++ b/vendor/myclabs/deep-copy/src/DeepCopy/Exception/CloneException.php
@@ -0,0 +1,9 @@
+<?php
+
+namespace DeepCopy\Exception;
+
+use UnexpectedValueException;
+
+class CloneException extends UnexpectedValueException
+{
+} 
\ No newline at end of file
diff --git a/vendor/myclabs/deep-copy/src/DeepCopy/Exception/PropertyException.php b/vendor/myclabs/deep-copy/src/DeepCopy/Exception/PropertyException.php
new file mode 100644
index 0000000000000000000000000000000000000000..9702101a9b1b4ca7015181c0006bb1caf6d9d3f5
--- /dev/null
+++ b/vendor/myclabs/deep-copy/src/DeepCopy/Exception/PropertyException.php
@@ -0,0 +1,9 @@
+<?php
+
+namespace DeepCopy\Exception;
+
+use ReflectionException;
+
+class PropertyException extends ReflectionException
+{
+}
diff --git a/vendor/myclabs/deep-copy/src/DeepCopy/Filter/Doctrine/DoctrineCollectionFilter.php b/vendor/myclabs/deep-copy/src/DeepCopy/Filter/Doctrine/DoctrineCollectionFilter.php
new file mode 100644
index 0000000000000000000000000000000000000000..e6d937710418676bcb2db55b6a62a8a17b8d0111
--- /dev/null
+++ b/vendor/myclabs/deep-copy/src/DeepCopy/Filter/Doctrine/DoctrineCollectionFilter.php
@@ -0,0 +1,33 @@
+<?php
+
+namespace DeepCopy\Filter\Doctrine;
+
+use DeepCopy\Filter\Filter;
+use DeepCopy\Reflection\ReflectionHelper;
+
+/**
+ * @final
+ */
+class DoctrineCollectionFilter implements Filter
+{
+    /**
+     * Copies the object property doctrine collection.
+     *
+     * {@inheritdoc}
+     */
+    public function apply($object, $property, $objectCopier)
+    {
+        $reflectionProperty = ReflectionHelper::getProperty($object, $property);
+
+        $reflectionProperty->setAccessible(true);
+        $oldCollection = $reflectionProperty->getValue($object);
+
+        $newCollection = $oldCollection->map(
+            function ($item) use ($objectCopier) {
+                return $objectCopier($item);
+            }
+        );
+
+        $reflectionProperty->setValue($object, $newCollection);
+    }
+}
diff --git a/vendor/myclabs/deep-copy/src/DeepCopy/Filter/Doctrine/DoctrineEmptyCollectionFilter.php b/vendor/myclabs/deep-copy/src/DeepCopy/Filter/Doctrine/DoctrineEmptyCollectionFilter.php
new file mode 100644
index 0000000000000000000000000000000000000000..7b33fd5478f87ef28c2b5adda96ca04b0440c558
--- /dev/null
+++ b/vendor/myclabs/deep-copy/src/DeepCopy/Filter/Doctrine/DoctrineEmptyCollectionFilter.php
@@ -0,0 +1,28 @@
+<?php
+
+namespace DeepCopy\Filter\Doctrine;
+
+use DeepCopy\Filter\Filter;
+use DeepCopy\Reflection\ReflectionHelper;
+use Doctrine\Common\Collections\ArrayCollection;
+
+/**
+ * @final
+ */
+class DoctrineEmptyCollectionFilter implements Filter
+{
+    /**
+     * Sets the object property to an empty doctrine collection.
+     *
+     * @param object   $object
+     * @param string   $property
+     * @param callable $objectCopier
+     */
+    public function apply($object, $property, $objectCopier)
+    {
+        $reflectionProperty = ReflectionHelper::getProperty($object, $property);
+        $reflectionProperty->setAccessible(true);
+
+        $reflectionProperty->setValue($object, new ArrayCollection());
+    }
+} 
\ No newline at end of file
diff --git a/vendor/myclabs/deep-copy/src/DeepCopy/Filter/Doctrine/DoctrineProxyFilter.php b/vendor/myclabs/deep-copy/src/DeepCopy/Filter/Doctrine/DoctrineProxyFilter.php
new file mode 100644
index 0000000000000000000000000000000000000000..8bee8f769a5594c5a984f3452f227f436fdd3f03
--- /dev/null
+++ b/vendor/myclabs/deep-copy/src/DeepCopy/Filter/Doctrine/DoctrineProxyFilter.php
@@ -0,0 +1,22 @@
+<?php
+
+namespace DeepCopy\Filter\Doctrine;
+
+use DeepCopy\Filter\Filter;
+
+/**
+ * @final
+ */
+class DoctrineProxyFilter implements Filter
+{
+    /**
+     * Triggers the magic method __load() on a Doctrine Proxy class to load the
+     * actual entity from the database.
+     *
+     * {@inheritdoc}
+     */
+    public function apply($object, $property, $objectCopier)
+    {
+        $object->__load();
+    }
+}
diff --git a/vendor/myclabs/deep-copy/src/DeepCopy/Filter/Filter.php b/vendor/myclabs/deep-copy/src/DeepCopy/Filter/Filter.php
new file mode 100644
index 0000000000000000000000000000000000000000..85ba18ce1144c80206ef2b7b163fef2f5bf86a16
--- /dev/null
+++ b/vendor/myclabs/deep-copy/src/DeepCopy/Filter/Filter.php
@@ -0,0 +1,18 @@
+<?php
+
+namespace DeepCopy\Filter;
+
+/**
+ * Filter to apply to a property while copying an object
+ */
+interface Filter
+{
+    /**
+     * Applies the filter to the object.
+     *
+     * @param object   $object
+     * @param string   $property
+     * @param callable $objectCopier
+     */
+    public function apply($object, $property, $objectCopier);
+}
diff --git a/vendor/myclabs/deep-copy/src/DeepCopy/Filter/KeepFilter.php b/vendor/myclabs/deep-copy/src/DeepCopy/Filter/KeepFilter.php
new file mode 100644
index 0000000000000000000000000000000000000000..4b11a081ba34441fc1eee89a4a53e4c5caaedd38
--- /dev/null
+++ b/vendor/myclabs/deep-copy/src/DeepCopy/Filter/KeepFilter.php
@@ -0,0 +1,16 @@
+<?php
+
+namespace DeepCopy\Filter;
+
+class KeepFilter implements Filter
+{
+    /**
+     * Keeps the value of the object property.
+     *
+     * {@inheritdoc}
+     */
+    public function apply($object, $property, $objectCopier)
+    {
+        // Nothing to do
+    }
+}
diff --git a/vendor/myclabs/deep-copy/src/DeepCopy/Filter/ReplaceFilter.php b/vendor/myclabs/deep-copy/src/DeepCopy/Filter/ReplaceFilter.php
new file mode 100644
index 0000000000000000000000000000000000000000..7aca593bbc16172b5eaef83ddaed4e72a8aed207
--- /dev/null
+++ b/vendor/myclabs/deep-copy/src/DeepCopy/Filter/ReplaceFilter.php
@@ -0,0 +1,39 @@
+<?php
+
+namespace DeepCopy\Filter;
+
+use DeepCopy\Reflection\ReflectionHelper;
+
+/**
+ * @final
+ */
+class ReplaceFilter implements Filter
+{
+    /**
+     * @var callable
+     */
+    protected $callback;
+
+    /**
+     * @param callable $callable Will be called to get the new value for each property to replace
+     */
+    public function __construct(callable $callable)
+    {
+        $this->callback = $callable;
+    }
+
+    /**
+     * Replaces the object property by the result of the callback called with the object property.
+     *
+     * {@inheritdoc}
+     */
+    public function apply($object, $property, $objectCopier)
+    {
+        $reflectionProperty = ReflectionHelper::getProperty($object, $property);
+        $reflectionProperty->setAccessible(true);
+
+        $value = call_user_func($this->callback, $reflectionProperty->getValue($object));
+
+        $reflectionProperty->setValue($object, $value);
+    }
+}
diff --git a/vendor/myclabs/deep-copy/src/DeepCopy/Filter/SetNullFilter.php b/vendor/myclabs/deep-copy/src/DeepCopy/Filter/SetNullFilter.php
new file mode 100644
index 0000000000000000000000000000000000000000..bea86b884877d04852eee7b824a53d751f4318dd
--- /dev/null
+++ b/vendor/myclabs/deep-copy/src/DeepCopy/Filter/SetNullFilter.php
@@ -0,0 +1,24 @@
+<?php
+
+namespace DeepCopy\Filter;
+
+use DeepCopy\Reflection\ReflectionHelper;
+
+/**
+ * @final
+ */
+class SetNullFilter implements Filter
+{
+    /**
+     * Sets the object property to null.
+     *
+     * {@inheritdoc}
+     */
+    public function apply($object, $property, $objectCopier)
+    {
+        $reflectionProperty = ReflectionHelper::getProperty($object, $property);
+
+        $reflectionProperty->setAccessible(true);
+        $reflectionProperty->setValue($object, null);
+    }
+}
diff --git a/vendor/myclabs/deep-copy/src/DeepCopy/Matcher/Doctrine/DoctrineProxyMatcher.php b/vendor/myclabs/deep-copy/src/DeepCopy/Matcher/Doctrine/DoctrineProxyMatcher.php
new file mode 100644
index 0000000000000000000000000000000000000000..ec8856f50355b1b20755f5bf5789298cb4ef9ab2
--- /dev/null
+++ b/vendor/myclabs/deep-copy/src/DeepCopy/Matcher/Doctrine/DoctrineProxyMatcher.php
@@ -0,0 +1,22 @@
+<?php
+
+namespace DeepCopy\Matcher\Doctrine;
+
+use DeepCopy\Matcher\Matcher;
+use Doctrine\Common\Persistence\Proxy;
+
+/**
+ * @final
+ */
+class DoctrineProxyMatcher implements Matcher
+{
+    /**
+     * Matches a Doctrine Proxy class.
+     *
+     * {@inheritdoc}
+     */
+    public function matches($object, $property)
+    {
+        return $object instanceof Proxy;
+    }
+}
diff --git a/vendor/myclabs/deep-copy/src/DeepCopy/Matcher/Matcher.php b/vendor/myclabs/deep-copy/src/DeepCopy/Matcher/Matcher.php
new file mode 100644
index 0000000000000000000000000000000000000000..d67f3cac6e31c40d6a63a281f105a194399e26b1
--- /dev/null
+++ b/vendor/myclabs/deep-copy/src/DeepCopy/Matcher/Matcher.php
@@ -0,0 +1,14 @@
+<?php
+
+namespace DeepCopy\Matcher;
+
+interface Matcher
+{
+    /**
+     * @param object $object
+     * @param string $property
+     *
+     * @return boolean
+     */
+    public function matches($object, $property);
+}
diff --git a/vendor/myclabs/deep-copy/src/DeepCopy/Matcher/PropertyMatcher.php b/vendor/myclabs/deep-copy/src/DeepCopy/Matcher/PropertyMatcher.php
new file mode 100644
index 0000000000000000000000000000000000000000..073b20cb8288aa96ec4382a2287ff5ea9ac9c51d
--- /dev/null
+++ b/vendor/myclabs/deep-copy/src/DeepCopy/Matcher/PropertyMatcher.php
@@ -0,0 +1,39 @@
+<?php
+
+namespace DeepCopy\Matcher;
+
+/**
+ * @final
+ */
+class PropertyMatcher implements Matcher
+{
+    /**
+     * @var string
+     */
+    private $class;
+
+    /**
+     * @var string
+     */
+    private $property;
+
+    /**
+     * @param string $class    Class name
+     * @param string $property Property name
+     */
+    public function __construct($class, $property)
+    {
+        $this->class = $class;
+        $this->property = $property;
+    }
+
+    /**
+     * Matches a specific property of a specific class.
+     *
+     * {@inheritdoc}
+     */
+    public function matches($object, $property)
+    {
+        return ($object instanceof $this->class) && $property == $this->property;
+    }
+}
diff --git a/vendor/myclabs/deep-copy/src/DeepCopy/Matcher/PropertyNameMatcher.php b/vendor/myclabs/deep-copy/src/DeepCopy/Matcher/PropertyNameMatcher.php
new file mode 100644
index 0000000000000000000000000000000000000000..c8ec0d2bc1751fff332ae872da4d96d73ba76d2a
--- /dev/null
+++ b/vendor/myclabs/deep-copy/src/DeepCopy/Matcher/PropertyNameMatcher.php
@@ -0,0 +1,32 @@
+<?php
+
+namespace DeepCopy\Matcher;
+
+/**
+ * @final
+ */
+class PropertyNameMatcher implements Matcher
+{
+    /**
+     * @var string
+     */
+    private $property;
+
+    /**
+     * @param string $property Property name
+     */
+    public function __construct($property)
+    {
+        $this->property = $property;
+    }
+
+    /**
+     * Matches a property by its name.
+     *
+     * {@inheritdoc}
+     */
+    public function matches($object, $property)
+    {
+        return $property == $this->property;
+    }
+}
diff --git a/vendor/myclabs/deep-copy/src/DeepCopy/Matcher/PropertyTypeMatcher.php b/vendor/myclabs/deep-copy/src/DeepCopy/Matcher/PropertyTypeMatcher.php
new file mode 100644
index 0000000000000000000000000000000000000000..c7f46908c6240b8446e8e8c5f94f4e1966de65bd
--- /dev/null
+++ b/vendor/myclabs/deep-copy/src/DeepCopy/Matcher/PropertyTypeMatcher.php
@@ -0,0 +1,52 @@
+<?php
+
+namespace DeepCopy\Matcher;
+
+use DeepCopy\Reflection\ReflectionHelper;
+use ReflectionException;
+
+/**
+ * Matches a property by its type.
+ *
+ * It is recommended to use {@see DeepCopy\TypeFilter\TypeFilter} instead, as it applies on all occurrences
+ * of given type in copied context (eg. array elements), not just on object properties.
+ *
+ * @final
+ */
+class PropertyTypeMatcher implements Matcher
+{
+    /**
+     * @var string
+     */
+    private $propertyType;
+
+    /**
+     * @param string $propertyType Property type
+     */
+    public function __construct($propertyType)
+    {
+        $this->propertyType = $propertyType;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function matches($object, $property)
+    {
+        try {
+            $reflectionProperty = ReflectionHelper::getProperty($object, $property);
+        } catch (ReflectionException $exception) {
+            return false;
+        }
+
+        $reflectionProperty->setAccessible(true);
+
+        // Uninitialized properties (for PHP >7.4)
+        if (method_exists($reflectionProperty, 'isInitialized') && !$reflectionProperty->isInitialized($object)) {
+            // null instanceof $this->propertyType
+            return false;
+        }
+
+        return $reflectionProperty->getValue($object) instanceof $this->propertyType;
+    }
+}
diff --git a/vendor/myclabs/deep-copy/src/DeepCopy/Reflection/ReflectionHelper.php b/vendor/myclabs/deep-copy/src/DeepCopy/Reflection/ReflectionHelper.php
new file mode 100644
index 0000000000000000000000000000000000000000..742410cb2adde479d7e02629b0915ffb0624a05c
--- /dev/null
+++ b/vendor/myclabs/deep-copy/src/DeepCopy/Reflection/ReflectionHelper.php
@@ -0,0 +1,78 @@
+<?php
+
+namespace DeepCopy\Reflection;
+
+use DeepCopy\Exception\PropertyException;
+use ReflectionClass;
+use ReflectionException;
+use ReflectionObject;
+use ReflectionProperty;
+
+class ReflectionHelper
+{
+    /**
+     * Retrieves all properties (including private ones), from object and all its ancestors.
+     *
+     * Standard \ReflectionClass->getProperties() does not return private properties from ancestor classes.
+     *
+     * @author muratyaman@gmail.com
+     * @see http://php.net/manual/en/reflectionclass.getproperties.php
+     *
+     * @param ReflectionClass $ref
+     *
+     * @return ReflectionProperty[]
+     */
+    public static function getProperties(ReflectionClass $ref)
+    {
+        $props = $ref->getProperties();
+        $propsArr = array();
+
+        foreach ($props as $prop) {
+            $propertyName = $prop->getName();
+            $propsArr[$propertyName] = $prop;
+        }
+
+        if ($parentClass = $ref->getParentClass()) {
+            $parentPropsArr = self::getProperties($parentClass);
+            foreach ($propsArr as $key => $property) {
+                $parentPropsArr[$key] = $property;
+            }
+
+            return $parentPropsArr;
+        }
+
+        return $propsArr;
+    }
+
+    /**
+     * Retrieves property by name from object and all its ancestors.
+     *
+     * @param object|string $object
+     * @param string $name
+     *
+     * @throws PropertyException
+     * @throws ReflectionException
+     *
+     * @return ReflectionProperty
+     */
+    public static function getProperty($object, $name)
+    {
+        $reflection = is_object($object) ? new ReflectionObject($object) : new ReflectionClass($object);
+
+        if ($reflection->hasProperty($name)) {
+            return $reflection->getProperty($name);
+        }
+
+        if ($parentClass = $reflection->getParentClass()) {
+            return self::getProperty($parentClass->getName(), $name);
+        }
+
+        throw new PropertyException(
+            sprintf(
+                'The class "%s" doesn\'t have a property with the given name: "%s".',
+                is_object($object) ? get_class($object) : $object,
+                $name
+            )
+        );
+    }
+}
diff --git a/vendor/myclabs/deep-copy/src/DeepCopy/TypeFilter/Date/DateIntervalFilter.php b/vendor/myclabs/deep-copy/src/DeepCopy/TypeFilter/Date/DateIntervalFilter.php
new file mode 100644
index 0000000000000000000000000000000000000000..becd1cfffda49054ffb77e86e2a539db34990eeb
--- /dev/null
+++ b/vendor/myclabs/deep-copy/src/DeepCopy/TypeFilter/Date/DateIntervalFilter.php
@@ -0,0 +1,33 @@
+<?php
+
+namespace DeepCopy\TypeFilter\Date;
+
+use DateInterval;
+use DeepCopy\TypeFilter\TypeFilter;
+
+/**
+ * @final
+ *
+ * @deprecated Will be removed in 2.0. This filter will no longer be necessary in PHP 7.1+.
+ */
+class DateIntervalFilter implements TypeFilter
+{
+
+    /**
+     * {@inheritdoc}
+     *
+     * @param DateInterval $element
+     *
+     * @see http://news.php.net/php.bugs/205076
+     */
+    public function apply($element)
+    {
+        $copy = new DateInterval('P0D');
+
+        foreach ($element as $propertyName => $propertyValue) {
+            $copy->{$propertyName} = $propertyValue;
+        }
+
+        return $copy;
+    }
+}
diff --git a/vendor/myclabs/deep-copy/src/DeepCopy/TypeFilter/ReplaceFilter.php b/vendor/myclabs/deep-copy/src/DeepCopy/TypeFilter/ReplaceFilter.php
new file mode 100644
index 0000000000000000000000000000000000000000..164f8b8e26447acde3b3030a0fd9022fb1734a40
--- /dev/null
+++ b/vendor/myclabs/deep-copy/src/DeepCopy/TypeFilter/ReplaceFilter.php
@@ -0,0 +1,30 @@
+<?php
+
+namespace DeepCopy\TypeFilter;
+
+/**
+ * @final
+ */
+class ReplaceFilter implements TypeFilter
+{
+    /**
+     * @var callable
+     */
+    protected $callback;
+
+    /**
+     * @param callable $callable Will be called to get the new value for each element to replace
+     */
+    public function __construct(callable $callable)
+    {
+        $this->callback = $callable;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function apply($element)
+    {
+        return call_user_func($this->callback, $element);
+    }
+}
diff --git a/vendor/myclabs/deep-copy/src/DeepCopy/TypeFilter/ShallowCopyFilter.php b/vendor/myclabs/deep-copy/src/DeepCopy/TypeFilter/ShallowCopyFilter.php
new file mode 100644
index 0000000000000000000000000000000000000000..a5fbd7a2b453f52f5685b1c52b1e493df96c8f02
--- /dev/null
+++ b/vendor/myclabs/deep-copy/src/DeepCopy/TypeFilter/ShallowCopyFilter.php
@@ -0,0 +1,17 @@
+<?php
+
+namespace DeepCopy\TypeFilter;
+
+/**
+ * @final
+ */
+class ShallowCopyFilter implements TypeFilter
+{
+    /**
+     * {@inheritdoc}
+     */
+    public function apply($element)
+    {
+        return clone $element;
+    }
+}
diff --git a/vendor/myclabs/deep-copy/src/DeepCopy/TypeFilter/Spl/ArrayObjectFilter.php b/vendor/myclabs/deep-copy/src/DeepCopy/TypeFilter/Spl/ArrayObjectFilter.php
new file mode 100644
index 0000000000000000000000000000000000000000..17846017910770f442c5c2e8a7565807ff9cb240
--- /dev/null
+++ b/vendor/myclabs/deep-copy/src/DeepCopy/TypeFilter/Spl/ArrayObjectFilter.php
@@ -0,0 +1,36 @@
+<?php
+namespace DeepCopy\TypeFilter\Spl;
+
+use DeepCopy\DeepCopy;
+use DeepCopy\TypeFilter\TypeFilter;
+
+/**
+ * In PHP 7.4 the storage of an ArrayObject isn't returned as
+ * ReflectionProperty. So we deep copy its array copy.
+ */
+final class ArrayObjectFilter implements TypeFilter
+{
+    /**
+     * @var DeepCopy
+     */
+    private $copier;
+
+    public function __construct(DeepCopy $copier)
+    {
+        $this->copier = $copier;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function apply($arrayObject)
+    {
+        $clone = clone $arrayObject;
+        foreach ($arrayObject->getArrayCopy() as $k => $v) {
+            $clone->offsetSet($k, $this->copier->copy($v));
+        }
+
+        return $clone;
+    }
+}
+
diff --git a/vendor/myclabs/deep-copy/src/DeepCopy/TypeFilter/Spl/SplDoublyLinkedList.php b/vendor/myclabs/deep-copy/src/DeepCopy/TypeFilter/Spl/SplDoublyLinkedList.php
new file mode 100644
index 0000000000000000000000000000000000000000..c5644cff8695ca58ba5a6580070e9858ef553079
--- /dev/null
+++ b/vendor/myclabs/deep-copy/src/DeepCopy/TypeFilter/Spl/SplDoublyLinkedList.php
@@ -0,0 +1,10 @@
+<?php
+
+namespace DeepCopy\TypeFilter\Spl;
+
+/**
+ * @deprecated Use {@see SplDoublyLinkedListFilter} instead.
+ */
+class SplDoublyLinkedList extends SplDoublyLinkedListFilter
+{
+}
diff --git a/vendor/myclabs/deep-copy/src/DeepCopy/TypeFilter/Spl/SplDoublyLinkedListFilter.php b/vendor/myclabs/deep-copy/src/DeepCopy/TypeFilter/Spl/SplDoublyLinkedListFilter.php
new file mode 100644
index 0000000000000000000000000000000000000000..c33be45807f0c83d49128c7cb70be8d6915cddc9
--- /dev/null
+++ b/vendor/myclabs/deep-copy/src/DeepCopy/TypeFilter/Spl/SplDoublyLinkedListFilter.php
@@ -0,0 +1,51 @@
+<?php
+
+namespace DeepCopy\TypeFilter\Spl;
+
+use Closure;
+use DeepCopy\DeepCopy;
+use DeepCopy\TypeFilter\TypeFilter;
+use SplDoublyLinkedList;
+
+/**
+ * @final
+ */
+class SplDoublyLinkedListFilter implements TypeFilter
+{
+    private $copier;
+
+    public function __construct(DeepCopy $copier)
+    {
+        $this->copier = $copier;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function apply($element)
+    {
+        $newElement = clone $element;
+
+        $copy = $this->createCopyClosure();
+
+        return $copy($newElement);
+    }
+
+    private function createCopyClosure()
+    {
+        $copier = $this->copier;
+
+        $copy = function (SplDoublyLinkedList $list) use ($copier) {
+            // Replace each element in the list with a deep copy of itself
+            for ($i = 1; $i <= $list->count(); $i++) {
+                $copy = $copier->recursiveCopy($list->shift());
+
+                $list->push($copy);
+            }
+
+            return $list;
+        };
+
+        return Closure::bind($copy, null, DeepCopy::class);
+    }
+}
diff --git a/vendor/myclabs/deep-copy/src/DeepCopy/TypeFilter/TypeFilter.php b/vendor/myclabs/deep-copy/src/DeepCopy/TypeFilter/TypeFilter.php
new file mode 100644
index 0000000000000000000000000000000000000000..5785a7da9ecd523bd8d79af9e0fce69d1864186b
--- /dev/null
+++ b/vendor/myclabs/deep-copy/src/DeepCopy/TypeFilter/TypeFilter.php
@@ -0,0 +1,13 @@
+<?php
+
+namespace DeepCopy\TypeFilter;
+
+interface TypeFilter
+{
+    /**
+     * Applies the filter to the object.
+     *
+     * @param mixed $element
+     */
+    public function apply($element);
+}
diff --git a/vendor/myclabs/deep-copy/src/DeepCopy/TypeMatcher/TypeMatcher.php b/vendor/myclabs/deep-copy/src/DeepCopy/TypeMatcher/TypeMatcher.php
new file mode 100644
index 0000000000000000000000000000000000000000..a563cb294e6b8b7725a13936174d714bce034356
--- /dev/null
+++ b/vendor/myclabs/deep-copy/src/DeepCopy/TypeMatcher/TypeMatcher.php
@@ -0,0 +1,29 @@
+<?php
+
+namespace DeepCopy\TypeMatcher;
+
+class TypeMatcher
+{
+    /**
+     * @var string
+     */
+    private $type;
+
+    /**
+     * @param string $type
+     */
+    public function __construct($type)
+    {
+        $this->type = $type;
+    }
+
+    /**
+     * @param mixed $element
+     *
+     * @return boolean
+     */
+    public function matches($element)
+    {
+        return is_object($element) ? is_a($element, $this->type) : gettype($element) === $this->type;
+    }
+}
diff --git a/vendor/myclabs/deep-copy/src/DeepCopy/deep_copy.php b/vendor/myclabs/deep-copy/src/DeepCopy/deep_copy.php
new file mode 100644
index 0000000000000000000000000000000000000000..55dcc926179fcc7b8f1884204fe65db2cc7084e5
--- /dev/null
+++ b/vendor/myclabs/deep-copy/src/DeepCopy/deep_copy.php
@@ -0,0 +1,20 @@
+<?php
+
+namespace DeepCopy;
+
+use function function_exists;
+
+if (false === function_exists('DeepCopy\deep_copy')) {
+    /**
+     * Deep copies the given value.
+     *
+     * @param mixed $value
+     * @param bool  $useCloneMethod
+     *
+     * @return mixed
+     */
+    function deep_copy($value, $useCloneMethod = false)
+    {
+        return (new DeepCopy($useCloneMethod))->copy($value);
+    }
+}
diff --git a/vendor/nikic/php-parser/.github/workflows/main.yml b/vendor/nikic/php-parser/.github/workflows/main.yml
new file mode 100644
index 0000000000000000000000000000000000000000..426d4c83d24277ca457f96762702bc0d892381d2
--- /dev/null
+++ b/vendor/nikic/php-parser/.github/workflows/main.yml
@@ -0,0 +1,86 @@
+# https://help.github.com/en/categories/automating-your-workflow-with-github-actions
+name: Main
+on:
+  push:
+  pull_request:
+
+jobs:
+  tests_70:
+    runs-on: "ubuntu-latest"
+    name: "PHP 7.0 Unit Tests"
+    steps:
+      - name: "Checkout"
+        uses: "actions/checkout@v2"
+      - name: "Install PHP"
+        uses: "shivammathur/setup-php@v2"
+        with:
+          coverage: "xdebug"
+          php-version: "7.0"
+          tools: composer:v2
+      - name: "Install dependencies"
+        run: |
+          composer require php-coveralls/php-coveralls:^2.2 --dev --no-update
+          composer update --no-progress --prefer-dist
+      - name: "Tests"
+        run: "php vendor/bin/phpunit --coverage-clover build/logs/clover.xml"
+      - name: Coveralls
+        env:
+          COVERALLS_REPO_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+        run: "php vendor/bin/php-coveralls"
+        if: ${{ success() }}
+  tests:
+    runs-on: "ubuntu-latest"
+    name: "PHP ${{ matrix.php-version }} Unit Tests"
+    strategy:
+      matrix:
+        php-version:
+          - "7.1"
+          - "7.2"
+          - "7.3"
+          - "7.4"
+          - "8.0"
+    steps:
+      - name: "Checkout"
+        uses: "actions/checkout@v2"
+      - name: "Install PHP"
+        uses: "shivammathur/setup-php@v2"
+        with:
+          coverage: "none"
+          php-version: "${{ matrix.php-version }}"
+          tools: composer:v2
+      - name: "Install dependencies"
+        run: "composer update --no-progress --prefer-dist"
+      - name: "PHPUnit"
+        run: "php vendor/bin/phpunit"
+  test_old_73_80:
+    runs-on: "ubuntu-latest"
+    name: "PHP 7.3 Code on PHP 8.0 Integration Tests"
+    steps:
+      - name: "Checkout"
+        uses: "actions/checkout@v2"
+      - name: "Install PHP"
+        uses: "shivammathur/setup-php@v2"
+        with:
+          coverage: "none"
+          php-version: "8.0"
+          tools: composer:v2
+      - name: "Install PHP 8 dependencies"
+        run: "composer update --no-progress --prefer-dist"
+      - name: "Tests"
+        run: "test_old/run-php-src.sh 7.3.21"
+  test_old_80_70:
+    runs-on: "ubuntu-latest"
+    name: "PHP 8.0 Code on PHP 7.0 Integration Tests"
+    steps:
+      - name: "Checkout"
+        uses: "actions/checkout@v2"
+      - name: "Install PHP"
+        uses: "shivammathur/setup-php@v2"
+        with:
+          coverage: "none"
+          php-version: "7.0"
+          tools: composer:v2
+      - name: "Install PHP 8 dependencies"
+        run: "composer update --no-progress --prefer-dist"
+      - name: "Tests"
+        run: "test_old/run-php-src.sh 8.0.0"
diff --git a/vendor/nikic/php-parser/LICENSE b/vendor/nikic/php-parser/LICENSE
new file mode 100644
index 0000000000000000000000000000000000000000..2e56718358791b095d659b54f6c6e03f2bfb5f4f
--- /dev/null
+++ b/vendor/nikic/php-parser/LICENSE
@@ -0,0 +1,29 @@
+BSD 3-Clause License
+
+Copyright (c) 2011, Nikita Popov
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this
+   list of conditions and the following disclaimer.
+
+2. 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.
+
+3. Neither the name of the copyright holder nor the names of its
+   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 HOLDER 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/nikic/php-parser/README.md b/vendor/nikic/php-parser/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..4c8deada9311526abb7357cc38b1f2b6432f9158
--- /dev/null
+++ b/vendor/nikic/php-parser/README.md
@@ -0,0 +1,225 @@
+PHP Parser
+==========
+
+[![Coverage Status](https://coveralls.io/repos/github/nikic/PHP-Parser/badge.svg?branch=master)](https://coveralls.io/github/nikic/PHP-Parser?branch=master)
+
+This is a PHP 5.2 to PHP 8.0 parser written in PHP. Its purpose is to simplify static code analysis and
+manipulation.
+
+[**Documentation for version 4.x**][doc_master] (stable; for running on PHP >= 7.0; for parsing PHP 5.2 to PHP 8.0).
+
+[Documentation for version 3.x][doc_3_x] (unsupported; for running on PHP >= 5.5; for parsing PHP 5.2 to PHP 7.2).
+
+Features
+--------
+
+The main features provided by this library are:
+
+ * Parsing PHP 5, PHP 7, and PHP 8 code into an abstract syntax tree (AST).
+   * Invalid code can be parsed into a partial AST.
+   * The AST contains accurate location information.
+ * Dumping the AST in human-readable form.
+ * Converting an AST back to PHP code.
+   * Experimental: Formatting can be preserved for partially changed ASTs.
+ * Infrastructure to traverse and modify ASTs.
+ * Resolution of namespaced names.
+ * Evaluation of constant expressions.
+ * Builders to simplify AST construction for code generation.
+ * Converting an AST into JSON and back.
+
+Quick Start
+-----------
+
+Install the library using [composer](https://getcomposer.org):
+
+    php composer.phar require nikic/php-parser
+
+Parse some PHP code into an AST and dump the result in human-readable form:
+
+```php
+<?php
+use PhpParser\Error;
+use PhpParser\NodeDumper;
+use PhpParser\ParserFactory;
+
+$code = <<<'CODE'
+<?php
+
+function test($foo)
+{
+    var_dump($foo);
+}
+CODE;
+
+$parser = (new ParserFactory)->create(ParserFactory::PREFER_PHP7);
+try {
+    $ast = $parser->parse($code);
+} catch (Error $error) {
+    echo "Parse error: {$error->getMessage()}\n";
+    return;
+}
+
+$dumper = new NodeDumper;
+echo $dumper->dump($ast) . "\n";
+```
+
+This dumps an AST looking something like this:
+
+```
+array(
+    0: Stmt_Function(
+        byRef: false
+        name: Identifier(
+            name: test
+        )
+        params: array(
+            0: Param(
+                type: null
+                byRef: false
+                variadic: false
+                var: Expr_Variable(
+                    name: foo
+                )
+                default: null
+            )
+        )
+        returnType: null
+        stmts: array(
+            0: Stmt_Expression(
+                expr: Expr_FuncCall(
+                    name: Name(
+                        parts: array(
+                            0: var_dump
+                        )
+                    )
+                    args: array(
+                        0: Arg(
+                            value: Expr_Variable(
+                                name: foo
+                            )
+                            byRef: false
+                            unpack: false
+                        )
+                    )
+                )
+            )
+        )
+    )
+)
+```
+
+Let's traverse the AST and perform some kind of modification. For example, drop all function bodies:
+
+```php
+use PhpParser\Node;
+use PhpParser\Node\Stmt\Function_;
+use PhpParser\NodeTraverser;
+use PhpParser\NodeVisitorAbstract;
+
+$traverser = new NodeTraverser();
+$traverser->addVisitor(new class extends NodeVisitorAbstract {
+    public function enterNode(Node $node) {
+        if ($node instanceof Function_) {
+            // Clean out the function body
+            $node->stmts = [];
+        }
+    }
+});
+
+$ast = $traverser->traverse($ast);
+echo $dumper->dump($ast) . "\n";
+```
+
+This gives us an AST where the `Function_::$stmts` are empty:
+
+```
+array(
+    0: Stmt_Function(
+        byRef: false
+        name: Identifier(
+            name: test
+        )
+        params: array(
+            0: Param(
+                type: null
+                byRef: false
+                variadic: false
+                var: Expr_Variable(
+                    name: foo
+                )
+                default: null
+            )
+        )
+        returnType: null
+        stmts: array(
+        )
+    )
+)
+```
+
+Finally, we can convert the new AST back to PHP code:
+
+```php
+use PhpParser\PrettyPrinter;
+
+$prettyPrinter = new PrettyPrinter\Standard;
+echo $prettyPrinter->prettyPrintFile($ast);
+```
+
+This gives us our original code, minus the `var_dump()` call inside the function:
+
+```php
+<?php
+
+function test($foo)
+{
+}
+```
+
+For a more comprehensive introduction, see the documentation.
+
+Documentation
+-------------
+
+ 1. [Introduction](doc/0_Introduction.markdown)
+ 2. [Usage of basic components](doc/2_Usage_of_basic_components.markdown)
+
+Component documentation:
+
+ * [Walking the AST](doc/component/Walking_the_AST.markdown)
+   * Node visitors
+   * Modifying the AST from a visitor
+   * Short-circuiting traversals
+   * Interleaved visitors
+   * Simple node finding API
+   * Parent and sibling references
+ * [Name resolution](doc/component/Name_resolution.markdown)
+   * Name resolver options
+   * Name resolution context
+ * [Pretty printing](doc/component/Pretty_printing.markdown)
+   * Converting AST back to PHP code
+   * Customizing formatting
+   * Formatting-preserving code transformations
+ * [AST builders](doc/component/AST_builders.markdown)
+   * Fluent builders for AST nodes
+ * [Lexer](doc/component/Lexer.markdown)
+   * Lexer options
+   * Token and file positions for nodes
+   * Custom attributes
+ * [Error handling](doc/component/Error_handling.markdown)
+   * Column information for errors
+   * Error recovery (parsing of syntactically incorrect code)
+ * [Constant expression evaluation](doc/component/Constant_expression_evaluation.markdown)
+   * Evaluating constant/property/etc initializers
+   * Handling errors and unsupported expressions
+ * [JSON representation](doc/component/JSON_representation.markdown)
+   * JSON encoding and decoding of ASTs
+ * [Performance](doc/component/Performance.markdown)
+   * Disabling XDebug
+   * Reusing objects
+   * Garbage collection impact
+ * [Frequently asked questions](doc/component/FAQ.markdown)
+   * Parent and sibling references
+
+ [doc_3_x]: https://github.com/nikic/PHP-Parser/tree/3.x/doc
+ [doc_master]: https://github.com/nikic/PHP-Parser/tree/master/doc
diff --git a/vendor/nikic/php-parser/bin/php-parse b/vendor/nikic/php-parser/bin/php-parse
new file mode 100755
index 0000000000000000000000000000000000000000..a002f8527193b836c5ccf98c36483edcc8f37355
--- /dev/null
+++ b/vendor/nikic/php-parser/bin/php-parse
@@ -0,0 +1,205 @@
+#!/usr/bin/env php
+<?php
+
+foreach ([__DIR__ . '/../../../autoload.php', __DIR__ . '/../vendor/autoload.php'] as $file) {
+    if (file_exists($file)) {
+        require $file;
+        break;
+    }
+}
+
+ini_set('xdebug.max_nesting_level', 3000);
+
+// Disable XDebug var_dump() output truncation
+ini_set('xdebug.var_display_max_children', -1);
+ini_set('xdebug.var_display_max_data', -1);
+ini_set('xdebug.var_display_max_depth', -1);
+
+list($operations, $files, $attributes) = parseArgs($argv);
+
+/* Dump nodes by default */
+if (empty($operations)) {
+    $operations[] = 'dump';
+}
+
+if (empty($files)) {
+    showHelp("Must specify at least one file.");
+}
+
+$lexer = new PhpParser\Lexer\Emulative(['usedAttributes' => [
+    'startLine', 'endLine', 'startFilePos', 'endFilePos', 'comments'
+]]);
+$parser = (new PhpParser\ParserFactory)->create(
+    PhpParser\ParserFactory::PREFER_PHP7,
+    $lexer
+);
+$dumper = new PhpParser\NodeDumper([
+    'dumpComments' => true,
+    'dumpPositions' => $attributes['with-positions'],
+]);
+$prettyPrinter = new PhpParser\PrettyPrinter\Standard;
+
+$traverser = new PhpParser\NodeTraverser();
+$traverser->addVisitor(new PhpParser\NodeVisitor\NameResolver);
+
+foreach ($files as $file) {
+    if (strpos($file, '<?php') === 0) {
+        $code = $file;
+        fwrite(STDERR, "====> Code $code\n");
+    } else {
+        if (!file_exists($file)) {
+            fwrite(STDERR, "File $file does not exist.\n");
+            exit(1);
+        }
+
+        $code = file_get_contents($file);
+        fwrite(STDERR, "====> File $file:\n");
+    }
+
+    if ($attributes['with-recovery']) {
+        $errorHandler = new PhpParser\ErrorHandler\Collecting;
+        $stmts = $parser->parse($code, $errorHandler);
+        foreach ($errorHandler->getErrors() as $error) {
+            $message = formatErrorMessage($error, $code, $attributes['with-column-info']);
+            fwrite(STDERR, $message . "\n");
+        }
+        if (null === $stmts) {
+            continue;
+        }
+    } else {
+        try {
+            $stmts = $parser->parse($code);
+        } catch (PhpParser\Error $error) {
+            $message = formatErrorMessage($error, $code, $attributes['with-column-info']);
+            fwrite(STDERR, $message . "\n");
+            exit(1);
+        }
+    }
+
+    foreach ($operations as $operation) {
+        if ('dump' === $operation) {
+            fwrite(STDERR, "==> Node dump:\n");
+            echo $dumper->dump($stmts, $code), "\n";
+        } elseif ('pretty-print' === $operation) {
+            fwrite(STDERR, "==> Pretty print:\n");
+            echo $prettyPrinter->prettyPrintFile($stmts), "\n";
+        } elseif ('json-dump' === $operation) {
+            fwrite(STDERR, "==> JSON dump:\n");
+            echo json_encode($stmts, JSON_PRETTY_PRINT), "\n";
+        } elseif ('var-dump' === $operation) {
+            fwrite(STDERR, "==> var_dump():\n");
+            var_dump($stmts);
+        } elseif ('resolve-names' === $operation) {
+            fwrite(STDERR, "==> Resolved names.\n");
+            $stmts = $traverser->traverse($stmts);
+        }
+    }
+}
+
+function formatErrorMessage(PhpParser\Error $e, $code, $withColumnInfo) {
+    if ($withColumnInfo && $e->hasColumnInfo()) {
+        return $e->getMessageWithColumnInfo($code);
+    } else {
+        return $e->getMessage();
+    }
+}
+
+function showHelp($error = '') {
+    if ($error) {
+        fwrite(STDERR, $error . "\n\n");
+    }
+    fwrite($error ? STDERR : STDOUT, <<<OUTPUT
+Usage: php-parse [operations] file1.php [file2.php ...]
+   or: php-parse [operations] "<?php code"
+Turn PHP source code into an abstract syntax tree.
+
+Operations is a list of the following options (--dump by default):
+
+    -d, --dump              Dump nodes using NodeDumper
+    -p, --pretty-print      Pretty print file using PrettyPrinter\Standard
+    -j, --json-dump         Print json_encode() result
+        --var-dump          var_dump() nodes (for exact structure)
+    -N, --resolve-names     Resolve names using NodeVisitor\NameResolver
+    -c, --with-column-info  Show column-numbers for errors (if available)
+    -P, --with-positions    Show positions in node dumps
+    -r, --with-recovery     Use parsing with error recovery
+    -h, --help              Display this page
+
+Example:
+    php-parse -d -p -N -d file.php
+
+    Dumps nodes, pretty prints them, then resolves names and dumps them again.
+
+
+OUTPUT
+    );
+    exit($error ? 1 : 0);
+}
+
+function parseArgs($args) {
+    $operations = [];
+    $files = [];
+    $attributes = [
+        'with-column-info' => false,
+        'with-positions' => false,
+        'with-recovery' => false,
+    ];
+
+    array_shift($args);
+    $parseOptions = true;
+    foreach ($args as $arg) {
+        if (!$parseOptions) {
+            $files[] = $arg;
+            continue;
+        }
+
+        switch ($arg) {
+            case '--dump':
+            case '-d':
+                $operations[] = 'dump';
+                break;
+            case '--pretty-print':
+            case '-p':
+                $operations[] = 'pretty-print';
+                break;
+            case '--json-dump':
+            case '-j':
+                $operations[] = 'json-dump';
+                break;
+            case '--var-dump':
+                $operations[] = 'var-dump';
+                break;
+            case '--resolve-names':
+            case '-N';
+                $operations[] = 'resolve-names';
+                break;
+            case '--with-column-info':
+            case '-c';
+                $attributes['with-column-info'] = true;
+                break;
+            case '--with-positions':
+            case '-P':
+                $attributes['with-positions'] = true;
+                break;
+            case '--with-recovery':
+            case '-r':
+                $attributes['with-recovery'] = true;
+                break;
+            case '--help':
+            case '-h';
+                showHelp();
+                break;
+            case '--':
+                $parseOptions = false;
+                break;
+            default:
+                if ($arg[0] === '-') {
+                    showHelp("Invalid operation $arg.");
+                } else {
+                    $files[] = $arg;
+                }
+        }
+    }
+
+    return [$operations, $files, $attributes];
+}
diff --git a/vendor/nikic/php-parser/composer.json b/vendor/nikic/php-parser/composer.json
new file mode 100644
index 0000000000000000000000000000000000000000..2fd064a21242490c5ac6129e9b19af4323e4b9d1
--- /dev/null
+++ b/vendor/nikic/php-parser/composer.json
@@ -0,0 +1,41 @@
+{
+    "name": "nikic/php-parser",
+    "type": "library",
+    "description": "A PHP parser written in PHP",
+    "keywords": [
+        "php",
+        "parser"
+    ],
+    "license": "BSD-3-Clause",
+    "authors": [
+        {
+            "name": "Nikita Popov"
+        }
+    ],
+    "require": {
+        "php": ">=7.0",
+        "ext-tokenizer": "*"
+    },
+    "require-dev": {
+        "phpunit/phpunit": "^6.5 || ^7.0 || ^8.0 || ^9.0",
+        "ircmaxell/php-yacc": "^0.0.7"
+    },
+    "extra": {
+        "branch-alias": {
+            "dev-master": "4.9-dev"
+        }
+    },
+    "autoload": {
+        "psr-4": {
+            "PhpParser\\": "lib/PhpParser"
+        }
+    },
+    "autoload-dev": {
+        "psr-4": {
+            "PhpParser\\": "test/PhpParser/"
+        }
+    },
+    "bin": [
+        "bin/php-parse"
+    ]
+}
diff --git a/vendor/nikic/php-parser/grammar/README.md b/vendor/nikic/php-parser/grammar/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..4bae11d8261cb1bf6462f5be54e22f1a7f099afa
--- /dev/null
+++ b/vendor/nikic/php-parser/grammar/README.md
@@ -0,0 +1,30 @@
+What do all those files mean?
+=============================
+
+ * `php5.y`:             PHP 5 grammar written in a pseudo language
+ * `php7.y`:             PHP 7 grammar written in a pseudo language
+ * `tokens.y`:           Tokens definition shared between PHP 5 and PHP 7 grammars
+ * `parser.template`:    A `kmyacc` parser prototype file for PHP
+ * `tokens.template`:    A `kmyacc` prototype file for the `Tokens` class
+ * `rebuildParsers.php`: Preprocesses the grammar and builds the parser using `kmyacc`
+
+.phpy pseudo language
+=====================
+
+The `.y` file is a normal grammar in `kmyacc` (`yacc`) style, with some transformations
+applied to it:
+
+ * Nodes are created using the syntax `Name[..., ...]`. This is transformed into
+   `new Name(..., ..., attributes())`
+ * Some function-like constructs are resolved (see `rebuildParsers.php` for a list)
+
+Building the parser
+===================
+
+Run `php grammar/rebuildParsers.php` to rebuild the parsers. Additional options:
+
+ * The `KMYACC` environment variable can be used to specify an alternative `kmyacc` binary.
+   By default the `phpyacc` dev dependency will be used. To use the original `kmyacc`, you
+   need to compile [moriyoshi's fork](https://github.com/moriyoshi/kmyacc-forked).
+ * The `--debug` option enables emission of debug symbols and creates the `y.output` file.
+ * The `--keep-tmp-grammar` option preserves the preprocessed grammar file.
diff --git a/vendor/nikic/php-parser/grammar/parser.template b/vendor/nikic/php-parser/grammar/parser.template
new file mode 100644
index 0000000000000000000000000000000000000000..6166607c9e4787be64704016fe0e009a21e51583
--- /dev/null
+++ b/vendor/nikic/php-parser/grammar/parser.template
@@ -0,0 +1,106 @@
+<?php
+$meta #
+#semval($) $this->semValue
+#semval($,%t) $this->semValue
+#semval(%n) $stackPos-(%l-%n)
+#semval(%n,%t) $stackPos-(%l-%n)
+
+namespace PhpParser\Parser;
+
+use PhpParser\Error;
+use PhpParser\Node;
+use PhpParser\Node\Expr;
+use PhpParser\Node\Name;
+use PhpParser\Node\Scalar;
+use PhpParser\Node\Stmt;
+#include;
+
+/* This is an automatically GENERATED file, which should not be manually edited.
+ * Instead edit one of the following:
+ *  * the grammar files grammar/php5.y or grammar/php7.y
+ *  * the skeleton file grammar/parser.template
+ *  * the preprocessing script grammar/rebuildParsers.php
+ */
+class #(-p) extends \PhpParser\ParserAbstract
+{
+    protected $tokenToSymbolMapSize = #(YYMAXLEX);
+    protected $actionTableSize = #(YYLAST);
+    protected $gotoTableSize = #(YYGLAST);
+
+    protected $invalidSymbol = #(YYBADCH);
+    protected $errorSymbol = #(YYINTERRTOK);
+    protected $defaultAction = #(YYDEFAULT);
+    protected $unexpectedTokenRule = #(YYUNEXPECTED);
+
+    protected $YY2TBLSTATE = #(YY2TBLSTATE);
+    protected $numNonLeafStates = #(YYNLSTATES);
+
+    protected $symbolToName = array(
+        #listvar terminals
+    );
+
+    protected $tokenToSymbol = array(
+        #listvar yytranslate
+    );
+
+    protected $action = array(
+        #listvar yyaction
+    );
+
+    protected $actionCheck = array(
+        #listvar yycheck
+    );
+
+    protected $actionBase = array(
+        #listvar yybase
+    );
+
+    protected $actionDefault = array(
+        #listvar yydefault
+    );
+
+    protected $goto = array(
+        #listvar yygoto
+    );
+
+    protected $gotoCheck = array(
+        #listvar yygcheck
+    );
+
+    protected $gotoBase = array(
+        #listvar yygbase
+    );
+
+    protected $gotoDefault = array(
+        #listvar yygdefault
+    );
+
+    protected $ruleToNonTerminal = array(
+        #listvar yylhs
+    );
+
+    protected $ruleToLength = array(
+        #listvar yylen
+    );
+#if -t
+
+    protected $productions = array(
+        #production-strings;
+    );
+#endif
+
+    protected function initReduceCallbacks() {
+        $this->reduceCallbacks = [
+#reduce
+            %n => function ($stackPos) {
+                %b
+            },
+#noact
+            %n => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+#endreduce
+        ];
+    }
+}
+#tailcode;
diff --git a/vendor/nikic/php-parser/grammar/php5.y b/vendor/nikic/php-parser/grammar/php5.y
new file mode 100644
index 0000000000000000000000000000000000000000..c7d245dc78f6b1c67f0e9739c376aa91953a5a84
--- /dev/null
+++ b/vendor/nikic/php-parser/grammar/php5.y
@@ -0,0 +1,1026 @@
+%pure_parser
+%expect 6
+
+%tokens
+
+%%
+
+start:
+    top_statement_list                                      { $$ = $this->handleNamespaces($1); }
+;
+
+top_statement_list_ex:
+      top_statement_list_ex top_statement                   { pushNormalizing($1, $2); }
+    | /* empty */                                           { init(); }
+;
+
+top_statement_list:
+      top_statement_list_ex
+          { makeZeroLengthNop($nop, $this->lookaheadStartAttributes);
+            if ($nop !== null) { $1[] = $nop; } $$ = $1; }
+;
+
+reserved_non_modifiers:
+      T_INCLUDE | T_INCLUDE_ONCE | T_EVAL | T_REQUIRE | T_REQUIRE_ONCE | T_LOGICAL_OR | T_LOGICAL_XOR | T_LOGICAL_AND
+    | T_INSTANCEOF | T_NEW | T_CLONE | T_EXIT | T_IF | T_ELSEIF | T_ELSE | T_ENDIF | T_ECHO | T_DO | T_WHILE
+    | T_ENDWHILE | T_FOR | T_ENDFOR | T_FOREACH | T_ENDFOREACH | T_DECLARE | T_ENDDECLARE | T_AS | T_TRY | T_CATCH
+    | T_FINALLY | T_THROW | T_USE | T_INSTEADOF | T_GLOBAL | T_VAR | T_UNSET | T_ISSET | T_EMPTY | T_CONTINUE | T_GOTO
+    | T_FUNCTION | T_CONST | T_RETURN | T_PRINT | T_YIELD | T_LIST | T_SWITCH | T_ENDSWITCH | T_CASE | T_DEFAULT
+    | T_BREAK | T_ARRAY | T_CALLABLE | T_EXTENDS | T_IMPLEMENTS | T_NAMESPACE | T_TRAIT | T_INTERFACE | T_CLASS
+    | T_CLASS_C | T_TRAIT_C | T_FUNC_C | T_METHOD_C | T_LINE | T_FILE | T_DIR | T_NS_C | T_HALT_COMPILER | T_FN
+    | T_MATCH
+;
+
+semi_reserved:
+      reserved_non_modifiers
+    | T_STATIC | T_ABSTRACT | T_FINAL | T_PRIVATE | T_PROTECTED | T_PUBLIC
+;
+
+identifier_ex:
+      T_STRING                                              { $$ = Node\Identifier[$1]; }
+    | semi_reserved                                         { $$ = Node\Identifier[$1]; }
+;
+
+identifier:
+      T_STRING                                              { $$ = Node\Identifier[$1]; }
+;
+
+reserved_non_modifiers_identifier:
+      reserved_non_modifiers                                { $$ = Node\Identifier[$1]; }
+;
+
+namespace_name:
+      T_STRING                                              { $$ = Name[$1]; }
+    | T_NAME_QUALIFIED                                      { $$ = Name[$1]; }
+;
+
+legacy_namespace_name:
+      namespace_name                                        { $$ = $1; }
+    | T_NAME_FULLY_QUALIFIED                                { $$ = Name[substr($1, 1)]; }
+;
+
+plain_variable:
+      T_VARIABLE                                            { $$ = Expr\Variable[parseVar($1)]; }
+;
+
+top_statement:
+      statement                                             { $$ = $1; }
+    | function_declaration_statement                        { $$ = $1; }
+    | class_declaration_statement                           { $$ = $1; }
+    | T_HALT_COMPILER
+          { $$ = Stmt\HaltCompiler[$this->lexer->handleHaltCompiler()]; }
+    | T_NAMESPACE namespace_name ';'
+          { $$ = Stmt\Namespace_[$2, null];
+            $$->setAttribute('kind', Stmt\Namespace_::KIND_SEMICOLON);
+            $this->checkNamespace($$); }
+    | T_NAMESPACE namespace_name '{' top_statement_list '}'
+          { $$ = Stmt\Namespace_[$2, $4];
+            $$->setAttribute('kind', Stmt\Namespace_::KIND_BRACED);
+            $this->checkNamespace($$); }
+    | T_NAMESPACE '{' top_statement_list '}'
+          { $$ = Stmt\Namespace_[null, $3];
+            $$->setAttribute('kind', Stmt\Namespace_::KIND_BRACED);
+            $this->checkNamespace($$); }
+    | T_USE use_declarations ';'                            { $$ = Stmt\Use_[$2, Stmt\Use_::TYPE_NORMAL]; }
+    | T_USE use_type use_declarations ';'                   { $$ = Stmt\Use_[$3, $2]; }
+    | group_use_declaration ';'                             { $$ = $1; }
+    | T_CONST constant_declaration_list ';'                 { $$ = Stmt\Const_[$2]; }
+;
+
+use_type:
+      T_FUNCTION                                            { $$ = Stmt\Use_::TYPE_FUNCTION; }
+    | T_CONST                                               { $$ = Stmt\Use_::TYPE_CONSTANT; }
+;
+
+group_use_declaration:
+      T_USE use_type legacy_namespace_name T_NS_SEPARATOR '{' unprefixed_use_declarations '}'
+          { $$ = Stmt\GroupUse[$3, $6, $2]; }
+    | T_USE legacy_namespace_name T_NS_SEPARATOR '{' inline_use_declarations '}'
+          { $$ = Stmt\GroupUse[$2, $5, Stmt\Use_::TYPE_UNKNOWN]; }
+;
+
+unprefixed_use_declarations:
+      unprefixed_use_declarations ',' unprefixed_use_declaration
+          { push($1, $3); }
+    | unprefixed_use_declaration                            { init($1); }
+;
+
+use_declarations:
+      use_declarations ',' use_declaration                  { push($1, $3); }
+    | use_declaration                                       { init($1); }
+;
+
+inline_use_declarations:
+      inline_use_declarations ',' inline_use_declaration    { push($1, $3); }
+    | inline_use_declaration                                { init($1); }
+;
+
+unprefixed_use_declaration:
+      namespace_name
+          { $$ = Stmt\UseUse[$1, null, Stmt\Use_::TYPE_UNKNOWN]; $this->checkUseUse($$, #1); }
+    | namespace_name T_AS identifier
+          { $$ = Stmt\UseUse[$1, $3, Stmt\Use_::TYPE_UNKNOWN]; $this->checkUseUse($$, #3); }
+;
+
+use_declaration:
+      legacy_namespace_name
+          { $$ = Stmt\UseUse[$1, null, Stmt\Use_::TYPE_UNKNOWN]; $this->checkUseUse($$, #1); }
+    | legacy_namespace_name T_AS identifier
+          { $$ = Stmt\UseUse[$1, $3, Stmt\Use_::TYPE_UNKNOWN]; $this->checkUseUse($$, #3); }
+;
+
+inline_use_declaration:
+      unprefixed_use_declaration                            { $$ = $1; $$->type = Stmt\Use_::TYPE_NORMAL; }
+    | use_type unprefixed_use_declaration                   { $$ = $2; $$->type = $1; }
+;
+
+constant_declaration_list:
+      constant_declaration_list ',' constant_declaration    { push($1, $3); }
+    | constant_declaration                                  { init($1); }
+;
+
+constant_declaration:
+    identifier '=' static_scalar                            { $$ = Node\Const_[$1, $3]; }
+;
+
+class_const_list:
+      class_const_list ',' class_const                      { push($1, $3); }
+    | class_const                                           { init($1); }
+;
+
+class_const:
+    identifier_ex '=' static_scalar                         { $$ = Node\Const_[$1, $3]; }
+;
+
+inner_statement_list_ex:
+      inner_statement_list_ex inner_statement               { pushNormalizing($1, $2); }
+    | /* empty */                                           { init(); }
+;
+
+inner_statement_list:
+      inner_statement_list_ex
+          { makeZeroLengthNop($nop, $this->lookaheadStartAttributes);
+            if ($nop !== null) { $1[] = $nop; } $$ = $1; }
+;
+
+inner_statement:
+      statement                                             { $$ = $1; }
+    | function_declaration_statement                        { $$ = $1; }
+    | class_declaration_statement                           { $$ = $1; }
+    | T_HALT_COMPILER
+          { throw new Error('__HALT_COMPILER() can only be used from the outermost scope', attributes()); }
+;
+
+non_empty_statement:
+      '{' inner_statement_list '}'
+    {
+        if ($2) {
+            $$ = $2; prependLeadingComments($$);
+        } else {
+            makeNop($$, $this->startAttributeStack[#1], $this->endAttributes);
+            if (null === $$) { $$ = array(); }
+        }
+    }
+    | T_IF parentheses_expr statement elseif_list else_single
+          { $$ = Stmt\If_[$2, ['stmts' => toArray($3), 'elseifs' => $4, 'else' => $5]]; }
+    | T_IF parentheses_expr ':' inner_statement_list new_elseif_list new_else_single T_ENDIF ';'
+          { $$ = Stmt\If_[$2, ['stmts' => $4, 'elseifs' => $5, 'else' => $6]]; }
+    | T_WHILE parentheses_expr while_statement              { $$ = Stmt\While_[$2, $3]; }
+    | T_DO statement T_WHILE parentheses_expr ';'           { $$ = Stmt\Do_   [$4, toArray($2)]; }
+    | T_FOR '(' for_expr ';'  for_expr ';' for_expr ')' for_statement
+          { $$ = Stmt\For_[['init' => $3, 'cond' => $5, 'loop' => $7, 'stmts' => $9]]; }
+    | T_SWITCH parentheses_expr switch_case_list            { $$ = Stmt\Switch_[$2, $3]; }
+    | T_BREAK ';'                                           { $$ = Stmt\Break_[null]; }
+    | T_BREAK expr ';'                                      { $$ = Stmt\Break_[$2]; }
+    | T_CONTINUE ';'                                        { $$ = Stmt\Continue_[null]; }
+    | T_CONTINUE expr ';'                                   { $$ = Stmt\Continue_[$2]; }
+    | T_RETURN ';'                                          { $$ = Stmt\Return_[null]; }
+    | T_RETURN expr ';'                                     { $$ = Stmt\Return_[$2]; }
+    | T_GLOBAL global_var_list ';'                          { $$ = Stmt\Global_[$2]; }
+    | T_STATIC static_var_list ';'                          { $$ = Stmt\Static_[$2]; }
+    | T_ECHO expr_list ';'                                  { $$ = Stmt\Echo_[$2]; }
+    | T_INLINE_HTML                                         { $$ = Stmt\InlineHTML[$1]; }
+    | yield_expr ';'                                        { $$ = Stmt\Expression[$1]; }
+    | expr ';'                                              { $$ = Stmt\Expression[$1]; }
+    | T_UNSET '(' variables_list ')' ';'                    { $$ = Stmt\Unset_[$3]; }
+    | T_FOREACH '(' expr T_AS foreach_variable ')' foreach_statement
+          { $$ = Stmt\Foreach_[$3, $5[0], ['keyVar' => null, 'byRef' => $5[1], 'stmts' => $7]]; }
+    | T_FOREACH '(' expr T_AS variable T_DOUBLE_ARROW foreach_variable ')' foreach_statement
+          { $$ = Stmt\Foreach_[$3, $7[0], ['keyVar' => $5, 'byRef' => $7[1], 'stmts' => $9]]; }
+    | T_DECLARE '(' declare_list ')' declare_statement      { $$ = Stmt\Declare_[$3, $5]; }
+    | T_TRY '{' inner_statement_list '}' catches optional_finally
+          { $$ = Stmt\TryCatch[$3, $5, $6]; $this->checkTryCatch($$); }
+    | T_THROW expr ';'                                      { $$ = Stmt\Throw_[$2]; }
+    | T_GOTO identifier ';'                                 { $$ = Stmt\Goto_[$2]; }
+    | identifier ':'                                        { $$ = Stmt\Label[$1]; }
+    | expr error                                            { $$ = Stmt\Expression[$1]; }
+    | error                                                 { $$ = array(); /* means: no statement */ }
+;
+
+statement:
+      non_empty_statement                                   { $$ = $1; }
+    | ';'
+          { makeNop($$, $this->startAttributeStack[#1], $this->endAttributes);
+            if ($$ === null) $$ = array(); /* means: no statement */ }
+;
+
+catches:
+      /* empty */                                           { init(); }
+    | catches catch                                         { push($1, $2); }
+;
+
+catch:
+    T_CATCH '(' name plain_variable ')' '{' inner_statement_list '}'
+        { $$ = Stmt\Catch_[array($3), $4, $7]; }
+;
+
+optional_finally:
+      /* empty */                                           { $$ = null; }
+    | T_FINALLY '{' inner_statement_list '}'                { $$ = Stmt\Finally_[$3]; }
+;
+
+variables_list:
+      variable                                              { init($1); }
+    | variables_list ',' variable                           { push($1, $3); }
+;
+
+optional_ref:
+      /* empty */                                           { $$ = false; }
+    | '&'                                                   { $$ = true; }
+;
+
+optional_ellipsis:
+      /* empty */                                           { $$ = false; }
+    | T_ELLIPSIS                                            { $$ = true; }
+;
+
+function_declaration_statement:
+    T_FUNCTION optional_ref identifier '(' parameter_list ')' optional_return_type '{' inner_statement_list '}'
+        { $$ = Stmt\Function_[$3, ['byRef' => $2, 'params' => $5, 'returnType' => $7, 'stmts' => $9]]; }
+;
+
+class_declaration_statement:
+      class_entry_type identifier extends_from implements_list '{' class_statement_list '}'
+          { $$ = Stmt\Class_[$2, ['type' => $1, 'extends' => $3, 'implements' => $4, 'stmts' => $6]];
+            $this->checkClass($$, #2); }
+    | T_INTERFACE identifier interface_extends_list '{' class_statement_list '}'
+          { $$ = Stmt\Interface_[$2, ['extends' => $3, 'stmts' => $5]];
+            $this->checkInterface($$, #2); }
+    | T_TRAIT identifier '{' class_statement_list '}'
+          { $$ = Stmt\Trait_[$2, ['stmts' => $4]]; }
+;
+
+class_entry_type:
+      T_CLASS                                               { $$ = 0; }
+    | T_ABSTRACT T_CLASS                                    { $$ = Stmt\Class_::MODIFIER_ABSTRACT; }
+    | T_FINAL T_CLASS                                       { $$ = Stmt\Class_::MODIFIER_FINAL; }
+;
+
+extends_from:
+      /* empty */                                           { $$ = null; }
+    | T_EXTENDS class_name                                  { $$ = $2; }
+;
+
+interface_extends_list:
+      /* empty */                                           { $$ = array(); }
+    | T_EXTENDS class_name_list                             { $$ = $2; }
+;
+
+implements_list:
+      /* empty */                                           { $$ = array(); }
+    | T_IMPLEMENTS class_name_list                          { $$ = $2; }
+;
+
+class_name_list:
+      class_name                                            { init($1); }
+    | class_name_list ',' class_name                        { push($1, $3); }
+;
+
+for_statement:
+      statement                                             { $$ = toArray($1); }
+    | ':' inner_statement_list T_ENDFOR ';'                 { $$ = $2; }
+;
+
+foreach_statement:
+      statement                                             { $$ = toArray($1); }
+    | ':' inner_statement_list T_ENDFOREACH ';'             { $$ = $2; }
+;
+
+declare_statement:
+      non_empty_statement                                   { $$ = toArray($1); }
+    | ';'                                                   { $$ = null; }
+    | ':' inner_statement_list T_ENDDECLARE ';'             { $$ = $2; }
+;
+
+declare_list:
+      declare_list_element                                  { init($1); }
+    | declare_list ',' declare_list_element                 { push($1, $3); }
+;
+
+declare_list_element:
+      identifier '=' static_scalar                          { $$ = Stmt\DeclareDeclare[$1, $3]; }
+;
+
+switch_case_list:
+      '{' case_list '}'                                     { $$ = $2; }
+    | '{' ';' case_list '}'                                 { $$ = $3; }
+    | ':' case_list T_ENDSWITCH ';'                         { $$ = $2; }
+    | ':' ';' case_list T_ENDSWITCH ';'                     { $$ = $3; }
+;
+
+case_list:
+      /* empty */                                           { init(); }
+    | case_list case                                        { push($1, $2); }
+;
+
+case:
+      T_CASE expr case_separator inner_statement_list_ex    { $$ = Stmt\Case_[$2, $4]; }
+    | T_DEFAULT case_separator inner_statement_list_ex      { $$ = Stmt\Case_[null, $3]; }
+;
+
+case_separator:
+      ':'
+    | ';'
+;
+
+while_statement:
+      statement                                             { $$ = toArray($1); }
+    | ':' inner_statement_list T_ENDWHILE ';'               { $$ = $2; }
+;
+
+elseif_list:
+      /* empty */                                           { init(); }
+    | elseif_list elseif                                    { push($1, $2); }
+;
+
+elseif:
+      T_ELSEIF parentheses_expr statement                   { $$ = Stmt\ElseIf_[$2, toArray($3)]; }
+;
+
+new_elseif_list:
+      /* empty */                                           { init(); }
+    | new_elseif_list new_elseif                            { push($1, $2); }
+;
+
+new_elseif:
+     T_ELSEIF parentheses_expr ':' inner_statement_list     { $$ = Stmt\ElseIf_[$2, $4]; }
+;
+
+else_single:
+      /* empty */                                           { $$ = null; }
+    | T_ELSE statement                                      { $$ = Stmt\Else_[toArray($2)]; }
+;
+
+new_else_single:
+      /* empty */                                           { $$ = null; }
+    | T_ELSE ':' inner_statement_list                       { $$ = Stmt\Else_[$3]; }
+;
+
+foreach_variable:
+      variable                                              { $$ = array($1, false); }
+    | '&' variable                                          { $$ = array($2, true); }
+    | list_expr                                             { $$ = array($1, false); }
+;
+
+parameter_list:
+      non_empty_parameter_list                              { $$ = $1; }
+    | /* empty */                                           { $$ = array(); }
+;
+
+non_empty_parameter_list:
+      parameter                                             { init($1); }
+    | non_empty_parameter_list ',' parameter                { push($1, $3); }
+;
+
+parameter:
+      optional_param_type optional_ref optional_ellipsis plain_variable
+          { $$ = Node\Param[$4, null, $1, $2, $3]; $this->checkParam($$); }
+    | optional_param_type optional_ref optional_ellipsis plain_variable '=' static_scalar
+          { $$ = Node\Param[$4, $6, $1, $2, $3]; $this->checkParam($$); }
+;
+
+type:
+      name                                                  { $$ = $1; }
+    | T_ARRAY                                               { $$ = Node\Identifier['array']; }
+    | T_CALLABLE                                            { $$ = Node\Identifier['callable']; }
+;
+
+optional_param_type:
+      /* empty */                                           { $$ = null; }
+    | type                                                  { $$ = $1; }
+;
+
+optional_return_type:
+      /* empty */                                           { $$ = null; }
+    | ':' type                                              { $$ = $2; }
+;
+
+argument_list:
+      '(' ')'                                               { $$ = array(); }
+    | '(' non_empty_argument_list ')'                       { $$ = $2; }
+    | '(' yield_expr ')'                                    { $$ = array(Node\Arg[$2, false, false]); }
+;
+
+non_empty_argument_list:
+      argument                                              { init($1); }
+    | non_empty_argument_list ',' argument                  { push($1, $3); }
+;
+
+argument:
+      expr                                                  { $$ = Node\Arg[$1, false, false]; }
+    | '&' variable                                          { $$ = Node\Arg[$2, true, false]; }
+    | T_ELLIPSIS expr                                       { $$ = Node\Arg[$2, false, true]; }
+;
+
+global_var_list:
+      global_var_list ',' global_var                        { push($1, $3); }
+    | global_var                                            { init($1); }
+;
+
+global_var:
+      plain_variable                                        { $$ = $1; }
+    | '$' variable                                          { $$ = Expr\Variable[$2]; }
+    | '$' '{' expr '}'                                      { $$ = Expr\Variable[$3]; }
+;
+
+static_var_list:
+      static_var_list ',' static_var                        { push($1, $3); }
+    | static_var                                            { init($1); }
+;
+
+static_var:
+      plain_variable                                        { $$ = Stmt\StaticVar[$1, null]; }
+    | plain_variable '=' static_scalar                      { $$ = Stmt\StaticVar[$1, $3]; }
+;
+
+class_statement_list_ex:
+      class_statement_list_ex class_statement               { if ($2 !== null) { push($1, $2); } }
+    | /* empty */                                           { init(); }
+;
+
+class_statement_list:
+      class_statement_list_ex
+          { makeZeroLengthNop($nop, $this->lookaheadStartAttributes);
+            if ($nop !== null) { $1[] = $nop; } $$ = $1; }
+;
+
+class_statement:
+      variable_modifiers property_declaration_list ';'
+          { $$ = Stmt\Property[$1, $2]; $this->checkProperty($$, #1); }
+    | T_CONST class_const_list ';'                          { $$ = Stmt\ClassConst[$2, 0]; }
+    | method_modifiers T_FUNCTION optional_ref identifier_ex '(' parameter_list ')' optional_return_type method_body
+          { $$ = Stmt\ClassMethod[$4, ['type' => $1, 'byRef' => $3, 'params' => $6, 'returnType' => $8, 'stmts' => $9]];
+            $this->checkClassMethod($$, #1); }
+    | T_USE class_name_list trait_adaptations               { $$ = Stmt\TraitUse[$2, $3]; }
+;
+
+trait_adaptations:
+      ';'                                                   { $$ = array(); }
+    | '{' trait_adaptation_list '}'                         { $$ = $2; }
+;
+
+trait_adaptation_list:
+      /* empty */                                           { init(); }
+    | trait_adaptation_list trait_adaptation                { push($1, $2); }
+;
+
+trait_adaptation:
+      trait_method_reference_fully_qualified T_INSTEADOF class_name_list ';'
+          { $$ = Stmt\TraitUseAdaptation\Precedence[$1[0], $1[1], $3]; }
+    | trait_method_reference T_AS member_modifier identifier_ex ';'
+          { $$ = Stmt\TraitUseAdaptation\Alias[$1[0], $1[1], $3, $4]; }
+    | trait_method_reference T_AS member_modifier ';'
+          { $$ = Stmt\TraitUseAdaptation\Alias[$1[0], $1[1], $3, null]; }
+    | trait_method_reference T_AS identifier ';'
+          { $$ = Stmt\TraitUseAdaptation\Alias[$1[0], $1[1], null, $3]; }
+    | trait_method_reference T_AS reserved_non_modifiers_identifier ';'
+          { $$ = Stmt\TraitUseAdaptation\Alias[$1[0], $1[1], null, $3]; }
+;
+
+trait_method_reference_fully_qualified:
+      name T_PAAMAYIM_NEKUDOTAYIM identifier_ex             { $$ = array($1, $3); }
+;
+trait_method_reference:
+      trait_method_reference_fully_qualified                { $$ = $1; }
+    | identifier_ex                                         { $$ = array(null, $1); }
+;
+
+method_body:
+      ';' /* abstract method */                             { $$ = null; }
+    | '{' inner_statement_list '}'                          { $$ = $2; }
+;
+
+variable_modifiers:
+      non_empty_member_modifiers                            { $$ = $1; }
+    | T_VAR                                                 { $$ = 0; }
+;
+
+method_modifiers:
+      /* empty */                                           { $$ = 0; }
+    | non_empty_member_modifiers                            { $$ = $1; }
+;
+
+non_empty_member_modifiers:
+      member_modifier                                       { $$ = $1; }
+    | non_empty_member_modifiers member_modifier            { $this->checkModifier($1, $2, #2); $$ = $1 | $2; }
+;
+
+member_modifier:
+      T_PUBLIC                                              { $$ = Stmt\Class_::MODIFIER_PUBLIC; }
+    | T_PROTECTED                                           { $$ = Stmt\Class_::MODIFIER_PROTECTED; }
+    | T_PRIVATE                                             { $$ = Stmt\Class_::MODIFIER_PRIVATE; }
+    | T_STATIC                                              { $$ = Stmt\Class_::MODIFIER_STATIC; }
+    | T_ABSTRACT                                            { $$ = Stmt\Class_::MODIFIER_ABSTRACT; }
+    | T_FINAL                                               { $$ = Stmt\Class_::MODIFIER_FINAL; }
+;
+
+property_declaration_list:
+      property_declaration                                  { init($1); }
+    | property_declaration_list ',' property_declaration    { push($1, $3); }
+;
+
+property_decl_name:
+      T_VARIABLE                                            { $$ = Node\VarLikeIdentifier[parseVar($1)]; }
+;
+
+property_declaration:
+      property_decl_name                                    { $$ = Stmt\PropertyProperty[$1, null]; }
+    | property_decl_name '=' static_scalar                  { $$ = Stmt\PropertyProperty[$1, $3]; }
+;
+
+expr_list:
+      expr_list ',' expr                                    { push($1, $3); }
+    | expr                                                  { init($1); }
+;
+
+for_expr:
+      /* empty */                                           { $$ = array(); }
+    | expr_list                                             { $$ = $1; }
+;
+
+expr:
+      variable                                              { $$ = $1; }
+    | list_expr '=' expr                                    { $$ = Expr\Assign[$1, $3]; }
+    | variable '=' expr                                     { $$ = Expr\Assign[$1, $3]; }
+    | variable '=' '&' variable                             { $$ = Expr\AssignRef[$1, $4]; }
+    | variable '=' '&' new_expr                             { $$ = Expr\AssignRef[$1, $4]; }
+    | new_expr                                              { $$ = $1; }
+    | T_CLONE expr                                          { $$ = Expr\Clone_[$2]; }
+    | variable T_PLUS_EQUAL expr                            { $$ = Expr\AssignOp\Plus      [$1, $3]; }
+    | variable T_MINUS_EQUAL expr                           { $$ = Expr\AssignOp\Minus     [$1, $3]; }
+    | variable T_MUL_EQUAL expr                             { $$ = Expr\AssignOp\Mul       [$1, $3]; }
+    | variable T_DIV_EQUAL expr                             { $$ = Expr\AssignOp\Div       [$1, $3]; }
+    | variable T_CONCAT_EQUAL expr                          { $$ = Expr\AssignOp\Concat    [$1, $3]; }
+    | variable T_MOD_EQUAL expr                             { $$ = Expr\AssignOp\Mod       [$1, $3]; }
+    | variable T_AND_EQUAL expr                             { $$ = Expr\AssignOp\BitwiseAnd[$1, $3]; }
+    | variable T_OR_EQUAL expr                              { $$ = Expr\AssignOp\BitwiseOr [$1, $3]; }
+    | variable T_XOR_EQUAL expr                             { $$ = Expr\AssignOp\BitwiseXor[$1, $3]; }
+    | variable T_SL_EQUAL expr                              { $$ = Expr\AssignOp\ShiftLeft [$1, $3]; }
+    | variable T_SR_EQUAL expr                              { $$ = Expr\AssignOp\ShiftRight[$1, $3]; }
+    | variable T_POW_EQUAL expr                             { $$ = Expr\AssignOp\Pow       [$1, $3]; }
+    | variable T_COALESCE_EQUAL expr                        { $$ = Expr\AssignOp\Coalesce  [$1, $3]; }
+    | variable T_INC                                        { $$ = Expr\PostInc[$1]; }
+    | T_INC variable                                        { $$ = Expr\PreInc [$2]; }
+    | variable T_DEC                                        { $$ = Expr\PostDec[$1]; }
+    | T_DEC variable                                        { $$ = Expr\PreDec [$2]; }
+    | expr T_BOOLEAN_OR expr                                { $$ = Expr\BinaryOp\BooleanOr [$1, $3]; }
+    | expr T_BOOLEAN_AND expr                               { $$ = Expr\BinaryOp\BooleanAnd[$1, $3]; }
+    | expr T_LOGICAL_OR expr                                { $$ = Expr\BinaryOp\LogicalOr [$1, $3]; }
+    | expr T_LOGICAL_AND expr                               { $$ = Expr\BinaryOp\LogicalAnd[$1, $3]; }
+    | expr T_LOGICAL_XOR expr                               { $$ = Expr\BinaryOp\LogicalXor[$1, $3]; }
+    | expr '|' expr                                         { $$ = Expr\BinaryOp\BitwiseOr [$1, $3]; }
+    | expr '&' expr                                         { $$ = Expr\BinaryOp\BitwiseAnd[$1, $3]; }
+    | expr '^' expr                                         { $$ = Expr\BinaryOp\BitwiseXor[$1, $3]; }
+    | expr '.' expr                                         { $$ = Expr\BinaryOp\Concat    [$1, $3]; }
+    | expr '+' expr                                         { $$ = Expr\BinaryOp\Plus      [$1, $3]; }
+    | expr '-' expr                                         { $$ = Expr\BinaryOp\Minus     [$1, $3]; }
+    | expr '*' expr                                         { $$ = Expr\BinaryOp\Mul       [$1, $3]; }
+    | expr '/' expr                                         { $$ = Expr\BinaryOp\Div       [$1, $3]; }
+    | expr '%' expr                                         { $$ = Expr\BinaryOp\Mod       [$1, $3]; }
+    | expr T_SL expr                                        { $$ = Expr\BinaryOp\ShiftLeft [$1, $3]; }
+    | expr T_SR expr                                        { $$ = Expr\BinaryOp\ShiftRight[$1, $3]; }
+    | expr T_POW expr                                       { $$ = Expr\BinaryOp\Pow       [$1, $3]; }
+    | '+' expr %prec T_INC                                  { $$ = Expr\UnaryPlus [$2]; }
+    | '-' expr %prec T_INC                                  { $$ = Expr\UnaryMinus[$2]; }
+    | '!' expr                                              { $$ = Expr\BooleanNot[$2]; }
+    | '~' expr                                              { $$ = Expr\BitwiseNot[$2]; }
+    | expr T_IS_IDENTICAL expr                              { $$ = Expr\BinaryOp\Identical     [$1, $3]; }
+    | expr T_IS_NOT_IDENTICAL expr                          { $$ = Expr\BinaryOp\NotIdentical  [$1, $3]; }
+    | expr T_IS_EQUAL expr                                  { $$ = Expr\BinaryOp\Equal         [$1, $3]; }
+    | expr T_IS_NOT_EQUAL expr                              { $$ = Expr\BinaryOp\NotEqual      [$1, $3]; }
+    | expr T_SPACESHIP expr                                 { $$ = Expr\BinaryOp\Spaceship     [$1, $3]; }
+    | expr '<' expr                                         { $$ = Expr\BinaryOp\Smaller       [$1, $3]; }
+    | expr T_IS_SMALLER_OR_EQUAL expr                       { $$ = Expr\BinaryOp\SmallerOrEqual[$1, $3]; }
+    | expr '>' expr                                         { $$ = Expr\BinaryOp\Greater       [$1, $3]; }
+    | expr T_IS_GREATER_OR_EQUAL expr                       { $$ = Expr\BinaryOp\GreaterOrEqual[$1, $3]; }
+    | expr T_INSTANCEOF class_name_reference                { $$ = Expr\Instanceof_[$1, $3]; }
+    | parentheses_expr                                      { $$ = $1; }
+    /* we need a separate '(' new_expr ')' rule to avoid problems caused by a s/r conflict */
+    | '(' new_expr ')'                                      { $$ = $2; }
+    | expr '?' expr ':' expr                                { $$ = Expr\Ternary[$1, $3,   $5]; }
+    | expr '?' ':' expr                                     { $$ = Expr\Ternary[$1, null, $4]; }
+    | expr T_COALESCE expr                                  { $$ = Expr\BinaryOp\Coalesce[$1, $3]; }
+    | T_ISSET '(' variables_list ')'                        { $$ = Expr\Isset_[$3]; }
+    | T_EMPTY '(' expr ')'                                  { $$ = Expr\Empty_[$3]; }
+    | T_INCLUDE expr                                        { $$ = Expr\Include_[$2, Expr\Include_::TYPE_INCLUDE]; }
+    | T_INCLUDE_ONCE expr                                   { $$ = Expr\Include_[$2, Expr\Include_::TYPE_INCLUDE_ONCE]; }
+    | T_EVAL parentheses_expr                               { $$ = Expr\Eval_[$2]; }
+    | T_REQUIRE expr                                        { $$ = Expr\Include_[$2, Expr\Include_::TYPE_REQUIRE]; }
+    | T_REQUIRE_ONCE expr                                   { $$ = Expr\Include_[$2, Expr\Include_::TYPE_REQUIRE_ONCE]; }
+    | T_INT_CAST expr                                       { $$ = Expr\Cast\Int_    [$2]; }
+    | T_DOUBLE_CAST expr
+          { $attrs = attributes();
+            $attrs['kind'] = $this->getFloatCastKind($1);
+            $$ = new Expr\Cast\Double($2, $attrs); }
+    | T_STRING_CAST expr                                    { $$ = Expr\Cast\String_ [$2]; }
+    | T_ARRAY_CAST expr                                     { $$ = Expr\Cast\Array_  [$2]; }
+    | T_OBJECT_CAST expr                                    { $$ = Expr\Cast\Object_ [$2]; }
+    | T_BOOL_CAST expr                                      { $$ = Expr\Cast\Bool_   [$2]; }
+    | T_UNSET_CAST expr                                     { $$ = Expr\Cast\Unset_  [$2]; }
+    | T_EXIT exit_expr
+          { $attrs = attributes();
+            $attrs['kind'] = strtolower($1) === 'exit' ? Expr\Exit_::KIND_EXIT : Expr\Exit_::KIND_DIE;
+            $$ = new Expr\Exit_($2, $attrs); }
+    | '@' expr                                              { $$ = Expr\ErrorSuppress[$2]; }
+    | scalar                                                { $$ = $1; }
+    | array_expr                                            { $$ = $1; }
+    | scalar_dereference                                    { $$ = $1; }
+    | '`' backticks_expr '`'                                { $$ = Expr\ShellExec[$2]; }
+    | T_PRINT expr                                          { $$ = Expr\Print_[$2]; }
+    | T_YIELD                                               { $$ = Expr\Yield_[null, null]; }
+    | T_YIELD_FROM expr                                     { $$ = Expr\YieldFrom[$2]; }
+    | T_FUNCTION optional_ref '(' parameter_list ')' lexical_vars optional_return_type
+      '{' inner_statement_list '}'
+          { $$ = Expr\Closure[['static' => false, 'byRef' => $2, 'params' => $4, 'uses' => $6, 'returnType' => $7, 'stmts' => $9]]; }
+    | T_STATIC T_FUNCTION optional_ref '(' parameter_list ')' lexical_vars optional_return_type
+      '{' inner_statement_list '}'
+          { $$ = Expr\Closure[['static' => true, 'byRef' => $3, 'params' => $5, 'uses' => $7, 'returnType' => $8, 'stmts' => $10]]; }
+;
+
+parentheses_expr:
+      '(' expr ')'                                          { $$ = $2; }
+    | '(' yield_expr ')'                                    { $$ = $2; }
+;
+
+yield_expr:
+      T_YIELD expr                                          { $$ = Expr\Yield_[$2, null]; }
+    | T_YIELD expr T_DOUBLE_ARROW expr                      { $$ = Expr\Yield_[$4, $2]; }
+;
+
+array_expr:
+      T_ARRAY '(' array_pair_list ')'
+          { $attrs = attributes(); $attrs['kind'] = Expr\Array_::KIND_LONG;
+            $$ = new Expr\Array_($3, $attrs); }
+    | '[' array_pair_list ']'
+          { $attrs = attributes(); $attrs['kind'] = Expr\Array_::KIND_SHORT;
+            $$ = new Expr\Array_($2, $attrs); }
+;
+
+scalar_dereference:
+      array_expr '[' dim_offset ']'                         { $$ = Expr\ArrayDimFetch[$1, $3]; }
+    | T_CONSTANT_ENCAPSED_STRING '[' dim_offset ']'
+          { $attrs = attributes(); $attrs['kind'] = strKind($1);
+            $$ = Expr\ArrayDimFetch[new Scalar\String_(Scalar\String_::parse($1), $attrs), $3]; }
+    | constant '[' dim_offset ']'                           { $$ = Expr\ArrayDimFetch[$1, $3]; }
+    | scalar_dereference '[' dim_offset ']'                 { $$ = Expr\ArrayDimFetch[$1, $3]; }
+    /* alternative array syntax missing intentionally */
+;
+
+anonymous_class:
+      T_CLASS ctor_arguments extends_from implements_list '{' class_statement_list '}'
+          { $$ = array(Stmt\Class_[null, ['type' => 0, 'extends' => $3, 'implements' => $4, 'stmts' => $6]], $2);
+            $this->checkClass($$[0], -1); }
+;
+
+new_expr:
+      T_NEW class_name_reference ctor_arguments             { $$ = Expr\New_[$2, $3]; }
+    | T_NEW anonymous_class
+          { list($class, $ctorArgs) = $2; $$ = Expr\New_[$class, $ctorArgs]; }
+;
+
+lexical_vars:
+      /* empty */                                           { $$ = array(); }
+    | T_USE '(' lexical_var_list ')'                        { $$ = $3; }
+;
+
+lexical_var_list:
+      lexical_var                                           { init($1); }
+    | lexical_var_list ',' lexical_var                      { push($1, $3); }
+;
+
+lexical_var:
+      optional_ref plain_variable                           { $$ = Expr\ClosureUse[$2, $1]; }
+;
+
+function_call:
+      name argument_list                                    { $$ = Expr\FuncCall[$1, $2]; }
+    | class_name_or_var T_PAAMAYIM_NEKUDOTAYIM identifier_ex argument_list
+          { $$ = Expr\StaticCall[$1, $3, $4]; }
+    | class_name_or_var T_PAAMAYIM_NEKUDOTAYIM '{' expr '}' argument_list
+          { $$ = Expr\StaticCall[$1, $4, $6]; }
+    | static_property argument_list
+          { $$ = $this->fixupPhp5StaticPropCall($1, $2, attributes()); }
+    | variable_without_objects argument_list
+          { $$ = Expr\FuncCall[$1, $2]; }
+    | function_call '[' dim_offset ']'                      { $$ = Expr\ArrayDimFetch[$1, $3]; }
+      /* alternative array syntax missing intentionally */
+;
+
+class_name:
+      T_STATIC                                              { $$ = Name[$1]; }
+    | name                                                  { $$ = $1; }
+;
+
+name:
+      T_STRING                                              { $$ = Name[$1]; }
+    | T_NAME_QUALIFIED                                      { $$ = Name[$1]; }
+    | T_NAME_FULLY_QUALIFIED                                { $$ = Name\FullyQualified[substr($1, 1)]; }
+    | T_NAME_RELATIVE                                       { $$ = Name\Relative[substr($1, 10)]; }
+;
+
+class_name_reference:
+      class_name                                            { $$ = $1; }
+    | dynamic_class_name_reference                          { $$ = $1; }
+;
+
+dynamic_class_name_reference:
+      object_access_for_dcnr                                { $$ = $1; }
+    | base_variable                                         { $$ = $1; }
+;
+
+class_name_or_var:
+      class_name                                            { $$ = $1; }
+    | reference_variable                                    { $$ = $1; }
+;
+
+object_access_for_dcnr:
+      base_variable T_OBJECT_OPERATOR object_property
+          { $$ = Expr\PropertyFetch[$1, $3]; }
+    | object_access_for_dcnr T_OBJECT_OPERATOR object_property
+          { $$ = Expr\PropertyFetch[$1, $3]; }
+    | object_access_for_dcnr '[' dim_offset ']'             { $$ = Expr\ArrayDimFetch[$1, $3]; }
+    | object_access_for_dcnr '{' expr '}'                   { $$ = Expr\ArrayDimFetch[$1, $3]; }
+;
+
+exit_expr:
+      /* empty */                                           { $$ = null; }
+    | '(' ')'                                               { $$ = null; }
+    | parentheses_expr                                      { $$ = $1; }
+;
+
+backticks_expr:
+      /* empty */                                           { $$ = array(); }
+    | T_ENCAPSED_AND_WHITESPACE
+          { $$ = array(Scalar\EncapsedStringPart[Scalar\String_::parseEscapeSequences($1, '`', false)]); }
+    | encaps_list                                           { parseEncapsed($1, '`', false); $$ = $1; }
+;
+
+ctor_arguments:
+      /* empty */                                           { $$ = array(); }
+    | argument_list                                         { $$ = $1; }
+;
+
+common_scalar:
+      T_LNUMBER                                             { $$ = $this->parseLNumber($1, attributes(), true); }
+    | T_DNUMBER                                             { $$ = Scalar\DNumber[Scalar\DNumber::parse($1)]; }
+    | T_CONSTANT_ENCAPSED_STRING
+          { $attrs = attributes(); $attrs['kind'] = strKind($1);
+            $$ = new Scalar\String_(Scalar\String_::parse($1, false), $attrs); }
+    | T_LINE                                                { $$ = Scalar\MagicConst\Line[]; }
+    | T_FILE                                                { $$ = Scalar\MagicConst\File[]; }
+    | T_DIR                                                 { $$ = Scalar\MagicConst\Dir[]; }
+    | T_CLASS_C                                             { $$ = Scalar\MagicConst\Class_[]; }
+    | T_TRAIT_C                                             { $$ = Scalar\MagicConst\Trait_[]; }
+    | T_METHOD_C                                            { $$ = Scalar\MagicConst\Method[]; }
+    | T_FUNC_C                                              { $$ = Scalar\MagicConst\Function_[]; }
+    | T_NS_C                                                { $$ = Scalar\MagicConst\Namespace_[]; }
+    | T_START_HEREDOC T_ENCAPSED_AND_WHITESPACE T_END_HEREDOC
+          { $$ = $this->parseDocString($1, $2, $3, attributes(), stackAttributes(#3), false); }
+    | T_START_HEREDOC T_END_HEREDOC
+          { $$ = $this->parseDocString($1, '', $2, attributes(), stackAttributes(#2), false); }
+;
+
+static_scalar:
+      common_scalar                                         { $$ = $1; }
+    | class_name T_PAAMAYIM_NEKUDOTAYIM identifier_ex       { $$ = Expr\ClassConstFetch[$1, $3]; }
+    | name                                                  { $$ = Expr\ConstFetch[$1]; }
+    | T_ARRAY '(' static_array_pair_list ')'                { $$ = Expr\Array_[$3]; }
+    | '[' static_array_pair_list ']'                        { $$ = Expr\Array_[$2]; }
+    | static_operation                                      { $$ = $1; }
+;
+
+static_operation:
+      static_scalar T_BOOLEAN_OR static_scalar              { $$ = Expr\BinaryOp\BooleanOr [$1, $3]; }
+    | static_scalar T_BOOLEAN_AND static_scalar             { $$ = Expr\BinaryOp\BooleanAnd[$1, $3]; }
+    | static_scalar T_LOGICAL_OR static_scalar              { $$ = Expr\BinaryOp\LogicalOr [$1, $3]; }
+    | static_scalar T_LOGICAL_AND static_scalar             { $$ = Expr\BinaryOp\LogicalAnd[$1, $3]; }
+    | static_scalar T_LOGICAL_XOR static_scalar             { $$ = Expr\BinaryOp\LogicalXor[$1, $3]; }
+    | static_scalar '|' static_scalar                       { $$ = Expr\BinaryOp\BitwiseOr [$1, $3]; }
+    | static_scalar '&' static_scalar                       { $$ = Expr\BinaryOp\BitwiseAnd[$1, $3]; }
+    | static_scalar '^' static_scalar                       { $$ = Expr\BinaryOp\BitwiseXor[$1, $3]; }
+    | static_scalar '.' static_scalar                       { $$ = Expr\BinaryOp\Concat    [$1, $3]; }
+    | static_scalar '+' static_scalar                       { $$ = Expr\BinaryOp\Plus      [$1, $3]; }
+    | static_scalar '-' static_scalar                       { $$ = Expr\BinaryOp\Minus     [$1, $3]; }
+    | static_scalar '*' static_scalar                       { $$ = Expr\BinaryOp\Mul       [$1, $3]; }
+    | static_scalar '/' static_scalar                       { $$ = Expr\BinaryOp\Div       [$1, $3]; }
+    | static_scalar '%' static_scalar                       { $$ = Expr\BinaryOp\Mod       [$1, $3]; }
+    | static_scalar T_SL static_scalar                      { $$ = Expr\BinaryOp\ShiftLeft [$1, $3]; }
+    | static_scalar T_SR static_scalar                      { $$ = Expr\BinaryOp\ShiftRight[$1, $3]; }
+    | static_scalar T_POW static_scalar                     { $$ = Expr\BinaryOp\Pow       [$1, $3]; }
+    | '+' static_scalar %prec T_INC                         { $$ = Expr\UnaryPlus [$2]; }
+    | '-' static_scalar %prec T_INC                         { $$ = Expr\UnaryMinus[$2]; }
+    | '!' static_scalar                                     { $$ = Expr\BooleanNot[$2]; }
+    | '~' static_scalar                                     { $$ = Expr\BitwiseNot[$2]; }
+    | static_scalar T_IS_IDENTICAL static_scalar            { $$ = Expr\BinaryOp\Identical     [$1, $3]; }
+    | static_scalar T_IS_NOT_IDENTICAL static_scalar        { $$ = Expr\BinaryOp\NotIdentical  [$1, $3]; }
+    | static_scalar T_IS_EQUAL static_scalar                { $$ = Expr\BinaryOp\Equal         [$1, $3]; }
+    | static_scalar T_IS_NOT_EQUAL static_scalar            { $$ = Expr\BinaryOp\NotEqual      [$1, $3]; }
+    | static_scalar '<' static_scalar                       { $$ = Expr\BinaryOp\Smaller       [$1, $3]; }
+    | static_scalar T_IS_SMALLER_OR_EQUAL static_scalar     { $$ = Expr\BinaryOp\SmallerOrEqual[$1, $3]; }
+    | static_scalar '>' static_scalar                       { $$ = Expr\BinaryOp\Greater       [$1, $3]; }
+    | static_scalar T_IS_GREATER_OR_EQUAL static_scalar     { $$ = Expr\BinaryOp\GreaterOrEqual[$1, $3]; }
+    | static_scalar '?' static_scalar ':' static_scalar     { $$ = Expr\Ternary[$1, $3,   $5]; }
+    | static_scalar '?' ':' static_scalar                   { $$ = Expr\Ternary[$1, null, $4]; }
+    | static_scalar '[' static_scalar ']'                   { $$ = Expr\ArrayDimFetch[$1, $3]; }
+    | '(' static_scalar ')'                                 { $$ = $2; }
+;
+
+constant:
+      name                                                  { $$ = Expr\ConstFetch[$1]; }
+    | class_name_or_var T_PAAMAYIM_NEKUDOTAYIM identifier_ex
+          { $$ = Expr\ClassConstFetch[$1, $3]; }
+;
+
+scalar:
+      common_scalar                                         { $$ = $1; }
+    | constant                                              { $$ = $1; }
+    | '"' encaps_list '"'
+          { $attrs = attributes(); $attrs['kind'] = Scalar\String_::KIND_DOUBLE_QUOTED;
+            parseEncapsed($2, '"', true); $$ = new Scalar\Encapsed($2, $attrs); }
+    | T_START_HEREDOC encaps_list T_END_HEREDOC
+          { $$ = $this->parseDocString($1, $2, $3, attributes(), stackAttributes(#3), true); }
+;
+
+static_array_pair_list:
+      /* empty */                                           { $$ = array(); }
+    | non_empty_static_array_pair_list optional_comma       { $$ = $1; }
+;
+
+optional_comma:
+      /* empty */
+    | ','
+;
+
+non_empty_static_array_pair_list:
+      non_empty_static_array_pair_list ',' static_array_pair { push($1, $3); }
+    | static_array_pair                                      { init($1); }
+;
+
+static_array_pair:
+      static_scalar T_DOUBLE_ARROW static_scalar            { $$ = Expr\ArrayItem[$3, $1,   false]; }
+    | static_scalar                                         { $$ = Expr\ArrayItem[$1, null, false]; }
+;
+
+variable:
+      object_access                                         { $$ = $1; }
+    | base_variable                                         { $$ = $1; }
+    | function_call                                         { $$ = $1; }
+    | new_expr_array_deref                                  { $$ = $1; }
+;
+
+new_expr_array_deref:
+      '(' new_expr ')' '[' dim_offset ']'                   { $$ = Expr\ArrayDimFetch[$2, $5]; }
+    | new_expr_array_deref '[' dim_offset ']'               { $$ = Expr\ArrayDimFetch[$1, $3]; }
+      /* alternative array syntax missing intentionally */
+;
+
+object_access:
+      variable_or_new_expr T_OBJECT_OPERATOR object_property
+          { $$ = Expr\PropertyFetch[$1, $3]; }
+    | variable_or_new_expr T_OBJECT_OPERATOR object_property argument_list
+          { $$ = Expr\MethodCall[$1, $3, $4]; }
+    | object_access argument_list                           { $$ = Expr\FuncCall[$1, $2]; }
+    | object_access '[' dim_offset ']'                      { $$ = Expr\ArrayDimFetch[$1, $3]; }
+    | object_access '{' expr '}'                            { $$ = Expr\ArrayDimFetch[$1, $3]; }
+;
+
+variable_or_new_expr:
+      variable                                              { $$ = $1; }
+    | '(' new_expr ')'                                      { $$ = $2; }
+;
+
+variable_without_objects:
+      reference_variable                                    { $$ = $1; }
+    | '$' variable_without_objects                          { $$ = Expr\Variable[$2]; }
+;
+
+base_variable:
+      variable_without_objects                              { $$ = $1; }
+    | static_property                                       { $$ = $1; }
+;
+
+static_property:
+      class_name_or_var T_PAAMAYIM_NEKUDOTAYIM '$' reference_variable
+          { $$ = Expr\StaticPropertyFetch[$1, $4]; }
+    | static_property_with_arrays                           { $$ = $1; }
+;
+
+static_property_simple_name:
+      T_VARIABLE
+          { $var = parseVar($1); $$ = \is_string($var) ? Node\VarLikeIdentifier[$var] : $var; }
+;
+
+static_property_with_arrays:
+      class_name_or_var T_PAAMAYIM_NEKUDOTAYIM static_property_simple_name
+          { $$ = Expr\StaticPropertyFetch[$1, $3]; }
+    | class_name_or_var T_PAAMAYIM_NEKUDOTAYIM '$' '{' expr '}'
+          { $$ = Expr\StaticPropertyFetch[$1, $5]; }
+    | static_property_with_arrays '[' dim_offset ']'        { $$ = Expr\ArrayDimFetch[$1, $3]; }
+    | static_property_with_arrays '{' expr '}'              { $$ = Expr\ArrayDimFetch[$1, $3]; }
+;
+
+reference_variable:
+      reference_variable '[' dim_offset ']'                 { $$ = Expr\ArrayDimFetch[$1, $3]; }
+    | reference_variable '{' expr '}'                       { $$ = Expr\ArrayDimFetch[$1, $3]; }
+    | plain_variable                                        { $$ = $1; }
+    | '$' '{' expr '}'                                      { $$ = Expr\Variable[$3]; }
+;
+
+dim_offset:
+      /* empty */                                           { $$ = null; }
+    | expr                                                  { $$ = $1; }
+;
+
+object_property:
+      identifier                                            { $$ = $1; }
+    | '{' expr '}'                                          { $$ = $2; }
+    | variable_without_objects                              { $$ = $1; }
+    | error                                                 { $$ = Expr\Error[]; $this->errorState = 2; }
+;
+
+list_expr:
+      T_LIST '(' list_expr_elements ')'                     { $$ = Expr\List_[$3]; }
+;
+
+list_expr_elements:
+      list_expr_elements ',' list_expr_element              { push($1, $3); }
+    | list_expr_element                                     { init($1); }
+;
+
+list_expr_element:
+      variable                                              { $$ = Expr\ArrayItem[$1, null, false]; }
+    | list_expr                                             { $$ = Expr\ArrayItem[$1, null, false]; }
+    | /* empty */                                           { $$ = null; }
+;
+
+array_pair_list:
+      /* empty */                                           { $$ = array(); }
+    | non_empty_array_pair_list optional_comma              { $$ = $1; }
+;
+
+non_empty_array_pair_list:
+      non_empty_array_pair_list ',' array_pair              { push($1, $3); }
+    | array_pair                                            { init($1); }
+;
+
+array_pair:
+      expr T_DOUBLE_ARROW expr                              { $$ = Expr\ArrayItem[$3, $1,   false]; }
+    | expr                                                  { $$ = Expr\ArrayItem[$1, null, false]; }
+    | expr T_DOUBLE_ARROW '&' variable                      { $$ = Expr\ArrayItem[$4, $1,   true]; }
+    | '&' variable                                          { $$ = Expr\ArrayItem[$2, null, true]; }
+    | T_ELLIPSIS expr                                       { $$ = Expr\ArrayItem[$2, null, false, attributes(), true]; }
+;
+
+encaps_list:
+      encaps_list encaps_var                                { push($1, $2); }
+    | encaps_list encaps_string_part                        { push($1, $2); }
+    | encaps_var                                            { init($1); }
+    | encaps_string_part encaps_var                         { init($1, $2); }
+;
+
+encaps_string_part:
+      T_ENCAPSED_AND_WHITESPACE                             { $$ = Scalar\EncapsedStringPart[$1]; }
+;
+
+encaps_str_varname:
+      T_STRING_VARNAME                                      { $$ = Expr\Variable[$1]; }
+;
+
+encaps_var:
+      plain_variable                                        { $$ = $1; }
+    | plain_variable '[' encaps_var_offset ']'              { $$ = Expr\ArrayDimFetch[$1, $3]; }
+    | plain_variable T_OBJECT_OPERATOR identifier           { $$ = Expr\PropertyFetch[$1, $3]; }
+    | T_DOLLAR_OPEN_CURLY_BRACES expr '}'                   { $$ = Expr\Variable[$2]; }
+    | T_DOLLAR_OPEN_CURLY_BRACES T_STRING_VARNAME '}'       { $$ = Expr\Variable[$2]; }
+    | T_DOLLAR_OPEN_CURLY_BRACES encaps_str_varname '[' expr ']' '}'
+          { $$ = Expr\ArrayDimFetch[$2, $4]; }
+    | T_CURLY_OPEN variable '}'                             { $$ = $2; }
+;
+
+encaps_var_offset:
+      T_STRING                                              { $$ = Scalar\String_[$1]; }
+    | T_NUM_STRING                                          { $$ = $this->parseNumString($1, attributes()); }
+    | plain_variable                                        { $$ = $1; }
+;
+
+%%
diff --git a/vendor/nikic/php-parser/grammar/php7.y b/vendor/nikic/php-parser/grammar/php7.y
new file mode 100644
index 0000000000000000000000000000000000000000..4ca244d8a6d12b07a0837320212c4da744eaad2f
--- /dev/null
+++ b/vendor/nikic/php-parser/grammar/php7.y
@@ -0,0 +1,1138 @@
+%pure_parser
+%expect 2
+
+%tokens
+
+%%
+
+start:
+    top_statement_list                                      { $$ = $this->handleNamespaces($1); }
+;
+
+top_statement_list_ex:
+      top_statement_list_ex top_statement                   { pushNormalizing($1, $2); }
+    | /* empty */                                           { init(); }
+;
+
+top_statement_list:
+      top_statement_list_ex
+          { makeZeroLengthNop($nop, $this->lookaheadStartAttributes);
+            if ($nop !== null) { $1[] = $nop; } $$ = $1; }
+;
+
+reserved_non_modifiers:
+      T_INCLUDE | T_INCLUDE_ONCE | T_EVAL | T_REQUIRE | T_REQUIRE_ONCE | T_LOGICAL_OR | T_LOGICAL_XOR | T_LOGICAL_AND
+    | T_INSTANCEOF | T_NEW | T_CLONE | T_EXIT | T_IF | T_ELSEIF | T_ELSE | T_ENDIF | T_ECHO | T_DO | T_WHILE
+    | T_ENDWHILE | T_FOR | T_ENDFOR | T_FOREACH | T_ENDFOREACH | T_DECLARE | T_ENDDECLARE | T_AS | T_TRY | T_CATCH
+    | T_FINALLY | T_THROW | T_USE | T_INSTEADOF | T_GLOBAL | T_VAR | T_UNSET | T_ISSET | T_EMPTY | T_CONTINUE | T_GOTO
+    | T_FUNCTION | T_CONST | T_RETURN | T_PRINT | T_YIELD | T_LIST | T_SWITCH | T_ENDSWITCH | T_CASE | T_DEFAULT
+    | T_BREAK | T_ARRAY | T_CALLABLE | T_EXTENDS | T_IMPLEMENTS | T_NAMESPACE | T_TRAIT | T_INTERFACE | T_CLASS
+    | T_CLASS_C | T_TRAIT_C | T_FUNC_C | T_METHOD_C | T_LINE | T_FILE | T_DIR | T_NS_C | T_HALT_COMPILER | T_FN
+    | T_MATCH
+;
+
+semi_reserved:
+      reserved_non_modifiers
+    | T_STATIC | T_ABSTRACT | T_FINAL | T_PRIVATE | T_PROTECTED | T_PUBLIC
+;
+
+identifier_ex:
+      T_STRING                                              { $$ = Node\Identifier[$1]; }
+    | semi_reserved                                         { $$ = Node\Identifier[$1]; }
+;
+
+identifier:
+      T_STRING                                              { $$ = Node\Identifier[$1]; }
+;
+
+reserved_non_modifiers_identifier:
+      reserved_non_modifiers                                { $$ = Node\Identifier[$1]; }
+;
+
+namespace_declaration_name:
+      T_STRING                                              { $$ = Name[$1]; }
+    | semi_reserved                                         { $$ = Name[$1]; }
+    | T_NAME_QUALIFIED                                      { $$ = Name[$1]; }
+;
+
+namespace_name:
+      T_STRING                                              { $$ = Name[$1]; }
+    | T_NAME_QUALIFIED                                      { $$ = Name[$1]; }
+;
+
+legacy_namespace_name:
+      namespace_name                                        { $$ = $1; }
+    | T_NAME_FULLY_QUALIFIED                                { $$ = Name[substr($1, 1)]; }
+;
+
+plain_variable:
+      T_VARIABLE                                            { $$ = Expr\Variable[parseVar($1)]; }
+;
+
+semi:
+      ';'                                                   { /* nothing */ }
+    | error                                                 { /* nothing */ }
+;
+
+no_comma:
+      /* empty */ { /* nothing */ }
+    | ',' { $this->emitError(new Error('A trailing comma is not allowed here', attributes())); }
+;
+
+optional_comma:
+      /* empty */
+    | ','
+;
+
+attribute_decl:
+      class_name                                            { $$ = Node\Attribute[$1, []]; }
+    | class_name argument_list                              { $$ = Node\Attribute[$1, $2]; }
+;
+
+attribute_group:
+      attribute_decl                                        { init($1); }
+    | attribute_group ',' attribute_decl                    { push($1, $3); }
+;
+
+attribute:
+      T_ATTRIBUTE attribute_group optional_comma ']'        { $$ = Node\AttributeGroup[$2]; }
+;
+
+attributes:
+      attribute                                             { init($1); }
+    | attributes attribute                                  { push($1, $2); }
+;
+
+optional_attributes:
+      /* empty */                                           { $$ = []; }
+    | attributes                                            { $$ = $1; }
+;
+
+top_statement:
+      statement                                             { $$ = $1; }
+    | function_declaration_statement                        { $$ = $1; }
+    | class_declaration_statement                           { $$ = $1; }
+    | T_HALT_COMPILER
+          { $$ = Stmt\HaltCompiler[$this->lexer->handleHaltCompiler()]; }
+    | T_NAMESPACE namespace_declaration_name semi
+          { $$ = Stmt\Namespace_[$2, null];
+            $$->setAttribute('kind', Stmt\Namespace_::KIND_SEMICOLON);
+            $this->checkNamespace($$); }
+    | T_NAMESPACE namespace_declaration_name '{' top_statement_list '}'
+          { $$ = Stmt\Namespace_[$2, $4];
+            $$->setAttribute('kind', Stmt\Namespace_::KIND_BRACED);
+            $this->checkNamespace($$); }
+    | T_NAMESPACE '{' top_statement_list '}'
+          { $$ = Stmt\Namespace_[null, $3];
+            $$->setAttribute('kind', Stmt\Namespace_::KIND_BRACED);
+            $this->checkNamespace($$); }
+    | T_USE use_declarations semi                           { $$ = Stmt\Use_[$2, Stmt\Use_::TYPE_NORMAL]; }
+    | T_USE use_type use_declarations semi                  { $$ = Stmt\Use_[$3, $2]; }
+    | group_use_declaration semi                            { $$ = $1; }
+    | T_CONST constant_declaration_list semi                { $$ = Stmt\Const_[$2]; }
+;
+
+use_type:
+      T_FUNCTION                                            { $$ = Stmt\Use_::TYPE_FUNCTION; }
+    | T_CONST                                               { $$ = Stmt\Use_::TYPE_CONSTANT; }
+;
+
+group_use_declaration:
+      T_USE use_type legacy_namespace_name T_NS_SEPARATOR '{' unprefixed_use_declarations '}'
+          { $$ = Stmt\GroupUse[$3, $6, $2]; }
+    | T_USE legacy_namespace_name T_NS_SEPARATOR '{' inline_use_declarations '}'
+          { $$ = Stmt\GroupUse[$2, $5, Stmt\Use_::TYPE_UNKNOWN]; }
+;
+
+unprefixed_use_declarations:
+      non_empty_unprefixed_use_declarations optional_comma  { $$ = $1; }
+;
+
+non_empty_unprefixed_use_declarations:
+      non_empty_unprefixed_use_declarations ',' unprefixed_use_declaration
+          { push($1, $3); }
+    | unprefixed_use_declaration                            { init($1); }
+;
+
+use_declarations:
+      non_empty_use_declarations no_comma                   { $$ = $1; }
+;
+
+non_empty_use_declarations:
+      non_empty_use_declarations ',' use_declaration        { push($1, $3); }
+    | use_declaration                                       { init($1); }
+;
+
+inline_use_declarations:
+      non_empty_inline_use_declarations optional_comma      { $$ = $1; }
+;
+
+non_empty_inline_use_declarations:
+      non_empty_inline_use_declarations ',' inline_use_declaration
+          { push($1, $3); }
+    | inline_use_declaration                                { init($1); }
+;
+
+unprefixed_use_declaration:
+      namespace_name
+          { $$ = Stmt\UseUse[$1, null, Stmt\Use_::TYPE_UNKNOWN]; $this->checkUseUse($$, #1); }
+    | namespace_name T_AS identifier
+          { $$ = Stmt\UseUse[$1, $3, Stmt\Use_::TYPE_UNKNOWN]; $this->checkUseUse($$, #3); }
+;
+
+use_declaration:
+      legacy_namespace_name
+          { $$ = Stmt\UseUse[$1, null, Stmt\Use_::TYPE_UNKNOWN]; $this->checkUseUse($$, #1); }
+    | legacy_namespace_name T_AS identifier
+          { $$ = Stmt\UseUse[$1, $3, Stmt\Use_::TYPE_UNKNOWN]; $this->checkUseUse($$, #3); }
+;
+
+inline_use_declaration:
+      unprefixed_use_declaration                            { $$ = $1; $$->type = Stmt\Use_::TYPE_NORMAL; }
+    | use_type unprefixed_use_declaration                   { $$ = $2; $$->type = $1; }
+;
+
+constant_declaration_list:
+      non_empty_constant_declaration_list no_comma          { $$ = $1; }
+;
+
+non_empty_constant_declaration_list:
+      non_empty_constant_declaration_list ',' constant_declaration
+          { push($1, $3); }
+    | constant_declaration                                  { init($1); }
+;
+
+constant_declaration:
+    identifier '=' expr                                     { $$ = Node\Const_[$1, $3]; }
+;
+
+class_const_list:
+      non_empty_class_const_list no_comma                   { $$ = $1; }
+;
+
+non_empty_class_const_list:
+      non_empty_class_const_list ',' class_const            { push($1, $3); }
+    | class_const                                           { init($1); }
+;
+
+class_const:
+    identifier_ex '=' expr                                  { $$ = Node\Const_[$1, $3]; }
+;
+
+inner_statement_list_ex:
+      inner_statement_list_ex inner_statement               { pushNormalizing($1, $2); }
+    | /* empty */                                           { init(); }
+;
+
+inner_statement_list:
+      inner_statement_list_ex
+          { makeZeroLengthNop($nop, $this->lookaheadStartAttributes);
+            if ($nop !== null) { $1[] = $nop; } $$ = $1; }
+;
+
+inner_statement:
+      statement                                             { $$ = $1; }
+    | function_declaration_statement                        { $$ = $1; }
+    | class_declaration_statement                           { $$ = $1; }
+    | T_HALT_COMPILER
+          { throw new Error('__HALT_COMPILER() can only be used from the outermost scope', attributes()); }
+;
+
+non_empty_statement:
+      '{' inner_statement_list '}'
+    {
+        if ($2) {
+            $$ = $2; prependLeadingComments($$);
+        } else {
+            makeNop($$, $this->startAttributeStack[#1], $this->endAttributes);
+            if (null === $$) { $$ = array(); }
+        }
+    }
+    | T_IF '(' expr ')' statement elseif_list else_single
+          { $$ = Stmt\If_[$3, ['stmts' => toArray($5), 'elseifs' => $6, 'else' => $7]]; }
+    | T_IF '(' expr ')' ':' inner_statement_list new_elseif_list new_else_single T_ENDIF ';'
+          { $$ = Stmt\If_[$3, ['stmts' => $6, 'elseifs' => $7, 'else' => $8]]; }
+    | T_WHILE '(' expr ')' while_statement                  { $$ = Stmt\While_[$3, $5]; }
+    | T_DO statement T_WHILE '(' expr ')' ';'               { $$ = Stmt\Do_   [$5, toArray($2)]; }
+    | T_FOR '(' for_expr ';'  for_expr ';' for_expr ')' for_statement
+          { $$ = Stmt\For_[['init' => $3, 'cond' => $5, 'loop' => $7, 'stmts' => $9]]; }
+    | T_SWITCH '(' expr ')' switch_case_list                { $$ = Stmt\Switch_[$3, $5]; }
+    | T_BREAK optional_expr semi                            { $$ = Stmt\Break_[$2]; }
+    | T_CONTINUE optional_expr semi                         { $$ = Stmt\Continue_[$2]; }
+    | T_RETURN optional_expr semi                           { $$ = Stmt\Return_[$2]; }
+    | T_GLOBAL global_var_list semi                         { $$ = Stmt\Global_[$2]; }
+    | T_STATIC static_var_list semi                         { $$ = Stmt\Static_[$2]; }
+    | T_ECHO expr_list_forbid_comma semi                    { $$ = Stmt\Echo_[$2]; }
+    | T_INLINE_HTML                                         { $$ = Stmt\InlineHTML[$1]; }
+    | expr semi {
+        $e = $1;
+        if ($e instanceof Expr\Throw_) {
+            // For backwards-compatibility reasons, convert throw in statement position into
+            // Stmt\Throw_ rather than Stmt\Expression(Expr\Throw_).
+            $$ = Stmt\Throw_[$e->expr];
+        } else {
+            $$ = Stmt\Expression[$e];
+        }
+    }
+    | T_UNSET '(' variables_list ')' semi                   { $$ = Stmt\Unset_[$3]; }
+    | T_FOREACH '(' expr T_AS foreach_variable ')' foreach_statement
+          { $$ = Stmt\Foreach_[$3, $5[0], ['keyVar' => null, 'byRef' => $5[1], 'stmts' => $7]]; }
+    | T_FOREACH '(' expr T_AS variable T_DOUBLE_ARROW foreach_variable ')' foreach_statement
+          { $$ = Stmt\Foreach_[$3, $7[0], ['keyVar' => $5, 'byRef' => $7[1], 'stmts' => $9]]; }
+    | T_FOREACH '(' expr error ')' foreach_statement
+          { $$ = Stmt\Foreach_[$3, new Expr\Error(stackAttributes(#4)), ['stmts' => $6]]; }
+    | T_DECLARE '(' declare_list ')' declare_statement      { $$ = Stmt\Declare_[$3, $5]; }
+    | T_TRY '{' inner_statement_list '}' catches optional_finally
+          { $$ = Stmt\TryCatch[$3, $5, $6]; $this->checkTryCatch($$); }
+    | T_GOTO identifier semi                                { $$ = Stmt\Goto_[$2]; }
+    | identifier ':'                                        { $$ = Stmt\Label[$1]; }
+    | error                                                 { $$ = array(); /* means: no statement */ }
+;
+
+statement:
+      non_empty_statement                                   { $$ = $1; }
+    | ';'
+          { makeNop($$, $this->startAttributeStack[#1], $this->endAttributes);
+            if ($$ === null) $$ = array(); /* means: no statement */ }
+;
+
+catches:
+      /* empty */                                           { init(); }
+    | catches catch                                         { push($1, $2); }
+;
+
+name_union:
+      name                                                  { init($1); }
+    | name_union '|' name                                   { push($1, $3); }
+;
+
+catch:
+    T_CATCH '(' name_union optional_plain_variable ')' '{' inner_statement_list '}'
+        { $$ = Stmt\Catch_[$3, $4, $7]; }
+;
+
+optional_finally:
+      /* empty */                                           { $$ = null; }
+    | T_FINALLY '{' inner_statement_list '}'                { $$ = Stmt\Finally_[$3]; }
+;
+
+variables_list:
+      non_empty_variables_list optional_comma               { $$ = $1; }
+;
+
+non_empty_variables_list:
+      variable                                              { init($1); }
+    | non_empty_variables_list ',' variable                 { push($1, $3); }
+;
+
+optional_ref:
+      /* empty */                                           { $$ = false; }
+    | '&'                                                   { $$ = true; }
+;
+
+optional_ellipsis:
+      /* empty */                                           { $$ = false; }
+    | T_ELLIPSIS                                            { $$ = true; }
+;
+
+block_or_error:
+      '{' inner_statement_list '}'                          { $$ = $2; }
+    | error                                                 { $$ = []; }
+;
+
+function_declaration_statement:
+      T_FUNCTION optional_ref identifier '(' parameter_list ')' optional_return_type block_or_error
+          { $$ = Stmt\Function_[$3, ['byRef' => $2, 'params' => $5, 'returnType' => $7, 'stmts' => $8, 'attrGroups' => []]]; }
+    | attributes T_FUNCTION optional_ref identifier '(' parameter_list ')' optional_return_type block_or_error
+          { $$ = Stmt\Function_[$4, ['byRef' => $3, 'params' => $6, 'returnType' => $8, 'stmts' => $9, 'attrGroups' => $1]]; }
+;
+
+class_declaration_statement:
+      optional_attributes class_entry_type identifier extends_from implements_list '{' class_statement_list '}'
+          { $$ = Stmt\Class_[$3, ['type' => $2, 'extends' => $4, 'implements' => $5, 'stmts' => $7, 'attrGroups' => $1]];
+            $this->checkClass($$, #3); }
+    | optional_attributes T_INTERFACE identifier interface_extends_list '{' class_statement_list '}'
+          { $$ = Stmt\Interface_[$3, ['extends' => $4, 'stmts' => $6, 'attrGroups' => $1]];
+            $this->checkInterface($$, #3); }
+    | optional_attributes T_TRAIT identifier '{' class_statement_list '}'
+          { $$ = Stmt\Trait_[$3, ['stmts' => $5, 'attrGroups' => $1]]; }
+;
+
+class_entry_type:
+      T_CLASS                                               { $$ = 0; }
+    | T_ABSTRACT T_CLASS                                    { $$ = Stmt\Class_::MODIFIER_ABSTRACT; }
+    | T_FINAL T_CLASS                                       { $$ = Stmt\Class_::MODIFIER_FINAL; }
+;
+
+extends_from:
+      /* empty */                                           { $$ = null; }
+    | T_EXTENDS class_name                                  { $$ = $2; }
+;
+
+interface_extends_list:
+      /* empty */                                           { $$ = array(); }
+    | T_EXTENDS class_name_list                             { $$ = $2; }
+;
+
+implements_list:
+      /* empty */                                           { $$ = array(); }
+    | T_IMPLEMENTS class_name_list                          { $$ = $2; }
+;
+
+class_name_list:
+      non_empty_class_name_list no_comma                    { $$ = $1; }
+;
+
+non_empty_class_name_list:
+      class_name                                            { init($1); }
+    | non_empty_class_name_list ',' class_name              { push($1, $3); }
+;
+
+for_statement:
+      statement                                             { $$ = toArray($1); }
+    | ':' inner_statement_list T_ENDFOR ';'                 { $$ = $2; }
+;
+
+foreach_statement:
+      statement                                             { $$ = toArray($1); }
+    | ':' inner_statement_list T_ENDFOREACH ';'             { $$ = $2; }
+;
+
+declare_statement:
+      non_empty_statement                                   { $$ = toArray($1); }
+    | ';'                                                   { $$ = null; }
+    | ':' inner_statement_list T_ENDDECLARE ';'             { $$ = $2; }
+;
+
+declare_list:
+      non_empty_declare_list no_comma                       { $$ = $1; }
+;
+
+non_empty_declare_list:
+      declare_list_element                                  { init($1); }
+    | non_empty_declare_list ',' declare_list_element       { push($1, $3); }
+;
+
+declare_list_element:
+      identifier '=' expr                                   { $$ = Stmt\DeclareDeclare[$1, $3]; }
+;
+
+switch_case_list:
+      '{' case_list '}'                                     { $$ = $2; }
+    | '{' ';' case_list '}'                                 { $$ = $3; }
+    | ':' case_list T_ENDSWITCH ';'                         { $$ = $2; }
+    | ':' ';' case_list T_ENDSWITCH ';'                     { $$ = $3; }
+;
+
+case_list:
+      /* empty */                                           { init(); }
+    | case_list case                                        { push($1, $2); }
+;
+
+case:
+      T_CASE expr case_separator inner_statement_list_ex    { $$ = Stmt\Case_[$2, $4]; }
+    | T_DEFAULT case_separator inner_statement_list_ex      { $$ = Stmt\Case_[null, $3]; }
+;
+
+case_separator:
+      ':'
+    | ';'
+;
+
+match:
+      T_MATCH '(' expr ')' '{' match_arm_list '}'           { $$ = Expr\Match_[$3, $6]; }
+;
+
+match_arm_list:
+      /* empty */                                           { $$ = []; }
+    | non_empty_match_arm_list optional_comma               { $$ = $1; }
+;
+
+non_empty_match_arm_list:
+      match_arm                                             { init($1); }
+    | non_empty_match_arm_list ',' match_arm                { push($1, $3); }
+;
+
+match_arm:
+      expr_list_allow_comma T_DOUBLE_ARROW expr             { $$ = Node\MatchArm[$1, $3]; }
+    | T_DEFAULT optional_comma T_DOUBLE_ARROW expr          { $$ = Node\MatchArm[null, $4]; }
+;
+
+while_statement:
+      statement                                             { $$ = toArray($1); }
+    | ':' inner_statement_list T_ENDWHILE ';'               { $$ = $2; }
+;
+
+elseif_list:
+      /* empty */                                           { init(); }
+    | elseif_list elseif                                    { push($1, $2); }
+;
+
+elseif:
+      T_ELSEIF '(' expr ')' statement                       { $$ = Stmt\ElseIf_[$3, toArray($5)]; }
+;
+
+new_elseif_list:
+      /* empty */                                           { init(); }
+    | new_elseif_list new_elseif                            { push($1, $2); }
+;
+
+new_elseif:
+     T_ELSEIF '(' expr ')' ':' inner_statement_list         { $$ = Stmt\ElseIf_[$3, $6]; }
+;
+
+else_single:
+      /* empty */                                           { $$ = null; }
+    | T_ELSE statement                                      { $$ = Stmt\Else_[toArray($2)]; }
+;
+
+new_else_single:
+      /* empty */                                           { $$ = null; }
+    | T_ELSE ':' inner_statement_list                       { $$ = Stmt\Else_[$3]; }
+;
+
+foreach_variable:
+      variable                                              { $$ = array($1, false); }
+    | '&' variable                                          { $$ = array($2, true); }
+    | list_expr                                             { $$ = array($1, false); }
+    | array_short_syntax                                    { $$ = array($1, false); }
+;
+
+parameter_list:
+      non_empty_parameter_list optional_comma               { $$ = $1; }
+    | /* empty */                                           { $$ = array(); }
+;
+
+non_empty_parameter_list:
+      parameter                                             { init($1); }
+    | non_empty_parameter_list ',' parameter                { push($1, $3); }
+;
+
+optional_visibility_modifier:
+      /* empty */               { $$ = 0; }
+    | T_PUBLIC                  { $$ = Stmt\Class_::MODIFIER_PUBLIC; }
+    | T_PROTECTED               { $$ = Stmt\Class_::MODIFIER_PROTECTED; }
+    | T_PRIVATE                 { $$ = Stmt\Class_::MODIFIER_PRIVATE; }
+;
+
+parameter:
+      optional_attributes optional_visibility_modifier optional_type_without_static optional_ref optional_ellipsis plain_variable
+          { $$ = new Node\Param($6, null, $3, $4, $5, attributes(), $2, $1);
+            $this->checkParam($$); }
+    | optional_attributes optional_visibility_modifier optional_type_without_static optional_ref optional_ellipsis plain_variable '=' expr
+          { $$ = new Node\Param($6, $8, $3, $4, $5, attributes(), $2, $1);
+            $this->checkParam($$); }
+    | optional_attributes optional_visibility_modifier optional_type_without_static optional_ref optional_ellipsis error
+          { $$ = new Node\Param(Expr\Error[], null, $3, $4, $5, attributes(), $2, $1); }
+;
+
+type_expr:
+      type                                                  { $$ = $1; }
+    | '?' type                                              { $$ = Node\NullableType[$2]; }
+    | union_type                                            { $$ = Node\UnionType[$1]; }
+;
+
+type:
+      type_without_static                                   { $$ = $1; }
+    | T_STATIC                                              { $$ = Node\Name['static']; }
+;
+
+type_without_static:
+      name                                                  { $$ = $this->handleBuiltinTypes($1); }
+    | T_ARRAY                                               { $$ = Node\Identifier['array']; }
+    | T_CALLABLE                                            { $$ = Node\Identifier['callable']; }
+;
+
+union_type:
+      type '|' type                                         { init($1, $3); }
+    | union_type '|' type                                   { push($1, $3); }
+;
+
+union_type_without_static:
+      type_without_static '|' type_without_static           { init($1, $3); }
+    | union_type_without_static '|' type_without_static     { push($1, $3); }
+;
+
+type_expr_without_static:
+      type_without_static                                   { $$ = $1; }
+    | '?' type_without_static                               { $$ = Node\NullableType[$2]; }
+    | union_type_without_static                             { $$ = Node\UnionType[$1]; }
+;
+
+optional_type_without_static:
+      /* empty */                                           { $$ = null; }
+    | type_expr_without_static                              { $$ = $1; }
+;
+
+optional_return_type:
+      /* empty */                                           { $$ = null; }
+    | ':' type_expr                                         { $$ = $2; }
+    | ':' error                                             { $$ = null; }
+;
+
+argument_list:
+      '(' ')'                                               { $$ = array(); }
+    | '(' non_empty_argument_list optional_comma ')'        { $$ = $2; }
+;
+
+non_empty_argument_list:
+      argument                                              { init($1); }
+    | non_empty_argument_list ',' argument                  { push($1, $3); }
+;
+
+argument:
+      expr                                                  { $$ = Node\Arg[$1, false, false]; }
+    | '&' variable                                          { $$ = Node\Arg[$2, true, false]; }
+    | T_ELLIPSIS expr                                       { $$ = Node\Arg[$2, false, true]; }
+    | identifier_ex ':' expr
+          { $$ = new Node\Arg($3, false, false, attributes(), $1); }
+;
+
+global_var_list:
+      non_empty_global_var_list no_comma                    { $$ = $1; }
+;
+
+non_empty_global_var_list:
+      non_empty_global_var_list ',' global_var              { push($1, $3); }
+    | global_var                                            { init($1); }
+;
+
+global_var:
+      simple_variable                                       { $$ = $1; }
+;
+
+static_var_list:
+      non_empty_static_var_list no_comma                    { $$ = $1; }
+;
+
+non_empty_static_var_list:
+      non_empty_static_var_list ',' static_var              { push($1, $3); }
+    | static_var                                            { init($1); }
+;
+
+static_var:
+      plain_variable                                        { $$ = Stmt\StaticVar[$1, null]; }
+    | plain_variable '=' expr                               { $$ = Stmt\StaticVar[$1, $3]; }
+;
+
+class_statement_list_ex:
+      class_statement_list_ex class_statement               { if ($2 !== null) { push($1, $2); } }
+    | /* empty */                                           { init(); }
+;
+
+class_statement_list:
+      class_statement_list_ex
+          { makeZeroLengthNop($nop, $this->lookaheadStartAttributes);
+            if ($nop !== null) { $1[] = $nop; } $$ = $1; }
+;
+
+class_statement:
+      optional_attributes variable_modifiers optional_type_without_static property_declaration_list semi
+          { $$ = new Stmt\Property($2, $4, attributes(), $3, $1);
+            $this->checkProperty($$, #2); }
+    | optional_attributes method_modifiers T_CONST class_const_list semi
+          { $$ = new Stmt\ClassConst($4, $2, attributes(), $1);
+            $this->checkClassConst($$, #2); }
+    | optional_attributes method_modifiers T_FUNCTION optional_ref identifier_ex '(' parameter_list ')' optional_return_type method_body
+          { $$ = Stmt\ClassMethod[$5, ['type' => $2, 'byRef' => $4, 'params' => $7, 'returnType' => $9, 'stmts' => $10, 'attrGroups' => $1]];
+            $this->checkClassMethod($$, #2); }
+    | T_USE class_name_list trait_adaptations               { $$ = Stmt\TraitUse[$2, $3]; }
+    | error                                                 { $$ = null; /* will be skipped */ }
+;
+
+trait_adaptations:
+      ';'                                                   { $$ = array(); }
+    | '{' trait_adaptation_list '}'                         { $$ = $2; }
+;
+
+trait_adaptation_list:
+      /* empty */                                           { init(); }
+    | trait_adaptation_list trait_adaptation                { push($1, $2); }
+;
+
+trait_adaptation:
+      trait_method_reference_fully_qualified T_INSTEADOF class_name_list ';'
+          { $$ = Stmt\TraitUseAdaptation\Precedence[$1[0], $1[1], $3]; }
+    | trait_method_reference T_AS member_modifier identifier_ex ';'
+          { $$ = Stmt\TraitUseAdaptation\Alias[$1[0], $1[1], $3, $4]; }
+    | trait_method_reference T_AS member_modifier ';'
+          { $$ = Stmt\TraitUseAdaptation\Alias[$1[0], $1[1], $3, null]; }
+    | trait_method_reference T_AS identifier ';'
+          { $$ = Stmt\TraitUseAdaptation\Alias[$1[0], $1[1], null, $3]; }
+    | trait_method_reference T_AS reserved_non_modifiers_identifier ';'
+          { $$ = Stmt\TraitUseAdaptation\Alias[$1[0], $1[1], null, $3]; }
+;
+
+trait_method_reference_fully_qualified:
+      name T_PAAMAYIM_NEKUDOTAYIM identifier_ex             { $$ = array($1, $3); }
+;
+trait_method_reference:
+      trait_method_reference_fully_qualified                { $$ = $1; }
+    | identifier_ex                                         { $$ = array(null, $1); }
+;
+
+method_body:
+      ';' /* abstract method */                             { $$ = null; }
+    | block_or_error                                        { $$ = $1; }
+;
+
+variable_modifiers:
+      non_empty_member_modifiers                            { $$ = $1; }
+    | T_VAR                                                 { $$ = 0; }
+;
+
+method_modifiers:
+      /* empty */                                           { $$ = 0; }
+    | non_empty_member_modifiers                            { $$ = $1; }
+;
+
+non_empty_member_modifiers:
+      member_modifier                                       { $$ = $1; }
+    | non_empty_member_modifiers member_modifier            { $this->checkModifier($1, $2, #2); $$ = $1 | $2; }
+;
+
+member_modifier:
+      T_PUBLIC                                              { $$ = Stmt\Class_::MODIFIER_PUBLIC; }
+    | T_PROTECTED                                           { $$ = Stmt\Class_::MODIFIER_PROTECTED; }
+    | T_PRIVATE                                             { $$ = Stmt\Class_::MODIFIER_PRIVATE; }
+    | T_STATIC                                              { $$ = Stmt\Class_::MODIFIER_STATIC; }
+    | T_ABSTRACT                                            { $$ = Stmt\Class_::MODIFIER_ABSTRACT; }
+    | T_FINAL                                               { $$ = Stmt\Class_::MODIFIER_FINAL; }
+;
+
+property_declaration_list:
+      non_empty_property_declaration_list no_comma          { $$ = $1; }
+;
+
+non_empty_property_declaration_list:
+      property_declaration                                  { init($1); }
+    | non_empty_property_declaration_list ',' property_declaration
+          { push($1, $3); }
+;
+
+property_decl_name:
+      T_VARIABLE                                            { $$ = Node\VarLikeIdentifier[parseVar($1)]; }
+;
+
+property_declaration:
+      property_decl_name                                    { $$ = Stmt\PropertyProperty[$1, null]; }
+    | property_decl_name '=' expr                           { $$ = Stmt\PropertyProperty[$1, $3]; }
+;
+
+expr_list_forbid_comma:
+      non_empty_expr_list no_comma                          { $$ = $1; }
+;
+
+expr_list_allow_comma:
+      non_empty_expr_list optional_comma                    { $$ = $1; }
+;
+
+non_empty_expr_list:
+      non_empty_expr_list ',' expr                          { push($1, $3); }
+    | expr                                                  { init($1); }
+;
+
+for_expr:
+      /* empty */                                           { $$ = array(); }
+    | expr_list_forbid_comma                                { $$ = $1; }
+;
+
+expr:
+      variable                                              { $$ = $1; }
+    | list_expr '=' expr                                    { $$ = Expr\Assign[$1, $3]; }
+    | array_short_syntax '=' expr                           { $$ = Expr\Assign[$1, $3]; }
+    | variable '=' expr                                     { $$ = Expr\Assign[$1, $3]; }
+    | variable '=' '&' variable                             { $$ = Expr\AssignRef[$1, $4]; }
+    | new_expr                                              { $$ = $1; }
+    | match                                                 { $$ = $1; }
+    | T_CLONE expr                                          { $$ = Expr\Clone_[$2]; }
+    | variable T_PLUS_EQUAL expr                            { $$ = Expr\AssignOp\Plus      [$1, $3]; }
+    | variable T_MINUS_EQUAL expr                           { $$ = Expr\AssignOp\Minus     [$1, $3]; }
+    | variable T_MUL_EQUAL expr                             { $$ = Expr\AssignOp\Mul       [$1, $3]; }
+    | variable T_DIV_EQUAL expr                             { $$ = Expr\AssignOp\Div       [$1, $3]; }
+    | variable T_CONCAT_EQUAL expr                          { $$ = Expr\AssignOp\Concat    [$1, $3]; }
+    | variable T_MOD_EQUAL expr                             { $$ = Expr\AssignOp\Mod       [$1, $3]; }
+    | variable T_AND_EQUAL expr                             { $$ = Expr\AssignOp\BitwiseAnd[$1, $3]; }
+    | variable T_OR_EQUAL expr                              { $$ = Expr\AssignOp\BitwiseOr [$1, $3]; }
+    | variable T_XOR_EQUAL expr                             { $$ = Expr\AssignOp\BitwiseXor[$1, $3]; }
+    | variable T_SL_EQUAL expr                              { $$ = Expr\AssignOp\ShiftLeft [$1, $3]; }
+    | variable T_SR_EQUAL expr                              { $$ = Expr\AssignOp\ShiftRight[$1, $3]; }
+    | variable T_POW_EQUAL expr                             { $$ = Expr\AssignOp\Pow       [$1, $3]; }
+    | variable T_COALESCE_EQUAL expr                        { $$ = Expr\AssignOp\Coalesce  [$1, $3]; }
+    | variable T_INC                                        { $$ = Expr\PostInc[$1]; }
+    | T_INC variable                                        { $$ = Expr\PreInc [$2]; }
+    | variable T_DEC                                        { $$ = Expr\PostDec[$1]; }
+    | T_DEC variable                                        { $$ = Expr\PreDec [$2]; }
+    | expr T_BOOLEAN_OR expr                                { $$ = Expr\BinaryOp\BooleanOr [$1, $3]; }
+    | expr T_BOOLEAN_AND expr                               { $$ = Expr\BinaryOp\BooleanAnd[$1, $3]; }
+    | expr T_LOGICAL_OR expr                                { $$ = Expr\BinaryOp\LogicalOr [$1, $3]; }
+    | expr T_LOGICAL_AND expr                               { $$ = Expr\BinaryOp\LogicalAnd[$1, $3]; }
+    | expr T_LOGICAL_XOR expr                               { $$ = Expr\BinaryOp\LogicalXor[$1, $3]; }
+    | expr '|' expr                                         { $$ = Expr\BinaryOp\BitwiseOr [$1, $3]; }
+    | expr '&' expr                                         { $$ = Expr\BinaryOp\BitwiseAnd[$1, $3]; }
+    | expr '^' expr                                         { $$ = Expr\BinaryOp\BitwiseXor[$1, $3]; }
+    | expr '.' expr                                         { $$ = Expr\BinaryOp\Concat    [$1, $3]; }
+    | expr '+' expr                                         { $$ = Expr\BinaryOp\Plus      [$1, $3]; }
+    | expr '-' expr                                         { $$ = Expr\BinaryOp\Minus     [$1, $3]; }
+    | expr '*' expr                                         { $$ = Expr\BinaryOp\Mul       [$1, $3]; }
+    | expr '/' expr                                         { $$ = Expr\BinaryOp\Div       [$1, $3]; }
+    | expr '%' expr                                         { $$ = Expr\BinaryOp\Mod       [$1, $3]; }
+    | expr T_SL expr                                        { $$ = Expr\BinaryOp\ShiftLeft [$1, $3]; }
+    | expr T_SR expr                                        { $$ = Expr\BinaryOp\ShiftRight[$1, $3]; }
+    | expr T_POW expr                                       { $$ = Expr\BinaryOp\Pow       [$1, $3]; }
+    | '+' expr %prec T_INC                                  { $$ = Expr\UnaryPlus [$2]; }
+    | '-' expr %prec T_INC                                  { $$ = Expr\UnaryMinus[$2]; }
+    | '!' expr                                              { $$ = Expr\BooleanNot[$2]; }
+    | '~' expr                                              { $$ = Expr\BitwiseNot[$2]; }
+    | expr T_IS_IDENTICAL expr                              { $$ = Expr\BinaryOp\Identical     [$1, $3]; }
+    | expr T_IS_NOT_IDENTICAL expr                          { $$ = Expr\BinaryOp\NotIdentical  [$1, $3]; }
+    | expr T_IS_EQUAL expr                                  { $$ = Expr\BinaryOp\Equal         [$1, $3]; }
+    | expr T_IS_NOT_EQUAL expr                              { $$ = Expr\BinaryOp\NotEqual      [$1, $3]; }
+    | expr T_SPACESHIP expr                                 { $$ = Expr\BinaryOp\Spaceship     [$1, $3]; }
+    | expr '<' expr                                         { $$ = Expr\BinaryOp\Smaller       [$1, $3]; }
+    | expr T_IS_SMALLER_OR_EQUAL expr                       { $$ = Expr\BinaryOp\SmallerOrEqual[$1, $3]; }
+    | expr '>' expr                                         { $$ = Expr\BinaryOp\Greater       [$1, $3]; }
+    | expr T_IS_GREATER_OR_EQUAL expr                       { $$ = Expr\BinaryOp\GreaterOrEqual[$1, $3]; }
+    | expr T_INSTANCEOF class_name_reference                { $$ = Expr\Instanceof_[$1, $3]; }
+    | '(' expr ')'                                          { $$ = $2; }
+    | expr '?' expr ':' expr                                { $$ = Expr\Ternary[$1, $3,   $5]; }
+    | expr '?' ':' expr                                     { $$ = Expr\Ternary[$1, null, $4]; }
+    | expr T_COALESCE expr                                  { $$ = Expr\BinaryOp\Coalesce[$1, $3]; }
+    | T_ISSET '(' expr_list_allow_comma ')'                 { $$ = Expr\Isset_[$3]; }
+    | T_EMPTY '(' expr ')'                                  { $$ = Expr\Empty_[$3]; }
+    | T_INCLUDE expr                                        { $$ = Expr\Include_[$2, Expr\Include_::TYPE_INCLUDE]; }
+    | T_INCLUDE_ONCE expr                                   { $$ = Expr\Include_[$2, Expr\Include_::TYPE_INCLUDE_ONCE]; }
+    | T_EVAL '(' expr ')'                                   { $$ = Expr\Eval_[$3]; }
+    | T_REQUIRE expr                                        { $$ = Expr\Include_[$2, Expr\Include_::TYPE_REQUIRE]; }
+    | T_REQUIRE_ONCE expr                                   { $$ = Expr\Include_[$2, Expr\Include_::TYPE_REQUIRE_ONCE]; }
+    | T_INT_CAST expr                                       { $$ = Expr\Cast\Int_    [$2]; }
+    | T_DOUBLE_CAST expr
+          { $attrs = attributes();
+            $attrs['kind'] = $this->getFloatCastKind($1);
+            $$ = new Expr\Cast\Double($2, $attrs); }
+    | T_STRING_CAST expr                                    { $$ = Expr\Cast\String_ [$2]; }
+    | T_ARRAY_CAST expr                                     { $$ = Expr\Cast\Array_  [$2]; }
+    | T_OBJECT_CAST expr                                    { $$ = Expr\Cast\Object_ [$2]; }
+    | T_BOOL_CAST expr                                      { $$ = Expr\Cast\Bool_   [$2]; }
+    | T_UNSET_CAST expr                                     { $$ = Expr\Cast\Unset_  [$2]; }
+    | T_EXIT exit_expr
+          { $attrs = attributes();
+            $attrs['kind'] = strtolower($1) === 'exit' ? Expr\Exit_::KIND_EXIT : Expr\Exit_::KIND_DIE;
+            $$ = new Expr\Exit_($2, $attrs); }
+    | '@' expr                                              { $$ = Expr\ErrorSuppress[$2]; }
+    | scalar                                                { $$ = $1; }
+    | '`' backticks_expr '`'                                { $$ = Expr\ShellExec[$2]; }
+    | T_PRINT expr                                          { $$ = Expr\Print_[$2]; }
+    | T_YIELD                                               { $$ = Expr\Yield_[null, null]; }
+    | T_YIELD expr                                          { $$ = Expr\Yield_[$2, null]; }
+    | T_YIELD expr T_DOUBLE_ARROW expr                      { $$ = Expr\Yield_[$4, $2]; }
+    | T_YIELD_FROM expr                                     { $$ = Expr\YieldFrom[$2]; }
+    | T_THROW expr                                          { $$ = Expr\Throw_[$2]; }
+
+    | T_FN optional_ref '(' parameter_list ')' optional_return_type T_DOUBLE_ARROW expr
+          { $$ = Expr\ArrowFunction[['static' => false, 'byRef' => $2, 'params' => $4, 'returnType' => $6, 'expr' => $8, 'attrGroups' => []]]; }
+    | T_STATIC T_FN optional_ref '(' parameter_list ')' optional_return_type T_DOUBLE_ARROW expr
+          { $$ = Expr\ArrowFunction[['static' => true, 'byRef' => $3, 'params' => $5, 'returnType' => $7, 'expr' => $9, 'attrGroups' => []]]; }
+    | T_FUNCTION optional_ref '(' parameter_list ')' lexical_vars optional_return_type block_or_error
+          { $$ = Expr\Closure[['static' => false, 'byRef' => $2, 'params' => $4, 'uses' => $6, 'returnType' => $7, 'stmts' => $8, 'attrGroups' => []]]; }
+    | T_STATIC T_FUNCTION optional_ref '(' parameter_list ')' lexical_vars optional_return_type       block_or_error
+          { $$ = Expr\Closure[['static' => true, 'byRef' => $3, 'params' => $5, 'uses' => $7, 'returnType' => $8, 'stmts' => $9, 'attrGroups' => []]]; }
+
+    | attributes T_FN optional_ref '(' parameter_list ')' optional_return_type T_DOUBLE_ARROW expr
+          { $$ = Expr\ArrowFunction[['static' => false, 'byRef' => $3, 'params' => $5, 'returnType' => $7, 'expr' => $9, 'attrGroups' => $1]]; }
+    | attributes T_STATIC T_FN optional_ref '(' parameter_list ')' optional_return_type T_DOUBLE_ARROW expr
+          { $$ = Expr\ArrowFunction[['static' => true, 'byRef' => $4, 'params' => $6, 'returnType' => $8, 'expr' => $10, 'attrGroups' => $1]]; }
+    | attributes T_FUNCTION optional_ref '(' parameter_list ')' lexical_vars optional_return_type block_or_error
+          { $$ = Expr\Closure[['static' => false, 'byRef' => $3, 'params' => $5, 'uses' => $7, 'returnType' => $8, 'stmts' => $9, 'attrGroups' => $1]]; }
+    | attributes T_STATIC T_FUNCTION optional_ref '(' parameter_list ')' lexical_vars optional_return_type       block_or_error
+          { $$ = Expr\Closure[['static' => true, 'byRef' => $4, 'params' => $6, 'uses' => $8, 'returnType' => $9, 'stmts' => $10, 'attrGroups' => $1]]; }
+;
+
+anonymous_class:
+      optional_attributes T_CLASS ctor_arguments extends_from implements_list '{' class_statement_list '}'
+          { $$ = array(Stmt\Class_[null, ['type' => 0, 'extends' => $4, 'implements' => $5, 'stmts' => $7, 'attrGroups' => $1]], $3);
+            $this->checkClass($$[0], -1); }
+;
+
+new_expr:
+      T_NEW class_name_reference ctor_arguments             { $$ = Expr\New_[$2, $3]; }
+    | T_NEW anonymous_class
+          { list($class, $ctorArgs) = $2; $$ = Expr\New_[$class, $ctorArgs]; }
+;
+
+lexical_vars:
+      /* empty */                                           { $$ = array(); }
+    | T_USE '(' lexical_var_list ')'                        { $$ = $3; }
+;
+
+lexical_var_list:
+      non_empty_lexical_var_list optional_comma             { $$ = $1; }
+;
+
+non_empty_lexical_var_list:
+      lexical_var                                           { init($1); }
+    | non_empty_lexical_var_list ',' lexical_var            { push($1, $3); }
+;
+
+lexical_var:
+      optional_ref plain_variable                           { $$ = Expr\ClosureUse[$2, $1]; }
+;
+
+function_call:
+      name argument_list                                    { $$ = Expr\FuncCall[$1, $2]; }
+    | callable_expr argument_list                           { $$ = Expr\FuncCall[$1, $2]; }
+    | class_name_or_var T_PAAMAYIM_NEKUDOTAYIM member_name argument_list
+          { $$ = Expr\StaticCall[$1, $3, $4]; }
+;
+
+class_name:
+      T_STATIC                                              { $$ = Name[$1]; }
+    | name                                                  { $$ = $1; }
+;
+
+name:
+      T_STRING                                              { $$ = Name[$1]; }
+    | T_NAME_QUALIFIED                                      { $$ = Name[$1]; }
+    | T_NAME_FULLY_QUALIFIED                                { $$ = Name\FullyQualified[substr($1, 1)]; }
+    | T_NAME_RELATIVE                                       { $$ = Name\Relative[substr($1, 10)]; }
+;
+
+class_name_reference:
+      class_name                                            { $$ = $1; }
+    | new_variable                                          { $$ = $1; }
+    | '(' expr ')'                                          { $$ = $2; }
+    | error                                                 { $$ = Expr\Error[]; $this->errorState = 2; }
+;
+
+class_name_or_var:
+      class_name                                            { $$ = $1; }
+    | fully_dereferencable                                  { $$ = $1; }
+;
+
+exit_expr:
+      /* empty */                                           { $$ = null; }
+    | '(' optional_expr ')'                                 { $$ = $2; }
+;
+
+backticks_expr:
+      /* empty */                                           { $$ = array(); }
+    | T_ENCAPSED_AND_WHITESPACE
+          { $$ = array(Scalar\EncapsedStringPart[Scalar\String_::parseEscapeSequences($1, '`')]); }
+    | encaps_list                                           { parseEncapsed($1, '`', true); $$ = $1; }
+;
+
+ctor_arguments:
+      /* empty */                                           { $$ = array(); }
+    | argument_list                                         { $$ = $1; }
+;
+
+constant:
+      name                                                  { $$ = Expr\ConstFetch[$1]; }
+    | T_LINE                                                { $$ = Scalar\MagicConst\Line[]; }
+    | T_FILE                                                { $$ = Scalar\MagicConst\File[]; }
+    | T_DIR                                                 { $$ = Scalar\MagicConst\Dir[]; }
+    | T_CLASS_C                                             { $$ = Scalar\MagicConst\Class_[]; }
+    | T_TRAIT_C                                             { $$ = Scalar\MagicConst\Trait_[]; }
+    | T_METHOD_C                                            { $$ = Scalar\MagicConst\Method[]; }
+    | T_FUNC_C                                              { $$ = Scalar\MagicConst\Function_[]; }
+    | T_NS_C                                                { $$ = Scalar\MagicConst\Namespace_[]; }
+;
+
+class_constant:
+      class_name_or_var T_PAAMAYIM_NEKUDOTAYIM identifier_ex
+          { $$ = Expr\ClassConstFetch[$1, $3]; }
+    /* We interpret an isolated FOO:: as an unfinished class constant fetch. It could also be
+       an unfinished static property fetch or unfinished scoped call. */
+    | class_name_or_var T_PAAMAYIM_NEKUDOTAYIM error
+          { $$ = Expr\ClassConstFetch[$1, new Expr\Error(stackAttributes(#3))]; $this->errorState = 2; }
+;
+
+array_short_syntax:
+      '[' array_pair_list ']'
+          { $attrs = attributes(); $attrs['kind'] = Expr\Array_::KIND_SHORT;
+            $$ = new Expr\Array_($2, $attrs); }
+;
+
+dereferencable_scalar:
+      T_ARRAY '(' array_pair_list ')'
+          { $attrs = attributes(); $attrs['kind'] = Expr\Array_::KIND_LONG;
+            $$ = new Expr\Array_($3, $attrs); }
+    | array_short_syntax                                    { $$ = $1; }
+    | T_CONSTANT_ENCAPSED_STRING
+          { $attrs = attributes(); $attrs['kind'] = strKind($1);
+            $$ = new Scalar\String_(Scalar\String_::parse($1), $attrs); }
+    | '"' encaps_list '"'
+          { $attrs = attributes(); $attrs['kind'] = Scalar\String_::KIND_DOUBLE_QUOTED;
+            parseEncapsed($2, '"', true); $$ = new Scalar\Encapsed($2, $attrs); }
+;
+
+scalar:
+      T_LNUMBER                                             { $$ = $this->parseLNumber($1, attributes()); }
+    | T_DNUMBER                                             { $$ = Scalar\DNumber[Scalar\DNumber::parse($1)]; }
+    | dereferencable_scalar                                 { $$ = $1; }
+    | constant                                              { $$ = $1; }
+    | class_constant                                        { $$ = $1; }
+    | T_START_HEREDOC T_ENCAPSED_AND_WHITESPACE T_END_HEREDOC
+          { $$ = $this->parseDocString($1, $2, $3, attributes(), stackAttributes(#3), true); }
+    | T_START_HEREDOC T_END_HEREDOC
+          { $$ = $this->parseDocString($1, '', $2, attributes(), stackAttributes(#2), true); }
+    | T_START_HEREDOC encaps_list T_END_HEREDOC
+          { $$ = $this->parseDocString($1, $2, $3, attributes(), stackAttributes(#3), true); }
+;
+
+optional_expr:
+      /* empty */                                           { $$ = null; }
+    | expr                                                  { $$ = $1; }
+;
+
+fully_dereferencable:
+      variable                                              { $$ = $1; }
+    | '(' expr ')'                                          { $$ = $2; }
+    | dereferencable_scalar                                 { $$ = $1; }
+    | class_constant                                        { $$ = $1; }
+;
+
+array_object_dereferencable:
+      fully_dereferencable                                  { $$ = $1; }
+    | constant                                              { $$ = $1; }
+;
+
+callable_expr:
+      callable_variable                                     { $$ = $1; }
+    | '(' expr ')'                                          { $$ = $2; }
+    | dereferencable_scalar                                 { $$ = $1; }
+;
+
+callable_variable:
+      simple_variable                                       { $$ = $1; }
+    | array_object_dereferencable '[' optional_expr ']'     { $$ = Expr\ArrayDimFetch[$1, $3]; }
+    | array_object_dereferencable '{' expr '}'              { $$ = Expr\ArrayDimFetch[$1, $3]; }
+    | function_call                                         { $$ = $1; }
+    | array_object_dereferencable T_OBJECT_OPERATOR property_name argument_list
+          { $$ = Expr\MethodCall[$1, $3, $4]; }
+    | array_object_dereferencable T_NULLSAFE_OBJECT_OPERATOR property_name argument_list
+          { $$ = Expr\NullsafeMethodCall[$1, $3, $4]; }
+;
+
+optional_plain_variable:
+      /* empty */                                           { $$ = null; }
+    | plain_variable                                        { $$ = $1; }
+;
+
+variable:
+      callable_variable                                     { $$ = $1; }
+    | static_member                                         { $$ = $1; }
+    | array_object_dereferencable T_OBJECT_OPERATOR property_name
+          { $$ = Expr\PropertyFetch[$1, $3]; }
+    | array_object_dereferencable T_NULLSAFE_OBJECT_OPERATOR property_name
+          { $$ = Expr\NullsafePropertyFetch[$1, $3]; }
+;
+
+simple_variable:
+      plain_variable                                        { $$ = $1; }
+    | '$' '{' expr '}'                                      { $$ = Expr\Variable[$3]; }
+    | '$' simple_variable                                   { $$ = Expr\Variable[$2]; }
+    | '$' error                                             { $$ = Expr\Variable[Expr\Error[]]; $this->errorState = 2; }
+;
+
+static_member_prop_name:
+      simple_variable
+          { $var = $1->name; $$ = \is_string($var) ? Node\VarLikeIdentifier[$var] : $var; }
+;
+
+static_member:
+      class_name_or_var T_PAAMAYIM_NEKUDOTAYIM static_member_prop_name
+          { $$ = Expr\StaticPropertyFetch[$1, $3]; }
+;
+
+new_variable:
+      simple_variable                                       { $$ = $1; }
+    | new_variable '[' optional_expr ']'                    { $$ = Expr\ArrayDimFetch[$1, $3]; }
+    | new_variable '{' expr '}'                             { $$ = Expr\ArrayDimFetch[$1, $3]; }
+    | new_variable T_OBJECT_OPERATOR property_name          { $$ = Expr\PropertyFetch[$1, $3]; }
+    | new_variable T_NULLSAFE_OBJECT_OPERATOR property_name { $$ = Expr\NullsafePropertyFetch[$1, $3]; }
+    | class_name T_PAAMAYIM_NEKUDOTAYIM static_member_prop_name
+          { $$ = Expr\StaticPropertyFetch[$1, $3]; }
+    | new_variable T_PAAMAYIM_NEKUDOTAYIM static_member_prop_name
+          { $$ = Expr\StaticPropertyFetch[$1, $3]; }
+;
+
+member_name:
+      identifier_ex                                         { $$ = $1; }
+    | '{' expr '}'                                          { $$ = $2; }
+    | simple_variable                                       { $$ = $1; }
+;
+
+property_name:
+      identifier                                            { $$ = $1; }
+    | '{' expr '}'                                          { $$ = $2; }
+    | simple_variable                                       { $$ = $1; }
+    | error                                                 { $$ = Expr\Error[]; $this->errorState = 2; }
+;
+
+list_expr:
+      T_LIST '(' inner_array_pair_list ')'                  { $$ = Expr\List_[$3]; }
+;
+
+array_pair_list:
+      inner_array_pair_list
+          { $$ = $1; $end = count($$)-1; if ($$[$end] === null) array_pop($$); }
+;
+
+comma_or_error:
+      ','
+    | error
+          { /* do nothing -- prevent default action of $$=$1. See #551. */ }
+;
+
+inner_array_pair_list:
+      inner_array_pair_list comma_or_error array_pair       { push($1, $3); }
+    | array_pair                                            { init($1); }
+;
+
+array_pair:
+      expr                                                  { $$ = Expr\ArrayItem[$1, null, false]; }
+    | '&' variable                                          { $$ = Expr\ArrayItem[$2, null, true]; }
+    | list_expr                                             { $$ = Expr\ArrayItem[$1, null, false]; }
+    | expr T_DOUBLE_ARROW expr                              { $$ = Expr\ArrayItem[$3, $1,   false]; }
+    | expr T_DOUBLE_ARROW '&' variable                      { $$ = Expr\ArrayItem[$4, $1,   true]; }
+    | expr T_DOUBLE_ARROW list_expr                         { $$ = Expr\ArrayItem[$3, $1,   false]; }
+    | T_ELLIPSIS expr                                       { $$ = Expr\ArrayItem[$2, null, false, attributes(), true]; }
+    | /* empty */                                           { $$ = null; }
+;
+
+encaps_list:
+      encaps_list encaps_var                                { push($1, $2); }
+    | encaps_list encaps_string_part                        { push($1, $2); }
+    | encaps_var                                            { init($1); }
+    | encaps_string_part encaps_var                         { init($1, $2); }
+;
+
+encaps_string_part:
+      T_ENCAPSED_AND_WHITESPACE                             { $$ = Scalar\EncapsedStringPart[$1]; }
+;
+
+encaps_str_varname:
+      T_STRING_VARNAME                                      { $$ = Expr\Variable[$1]; }
+;
+
+encaps_var:
+      plain_variable                                        { $$ = $1; }
+    | plain_variable '[' encaps_var_offset ']'              { $$ = Expr\ArrayDimFetch[$1, $3]; }
+    | plain_variable T_OBJECT_OPERATOR identifier           { $$ = Expr\PropertyFetch[$1, $3]; }
+    | plain_variable T_NULLSAFE_OBJECT_OPERATOR identifier  { $$ = Expr\NullsafePropertyFetch[$1, $3]; }
+    | T_DOLLAR_OPEN_CURLY_BRACES expr '}'                   { $$ = Expr\Variable[$2]; }
+    | T_DOLLAR_OPEN_CURLY_BRACES T_STRING_VARNAME '}'       { $$ = Expr\Variable[$2]; }
+    | T_DOLLAR_OPEN_CURLY_BRACES encaps_str_varname '[' expr ']' '}'
+          { $$ = Expr\ArrayDimFetch[$2, $4]; }
+    | T_CURLY_OPEN variable '}'                             { $$ = $2; }
+;
+
+encaps_var_offset:
+      T_STRING                                              { $$ = Scalar\String_[$1]; }
+    | T_NUM_STRING                                          { $$ = $this->parseNumString($1, attributes()); }
+    | '-' T_NUM_STRING                                      { $$ = $this->parseNumString('-' . $2, attributes()); }
+    | plain_variable                                        { $$ = $1; }
+;
+
+%%
diff --git a/vendor/nikic/php-parser/grammar/rebuildParsers.php b/vendor/nikic/php-parser/grammar/rebuildParsers.php
new file mode 100644
index 0000000000000000000000000000000000000000..88a53f13348ce82777dbed9632341a04fd50c504
--- /dev/null
+++ b/vendor/nikic/php-parser/grammar/rebuildParsers.php
@@ -0,0 +1,261 @@
+<?php
+
+$grammarFileToName = [
+    __DIR__ . '/php5.y' => 'Php5',
+    __DIR__ . '/php7.y' => 'Php7',
+];
+
+$tokensFile     = __DIR__ . '/tokens.y';
+$tokensTemplate = __DIR__ . '/tokens.template';
+$skeletonFile   = __DIR__ . '/parser.template';
+$tmpGrammarFile = __DIR__ . '/tmp_parser.phpy';
+$tmpResultFile  = __DIR__ . '/tmp_parser.php';
+$resultDir = __DIR__ . '/../lib/PhpParser/Parser';
+$tokensResultsFile = $resultDir . '/Tokens.php';
+
+$kmyacc = getenv('KMYACC');
+if (!$kmyacc) {
+    // Use phpyacc from dev dependencies by default.
+    $kmyacc = __DIR__ . '/../vendor/bin/phpyacc';
+}
+
+$options = array_flip($argv);
+$optionDebug = isset($options['--debug']);
+$optionKeepTmpGrammar = isset($options['--keep-tmp-grammar']);
+
+///////////////////////////////
+/// Utility regex constants ///
+///////////////////////////////
+
+const LIB = '(?(DEFINE)
+    (?<singleQuotedString>\'[^\\\\\']*+(?:\\\\.[^\\\\\']*+)*+\')
+    (?<doubleQuotedString>"[^\\\\"]*+(?:\\\\.[^\\\\"]*+)*+")
+    (?<string>(?&singleQuotedString)|(?&doubleQuotedString))
+    (?<comment>/\*[^*]*+(?:\*(?!/)[^*]*+)*+\*/)
+    (?<code>\{[^\'"/{}]*+(?:(?:(?&string)|(?&comment)|(?&code)|/)[^\'"/{}]*+)*+})
+)';
+
+const PARAMS = '\[(?<params>[^[\]]*+(?:\[(?&params)\][^[\]]*+)*+)\]';
+const ARGS   = '\((?<args>[^()]*+(?:\((?&args)\)[^()]*+)*+)\)';
+
+///////////////////
+/// Main script ///
+///////////////////
+
+$tokens = file_get_contents($tokensFile);
+
+foreach ($grammarFileToName as $grammarFile => $name) {
+    echo "Building temporary $name grammar file.\n";
+
+    $grammarCode = file_get_contents($grammarFile);
+    $grammarCode = str_replace('%tokens', $tokens, $grammarCode);
+
+    $grammarCode = resolveNodes($grammarCode);
+    $grammarCode = resolveMacros($grammarCode);
+    $grammarCode = resolveStackAccess($grammarCode);
+
+    file_put_contents($tmpGrammarFile, $grammarCode);
+
+    $additionalArgs = $optionDebug ? '-t -v' : '';
+
+    echo "Building $name parser.\n";
+    $output = execCmd("$kmyacc $additionalArgs -m $skeletonFile -p $name $tmpGrammarFile");
+
+    $resultCode = file_get_contents($tmpResultFile);
+    $resultCode = removeTrailingWhitespace($resultCode);
+
+    ensureDirExists($resultDir);
+    file_put_contents("$resultDir/$name.php", $resultCode);
+    unlink($tmpResultFile);
+
+    echo "Building token definition.\n";
+    $output = execCmd("$kmyacc -m $tokensTemplate $tmpGrammarFile");
+    rename($tmpResultFile, $tokensResultsFile);
+
+    if (!$optionKeepTmpGrammar) {
+        unlink($tmpGrammarFile);
+    }
+}
+
+///////////////////////////////
+/// Preprocessing functions ///
+///////////////////////////////
+
+function resolveNodes($code) {
+    return preg_replace_callback(
+        '~\b(?<name>[A-Z][a-zA-Z_\\\\]++)\s*' . PARAMS . '~',
+        function($matches) {
+            // recurse
+            $matches['params'] = resolveNodes($matches['params']);
+
+            $params = magicSplit(
+                '(?:' . PARAMS . '|' . ARGS . ')(*SKIP)(*FAIL)|,',
+                $matches['params']
+            );
+
+            $paramCode = '';
+            foreach ($params as $param) {
+                $paramCode .= $param . ', ';
+            }
+
+            return 'new ' . $matches['name'] . '(' . $paramCode . 'attributes())';
+        },
+        $code
+    );
+}
+
+function resolveMacros($code) {
+    return preg_replace_callback(
+        '~\b(?<!::|->)(?!array\()(?<name>[a-z][A-Za-z]++)' . ARGS . '~',
+        function($matches) {
+            // recurse
+            $matches['args'] = resolveMacros($matches['args']);
+
+            $name = $matches['name'];
+            $args = magicSplit(
+                '(?:' . PARAMS . '|' . ARGS . ')(*SKIP)(*FAIL)|,',
+                $matches['args']
+            );
+
+            if ('attributes' === $name) {
+                assertArgs(0, $args, $name);
+                return '$this->startAttributeStack[#1] + $this->endAttributes';
+            }
+
+            if ('stackAttributes' === $name) {
+                assertArgs(1, $args, $name);
+                return '$this->startAttributeStack[' . $args[0] . ']'
+                     . ' + $this->endAttributeStack[' . $args[0] . ']';
+            }
+
+            if ('init' === $name) {
+                return '$$ = array(' . implode(', ', $args) . ')';
+            }
+
+            if ('push' === $name) {
+                assertArgs(2, $args, $name);
+
+                return $args[0] . '[] = ' . $args[1] . '; $$ = ' . $args[0];
+            }
+
+            if ('pushNormalizing' === $name) {
+                assertArgs(2, $args, $name);
+
+                return 'if (is_array(' . $args[1] . ')) { $$ = array_merge(' . $args[0] . ', ' . $args[1] . '); }'
+                     . ' else { ' . $args[0] . '[] = ' . $args[1] . '; $$ = ' . $args[0] . '; }';
+            }
+
+            if ('toArray' == $name) {
+                assertArgs(1, $args, $name);
+
+                return 'is_array(' . $args[0] . ') ? ' . $args[0] . ' : array(' . $args[0] . ')';
+            }
+
+            if ('parseVar' === $name) {
+                assertArgs(1, $args, $name);
+
+                return 'substr(' . $args[0] . ', 1)';
+            }
+
+            if ('parseEncapsed' === $name) {
+                assertArgs(3, $args, $name);
+
+                return 'foreach (' . $args[0] . ' as $s) { if ($s instanceof Node\Scalar\EncapsedStringPart) {'
+                     . ' $s->value = Node\Scalar\String_::parseEscapeSequences($s->value, ' . $args[1] . ', ' . $args[2] . '); } }';
+            }
+
+            if ('makeNop' === $name) {
+                assertArgs(3, $args, $name);
+
+                return '$startAttributes = ' . $args[1] . ';'
+                . ' if (isset($startAttributes[\'comments\']))'
+                . ' { ' . $args[0] . ' = new Stmt\Nop($startAttributes + ' . $args[2] . '); }'
+                . ' else { ' . $args[0] . ' = null; }';
+            }
+
+            if ('makeZeroLengthNop' == $name) {
+                assertArgs(2, $args, $name);
+
+                return '$startAttributes = ' . $args[1] . ';'
+                    . ' if (isset($startAttributes[\'comments\']))'
+                    . ' { ' . $args[0] . ' = new Stmt\Nop($this->createCommentNopAttributes($startAttributes[\'comments\'])); }'
+                    . ' else { ' . $args[0] . ' = null; }';
+            }
+
+            if ('strKind' === $name) {
+                assertArgs(1, $args, $name);
+
+                return '(' . $args[0] . '[0] === "\'" || (' . $args[0] . '[1] === "\'" && '
+                     . '(' . $args[0] . '[0] === \'b\' || ' . $args[0] . '[0] === \'B\')) '
+                     . '? Scalar\String_::KIND_SINGLE_QUOTED : Scalar\String_::KIND_DOUBLE_QUOTED)';
+            }
+
+            if ('prependLeadingComments' === $name) {
+                assertArgs(1, $args, $name);
+
+                return '$attrs = $this->startAttributeStack[#1]; $stmts = ' . $args[0] . '; '
+                . 'if (!empty($attrs[\'comments\'])) {'
+                . '$stmts[0]->setAttribute(\'comments\', '
+                . 'array_merge($attrs[\'comments\'], $stmts[0]->getAttribute(\'comments\', []))); }';
+            }
+
+            return $matches[0];
+        },
+        $code
+    );
+}
+
+function assertArgs($num, $args, $name) {
+    if ($num != count($args)) {
+        die('Wrong argument count for ' . $name . '().');
+    }
+}
+
+function resolveStackAccess($code) {
+    $code = preg_replace('/\$\d+/', '$this->semStack[$0]', $code);
+    $code = preg_replace('/#(\d+)/', '$$1', $code);
+    return $code;
+}
+
+function removeTrailingWhitespace($code) {
+    $lines = explode("\n", $code);
+    $lines = array_map('rtrim', $lines);
+    return implode("\n", $lines);
+}
+
+function ensureDirExists($dir) {
+    if (!is_dir($dir)) {
+        mkdir($dir, 0777, true);
+    }
+}
+
+function execCmd($cmd) {
+    $output = trim(shell_exec("$cmd 2>&1"));
+    if ($output !== "") {
+        echo "> " . $cmd . "\n";
+        echo $output;
+    }
+    return $output;
+}
+
+//////////////////////////////
+/// Regex helper functions ///
+//////////////////////////////
+
+function regex($regex) {
+    return '~' . LIB . '(?:' . str_replace('~', '\~', $regex) . ')~';
+}
+
+function magicSplit($regex, $string) {
+    $pieces = preg_split(regex('(?:(?&string)|(?&comment)|(?&code))(*SKIP)(*FAIL)|' . $regex), $string);
+
+    foreach ($pieces as &$piece) {
+        $piece = trim($piece);
+    }
+
+    if ($pieces === ['']) {
+        return [];
+    }
+
+    return $pieces;
+}
diff --git a/vendor/nikic/php-parser/grammar/tokens.template b/vendor/nikic/php-parser/grammar/tokens.template
new file mode 100644
index 0000000000000000000000000000000000000000..ba4e4901c0bfc12b49d193ab4e380e1ac4cdf4f2
--- /dev/null
+++ b/vendor/nikic/php-parser/grammar/tokens.template
@@ -0,0 +1,17 @@
+<?php
+$meta #
+#semval($) $this->semValue
+#semval($,%t) $this->semValue
+#semval(%n) $this->stackPos-(%l-%n)
+#semval(%n,%t) $this->stackPos-(%l-%n)
+
+namespace PhpParser\Parser;
+#include;
+
+/* GENERATED file based on grammar/tokens.y */
+final class Tokens
+{
+#tokenval
+    const %s = %n;
+#endtokenval
+}
diff --git a/vendor/nikic/php-parser/grammar/tokens.y b/vendor/nikic/php-parser/grammar/tokens.y
new file mode 100644
index 0000000000000000000000000000000000000000..b0b0360cd26574b786343d4fe103624e18ce1c21
--- /dev/null
+++ b/vendor/nikic/php-parser/grammar/tokens.y
@@ -0,0 +1,113 @@
+/* We currently rely on the token ID mapping to be the same between PHP 5 and PHP 7 - so the same lexer can be used for
+ * both. This is enforced by sharing this token file. */
+
+%right T_THROW
+%left T_INCLUDE T_INCLUDE_ONCE T_EVAL T_REQUIRE T_REQUIRE_ONCE
+%left ','
+%left T_LOGICAL_OR
+%left T_LOGICAL_XOR
+%left T_LOGICAL_AND
+%right T_PRINT
+%right T_YIELD
+%right T_DOUBLE_ARROW
+%right T_YIELD_FROM
+%left '=' T_PLUS_EQUAL T_MINUS_EQUAL T_MUL_EQUAL T_DIV_EQUAL T_CONCAT_EQUAL T_MOD_EQUAL T_AND_EQUAL T_OR_EQUAL T_XOR_EQUAL T_SL_EQUAL T_SR_EQUAL T_POW_EQUAL T_COALESCE_EQUAL
+%left '?' ':'
+%right T_COALESCE
+%left T_BOOLEAN_OR
+%left T_BOOLEAN_AND
+%left '|'
+%left '^'
+%left '&'
+%nonassoc T_IS_EQUAL T_IS_NOT_EQUAL T_IS_IDENTICAL T_IS_NOT_IDENTICAL T_SPACESHIP
+%nonassoc '<' T_IS_SMALLER_OR_EQUAL '>' T_IS_GREATER_OR_EQUAL
+%left T_SL T_SR
+%left '+' '-' '.'
+%left '*' '/' '%'
+%right '!'
+%nonassoc T_INSTANCEOF
+%right '~' T_INC T_DEC T_INT_CAST T_DOUBLE_CAST T_STRING_CAST T_ARRAY_CAST T_OBJECT_CAST T_BOOL_CAST T_UNSET_CAST '@'
+%right T_POW
+%right '['
+%nonassoc T_NEW T_CLONE
+%token T_EXIT
+%token T_IF
+%left T_ELSEIF
+%left T_ELSE
+%left T_ENDIF
+%token T_LNUMBER
+%token T_DNUMBER
+%token T_STRING
+%token T_STRING_VARNAME
+%token T_VARIABLE
+%token T_NUM_STRING
+%token T_INLINE_HTML
+%token T_ENCAPSED_AND_WHITESPACE
+%token T_CONSTANT_ENCAPSED_STRING
+%token T_ECHO
+%token T_DO
+%token T_WHILE
+%token T_ENDWHILE
+%token T_FOR
+%token T_ENDFOR
+%token T_FOREACH
+%token T_ENDFOREACH
+%token T_DECLARE
+%token T_ENDDECLARE
+%token T_AS
+%token T_SWITCH
+%token T_MATCH
+%token T_ENDSWITCH
+%token T_CASE
+%token T_DEFAULT
+%token T_BREAK
+%token T_CONTINUE
+%token T_GOTO
+%token T_FUNCTION
+%token T_FN
+%token T_CONST
+%token T_RETURN
+%token T_TRY
+%token T_CATCH
+%token T_FINALLY
+%token T_THROW
+%token T_USE
+%token T_INSTEADOF
+%token T_GLOBAL
+%right T_STATIC T_ABSTRACT T_FINAL T_PRIVATE T_PROTECTED T_PUBLIC
+%token T_VAR
+%token T_UNSET
+%token T_ISSET
+%token T_EMPTY
+%token T_HALT_COMPILER
+%token T_CLASS
+%token T_TRAIT
+%token T_INTERFACE
+%token T_EXTENDS
+%token T_IMPLEMENTS
+%token T_OBJECT_OPERATOR
+%token T_NULLSAFE_OBJECT_OPERATOR
+%token T_DOUBLE_ARROW
+%token T_LIST
+%token T_ARRAY
+%token T_CALLABLE
+%token T_CLASS_C
+%token T_TRAIT_C
+%token T_METHOD_C
+%token T_FUNC_C
+%token T_LINE
+%token T_FILE
+%token T_START_HEREDOC
+%token T_END_HEREDOC
+%token T_DOLLAR_OPEN_CURLY_BRACES
+%token T_CURLY_OPEN
+%token T_PAAMAYIM_NEKUDOTAYIM
+%token T_NAMESPACE
+%token T_NS_C
+%token T_DIR
+%token T_NS_SEPARATOR
+%token T_ELLIPSIS
+%token T_NAME_FULLY_QUALIFIED
+%token T_NAME_QUALIFIED
+%token T_NAME_RELATIVE
+%token T_ATTRIBUTE
\ No newline at end of file
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Builder.php b/vendor/nikic/php-parser/lib/PhpParser/Builder.php
new file mode 100644
index 0000000000000000000000000000000000000000..26d8921efc6ad4294a1a059e2d545498ac7621ad
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Builder.php
@@ -0,0 +1,13 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser;
+
+interface Builder
+{
+    /**
+     * Returns the built node.
+     *
+     * @return Node The built node
+     */
+    public function getNode() : Node;
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Builder/Class_.php b/vendor/nikic/php-parser/lib/PhpParser/Builder/Class_.php
new file mode 100644
index 0000000000000000000000000000000000000000..c2f2468914250f3818f3afd2e836ed674dde62e6
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Builder/Class_.php
@@ -0,0 +1,122 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Builder;
+
+use PhpParser;
+use PhpParser\BuilderHelpers;
+use PhpParser\Node\Name;
+use PhpParser\Node\Stmt;
+
+class Class_ extends Declaration
+{
+    protected $name;
+
+    protected $extends = null;
+    protected $implements = [];
+    protected $flags = 0;
+
+    protected $uses = [];
+    protected $constants = [];
+    protected $properties = [];
+    protected $methods = [];
+
+    /**
+     * Creates a class builder.
+     *
+     * @param string $name Name of the class
+     */
+    public function __construct(string $name) {
+        $this->name = $name;
+    }
+
+    /**
+     * Extends a class.
+     *
+     * @param Name|string $class Name of class to extend
+     *
+     * @return $this The builder instance (for fluid interface)
+     */
+    public function extend($class) {
+        $this->extends = BuilderHelpers::normalizeName($class);
+
+        return $this;
+    }
+
+    /**
+     * Implements one or more interfaces.
+     *
+     * @param Name|string ...$interfaces Names of interfaces to implement
+     *
+     * @return $this The builder instance (for fluid interface)
+     */
+    public function implement(...$interfaces) {
+        foreach ($interfaces as $interface) {
+            $this->implements[] = BuilderHelpers::normalizeName($interface);
+        }
+
+        return $this;
+    }
+
+    /**
+     * Makes the class abstract.
+     *
+     * @return $this The builder instance (for fluid interface)
+     */
+    public function makeAbstract() {
+        $this->flags = BuilderHelpers::addModifier($this->flags, Stmt\Class_::MODIFIER_ABSTRACT);
+
+        return $this;
+    }
+
+    /**
+     * Makes the class final.
+     *
+     * @return $this The builder instance (for fluid interface)
+     */
+    public function makeFinal() {
+        $this->flags = BuilderHelpers::addModifier($this->flags, Stmt\Class_::MODIFIER_FINAL);
+
+        return $this;
+    }
+
+    /**
+     * Adds a statement.
+     *
+     * @param Stmt|PhpParser\Builder $stmt The statement to add
+     *
+     * @return $this The builder instance (for fluid interface)
+     */
+    public function addStmt($stmt) {
+        $stmt = BuilderHelpers::normalizeNode($stmt);
+
+        $targets = [
+            Stmt\TraitUse::class    => &$this->uses,
+            Stmt\ClassConst::class  => &$this->constants,
+            Stmt\Property::class    => &$this->properties,
+            Stmt\ClassMethod::class => &$this->methods,
+        ];
+
+        $class = \get_class($stmt);
+        if (!isset($targets[$class])) {
+            throw new \LogicException(sprintf('Unexpected node of type "%s"', $stmt->getType()));
+        }
+
+        $targets[$class][] = $stmt;
+
+        return $this;
+    }
+
+    /**
+     * Returns the built class node.
+     *
+     * @return Stmt\Class_ The built class node
+     */
+    public function getNode() : PhpParser\Node {
+        return new Stmt\Class_($this->name, [
+            'flags' => $this->flags,
+            'extends' => $this->extends,
+            'implements' => $this->implements,
+            'stmts' => array_merge($this->uses, $this->constants, $this->properties, $this->methods),
+        ], $this->attributes);
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Builder/Declaration.php b/vendor/nikic/php-parser/lib/PhpParser/Builder/Declaration.php
new file mode 100644
index 0000000000000000000000000000000000000000..830949928aac0f9583e1e38363c9c8f5f12dea1e
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Builder/Declaration.php
@@ -0,0 +1,43 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Builder;
+
+use PhpParser;
+use PhpParser\BuilderHelpers;
+
+abstract class Declaration implements PhpParser\Builder
+{
+    protected $attributes = [];
+
+    abstract public function addStmt($stmt);
+
+    /**
+     * Adds multiple statements.
+     *
+     * @param array $stmts The statements to add
+     *
+     * @return $this The builder instance (for fluid interface)
+     */
+    public function addStmts(array $stmts) {
+        foreach ($stmts as $stmt) {
+            $this->addStmt($stmt);
+        }
+
+        return $this;
+    }
+
+    /**
+     * Sets doc comment for the declaration.
+     *
+     * @param PhpParser\Comment\Doc|string $docComment Doc comment to set
+     *
+     * @return $this The builder instance (for fluid interface)
+     */
+    public function setDocComment($docComment) {
+        $this->attributes['comments'] = [
+            BuilderHelpers::normalizeDocComment($docComment)
+        ];
+
+        return $this;
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Builder/FunctionLike.php b/vendor/nikic/php-parser/lib/PhpParser/Builder/FunctionLike.php
new file mode 100644
index 0000000000000000000000000000000000000000..8e7db399d395a7e47dd8fa940f0f82032c123c15
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Builder/FunctionLike.php
@@ -0,0 +1,74 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Builder;
+
+use PhpParser\BuilderHelpers;
+use PhpParser\Node;
+
+abstract class FunctionLike extends Declaration
+{
+    protected $returnByRef = false;
+    protected $params = [];
+
+    /** @var string|Node\Name|Node\NullableType|null */
+    protected $returnType = null;
+
+    /**
+     * Make the function return by reference.
+     *
+     * @return $this The builder instance (for fluid interface)
+     */
+    public function makeReturnByRef() {
+        $this->returnByRef = true;
+
+        return $this;
+    }
+
+    /**
+     * Adds a parameter.
+     *
+     * @param Node\Param|Param $param The parameter to add
+     *
+     * @return $this The builder instance (for fluid interface)
+     */
+    public function addParam($param) {
+        $param = BuilderHelpers::normalizeNode($param);
+
+        if (!$param instanceof Node\Param) {
+            throw new \LogicException(sprintf('Expected parameter node, got "%s"', $param->getType()));
+        }
+
+        $this->params[] = $param;
+
+        return $this;
+    }
+
+    /**
+     * Adds multiple parameters.
+     *
+     * @param array $params The parameters to add
+     *
+     * @return $this The builder instance (for fluid interface)
+     */
+    public function addParams(array $params) {
+        foreach ($params as $param) {
+            $this->addParam($param);
+        }
+
+        return $this;
+    }
+
+    /**
+     * Sets the return type for PHP 7.
+     *
+     * @param string|Node\Name|Node\NullableType $type One of array, callable, string, int, float,
+     *                                                 bool, iterable, or a class/interface name.
+     *
+     * @return $this The builder instance (for fluid interface)
+     */
+    public function setReturnType($type) {
+        $this->returnType = BuilderHelpers::normalizeType($type);
+
+        return $this;
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Builder/Function_.php b/vendor/nikic/php-parser/lib/PhpParser/Builder/Function_.php
new file mode 100644
index 0000000000000000000000000000000000000000..56eda2a8125f6645de64cd0242a2cdca56d8bfd3
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Builder/Function_.php
@@ -0,0 +1,50 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Builder;
+
+use PhpParser;
+use PhpParser\BuilderHelpers;
+use PhpParser\Node;
+use PhpParser\Node\Stmt;
+
+class Function_ extends FunctionLike
+{
+    protected $name;
+    protected $stmts = [];
+
+    /**
+     * Creates a function builder.
+     *
+     * @param string $name Name of the function
+     */
+    public function __construct(string $name) {
+        $this->name = $name;
+    }
+
+    /**
+     * Adds a statement.
+     *
+     * @param Node|PhpParser\Builder $stmt The statement to add
+     *
+     * @return $this The builder instance (for fluid interface)
+     */
+    public function addStmt($stmt) {
+        $this->stmts[] = BuilderHelpers::normalizeStmt($stmt);
+
+        return $this;
+    }
+
+    /**
+     * Returns the built function node.
+     *
+     * @return Stmt\Function_ The built function node
+     */
+    public function getNode() : Node {
+        return new Stmt\Function_($this->name, [
+            'byRef'      => $this->returnByRef,
+            'params'     => $this->params,
+            'returnType' => $this->returnType,
+            'stmts'      => $this->stmts,
+        ], $this->attributes);
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Builder/Interface_.php b/vendor/nikic/php-parser/lib/PhpParser/Builder/Interface_.php
new file mode 100644
index 0000000000000000000000000000000000000000..87e5b93ee1d8feec142198ee51109553e76b486e
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Builder/Interface_.php
@@ -0,0 +1,75 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Builder;
+
+use PhpParser;
+use PhpParser\BuilderHelpers;
+use PhpParser\Node\Name;
+use PhpParser\Node\Stmt;
+
+class Interface_ extends Declaration
+{
+    protected $name;
+    protected $extends = [];
+    protected $constants = [];
+    protected $methods = [];
+
+    /**
+     * Creates an interface builder.
+     *
+     * @param string $name Name of the interface
+     */
+    public function __construct(string $name) {
+        $this->name = $name;
+    }
+
+    /**
+     * Extends one or more interfaces.
+     *
+     * @param Name|string ...$interfaces Names of interfaces to extend
+     *
+     * @return $this The builder instance (for fluid interface)
+     */
+    public function extend(...$interfaces) {
+        foreach ($interfaces as $interface) {
+            $this->extends[] = BuilderHelpers::normalizeName($interface);
+        }
+
+        return $this;
+    }
+
+    /**
+     * Adds a statement.
+     *
+     * @param Stmt|PhpParser\Builder $stmt The statement to add
+     *
+     * @return $this The builder instance (for fluid interface)
+     */
+    public function addStmt($stmt) {
+        $stmt = BuilderHelpers::normalizeNode($stmt);
+
+        if ($stmt instanceof Stmt\ClassConst) {
+            $this->constants[] = $stmt;
+        } elseif ($stmt instanceof Stmt\ClassMethod) {
+            // we erase all statements in the body of an interface method
+            $stmt->stmts = null;
+            $this->methods[] = $stmt;
+        } else {
+            throw new \LogicException(sprintf('Unexpected node of type "%s"', $stmt->getType()));
+        }
+
+        return $this;
+    }
+
+    /**
+     * Returns the built interface node.
+     *
+     * @return Stmt\Interface_ The built interface node
+     */
+    public function getNode() : PhpParser\Node {
+        return new Stmt\Interface_($this->name, [
+            'extends' => $this->extends,
+            'stmts' => array_merge($this->constants, $this->methods),
+        ], $this->attributes);
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Builder/Method.php b/vendor/nikic/php-parser/lib/PhpParser/Builder/Method.php
new file mode 100644
index 0000000000000000000000000000000000000000..a3e8676592d4ffda874727e96dfd16ee2ba4ce9e
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Builder/Method.php
@@ -0,0 +1,129 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Builder;
+
+use PhpParser;
+use PhpParser\BuilderHelpers;
+use PhpParser\Node;
+use PhpParser\Node\Stmt;
+
+class Method extends FunctionLike
+{
+    protected $name;
+    protected $flags = 0;
+
+    /** @var array|null */
+    protected $stmts = [];
+
+    /**
+     * Creates a method builder.
+     *
+     * @param string $name Name of the method
+     */
+    public function __construct(string $name) {
+        $this->name = $name;
+    }
+
+    /**
+     * Makes the method public.
+     *
+     * @return $this The builder instance (for fluid interface)
+     */
+    public function makePublic() {
+        $this->flags = BuilderHelpers::addModifier($this->flags, Stmt\Class_::MODIFIER_PUBLIC);
+
+        return $this;
+    }
+
+    /**
+     * Makes the method protected.
+     *
+     * @return $this The builder instance (for fluid interface)
+     */
+    public function makeProtected() {
+        $this->flags = BuilderHelpers::addModifier($this->flags, Stmt\Class_::MODIFIER_PROTECTED);
+
+        return $this;
+    }
+
+    /**
+     * Makes the method private.
+     *
+     * @return $this The builder instance (for fluid interface)
+     */
+    public function makePrivate() {
+        $this->flags = BuilderHelpers::addModifier($this->flags, Stmt\Class_::MODIFIER_PRIVATE);
+
+        return $this;
+    }
+
+    /**
+     * Makes the method static.
+     *
+     * @return $this The builder instance (for fluid interface)
+     */
+    public function makeStatic() {
+        $this->flags = BuilderHelpers::addModifier($this->flags, Stmt\Class_::MODIFIER_STATIC);
+
+        return $this;
+    }
+
+    /**
+     * Makes the method abstract.
+     *
+     * @return $this The builder instance (for fluid interface)
+     */
+    public function makeAbstract() {
+        if (!empty($this->stmts)) {
+            throw new \LogicException('Cannot make method with statements abstract');
+        }
+
+        $this->flags = BuilderHelpers::addModifier($this->flags, Stmt\Class_::MODIFIER_ABSTRACT);
+        $this->stmts = null; // abstract methods don't have statements
+
+        return $this;
+    }
+
+    /**
+     * Makes the method final.
+     *
+     * @return $this The builder instance (for fluid interface)
+     */
+    public function makeFinal() {
+        $this->flags = BuilderHelpers::addModifier($this->flags, Stmt\Class_::MODIFIER_FINAL);
+
+        return $this;
+    }
+
+    /**
+     * Adds a statement.
+     *
+     * @param Node|PhpParser\Builder $stmt The statement to add
+     *
+     * @return $this The builder instance (for fluid interface)
+     */
+    public function addStmt($stmt) {
+        if (null === $this->stmts) {
+            throw new \LogicException('Cannot add statements to an abstract method');
+        }
+
+        $this->stmts[] = BuilderHelpers::normalizeStmt($stmt);
+
+        return $this;
+    }
+
+    /**
+     * Returns the built method node.
+     *
+     * @return Stmt\ClassMethod The built method node
+     */
+    public function getNode() : Node {
+        return new Stmt\ClassMethod($this->name, [
+            'flags'      => $this->flags,
+            'byRef'      => $this->returnByRef,
+            'params'     => $this->params,
+            'returnType' => $this->returnType,
+            'stmts'      => $this->stmts,
+        ], $this->attributes);
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Builder/Namespace_.php b/vendor/nikic/php-parser/lib/PhpParser/Builder/Namespace_.php
new file mode 100644
index 0000000000000000000000000000000000000000..b9ccab3ec1c9de755134744a5ab762158d1b8637
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Builder/Namespace_.php
@@ -0,0 +1,45 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Builder;
+
+use PhpParser;
+use PhpParser\BuilderHelpers;
+use PhpParser\Node;
+use PhpParser\Node\Stmt;
+
+class Namespace_ extends Declaration
+{
+    private $name;
+    private $stmts = [];
+
+    /**
+     * Creates a namespace builder.
+     *
+     * @param Node\Name|string|null $name Name of the namespace
+     */
+    public function __construct($name) {
+        $this->name = null !== $name ? BuilderHelpers::normalizeName($name) : null;
+    }
+
+    /**
+     * Adds a statement.
+     *
+     * @param Node|PhpParser\Builder $stmt The statement to add
+     *
+     * @return $this The builder instance (for fluid interface)
+     */
+    public function addStmt($stmt) {
+        $this->stmts[] = BuilderHelpers::normalizeStmt($stmt);
+
+        return $this;
+    }
+
+    /**
+     * Returns the built node.
+     *
+     * @return Node The built node
+     */
+    public function getNode() : Node {
+        return new Stmt\Namespace_($this->name, $this->stmts, $this->attributes);
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Builder/Param.php b/vendor/nikic/php-parser/lib/PhpParser/Builder/Param.php
new file mode 100644
index 0000000000000000000000000000000000000000..c6491786e34bc0311e4be053ba49e0037bdc589b
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Builder/Param.php
@@ -0,0 +1,106 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Builder;
+
+use PhpParser;
+use PhpParser\BuilderHelpers;
+use PhpParser\Node;
+
+class Param implements PhpParser\Builder
+{
+    protected $name;
+
+    protected $default = null;
+
+    /** @var Node\Identifier|Node\Name|Node\NullableType|null */
+    protected $type = null;
+
+    protected $byRef = false;
+
+    protected $variadic = false;
+
+    /**
+     * Creates a parameter builder.
+     *
+     * @param string $name Name of the parameter
+     */
+    public function __construct(string $name) {
+        $this->name = $name;
+    }
+
+    /**
+     * Sets default value for the parameter.
+     *
+     * @param mixed $value Default value to use
+     *
+     * @return $this The builder instance (for fluid interface)
+     */
+    public function setDefault($value) {
+        $this->default = BuilderHelpers::normalizeValue($value);
+
+        return $this;
+    }
+
+    /**
+     * Sets type for the parameter.
+     *
+     * @param string|Node\Name|Node\NullableType|Node\UnionType $type Parameter type
+     *
+     * @return $this The builder instance (for fluid interface)
+     */
+    public function setType($type) {
+        $this->type = BuilderHelpers::normalizeType($type);
+        if ($this->type == 'void') {
+            throw new \LogicException('Parameter type cannot be void');
+        }
+
+        return $this;
+    }
+
+    /**
+     * Sets type for the parameter.
+     *
+     * @param string|Node\Name|Node\NullableType|Node\UnionType $type Parameter type
+     *
+     * @return $this The builder instance (for fluid interface)
+     *
+     * @deprecated Use setType() instead
+     */
+    public function setTypeHint($type) {
+        return $this->setType($type);
+    }
+
+    /**
+     * Make the parameter accept the value by reference.
+     *
+     * @return $this The builder instance (for fluid interface)
+     */
+    public function makeByRef() {
+        $this->byRef = true;
+
+        return $this;
+    }
+
+    /**
+     * Make the parameter variadic
+     *
+     * @return $this The builder instance (for fluid interface)
+     */
+    public function makeVariadic() {
+        $this->variadic = true;
+
+        return $this;
+    }
+
+    /**
+     * Returns the built parameter node.
+     *
+     * @return Node\Param The built parameter node
+     */
+    public function getNode() : Node {
+        return new Node\Param(
+            new Node\Expr\Variable($this->name),
+            $this->default, $this->type, $this->byRef, $this->variadic
+        );
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Builder/Property.php b/vendor/nikic/php-parser/lib/PhpParser/Builder/Property.php
new file mode 100644
index 0000000000000000000000000000000000000000..1f3bdb27234b971f996c026754abe06d783cb943
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Builder/Property.php
@@ -0,0 +1,132 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Builder;
+
+use PhpParser;
+use PhpParser\BuilderHelpers;
+use PhpParser\Node\Identifier;
+use PhpParser\Node\Name;
+use PhpParser\Node\NullableType;
+use PhpParser\Node\Stmt;
+
+class Property implements PhpParser\Builder
+{
+    protected $name;
+
+    protected $flags = 0;
+    protected $default = null;
+    protected $attributes = [];
+
+    /** @var null|Identifier|Name|NullableType */
+    protected $type;
+
+    /**
+     * Creates a property builder.
+     *
+     * @param string $name Name of the property
+     */
+    public function __construct(string $name) {
+        $this->name = $name;
+    }
+
+    /**
+     * Makes the property public.
+     *
+     * @return $this The builder instance (for fluid interface)
+     */
+    public function makePublic() {
+        $this->flags = BuilderHelpers::addModifier($this->flags, Stmt\Class_::MODIFIER_PUBLIC);
+
+        return $this;
+    }
+
+    /**
+     * Makes the property protected.
+     *
+     * @return $this The builder instance (for fluid interface)
+     */
+    public function makeProtected() {
+        $this->flags = BuilderHelpers::addModifier($this->flags, Stmt\Class_::MODIFIER_PROTECTED);
+
+        return $this;
+    }
+
+    /**
+     * Makes the property private.
+     *
+     * @return $this The builder instance (for fluid interface)
+     */
+    public function makePrivate() {
+        $this->flags = BuilderHelpers::addModifier($this->flags, Stmt\Class_::MODIFIER_PRIVATE);
+
+        return $this;
+    }
+
+    /**
+     * Makes the property static.
+     *
+     * @return $this The builder instance (for fluid interface)
+     */
+    public function makeStatic() {
+        $this->flags = BuilderHelpers::addModifier($this->flags, Stmt\Class_::MODIFIER_STATIC);
+
+        return $this;
+    }
+
+    /**
+     * Sets default value for the property.
+     *
+     * @param mixed $value Default value to use
+     *
+     * @return $this The builder instance (for fluid interface)
+     */
+    public function setDefault($value) {
+        $this->default = BuilderHelpers::normalizeValue($value);
+
+        return $this;
+    }
+
+    /**
+     * Sets doc comment for the property.
+     *
+     * @param PhpParser\Comment\Doc|string $docComment Doc comment to set
+     *
+     * @return $this The builder instance (for fluid interface)
+     */
+    public function setDocComment($docComment) {
+        $this->attributes = [
+            'comments' => [BuilderHelpers::normalizeDocComment($docComment)]
+        ];
+
+        return $this;
+    }
+
+    /**
+     * Sets the property type for PHP 7.4+.
+     *
+     * @param string|Name|NullableType|Identifier $type
+     *
+     * @return $this
+     */
+    public function setType($type) {
+        $this->type = BuilderHelpers::normalizeType($type);
+
+        return $this;
+    }
+
+    /**
+     * Returns the built class node.
+     *
+     * @return Stmt\Property The built property node
+     */
+    public function getNode() : PhpParser\Node {
+        return new Stmt\Property(
+            $this->flags !== 0 ? $this->flags : Stmt\Class_::MODIFIER_PUBLIC,
+            [
+                new Stmt\PropertyProperty($this->name, $this->default)
+            ],
+            $this->attributes,
+            $this->type
+        );
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Builder/TraitUse.php b/vendor/nikic/php-parser/lib/PhpParser/Builder/TraitUse.php
new file mode 100644
index 0000000000000000000000000000000000000000..311e8cd7b65cb9947127e8d68b54223f3bfd1203
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Builder/TraitUse.php
@@ -0,0 +1,64 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Builder;
+
+use PhpParser\Builder;
+use PhpParser\BuilderHelpers;
+use PhpParser\Node;
+use PhpParser\Node\Stmt;
+
+class TraitUse implements Builder
+{
+    protected $traits = [];
+    protected $adaptations = [];
+
+    /**
+     * Creates a trait use builder.
+     *
+     * @param Node\Name|string ...$traits Names of used traits
+     */
+    public function __construct(...$traits) {
+        foreach ($traits as $trait) {
+            $this->and($trait);
+        }
+    }
+
+    /**
+     * Adds used trait.
+     *
+     * @param Node\Name|string $trait Trait name
+     *
+     * @return $this The builder instance (for fluid interface)
+     */
+    public function and($trait) {
+        $this->traits[] = BuilderHelpers::normalizeName($trait);
+        return $this;
+    }
+
+    /**
+     * Adds trait adaptation.
+     *
+     * @param Stmt\TraitUseAdaptation|Builder\TraitUseAdaptation $adaptation Trait adaptation
+     *
+     * @return $this The builder instance (for fluid interface)
+     */
+    public function with($adaptation) {
+        $adaptation = BuilderHelpers::normalizeNode($adaptation);
+
+        if (!$adaptation instanceof Stmt\TraitUseAdaptation) {
+            throw new \LogicException('Adaptation must have type TraitUseAdaptation');
+        }
+
+        $this->adaptations[] = $adaptation;
+        return $this;
+    }
+
+    /**
+     * Returns the built node.
+     *
+     * @return Node The built node
+     */
+    public function getNode() : Node {
+        return new Stmt\TraitUse($this->traits, $this->adaptations);
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Builder/TraitUseAdaptation.php b/vendor/nikic/php-parser/lib/PhpParser/Builder/TraitUseAdaptation.php
new file mode 100644
index 0000000000000000000000000000000000000000..eb6c0b622dd0c822dd76374675e791f923935674
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Builder/TraitUseAdaptation.php
@@ -0,0 +1,148 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Builder;
+
+use PhpParser\Builder;
+use PhpParser\BuilderHelpers;
+use PhpParser\Node;
+use PhpParser\Node\Stmt;
+
+class TraitUseAdaptation implements Builder
+{
+    const TYPE_UNDEFINED  = 0;
+    const TYPE_ALIAS      = 1;
+    const TYPE_PRECEDENCE = 2;
+
+    /** @var int Type of building adaptation */
+    protected $type;
+
+    protected $trait;
+    protected $method;
+
+    protected $modifier = null;
+    protected $alias = null;
+
+    protected $insteadof = [];
+
+    /**
+     * Creates a trait use adaptation builder.
+     *
+     * @param Node\Name|string|null  $trait  Name of adaptated trait
+     * @param Node\Identifier|string $method Name of adaptated method
+     */
+    public function __construct($trait, $method) {
+        $this->type = self::TYPE_UNDEFINED;
+
+        $this->trait = is_null($trait)? null: BuilderHelpers::normalizeName($trait);
+        $this->method = BuilderHelpers::normalizeIdentifier($method);
+    }
+
+    /**
+     * Sets alias of method.
+     *
+     * @param Node\Identifier|string $alias Alias for adaptated method
+     *
+     * @return $this The builder instance (for fluid interface)
+     */
+    public function as($alias) {
+        if ($this->type === self::TYPE_UNDEFINED) {
+            $this->type = self::TYPE_ALIAS;
+        }
+
+        if ($this->type !== self::TYPE_ALIAS) {
+            throw new \LogicException('Cannot set alias for not alias adaptation buider');
+        }
+
+        $this->alias = $alias;
+        return $this;
+    }
+
+    /**
+     * Sets adaptated method public.
+     *
+     * @return $this The builder instance (for fluid interface)
+     */
+    public function makePublic() {
+        $this->setModifier(Stmt\Class_::MODIFIER_PUBLIC);
+        return $this;
+    }
+
+    /**
+     * Sets adaptated method protected.
+     *
+     * @return $this The builder instance (for fluid interface)
+     */
+    public function makeProtected() {
+        $this->setModifier(Stmt\Class_::MODIFIER_PROTECTED);
+        return $this;
+    }
+
+    /**
+     * Sets adaptated method private.
+     *
+     * @return $this The builder instance (for fluid interface)
+     */
+    public function makePrivate() {
+        $this->setModifier(Stmt\Class_::MODIFIER_PRIVATE);
+        return $this;
+    }
+
+    /**
+     * Adds overwritten traits.
+     *
+     * @param Node\Name|string ...$traits Traits for overwrite
+     *
+     * @return $this The builder instance (for fluid interface)
+     */
+    public function insteadof(...$traits) {
+        if ($this->type === self::TYPE_UNDEFINED) {
+            if (is_null($this->trait)) {
+                throw new \LogicException('Precedence adaptation must have trait');
+            }
+
+            $this->type = self::TYPE_PRECEDENCE;
+        }
+
+        if ($this->type !== self::TYPE_PRECEDENCE) {
+            throw new \LogicException('Cannot add overwritten traits for not precedence adaptation buider');
+        }
+
+        foreach ($traits as $trait) {
+            $this->insteadof[] = BuilderHelpers::normalizeName($trait);
+        }
+
+        return $this;
+    }
+
+    protected function setModifier(int $modifier) {
+        if ($this->type === self::TYPE_UNDEFINED) {
+            $this->type = self::TYPE_ALIAS;
+        }
+
+        if ($this->type !== self::TYPE_ALIAS) {
+            throw new \LogicException('Cannot set access modifier for not alias adaptation buider');
+        }
+
+        if (is_null($this->modifier)) {
+            $this->modifier = $modifier;
+        } else {
+            throw new \LogicException('Multiple access type modifiers are not allowed');
+        }
+    }
+
+    /**
+     * Returns the built node.
+     *
+     * @return Node The built node
+     */
+    public function getNode() : Node {
+        switch ($this->type) {
+            case self::TYPE_ALIAS:
+                return new Stmt\TraitUseAdaptation\Alias($this->trait, $this->method, $this->modifier, $this->alias);
+            case self::TYPE_PRECEDENCE:
+                return new Stmt\TraitUseAdaptation\Precedence($this->trait, $this->method, $this->insteadof);
+            default:
+                throw new \LogicException('Type of adaptation is not defined');
+        }
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Builder/Trait_.php b/vendor/nikic/php-parser/lib/PhpParser/Builder/Trait_.php
new file mode 100644
index 0000000000000000000000000000000000000000..a836d40c60a5ab2ad8f85a750ffc531773f58e0e
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Builder/Trait_.php
@@ -0,0 +1,60 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Builder;
+
+use PhpParser;
+use PhpParser\BuilderHelpers;
+use PhpParser\Node\Stmt;
+
+class Trait_ extends Declaration
+{
+    protected $name;
+    protected $uses = [];
+    protected $properties = [];
+    protected $methods = [];
+
+    /**
+     * Creates an interface builder.
+     *
+     * @param string $name Name of the interface
+     */
+    public function __construct(string $name) {
+        $this->name = $name;
+    }
+
+    /**
+     * Adds a statement.
+     *
+     * @param Stmt|PhpParser\Builder $stmt The statement to add
+     *
+     * @return $this The builder instance (for fluid interface)
+     */
+    public function addStmt($stmt) {
+        $stmt = BuilderHelpers::normalizeNode($stmt);
+
+        if ($stmt instanceof Stmt\Property) {
+            $this->properties[] = $stmt;
+        } elseif ($stmt instanceof Stmt\ClassMethod) {
+            $this->methods[] = $stmt;
+        } elseif ($stmt instanceof Stmt\TraitUse) {
+            $this->uses[] = $stmt;
+        } else {
+            throw new \LogicException(sprintf('Unexpected node of type "%s"', $stmt->getType()));
+        }
+
+        return $this;
+    }
+
+    /**
+     * Returns the built trait node.
+     *
+     * @return Stmt\Trait_ The built interface node
+     */
+    public function getNode() : PhpParser\Node {
+        return new Stmt\Trait_(
+            $this->name, [
+                'stmts' => array_merge($this->uses, $this->properties, $this->methods)
+            ], $this->attributes
+        );
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Builder/Use_.php b/vendor/nikic/php-parser/lib/PhpParser/Builder/Use_.php
new file mode 100644
index 0000000000000000000000000000000000000000..2026a1726149a1b9c15c7f45d0884ff8a56f9933
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Builder/Use_.php
@@ -0,0 +1,49 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Builder;
+
+use PhpParser\Builder;
+use PhpParser\BuilderHelpers;
+use PhpParser\Node;
+use PhpParser\Node\Stmt;
+
+class Use_ implements Builder
+{
+    protected $name;
+    protected $type;
+    protected $alias = null;
+
+    /**
+     * Creates a name use (alias) builder.
+     *
+     * @param Node\Name|string $name Name of the entity (namespace, class, function, constant) to alias
+     * @param int              $type One of the Stmt\Use_::TYPE_* constants
+     */
+    public function __construct($name, int $type) {
+        $this->name = BuilderHelpers::normalizeName($name);
+        $this->type = $type;
+    }
+
+    /**
+     * Sets alias for used name.
+     *
+     * @param string $alias Alias to use (last component of full name by default)
+     *
+     * @return $this The builder instance (for fluid interface)
+     */
+    public function as(string $alias) {
+        $this->alias = $alias;
+        return $this;
+    }
+
+    /**
+     * Returns the built node.
+     *
+     * @return Node The built node
+     */
+    public function getNode() : Node {
+        return new Stmt\Use_([
+            new Stmt\UseUse($this->name, $this->alias)
+        ], $this->type);
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/BuilderFactory.php b/vendor/nikic/php-parser/lib/PhpParser/BuilderFactory.php
new file mode 100644
index 0000000000000000000000000000000000000000..18bd1cd5c226830dc0b365f2bcd99dfe342bd1b2
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/BuilderFactory.php
@@ -0,0 +1,348 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser;
+
+use PhpParser\Node\Arg;
+use PhpParser\Node\Expr;
+use PhpParser\Node\Expr\BinaryOp\Concat;
+use PhpParser\Node\Identifier;
+use PhpParser\Node\Name;
+use PhpParser\Node\Scalar\String_;
+use PhpParser\Node\Stmt\Use_;
+
+class BuilderFactory
+{
+    /**
+     * Creates a namespace builder.
+     *
+     * @param null|string|Node\Name $name Name of the namespace
+     *
+     * @return Builder\Namespace_ The created namespace builder
+     */
+    public function namespace($name) : Builder\Namespace_ {
+        return new Builder\Namespace_($name);
+    }
+
+    /**
+     * Creates a class builder.
+     *
+     * @param string $name Name of the class
+     *
+     * @return Builder\Class_ The created class builder
+     */
+    public function class(string $name) : Builder\Class_ {
+        return new Builder\Class_($name);
+    }
+
+    /**
+     * Creates an interface builder.
+     *
+     * @param string $name Name of the interface
+     *
+     * @return Builder\Interface_ The created interface builder
+     */
+    public function interface(string $name) : Builder\Interface_ {
+        return new Builder\Interface_($name);
+    }
+
+    /**
+     * Creates a trait builder.
+     *
+     * @param string $name Name of the trait
+     *
+     * @return Builder\Trait_ The created trait builder
+     */
+    public function trait(string $name) : Builder\Trait_ {
+        return new Builder\Trait_($name);
+    }
+
+    /**
+     * Creates a trait use builder.
+     *
+     * @param Node\Name|string ...$traits Trait names
+     *
+     * @return Builder\TraitUse The create trait use builder
+     */
+    public function useTrait(...$traits) : Builder\TraitUse {
+        return new Builder\TraitUse(...$traits);
+    }
+
+    /**
+     * Creates a trait use adaptation builder.
+     *
+     * @param Node\Name|string|null  $trait  Trait name
+     * @param Node\Identifier|string $method Method name
+     *
+     * @return Builder\TraitUseAdaptation The create trait use adaptation builder
+     */
+    public function traitUseAdaptation($trait, $method = null) : Builder\TraitUseAdaptation {
+        if ($method === null) {
+            $method = $trait;
+            $trait = null;
+        }
+
+        return new Builder\TraitUseAdaptation($trait, $method);
+    }
+
+    /**
+     * Creates a method builder.
+     *
+     * @param string $name Name of the method
+     *
+     * @return Builder\Method The created method builder
+     */
+    public function method(string $name) : Builder\Method {
+        return new Builder\Method($name);
+    }
+
+    /**
+     * Creates a parameter builder.
+     *
+     * @param string $name Name of the parameter
+     *
+     * @return Builder\Param The created parameter builder
+     */
+    public function param(string $name) : Builder\Param {
+        return new Builder\Param($name);
+    }
+
+    /**
+     * Creates a property builder.
+     *
+     * @param string $name Name of the property
+     *
+     * @return Builder\Property The created property builder
+     */
+    public function property(string $name) : Builder\Property {
+        return new Builder\Property($name);
+    }
+
+    /**
+     * Creates a function builder.
+     *
+     * @param string $name Name of the function
+     *
+     * @return Builder\Function_ The created function builder
+     */
+    public function function(string $name) : Builder\Function_ {
+        return new Builder\Function_($name);
+    }
+
+    /**
+     * Creates a namespace/class use builder.
+     *
+     * @param Node\Name|string $name Name of the entity (namespace or class) to alias
+     *
+     * @return Builder\Use_ The created use builder
+     */
+    public function use($name) : Builder\Use_ {
+        return new Builder\Use_($name, Use_::TYPE_NORMAL);
+    }
+
+    /**
+     * Creates a function use builder.
+     *
+     * @param Node\Name|string $name Name of the function to alias
+     *
+     * @return Builder\Use_ The created use function builder
+     */
+    public function useFunction($name) : Builder\Use_ {
+        return new Builder\Use_($name, Use_::TYPE_FUNCTION);
+    }
+
+    /**
+     * Creates a constant use builder.
+     *
+     * @param Node\Name|string $name Name of the const to alias
+     *
+     * @return Builder\Use_ The created use const builder
+     */
+    public function useConst($name) : Builder\Use_ {
+        return new Builder\Use_($name, Use_::TYPE_CONSTANT);
+    }
+
+    /**
+     * Creates node a for a literal value.
+     *
+     * @param Expr|bool|null|int|float|string|array $value $value
+     *
+     * @return Expr
+     */
+    public function val($value) : Expr {
+        return BuilderHelpers::normalizeValue($value);
+    }
+
+    /**
+     * Creates variable node.
+     *
+     * @param string|Expr $name Name
+     *
+     * @return Expr\Variable
+     */
+    public function var($name) : Expr\Variable {
+        if (!\is_string($name) && !$name instanceof Expr) {
+            throw new \LogicException('Variable name must be string or Expr');
+        }
+
+        return new Expr\Variable($name);
+    }
+
+    /**
+     * Normalizes an argument list.
+     *
+     * Creates Arg nodes for all arguments and converts literal values to expressions.
+     *
+     * @param array $args List of arguments to normalize
+     *
+     * @return Arg[]
+     */
+    public function args(array $args) : array {
+        $normalizedArgs = [];
+        foreach ($args as $arg) {
+            if ($arg instanceof Arg) {
+                $normalizedArgs[] = $arg;
+            } else {
+                $normalizedArgs[] = new Arg(BuilderHelpers::normalizeValue($arg));
+            }
+        }
+        return $normalizedArgs;
+    }
+
+    /**
+     * Creates a function call node.
+     *
+     * @param string|Name|Expr $name Function name
+     * @param array            $args Function arguments
+     *
+     * @return Expr\FuncCall
+     */
+    public function funcCall($name, array $args = []) : Expr\FuncCall {
+        return new Expr\FuncCall(
+            BuilderHelpers::normalizeNameOrExpr($name),
+            $this->args($args)
+        );
+    }
+
+    /**
+     * Creates a method call node.
+     *
+     * @param Expr                   $var  Variable the method is called on
+     * @param string|Identifier|Expr $name Method name
+     * @param array                  $args Method arguments
+     *
+     * @return Expr\MethodCall
+     */
+    public function methodCall(Expr $var, $name, array $args = []) : Expr\MethodCall {
+        return new Expr\MethodCall(
+            $var,
+            BuilderHelpers::normalizeIdentifierOrExpr($name),
+            $this->args($args)
+        );
+    }
+
+    /**
+     * Creates a static method call node.
+     *
+     * @param string|Name|Expr       $class Class name
+     * @param string|Identifier|Expr $name  Method name
+     * @param array                  $args  Method arguments
+     *
+     * @return Expr\StaticCall
+     */
+    public function staticCall($class, $name, array $args = []) : Expr\StaticCall {
+        return new Expr\StaticCall(
+            BuilderHelpers::normalizeNameOrExpr($class),
+            BuilderHelpers::normalizeIdentifierOrExpr($name),
+            $this->args($args)
+        );
+    }
+
+    /**
+     * Creates an object creation node.
+     *
+     * @param string|Name|Expr $class Class name
+     * @param array            $args  Constructor arguments
+     *
+     * @return Expr\New_
+     */
+    public function new($class, array $args = []) : Expr\New_ {
+        return new Expr\New_(
+            BuilderHelpers::normalizeNameOrExpr($class),
+            $this->args($args)
+        );
+    }
+
+    /**
+     * Creates a constant fetch node.
+     *
+     * @param string|Name $name Constant name
+     *
+     * @return Expr\ConstFetch
+     */
+    public function constFetch($name) : Expr\ConstFetch {
+        return new Expr\ConstFetch(BuilderHelpers::normalizeName($name));
+    }
+    
+    /**
+     * Creates a property fetch node.
+     *
+     * @param Expr                   $var  Variable holding object
+     * @param string|Identifier|Expr $name Property name
+     *
+     * @return Expr\PropertyFetch
+     */
+    public function propertyFetch(Expr $var, $name) : Expr\PropertyFetch {
+        return new Expr\PropertyFetch($var, BuilderHelpers::normalizeIdentifierOrExpr($name));
+    }
+
+    /**
+     * Creates a class constant fetch node.
+     *
+     * @param string|Name|Expr  $class Class name
+     * @param string|Identifier $name  Constant name
+     *
+     * @return Expr\ClassConstFetch
+     */
+    public function classConstFetch($class, $name): Expr\ClassConstFetch {
+        return new Expr\ClassConstFetch(
+            BuilderHelpers::normalizeNameOrExpr($class),
+            BuilderHelpers::normalizeIdentifier($name)
+        );
+    }
+
+    /**
+     * Creates nested Concat nodes from a list of expressions.
+     *
+     * @param Expr|string ...$exprs Expressions or literal strings
+     *
+     * @return Concat
+     */
+    public function concat(...$exprs) : Concat {
+        $numExprs = count($exprs);
+        if ($numExprs < 2) {
+            throw new \LogicException('Expected at least two expressions');
+        }
+
+        $lastConcat = $this->normalizeStringExpr($exprs[0]);
+        for ($i = 1; $i < $numExprs; $i++) {
+            $lastConcat = new Concat($lastConcat, $this->normalizeStringExpr($exprs[$i]));
+        }
+        return $lastConcat;
+    }
+
+    /**
+     * @param string|Expr $expr
+     * @return Expr
+     */
+    private function normalizeStringExpr($expr) : Expr {
+        if ($expr instanceof Expr) {
+            return $expr;
+        }
+
+        if (\is_string($expr)) {
+            return new String_($expr);
+        }
+
+        throw new \LogicException('Expected string or Expr');
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/BuilderHelpers.php b/vendor/nikic/php-parser/lib/PhpParser/BuilderHelpers.php
new file mode 100644
index 0000000000000000000000000000000000000000..180bf35d0e7732f4f67628f2cc99adffdb2e58f5
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/BuilderHelpers.php
@@ -0,0 +1,285 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser;
+
+use PhpParser\Node\Expr;
+use PhpParser\Node\Identifier;
+use PhpParser\Node\Name;
+use PhpParser\Node\NullableType;
+use PhpParser\Node\Scalar;
+use PhpParser\Node\Stmt;
+use PhpParser\Node\UnionType;
+
+/**
+ * This class defines helpers used in the implementation of builders. Don't use it directly.
+ *
+ * @internal
+ */
+final class BuilderHelpers
+{
+    /**
+     * Normalizes a node: Converts builder objects to nodes.
+     *
+     * @param Node|Builder $node The node to normalize
+     *
+     * @return Node The normalized node
+     */
+    public static function normalizeNode($node) : Node {
+        if ($node instanceof Builder) {
+            return $node->getNode();
+        } elseif ($node instanceof Node) {
+            return $node;
+        }
+
+        throw new \LogicException('Expected node or builder object');
+    }
+
+    /**
+     * Normalizes a node to a statement.
+     *
+     * Expressions are wrapped in a Stmt\Expression node.
+     *
+     * @param Node|Builder $node The node to normalize
+     *
+     * @return Stmt The normalized statement node
+     */
+    public static function normalizeStmt($node) : Stmt {
+        $node = self::normalizeNode($node);
+        if ($node instanceof Stmt) {
+            return $node;
+        }
+
+        if ($node instanceof Expr) {
+            return new Stmt\Expression($node);
+        }
+
+        throw new \LogicException('Expected statement or expression node');
+    }
+
+    /**
+     * Normalizes strings to Identifier.
+     *
+     * @param string|Identifier $name The identifier to normalize
+     *
+     * @return Identifier The normalized identifier
+     */
+    public static function normalizeIdentifier($name) : Identifier {
+        if ($name instanceof Identifier) {
+            return $name;
+        }
+
+        if (\is_string($name)) {
+            return new Identifier($name);
+        }
+
+        throw new \LogicException('Expected string or instance of Node\Identifier');
+    }
+
+    /**
+     * Normalizes strings to Identifier, also allowing expressions.
+     *
+     * @param string|Identifier|Expr $name The identifier to normalize
+     *
+     * @return Identifier|Expr The normalized identifier or expression
+     */
+    public static function normalizeIdentifierOrExpr($name) {
+        if ($name instanceof Identifier || $name instanceof Expr) {
+            return $name;
+        }
+
+        if (\is_string($name)) {
+            return new Identifier($name);
+        }
+
+        throw new \LogicException('Expected string or instance of Node\Identifier or Node\Expr');
+    }
+
+    /**
+     * Normalizes a name: Converts string names to Name nodes.
+     *
+     * @param Name|string $name The name to normalize
+     *
+     * @return Name The normalized name
+     */
+    public static function normalizeName($name) : Name {
+        return self::normalizeNameCommon($name, false);
+    }
+
+    /**
+     * Normalizes a name: Converts string names to Name nodes, while also allowing expressions.
+     *
+     * @param Expr|Name|string $name The name to normalize
+     *
+     * @return Name|Expr The normalized name or expression
+     */
+    public static function normalizeNameOrExpr($name) {
+        return self::normalizeNameCommon($name, true);
+    }
+
+    /**
+     * Normalizes a name: Converts string names to Name nodes, optionally allowing expressions.
+     *
+     * @param Expr|Name|string $name      The name to normalize
+     * @param bool             $allowExpr Whether to also allow expressions
+     *
+     * @return Name|Expr The normalized name, or expression (if allowed)
+     */
+    private static function normalizeNameCommon($name, bool $allowExpr) {
+        if ($name instanceof Name) {
+            return $name;
+        } elseif (is_string($name)) {
+            if (!$name) {
+                throw new \LogicException('Name cannot be empty');
+            }
+
+            if ($name[0] === '\\') {
+                return new Name\FullyQualified(substr($name, 1));
+            } elseif (0 === strpos($name, 'namespace\\')) {
+                return new Name\Relative(substr($name, strlen('namespace\\')));
+            } else {
+                return new Name($name);
+            }
+        }
+
+        if ($allowExpr) {
+            if ($name instanceof Expr) {
+                return $name;
+            }
+            throw new \LogicException(
+                'Name must be a string or an instance of Node\Name or Node\Expr'
+            );
+        } else {
+            throw new \LogicException('Name must be a string or an instance of Node\Name');
+        }
+    }
+
+    /**
+     * Normalizes a type: Converts plain-text type names into proper AST representation.
+     *
+     * In particular, builtin types become Identifiers, custom types become Names and nullables
+     * are wrapped in NullableType nodes.
+     *
+     * @param string|Name|Identifier|NullableType|UnionType $type The type to normalize
+     *
+     * @return Name|Identifier|NullableType|UnionType The normalized type
+     */
+    public static function normalizeType($type) {
+        if (!is_string($type)) {
+            if (
+                !$type instanceof Name && !$type instanceof Identifier &&
+                !$type instanceof NullableType && !$type instanceof UnionType
+            ) {
+                throw new \LogicException(
+                    'Type must be a string, or an instance of Name, Identifier, NullableType or UnionType'
+                );
+            }
+            return $type;
+        }
+
+        $nullable = false;
+        if (strlen($type) > 0 && $type[0] === '?') {
+            $nullable = true;
+            $type = substr($type, 1);
+        }
+
+        $builtinTypes = [
+            'array', 'callable', 'string', 'int', 'float', 'bool', 'iterable', 'void', 'object', 'mixed'
+        ];
+
+        $lowerType = strtolower($type);
+        if (in_array($lowerType, $builtinTypes)) {
+            $type = new Identifier($lowerType);
+        } else {
+            $type = self::normalizeName($type);
+        }
+
+        if ($nullable && (string) $type === 'void') {
+            throw new \LogicException('void type cannot be nullable');
+        }
+
+        if ($nullable && (string) $type === 'mixed') {
+            throw new \LogicException('mixed type cannot be nullable');
+        }
+
+        return $nullable ? new NullableType($type) : $type;
+    }
+
+    /**
+     * Normalizes a value: Converts nulls, booleans, integers,
+     * floats, strings and arrays into their respective nodes
+     *
+     * @param Node\Expr|bool|null|int|float|string|array $value The value to normalize
+     *
+     * @return Expr The normalized value
+     */
+    public static function normalizeValue($value) : Expr {
+        if ($value instanceof Node\Expr) {
+            return $value;
+        } elseif (is_null($value)) {
+            return new Expr\ConstFetch(
+                new Name('null')
+            );
+        } elseif (is_bool($value)) {
+            return new Expr\ConstFetch(
+                new Name($value ? 'true' : 'false')
+            );
+        } elseif (is_int($value)) {
+            return new Scalar\LNumber($value);
+        } elseif (is_float($value)) {
+            return new Scalar\DNumber($value);
+        } elseif (is_string($value)) {
+            return new Scalar\String_($value);
+        } elseif (is_array($value)) {
+            $items = [];
+            $lastKey = -1;
+            foreach ($value as $itemKey => $itemValue) {
+                // for consecutive, numeric keys don't generate keys
+                if (null !== $lastKey && ++$lastKey === $itemKey) {
+                    $items[] = new Expr\ArrayItem(
+                        self::normalizeValue($itemValue)
+                    );
+                } else {
+                    $lastKey = null;
+                    $items[] = new Expr\ArrayItem(
+                        self::normalizeValue($itemValue),
+                        self::normalizeValue($itemKey)
+                    );
+                }
+            }
+
+            return new Expr\Array_($items);
+        } else {
+            throw new \LogicException('Invalid value');
+        }
+    }
+
+    /**
+     * Normalizes a doc comment: Converts plain strings to PhpParser\Comment\Doc.
+     *
+     * @param Comment\Doc|string $docComment The doc comment to normalize
+     *
+     * @return Comment\Doc The normalized doc comment
+     */
+    public static function normalizeDocComment($docComment) : Comment\Doc {
+        if ($docComment instanceof Comment\Doc) {
+            return $docComment;
+        } elseif (is_string($docComment)) {
+            return new Comment\Doc($docComment);
+        } else {
+            throw new \LogicException('Doc comment must be a string or an instance of PhpParser\Comment\Doc');
+        }
+    }
+
+    /**
+     * Adds a modifier and returns new modifier bitmask.
+     *
+     * @param int $modifiers Existing modifiers
+     * @param int $modifier  Modifier to set
+     *
+     * @return int New modifiers
+     */
+    public static function addModifier(int $modifiers, int $modifier) : int {
+        Stmt\Class_::verifyModifier($modifiers, $modifier);
+        return $modifiers | $modifier;
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Comment.php b/vendor/nikic/php-parser/lib/PhpParser/Comment.php
new file mode 100644
index 0000000000000000000000000000000000000000..61e98d3dca7e63797ab563acb8f94e8052728086
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Comment.php
@@ -0,0 +1,239 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser;
+
+class Comment implements \JsonSerializable
+{
+    protected $text;
+    protected $startLine;
+    protected $startFilePos;
+    protected $startTokenPos;
+    protected $endLine;
+    protected $endFilePos;
+    protected $endTokenPos;
+
+    /**
+     * Constructs a comment node.
+     *
+     * @param string $text          Comment text (including comment delimiters like /*)
+     * @param int    $startLine     Line number the comment started on
+     * @param int    $startFilePos  File offset the comment started on
+     * @param int    $startTokenPos Token offset the comment started on
+     */
+    public function __construct(
+        string $text,
+        int $startLine = -1, int $startFilePos = -1, int $startTokenPos = -1,
+        int $endLine = -1, int $endFilePos = -1, int $endTokenPos = -1
+    ) {
+        $this->text = $text;
+        $this->startLine = $startLine;
+        $this->startFilePos = $startFilePos;
+        $this->startTokenPos = $startTokenPos;
+        $this->endLine = $endLine;
+        $this->endFilePos = $endFilePos;
+        $this->endTokenPos = $endTokenPos;
+    }
+
+    /**
+     * Gets the comment text.
+     *
+     * @return string The comment text (including comment delimiters like /*)
+     */
+    public function getText() : string {
+        return $this->text;
+    }
+
+    /**
+     * Gets the line number the comment started on.
+     *
+     * @return int Line number (or -1 if not available)
+     */
+    public function getStartLine() : int {
+        return $this->startLine;
+    }
+
+    /**
+     * Gets the file offset the comment started on.
+     *
+     * @return int File offset (or -1 if not available)
+     */
+    public function getStartFilePos() : int {
+        return $this->startFilePos;
+    }
+
+    /**
+     * Gets the token offset the comment started on.
+     *
+     * @return int Token offset (or -1 if not available)
+     */
+    public function getStartTokenPos() : int {
+        return $this->startTokenPos;
+    }
+
+    /**
+     * Gets the line number the comment ends on.
+     *
+     * @return int Line number (or -1 if not available)
+     */
+    public function getEndLine() : int {
+        return $this->endLine;
+    }
+
+    /**
+     * Gets the file offset the comment ends on.
+     *
+     * @return int File offset (or -1 if not available)
+     */
+    public function getEndFilePos() : int {
+        return $this->endFilePos;
+    }
+
+    /**
+     * Gets the token offset the comment ends on.
+     *
+     * @return int Token offset (or -1 if not available)
+     */
+    public function getEndTokenPos() : int {
+        return $this->endTokenPos;
+    }
+
+    /**
+     * Gets the line number the comment started on.
+     *
+     * @deprecated Use getStartLine() instead
+     *
+     * @return int Line number
+     */
+    public function getLine() : int {
+        return $this->startLine;
+    }
+
+    /**
+     * Gets the file offset the comment started on.
+     *
+     * @deprecated Use getStartFilePos() instead
+     *
+     * @return int File offset
+     */
+    public function getFilePos() : int {
+        return $this->startFilePos;
+    }
+
+    /**
+     * Gets the token offset the comment started on.
+     *
+     * @deprecated Use getStartTokenPos() instead
+     *
+     * @return int Token offset
+     */
+    public function getTokenPos() : int {
+        return $this->startTokenPos;
+    }
+
+    /**
+     * Gets the comment text.
+     *
+     * @return string The comment text (including comment delimiters like /*)
+     */
+    public function __toString() : string {
+        return $this->text;
+    }
+
+    /**
+     * Gets the reformatted comment text.
+     *
+     * "Reformatted" here means that we try to clean up the whitespace at the
+     * starts of the lines. This is necessary because we receive the comments
+     * without trailing whitespace on the first line, but with trailing whitespace
+     * on all subsequent lines.
+     *
+     * @return mixed|string
+     */
+    public function getReformattedText() {
+        $text = trim($this->text);
+        $newlinePos = strpos($text, "\n");
+        if (false === $newlinePos) {
+            // Single line comments don't need further processing
+            return $text;
+        } elseif (preg_match('((*BSR_ANYCRLF)(*ANYCRLF)^.*(?:\R\s+\*.*)+$)', $text)) {
+            // Multi line comment of the type
+            //
+            //     /*
+            //      * Some text.
+            //      * Some more text.
+            //      */
+            //
+            // is handled by replacing the whitespace sequences before the * by a single space
+            return preg_replace('(^\s+\*)m', ' *', $this->text);
+        } elseif (preg_match('(^/\*\*?\s*[\r\n])', $text) && preg_match('(\n(\s*)\*/$)', $text, $matches)) {
+            // Multi line comment of the type
+            //
+            //    /*
+            //        Some text.
+            //        Some more text.
+            //    */
+            //
+            // is handled by removing the whitespace sequence on the line before the closing
+            // */ on all lines. So if the last line is "    */", then "    " is removed at the
+            // start of all lines.
+            return preg_replace('(^' . preg_quote($matches[1]) . ')m', '', $text);
+        } elseif (preg_match('(^/\*\*?\s*(?!\s))', $text, $matches)) {
+            // Multi line comment of the type
+            //
+            //     /* Some text.
+            //        Some more text.
+            //          Indented text.
+            //        Even more text. */
+            //
+            // is handled by removing the difference between the shortest whitespace prefix on all
+            // lines and the length of the "/* " opening sequence.
+            $prefixLen = $this->getShortestWhitespacePrefixLen(substr($text, $newlinePos + 1));
+            $removeLen = $prefixLen - strlen($matches[0]);
+            return preg_replace('(^\s{' . $removeLen . '})m', '', $text);
+        }
+
+        // No idea how to format this comment, so simply return as is
+        return $text;
+    }
+
+    /**
+     * Get length of shortest whitespace prefix (at the start of a line).
+     *
+     * If there is a line with no prefix whitespace, 0 is a valid return value.
+     *
+     * @param string $str String to check
+     * @return int Length in characters. Tabs count as single characters.
+     */
+    private function getShortestWhitespacePrefixLen(string $str) : int {
+        $lines = explode("\n", $str);
+        $shortestPrefixLen = \INF;
+        foreach ($lines as $line) {
+            preg_match('(^\s*)', $line, $matches);
+            $prefixLen = strlen($matches[0]);
+            if ($prefixLen < $shortestPrefixLen) {
+                $shortestPrefixLen = $prefixLen;
+            }
+        }
+        return $shortestPrefixLen;
+    }
+
+    /**
+     * @return       array
+     * @psalm-return array{nodeType:string, text:mixed, line:mixed, filePos:mixed}
+     */
+    public function jsonSerialize() : array {
+        // Technically not a node, but we make it look like one anyway
+        $type = $this instanceof Comment\Doc ? 'Comment_Doc' : 'Comment';
+        return [
+            'nodeType' => $type,
+            'text' => $this->text,
+            // TODO: Rename these to include "start".
+            'line' => $this->startLine,
+            'filePos' => $this->startFilePos,
+            'tokenPos' => $this->startTokenPos,
+            'endLine' => $this->endLine,
+            'endFilePos' => $this->endFilePos,
+            'endTokenPos' => $this->endTokenPos,
+        ];
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Comment/Doc.php b/vendor/nikic/php-parser/lib/PhpParser/Comment/Doc.php
new file mode 100644
index 0000000000000000000000000000000000000000..a9db6128f4fd1c2b616a1a781bd9ddf46b39294c
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Comment/Doc.php
@@ -0,0 +1,7 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Comment;
+
+class Doc extends \PhpParser\Comment
+{
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/ConstExprEvaluationException.php b/vendor/nikic/php-parser/lib/PhpParser/ConstExprEvaluationException.php
new file mode 100644
index 0000000000000000000000000000000000000000..49c92d5950660dd8649f4177282352992dd2291b
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/ConstExprEvaluationException.php
@@ -0,0 +1,6 @@
+<?php
+
+namespace PhpParser;
+
+class ConstExprEvaluationException extends \Exception
+{}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/ConstExprEvaluator.php b/vendor/nikic/php-parser/lib/PhpParser/ConstExprEvaluator.php
new file mode 100644
index 0000000000000000000000000000000000000000..7f02e6f245cfa03b41df65eb393c567e1ccb0b5d
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/ConstExprEvaluator.php
@@ -0,0 +1,226 @@
+<?php
+
+namespace PhpParser;
+
+use PhpParser\Node\Expr;
+use PhpParser\Node\Scalar;
+
+/**
+ * Evaluates constant expressions.
+ *
+ * This evaluator is able to evaluate all constant expressions (as defined by PHP), which can be
+ * evaluated without further context. If a subexpression is not of this type, a user-provided
+ * fallback evaluator is invoked. To support all constant expressions that are also supported by
+ * PHP (and not already handled by this class), the fallback evaluator must be able to handle the
+ * following node types:
+ *
+ *  * All Scalar\MagicConst\* nodes.
+ *  * Expr\ConstFetch nodes. Only null/false/true are already handled by this class.
+ *  * Expr\ClassConstFetch nodes.
+ *
+ * The fallback evaluator should throw ConstExprEvaluationException for nodes it cannot evaluate.
+ *
+ * The evaluation is dependent on runtime configuration in two respects: Firstly, floating
+ * point to string conversions are affected by the precision ini setting. Secondly, they are also
+ * affected by the LC_NUMERIC locale.
+ */
+class ConstExprEvaluator
+{
+    private $fallbackEvaluator;
+
+    /**
+     * Create a constant expression evaluator.
+     *
+     * The provided fallback evaluator is invoked whenever a subexpression cannot be evaluated. See
+     * class doc comment for more information.
+     *
+     * @param callable|null $fallbackEvaluator To call if subexpression cannot be evaluated
+     */
+    public function __construct(callable $fallbackEvaluator = null) {
+        $this->fallbackEvaluator = $fallbackEvaluator ?? function(Expr $expr) {
+            throw new ConstExprEvaluationException(
+                "Expression of type {$expr->getType()} cannot be evaluated"
+            );
+        };
+    }
+
+    /**
+     * Silently evaluates a constant expression into a PHP value.
+     *
+     * Thrown Errors, warnings or notices will be converted into a ConstExprEvaluationException.
+     * The original source of the exception is available through getPrevious().
+     *
+     * If some part of the expression cannot be evaluated, the fallback evaluator passed to the
+     * constructor will be invoked. By default, if no fallback is provided, an exception of type
+     * ConstExprEvaluationException is thrown.
+     *
+     * See class doc comment for caveats and limitations.
+     *
+     * @param Expr $expr Constant expression to evaluate
+     * @return mixed Result of evaluation
+     *
+     * @throws ConstExprEvaluationException if the expression cannot be evaluated or an error occurred
+     */
+    public function evaluateSilently(Expr $expr) {
+        set_error_handler(function($num, $str, $file, $line) {
+            throw new \ErrorException($str, 0, $num, $file, $line);
+        });
+
+        try {
+            return $this->evaluate($expr);
+        } catch (\Throwable $e) {
+            if (!$e instanceof ConstExprEvaluationException) {
+                $e = new ConstExprEvaluationException(
+                    "An error occurred during constant expression evaluation", 0, $e);
+            }
+            throw $e;
+        } finally {
+            restore_error_handler();
+        }
+    }
+
+    /**
+     * Directly evaluates a constant expression into a PHP value.
+     *
+     * May generate Error exceptions, warnings or notices. Use evaluateSilently() to convert these
+     * into a ConstExprEvaluationException.
+     *
+     * If some part of the expression cannot be evaluated, the fallback evaluator passed to the
+     * constructor will be invoked. By default, if no fallback is provided, an exception of type
+     * ConstExprEvaluationException is thrown.
+     *
+     * See class doc comment for caveats and limitations.
+     *
+     * @param Expr $expr Constant expression to evaluate
+     * @return mixed Result of evaluation
+     *
+     * @throws ConstExprEvaluationException if the expression cannot be evaluated
+     */
+    public function evaluateDirectly(Expr $expr) {
+        return $this->evaluate($expr);
+    }
+
+    private function evaluate(Expr $expr) {
+        if ($expr instanceof Scalar\LNumber
+            || $expr instanceof Scalar\DNumber
+            || $expr instanceof Scalar\String_
+        ) {
+            return $expr->value;
+        }
+
+        if ($expr instanceof Expr\Array_) {
+            return $this->evaluateArray($expr);
+        }
+
+        // Unary operators
+        if ($expr instanceof Expr\UnaryPlus) {
+            return +$this->evaluate($expr->expr);
+        }
+        if ($expr instanceof Expr\UnaryMinus) {
+            return -$this->evaluate($expr->expr);
+        }
+        if ($expr instanceof Expr\BooleanNot) {
+            return !$this->evaluate($expr->expr);
+        }
+        if ($expr instanceof Expr\BitwiseNot) {
+            return ~$this->evaluate($expr->expr);
+        }
+
+        if ($expr instanceof Expr\BinaryOp) {
+            return $this->evaluateBinaryOp($expr);
+        }
+
+        if ($expr instanceof Expr\Ternary) {
+            return $this->evaluateTernary($expr);
+        }
+
+        if ($expr instanceof Expr\ArrayDimFetch && null !== $expr->dim) {
+            return $this->evaluate($expr->var)[$this->evaluate($expr->dim)];
+        }
+
+        if ($expr instanceof Expr\ConstFetch) {
+            return $this->evaluateConstFetch($expr);
+        }
+
+        return ($this->fallbackEvaluator)($expr);
+    }
+
+    private function evaluateArray(Expr\Array_ $expr) {
+        $array = [];
+        foreach ($expr->items as $item) {
+            if (null !== $item->key) {
+                $array[$this->evaluate($item->key)] = $this->evaluate($item->value);
+            } else {
+                $array[] = $this->evaluate($item->value);
+            }
+        }
+        return $array;
+    }
+
+    private function evaluateTernary(Expr\Ternary $expr) {
+        if (null === $expr->if) {
+            return $this->evaluate($expr->cond) ?: $this->evaluate($expr->else);
+        }
+
+        return $this->evaluate($expr->cond)
+            ? $this->evaluate($expr->if)
+            : $this->evaluate($expr->else);
+    }
+
+    private function evaluateBinaryOp(Expr\BinaryOp $expr) {
+        if ($expr instanceof Expr\BinaryOp\Coalesce
+            && $expr->left instanceof Expr\ArrayDimFetch
+        ) {
+            // This needs to be special cased to respect BP_VAR_IS fetch semantics
+            return $this->evaluate($expr->left->var)[$this->evaluate($expr->left->dim)]
+                ?? $this->evaluate($expr->right);
+        }
+
+        // The evaluate() calls are repeated in each branch, because some of the operators are
+        // short-circuiting and evaluating the RHS in advance may be illegal in that case
+        $l = $expr->left;
+        $r = $expr->right;
+        switch ($expr->getOperatorSigil()) {
+            case '&':   return $this->evaluate($l) &   $this->evaluate($r);
+            case '|':   return $this->evaluate($l) |   $this->evaluate($r);
+            case '^':   return $this->evaluate($l) ^   $this->evaluate($r);
+            case '&&':  return $this->evaluate($l) &&  $this->evaluate($r);
+            case '||':  return $this->evaluate($l) ||  $this->evaluate($r);
+            case '??':  return $this->evaluate($l) ??  $this->evaluate($r);
+            case '.':   return $this->evaluate($l) .   $this->evaluate($r);
+            case '/':   return $this->evaluate($l) /   $this->evaluate($r);
+            case '==':  return $this->evaluate($l) ==  $this->evaluate($r);
+            case '>':   return $this->evaluate($l) >   $this->evaluate($r);
+            case '>=':  return $this->evaluate($l) >=  $this->evaluate($r);
+            case '===': return $this->evaluate($l) === $this->evaluate($r);
+            case 'and': return $this->evaluate($l) and $this->evaluate($r);
+            case 'or':  return $this->evaluate($l) or  $this->evaluate($r);
+            case 'xor': return $this->evaluate($l) xor $this->evaluate($r);
+            case '-':   return $this->evaluate($l) -   $this->evaluate($r);
+            case '%':   return $this->evaluate($l) %   $this->evaluate($r);
+            case '*':   return $this->evaluate($l) *   $this->evaluate($r);
+            case '!=':  return $this->evaluate($l) !=  $this->evaluate($r);
+            case '!==': return $this->evaluate($l) !== $this->evaluate($r);
+            case '+':   return $this->evaluate($l) +   $this->evaluate($r);
+            case '**':  return $this->evaluate($l) **  $this->evaluate($r);
+            case '<<':  return $this->evaluate($l) <<  $this->evaluate($r);
+            case '>>':  return $this->evaluate($l) >>  $this->evaluate($r);
+            case '<':   return $this->evaluate($l) <   $this->evaluate($r);
+            case '<=':  return $this->evaluate($l) <=  $this->evaluate($r);
+            case '<=>': return $this->evaluate($l) <=> $this->evaluate($r);
+        }
+
+        throw new \Exception('Should not happen');
+    }
+
+    private function evaluateConstFetch(Expr\ConstFetch $expr) {
+        $name = $expr->name->toLowerString();
+        switch ($name) {
+            case 'null': return null;
+            case 'false': return false;
+            case 'true': return true;
+        }
+
+        return ($this->fallbackEvaluator)($expr);
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Error.php b/vendor/nikic/php-parser/lib/PhpParser/Error.php
new file mode 100644
index 0000000000000000000000000000000000000000..d1fb959d19f1543402a24c8f5146ae8f4de4d4b3
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Error.php
@@ -0,0 +1,180 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser;
+
+class Error extends \RuntimeException
+{
+    protected $rawMessage;
+    protected $attributes;
+
+    /**
+     * Creates an Exception signifying a parse error.
+     *
+     * @param string    $message    Error message
+     * @param array|int $attributes Attributes of node/token where error occurred
+     *                              (or start line of error -- deprecated)
+     */
+    public function __construct(string $message, $attributes = []) {
+        $this->rawMessage = $message;
+        if (is_array($attributes)) {
+            $this->attributes = $attributes;
+        } else {
+            $this->attributes = ['startLine' => $attributes];
+        }
+        $this->updateMessage();
+    }
+
+    /**
+     * Gets the error message
+     *
+     * @return string Error message
+     */
+    public function getRawMessage() : string {
+        return $this->rawMessage;
+    }
+
+    /**
+     * Gets the line the error starts in.
+     *
+     * @return int Error start line
+     */
+    public function getStartLine() : int {
+        return $this->attributes['startLine'] ?? -1;
+    }
+
+    /**
+     * Gets the line the error ends in.
+     *
+     * @return int Error end line
+     */
+    public function getEndLine() : int {
+        return $this->attributes['endLine'] ?? -1;
+    }
+
+    /**
+     * Gets the attributes of the node/token the error occurred at.
+     *
+     * @return array
+     */
+    public function getAttributes() : array {
+        return $this->attributes;
+    }
+
+    /**
+     * Sets the attributes of the node/token the error occurred at.
+     *
+     * @param array $attributes
+     */
+    public function setAttributes(array $attributes) {
+        $this->attributes = $attributes;
+        $this->updateMessage();
+    }
+
+    /**
+     * Sets the line of the PHP file the error occurred in.
+     *
+     * @param string $message Error message
+     */
+    public function setRawMessage(string $message) {
+        $this->rawMessage = $message;
+        $this->updateMessage();
+    }
+
+    /**
+     * Sets the line the error starts in.
+     *
+     * @param int $line Error start line
+     */
+    public function setStartLine(int $line) {
+        $this->attributes['startLine'] = $line;
+        $this->updateMessage();
+    }
+
+    /**
+     * Returns whether the error has start and end column information.
+     *
+     * For column information enable the startFilePos and endFilePos in the lexer options.
+     *
+     * @return bool
+     */
+    public function hasColumnInfo() : bool {
+        return isset($this->attributes['startFilePos'], $this->attributes['endFilePos']);
+    }
+
+    /**
+     * Gets the start column (1-based) into the line where the error started.
+     *
+     * @param string $code Source code of the file
+     * @return int
+     */
+    public function getStartColumn(string $code) : int {
+        if (!$this->hasColumnInfo()) {
+            throw new \RuntimeException('Error does not have column information');
+        }
+
+        return $this->toColumn($code, $this->attributes['startFilePos']);
+    }
+
+    /**
+     * Gets the end column (1-based) into the line where the error ended.
+     *
+     * @param string $code Source code of the file
+     * @return int
+     */
+    public function getEndColumn(string $code) : int {
+        if (!$this->hasColumnInfo()) {
+            throw new \RuntimeException('Error does not have column information');
+        }
+
+        return $this->toColumn($code, $this->attributes['endFilePos']);
+    }
+
+    /**
+     * Formats message including line and column information.
+     *
+     * @param string $code Source code associated with the error, for calculation of the columns
+     *
+     * @return string Formatted message
+     */
+    public function getMessageWithColumnInfo(string $code) : string {
+        return sprintf(
+            '%s from %d:%d to %d:%d', $this->getRawMessage(),
+            $this->getStartLine(), $this->getStartColumn($code),
+            $this->getEndLine(), $this->getEndColumn($code)
+        );
+    }
+
+    /**
+     * Converts a file offset into a column.
+     *
+     * @param string $code Source code that $pos indexes into
+     * @param int    $pos  0-based position in $code
+     *
+     * @return int 1-based column (relative to start of line)
+     */
+    private function toColumn(string $code, int $pos) : int {
+        if ($pos > strlen($code)) {
+            throw new \RuntimeException('Invalid position information');
+        }
+
+        $lineStartPos = strrpos($code, "\n", $pos - strlen($code));
+        if (false === $lineStartPos) {
+            $lineStartPos = -1;
+        }
+
+        return $pos - $lineStartPos;
+    }
+
+    /**
+     * Updates the exception message after a change to rawMessage or rawLine.
+     */
+    protected function updateMessage() {
+        $this->message = $this->rawMessage;
+
+        if (-1 === $this->getStartLine()) {
+            $this->message .= ' on unknown line';
+        } else {
+            $this->message .= ' on line ' . $this->getStartLine();
+        }
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/ErrorHandler.php b/vendor/nikic/php-parser/lib/PhpParser/ErrorHandler.php
new file mode 100644
index 0000000000000000000000000000000000000000..d620e7453606fe97da8dd13abba3abfff54252e8
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/ErrorHandler.php
@@ -0,0 +1,13 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser;
+
+interface ErrorHandler
+{
+    /**
+     * Handle an error generated during lexing, parsing or some other operation.
+     *
+     * @param Error $error The error that needs to be handled
+     */
+    public function handleError(Error $error);
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/ErrorHandler/Collecting.php b/vendor/nikic/php-parser/lib/PhpParser/ErrorHandler/Collecting.php
new file mode 100644
index 0000000000000000000000000000000000000000..784b61b14368d1ba55638fe801347959b9ac39ed
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/ErrorHandler/Collecting.php
@@ -0,0 +1,46 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\ErrorHandler;
+
+use PhpParser\Error;
+use PhpParser\ErrorHandler;
+
+/**
+ * Error handler that collects all errors into an array.
+ *
+ * This allows graceful handling of errors.
+ */
+class Collecting implements ErrorHandler
+{
+    /** @var Error[] Collected errors */
+    private $errors = [];
+
+    public function handleError(Error $error) {
+        $this->errors[] = $error;
+    }
+
+    /**
+     * Get collected errors.
+     *
+     * @return Error[]
+     */
+    public function getErrors() : array {
+        return $this->errors;
+    }
+
+    /**
+     * Check whether there are any errors.
+     *
+     * @return bool
+     */
+    public function hasErrors() : bool {
+        return !empty($this->errors);
+    }
+
+    /**
+     * Reset/clear collected errors.
+     */
+    public function clearErrors() {
+        $this->errors = [];
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/ErrorHandler/Throwing.php b/vendor/nikic/php-parser/lib/PhpParser/ErrorHandler/Throwing.php
new file mode 100644
index 0000000000000000000000000000000000000000..aeee989b1a6bfc9e68ee6f05cc016d7febdb1053
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/ErrorHandler/Throwing.php
@@ -0,0 +1,18 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\ErrorHandler;
+
+use PhpParser\Error;
+use PhpParser\ErrorHandler;
+
+/**
+ * Error handler that handles all errors by throwing them.
+ *
+ * This is the default strategy used by all components.
+ */
+class Throwing implements ErrorHandler
+{
+    public function handleError(Error $error) {
+        throw $error;
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Internal/DiffElem.php b/vendor/nikic/php-parser/lib/PhpParser/Internal/DiffElem.php
new file mode 100644
index 0000000000000000000000000000000000000000..a38b57ba93e648023310ab8d1d4b596b85be35e7
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Internal/DiffElem.php
@@ -0,0 +1,27 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Internal;
+
+/**
+ * @internal
+ */
+class DiffElem
+{
+    const TYPE_KEEP = 0;
+    const TYPE_REMOVE = 1;
+    const TYPE_ADD = 2;
+    const TYPE_REPLACE = 3;
+
+    /** @var int One of the TYPE_* constants */
+    public $type;
+    /** @var mixed Is null for add operations */
+    public $old;
+    /** @var mixed Is null for remove operations */
+    public $new;
+
+    public function __construct(int $type, $old, $new) {
+        $this->type = $type;
+        $this->old = $old;
+        $this->new = $new;
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Internal/Differ.php b/vendor/nikic/php-parser/lib/PhpParser/Internal/Differ.php
new file mode 100644
index 0000000000000000000000000000000000000000..7f218c74fe9ced921f40a3e4b666bcadf996f06e
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Internal/Differ.php
@@ -0,0 +1,164 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Internal;
+
+/**
+ * Implements the Myers diff algorithm.
+ *
+ * Myers, Eugene W. "An O (ND) difference algorithm and its variations."
+ * Algorithmica 1.1 (1986): 251-266.
+ *
+ * @internal
+ */
+class Differ
+{
+    private $isEqual;
+
+    /**
+     * Create differ over the given equality relation.
+     *
+     * @param callable $isEqual Equality relation with signature function($a, $b) : bool
+     */
+    public function __construct(callable $isEqual) {
+        $this->isEqual = $isEqual;
+    }
+
+    /**
+     * Calculate diff (edit script) from $old to $new.
+     *
+     * @param array $old Original array
+     * @param array $new New array
+     *
+     * @return DiffElem[] Diff (edit script)
+     */
+    public function diff(array $old, array $new) {
+        list($trace, $x, $y) = $this->calculateTrace($old, $new);
+        return $this->extractDiff($trace, $x, $y, $old, $new);
+    }
+
+    /**
+     * Calculate diff, including "replace" operations.
+     *
+     * If a sequence of remove operations is followed by the same number of add operations, these
+     * will be coalesced into replace operations.
+     *
+     * @param array $old Original array
+     * @param array $new New array
+     *
+     * @return DiffElem[] Diff (edit script), including replace operations
+     */
+    public function diffWithReplacements(array $old, array $new) {
+        return $this->coalesceReplacements($this->diff($old, $new));
+    }
+
+    private function calculateTrace(array $a, array $b) {
+        $n = \count($a);
+        $m = \count($b);
+        $max = $n + $m;
+        $v = [1 => 0];
+        $trace = [];
+        for ($d = 0; $d <= $max; $d++) {
+            $trace[] = $v;
+            for ($k = -$d; $k <= $d; $k += 2) {
+                if ($k === -$d || ($k !== $d && $v[$k-1] < $v[$k+1])) {
+                    $x = $v[$k+1];
+                } else {
+                    $x = $v[$k-1] + 1;
+                }
+
+                $y = $x - $k;
+                while ($x < $n && $y < $m && ($this->isEqual)($a[$x], $b[$y])) {
+                    $x++;
+                    $y++;
+                }
+
+                $v[$k] = $x;
+                if ($x >= $n && $y >= $m) {
+                    return [$trace, $x, $y];
+                }
+            }
+        }
+        throw new \Exception('Should not happen');
+    }
+
+    private function extractDiff(array $trace, int $x, int $y, array $a, array $b) {
+        $result = [];
+        for ($d = \count($trace) - 1; $d >= 0; $d--) {
+            $v = $trace[$d];
+            $k = $x - $y;
+
+            if ($k === -$d || ($k !== $d && $v[$k-1] < $v[$k+1])) {
+                $prevK = $k + 1;
+            } else {
+                $prevK = $k - 1;
+            }
+
+            $prevX = $v[$prevK];
+            $prevY = $prevX - $prevK;
+
+            while ($x > $prevX && $y > $prevY) {
+                $result[] = new DiffElem(DiffElem::TYPE_KEEP, $a[$x-1], $b[$y-1]);
+                $x--;
+                $y--;
+            }
+
+            if ($d === 0) {
+                break;
+            }
+
+            while ($x > $prevX) {
+                $result[] = new DiffElem(DiffElem::TYPE_REMOVE, $a[$x-1], null);
+                $x--;
+            }
+
+            while ($y > $prevY) {
+                $result[] = new DiffElem(DiffElem::TYPE_ADD, null, $b[$y-1]);
+                $y--;
+            }
+        }
+        return array_reverse($result);
+    }
+
+    /**
+     * Coalesce equal-length sequences of remove+add into a replace operation.
+     *
+     * @param DiffElem[] $diff
+     * @return DiffElem[]
+     */
+    private function coalesceReplacements(array $diff) {
+        $newDiff = [];
+        $c = \count($diff);
+        for ($i = 0; $i < $c; $i++) {
+            $diffType = $diff[$i]->type;
+            if ($diffType !== DiffElem::TYPE_REMOVE) {
+                $newDiff[] = $diff[$i];
+                continue;
+            }
+
+            $j = $i;
+            while ($j < $c && $diff[$j]->type === DiffElem::TYPE_REMOVE) {
+                $j++;
+            }
+
+            $k = $j;
+            while ($k < $c && $diff[$k]->type === DiffElem::TYPE_ADD) {
+                $k++;
+            }
+
+            if ($j - $i === $k - $j) {
+                $len = $j - $i;
+                for ($n = 0; $n < $len; $n++) {
+                    $newDiff[] = new DiffElem(
+                        DiffElem::TYPE_REPLACE, $diff[$i + $n]->old, $diff[$j + $n]->new
+                    );
+                }
+            } else {
+                for (; $i < $k; $i++) {
+                    $newDiff[] = $diff[$i];
+                }
+            }
+            $i = $k - 1;
+        }
+        return $newDiff;
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Internal/PrintableNewAnonClassNode.php b/vendor/nikic/php-parser/lib/PhpParser/Internal/PrintableNewAnonClassNode.php
new file mode 100644
index 0000000000000000000000000000000000000000..3eeac04a412dc13dc34527e59b0a203866e5507c
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Internal/PrintableNewAnonClassNode.php
@@ -0,0 +1,61 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Internal;
+
+use PhpParser\Node;
+use PhpParser\Node\Expr;
+
+/**
+ * This node is used internally by the format-preserving pretty printer to print anonymous classes.
+ *
+ * The normal anonymous class structure violates assumptions about the order of token offsets.
+ * Namely, the constructor arguments are part of the Expr\New_ node and follow the class node, even
+ * though they are actually interleaved with them. This special node type is used temporarily to
+ * restore a sane token offset order.
+ *
+ * @internal
+ */
+class PrintableNewAnonClassNode extends Expr
+{
+    /** @var Node\AttributeGroup[] PHP attribute groups */
+    public $attrGroups;
+    /** @var Node\Arg[] Arguments */
+    public $args;
+    /** @var null|Node\Name Name of extended class */
+    public $extends;
+    /** @var Node\Name[] Names of implemented interfaces */
+    public $implements;
+    /** @var Node\Stmt[] Statements */
+    public $stmts;
+
+    public function __construct(
+        array $attrGroups, array $args, Node\Name $extends = null, array $implements,
+        array $stmts, array $attributes
+    ) {
+        parent::__construct($attributes);
+        $this->attrGroups = $attrGroups;
+        $this->args = $args;
+        $this->extends = $extends;
+        $this->implements = $implements;
+        $this->stmts = $stmts;
+    }
+
+    public static function fromNewNode(Expr\New_ $newNode) {
+        $class = $newNode->class;
+        assert($class instanceof Node\Stmt\Class_);
+        // We don't assert that $class->name is null here, to allow consumers to assign unique names
+        // to anonymous classes for their own purposes. We simplify ignore the name here.
+        return new self(
+            $class->attrGroups, $newNode->args, $class->extends, $class->implements,
+            $class->stmts, $newNode->getAttributes()
+        );
+    }
+
+    public function getType() : string {
+        return 'Expr_PrintableNewAnonClass';
+    }
+
+    public function getSubNodeNames() : array {
+        return ['attrGroups', 'args', 'extends', 'implements', 'stmts'];
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Internal/TokenStream.php b/vendor/nikic/php-parser/lib/PhpParser/Internal/TokenStream.php
new file mode 100644
index 0000000000000000000000000000000000000000..84c0175ec52e06a748aa6895440d85ffd4aaef76
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Internal/TokenStream.php
@@ -0,0 +1,281 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Internal;
+
+/**
+ * Provides operations on token streams, for use by pretty printer.
+ *
+ * @internal
+ */
+class TokenStream
+{
+    /** @var array Tokens (in token_get_all format) */
+    private $tokens;
+    /** @var int[] Map from position to indentation */
+    private $indentMap;
+
+    /**
+     * Create token stream instance.
+     *
+     * @param array $tokens Tokens in token_get_all() format
+     */
+    public function __construct(array $tokens) {
+        $this->tokens = $tokens;
+        $this->indentMap = $this->calcIndentMap();
+    }
+
+    /**
+     * Whether the given position is immediately surrounded by parenthesis.
+     *
+     * @param int $startPos Start position
+     * @param int $endPos   End position
+     *
+     * @return bool
+     */
+    public function haveParens(int $startPos, int $endPos) : bool {
+        return $this->haveTokenImmediatelyBefore($startPos, '(')
+            && $this->haveTokenImmediatelyAfter($endPos, ')');
+    }
+
+    /**
+     * Whether the given position is immediately surrounded by braces.
+     *
+     * @param int $startPos Start position
+     * @param int $endPos   End position
+     *
+     * @return bool
+     */
+    public function haveBraces(int $startPos, int $endPos) : bool {
+        return ($this->haveTokenImmediatelyBefore($startPos, '{')
+                || $this->haveTokenImmediatelyBefore($startPos, T_CURLY_OPEN))
+            && $this->haveTokenImmediatelyAfter($endPos, '}');
+    }
+
+    /**
+     * Check whether the position is directly preceded by a certain token type.
+     *
+     * During this check whitespace and comments are skipped.
+     *
+     * @param int        $pos               Position before which the token should occur
+     * @param int|string $expectedTokenType Token to check for
+     *
+     * @return bool Whether the expected token was found
+     */
+    public function haveTokenImmediatelyBefore(int $pos, $expectedTokenType) : bool {
+        $tokens = $this->tokens;
+        $pos--;
+        for (; $pos >= 0; $pos--) {
+            $tokenType = $tokens[$pos][0];
+            if ($tokenType === $expectedTokenType) {
+                return true;
+            }
+            if ($tokenType !== \T_WHITESPACE
+                && $tokenType !== \T_COMMENT && $tokenType !== \T_DOC_COMMENT) {
+                break;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Check whether the position is directly followed by a certain token type.
+     *
+     * During this check whitespace and comments are skipped.
+     *
+     * @param int        $pos               Position after which the token should occur
+     * @param int|string $expectedTokenType Token to check for
+     *
+     * @return bool Whether the expected token was found
+     */
+    public function haveTokenImmediatelyAfter(int $pos, $expectedTokenType) : bool {
+        $tokens = $this->tokens;
+        $pos++;
+        for (; $pos < \count($tokens); $pos++) {
+            $tokenType = $tokens[$pos][0];
+            if ($tokenType === $expectedTokenType) {
+                return true;
+            }
+            if ($tokenType !== \T_WHITESPACE
+                && $tokenType !== \T_COMMENT && $tokenType !== \T_DOC_COMMENT) {
+                break;
+            }
+        }
+        return false;
+    }
+
+    public function skipLeft(int $pos, $skipTokenType) {
+        $tokens = $this->tokens;
+
+        $pos = $this->skipLeftWhitespace($pos);
+        if ($skipTokenType === \T_WHITESPACE) {
+            return $pos;
+        }
+
+        if ($tokens[$pos][0] !== $skipTokenType) {
+            // Shouldn't happen. The skip token MUST be there
+            throw new \Exception('Encountered unexpected token');
+        }
+        $pos--;
+
+        return $this->skipLeftWhitespace($pos);
+    }
+
+    public function skipRight(int $pos, $skipTokenType) {
+        $tokens = $this->tokens;
+
+        $pos = $this->skipRightWhitespace($pos);
+        if ($skipTokenType === \T_WHITESPACE) {
+            return $pos;
+        }
+
+        if ($tokens[$pos][0] !== $skipTokenType) {
+            // Shouldn't happen. The skip token MUST be there
+            throw new \Exception('Encountered unexpected token');
+        }
+        $pos++;
+
+        return $this->skipRightWhitespace($pos);
+    }
+
+    /**
+     * Return first non-whitespace token position smaller or equal to passed position.
+     *
+     * @param int $pos Token position
+     * @return int Non-whitespace token position
+     */
+    public function skipLeftWhitespace(int $pos) {
+        $tokens = $this->tokens;
+        for (; $pos >= 0; $pos--) {
+            $type = $tokens[$pos][0];
+            if ($type !== \T_WHITESPACE && $type !== \T_COMMENT && $type !== \T_DOC_COMMENT) {
+                break;
+            }
+        }
+        return $pos;
+    }
+
+    /**
+     * Return first non-whitespace position greater or equal to passed position.
+     *
+     * @param int $pos Token position
+     * @return int Non-whitespace token position
+     */
+    public function skipRightWhitespace(int $pos) {
+        $tokens = $this->tokens;
+        for ($count = \count($tokens); $pos < $count; $pos++) {
+            $type = $tokens[$pos][0];
+            if ($type !== \T_WHITESPACE && $type !== \T_COMMENT && $type !== \T_DOC_COMMENT) {
+                break;
+            }
+        }
+        return $pos;
+    }
+
+    public function findRight(int $pos, $findTokenType) {
+        $tokens = $this->tokens;
+        for ($count = \count($tokens); $pos < $count; $pos++) {
+            $type = $tokens[$pos][0];
+            if ($type === $findTokenType) {
+                return $pos;
+            }
+        }
+        return -1;
+    }
+
+    /**
+     * Whether the given position range contains a certain token type.
+     *
+     * @param int $startPos Starting position (inclusive)
+     * @param int $endPos Ending position (exclusive)
+     * @param int|string $tokenType Token type to look for
+     * @return bool Whether the token occurs in the given range
+     */
+    public function haveTokenInRange(int $startPos, int $endPos, $tokenType) {
+        $tokens = $this->tokens;
+        for ($pos = $startPos; $pos < $endPos; $pos++) {
+            if ($tokens[$pos][0] === $tokenType) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    public function haveBracesInRange(int $startPos, int $endPos) {
+        return $this->haveTokenInRange($startPos, $endPos, '{')
+            || $this->haveTokenInRange($startPos, $endPos, T_CURLY_OPEN)
+            || $this->haveTokenInRange($startPos, $endPos, '}');
+    }
+
+    /**
+     * Get indentation before token position.
+     *
+     * @param int $pos Token position
+     *
+     * @return int Indentation depth (in spaces)
+     */
+    public function getIndentationBefore(int $pos) : int {
+        return $this->indentMap[$pos];
+    }
+
+    /**
+     * Get the code corresponding to a token offset range, optionally adjusted for indentation.
+     *
+     * @param int $from   Token start position (inclusive)
+     * @param int $to     Token end position (exclusive)
+     * @param int $indent By how much the code should be indented (can be negative as well)
+     *
+     * @return string Code corresponding to token range, adjusted for indentation
+     */
+    public function getTokenCode(int $from, int $to, int $indent) : string {
+        $tokens = $this->tokens;
+        $result = '';
+        for ($pos = $from; $pos < $to; $pos++) {
+            $token = $tokens[$pos];
+            if (\is_array($token)) {
+                $type = $token[0];
+                $content = $token[1];
+                if ($type === \T_CONSTANT_ENCAPSED_STRING || $type === \T_ENCAPSED_AND_WHITESPACE) {
+                    $result .= $content;
+                } else {
+                    // TODO Handle non-space indentation
+                    if ($indent < 0) {
+                        $result .= str_replace("\n" . str_repeat(" ", -$indent), "\n", $content);
+                    } elseif ($indent > 0) {
+                        $result .= str_replace("\n", "\n" . str_repeat(" ", $indent), $content);
+                    } else {
+                        $result .= $content;
+                    }
+                }
+            } else {
+                $result .= $token;
+            }
+        }
+        return $result;
+    }
+
+    /**
+     * Precalculate the indentation at every token position.
+     *
+     * @return int[] Token position to indentation map
+     */
+    private function calcIndentMap() {
+        $indentMap = [];
+        $indent = 0;
+        foreach ($this->tokens as $token) {
+            $indentMap[] = $indent;
+
+            if ($token[0] === \T_WHITESPACE) {
+                $content = $token[1];
+                $newlinePos = \strrpos($content, "\n");
+                if (false !== $newlinePos) {
+                    $indent = \strlen($content) - $newlinePos - 1;
+                }
+            }
+        }
+
+        // Add a sentinel for one past end of the file
+        $indentMap[] = $indent;
+
+        return $indentMap;
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/JsonDecoder.php b/vendor/nikic/php-parser/lib/PhpParser/JsonDecoder.php
new file mode 100644
index 0000000000000000000000000000000000000000..47d2003d4bae6b54d650f3e86f8a93ab6be60db0
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/JsonDecoder.php
@@ -0,0 +1,103 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser;
+
+class JsonDecoder
+{
+    /** @var \ReflectionClass[] Node type to reflection class map */
+    private $reflectionClassCache;
+
+    public function decode(string $json) {
+        $value = json_decode($json, true);
+        if (json_last_error()) {
+            throw new \RuntimeException('JSON decoding error: ' . json_last_error_msg());
+        }
+
+        return $this->decodeRecursive($value);
+    }
+
+    private function decodeRecursive($value) {
+        if (\is_array($value)) {
+            if (isset($value['nodeType'])) {
+                if ($value['nodeType'] === 'Comment' || $value['nodeType'] === 'Comment_Doc') {
+                    return $this->decodeComment($value);
+                }
+                return $this->decodeNode($value);
+            }
+            return $this->decodeArray($value);
+        }
+        return $value;
+    }
+
+    private function decodeArray(array $array) : array {
+        $decodedArray = [];
+        foreach ($array as $key => $value) {
+            $decodedArray[$key] = $this->decodeRecursive($value);
+        }
+        return $decodedArray;
+    }
+
+    private function decodeNode(array $value) : Node {
+        $nodeType = $value['nodeType'];
+        if (!\is_string($nodeType)) {
+            throw new \RuntimeException('Node type must be a string');
+        }
+
+        $reflectionClass = $this->reflectionClassFromNodeType($nodeType);
+        /** @var Node $node */
+        $node = $reflectionClass->newInstanceWithoutConstructor();
+
+        if (isset($value['attributes'])) {
+            if (!\is_array($value['attributes'])) {
+                throw new \RuntimeException('Attributes must be an array');
+            }
+
+            $node->setAttributes($this->decodeArray($value['attributes']));
+        }
+
+        foreach ($value as $name => $subNode) {
+            if ($name === 'nodeType' || $name === 'attributes') {
+                continue;
+            }
+
+            $node->$name = $this->decodeRecursive($subNode);
+        }
+
+        return $node;
+    }
+
+    private function decodeComment(array $value) : Comment {
+        $className = $value['nodeType'] === 'Comment' ? Comment::class : Comment\Doc::class;
+        if (!isset($value['text'])) {
+            throw new \RuntimeException('Comment must have text');
+        }
+
+        return new $className(
+            $value['text'],
+            $value['line'] ?? -1, $value['filePos'] ?? -1, $value['tokenPos'] ?? -1,
+            $value['endLine'] ?? -1, $value['endFilePos'] ?? -1, $value['endTokenPos'] ?? -1
+        );
+    }
+
+    private function reflectionClassFromNodeType(string $nodeType) : \ReflectionClass {
+        if (!isset($this->reflectionClassCache[$nodeType])) {
+            $className = $this->classNameFromNodeType($nodeType);
+            $this->reflectionClassCache[$nodeType] = new \ReflectionClass($className);
+        }
+        return $this->reflectionClassCache[$nodeType];
+    }
+
+    private function classNameFromNodeType(string $nodeType) : string {
+        $className = 'PhpParser\\Node\\' . strtr($nodeType, '_', '\\');
+        if (class_exists($className)) {
+            return $className;
+        }
+
+        $className .= '_';
+        if (class_exists($className)) {
+            return $className;
+        }
+
+        throw new \RuntimeException("Unknown node type \"$nodeType\"");
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Lexer.php b/vendor/nikic/php-parser/lib/PhpParser/Lexer.php
new file mode 100644
index 0000000000000000000000000000000000000000..832a3f4b8948dae2ba58d1aceb324a3286907e72
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Lexer.php
@@ -0,0 +1,533 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser;
+
+use PhpParser\Parser\Tokens;
+
+class Lexer
+{
+    protected $code;
+    protected $tokens;
+    protected $pos;
+    protected $line;
+    protected $filePos;
+    protected $prevCloseTagHasNewline;
+
+    protected $tokenMap;
+    protected $dropTokens;
+    protected $identifierTokens;
+
+    private $attributeStartLineUsed;
+    private $attributeEndLineUsed;
+    private $attributeStartTokenPosUsed;
+    private $attributeEndTokenPosUsed;
+    private $attributeStartFilePosUsed;
+    private $attributeEndFilePosUsed;
+    private $attributeCommentsUsed;
+
+    /**
+     * Creates a Lexer.
+     *
+     * @param array $options Options array. Currently only the 'usedAttributes' option is supported,
+     *                       which is an array of attributes to add to the AST nodes. Possible
+     *                       attributes are: 'comments', 'startLine', 'endLine', 'startTokenPos',
+     *                       'endTokenPos', 'startFilePos', 'endFilePos'. The option defaults to the
+     *                       first three. For more info see getNextToken() docs.
+     */
+    public function __construct(array $options = []) {
+        // Create Map from internal tokens to PhpParser tokens.
+        $this->defineCompatibilityTokens();
+        $this->tokenMap = $this->createTokenMap();
+        $this->identifierTokens = $this->createIdentifierTokenMap();
+
+        // map of tokens to drop while lexing (the map is only used for isset lookup,
+        // that's why the value is simply set to 1; the value is never actually used.)
+        $this->dropTokens = array_fill_keys(
+            [\T_WHITESPACE, \T_OPEN_TAG, \T_COMMENT, \T_DOC_COMMENT, \T_BAD_CHARACTER], 1
+        );
+
+        $defaultAttributes = ['comments', 'startLine', 'endLine'];
+        $usedAttributes = array_fill_keys($options['usedAttributes'] ?? $defaultAttributes, true);
+
+        // Create individual boolean properties to make these checks faster.
+        $this->attributeStartLineUsed = isset($usedAttributes['startLine']);
+        $this->attributeEndLineUsed = isset($usedAttributes['endLine']);
+        $this->attributeStartTokenPosUsed = isset($usedAttributes['startTokenPos']);
+        $this->attributeEndTokenPosUsed = isset($usedAttributes['endTokenPos']);
+        $this->attributeStartFilePosUsed = isset($usedAttributes['startFilePos']);
+        $this->attributeEndFilePosUsed = isset($usedAttributes['endFilePos']);
+        $this->attributeCommentsUsed = isset($usedAttributes['comments']);
+    }
+
+    /**
+     * Initializes the lexer for lexing the provided source code.
+     *
+     * This function does not throw if lexing errors occur. Instead, errors may be retrieved using
+     * the getErrors() method.
+     *
+     * @param string $code The source code to lex
+     * @param ErrorHandler|null $errorHandler Error handler to use for lexing errors. Defaults to
+     *                                        ErrorHandler\Throwing
+     */
+    public function startLexing(string $code, ErrorHandler $errorHandler = null) {
+        if (null === $errorHandler) {
+            $errorHandler = new ErrorHandler\Throwing();
+        }
+
+        $this->code = $code; // keep the code around for __halt_compiler() handling
+        $this->pos  = -1;
+        $this->line =  1;
+        $this->filePos = 0;
+
+        // If inline HTML occurs without preceding code, treat it as if it had a leading newline.
+        // This ensures proper composability, because having a newline is the "safe" assumption.
+        $this->prevCloseTagHasNewline = true;
+
+        $scream = ini_set('xdebug.scream', '0');
+
+        $this->tokens = @token_get_all($code);
+        $this->postprocessTokens($errorHandler);
+
+        if (false !== $scream) {
+            ini_set('xdebug.scream', $scream);
+        }
+    }
+
+    private function handleInvalidCharacterRange($start, $end, $line, ErrorHandler $errorHandler) {
+        $tokens = [];
+        for ($i = $start; $i < $end; $i++) {
+            $chr = $this->code[$i];
+            if ($chr === "\0") {
+                // PHP cuts error message after null byte, so need special case
+                $errorMsg = 'Unexpected null byte';
+            } else {
+                $errorMsg = sprintf(
+                    'Unexpected character "%s" (ASCII %d)', $chr, ord($chr)
+                );
+            }
+
+            $tokens[] = [\T_BAD_CHARACTER, $chr, $line];
+            $errorHandler->handleError(new Error($errorMsg, [
+                'startLine' => $line,
+                'endLine' => $line,
+                'startFilePos' => $i,
+                'endFilePos' => $i,
+            ]));
+        }
+        return $tokens;
+    }
+
+    /**
+     * Check whether comment token is unterminated.
+     *
+     * @return bool
+     */
+    private function isUnterminatedComment($token) : bool {
+        return ($token[0] === \T_COMMENT || $token[0] === \T_DOC_COMMENT)
+            && substr($token[1], 0, 2) === '/*'
+            && substr($token[1], -2) !== '*/';
+    }
+
+    protected function postprocessTokens(ErrorHandler $errorHandler) {
+        // PHP's error handling for token_get_all() is rather bad, so if we want detailed
+        // error information we need to compute it ourselves. Invalid character errors are
+        // detected by finding "gaps" in the token array. Unterminated comments are detected
+        // by checking if a trailing comment has a "*/" at the end.
+        //
+        // Additionally, we canonicalize to the PHP 8 comment format here, which does not include
+        // the trailing whitespace anymore.
+        //
+        // We also canonicalize to the PHP 8 T_NAME_* tokens.
+
+        $filePos = 0;
+        $line = 1;
+        $numTokens = \count($this->tokens);
+        for ($i = 0; $i < $numTokens; $i++) {
+            $token = $this->tokens[$i];
+
+            // Since PHP 7.4 invalid characters are represented by a T_BAD_CHARACTER token.
+            // In this case we only need to emit an error.
+            if ($token[0] === \T_BAD_CHARACTER) {
+                $this->handleInvalidCharacterRange($filePos, $filePos + 1, $line, $errorHandler);
+            }
+
+            if ($token[0] === \T_COMMENT && substr($token[1], 0, 2) !== '/*'
+                    && preg_match('/(\r\n|\n|\r)$/D', $token[1], $matches)) {
+                $trailingNewline = $matches[0];
+                $token[1] = substr($token[1], 0, -strlen($trailingNewline));
+                $this->tokens[$i] = $token;
+                if (isset($this->tokens[$i + 1]) && $this->tokens[$i + 1][0] === \T_WHITESPACE) {
+                    // Move trailing newline into following T_WHITESPACE token, if it already exists.
+                    $this->tokens[$i + 1][1] = $trailingNewline . $this->tokens[$i + 1][1];
+                    $this->tokens[$i + 1][2]--;
+                } else {
+                    // Otherwise, we need to create a new T_WHITESPACE token.
+                    array_splice($this->tokens, $i + 1, 0, [
+                        [\T_WHITESPACE, $trailingNewline, $line],
+                    ]);
+                    $numTokens++;
+                }
+            }
+
+            // Emulate PHP 8 T_NAME_* tokens, by combining sequences of T_NS_SEPARATOR and T_STRING
+            // into a single token.
+            if (\is_array($token)
+                    && ($token[0] === \T_NS_SEPARATOR || isset($this->identifierTokens[$token[0]]))) {
+                $lastWasSeparator = $token[0] === \T_NS_SEPARATOR;
+                $text = $token[1];
+                for ($j = $i + 1; isset($this->tokens[$j]); $j++) {
+                    if ($lastWasSeparator) {
+                        if (!isset($this->identifierTokens[$this->tokens[$j][0]])) {
+                            break;
+                        }
+                        $lastWasSeparator = false;
+                    } else {
+                        if ($this->tokens[$j][0] !== \T_NS_SEPARATOR) {
+                            break;
+                        }
+                        $lastWasSeparator = true;
+                    }
+                    $text .= $this->tokens[$j][1];
+                }
+                if ($lastWasSeparator) {
+                    // Trailing separator is not part of the name.
+                    $j--;
+                    $text = substr($text, 0, -1);
+                }
+                if ($j > $i + 1) {
+                    if ($token[0] === \T_NS_SEPARATOR) {
+                        $type = \T_NAME_FULLY_QUALIFIED;
+                    } else if ($token[0] === \T_NAMESPACE) {
+                        $type = \T_NAME_RELATIVE;
+                    } else {
+                        $type = \T_NAME_QUALIFIED;
+                    }
+                    $token = [$type, $text, $line];
+                    array_splice($this->tokens, $i, $j - $i, [$token]);
+                    $numTokens -= $j - $i - 1;
+                }
+            }
+
+            $tokenValue = \is_string($token) ? $token : $token[1];
+            $tokenLen = \strlen($tokenValue);
+
+            if (substr($this->code, $filePos, $tokenLen) !== $tokenValue) {
+                // Something is missing, must be an invalid character
+                $nextFilePos = strpos($this->code, $tokenValue, $filePos);
+                $badCharTokens = $this->handleInvalidCharacterRange(
+                    $filePos, $nextFilePos, $line, $errorHandler);
+                $filePos = (int) $nextFilePos;
+
+                array_splice($this->tokens, $i, 0, $badCharTokens);
+                $numTokens += \count($badCharTokens);
+                $i += \count($badCharTokens);
+            }
+
+            $filePos += $tokenLen;
+            $line += substr_count($tokenValue, "\n");
+        }
+
+        if ($filePos !== \strlen($this->code)) {
+            if (substr($this->code, $filePos, 2) === '/*') {
+                // Unlike PHP, HHVM will drop unterminated comments entirely
+                $comment = substr($this->code, $filePos);
+                $errorHandler->handleError(new Error('Unterminated comment', [
+                    'startLine' => $line,
+                    'endLine' => $line + substr_count($comment, "\n"),
+                    'startFilePos' => $filePos,
+                    'endFilePos' => $filePos + \strlen($comment),
+                ]));
+
+                // Emulate the PHP behavior
+                $isDocComment = isset($comment[3]) && $comment[3] === '*';
+                $this->tokens[] = [$isDocComment ? \T_DOC_COMMENT : \T_COMMENT, $comment, $line];
+            } else {
+                // Invalid characters at the end of the input
+                $badCharTokens = $this->handleInvalidCharacterRange(
+                    $filePos, \strlen($this->code), $line, $errorHandler);
+                $this->tokens = array_merge($this->tokens, $badCharTokens);
+            }
+            return;
+        }
+
+        if (count($this->tokens) > 0) {
+            // Check for unterminated comment
+            $lastToken = $this->tokens[count($this->tokens) - 1];
+            if ($this->isUnterminatedComment($lastToken)) {
+                $errorHandler->handleError(new Error('Unterminated comment', [
+                    'startLine' => $line - substr_count($lastToken[1], "\n"),
+                    'endLine' => $line,
+                    'startFilePos' => $filePos - \strlen($lastToken[1]),
+                    'endFilePos' => $filePos,
+                ]));
+            }
+        }
+    }
+
+    /**
+     * Fetches the next token.
+     *
+     * The available attributes are determined by the 'usedAttributes' option, which can
+     * be specified in the constructor. The following attributes are supported:
+     *
+     *  * 'comments'      => Array of PhpParser\Comment or PhpParser\Comment\Doc instances,
+     *                       representing all comments that occurred between the previous
+     *                       non-discarded token and the current one.
+     *  * 'startLine'     => Line in which the node starts.
+     *  * 'endLine'       => Line in which the node ends.
+     *  * 'startTokenPos' => Offset into the token array of the first token in the node.
+     *  * 'endTokenPos'   => Offset into the token array of the last token in the node.
+     *  * 'startFilePos'  => Offset into the code string of the first character that is part of the node.
+     *  * 'endFilePos'    => Offset into the code string of the last character that is part of the node.
+     *
+     * @param mixed $value           Variable to store token content in
+     * @param mixed $startAttributes Variable to store start attributes in
+     * @param mixed $endAttributes   Variable to store end attributes in
+     *
+     * @return int Token id
+     */
+    public function getNextToken(&$value = null, &$startAttributes = null, &$endAttributes = null) : int {
+        $startAttributes = [];
+        $endAttributes   = [];
+
+        while (1) {
+            if (isset($this->tokens[++$this->pos])) {
+                $token = $this->tokens[$this->pos];
+            } else {
+                // EOF token with ID 0
+                $token = "\0";
+            }
+
+            if ($this->attributeStartLineUsed) {
+                $startAttributes['startLine'] = $this->line;
+            }
+            if ($this->attributeStartTokenPosUsed) {
+                $startAttributes['startTokenPos'] = $this->pos;
+            }
+            if ($this->attributeStartFilePosUsed) {
+                $startAttributes['startFilePos'] = $this->filePos;
+            }
+
+            if (\is_string($token)) {
+                $value = $token;
+                if (isset($token[1])) {
+                    // bug in token_get_all
+                    $this->filePos += 2;
+                    $id = ord('"');
+                } else {
+                    $this->filePos += 1;
+                    $id = ord($token);
+                }
+            } elseif (!isset($this->dropTokens[$token[0]])) {
+                $value = $token[1];
+                $id = $this->tokenMap[$token[0]];
+                if (\T_CLOSE_TAG === $token[0]) {
+                    $this->prevCloseTagHasNewline = false !== strpos($token[1], "\n");
+                } elseif (\T_INLINE_HTML === $token[0]) {
+                    $startAttributes['hasLeadingNewline'] = $this->prevCloseTagHasNewline;
+                }
+
+                $this->line += substr_count($value, "\n");
+                $this->filePos += \strlen($value);
+            } else {
+                $origLine = $this->line;
+                $origFilePos = $this->filePos;
+                $this->line += substr_count($token[1], "\n");
+                $this->filePos += \strlen($token[1]);
+
+                if (\T_COMMENT === $token[0] || \T_DOC_COMMENT === $token[0]) {
+                    if ($this->attributeCommentsUsed) {
+                        $comment = \T_DOC_COMMENT === $token[0]
+                            ? new Comment\Doc($token[1],
+                                $origLine, $origFilePos, $this->pos,
+                                $this->line, $this->filePos - 1, $this->pos)
+                            : new Comment($token[1],
+                                $origLine, $origFilePos, $this->pos,
+                                $this->line, $this->filePos - 1, $this->pos);
+                        $startAttributes['comments'][] = $comment;
+                    }
+                }
+                continue;
+            }
+
+            if ($this->attributeEndLineUsed) {
+                $endAttributes['endLine'] = $this->line;
+            }
+            if ($this->attributeEndTokenPosUsed) {
+                $endAttributes['endTokenPos'] = $this->pos;
+            }
+            if ($this->attributeEndFilePosUsed) {
+                $endAttributes['endFilePos'] = $this->filePos - 1;
+            }
+
+            return $id;
+        }
+
+        throw new \RuntimeException('Reached end of lexer loop');
+    }
+
+    /**
+     * Returns the token array for current code.
+     *
+     * The token array is in the same format as provided by the
+     * token_get_all() function and does not discard tokens (i.e.
+     * whitespace and comments are included). The token position
+     * attributes are against this token array.
+     *
+     * @return array Array of tokens in token_get_all() format
+     */
+    public function getTokens() : array {
+        return $this->tokens;
+    }
+
+    /**
+     * Handles __halt_compiler() by returning the text after it.
+     *
+     * @return string Remaining text
+     */
+    public function handleHaltCompiler() : string {
+        // text after T_HALT_COMPILER, still including ();
+        $textAfter = substr($this->code, $this->filePos);
+
+        // ensure that it is followed by ();
+        // this simplifies the situation, by not allowing any comments
+        // in between of the tokens.
+        if (!preg_match('~^\s*\(\s*\)\s*(?:;|\?>\r?\n?)~', $textAfter, $matches)) {
+            throw new Error('__HALT_COMPILER must be followed by "();"');
+        }
+
+        // prevent the lexer from returning any further tokens
+        $this->pos = count($this->tokens);
+
+        // return with (); removed
+        return substr($textAfter, strlen($matches[0]));
+    }
+
+    private function defineCompatibilityTokens() {
+        static $compatTokensDefined = false;
+        if ($compatTokensDefined) {
+            return;
+        }
+
+        $compatTokens = [
+            // PHP 7.4
+            'T_BAD_CHARACTER',
+            'T_FN',
+            'T_COALESCE_EQUAL',
+            // PHP 8.0
+            'T_NAME_QUALIFIED',
+            'T_NAME_FULLY_QUALIFIED',
+            'T_NAME_RELATIVE',
+            'T_MATCH',
+            'T_NULLSAFE_OBJECT_OPERATOR',
+            'T_ATTRIBUTE',
+        ];
+
+        // PHP-Parser might be used together with another library that also emulates some or all
+        // of these tokens. Perform a sanity-check that all already defined tokens have been
+        // assigned a unique ID.
+        $usedTokenIds = [];
+        foreach ($compatTokens as $token) {
+            if (\defined($token)) {
+                $tokenId = \constant($token);
+                $clashingToken = $usedTokenIds[$tokenId] ?? null;
+                if ($clashingToken !== null) {
+                    throw new \Error(sprintf(
+                        'Token %s has same ID as token %s, ' .
+                        'you may be using a library with broken token emulation',
+                        $token, $clashingToken
+                    ));
+                }
+                $usedTokenIds[$tokenId] = $token;
+            }
+        }
+
+        // Now define any tokens that have not yet been emulated. Try to assign IDs from -1
+        // downwards, but skip any IDs that may already be in use.
+        $newTokenId = -1;
+        foreach ($compatTokens as $token) {
+            if (!\defined($token)) {
+                while (isset($usedTokenIds[$newTokenId])) {
+                    $newTokenId--;
+                }
+                \define($token, $newTokenId);
+                $newTokenId--;
+            }
+        }
+
+        $compatTokensDefined = true;
+    }
+
+    /**
+     * Creates the token map.
+     *
+     * The token map maps the PHP internal token identifiers
+     * to the identifiers used by the Parser. Additionally it
+     * maps T_OPEN_TAG_WITH_ECHO to T_ECHO and T_CLOSE_TAG to ';'.
+     *
+     * @return array The token map
+     */
+    protected function createTokenMap() : array {
+        $tokenMap = [];
+
+        // 256 is the minimum possible token number, as everything below
+        // it is an ASCII value
+        for ($i = 256; $i < 1000; ++$i) {
+            if (\T_DOUBLE_COLON === $i) {
+                // T_DOUBLE_COLON is equivalent to T_PAAMAYIM_NEKUDOTAYIM
+                $tokenMap[$i] = Tokens::T_PAAMAYIM_NEKUDOTAYIM;
+            } elseif(\T_OPEN_TAG_WITH_ECHO === $i) {
+                // T_OPEN_TAG_WITH_ECHO with dropped T_OPEN_TAG results in T_ECHO
+                $tokenMap[$i] = Tokens::T_ECHO;
+            } elseif(\T_CLOSE_TAG === $i) {
+                // T_CLOSE_TAG is equivalent to ';'
+                $tokenMap[$i] = ord(';');
+            } elseif ('UNKNOWN' !== $name = token_name($i)) {
+                if ('T_HASHBANG' === $name) {
+                    // HHVM uses a special token for #! hashbang lines
+                    $tokenMap[$i] = Tokens::T_INLINE_HTML;
+                } elseif (defined($name = Tokens::class . '::' . $name)) {
+                    // Other tokens can be mapped directly
+                    $tokenMap[$i] = constant($name);
+                }
+            }
+        }
+
+        // HHVM uses a special token for numbers that overflow to double
+        if (defined('T_ONUMBER')) {
+            $tokenMap[\T_ONUMBER] = Tokens::T_DNUMBER;
+        }
+        // HHVM also has a separate token for the __COMPILER_HALT_OFFSET__ constant
+        if (defined('T_COMPILER_HALT_OFFSET')) {
+            $tokenMap[\T_COMPILER_HALT_OFFSET] = Tokens::T_STRING;
+        }
+
+        // Assign tokens for which we define compatibility constants, as token_name() does not know them.
+        $tokenMap[\T_FN] = Tokens::T_FN;
+        $tokenMap[\T_COALESCE_EQUAL] = Tokens::T_COALESCE_EQUAL;
+        $tokenMap[\T_NAME_QUALIFIED] = Tokens::T_NAME_QUALIFIED;
+        $tokenMap[\T_NAME_FULLY_QUALIFIED] = Tokens::T_NAME_FULLY_QUALIFIED;
+        $tokenMap[\T_NAME_RELATIVE] = Tokens::T_NAME_RELATIVE;
+        $tokenMap[\T_MATCH] = Tokens::T_MATCH;
+        $tokenMap[\T_NULLSAFE_OBJECT_OPERATOR] = Tokens::T_NULLSAFE_OBJECT_OPERATOR;
+        $tokenMap[\T_ATTRIBUTE] = Tokens::T_ATTRIBUTE;
+
+        return $tokenMap;
+    }
+
+    private function createIdentifierTokenMap(): array {
+        // Based on semi_reserved production.
+        return array_fill_keys([
+            \T_STRING,
+            \T_STATIC, \T_ABSTRACT, \T_FINAL, \T_PRIVATE, \T_PROTECTED, \T_PUBLIC,
+            \T_INCLUDE, \T_INCLUDE_ONCE, \T_EVAL, \T_REQUIRE, \T_REQUIRE_ONCE, \T_LOGICAL_OR, \T_LOGICAL_XOR, \T_LOGICAL_AND,
+            \T_INSTANCEOF, \T_NEW, \T_CLONE, \T_EXIT, \T_IF, \T_ELSEIF, \T_ELSE, \T_ENDIF, \T_ECHO, \T_DO, \T_WHILE,
+            \T_ENDWHILE, \T_FOR, \T_ENDFOR, \T_FOREACH, \T_ENDFOREACH, \T_DECLARE, \T_ENDDECLARE, \T_AS, \T_TRY, \T_CATCH,
+            \T_FINALLY, \T_THROW, \T_USE, \T_INSTEADOF, \T_GLOBAL, \T_VAR, \T_UNSET, \T_ISSET, \T_EMPTY, \T_CONTINUE, \T_GOTO,
+            \T_FUNCTION, \T_CONST, \T_RETURN, \T_PRINT, \T_YIELD, \T_LIST, \T_SWITCH, \T_ENDSWITCH, \T_CASE, \T_DEFAULT,
+            \T_BREAK, \T_ARRAY, \T_CALLABLE, \T_EXTENDS, \T_IMPLEMENTS, \T_NAMESPACE, \T_TRAIT, \T_INTERFACE, \T_CLASS,
+            \T_CLASS_C, \T_TRAIT_C, \T_FUNC_C, \T_METHOD_C, \T_LINE, \T_FILE, \T_DIR, \T_NS_C, \T_HALT_COMPILER, \T_FN,
+            \T_MATCH,
+        ], true);
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Lexer/Emulative.php b/vendor/nikic/php-parser/lib/PhpParser/Lexer/Emulative.php
new file mode 100644
index 0000000000000000000000000000000000000000..cf1f8e5a954b93d370f640ea8cf682f16fa57ffb
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Lexer/Emulative.php
@@ -0,0 +1,242 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Lexer;
+
+use PhpParser\Error;
+use PhpParser\ErrorHandler;
+use PhpParser\Lexer;
+use PhpParser\Lexer\TokenEmulator\AttributeEmulator;
+use PhpParser\Lexer\TokenEmulator\CoaleseEqualTokenEmulator;
+use PhpParser\Lexer\TokenEmulator\FlexibleDocStringEmulator;
+use PhpParser\Lexer\TokenEmulator\FnTokenEmulator;
+use PhpParser\Lexer\TokenEmulator\MatchTokenEmulator;
+use PhpParser\Lexer\TokenEmulator\NullsafeTokenEmulator;
+use PhpParser\Lexer\TokenEmulator\NumericLiteralSeparatorEmulator;
+use PhpParser\Lexer\TokenEmulator\ReverseEmulator;
+use PhpParser\Lexer\TokenEmulator\TokenEmulator;
+use PhpParser\Parser\Tokens;
+
+class Emulative extends Lexer
+{
+    const PHP_7_3 = '7.3dev';
+    const PHP_7_4 = '7.4dev';
+    const PHP_8_0 = '8.0dev';
+
+    /** @var mixed[] Patches used to reverse changes introduced in the code */
+    private $patches = [];
+
+    /** @var TokenEmulator[] */
+    private $emulators = [];
+
+    /** @var string */
+    private $targetPhpVersion;
+
+    /**
+     * @param mixed[] $options Lexer options. In addition to the usual options,
+     *                         accepts a 'phpVersion' string that specifies the
+     *                         version to emulated. Defaults to newest supported.
+     */
+    public function __construct(array $options = [])
+    {
+        $this->targetPhpVersion = $options['phpVersion'] ?? Emulative::PHP_8_0;
+        unset($options['phpVersion']);
+
+        parent::__construct($options);
+
+        $emulators = [
+            new FlexibleDocStringEmulator(),
+            new FnTokenEmulator(),
+            new MatchTokenEmulator(),
+            new CoaleseEqualTokenEmulator(),
+            new NumericLiteralSeparatorEmulator(),
+            new NullsafeTokenEmulator(),
+            new AttributeEmulator(),
+        ];
+
+        // Collect emulators that are relevant for the PHP version we're running
+        // and the PHP version we're targeting for emulation.
+        foreach ($emulators as $emulator) {
+            $emulatorPhpVersion = $emulator->getPhpVersion();
+            if ($this->isForwardEmulationNeeded($emulatorPhpVersion)) {
+                $this->emulators[] = $emulator;
+            } else if ($this->isReverseEmulationNeeded($emulatorPhpVersion)) {
+                $this->emulators[] = new ReverseEmulator($emulator);
+            }
+        }
+    }
+
+    public function startLexing(string $code, ErrorHandler $errorHandler = null) {
+        $emulators = array_filter($this->emulators, function($emulator) use($code) {
+            return $emulator->isEmulationNeeded($code);
+        });
+
+        if (empty($emulators)) {
+            // Nothing to emulate, yay
+            parent::startLexing($code, $errorHandler);
+            return;
+        }
+
+        $this->patches = [];
+        foreach ($emulators as $emulator) {
+            $code = $emulator->preprocessCode($code, $this->patches);
+        }
+
+        $collector = new ErrorHandler\Collecting();
+        parent::startLexing($code, $collector);
+        $this->sortPatches();
+        $this->fixupTokens();
+
+        $errors = $collector->getErrors();
+        if (!empty($errors)) {
+            $this->fixupErrors($errors);
+            foreach ($errors as $error) {
+                $errorHandler->handleError($error);
+            }
+        }
+
+        foreach ($emulators as $emulator) {
+            $this->tokens = $emulator->emulate($code, $this->tokens);
+        }
+    }
+
+    private function isForwardEmulationNeeded(string $emulatorPhpVersion): bool {
+        return version_compare(\PHP_VERSION, $emulatorPhpVersion, '<')
+            && version_compare($this->targetPhpVersion, $emulatorPhpVersion, '>=');
+    }
+
+    private function isReverseEmulationNeeded(string $emulatorPhpVersion): bool {
+        return version_compare(\PHP_VERSION, $emulatorPhpVersion, '>=')
+            && version_compare($this->targetPhpVersion, $emulatorPhpVersion, '<');
+    }
+
+    private function sortPatches()
+    {
+        // Patches may be contributed by different emulators.
+        // Make sure they are sorted by increasing patch position.
+        usort($this->patches, function($p1, $p2) {
+            return $p1[0] <=> $p2[0];
+        });
+    }
+
+    private function fixupTokens()
+    {
+        if (\count($this->patches) === 0) {
+            return;
+        }
+
+        // Load first patch
+        $patchIdx = 0;
+
+        list($patchPos, $patchType, $patchText) = $this->patches[$patchIdx];
+
+        // We use a manual loop over the tokens, because we modify the array on the fly
+        $pos = 0;
+        for ($i = 0, $c = \count($this->tokens); $i < $c; $i++) {
+            $token = $this->tokens[$i];
+            if (\is_string($token)) {
+                if ($patchPos === $pos) {
+                    // Only support replacement for string tokens.
+                    assert($patchType === 'replace');
+                    $this->tokens[$i] = $patchText;
+
+                    // Fetch the next patch
+                    $patchIdx++;
+                    if ($patchIdx >= \count($this->patches)) {
+                        // No more patches, we're done
+                        return;
+                    }
+                    list($patchPos, $patchType, $patchText) = $this->patches[$patchIdx];
+                }
+
+                $pos += \strlen($token);
+                continue;
+            }
+
+            $len = \strlen($token[1]);
+            $posDelta = 0;
+            while ($patchPos >= $pos && $patchPos < $pos + $len) {
+                $patchTextLen = \strlen($patchText);
+                if ($patchType === 'remove') {
+                    if ($patchPos === $pos && $patchTextLen === $len) {
+                        // Remove token entirely
+                        array_splice($this->tokens, $i, 1, []);
+                        $i--;
+                        $c--;
+                    } else {
+                        // Remove from token string
+                        $this->tokens[$i][1] = substr_replace(
+                            $token[1], '', $patchPos - $pos + $posDelta, $patchTextLen
+                        );
+                        $posDelta -= $patchTextLen;
+                    }
+                } elseif ($patchType === 'add') {
+                    // Insert into the token string
+                    $this->tokens[$i][1] = substr_replace(
+                        $token[1], $patchText, $patchPos - $pos + $posDelta, 0
+                    );
+                    $posDelta += $patchTextLen;
+                } else if ($patchType === 'replace') {
+                    // Replace inside the token string
+                    $this->tokens[$i][1] = substr_replace(
+                        $token[1], $patchText, $patchPos - $pos + $posDelta, $patchTextLen
+                    );
+                } else {
+                    assert(false);
+                }
+
+                // Fetch the next patch
+                $patchIdx++;
+                if ($patchIdx >= \count($this->patches)) {
+                    // No more patches, we're done
+                    return;
+                }
+
+                list($patchPos, $patchType, $patchText) = $this->patches[$patchIdx];
+
+                // Multiple patches may apply to the same token. Reload the current one to check
+                // If the new patch applies
+                $token = $this->tokens[$i];
+            }
+
+            $pos += $len;
+        }
+
+        // A patch did not apply
+        assert(false);
+    }
+
+    /**
+     * Fixup line and position information in errors.
+     *
+     * @param Error[] $errors
+     */
+    private function fixupErrors(array $errors) {
+        foreach ($errors as $error) {
+            $attrs = $error->getAttributes();
+
+            $posDelta = 0;
+            $lineDelta = 0;
+            foreach ($this->patches as $patch) {
+                list($patchPos, $patchType, $patchText) = $patch;
+                if ($patchPos >= $attrs['startFilePos']) {
+                    // No longer relevant
+                    break;
+                }
+
+                if ($patchType === 'add') {
+                    $posDelta += strlen($patchText);
+                    $lineDelta += substr_count($patchText, "\n");
+                } else if ($patchType === 'remove') {
+                    $posDelta -= strlen($patchText);
+                    $lineDelta -= substr_count($patchText, "\n");
+                }
+            }
+
+            $attrs['startFilePos'] += $posDelta;
+            $attrs['endFilePos'] += $posDelta;
+            $attrs['startLine'] += $lineDelta;
+            $attrs['endLine'] += $lineDelta;
+            $error->setAttributes($attrs);
+        }
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/AttributeEmulator.php b/vendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/AttributeEmulator.php
new file mode 100644
index 0000000000000000000000000000000000000000..6776a51975fbd202e7aa75aab92701383568ce60
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/AttributeEmulator.php
@@ -0,0 +1,56 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Lexer\TokenEmulator;
+
+use PhpParser\Lexer\Emulative;
+
+final class AttributeEmulator extends TokenEmulator
+{
+    public function getPhpVersion(): string
+    {
+        return Emulative::PHP_8_0;
+    }
+
+    public function isEmulationNeeded(string $code) : bool
+    {
+        return strpos($code, '#[') !== false;
+    }
+
+    public function emulate(string $code, array $tokens): array
+    {
+        // We need to manually iterate and manage a count because we'll change
+        // the tokens array on the way.
+        $line = 1;
+        for ($i = 0, $c = count($tokens); $i < $c; ++$i) {
+            if ($tokens[$i] === '#' && isset($tokens[$i + 1]) && $tokens[$i + 1] === '[') {
+                array_splice($tokens, $i, 2, [
+                    [\T_ATTRIBUTE, '#[', $line]
+                ]);
+                $c--;
+                continue;
+            }
+            if (\is_array($tokens[$i])) {
+                $line += substr_count($tokens[$i][1], "\n");
+            }
+        }
+
+        return $tokens;
+    }
+
+    public function reverseEmulate(string $code, array $tokens): array
+    {
+        // TODO
+        return $tokens;
+    }
+
+    public function preprocessCode(string $code, array &$patches): string {
+        $pos = 0;
+        while (false !== $pos = strpos($code, '#[', $pos)) {
+            // Replace #[ with %[
+            $code[$pos] = '%';
+            $patches[] = [$pos, 'replace', '#'];
+            $pos += 2;
+        }
+        return $code;
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/CoaleseEqualTokenEmulator.php b/vendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/CoaleseEqualTokenEmulator.php
new file mode 100644
index 0000000000000000000000000000000000000000..d91da92143c514a8b58b9cd2cf5ff01453bc485b
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/CoaleseEqualTokenEmulator.php
@@ -0,0 +1,47 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Lexer\TokenEmulator;
+
+use PhpParser\Lexer\Emulative;
+
+final class CoaleseEqualTokenEmulator extends TokenEmulator
+{
+    public function getPhpVersion(): string
+    {
+        return Emulative::PHP_7_4;
+    }
+
+    public function isEmulationNeeded(string $code): bool
+    {
+        return strpos($code, '??=') !== false;
+    }
+
+    public function emulate(string $code, array $tokens): array
+    {
+        // We need to manually iterate and manage a count because we'll change
+        // the tokens array on the way
+        $line = 1;
+        for ($i = 0, $c = count($tokens); $i < $c; ++$i) {
+            if (isset($tokens[$i + 1])) {
+                if ($tokens[$i][0] === T_COALESCE && $tokens[$i + 1] === '=') {
+                    array_splice($tokens, $i, 2, [
+                        [\T_COALESCE_EQUAL, '??=', $line]
+                    ]);
+                    $c--;
+                    continue;
+                }
+            }
+            if (\is_array($tokens[$i])) {
+                $line += substr_count($tokens[$i][1], "\n");
+            }
+        }
+
+        return $tokens;
+    }
+
+    public function reverseEmulate(string $code, array $tokens): array
+    {
+        // ??= was not valid code previously, don't bother.
+        return $tokens;
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/FlexibleDocStringEmulator.php b/vendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/FlexibleDocStringEmulator.php
new file mode 100644
index 0000000000000000000000000000000000000000..c15d6271fcb51610988acf5851cea6a8cd67170e
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/FlexibleDocStringEmulator.php
@@ -0,0 +1,76 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Lexer\TokenEmulator;
+
+use PhpParser\Lexer\Emulative;
+
+final class FlexibleDocStringEmulator extends TokenEmulator
+{
+    const FLEXIBLE_DOC_STRING_REGEX = <<<'REGEX'
+/<<<[ \t]*(['"]?)([a-zA-Z_\x80-\xff][a-zA-Z0-9_\x80-\xff]*)\1\r?\n
+(?:.*\r?\n)*?
+(?<indentation>\h*)\2(?![a-zA-Z0-9_\x80-\xff])(?<separator>(?:;?[\r\n])?)/x
+REGEX;
+
+    public function getPhpVersion(): string
+    {
+        return Emulative::PHP_7_3;
+    }
+
+    public function isEmulationNeeded(string $code) : bool
+    {
+        return strpos($code, '<<<') !== false;
+    }
+
+    public function emulate(string $code, array $tokens): array
+    {
+        // Handled by preprocessing + fixup.
+        return $tokens;
+    }
+
+    public function reverseEmulate(string $code, array $tokens): array
+    {
+        // Not supported.
+        return $tokens;
+    }
+
+    public function preprocessCode(string $code, array &$patches): string {
+        if (!preg_match_all(self::FLEXIBLE_DOC_STRING_REGEX, $code, $matches, PREG_SET_ORDER|PREG_OFFSET_CAPTURE)) {
+            // No heredoc/nowdoc found
+            return $code;
+        }
+
+        // Keep track of how much we need to adjust string offsets due to the modifications we
+        // already made
+        $posDelta = 0;
+        foreach ($matches as $match) {
+            $indentation = $match['indentation'][0];
+            $indentationStart = $match['indentation'][1];
+
+            $separator = $match['separator'][0];
+            $separatorStart = $match['separator'][1];
+
+            if ($indentation === '' && $separator !== '') {
+                // Ordinary heredoc/nowdoc
+                continue;
+            }
+
+            if ($indentation !== '') {
+                // Remove indentation
+                $indentationLen = strlen($indentation);
+                $code = substr_replace($code, '', $indentationStart + $posDelta, $indentationLen);
+                $patches[] = [$indentationStart + $posDelta, 'add', $indentation];
+                $posDelta -= $indentationLen;
+            }
+
+            if ($separator === '') {
+                // Insert newline as separator
+                $code = substr_replace($code, "\n", $separatorStart + $posDelta, 0);
+                $patches[] = [$separatorStart + $posDelta, 'remove', "\n"];
+                $posDelta += 1;
+            }
+        }
+
+        return $code;
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/FnTokenEmulator.php b/vendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/FnTokenEmulator.php
new file mode 100644
index 0000000000000000000000000000000000000000..eb7e49634ac6221891d95874a32e03b885a23d58
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/FnTokenEmulator.php
@@ -0,0 +1,23 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Lexer\TokenEmulator;
+
+use PhpParser\Lexer\Emulative;
+
+final class FnTokenEmulator extends KeywordEmulator
+{
+    public function getPhpVersion(): string
+    {
+        return Emulative::PHP_7_4;
+    }
+
+    public function getKeywordString(): string
+    {
+        return 'fn';
+    }
+
+    public function getKeywordToken(): int
+    {
+        return \T_FN;
+    }
+}
\ No newline at end of file
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/KeywordEmulator.php b/vendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/KeywordEmulator.php
new file mode 100644
index 0000000000000000000000000000000000000000..e7c0512bd716273a6a425c4a836ae21e83aebf19
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/KeywordEmulator.php
@@ -0,0 +1,60 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Lexer\TokenEmulator;
+
+abstract class KeywordEmulator extends TokenEmulator
+{
+    abstract function getKeywordString(): string;
+    abstract function getKeywordToken(): int;
+
+    public function isEmulationNeeded(string $code): bool
+    {
+        return strpos(strtolower($code), $this->getKeywordString()) !== false;
+    }
+
+    public function emulate(string $code, array $tokens): array
+    {
+        $keywordString = $this->getKeywordString();
+        foreach ($tokens as $i => $token) {
+            if ($token[0] === T_STRING && strtolower($token[1]) === $keywordString) {
+                $previousNonSpaceToken = $this->getPreviousNonSpaceToken($tokens, $i);
+                if ($previousNonSpaceToken !== null && $previousNonSpaceToken[0] === \T_OBJECT_OPERATOR) {
+                    continue;
+                }
+
+                $tokens[$i][0] = $this->getKeywordToken();
+            }
+        }
+
+        return $tokens;
+    }
+
+    /**
+     * @param mixed[] $tokens
+     * @return mixed[]|null
+     */
+    private function getPreviousNonSpaceToken(array $tokens, int $start)
+    {
+        for ($i = $start - 1; $i >= 0; --$i) {
+            if ($tokens[$i][0] === T_WHITESPACE) {
+                continue;
+            }
+
+            return $tokens[$i];
+        }
+
+        return null;
+    }
+
+    public function reverseEmulate(string $code, array $tokens): array
+    {
+        $keywordToken = $this->getKeywordToken();
+        foreach ($tokens as $i => $token) {
+            if ($token[0] === $keywordToken) {
+                $tokens[$i][0] = \T_STRING;
+            }
+        }
+
+        return $tokens;
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/MatchTokenEmulator.php b/vendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/MatchTokenEmulator.php
new file mode 100644
index 0000000000000000000000000000000000000000..902a46dfcb76bdf11e6c187d6d6dd5046fddce24
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/MatchTokenEmulator.php
@@ -0,0 +1,23 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Lexer\TokenEmulator;
+
+use PhpParser\Lexer\Emulative;
+
+final class MatchTokenEmulator extends KeywordEmulator
+{
+    public function getPhpVersion(): string
+    {
+        return Emulative::PHP_8_0;
+    }
+
+    public function getKeywordString(): string
+    {
+        return 'match';
+    }
+
+    public function getKeywordToken(): int
+    {
+        return \T_MATCH;
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/NullsafeTokenEmulator.php b/vendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/NullsafeTokenEmulator.php
new file mode 100644
index 0000000000000000000000000000000000000000..1a29c676e450c4eec02065295ef195c83f623878
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/NullsafeTokenEmulator.php
@@ -0,0 +1,67 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Lexer\TokenEmulator;
+
+use PhpParser\Lexer\Emulative;
+
+final class NullsafeTokenEmulator extends TokenEmulator
+{
+    public function getPhpVersion(): string
+    {
+        return Emulative::PHP_8_0;
+    }
+
+    public function isEmulationNeeded(string $code): bool
+    {
+        return strpos($code, '?->') !== false;
+    }
+
+    public function emulate(string $code, array $tokens): array
+    {
+        // We need to manually iterate and manage a count because we'll change
+        // the tokens array on the way
+        $line = 1;
+        for ($i = 0, $c = count($tokens); $i < $c; ++$i) {
+            if ($tokens[$i] === '?' && isset($tokens[$i + 1]) && $tokens[$i + 1][0] === \T_OBJECT_OPERATOR) {
+                array_splice($tokens, $i, 2, [
+                    [\T_NULLSAFE_OBJECT_OPERATOR, '?->', $line]
+                ]);
+                $c--;
+                continue;
+            }
+
+            // Handle ?-> inside encapsed string.
+            if ($tokens[$i][0] === \T_ENCAPSED_AND_WHITESPACE && isset($tokens[$i - 1])
+                && $tokens[$i - 1][0] === \T_VARIABLE
+                && preg_match('/^\?->([a-zA-Z_\x80-\xff][a-zA-Z0-9_\x80-\xff]*)/', $tokens[$i][1], $matches)
+            ) {
+                $replacement = [
+                    [\T_NULLSAFE_OBJECT_OPERATOR, '?->', $line],
+                    [\T_STRING, $matches[1], $line],
+                ];
+                if (\strlen($matches[0]) !== \strlen($tokens[$i][1])) {
+                    $replacement[] = [
+                        \T_ENCAPSED_AND_WHITESPACE,
+                        \substr($tokens[$i][1], \strlen($matches[0])),
+                        $line
+                    ];
+                }
+                array_splice($tokens, $i, 1, $replacement);
+                $c += \count($replacement) - 1;
+                continue;
+            }
+
+            if (\is_array($tokens[$i])) {
+                $line += substr_count($tokens[$i][1], "\n");
+            }
+        }
+
+        return $tokens;
+    }
+
+    public function reverseEmulate(string $code, array $tokens): array
+    {
+        // ?-> was not valid code previously, don't bother.
+        return $tokens;
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/NumericLiteralSeparatorEmulator.php b/vendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/NumericLiteralSeparatorEmulator.php
new file mode 100644
index 0000000000000000000000000000000000000000..cdf793e46e81e865d45317fc0ef23ee882091085
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/NumericLiteralSeparatorEmulator.php
@@ -0,0 +1,105 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Lexer\TokenEmulator;
+
+use PhpParser\Lexer\Emulative;
+
+final class NumericLiteralSeparatorEmulator extends TokenEmulator
+{
+    const BIN = '(?:0b[01]+(?:_[01]+)*)';
+    const HEX = '(?:0x[0-9a-f]+(?:_[0-9a-f]+)*)';
+    const DEC = '(?:[0-9]+(?:_[0-9]+)*)';
+    const SIMPLE_FLOAT = '(?:' . self::DEC . '\.' . self::DEC . '?|\.' . self::DEC . ')';
+    const EXP = '(?:e[+-]?' . self::DEC . ')';
+    const FLOAT = '(?:' . self::SIMPLE_FLOAT . self::EXP . '?|' . self::DEC . self::EXP . ')';
+    const NUMBER = '~' . self::FLOAT . '|' . self::BIN . '|' . self::HEX . '|' . self::DEC . '~iA';
+
+    public function getPhpVersion(): string
+    {
+        return Emulative::PHP_7_4;
+    }
+
+    public function isEmulationNeeded(string $code) : bool
+    {
+        return preg_match('~[0-9]_[0-9]~', $code)
+            || preg_match('~0x[0-9a-f]+_[0-9a-f]~i', $code);
+    }
+
+    public function emulate(string $code, array $tokens): array
+    {
+        // We need to manually iterate and manage a count because we'll change
+        // the tokens array on the way
+        $codeOffset = 0;
+        for ($i = 0, $c = count($tokens); $i < $c; ++$i) {
+            $token = $tokens[$i];
+            $tokenLen = \strlen(\is_array($token) ? $token[1] : $token);
+
+            if ($token[0] !== T_LNUMBER && $token[0] !== T_DNUMBER) {
+                $codeOffset += $tokenLen;
+                continue;
+            }
+
+            $res = preg_match(self::NUMBER, $code, $matches, 0, $codeOffset);
+            assert($res, "No number at number token position");
+
+            $match = $matches[0];
+            $matchLen = \strlen($match);
+            if ($matchLen === $tokenLen) {
+                // Original token already holds the full number.
+                $codeOffset += $tokenLen;
+                continue;
+            }
+
+            $tokenKind = $this->resolveIntegerOrFloatToken($match);
+            $newTokens = [[$tokenKind, $match, $token[2]]];
+
+            $numTokens = 1;
+            $len = $tokenLen;
+            while ($matchLen > $len) {
+                $nextToken = $tokens[$i + $numTokens];
+                $nextTokenText = \is_array($nextToken) ? $nextToken[1] : $nextToken;
+                $nextTokenLen = \strlen($nextTokenText);
+
+                $numTokens++;
+                if ($matchLen < $len + $nextTokenLen) {
+                    // Split trailing characters into a partial token.
+                    assert(is_array($nextToken), "Partial token should be an array token");
+                    $partialText = substr($nextTokenText, $matchLen - $len);
+                    $newTokens[] = [$nextToken[0], $partialText, $nextToken[2]];
+                    break;
+                }
+
+                $len += $nextTokenLen;
+            }
+
+            array_splice($tokens, $i, $numTokens, $newTokens);
+            $c -= $numTokens - \count($newTokens);
+            $codeOffset += $matchLen;
+        }
+
+        return $tokens;
+    }
+
+    private function resolveIntegerOrFloatToken(string $str): int
+    {
+        $str = str_replace('_', '', $str);
+
+        if (stripos($str, '0b') === 0) {
+            $num = bindec($str);
+        } elseif (stripos($str, '0x') === 0) {
+            $num = hexdec($str);
+        } elseif (stripos($str, '0') === 0 && ctype_digit($str)) {
+            $num = octdec($str);
+        } else {
+            $num = +$str;
+        }
+
+        return is_float($num) ? T_DNUMBER : T_LNUMBER;
+    }
+
+    public function reverseEmulate(string $code, array $tokens): array
+    {
+        // Numeric separators were not legal code previously, don't bother.
+        return $tokens;
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/ReverseEmulator.php b/vendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/ReverseEmulator.php
new file mode 100644
index 0000000000000000000000000000000000000000..90093f66b21c4e9efbc7c10c588958b5658ffff1
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/ReverseEmulator.php
@@ -0,0 +1,36 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Lexer\TokenEmulator;
+
+/**
+ * Reverses emulation direction of the inner emulator.
+ */
+final class ReverseEmulator extends TokenEmulator
+{
+    /** @var TokenEmulator Inner emulator */
+    private $emulator;
+
+    public function __construct(TokenEmulator $emulator) {
+        $this->emulator = $emulator;
+    }
+
+    public function getPhpVersion(): string {
+        return $this->emulator->getPhpVersion();
+    }
+
+    public function isEmulationNeeded(string $code): bool {
+        return $this->emulator->isEmulationNeeded($code);
+    }
+
+    public function emulate(string $code, array $tokens): array {
+        return $this->emulator->reverseEmulate($code, $tokens);
+    }
+
+    public function reverseEmulate(string $code, array $tokens): array {
+        return $this->emulator->emulate($code, $tokens);
+    }
+
+    public function preprocessCode(string $code, array &$patches): string {
+        return $code;
+    }
+}
\ No newline at end of file
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/TokenEmulator.php b/vendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/TokenEmulator.php
new file mode 100644
index 0000000000000000000000000000000000000000..a020bc0ff49f92e160a4a53944249776e5b71174
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/TokenEmulator.php
@@ -0,0 +1,25 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Lexer\TokenEmulator;
+
+/** @internal */
+abstract class TokenEmulator
+{
+    abstract public function getPhpVersion(): string;
+
+    abstract public function isEmulationNeeded(string $code): bool;
+
+    /**
+     * @return array Modified Tokens
+     */
+    abstract public function emulate(string $code, array $tokens): array;
+
+    /**
+     * @return array Modified Tokens
+     */
+    abstract public function reverseEmulate(string $code, array $tokens): array;
+
+    public function preprocessCode(string $code, array &$patches): string {
+        return $code;
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/NameContext.php b/vendor/nikic/php-parser/lib/PhpParser/NameContext.php
new file mode 100644
index 0000000000000000000000000000000000000000..777a4afdeebfe1cee4d605607b49422b76cfbd01
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/NameContext.php
@@ -0,0 +1,285 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser;
+
+use PhpParser\Node\Name;
+use PhpParser\Node\Name\FullyQualified;
+use PhpParser\Node\Stmt;
+
+class NameContext
+{
+    /** @var null|Name Current namespace */
+    protected $namespace;
+
+    /** @var Name[][] Map of format [aliasType => [aliasName => originalName]] */
+    protected $aliases = [];
+
+    /** @var Name[][] Same as $aliases but preserving original case */
+    protected $origAliases = [];
+
+    /** @var ErrorHandler Error handler */
+    protected $errorHandler;
+
+    /**
+     * Create a name context.
+     *
+     * @param ErrorHandler $errorHandler Error handling used to report errors
+     */
+    public function __construct(ErrorHandler $errorHandler) {
+        $this->errorHandler = $errorHandler;
+    }
+
+    /**
+     * Start a new namespace.
+     *
+     * This also resets the alias table.
+     *
+     * @param Name|null $namespace Null is the global namespace
+     */
+    public function startNamespace(Name $namespace = null) {
+        $this->namespace = $namespace;
+        $this->origAliases = $this->aliases = [
+            Stmt\Use_::TYPE_NORMAL   => [],
+            Stmt\Use_::TYPE_FUNCTION => [],
+            Stmt\Use_::TYPE_CONSTANT => [],
+        ];
+    }
+
+    /**
+     * Add an alias / import.
+     *
+     * @param Name   $name        Original name
+     * @param string $aliasName   Aliased name
+     * @param int    $type        One of Stmt\Use_::TYPE_*
+     * @param array  $errorAttrs Attributes to use to report an error
+     */
+    public function addAlias(Name $name, string $aliasName, int $type, array $errorAttrs = []) {
+        // Constant names are case sensitive, everything else case insensitive
+        if ($type === Stmt\Use_::TYPE_CONSTANT) {
+            $aliasLookupName = $aliasName;
+        } else {
+            $aliasLookupName = strtolower($aliasName);
+        }
+
+        if (isset($this->aliases[$type][$aliasLookupName])) {
+            $typeStringMap = [
+                Stmt\Use_::TYPE_NORMAL   => '',
+                Stmt\Use_::TYPE_FUNCTION => 'function ',
+                Stmt\Use_::TYPE_CONSTANT => 'const ',
+            ];
+
+            $this->errorHandler->handleError(new Error(
+                sprintf(
+                    'Cannot use %s%s as %s because the name is already in use',
+                    $typeStringMap[$type], $name, $aliasName
+                ),
+                $errorAttrs
+            ));
+            return;
+        }
+
+        $this->aliases[$type][$aliasLookupName] = $name;
+        $this->origAliases[$type][$aliasName] = $name;
+    }
+
+    /**
+     * Get current namespace.
+     *
+     * @return null|Name Namespace (or null if global namespace)
+     */
+    public function getNamespace() {
+        return $this->namespace;
+    }
+
+    /**
+     * Get resolved name.
+     *
+     * @param Name $name Name to resolve
+     * @param int  $type One of Stmt\Use_::TYPE_{FUNCTION|CONSTANT}
+     *
+     * @return null|Name Resolved name, or null if static resolution is not possible
+     */
+    public function getResolvedName(Name $name, int $type) {
+        // don't resolve special class names
+        if ($type === Stmt\Use_::TYPE_NORMAL && $name->isSpecialClassName()) {
+            if (!$name->isUnqualified()) {
+                $this->errorHandler->handleError(new Error(
+                    sprintf("'\\%s' is an invalid class name", $name->toString()),
+                    $name->getAttributes()
+                ));
+            }
+            return $name;
+        }
+
+        // fully qualified names are already resolved
+        if ($name->isFullyQualified()) {
+            return $name;
+        }
+
+        // Try to resolve aliases
+        if (null !== $resolvedName = $this->resolveAlias($name, $type)) {
+            return $resolvedName;
+        }
+
+        if ($type !== Stmt\Use_::TYPE_NORMAL && $name->isUnqualified()) {
+            if (null === $this->namespace) {
+                // outside of a namespace unaliased unqualified is same as fully qualified
+                return new FullyQualified($name, $name->getAttributes());
+            }
+
+            // Cannot resolve statically
+            return null;
+        }
+
+        // if no alias exists prepend current namespace
+        return FullyQualified::concat($this->namespace, $name, $name->getAttributes());
+    }
+
+    /**
+     * Get resolved class name.
+     *
+     * @param Name $name Class ame to resolve
+     *
+     * @return Name Resolved name
+     */
+    public function getResolvedClassName(Name $name) : Name {
+        return $this->getResolvedName($name, Stmt\Use_::TYPE_NORMAL);
+    }
+
+    /**
+     * Get possible ways of writing a fully qualified name (e.g., by making use of aliases).
+     *
+     * @param string $name Fully-qualified name (without leading namespace separator)
+     * @param int    $type One of Stmt\Use_::TYPE_*
+     *
+     * @return Name[] Possible representations of the name
+     */
+    public function getPossibleNames(string $name, int $type) : array {
+        $lcName = strtolower($name);
+
+        if ($type === Stmt\Use_::TYPE_NORMAL) {
+            // self, parent and static must always be unqualified
+            if ($lcName === "self" || $lcName === "parent" || $lcName === "static") {
+                return [new Name($name)];
+            }
+        }
+
+        // Collect possible ways to write this name, starting with the fully-qualified name
+        $possibleNames = [new FullyQualified($name)];
+
+        if (null !== $nsRelativeName = $this->getNamespaceRelativeName($name, $lcName, $type)) {
+            // Make sure there is no alias that makes the normally namespace-relative name
+            // into something else
+            if (null === $this->resolveAlias($nsRelativeName, $type)) {
+                $possibleNames[] = $nsRelativeName;
+            }
+        }
+
+        // Check for relevant namespace use statements
+        foreach ($this->origAliases[Stmt\Use_::TYPE_NORMAL] as $alias => $orig) {
+            $lcOrig = $orig->toLowerString();
+            if (0 === strpos($lcName, $lcOrig . '\\')) {
+                $possibleNames[] = new Name($alias . substr($name, strlen($lcOrig)));
+            }
+        }
+
+        // Check for relevant type-specific use statements
+        foreach ($this->origAliases[$type] as $alias => $orig) {
+            if ($type === Stmt\Use_::TYPE_CONSTANT) {
+                // Constants are are complicated-sensitive
+                $normalizedOrig = $this->normalizeConstName($orig->toString());
+                if ($normalizedOrig === $this->normalizeConstName($name)) {
+                    $possibleNames[] = new Name($alias);
+                }
+            } else {
+                // Everything else is case-insensitive
+                if ($orig->toLowerString() === $lcName) {
+                    $possibleNames[] = new Name($alias);
+                }
+            }
+        }
+
+        return $possibleNames;
+    }
+
+    /**
+     * Get shortest representation of this fully-qualified name.
+     *
+     * @param string $name Fully-qualified name (without leading namespace separator)
+     * @param int    $type One of Stmt\Use_::TYPE_*
+     *
+     * @return Name Shortest representation
+     */
+    public function getShortName(string $name, int $type) : Name {
+        $possibleNames = $this->getPossibleNames($name, $type);
+
+        // Find shortest name
+        $shortestName = null;
+        $shortestLength = \INF;
+        foreach ($possibleNames as $possibleName) {
+            $length = strlen($possibleName->toCodeString());
+            if ($length < $shortestLength) {
+                $shortestName = $possibleName;
+                $shortestLength = $length;
+            }
+        }
+
+       return $shortestName;
+    }
+
+    private function resolveAlias(Name $name, $type) {
+        $firstPart = $name->getFirst();
+
+        if ($name->isQualified()) {
+            // resolve aliases for qualified names, always against class alias table
+            $checkName = strtolower($firstPart);
+            if (isset($this->aliases[Stmt\Use_::TYPE_NORMAL][$checkName])) {
+                $alias = $this->aliases[Stmt\Use_::TYPE_NORMAL][$checkName];
+                return FullyQualified::concat($alias, $name->slice(1), $name->getAttributes());
+            }
+        } elseif ($name->isUnqualified()) {
+            // constant aliases are case-sensitive, function aliases case-insensitive
+            $checkName = $type === Stmt\Use_::TYPE_CONSTANT ? $firstPart : strtolower($firstPart);
+            if (isset($this->aliases[$type][$checkName])) {
+                // resolve unqualified aliases
+                return new FullyQualified($this->aliases[$type][$checkName], $name->getAttributes());
+            }
+        }
+
+        // No applicable aliases
+        return null;
+    }
+
+    private function getNamespaceRelativeName(string $name, string $lcName, int $type) {
+        if (null === $this->namespace) {
+            return new Name($name);
+        }
+
+        if ($type === Stmt\Use_::TYPE_CONSTANT) {
+            // The constants true/false/null always resolve to the global symbols, even inside a
+            // namespace, so they may be used without qualification
+            if ($lcName === "true" || $lcName === "false" || $lcName === "null") {
+                return new Name($name);
+            }
+        }
+
+        $namespacePrefix = strtolower($this->namespace . '\\');
+        if (0 === strpos($lcName, $namespacePrefix)) {
+            return new Name(substr($name, strlen($namespacePrefix)));
+        }
+
+        return null;
+    }
+
+    private function normalizeConstName(string $name) {
+        $nsSep = strrpos($name, '\\');
+        if (false === $nsSep) {
+            return $name;
+        }
+
+        // Constants have case-insensitive namespace and case-sensitive short-name
+        $ns = substr($name, 0, $nsSep);
+        $shortName = substr($name, $nsSep + 1);
+        return strtolower($ns) . '\\' . $shortName;
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node.php b/vendor/nikic/php-parser/lib/PhpParser/Node.php
new file mode 100644
index 0000000000000000000000000000000000000000..befb256504294d7c1d2dc4263bb429e46d903d73
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node.php
@@ -0,0 +1,151 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser;
+
+interface Node
+{
+    /**
+     * Gets the type of the node.
+     *
+     * @return string Type of the node
+     */
+    public function getType() : string;
+
+    /**
+     * Gets the names of the sub nodes.
+     *
+     * @return array Names of sub nodes
+     */
+    public function getSubNodeNames() : array;
+
+    /**
+     * Gets line the node started in (alias of getStartLine).
+     *
+     * @return int Start line (or -1 if not available)
+     */
+    public function getLine() : int;
+
+    /**
+     * Gets line the node started in.
+     *
+     * Requires the 'startLine' attribute to be enabled in the lexer (enabled by default).
+     *
+     * @return int Start line (or -1 if not available)
+     */
+    public function getStartLine() : int;
+
+    /**
+     * Gets the line the node ended in.
+     *
+     * Requires the 'endLine' attribute to be enabled in the lexer (enabled by default).
+     *
+     * @return int End line (or -1 if not available)
+     */
+    public function getEndLine() : int;
+
+    /**
+     * Gets the token offset of the first token that is part of this node.
+     *
+     * The offset is an index into the array returned by Lexer::getTokens().
+     *
+     * Requires the 'startTokenPos' attribute to be enabled in the lexer (DISABLED by default).
+     *
+     * @return int Token start position (or -1 if not available)
+     */
+    public function getStartTokenPos() : int;
+
+    /**
+     * Gets the token offset of the last token that is part of this node.
+     *
+     * The offset is an index into the array returned by Lexer::getTokens().
+     *
+     * Requires the 'endTokenPos' attribute to be enabled in the lexer (DISABLED by default).
+     *
+     * @return int Token end position (or -1 if not available)
+     */
+    public function getEndTokenPos() : int;
+
+    /**
+     * Gets the file offset of the first character that is part of this node.
+     *
+     * Requires the 'startFilePos' attribute to be enabled in the lexer (DISABLED by default).
+     *
+     * @return int File start position (or -1 if not available)
+     */
+    public function getStartFilePos() : int;
+
+    /**
+     * Gets the file offset of the last character that is part of this node.
+     *
+     * Requires the 'endFilePos' attribute to be enabled in the lexer (DISABLED by default).
+     *
+     * @return int File end position (or -1 if not available)
+     */
+    public function getEndFilePos() : int;
+
+    /**
+     * Gets all comments directly preceding this node.
+     *
+     * The comments are also available through the "comments" attribute.
+     *
+     * @return Comment[]
+     */
+    public function getComments() : array;
+
+    /**
+     * Gets the doc comment of the node.
+     *
+     * @return null|Comment\Doc Doc comment object or null
+     */
+    public function getDocComment();
+
+    /**
+     * Sets the doc comment of the node.
+     *
+     * This will either replace an existing doc comment or add it to the comments array.
+     *
+     * @param Comment\Doc $docComment Doc comment to set
+     */
+    public function setDocComment(Comment\Doc $docComment);
+
+    /**
+     * Sets an attribute on a node.
+     *
+     * @param string $key
+     * @param mixed  $value
+     */
+    public function setAttribute(string $key, $value);
+
+    /**
+     * Returns whether an attribute exists.
+     *
+     * @param string $key
+     *
+     * @return bool
+     */
+    public function hasAttribute(string $key) : bool;
+
+    /**
+     * Returns the value of an attribute.
+     *
+     * @param string $key
+     * @param mixed  $default
+     *
+     * @return mixed
+     */
+    public function getAttribute(string $key, $default = null);
+
+    /**
+     * Returns all the attributes of this node.
+     *
+     * @return array
+     */
+    public function getAttributes() : array;
+
+    /**
+     * Replaces all the attributes of this node.
+     *
+     * @param array $attributes
+     */
+    public function setAttributes(array $attributes);
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Arg.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Arg.php
new file mode 100644
index 0000000000000000000000000000000000000000..b25b0904a229c2c85d9ad27d43442b1345eb7113
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Arg.php
@@ -0,0 +1,45 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node;
+
+use PhpParser\NodeAbstract;
+
+class Arg extends NodeAbstract
+{
+    /** @var Identifier|null Parameter name (for named parameters) */
+    public $name;
+    /** @var Expr Value to pass */
+    public $value;
+    /** @var bool Whether to pass by ref */
+    public $byRef;
+    /** @var bool Whether to unpack the argument */
+    public $unpack;
+
+    /**
+     * Constructs a function call argument node.
+     *
+     * @param Expr  $value      Value to pass
+     * @param bool  $byRef      Whether to pass by ref
+     * @param bool  $unpack     Whether to unpack the argument
+     * @param array $attributes Additional attributes
+     * @param Identifier|null $name Parameter name (for named parameters)
+     */
+    public function __construct(
+        Expr $value, bool $byRef = false, bool $unpack = false, array $attributes = [],
+        Identifier $name = null
+    ) {
+        $this->attributes = $attributes;
+        $this->name = $name;
+        $this->value = $value;
+        $this->byRef = $byRef;
+        $this->unpack = $unpack;
+    }
+
+    public function getSubNodeNames() : array {
+        return ['name', 'value', 'byRef', 'unpack'];
+    }
+    
+    public function getType() : string {
+        return 'Arg';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Attribute.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Attribute.php
new file mode 100644
index 0000000000000000000000000000000000000000..c96f66e5147ef89d7f53c4b952d909bcd4d4ed97
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Attribute.php
@@ -0,0 +1,34 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node;
+
+use PhpParser\Node;
+use PhpParser\NodeAbstract;
+
+class Attribute extends NodeAbstract
+{
+    /** @var Name Attribute name */
+    public $name;
+
+    /** @var Arg[] Attribute arguments */
+    public $args;
+
+    /**
+     * @param Node\Name $name       Attribute name
+     * @param Arg[]     $args       Attribute arguments
+     * @param array     $attributes Additional node attributes
+     */
+    public function __construct(Name $name, array $args = [], array $attributes = []) {
+        $this->attributes = $attributes;
+        $this->name = $name;
+        $this->args = $args;
+    }
+
+    public function getSubNodeNames() : array {
+        return ['name', 'args'];
+    }
+
+    public function getType() : string {
+        return 'Attribute';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/AttributeGroup.php b/vendor/nikic/php-parser/lib/PhpParser/Node/AttributeGroup.php
new file mode 100644
index 0000000000000000000000000000000000000000..613bfc41343cb718bfc200b05afc0d98cf457267
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/AttributeGroup.php
@@ -0,0 +1,29 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node;
+
+use PhpParser\Node;
+use PhpParser\NodeAbstract;
+
+class AttributeGroup extends NodeAbstract
+{
+    /** @var Attribute[] Attributes */
+    public $attrs;
+
+    /**
+     * @param Attribute[] $attrs PHP attributes
+     * @param array $attributes Additional node attributes
+     */
+    public function __construct(array $attrs, array $attributes = []) {
+        $this->attributes = $attributes;
+        $this->attrs = $attrs;
+    }
+
+    public function getSubNodeNames() : array {
+        return ['attrs'];
+    }
+
+    public function getType() : string {
+        return 'AttributeGroup';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Const_.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Const_.php
new file mode 100644
index 0000000000000000000000000000000000000000..789a426552d45ba3f1714a005b82ea4c68fc562b
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Const_.php
@@ -0,0 +1,37 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node;
+
+use PhpParser\NodeAbstract;
+
+/**
+ * @property Name $namespacedName Namespaced name (for global constants, if using NameResolver)
+ */
+class Const_ extends NodeAbstract
+{
+    /** @var Identifier Name */
+    public $name;
+    /** @var Expr Value */
+    public $value;
+
+    /**
+     * Constructs a const node for use in class const and const statements.
+     *
+     * @param string|Identifier $name       Name
+     * @param Expr              $value      Value
+     * @param array             $attributes Additional attributes
+     */
+    public function __construct($name, Expr $value, array $attributes = []) {
+        $this->attributes = $attributes;
+        $this->name = \is_string($name) ? new Identifier($name) : $name;
+        $this->value = $value;
+    }
+
+    public function getSubNodeNames() : array {
+        return ['name', 'value'];
+    }
+    
+    public function getType() : string {
+        return 'Const';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Expr.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr.php
new file mode 100644
index 0000000000000000000000000000000000000000..6cf4df2233039ffa47035cab7bc69fda7d145272
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr.php
@@ -0,0 +1,9 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node;
+
+use PhpParser\NodeAbstract;
+
+abstract class Expr extends NodeAbstract
+{
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/ArrayDimFetch.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/ArrayDimFetch.php
new file mode 100644
index 0000000000000000000000000000000000000000..71694478e946b9fe9729574cb1c67e0d7fe208fd
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/ArrayDimFetch.php
@@ -0,0 +1,34 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node\Expr;
+
+use PhpParser\Node\Expr;
+
+class ArrayDimFetch extends Expr
+{
+    /** @var Expr Variable */
+    public $var;
+    /** @var null|Expr Array index / dim */
+    public $dim;
+
+    /**
+     * Constructs an array index fetch node.
+     *
+     * @param Expr      $var        Variable
+     * @param null|Expr $dim        Array index / dim
+     * @param array     $attributes Additional attributes
+     */
+    public function __construct(Expr $var, Expr $dim = null, array $attributes = []) {
+        $this->attributes = $attributes;
+        $this->var = $var;
+        $this->dim = $dim;
+    }
+
+    public function getSubNodeNames() : array {
+        return ['var', 'dim'];
+    }
+    
+    public function getType() : string {
+        return 'Expr_ArrayDimFetch';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/ArrayItem.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/ArrayItem.php
new file mode 100644
index 0000000000000000000000000000000000000000..1b078f82183200acde9c7374ae8acad2e3d0d529
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/ArrayItem.php
@@ -0,0 +1,41 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node\Expr;
+
+use PhpParser\Node\Expr;
+
+class ArrayItem extends Expr
+{
+    /** @var null|Expr Key */
+    public $key;
+    /** @var Expr Value */
+    public $value;
+    /** @var bool Whether to assign by reference */
+    public $byRef;
+    /** @var bool Whether to unpack the argument */
+    public $unpack;
+
+    /**
+     * Constructs an array item node.
+     *
+     * @param Expr      $value      Value
+     * @param null|Expr $key        Key
+     * @param bool      $byRef      Whether to assign by reference
+     * @param array     $attributes Additional attributes
+     */
+    public function __construct(Expr $value, Expr $key = null, bool $byRef = false, array $attributes = [], bool $unpack = false) {
+        $this->attributes = $attributes;
+        $this->key = $key;
+        $this->value = $value;
+        $this->byRef = $byRef;
+        $this->unpack = $unpack;
+    }
+
+    public function getSubNodeNames() : array {
+        return ['key', 'value', 'byRef', 'unpack'];
+    }
+
+    public function getType() : string {
+        return 'Expr_ArrayItem';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Array_.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Array_.php
new file mode 100644
index 0000000000000000000000000000000000000000..e6eaa2834db65fee7d42cab31b19219a2d54cd41
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Array_.php
@@ -0,0 +1,34 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node\Expr;
+
+use PhpParser\Node\Expr;
+
+class Array_ extends Expr
+{
+    // For use in "kind" attribute
+    const KIND_LONG = 1;  // array() syntax
+    const KIND_SHORT = 2; // [] syntax
+
+    /** @var (ArrayItem|null)[] Items */
+    public $items;
+
+    /**
+     * Constructs an array node.
+     *
+     * @param (ArrayItem|null)[] $items      Items of the array
+     * @param array       $attributes Additional attributes
+     */
+    public function __construct(array $items = [], array $attributes = []) {
+        $this->attributes = $attributes;
+        $this->items = $items;
+    }
+
+    public function getSubNodeNames() : array {
+        return ['items'];
+    }
+    
+    public function getType() : string {
+        return 'Expr_Array';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/ArrowFunction.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/ArrowFunction.php
new file mode 100644
index 0000000000000000000000000000000000000000..d293f0ae41802abf0434de0ac06790eac39e8909
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/ArrowFunction.php
@@ -0,0 +1,79 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node\Expr;
+
+use PhpParser\Node;
+use PhpParser\Node\Expr;
+use PhpParser\Node\FunctionLike;
+
+class ArrowFunction extends Expr implements FunctionLike
+{
+    /** @var bool */
+    public $static;
+
+    /** @var bool */
+    public $byRef;
+
+    /** @var Node\Param[] */
+    public $params = [];
+
+    /** @var null|Node\Identifier|Node\Name|Node\NullableType|Node\UnionType */
+    public $returnType;
+
+    /** @var Expr */
+    public $expr;
+    /** @var Node\AttributeGroup[] */
+    public $attrGroups;
+
+    /**
+     * @param array $subNodes   Array of the following optional subnodes:
+     *                          'static'     => false   : Whether the closure is static
+     *                          'byRef'      => false   : Whether to return by reference
+     *                          'params'     => array() : Parameters
+     *                          'returnType' => null    : Return type
+     *                          'expr'       => Expr    : Expression body
+     *                          'attrGroups' => array() : PHP attribute groups
+     * @param array $attributes Additional attributes
+     */
+    public function __construct(array $subNodes = [], array $attributes = []) {
+        $this->attributes = $attributes;
+        $this->static = $subNodes['static'] ?? false;
+        $this->byRef = $subNodes['byRef'] ?? false;
+        $this->params = $subNodes['params'] ?? [];
+        $returnType = $subNodes['returnType'] ?? null;
+        $this->returnType = \is_string($returnType) ? new Node\Identifier($returnType) : $returnType;
+        $this->expr = $subNodes['expr'] ?? null;
+        $this->attrGroups = $subNodes['attrGroups'] ?? [];
+    }
+
+    public function getSubNodeNames() : array {
+        return ['attrGroups', 'static', 'byRef', 'params', 'returnType', 'expr'];
+    }
+
+    public function returnsByRef() : bool {
+        return $this->byRef;
+    }
+
+    public function getParams() : array {
+        return $this->params;
+    }
+
+    public function getReturnType() {
+        return $this->returnType;
+    }
+
+    public function getAttrGroups() : array {
+        return $this->attrGroups;
+    }
+
+    /**
+     * @return Node\Stmt\Return_[]
+     */
+    public function getStmts() : array {
+        return [new Node\Stmt\Return_($this->expr)];
+    }
+
+    public function getType() : string {
+        return 'Expr_ArrowFunction';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Assign.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Assign.php
new file mode 100644
index 0000000000000000000000000000000000000000..cf9e6e82b465aea897da13819cc6a337a0fee192
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Assign.php
@@ -0,0 +1,34 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node\Expr;
+
+use PhpParser\Node\Expr;
+
+class Assign extends Expr
+{
+    /** @var Expr Variable */
+    public $var;
+    /** @var Expr Expression */
+    public $expr;
+
+    /**
+     * Constructs an assignment node.
+     *
+     * @param Expr  $var        Variable
+     * @param Expr  $expr       Expression
+     * @param array $attributes Additional attributes
+     */
+    public function __construct(Expr $var, Expr $expr, array $attributes = []) {
+        $this->attributes = $attributes;
+        $this->var = $var;
+        $this->expr = $expr;
+    }
+
+    public function getSubNodeNames() : array {
+        return ['var', 'expr'];
+    }
+    
+    public function getType() : string {
+        return 'Expr_Assign';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp.php
new file mode 100644
index 0000000000000000000000000000000000000000..bce8604f14d07dbcf8a97162006961aa9feba981
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp.php
@@ -0,0 +1,30 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node\Expr;
+
+use PhpParser\Node\Expr;
+
+abstract class AssignOp extends Expr
+{
+    /** @var Expr Variable */
+    public $var;
+    /** @var Expr Expression */
+    public $expr;
+
+    /**
+     * Constructs a compound assignment operation node.
+     *
+     * @param Expr  $var        Variable
+     * @param Expr  $expr       Expression
+     * @param array $attributes Additional attributes
+     */
+    public function __construct(Expr $var, Expr $expr, array $attributes = []) {
+        $this->attributes = $attributes;
+        $this->var = $var;
+        $this->expr = $expr;
+    }
+
+    public function getSubNodeNames() : array {
+        return ['var', 'expr'];
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/BitwiseAnd.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/BitwiseAnd.php
new file mode 100644
index 0000000000000000000000000000000000000000..420284cdc1ba4c70fce21df388b2a149ec448ab0
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/BitwiseAnd.php
@@ -0,0 +1,12 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node\Expr\AssignOp;
+
+use PhpParser\Node\Expr\AssignOp;
+
+class BitwiseAnd extends AssignOp
+{
+    public function getType() : string {
+        return 'Expr_AssignOp_BitwiseAnd';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/BitwiseOr.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/BitwiseOr.php
new file mode 100644
index 0000000000000000000000000000000000000000..481ad3bbceb316ffc2e120f050a66e48d0d756ec
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/BitwiseOr.php
@@ -0,0 +1,12 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node\Expr\AssignOp;
+
+use PhpParser\Node\Expr\AssignOp;
+
+class BitwiseOr extends AssignOp
+{
+    public function getType() : string {
+        return 'Expr_AssignOp_BitwiseOr';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/BitwiseXor.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/BitwiseXor.php
new file mode 100644
index 0000000000000000000000000000000000000000..f41d4c8e73f5033e762669c5532e33735bb7e3ed
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/BitwiseXor.php
@@ -0,0 +1,12 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node\Expr\AssignOp;
+
+use PhpParser\Node\Expr\AssignOp;
+
+class BitwiseXor extends AssignOp
+{
+    public function getType() : string {
+        return 'Expr_AssignOp_BitwiseXor';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Coalesce.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Coalesce.php
new file mode 100644
index 0000000000000000000000000000000000000000..c0e9b316cf08ecdf6e688891a20c3b6fd949927b
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Coalesce.php
@@ -0,0 +1,12 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node\Expr\AssignOp;
+
+use PhpParser\Node\Expr\AssignOp;
+
+class Coalesce extends AssignOp
+{
+    public function getType() : string {
+        return 'Expr_AssignOp_Coalesce';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Concat.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Concat.php
new file mode 100644
index 0000000000000000000000000000000000000000..ac1682078517252e466982da2eb935b59151c1ba
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Concat.php
@@ -0,0 +1,12 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node\Expr\AssignOp;
+
+use PhpParser\Node\Expr\AssignOp;
+
+class Concat extends AssignOp
+{
+    public function getType() : string {
+        return 'Expr_AssignOp_Concat';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Div.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Div.php
new file mode 100644
index 0000000000000000000000000000000000000000..f1fcfc09adc3360a22c8e385aee1c24f5f9d26e2
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Div.php
@@ -0,0 +1,12 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node\Expr\AssignOp;
+
+use PhpParser\Node\Expr\AssignOp;
+
+class Div extends AssignOp
+{
+    public function getType() : string {
+        return 'Expr_AssignOp_Div';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Minus.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Minus.php
new file mode 100644
index 0000000000000000000000000000000000000000..82ef4517b7830d50e4d4e1da6fe31dcd4587f7ac
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Minus.php
@@ -0,0 +1,12 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node\Expr\AssignOp;
+
+use PhpParser\Node\Expr\AssignOp;
+
+class Minus extends AssignOp
+{
+    public function getType() : string {
+        return 'Expr_AssignOp_Minus';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Mod.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Mod.php
new file mode 100644
index 0000000000000000000000000000000000000000..be3b4a0adbd390d6c0b21f0539137b80782523a0
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Mod.php
@@ -0,0 +1,12 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node\Expr\AssignOp;
+
+use PhpParser\Node\Expr\AssignOp;
+
+class Mod extends AssignOp
+{
+    public function getType() : string {
+        return 'Expr_AssignOp_Mod';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Mul.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Mul.php
new file mode 100644
index 0000000000000000000000000000000000000000..5c196c3bcb5b2e507b78514cf62318885f18003a
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Mul.php
@@ -0,0 +1,12 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node\Expr\AssignOp;
+
+use PhpParser\Node\Expr\AssignOp;
+
+class Mul extends AssignOp
+{
+    public function getType() : string {
+        return 'Expr_AssignOp_Mul';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Plus.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Plus.php
new file mode 100644
index 0000000000000000000000000000000000000000..dd101c61cb95b09b176cb0484715642d41c33043
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Plus.php
@@ -0,0 +1,12 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node\Expr\AssignOp;
+
+use PhpParser\Node\Expr\AssignOp;
+
+class Plus extends AssignOp
+{
+    public function getType() : string {
+        return 'Expr_AssignOp_Plus';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Pow.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Pow.php
new file mode 100644
index 0000000000000000000000000000000000000000..5e1307d1dae824e49652c9e063bc6ea485db4d28
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Pow.php
@@ -0,0 +1,12 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node\Expr\AssignOp;
+
+use PhpParser\Node\Expr\AssignOp;
+
+class Pow extends AssignOp
+{
+    public function getType() : string {
+        return 'Expr_AssignOp_Pow';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/ShiftLeft.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/ShiftLeft.php
new file mode 100644
index 0000000000000000000000000000000000000000..b8f88269b682f465abc08cb01ba15cf87b470d2f
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/ShiftLeft.php
@@ -0,0 +1,12 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node\Expr\AssignOp;
+
+use PhpParser\Node\Expr\AssignOp;
+
+class ShiftLeft extends AssignOp
+{
+    public function getType() : string {
+        return 'Expr_AssignOp_ShiftLeft';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/ShiftRight.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/ShiftRight.php
new file mode 100644
index 0000000000000000000000000000000000000000..e0cc67b7ff27b4f915c4e69fdb1c17130e352928
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/ShiftRight.php
@@ -0,0 +1,12 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node\Expr\AssignOp;
+
+use PhpParser\Node\Expr\AssignOp;
+
+class ShiftRight extends AssignOp
+{
+    public function getType() : string {
+        return 'Expr_AssignOp_ShiftRight';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignRef.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignRef.php
new file mode 100644
index 0000000000000000000000000000000000000000..de3c644c3c129b793fbc5feb86ee24e3026e7aac
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignRef.php
@@ -0,0 +1,34 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node\Expr;
+
+use PhpParser\Node\Expr;
+
+class AssignRef extends Expr
+{
+    /** @var Expr Variable reference is assigned to */
+    public $var;
+    /** @var Expr Variable which is referenced */
+    public $expr;
+
+    /**
+     * Constructs an assignment node.
+     *
+     * @param Expr  $var        Variable
+     * @param Expr  $expr       Expression
+     * @param array $attributes Additional attributes
+     */
+    public function __construct(Expr $var, Expr $expr, array $attributes = []) {
+        $this->attributes = $attributes;
+        $this->var = $var;
+        $this->expr = $expr;
+    }
+
+    public function getSubNodeNames() : array {
+        return ['var', 'expr'];
+    }
+    
+    public function getType() : string {
+        return 'Expr_AssignRef';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp.php
new file mode 100644
index 0000000000000000000000000000000000000000..d9c582b0d25cc0c4f0f00fdc9feeabb4255a4539
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp.php
@@ -0,0 +1,40 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node\Expr;
+
+use PhpParser\Node\Expr;
+
+abstract class BinaryOp extends Expr
+{
+    /** @var Expr The left hand side expression */
+    public $left;
+    /** @var Expr The right hand side expression */
+    public $right;
+
+    /**
+     * Constructs a binary operator node.
+     *
+     * @param Expr  $left       The left hand side expression
+     * @param Expr  $right      The right hand side expression
+     * @param array $attributes Additional attributes
+     */
+    public function __construct(Expr $left, Expr $right, array $attributes = []) {
+        $this->attributes = $attributes;
+        $this->left = $left;
+        $this->right = $right;
+    }
+
+    public function getSubNodeNames() : array {
+        return ['left', 'right'];
+    }
+
+    /**
+     * Get the operator sigil for this binary operation.
+     *
+     * In the case there are multiple possible sigils for an operator, this method does not
+     * necessarily return the one used in the parsed code.
+     *
+     * @return string
+     */
+    abstract public function getOperatorSigil() : string;
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/BitwiseAnd.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/BitwiseAnd.php
new file mode 100644
index 0000000000000000000000000000000000000000..d907393bfa70569049e973e1535d70e65c9b690e
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/BitwiseAnd.php
@@ -0,0 +1,16 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node\Expr\BinaryOp;
+
+use PhpParser\Node\Expr\BinaryOp;
+
+class BitwiseAnd extends BinaryOp
+{
+    public function getOperatorSigil() : string {
+        return '&';
+    }
+    
+    public function getType() : string {
+        return 'Expr_BinaryOp_BitwiseAnd';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/BitwiseOr.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/BitwiseOr.php
new file mode 100644
index 0000000000000000000000000000000000000000..d92069f321caa2f94ce8157dd4f7442f1e121a4f
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/BitwiseOr.php
@@ -0,0 +1,16 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node\Expr\BinaryOp;
+
+use PhpParser\Node\Expr\BinaryOp;
+
+class BitwiseOr extends BinaryOp
+{
+    public function getOperatorSigil() : string {
+        return '|';
+    }
+    
+    public function getType() : string {
+        return 'Expr_BinaryOp_BitwiseOr';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/BitwiseXor.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/BitwiseXor.php
new file mode 100644
index 0000000000000000000000000000000000000000..40fa94f88709a3198a0bbc5179b616a2c232eba0
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/BitwiseXor.php
@@ -0,0 +1,16 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node\Expr\BinaryOp;
+
+use PhpParser\Node\Expr\BinaryOp;
+
+class BitwiseXor extends BinaryOp
+{
+    public function getOperatorSigil() : string {
+        return '^';
+    }
+    
+    public function getType() : string {
+        return 'Expr_BinaryOp_BitwiseXor';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/BooleanAnd.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/BooleanAnd.php
new file mode 100644
index 0000000000000000000000000000000000000000..4c3c9e9b1e1e97b6dc69ed1aab1ea4b23bb2fc4a
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/BooleanAnd.php
@@ -0,0 +1,16 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node\Expr\BinaryOp;
+
+use PhpParser\Node\Expr\BinaryOp;
+
+class BooleanAnd extends BinaryOp
+{
+    public function getOperatorSigil() : string {
+        return '&&';
+    }
+    
+    public function getType() : string {
+        return 'Expr_BinaryOp_BooleanAnd';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/BooleanOr.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/BooleanOr.php
new file mode 100644
index 0000000000000000000000000000000000000000..5ad417279ae3a084472f20b06dd1ea4f32735812
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/BooleanOr.php
@@ -0,0 +1,16 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node\Expr\BinaryOp;
+
+use PhpParser\Node\Expr\BinaryOp;
+
+class BooleanOr extends BinaryOp
+{
+    public function getOperatorSigil() : string {
+        return '||';
+    }
+    
+    public function getType() : string {
+        return 'Expr_BinaryOp_BooleanOr';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Coalesce.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Coalesce.php
new file mode 100644
index 0000000000000000000000000000000000000000..b8cf6f45991fb47067ee79634f09e1bf5f4721d0
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Coalesce.php
@@ -0,0 +1,16 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node\Expr\BinaryOp;
+
+use PhpParser\Node\Expr\BinaryOp;
+
+class Coalesce extends BinaryOp
+{
+    public function getOperatorSigil() : string {
+        return '??';
+    }
+    
+    public function getType() : string {
+        return 'Expr_BinaryOp_Coalesce';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Concat.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Concat.php
new file mode 100644
index 0000000000000000000000000000000000000000..9a8d9873c081073f24dbef3a16662f216d7d53ad
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Concat.php
@@ -0,0 +1,16 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node\Expr\BinaryOp;
+
+use PhpParser\Node\Expr\BinaryOp;
+
+class Concat extends BinaryOp
+{
+    public function getOperatorSigil() : string {
+        return '.';
+    }
+    
+    public function getType() : string {
+        return 'Expr_BinaryOp_Concat';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Div.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Div.php
new file mode 100644
index 0000000000000000000000000000000000000000..d38df0db4de54a5231f7144d5edf9db2be23db20
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Div.php
@@ -0,0 +1,16 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node\Expr\BinaryOp;
+
+use PhpParser\Node\Expr\BinaryOp;
+
+class Div extends BinaryOp
+{
+    public function getOperatorSigil() : string {
+        return '/';
+    }
+    
+    public function getType() : string {
+        return 'Expr_BinaryOp_Div';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Equal.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Equal.php
new file mode 100644
index 0000000000000000000000000000000000000000..e7b11dc824df212a4860b841d35ef2537ca3f1b9
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Equal.php
@@ -0,0 +1,16 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node\Expr\BinaryOp;
+
+use PhpParser\Node\Expr\BinaryOp;
+
+class Equal extends BinaryOp
+{
+    public function getOperatorSigil() : string {
+        return '==';
+    }
+    
+    public function getType() : string {
+        return 'Expr_BinaryOp_Equal';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Greater.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Greater.php
new file mode 100644
index 0000000000000000000000000000000000000000..da01f7a100e8cdd964cc5fc097b83274276cee88
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Greater.php
@@ -0,0 +1,16 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node\Expr\BinaryOp;
+
+use PhpParser\Node\Expr\BinaryOp;
+
+class Greater extends BinaryOp
+{
+    public function getOperatorSigil() : string {
+        return '>';
+    }
+    
+    public function getType() : string {
+        return 'Expr_BinaryOp_Greater';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/GreaterOrEqual.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/GreaterOrEqual.php
new file mode 100644
index 0000000000000000000000000000000000000000..d677502cf5bd67469ca6a06bb60bab28463fd6a7
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/GreaterOrEqual.php
@@ -0,0 +1,16 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node\Expr\BinaryOp;
+
+use PhpParser\Node\Expr\BinaryOp;
+
+class GreaterOrEqual extends BinaryOp
+{
+    public function getOperatorSigil() : string {
+        return '>=';
+    }
+    
+    public function getType() : string {
+        return 'Expr_BinaryOp_GreaterOrEqual';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Identical.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Identical.php
new file mode 100644
index 0000000000000000000000000000000000000000..3d96285c64f4fcf98f2d68fc08592d9ce0401d54
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Identical.php
@@ -0,0 +1,16 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node\Expr\BinaryOp;
+
+use PhpParser\Node\Expr\BinaryOp;
+
+class Identical extends BinaryOp
+{
+    public function getOperatorSigil() : string {
+        return '===';
+    }
+    
+    public function getType() : string {
+        return 'Expr_BinaryOp_Identical';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/LogicalAnd.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/LogicalAnd.php
new file mode 100644
index 0000000000000000000000000000000000000000..2a3afd548f1b87716bd514a1d8fb76ac121ff468
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/LogicalAnd.php
@@ -0,0 +1,16 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node\Expr\BinaryOp;
+
+use PhpParser\Node\Expr\BinaryOp;
+
+class LogicalAnd extends BinaryOp
+{
+    public function getOperatorSigil() : string {
+        return 'and';
+    }
+    
+    public function getType() : string {
+        return 'Expr_BinaryOp_LogicalAnd';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/LogicalOr.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/LogicalOr.php
new file mode 100644
index 0000000000000000000000000000000000000000..21507dba6302a70f29d5f90e2fbc483f367dcd6a
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/LogicalOr.php
@@ -0,0 +1,16 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node\Expr\BinaryOp;
+
+use PhpParser\Node\Expr\BinaryOp;
+
+class LogicalOr extends BinaryOp
+{
+    public function getOperatorSigil() : string {
+        return 'or';
+    }
+    
+    public function getType() : string {
+        return 'Expr_BinaryOp_LogicalOr';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/LogicalXor.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/LogicalXor.php
new file mode 100644
index 0000000000000000000000000000000000000000..261c6a9100c729ac3844d4ee5dcee4e021f05b5a
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/LogicalXor.php
@@ -0,0 +1,16 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node\Expr\BinaryOp;
+
+use PhpParser\Node\Expr\BinaryOp;
+
+class LogicalXor extends BinaryOp
+{
+    public function getOperatorSigil() : string {
+        return 'xor';
+    }
+    
+    public function getType() : string {
+        return 'Expr_BinaryOp_LogicalXor';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Minus.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Minus.php
new file mode 100644
index 0000000000000000000000000000000000000000..54b3c6e9059264af552d26d8c80c0d58bbfc83c8
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Minus.php
@@ -0,0 +1,16 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node\Expr\BinaryOp;
+
+use PhpParser\Node\Expr\BinaryOp;
+
+class Minus extends BinaryOp
+{
+    public function getOperatorSigil() : string {
+        return '-';
+    }
+    
+    public function getType() : string {
+        return 'Expr_BinaryOp_Minus';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Mod.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Mod.php
new file mode 100644
index 0000000000000000000000000000000000000000..10340404017b4948a7089caffa2c69dab5ec6570
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Mod.php
@@ -0,0 +1,16 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node\Expr\BinaryOp;
+
+use PhpParser\Node\Expr\BinaryOp;
+
+class Mod extends BinaryOp
+{
+    public function getOperatorSigil() : string {
+        return '%';
+    }
+    
+    public function getType() : string {
+        return 'Expr_BinaryOp_Mod';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Mul.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Mul.php
new file mode 100644
index 0000000000000000000000000000000000000000..b82d0b2fcb7843bfe9f32e6549315726ebeb9ab5
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Mul.php
@@ -0,0 +1,16 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node\Expr\BinaryOp;
+
+use PhpParser\Node\Expr\BinaryOp;
+
+class Mul extends BinaryOp
+{
+    public function getOperatorSigil() : string {
+        return '*';
+    }
+    
+    public function getType() : string {
+        return 'Expr_BinaryOp_Mul';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/NotEqual.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/NotEqual.php
new file mode 100644
index 0000000000000000000000000000000000000000..51075da56310787283c33995879679ee3048d28d
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/NotEqual.php
@@ -0,0 +1,16 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node\Expr\BinaryOp;
+
+use PhpParser\Node\Expr\BinaryOp;
+
+class NotEqual extends BinaryOp
+{
+    public function getOperatorSigil() : string {
+        return '!=';
+    }
+    
+    public function getType() : string {
+        return 'Expr_BinaryOp_NotEqual';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/NotIdentical.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/NotIdentical.php
new file mode 100644
index 0000000000000000000000000000000000000000..fa4050e058c70105e13c82ab0621e89e24e131aa
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/NotIdentical.php
@@ -0,0 +1,16 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node\Expr\BinaryOp;
+
+use PhpParser\Node\Expr\BinaryOp;
+
+class NotIdentical extends BinaryOp
+{
+    public function getOperatorSigil() : string {
+        return '!==';
+    }
+    
+    public function getType() : string {
+        return 'Expr_BinaryOp_NotIdentical';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Plus.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Plus.php
new file mode 100644
index 0000000000000000000000000000000000000000..62f0229985dbdcd299a5e5d839fa477b31a545a7
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Plus.php
@@ -0,0 +1,16 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node\Expr\BinaryOp;
+
+use PhpParser\Node\Expr\BinaryOp;
+
+class Plus extends BinaryOp
+{
+    public function getOperatorSigil() : string {
+        return '+';
+    }
+    
+    public function getType() : string {
+        return 'Expr_BinaryOp_Plus';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Pow.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Pow.php
new file mode 100644
index 0000000000000000000000000000000000000000..572a1e8e4343b3d0dbfc724704251b7bf4773f7c
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Pow.php
@@ -0,0 +1,16 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node\Expr\BinaryOp;
+
+use PhpParser\Node\Expr\BinaryOp;
+
+class Pow extends BinaryOp
+{
+    public function getOperatorSigil() : string {
+        return '**';
+    }
+    
+    public function getType() : string {
+        return 'Expr_BinaryOp_Pow';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/ShiftLeft.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/ShiftLeft.php
new file mode 100644
index 0000000000000000000000000000000000000000..4e70b4ef0be5f69dd42112130d8db24a1d1a3fdb
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/ShiftLeft.php
@@ -0,0 +1,16 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node\Expr\BinaryOp;
+
+use PhpParser\Node\Expr\BinaryOp;
+
+class ShiftLeft extends BinaryOp
+{
+    public function getOperatorSigil() : string {
+        return '<<';
+    }
+    
+    public function getType() : string {
+        return 'Expr_BinaryOp_ShiftLeft';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/ShiftRight.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/ShiftRight.php
new file mode 100644
index 0000000000000000000000000000000000000000..45acbd046108da712b7cc7d84f970bb29b39e351
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/ShiftRight.php
@@ -0,0 +1,16 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node\Expr\BinaryOp;
+
+use PhpParser\Node\Expr\BinaryOp;
+
+class ShiftRight extends BinaryOp
+{
+    public function getOperatorSigil() : string {
+        return '>>';
+    }
+    
+    public function getType() : string {
+        return 'Expr_BinaryOp_ShiftRight';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Smaller.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Smaller.php
new file mode 100644
index 0000000000000000000000000000000000000000..3cb8e7e0d16680ed69aadf22d4c45a2749fa375e
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Smaller.php
@@ -0,0 +1,16 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node\Expr\BinaryOp;
+
+use PhpParser\Node\Expr\BinaryOp;
+
+class Smaller extends BinaryOp
+{
+    public function getOperatorSigil() : string {
+        return '<';
+    }
+    
+    public function getType() : string {
+        return 'Expr_BinaryOp_Smaller';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/SmallerOrEqual.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/SmallerOrEqual.php
new file mode 100644
index 0000000000000000000000000000000000000000..83e8e214d0df3e5c7181480a2d2fbf086ebda725
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/SmallerOrEqual.php
@@ -0,0 +1,16 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node\Expr\BinaryOp;
+
+use PhpParser\Node\Expr\BinaryOp;
+
+class SmallerOrEqual extends BinaryOp
+{
+    public function getOperatorSigil() : string {
+        return '<=';
+    }
+    
+    public function getType() : string {
+        return 'Expr_BinaryOp_SmallerOrEqual';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Spaceship.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Spaceship.php
new file mode 100644
index 0000000000000000000000000000000000000000..8c6d787f6aacc6d3ba4e2d4ccb6738b3f98580e4
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Spaceship.php
@@ -0,0 +1,16 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node\Expr\BinaryOp;
+
+use PhpParser\Node\Expr\BinaryOp;
+
+class Spaceship extends BinaryOp
+{
+    public function getOperatorSigil() : string {
+        return '<=>';
+    }
+    
+    public function getType() : string {
+        return 'Expr_BinaryOp_Spaceship';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BitwiseNot.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BitwiseNot.php
new file mode 100644
index 0000000000000000000000000000000000000000..ed44984beaa42ea3deee0b91a652d8bf772988a6
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BitwiseNot.php
@@ -0,0 +1,30 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node\Expr;
+
+use PhpParser\Node\Expr;
+
+class BitwiseNot extends Expr
+{
+    /** @var Expr Expression */
+    public $expr;
+
+    /**
+     * Constructs a bitwise not node.
+     *
+     * @param Expr  $expr       Expression
+     * @param array $attributes Additional attributes
+     */
+    public function __construct(Expr $expr, array $attributes = []) {
+        $this->attributes = $attributes;
+        $this->expr = $expr;
+    }
+
+    public function getSubNodeNames() : array {
+        return ['expr'];
+    }
+    
+    public function getType() : string {
+        return 'Expr_BitwiseNot';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BooleanNot.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BooleanNot.php
new file mode 100644
index 0000000000000000000000000000000000000000..bf27e9f657b0f30750aad99c57b949806beae6e0
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BooleanNot.php
@@ -0,0 +1,30 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node\Expr;
+
+use PhpParser\Node\Expr;
+
+class BooleanNot extends Expr
+{
+    /** @var Expr Expression */
+    public $expr;
+
+    /**
+     * Constructs a boolean not node.
+     *
+     * @param Expr $expr       Expression
+     * @param array               $attributes Additional attributes
+     */
+    public function __construct(Expr $expr, array $attributes = []) {
+        $this->attributes = $attributes;
+        $this->expr = $expr;
+    }
+
+    public function getSubNodeNames() : array {
+        return ['expr'];
+    }
+    
+    public function getType() : string {
+        return 'Expr_BooleanNot';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Cast.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Cast.php
new file mode 100644
index 0000000000000000000000000000000000000000..36769d4fc6b56562fd2407324a99c12dada907c4
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Cast.php
@@ -0,0 +1,26 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node\Expr;
+
+use PhpParser\Node\Expr;
+
+abstract class Cast extends Expr
+{
+    /** @var Expr Expression */
+    public $expr;
+
+    /**
+     * Constructs a cast node.
+     *
+     * @param Expr  $expr       Expression
+     * @param array $attributes Additional attributes
+     */
+    public function __construct(Expr $expr, array $attributes = []) {
+        $this->attributes = $attributes;
+        $this->expr = $expr;
+    }
+
+    public function getSubNodeNames() : array {
+        return ['expr'];
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/Array_.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/Array_.php
new file mode 100644
index 0000000000000000000000000000000000000000..57cc473b6256ce93155cb84552a898e113f2640d
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/Array_.php
@@ -0,0 +1,12 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node\Expr\Cast;
+
+use PhpParser\Node\Expr\Cast;
+
+class Array_ extends Cast
+{
+    public function getType() : string {
+        return 'Expr_Cast_Array';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/Bool_.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/Bool_.php
new file mode 100644
index 0000000000000000000000000000000000000000..04eb4af584592fc4e1801ba4305956d212d28f45
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/Bool_.php
@@ -0,0 +1,12 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node\Expr\Cast;
+
+use PhpParser\Node\Expr\Cast;
+
+class Bool_ extends Cast
+{
+    public function getType() : string {
+        return 'Expr_Cast_Bool';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/Double.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/Double.php
new file mode 100644
index 0000000000000000000000000000000000000000..891ba5f87085921a0d986af00d592493d95e3004
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/Double.php
@@ -0,0 +1,17 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node\Expr\Cast;
+
+use PhpParser\Node\Expr\Cast;
+
+class Double extends Cast
+{
+    // For use in "kind" attribute
+    const KIND_DOUBLE = 1; // "double" syntax
+    const KIND_FLOAT = 2;  // "float" syntax
+    const KIND_REAL = 3; // "real" syntax
+
+    public function getType() : string {
+        return 'Expr_Cast_Double';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/Int_.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/Int_.php
new file mode 100644
index 0000000000000000000000000000000000000000..01ed594bd0e5d625e02721e9b853e05fec153538
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/Int_.php
@@ -0,0 +1,12 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node\Expr\Cast;
+
+use PhpParser\Node\Expr\Cast;
+
+class Int_ extends Cast
+{
+    public function getType() : string {
+        return 'Expr_Cast_Int';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/Object_.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/Object_.php
new file mode 100644
index 0000000000000000000000000000000000000000..163752be89563027cc4111f63cfe5db49569e790
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/Object_.php
@@ -0,0 +1,12 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node\Expr\Cast;
+
+use PhpParser\Node\Expr\Cast;
+
+class Object_ extends Cast
+{
+    public function getType() : string {
+        return 'Expr_Cast_Object';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/String_.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/String_.php
new file mode 100644
index 0000000000000000000000000000000000000000..b3d99270ac8dd1bdd7e4c464aebc315ca0c973c3
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/String_.php
@@ -0,0 +1,12 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node\Expr\Cast;
+
+use PhpParser\Node\Expr\Cast;
+
+class String_ extends Cast
+{
+    public function getType() : string {
+        return 'Expr_Cast_String';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/Unset_.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/Unset_.php
new file mode 100644
index 0000000000000000000000000000000000000000..accda3e4ff786ce4fee15f2f23151a0feb813123
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/Unset_.php
@@ -0,0 +1,12 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node\Expr\Cast;
+
+use PhpParser\Node\Expr\Cast;
+
+class Unset_ extends Cast
+{
+    public function getType() : string {
+        return 'Expr_Cast_Unset';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/ClassConstFetch.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/ClassConstFetch.php
new file mode 100644
index 0000000000000000000000000000000000000000..faf832f9380bec04fd32305b64a3e0b02feaa9d0
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/ClassConstFetch.php
@@ -0,0 +1,36 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node\Expr;
+
+use PhpParser\Node\Expr;
+use PhpParser\Node\Identifier;
+use PhpParser\Node\Name;
+
+class ClassConstFetch extends Expr
+{
+    /** @var Name|Expr Class name */
+    public $class;
+    /** @var Identifier|Error Constant name */
+    public $name;
+
+    /**
+     * Constructs a class const fetch node.
+     *
+     * @param Name|Expr               $class      Class name
+     * @param string|Identifier|Error $name       Constant name
+     * @param array                   $attributes Additional attributes
+     */
+    public function __construct($class, $name, array $attributes = []) {
+        $this->attributes = $attributes;
+        $this->class = $class;
+        $this->name = \is_string($name) ? new Identifier($name) : $name;
+    }
+
+    public function getSubNodeNames() : array {
+        return ['class', 'name'];
+    }
+    
+    public function getType() : string {
+        return 'Expr_ClassConstFetch';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Clone_.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Clone_.php
new file mode 100644
index 0000000000000000000000000000000000000000..db216b8f8416f8872f2aceb0c4d8c9349ce5220b
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Clone_.php
@@ -0,0 +1,30 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node\Expr;
+
+use PhpParser\Node\Expr;
+
+class Clone_ extends Expr
+{
+    /** @var Expr Expression */
+    public $expr;
+
+    /**
+     * Constructs a clone node.
+     *
+     * @param Expr  $expr       Expression
+     * @param array $attributes Additional attributes
+     */
+    public function __construct(Expr $expr, array $attributes = []) {
+        $this->attributes = $attributes;
+        $this->expr = $expr;
+    }
+
+    public function getSubNodeNames() : array {
+        return ['expr'];
+    }
+    
+    public function getType() : string {
+        return 'Expr_Clone';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Closure.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Closure.php
new file mode 100644
index 0000000000000000000000000000000000000000..56e621f252480abaccff6c150b56c754db13b81b
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Closure.php
@@ -0,0 +1,79 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node\Expr;
+
+use PhpParser\Node;
+use PhpParser\Node\Expr;
+use PhpParser\Node\FunctionLike;
+
+class Closure extends Expr implements FunctionLike
+{
+    /** @var bool Whether the closure is static */
+    public $static;
+    /** @var bool Whether to return by reference */
+    public $byRef;
+    /** @var Node\Param[] Parameters */
+    public $params;
+    /** @var ClosureUse[] use()s */
+    public $uses;
+    /** @var null|Node\Identifier|Node\Name|Node\NullableType|Node\UnionType Return type */
+    public $returnType;
+    /** @var Node\Stmt[] Statements */
+    public $stmts;
+    /** @var Node\AttributeGroup[] PHP attribute groups */
+    public $attrGroups;
+
+    /**
+     * Constructs a lambda function node.
+     *
+     * @param array $subNodes   Array of the following optional subnodes:
+     *                          'static'     => false  : Whether the closure is static
+     *                          'byRef'      => false  : Whether to return by reference
+     *                          'params'     => array(): Parameters
+     *                          'uses'       => array(): use()s
+     *                          'returnType' => null   : Return type
+     *                          'stmts'      => array(): Statements
+     *                          'attrGroups' => array(): PHP attributes groups
+     * @param array $attributes Additional attributes
+     */
+    public function __construct(array $subNodes = [], array $attributes = []) {
+        $this->attributes = $attributes;
+        $this->static = $subNodes['static'] ?? false;
+        $this->byRef = $subNodes['byRef'] ?? false;
+        $this->params = $subNodes['params'] ?? [];
+        $this->uses = $subNodes['uses'] ?? [];
+        $returnType = $subNodes['returnType'] ?? null;
+        $this->returnType = \is_string($returnType) ? new Node\Identifier($returnType) : $returnType;
+        $this->stmts = $subNodes['stmts'] ?? [];
+        $this->attrGroups = $subNodes['attrGroups'] ?? [];
+    }
+
+    public function getSubNodeNames() : array {
+        return ['attrGroups', 'static', 'byRef', 'params', 'uses', 'returnType', 'stmts'];
+    }
+
+    public function returnsByRef() : bool {
+        return $this->byRef;
+    }
+
+    public function getParams() : array {
+        return $this->params;
+    }
+
+    public function getReturnType() {
+        return $this->returnType;
+    }
+
+    /** @return Node\Stmt[] */
+    public function getStmts() : array {
+        return $this->stmts;
+    }
+
+    public function getAttrGroups() : array {
+        return $this->attrGroups;
+    }
+
+    public function getType() : string {
+        return 'Expr_Closure';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/ClosureUse.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/ClosureUse.php
new file mode 100644
index 0000000000000000000000000000000000000000..2b8a096666388891f5bb6c15b23193b8debc8846
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/ClosureUse.php
@@ -0,0 +1,34 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node\Expr;
+
+use PhpParser\Node\Expr;
+
+class ClosureUse extends Expr
+{
+    /** @var Expr\Variable Variable to use */
+    public $var;
+    /** @var bool Whether to use by reference */
+    public $byRef;
+
+    /**
+     * Constructs a closure use node.
+     *
+     * @param Expr\Variable $var        Variable to use
+     * @param bool          $byRef      Whether to use by reference
+     * @param array         $attributes Additional attributes
+     */
+    public function __construct(Expr\Variable $var, bool $byRef = false, array $attributes = []) {
+        $this->attributes = $attributes;
+        $this->var = $var;
+        $this->byRef = $byRef;
+    }
+
+    public function getSubNodeNames() : array {
+        return ['var', 'byRef'];
+    }
+    
+    public function getType() : string {
+        return 'Expr_ClosureUse';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/ConstFetch.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/ConstFetch.php
new file mode 100644
index 0000000000000000000000000000000000000000..14ebd16bd8400b6d3118c15cff9ea2136c6edb38
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/ConstFetch.php
@@ -0,0 +1,31 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node\Expr;
+
+use PhpParser\Node\Expr;
+use PhpParser\Node\Name;
+
+class ConstFetch extends Expr
+{
+    /** @var Name Constant name */
+    public $name;
+
+    /**
+     * Constructs a const fetch node.
+     *
+     * @param Name  $name       Constant name
+     * @param array $attributes Additional attributes
+     */
+    public function __construct(Name $name, array $attributes = []) {
+        $this->attributes = $attributes;
+        $this->name = $name;
+    }
+
+    public function getSubNodeNames() : array {
+        return ['name'];
+    }
+    
+    public function getType() : string {
+        return 'Expr_ConstFetch';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Empty_.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Empty_.php
new file mode 100644
index 0000000000000000000000000000000000000000..4042ec93ca37a8f546d2a78bc362f4dfb378c9ff
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Empty_.php
@@ -0,0 +1,30 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node\Expr;
+
+use PhpParser\Node\Expr;
+
+class Empty_ extends Expr
+{
+    /** @var Expr Expression */
+    public $expr;
+
+    /**
+     * Constructs an empty() node.
+     *
+     * @param Expr  $expr       Expression
+     * @param array $attributes Additional attributes
+     */
+    public function __construct(Expr $expr, array $attributes = []) {
+        $this->attributes = $attributes;
+        $this->expr = $expr;
+    }
+
+    public function getSubNodeNames() : array {
+        return ['expr'];
+    }
+    
+    public function getType() : string {
+        return 'Expr_Empty';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Error.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Error.php
new file mode 100644
index 0000000000000000000000000000000000000000..1637f3aeae0a52ea4bdbc442f6816ea21c42ca17
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Error.php
@@ -0,0 +1,31 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node\Expr;
+
+use PhpParser\Node\Expr;
+
+/**
+ * Error node used during parsing with error recovery.
+ *
+ * An error node may be placed at a position where an expression is required, but an error occurred.
+ * Error nodes will not be present if the parser is run in throwOnError mode (the default).
+ */
+class Error extends Expr
+{
+    /**
+     * Constructs an error node.
+     *
+     * @param array $attributes Additional attributes
+     */
+    public function __construct(array $attributes = []) {
+        $this->attributes = $attributes;
+    }
+
+    public function getSubNodeNames() : array {
+        return [];
+    }
+    
+    public function getType() : string {
+        return 'Expr_Error';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/ErrorSuppress.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/ErrorSuppress.php
new file mode 100644
index 0000000000000000000000000000000000000000..c44ff6f93181748a0dcf56977bde40f8ed9b6558
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/ErrorSuppress.php
@@ -0,0 +1,30 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node\Expr;
+
+use PhpParser\Node\Expr;
+
+class ErrorSuppress extends Expr
+{
+    /** @var Expr Expression */
+    public $expr;
+
+    /**
+     * Constructs an error suppress node.
+     *
+     * @param Expr  $expr       Expression
+     * @param array $attributes Additional attributes
+     */
+    public function __construct(Expr $expr, array $attributes = []) {
+        $this->attributes = $attributes;
+        $this->expr = $expr;
+    }
+
+    public function getSubNodeNames() : array {
+        return ['expr'];
+    }
+    
+    public function getType() : string {
+        return 'Expr_ErrorSuppress';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Eval_.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Eval_.php
new file mode 100644
index 0000000000000000000000000000000000000000..856854743877cfd17c0d38bd2c2d0d5891e93422
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Eval_.php
@@ -0,0 +1,30 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node\Expr;
+
+use PhpParser\Node\Expr;
+
+class Eval_ extends Expr
+{
+    /** @var Expr Expression */
+    public $expr;
+
+    /**
+     * Constructs an eval() node.
+     *
+     * @param Expr  $expr       Expression
+     * @param array $attributes Additional attributes
+     */
+    public function __construct(Expr $expr, array $attributes = []) {
+        $this->attributes = $attributes;
+        $this->expr = $expr;
+    }
+
+    public function getSubNodeNames() : array {
+        return ['expr'];
+    }
+    
+    public function getType() : string {
+        return 'Expr_Eval';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Exit_.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Exit_.php
new file mode 100644
index 0000000000000000000000000000000000000000..b88a8f7e6f3f3912a6f9d32c18c3575da14e3406
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Exit_.php
@@ -0,0 +1,34 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node\Expr;
+
+use PhpParser\Node\Expr;
+
+class Exit_ extends Expr
+{
+    /* For use in "kind" attribute */
+    const KIND_EXIT = 1;
+    const KIND_DIE = 2;
+
+    /** @var null|Expr Expression */
+    public $expr;
+
+    /**
+     * Constructs an exit() node.
+     *
+     * @param null|Expr $expr       Expression
+     * @param array                    $attributes Additional attributes
+     */
+    public function __construct(Expr $expr = null, array $attributes = []) {
+        $this->attributes = $attributes;
+        $this->expr = $expr;
+    }
+
+    public function getSubNodeNames() : array {
+        return ['expr'];
+    }
+    
+    public function getType() : string {
+        return 'Expr_Exit';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/FuncCall.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/FuncCall.php
new file mode 100644
index 0000000000000000000000000000000000000000..1e8afa55962e994e2a699c710c890f40ff766a4b
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/FuncCall.php
@@ -0,0 +1,35 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node\Expr;
+
+use PhpParser\Node;
+use PhpParser\Node\Expr;
+
+class FuncCall extends Expr
+{
+    /** @var Node\Name|Expr Function name */
+    public $name;
+    /** @var Node\Arg[] Arguments */
+    public $args;
+
+    /**
+     * Constructs a function call node.
+     *
+     * @param Node\Name|Expr $name       Function name
+     * @param Node\Arg[]     $args       Arguments
+     * @param array          $attributes Additional attributes
+     */
+    public function __construct($name, array $args = [], array $attributes = []) {
+        $this->attributes = $attributes;
+        $this->name = $name;
+        $this->args = $args;
+    }
+
+    public function getSubNodeNames() : array {
+        return ['name', 'args'];
+    }
+    
+    public function getType() : string {
+        return 'Expr_FuncCall';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Include_.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Include_.php
new file mode 100644
index 0000000000000000000000000000000000000000..07ce5968e40e4ffe72d298ca9d894a7b8a9ff8f6
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Include_.php
@@ -0,0 +1,39 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node\Expr;
+
+use PhpParser\Node\Expr;
+
+class Include_ extends Expr
+{
+    const TYPE_INCLUDE      = 1;
+    const TYPE_INCLUDE_ONCE = 2;
+    const TYPE_REQUIRE      = 3;
+    const TYPE_REQUIRE_ONCE = 4;
+
+    /** @var Expr Expression */
+    public $expr;
+    /** @var int Type of include */
+    public $type;
+
+    /**
+     * Constructs an include node.
+     *
+     * @param Expr  $expr       Expression
+     * @param int   $type       Type of include
+     * @param array $attributes Additional attributes
+     */
+    public function __construct(Expr $expr, int $type, array $attributes = []) {
+        $this->attributes = $attributes;
+        $this->expr = $expr;
+        $this->type = $type;
+    }
+
+    public function getSubNodeNames() : array {
+        return ['expr', 'type'];
+    }
+    
+    public function getType() : string {
+        return 'Expr_Include';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Instanceof_.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Instanceof_.php
new file mode 100644
index 0000000000000000000000000000000000000000..9000d47bb1b0e36ff70a064c9e934a688bb58ce3
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Instanceof_.php
@@ -0,0 +1,35 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node\Expr;
+
+use PhpParser\Node\Expr;
+use PhpParser\Node\Name;
+
+class Instanceof_ extends Expr
+{
+    /** @var Expr Expression */
+    public $expr;
+    /** @var Name|Expr Class name */
+    public $class;
+
+    /**
+     * Constructs an instanceof check node.
+     *
+     * @param Expr      $expr       Expression
+     * @param Name|Expr $class      Class name
+     * @param array     $attributes Additional attributes
+     */
+    public function __construct(Expr $expr, $class, array $attributes = []) {
+        $this->attributes = $attributes;
+        $this->expr = $expr;
+        $this->class = $class;
+    }
+
+    public function getSubNodeNames() : array {
+        return ['expr', 'class'];
+    }
+    
+    public function getType() : string {
+        return 'Expr_Instanceof';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Isset_.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Isset_.php
new file mode 100644
index 0000000000000000000000000000000000000000..76b7387587b87e78e12f671f21db82eb1b169a70
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Isset_.php
@@ -0,0 +1,30 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node\Expr;
+
+use PhpParser\Node\Expr;
+
+class Isset_ extends Expr
+{
+    /** @var Expr[] Variables */
+    public $vars;
+
+    /**
+     * Constructs an array node.
+     *
+     * @param Expr[] $vars       Variables
+     * @param array  $attributes Additional attributes
+     */
+    public function __construct(array $vars, array $attributes = []) {
+        $this->attributes = $attributes;
+        $this->vars = $vars;
+    }
+
+    public function getSubNodeNames() : array {
+        return ['vars'];
+    }
+    
+    public function getType() : string {
+        return 'Expr_Isset';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/List_.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/List_.php
new file mode 100644
index 0000000000000000000000000000000000000000..c27a27b95738d2ccb8cb06684a358253391d38be
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/List_.php
@@ -0,0 +1,30 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node\Expr;
+
+use PhpParser\Node\Expr;
+
+class List_ extends Expr
+{
+    /** @var (ArrayItem|null)[] List of items to assign to */
+    public $items;
+
+    /**
+     * Constructs a list() destructuring node.
+     *
+     * @param (ArrayItem|null)[] $items      List of items to assign to
+     * @param array              $attributes Additional attributes
+     */
+    public function __construct(array $items, array $attributes = []) {
+        $this->attributes = $attributes;
+        $this->items = $items;
+    }
+
+    public function getSubNodeNames() : array {
+        return ['items'];
+    }
+    
+    public function getType() : string {
+        return 'Expr_List';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Match_.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Match_.php
new file mode 100644
index 0000000000000000000000000000000000000000..2455a3026410372bcbd1d987f3a81a000d1578a9
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Match_.php
@@ -0,0 +1,31 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node\Expr;
+
+use PhpParser\Node;
+use PhpParser\Node\MatchArm;
+
+class Match_ extends Node\Expr
+{
+    /** @var Node\Expr */
+    public $cond;
+    /** @var MatchArm[] */
+    public $arms;
+
+    /**
+     * @param MatchArm[] $arms
+     */
+    public function __construct(Node\Expr $cond, array $arms = [], array $attributes = []) {
+        $this->attributes = $attributes;
+        $this->cond = $cond;
+        $this->arms = $arms;
+    }
+
+    public function getSubNodeNames() : array {
+        return ['cond', 'arms'];
+    }
+
+    public function getType() : string {
+        return 'Expr_Match';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/MethodCall.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/MethodCall.php
new file mode 100644
index 0000000000000000000000000000000000000000..bd81bb43f6d7ec53cb2d15ff11da0f5361548c5c
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/MethodCall.php
@@ -0,0 +1,40 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node\Expr;
+
+use PhpParser\Node\Arg;
+use PhpParser\Node\Expr;
+use PhpParser\Node\Identifier;
+
+class MethodCall extends Expr
+{
+    /** @var Expr Variable holding object */
+    public $var;
+    /** @var Identifier|Expr Method name */
+    public $name;
+    /** @var Arg[] Arguments */
+    public $args;
+
+    /**
+     * Constructs a function call node.
+     *
+     * @param Expr                   $var        Variable holding object
+     * @param string|Identifier|Expr $name       Method name
+     * @param Arg[]                  $args       Arguments
+     * @param array                  $attributes Additional attributes
+     */
+    public function __construct(Expr $var, $name, array $args = [], array $attributes = []) {
+        $this->attributes = $attributes;
+        $this->var = $var;
+        $this->name = \is_string($name) ? new Identifier($name) : $name;
+        $this->args = $args;
+    }
+
+    public function getSubNodeNames() : array {
+        return ['var', 'name', 'args'];
+    }
+    
+    public function getType() : string {
+        return 'Expr_MethodCall';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/New_.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/New_.php
new file mode 100644
index 0000000000000000000000000000000000000000..c86f0c60158171ad14dfa62d396efdfad78c8d77
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/New_.php
@@ -0,0 +1,35 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node\Expr;
+
+use PhpParser\Node;
+use PhpParser\Node\Expr;
+
+class New_ extends Expr
+{
+    /** @var Node\Name|Expr|Node\Stmt\Class_ Class name */
+    public $class;
+    /** @var Node\Arg[] Arguments */
+    public $args;
+
+    /**
+     * Constructs a function call node.
+     *
+     * @param Node\Name|Expr|Node\Stmt\Class_ $class      Class name (or class node for anonymous classes)
+     * @param Node\Arg[]                      $args       Arguments
+     * @param array                           $attributes Additional attributes
+     */
+    public function __construct($class, array $args = [], array $attributes = []) {
+        $this->attributes = $attributes;
+        $this->class = $class;
+        $this->args = $args;
+    }
+
+    public function getSubNodeNames() : array {
+        return ['class', 'args'];
+    }
+    
+    public function getType() : string {
+        return 'Expr_New';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/NullsafeMethodCall.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/NullsafeMethodCall.php
new file mode 100644
index 0000000000000000000000000000000000000000..361e44622758cde938c9ce6d81c719077fac9d29
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/NullsafeMethodCall.php
@@ -0,0 +1,40 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node\Expr;
+
+use PhpParser\Node\Arg;
+use PhpParser\Node\Expr;
+use PhpParser\Node\Identifier;
+
+class NullsafeMethodCall extends Expr
+{
+    /** @var Expr Variable holding object */
+    public $var;
+    /** @var Identifier|Expr Method name */
+    public $name;
+    /** @var Arg[] Arguments */
+    public $args;
+
+    /**
+     * Constructs a nullsafe method call node.
+     *
+     * @param Expr                   $var        Variable holding object
+     * @param string|Identifier|Expr $name       Method name
+     * @param Arg[]                  $args       Arguments
+     * @param array                  $attributes Additional attributes
+     */
+    public function __construct(Expr $var, $name, array $args = [], array $attributes = []) {
+        $this->attributes = $attributes;
+        $this->var = $var;
+        $this->name = \is_string($name) ? new Identifier($name) : $name;
+        $this->args = $args;
+    }
+
+    public function getSubNodeNames() : array {
+        return ['var', 'name', 'args'];
+    }
+    
+    public function getType() : string {
+        return 'Expr_NullsafeMethodCall';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/NullsafePropertyFetch.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/NullsafePropertyFetch.php
new file mode 100644
index 0000000000000000000000000000000000000000..9317eb3b919cce090ac431b248a41902481ecf02
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/NullsafePropertyFetch.php
@@ -0,0 +1,35 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node\Expr;
+
+use PhpParser\Node\Expr;
+use PhpParser\Node\Identifier;
+
+class NullsafePropertyFetch extends Expr
+{
+    /** @var Expr Variable holding object */
+    public $var;
+    /** @var Identifier|Expr Property name */
+    public $name;
+
+    /**
+     * Constructs a nullsafe property fetch node.
+     *
+     * @param Expr                   $var        Variable holding object
+     * @param string|Identifier|Expr $name       Property name
+     * @param array                  $attributes Additional attributes
+     */
+    public function __construct(Expr $var, $name, array $attributes = []) {
+        $this->attributes = $attributes;
+        $this->var = $var;
+        $this->name = \is_string($name) ? new Identifier($name) : $name;
+    }
+
+    public function getSubNodeNames() : array {
+        return ['var', 'name'];
+    }
+    
+    public function getType() : string {
+        return 'Expr_NullsafePropertyFetch';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/PostDec.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/PostDec.php
new file mode 100644
index 0000000000000000000000000000000000000000..94d6c296d89b18aae05fa8c5bde48ae68a2cc830
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/PostDec.php
@@ -0,0 +1,30 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node\Expr;
+
+use PhpParser\Node\Expr;
+
+class PostDec extends Expr
+{
+    /** @var Expr Variable */
+    public $var;
+
+    /**
+     * Constructs a post decrement node.
+     *
+     * @param Expr  $var        Variable
+     * @param array $attributes Additional attributes
+     */
+    public function __construct(Expr $var, array $attributes = []) {
+        $this->attributes = $attributes;
+        $this->var = $var;
+    }
+
+    public function getSubNodeNames() : array {
+        return ['var'];
+    }
+    
+    public function getType() : string {
+        return 'Expr_PostDec';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/PostInc.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/PostInc.php
new file mode 100644
index 0000000000000000000000000000000000000000..005c443a2de79e1e02681cd04abe59a4c1eb4ad6
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/PostInc.php
@@ -0,0 +1,30 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node\Expr;
+
+use PhpParser\Node\Expr;
+
+class PostInc extends Expr
+{
+    /** @var Expr Variable */
+    public $var;
+
+    /**
+     * Constructs a post increment node.
+     *
+     * @param Expr  $var        Variable
+     * @param array $attributes Additional attributes
+     */
+    public function __construct(Expr $var, array $attributes = []) {
+        $this->attributes = $attributes;
+        $this->var = $var;
+    }
+
+    public function getSubNodeNames() : array {
+        return ['var'];
+    }
+    
+    public function getType() : string {
+        return 'Expr_PostInc';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/PreDec.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/PreDec.php
new file mode 100644
index 0000000000000000000000000000000000000000..a5ca685a8a6524f2910844454ef8828fd37de8fd
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/PreDec.php
@@ -0,0 +1,30 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node\Expr;
+
+use PhpParser\Node\Expr;
+
+class PreDec extends Expr
+{
+    /** @var Expr Variable */
+    public $var;
+
+    /**
+     * Constructs a pre decrement node.
+     *
+     * @param Expr  $var        Variable
+     * @param array $attributes Additional attributes
+     */
+    public function __construct(Expr $var, array $attributes = []) {
+        $this->attributes = $attributes;
+        $this->var = $var;
+    }
+
+    public function getSubNodeNames() : array {
+        return ['var'];
+    }
+
+    public function getType() : string {
+        return 'Expr_PreDec';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/PreInc.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/PreInc.php
new file mode 100644
index 0000000000000000000000000000000000000000..0986c447483fd3b63831ec030963d6e395d6d365
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/PreInc.php
@@ -0,0 +1,30 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node\Expr;
+
+use PhpParser\Node\Expr;
+
+class PreInc extends Expr
+{
+    /** @var Expr Variable */
+    public $var;
+
+    /**
+     * Constructs a pre increment node.
+     *
+     * @param Expr  $var        Variable
+     * @param array $attributes Additional attributes
+     */
+    public function __construct(Expr $var, array $attributes = []) {
+        $this->attributes = $attributes;
+        $this->var = $var;
+    }
+
+    public function getSubNodeNames() : array {
+        return ['var'];
+    }
+    
+    public function getType() : string {
+        return 'Expr_PreInc';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Print_.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Print_.php
new file mode 100644
index 0000000000000000000000000000000000000000..2d43c2ac82a3d8f58d79c1650756a9d057ca9188
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Print_.php
@@ -0,0 +1,30 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node\Expr;
+
+use PhpParser\Node\Expr;
+
+class Print_ extends Expr
+{
+    /** @var Expr Expression */
+    public $expr;
+
+    /**
+     * Constructs an print() node.
+     *
+     * @param Expr  $expr       Expression
+     * @param array $attributes Additional attributes
+     */
+    public function __construct(Expr $expr, array $attributes = []) {
+        $this->attributes = $attributes;
+        $this->expr = $expr;
+    }
+
+    public function getSubNodeNames() : array {
+        return ['expr'];
+    }
+    
+    public function getType() : string {
+        return 'Expr_Print';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/PropertyFetch.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/PropertyFetch.php
new file mode 100644
index 0000000000000000000000000000000000000000..4281f31ccf5c1c348e16e2ff05959015c7940f32
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/PropertyFetch.php
@@ -0,0 +1,35 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node\Expr;
+
+use PhpParser\Node\Expr;
+use PhpParser\Node\Identifier;
+
+class PropertyFetch extends Expr
+{
+    /** @var Expr Variable holding object */
+    public $var;
+    /** @var Identifier|Expr Property name */
+    public $name;
+
+    /**
+     * Constructs a function call node.
+     *
+     * @param Expr                   $var        Variable holding object
+     * @param string|Identifier|Expr $name       Property name
+     * @param array                  $attributes Additional attributes
+     */
+    public function __construct(Expr $var, $name, array $attributes = []) {
+        $this->attributes = $attributes;
+        $this->var = $var;
+        $this->name = \is_string($name) ? new Identifier($name) : $name;
+    }
+
+    public function getSubNodeNames() : array {
+        return ['var', 'name'];
+    }
+    
+    public function getType() : string {
+        return 'Expr_PropertyFetch';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/ShellExec.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/ShellExec.php
new file mode 100644
index 0000000000000000000000000000000000000000..537a7cc80926622020e359f381da5a8190470795
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/ShellExec.php
@@ -0,0 +1,30 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node\Expr;
+
+use PhpParser\Node\Expr;
+
+class ShellExec extends Expr
+{
+    /** @var array Encapsed string array */
+    public $parts;
+
+    /**
+     * Constructs a shell exec (backtick) node.
+     *
+     * @param array $parts      Encapsed string array
+     * @param array $attributes Additional attributes
+     */
+    public function __construct(array $parts, array $attributes = []) {
+        $this->attributes = $attributes;
+        $this->parts = $parts;
+    }
+
+    public function getSubNodeNames() : array {
+        return ['parts'];
+    }
+    
+    public function getType() : string {
+        return 'Expr_ShellExec';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/StaticCall.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/StaticCall.php
new file mode 100644
index 0000000000000000000000000000000000000000..9883f5af515aa93a27c9feef6502ac1f47848210
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/StaticCall.php
@@ -0,0 +1,40 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node\Expr;
+
+use PhpParser\Node;
+use PhpParser\Node\Expr;
+use PhpParser\Node\Identifier;
+
+class StaticCall extends Expr
+{
+    /** @var Node\Name|Expr Class name */
+    public $class;
+    /** @var Identifier|Expr Method name */
+    public $name;
+    /** @var Node\Arg[] Arguments */
+    public $args;
+
+    /**
+     * Constructs a static method call node.
+     *
+     * @param Node\Name|Expr         $class      Class name
+     * @param string|Identifier|Expr $name       Method name
+     * @param Node\Arg[]             $args       Arguments
+     * @param array                  $attributes Additional attributes
+     */
+    public function __construct($class, $name, array $args = [], array $attributes = []) {
+        $this->attributes = $attributes;
+        $this->class = $class;
+        $this->name = \is_string($name) ? new Identifier($name) : $name;
+        $this->args = $args;
+    }
+
+    public function getSubNodeNames() : array {
+        return ['class', 'name', 'args'];
+    }
+    
+    public function getType() : string {
+        return 'Expr_StaticCall';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/StaticPropertyFetch.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/StaticPropertyFetch.php
new file mode 100644
index 0000000000000000000000000000000000000000..1ee1a25e50d66d1f44bd3f1b4ddc201a2020044b
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/StaticPropertyFetch.php
@@ -0,0 +1,36 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node\Expr;
+
+use PhpParser\Node\Expr;
+use PhpParser\Node\Name;
+use PhpParser\Node\VarLikeIdentifier;
+
+class StaticPropertyFetch extends Expr
+{
+    /** @var Name|Expr Class name */
+    public $class;
+    /** @var VarLikeIdentifier|Expr Property name */
+    public $name;
+
+    /**
+     * Constructs a static property fetch node.
+     *
+     * @param Name|Expr                     $class      Class name
+     * @param string|VarLikeIdentifier|Expr $name       Property name
+     * @param array                         $attributes Additional attributes
+     */
+    public function __construct($class, $name, array $attributes = []) {
+        $this->attributes = $attributes;
+        $this->class = $class;
+        $this->name = \is_string($name) ? new VarLikeIdentifier($name) : $name;
+    }
+
+    public function getSubNodeNames() : array {
+        return ['class', 'name'];
+    }
+    
+    public function getType() : string {
+        return 'Expr_StaticPropertyFetch';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Ternary.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Ternary.php
new file mode 100644
index 0000000000000000000000000000000000000000..9316f47d4dc7e5782abac0092922546750792660
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Ternary.php
@@ -0,0 +1,38 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node\Expr;
+
+use PhpParser\Node\Expr;
+
+class Ternary extends Expr
+{
+    /** @var Expr Condition */
+    public $cond;
+    /** @var null|Expr Expression for true */
+    public $if;
+    /** @var Expr Expression for false */
+    public $else;
+
+    /**
+     * Constructs a ternary operator node.
+     *
+     * @param Expr      $cond       Condition
+     * @param null|Expr $if         Expression for true
+     * @param Expr      $else       Expression for false
+     * @param array                    $attributes Additional attributes
+     */
+    public function __construct(Expr $cond, $if, Expr $else, array $attributes = []) {
+        $this->attributes = $attributes;
+        $this->cond = $cond;
+        $this->if = $if;
+        $this->else = $else;
+    }
+
+    public function getSubNodeNames() : array {
+        return ['cond', 'if', 'else'];
+    }
+    
+    public function getType() : string {
+        return 'Expr_Ternary';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Throw_.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Throw_.php
new file mode 100644
index 0000000000000000000000000000000000000000..5c97f0e2b4d199bd83ce969fa7e92d0f18a43f09
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Throw_.php
@@ -0,0 +1,30 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node\Expr;
+
+use PhpParser\Node;
+
+class Throw_ extends Node\Expr
+{
+    /** @var Node\Expr Expression */
+    public $expr;
+
+    /**
+     * Constructs a throw expression node.
+     *
+     * @param Node\Expr $expr       Expression
+     * @param array     $attributes Additional attributes
+     */
+    public function __construct(Node\Expr $expr, array $attributes = []) {
+        $this->attributes = $attributes;
+        $this->expr = $expr;
+    }
+
+    public function getSubNodeNames() : array {
+        return ['expr'];
+    }
+
+    public function getType() : string {
+        return 'Expr_Throw';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/UnaryMinus.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/UnaryMinus.php
new file mode 100644
index 0000000000000000000000000000000000000000..ce8808bc6489791b8ba730527316a49618f437f3
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/UnaryMinus.php
@@ -0,0 +1,30 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node\Expr;
+
+use PhpParser\Node\Expr;
+
+class UnaryMinus extends Expr
+{
+    /** @var Expr Expression */
+    public $expr;
+
+    /**
+     * Constructs a unary minus node.
+     *
+     * @param Expr  $expr       Expression
+     * @param array $attributes Additional attributes
+     */
+    public function __construct(Expr $expr, array $attributes = []) {
+        $this->attributes = $attributes;
+        $this->expr = $expr;
+    }
+
+    public function getSubNodeNames() : array {
+        return ['expr'];
+    }
+    
+    public function getType() : string {
+        return 'Expr_UnaryMinus';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/UnaryPlus.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/UnaryPlus.php
new file mode 100644
index 0000000000000000000000000000000000000000..d23047e54efcd117dbebca52255a08cbf57169cf
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/UnaryPlus.php
@@ -0,0 +1,30 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node\Expr;
+
+use PhpParser\Node\Expr;
+
+class UnaryPlus extends Expr
+{
+    /** @var Expr Expression */
+    public $expr;
+
+    /**
+     * Constructs a unary plus node.
+     *
+     * @param Expr $expr       Expression
+     * @param array               $attributes Additional attributes
+     */
+    public function __construct(Expr $expr, array $attributes = []) {
+        $this->attributes = $attributes;
+        $this->expr = $expr;
+    }
+
+    public function getSubNodeNames() : array {
+        return ['expr'];
+    }
+    
+    public function getType() : string {
+        return 'Expr_UnaryPlus';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Variable.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Variable.php
new file mode 100644
index 0000000000000000000000000000000000000000..1f2b2314a3b636426c10bd3385d03bde769aa1fd
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Variable.php
@@ -0,0 +1,30 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node\Expr;
+
+use PhpParser\Node\Expr;
+
+class Variable extends Expr
+{
+    /** @var string|Expr Name */
+    public $name;
+
+    /**
+     * Constructs a variable node.
+     *
+     * @param string|Expr $name       Name
+     * @param array                      $attributes Additional attributes
+     */
+    public function __construct($name, array $attributes = []) {
+        $this->attributes = $attributes;
+        $this->name = $name;
+    }
+
+    public function getSubNodeNames() : array {
+        return ['name'];
+    }
+    
+    public function getType() : string {
+        return 'Expr_Variable';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/YieldFrom.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/YieldFrom.php
new file mode 100644
index 0000000000000000000000000000000000000000..a3efce618cd072c011d66738d52994b8ff158eed
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/YieldFrom.php
@@ -0,0 +1,30 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node\Expr;
+
+use PhpParser\Node\Expr;
+
+class YieldFrom extends Expr
+{
+    /** @var Expr Expression to yield from */
+    public $expr;
+
+    /**
+     * Constructs an "yield from" node.
+     *
+     * @param Expr  $expr       Expression
+     * @param array $attributes Additional attributes
+     */
+    public function __construct(Expr $expr, array $attributes = []) {
+        $this->attributes = $attributes;
+        $this->expr = $expr;
+    }
+
+    public function getSubNodeNames() : array {
+        return ['expr'];
+    }
+    
+    public function getType() : string {
+        return 'Expr_YieldFrom';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Yield_.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Yield_.php
new file mode 100644
index 0000000000000000000000000000000000000000..aef8fc333dd8ed37b10a7afa2374d863d124cd52
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Yield_.php
@@ -0,0 +1,34 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node\Expr;
+
+use PhpParser\Node\Expr;
+
+class Yield_ extends Expr
+{
+    /** @var null|Expr Key expression */
+    public $key;
+    /** @var null|Expr Value expression */
+    public $value;
+
+    /**
+     * Constructs a yield expression node.
+     *
+     * @param null|Expr $value      Value expression
+     * @param null|Expr $key        Key expression
+     * @param array     $attributes Additional attributes
+     */
+    public function __construct(Expr $value = null, Expr $key = null, array $attributes = []) {
+        $this->attributes = $attributes;
+        $this->key = $key;
+        $this->value = $value;
+    }
+
+    public function getSubNodeNames() : array {
+        return ['key', 'value'];
+    }
+    
+    public function getType() : string {
+        return 'Expr_Yield';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/FunctionLike.php b/vendor/nikic/php-parser/lib/PhpParser/Node/FunctionLike.php
new file mode 100644
index 0000000000000000000000000000000000000000..bbcf53e55fb71b371e02ea3f1da676f95c963780
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/FunctionLike.php
@@ -0,0 +1,43 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node;
+
+use PhpParser\Node;
+
+interface FunctionLike extends Node
+{
+    /**
+     * Whether to return by reference
+     *
+     * @return bool
+     */
+    public function returnsByRef() : bool;
+
+    /**
+     * List of parameters
+     *
+     * @return Param[]
+     */
+    public function getParams() : array;
+
+    /**
+     * Get the declared return type or null
+     *
+     * @return null|Identifier|Name|NullableType|UnionType
+     */
+    public function getReturnType();
+
+    /**
+     * The function body
+     *
+     * @return Stmt[]|null
+     */
+    public function getStmts();
+
+    /**
+     * Get PHP attribute groups.
+     *
+     * @return AttributeGroup[]
+     */
+    public function getAttrGroups() : array;
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Identifier.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Identifier.php
new file mode 100644
index 0000000000000000000000000000000000000000..2f262db0aa569e93f00f81122bf4ade1f18c212c
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Identifier.php
@@ -0,0 +1,75 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node;
+
+use PhpParser\NodeAbstract;
+
+/**
+ * Represents a non-namespaced name. Namespaced names are represented using Name nodes.
+ */
+class Identifier extends NodeAbstract
+{
+    /** @var string Identifier as string */
+    public $name;
+
+    private static $specialClassNames = [
+        'self'   => true,
+        'parent' => true,
+        'static' => true,
+    ];
+
+    /**
+     * Constructs an identifier node.
+     *
+     * @param string $name       Identifier as string
+     * @param array  $attributes Additional attributes
+     */
+    public function __construct(string $name, array $attributes = []) {
+        $this->attributes = $attributes;
+        $this->name = $name;
+    }
+
+    public function getSubNodeNames() : array {
+        return ['name'];
+    }
+
+    /**
+     * Get identifier as string.
+     *
+     * @return string Identifier as string.
+     */
+    public function toString() : string {
+        return $this->name;
+    }
+
+    /**
+     * Get lowercased identifier as string.
+     *
+     * @return string Lowercased identifier as string
+     */
+    public function toLowerString() : string {
+        return strtolower($this->name);
+    }
+
+    /**
+     * Checks whether the identifier is a special class name (self, parent or static).
+     *
+     * @return bool Whether identifier is a special class name
+     */
+    public function isSpecialClassName() : bool {
+        return isset(self::$specialClassNames[strtolower($this->name)]);
+    }
+
+    /**
+     * Get identifier as string.
+     *
+     * @return string Identifier as string
+     */
+    public function __toString() : string {
+        return $this->name;
+    }
+    
+    public function getType() : string {
+        return 'Identifier';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/MatchArm.php b/vendor/nikic/php-parser/lib/PhpParser/Node/MatchArm.php
new file mode 100644
index 0000000000000000000000000000000000000000..2ae1c86b8555302270f4dd8f3411e8c179531b06
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/MatchArm.php
@@ -0,0 +1,31 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node;
+
+use PhpParser\Node;
+use PhpParser\NodeAbstract;
+
+class MatchArm extends NodeAbstract
+{
+    /** @var null|Node\Expr[] */
+    public $conds;
+    /** @var Node\Expr */
+    public $body;
+
+    /**
+     * @param null|Node\Expr[] $conds
+     */
+    public function __construct($conds, Node\Expr $body, array $attributes = []) {
+        $this->conds = $conds;
+        $this->body = $body;
+        $this->attributes = $attributes;
+    }
+
+    public function getSubNodeNames() : array {
+        return ['conds', 'body'];
+    }
+
+    public function getType() : string {
+        return 'MatchArm';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Name.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Name.php
new file mode 100644
index 0000000000000000000000000000000000000000..6b1cc9f8ed2e6ff11cfc4eff04aadbe50e0e67d2
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Name.php
@@ -0,0 +1,242 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node;
+
+use PhpParser\NodeAbstract;
+
+class Name extends NodeAbstract
+{
+    /** @var string[] Parts of the name */
+    public $parts;
+
+    private static $specialClassNames = [
+        'self'   => true,
+        'parent' => true,
+        'static' => true,
+    ];
+
+    /**
+     * Constructs a name node.
+     *
+     * @param string|string[]|self $name       Name as string, part array or Name instance (copy ctor)
+     * @param array                $attributes Additional attributes
+     */
+    public function __construct($name, array $attributes = []) {
+        $this->attributes = $attributes;
+        $this->parts = self::prepareName($name);
+    }
+
+    public function getSubNodeNames() : array {
+        return ['parts'];
+    }
+
+    /**
+     * Gets the first part of the name, i.e. everything before the first namespace separator.
+     *
+     * @return string First part of the name
+     */
+    public function getFirst() : string {
+        return $this->parts[0];
+    }
+
+    /**
+     * Gets the last part of the name, i.e. everything after the last namespace separator.
+     *
+     * @return string Last part of the name
+     */
+    public function getLast() : string {
+        return $this->parts[count($this->parts) - 1];
+    }
+
+    /**
+     * Checks whether the name is unqualified. (E.g. Name)
+     *
+     * @return bool Whether the name is unqualified
+     */
+    public function isUnqualified() : bool {
+        return 1 === count($this->parts);
+    }
+
+    /**
+     * Checks whether the name is qualified. (E.g. Name\Name)
+     *
+     * @return bool Whether the name is qualified
+     */
+    public function isQualified() : bool {
+        return 1 < count($this->parts);
+    }
+
+    /**
+     * Checks whether the name is fully qualified. (E.g. \Name)
+     *
+     * @return bool Whether the name is fully qualified
+     */
+    public function isFullyQualified() : bool {
+        return false;
+    }
+
+    /**
+     * Checks whether the name is explicitly relative to the current namespace. (E.g. namespace\Name)
+     *
+     * @return bool Whether the name is relative
+     */
+    public function isRelative() : bool {
+        return false;
+    }
+
+    /**
+     * Returns a string representation of the name itself, without taking the name type into
+     * account (e.g., not including a leading backslash for fully qualified names).
+     *
+     * @return string String representation
+     */
+    public function toString() : string {
+        return implode('\\', $this->parts);
+    }
+
+    /**
+     * Returns a string representation of the name as it would occur in code (e.g., including
+     * leading backslash for fully qualified names.
+     *
+     * @return string String representation
+     */
+    public function toCodeString() : string {
+        return $this->toString();
+    }
+
+    /**
+     * Returns lowercased string representation of the name, without taking the name type into
+     * account (e.g., no leading backslash for fully qualified names).
+     *
+     * @return string Lowercased string representation
+     */
+    public function toLowerString() : string {
+        return strtolower(implode('\\', $this->parts));
+    }
+
+    /**
+     * Checks whether the identifier is a special class name (self, parent or static).
+     *
+     * @return bool Whether identifier is a special class name
+     */
+    public function isSpecialClassName() : bool {
+        return count($this->parts) === 1
+            && isset(self::$specialClassNames[strtolower($this->parts[0])]);
+    }
+
+    /**
+     * Returns a string representation of the name by imploding the namespace parts with the
+     * namespace separator.
+     *
+     * @return string String representation
+     */
+    public function __toString() : string {
+        return implode('\\', $this->parts);
+    }
+
+    /**
+     * Gets a slice of a name (similar to array_slice).
+     *
+     * This method returns a new instance of the same type as the original and with the same
+     * attributes.
+     *
+     * If the slice is empty, null is returned. The null value will be correctly handled in
+     * concatenations using concat().
+     *
+     * Offset and length have the same meaning as in array_slice().
+     *
+     * @param int      $offset Offset to start the slice at (may be negative)
+     * @param int|null $length Length of the slice (may be negative)
+     *
+     * @return static|null Sliced name
+     */
+    public function slice(int $offset, int $length = null) {
+        $numParts = count($this->parts);
+
+        $realOffset = $offset < 0 ? $offset + $numParts : $offset;
+        if ($realOffset < 0 || $realOffset > $numParts) {
+            throw new \OutOfBoundsException(sprintf('Offset %d is out of bounds', $offset));
+        }
+
+        if (null === $length) {
+            $realLength = $numParts - $realOffset;
+        } else {
+            $realLength = $length < 0 ? $length + $numParts - $realOffset : $length;
+            if ($realLength < 0 || $realLength > $numParts) {
+                throw new \OutOfBoundsException(sprintf('Length %d is out of bounds', $length));
+            }
+        }
+
+        if ($realLength === 0) {
+            // Empty slice is represented as null
+            return null;
+        }
+
+        return new static(array_slice($this->parts, $realOffset, $realLength), $this->attributes);
+    }
+
+    /**
+     * Concatenate two names, yielding a new Name instance.
+     *
+     * The type of the generated instance depends on which class this method is called on, for
+     * example Name\FullyQualified::concat() will yield a Name\FullyQualified instance.
+     *
+     * If one of the arguments is null, a new instance of the other name will be returned. If both
+     * arguments are null, null will be returned. As such, writing
+     *     Name::concat($namespace, $shortName)
+     * where $namespace is a Name node or null will work as expected.
+     *
+     * @param string|string[]|self|null $name1      The first name
+     * @param string|string[]|self|null $name2      The second name
+     * @param array                     $attributes Attributes to assign to concatenated name
+     *
+     * @return static|null Concatenated name
+     */
+    public static function concat($name1, $name2, array $attributes = []) {
+        if (null === $name1 && null === $name2) {
+            return null;
+        } elseif (null === $name1) {
+            return new static(self::prepareName($name2), $attributes);
+        } elseif (null === $name2) {
+            return new static(self::prepareName($name1), $attributes);
+        } else {
+            return new static(
+                array_merge(self::prepareName($name1), self::prepareName($name2)), $attributes
+            );
+        }
+    }
+
+    /**
+     * Prepares a (string, array or Name node) name for use in name changing methods by converting
+     * it to an array.
+     *
+     * @param string|string[]|self $name Name to prepare
+     *
+     * @return string[] Prepared name
+     */
+    private static function prepareName($name) : array {
+        if (\is_string($name)) {
+            if ('' === $name) {
+                throw new \InvalidArgumentException('Name cannot be empty');
+            }
+
+            return explode('\\', $name);
+        } elseif (\is_array($name)) {
+            if (empty($name)) {
+                throw new \InvalidArgumentException('Name cannot be empty');
+            }
+
+            return $name;
+        } elseif ($name instanceof self) {
+            return $name->parts;
+        }
+
+        throw new \InvalidArgumentException(
+            'Expected string, array of parts or Name instance'
+        );
+    }
+
+    public function getType() : string {
+        return 'Name';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Name/FullyQualified.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Name/FullyQualified.php
new file mode 100644
index 0000000000000000000000000000000000000000..1df93a56b60cdc127135c58f5e1c0269cdfa07f0
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Name/FullyQualified.php
@@ -0,0 +1,50 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node\Name;
+
+class FullyQualified extends \PhpParser\Node\Name
+{
+    /**
+     * Checks whether the name is unqualified. (E.g. Name)
+     *
+     * @return bool Whether the name is unqualified
+     */
+    public function isUnqualified() : bool {
+        return false;
+    }
+
+    /**
+     * Checks whether the name is qualified. (E.g. Name\Name)
+     *
+     * @return bool Whether the name is qualified
+     */
+    public function isQualified() : bool {
+        return false;
+    }
+
+    /**
+     * Checks whether the name is fully qualified. (E.g. \Name)
+     *
+     * @return bool Whether the name is fully qualified
+     */
+    public function isFullyQualified() : bool {
+        return true;
+    }
+
+    /**
+     * Checks whether the name is explicitly relative to the current namespace. (E.g. namespace\Name)
+     *
+     * @return bool Whether the name is relative
+     */
+    public function isRelative() : bool {
+        return false;
+    }
+
+    public function toCodeString() : string {
+        return '\\' . $this->toString();
+    }
+    
+    public function getType() : string {
+        return 'Name_FullyQualified';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Name/Relative.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Name/Relative.php
new file mode 100644
index 0000000000000000000000000000000000000000..57bf7af2b2671c794fd8346d77fc5c3d5cb27e04
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Name/Relative.php
@@ -0,0 +1,50 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node\Name;
+
+class Relative extends \PhpParser\Node\Name
+{
+    /**
+     * Checks whether the name is unqualified. (E.g. Name)
+     *
+     * @return bool Whether the name is unqualified
+     */
+    public function isUnqualified() : bool {
+        return false;
+    }
+
+    /**
+     * Checks whether the name is qualified. (E.g. Name\Name)
+     *
+     * @return bool Whether the name is qualified
+     */
+    public function isQualified() : bool {
+        return false;
+    }
+
+    /**
+     * Checks whether the name is fully qualified. (E.g. \Name)
+     *
+     * @return bool Whether the name is fully qualified
+     */
+    public function isFullyQualified() : bool {
+        return false;
+    }
+
+    /**
+     * Checks whether the name is explicitly relative to the current namespace. (E.g. namespace\Name)
+     *
+     * @return bool Whether the name is relative
+     */
+    public function isRelative() : bool {
+        return true;
+    }
+
+    public function toCodeString() : string {
+        return 'namespace\\' . $this->toString();
+    }
+    
+    public function getType() : string {
+        return 'Name_Relative';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/NullableType.php b/vendor/nikic/php-parser/lib/PhpParser/Node/NullableType.php
new file mode 100644
index 0000000000000000000000000000000000000000..36463657e98905df5cc4e4b30db53428b0886c90
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/NullableType.php
@@ -0,0 +1,30 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node;
+
+use PhpParser\NodeAbstract;
+
+class NullableType extends NodeAbstract
+{
+    /** @var Identifier|Name Type */
+    public $type;
+
+    /**
+     * Constructs a nullable type (wrapping another type).
+     *
+     * @param string|Identifier|Name $type       Type
+     * @param array                  $attributes Additional attributes
+     */
+    public function __construct($type, array $attributes = []) {
+        $this->attributes = $attributes;
+        $this->type = \is_string($type) ? new Identifier($type) : $type;
+    }
+
+    public function getSubNodeNames() : array {
+        return ['type'];
+    }
+    
+    public function getType() : string {
+        return 'NullableType';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Param.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Param.php
new file mode 100644
index 0000000000000000000000000000000000000000..315b5f24f64750353b1d8040eedc7b5a02b215e7
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Param.php
@@ -0,0 +1,60 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node;
+
+use PhpParser\NodeAbstract;
+
+class Param extends NodeAbstract
+{
+    /** @var null|Identifier|Name|NullableType|UnionType Type declaration */
+    public $type;
+    /** @var bool Whether parameter is passed by reference */
+    public $byRef;
+    /** @var bool Whether this is a variadic argument */
+    public $variadic;
+    /** @var Expr\Variable|Expr\Error Parameter variable */
+    public $var;
+    /** @var null|Expr Default value */
+    public $default;
+    /** @var int */
+    public $flags;
+    /** @var AttributeGroup[] PHP attribute groups */
+    public $attrGroups;
+
+    /**
+     * Constructs a parameter node.
+     *
+     * @param Expr\Variable|Expr\Error                           $var        Parameter variable
+     * @param null|Expr                                          $default    Default value
+     * @param null|string|Identifier|Name|NullableType|UnionType $type       Type declaration
+     * @param bool                                               $byRef      Whether is passed by reference
+     * @param bool                                               $variadic   Whether this is a variadic argument
+     * @param array                                              $attributes Additional attributes
+     * @param int                                                $flags      Optional visibility flags
+     * @param AttributeGroup[]                                   $attrGroups PHP attribute groups
+     */
+    public function __construct(
+        $var, Expr $default = null, $type = null,
+        bool $byRef = false, bool $variadic = false,
+        array $attributes = [],
+        int $flags = 0,
+        array $attrGroups = []
+    ) {
+        $this->attributes = $attributes;
+        $this->type = \is_string($type) ? new Identifier($type) : $type;
+        $this->byRef = $byRef;
+        $this->variadic = $variadic;
+        $this->var = $var;
+        $this->default = $default;
+        $this->flags = $flags;
+        $this->attrGroups = $attrGroups;
+    }
+
+    public function getSubNodeNames() : array {
+        return ['attrGroups', 'flags', 'type', 'byRef', 'variadic', 'var', 'default'];
+    }
+
+    public function getType() : string {
+        return 'Param';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Scalar.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Scalar.php
new file mode 100644
index 0000000000000000000000000000000000000000..8117909b65a48524f639c04b574f615a94bd8e90
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Scalar.php
@@ -0,0 +1,7 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node;
+
+abstract class Scalar extends Expr
+{
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Scalar/DNumber.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Scalar/DNumber.php
new file mode 100644
index 0000000000000000000000000000000000000000..29ce0dd40133cd735aa040b073a9820533b42a43
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Scalar/DNumber.php
@@ -0,0 +1,70 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node\Scalar;
+
+use PhpParser\Node\Scalar;
+
+class DNumber extends Scalar
+{
+    /** @var float Number value */
+    public $value;
+
+    /**
+     * Constructs a float number scalar node.
+     *
+     * @param float $value      Value of the number
+     * @param array $attributes Additional attributes
+     */
+    public function __construct(float $value, array $attributes = []) {
+        $this->attributes = $attributes;
+        $this->value = $value;
+    }
+
+    public function getSubNodeNames() : array {
+        return ['value'];
+    }
+
+    /**
+     * @internal
+     *
+     * Parses a DNUMBER token like PHP would.
+     *
+     * @param string $str A string number
+     *
+     * @return float The parsed number
+     */
+    public static function parse(string $str) : float {
+        $str = str_replace('_', '', $str);
+
+        // if string contains any of .eE just cast it to float
+        if (false !== strpbrk($str, '.eE')) {
+            return (float) $str;
+        }
+
+        // otherwise it's an integer notation that overflowed into a float
+        // if it starts with 0 it's one of the special integer notations
+        if ('0' === $str[0]) {
+            // hex
+            if ('x' === $str[1] || 'X' === $str[1]) {
+                return hexdec($str);
+            }
+
+            // bin
+            if ('b' === $str[1] || 'B' === $str[1]) {
+                return bindec($str);
+            }
+
+            // oct
+            // substr($str, 0, strcspn($str, '89')) cuts the string at the first invalid digit (8 or 9)
+            // so that only the digits before that are used
+            return octdec(substr($str, 0, strcspn($str, '89')));
+        }
+
+        // dec
+        return (float) $str;
+    }
+    
+    public function getType() : string {
+        return 'Scalar_DNumber';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Scalar/Encapsed.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Scalar/Encapsed.php
new file mode 100644
index 0000000000000000000000000000000000000000..fa5d2e2681998809581b694bd746d04d9926ee68
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Scalar/Encapsed.php
@@ -0,0 +1,31 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node\Scalar;
+
+use PhpParser\Node\Expr;
+use PhpParser\Node\Scalar;
+
+class Encapsed extends Scalar
+{
+    /** @var Expr[] list of string parts */
+    public $parts;
+
+    /**
+     * Constructs an encapsed string node.
+     *
+     * @param Expr[] $parts      Encaps list
+     * @param array  $attributes Additional attributes
+     */
+    public function __construct(array $parts, array $attributes = []) {
+        $this->attributes = $attributes;
+        $this->parts = $parts;
+    }
+
+    public function getSubNodeNames() : array {
+        return ['parts'];
+    }
+    
+    public function getType() : string {
+        return 'Scalar_Encapsed';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Scalar/EncapsedStringPart.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Scalar/EncapsedStringPart.php
new file mode 100644
index 0000000000000000000000000000000000000000..bb3194c1d7cc1b8cac22f2850c34f837a16357a2
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Scalar/EncapsedStringPart.php
@@ -0,0 +1,30 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node\Scalar;
+
+use PhpParser\Node\Scalar;
+
+class EncapsedStringPart extends Scalar
+{
+    /** @var string String value */
+    public $value;
+
+    /**
+     * Constructs a node representing a string part of an encapsed string.
+     *
+     * @param string $value      String value
+     * @param array  $attributes Additional attributes
+     */
+    public function __construct(string $value, array $attributes = []) {
+        $this->attributes = $attributes;
+        $this->value = $value;
+    }
+
+    public function getSubNodeNames() : array {
+        return ['value'];
+    }
+    
+    public function getType() : string {
+        return 'Scalar_EncapsedStringPart';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Scalar/LNumber.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Scalar/LNumber.php
new file mode 100644
index 0000000000000000000000000000000000000000..b33943547e2aaad5d112070bfce2a524489b041e
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Scalar/LNumber.php
@@ -0,0 +1,73 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node\Scalar;
+
+use PhpParser\Error;
+use PhpParser\Node\Scalar;
+
+class LNumber extends Scalar
+{
+    /* For use in "kind" attribute */
+    const KIND_BIN = 2;
+    const KIND_OCT = 8;
+    const KIND_DEC = 10;
+    const KIND_HEX = 16;
+
+    /** @var int Number value */
+    public $value;
+
+    /**
+     * Constructs an integer number scalar node.
+     *
+     * @param int   $value      Value of the number
+     * @param array $attributes Additional attributes
+     */
+    public function __construct(int $value, array $attributes = []) {
+        $this->attributes = $attributes;
+        $this->value = $value;
+    }
+
+    public function getSubNodeNames() : array {
+        return ['value'];
+    }
+
+    /**
+     * Constructs an LNumber node from a string number literal.
+     *
+     * @param string $str               String number literal (decimal, octal, hex or binary)
+     * @param array  $attributes        Additional attributes
+     * @param bool   $allowInvalidOctal Whether to allow invalid octal numbers (PHP 5)
+     *
+     * @return LNumber The constructed LNumber, including kind attribute
+     */
+    public static function fromString(string $str, array $attributes = [], bool $allowInvalidOctal = false) : LNumber {
+        $str = str_replace('_', '', $str);
+
+        if ('0' !== $str[0] || '0' === $str) {
+            $attributes['kind'] = LNumber::KIND_DEC;
+            return new LNumber((int) $str, $attributes);
+        }
+
+        if ('x' === $str[1] || 'X' === $str[1]) {
+            $attributes['kind'] = LNumber::KIND_HEX;
+            return new LNumber(hexdec($str), $attributes);
+        }
+
+        if ('b' === $str[1] || 'B' === $str[1]) {
+            $attributes['kind'] = LNumber::KIND_BIN;
+            return new LNumber(bindec($str), $attributes);
+        }
+
+        if (!$allowInvalidOctal && strpbrk($str, '89')) {
+            throw new Error('Invalid numeric literal', $attributes);
+        }
+
+        // use intval instead of octdec to get proper cutting behavior with malformed numbers
+        $attributes['kind'] = LNumber::KIND_OCT;
+        return new LNumber(intval($str, 8), $attributes);
+    }
+    
+    public function getType() : string {
+        return 'Scalar_LNumber';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst.php
new file mode 100644
index 0000000000000000000000000000000000000000..941f0c762079533469e035d49fef5e8bf035d8fd
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst.php
@@ -0,0 +1,28 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node\Scalar;
+
+use PhpParser\Node\Scalar;
+
+abstract class MagicConst extends Scalar
+{
+    /**
+     * Constructs a magic constant node.
+     *
+     * @param array $attributes Additional attributes
+     */
+    public function __construct(array $attributes = []) {
+        $this->attributes = $attributes;
+    }
+
+    public function getSubNodeNames() : array {
+        return [];
+    }
+
+    /**
+     * Get name of magic constant.
+     *
+     * @return string Name of magic constant
+     */
+    abstract public function getName() : string;
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Class_.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Class_.php
new file mode 100644
index 0000000000000000000000000000000000000000..244328476d6bac95a148ab5d888ad7396895671f
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Class_.php
@@ -0,0 +1,16 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node\Scalar\MagicConst;
+
+use PhpParser\Node\Scalar\MagicConst;
+
+class Class_ extends MagicConst
+{
+    public function getName() : string {
+        return '__CLASS__';
+    }
+    
+    public function getType() : string {
+        return 'Scalar_MagicConst_Class';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Dir.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Dir.php
new file mode 100644
index 0000000000000000000000000000000000000000..2b618473e3829a6fd643fcea13ef8d62bc5f18e4
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Dir.php
@@ -0,0 +1,16 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node\Scalar\MagicConst;
+
+use PhpParser\Node\Scalar\MagicConst;
+
+class Dir extends MagicConst
+{
+    public function getName() : string {
+        return '__DIR__';
+    }
+    
+    public function getType() : string {
+        return 'Scalar_MagicConst_Dir';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/File.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/File.php
new file mode 100644
index 0000000000000000000000000000000000000000..3422db069238299b04e987b2fa846a5505e8db70
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/File.php
@@ -0,0 +1,16 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node\Scalar\MagicConst;
+
+use PhpParser\Node\Scalar\MagicConst;
+
+class File extends MagicConst
+{
+    public function getName() : string {
+        return '__FILE__';
+    }
+    
+    public function getType() : string {
+        return 'Scalar_MagicConst_File';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Function_.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Function_.php
new file mode 100644
index 0000000000000000000000000000000000000000..1db65a15130ce0273a72d32b128a56e7cdfed25f
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Function_.php
@@ -0,0 +1,16 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node\Scalar\MagicConst;
+
+use PhpParser\Node\Scalar\MagicConst;
+
+class Function_ extends MagicConst
+{
+    public function getName() : string {
+        return '__FUNCTION__';
+    }
+    
+    public function getType() : string {
+        return 'Scalar_MagicConst_Function';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Line.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Line.php
new file mode 100644
index 0000000000000000000000000000000000000000..25d3de57c131705b47a60c67eb930e761543648b
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Line.php
@@ -0,0 +1,16 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node\Scalar\MagicConst;
+
+use PhpParser\Node\Scalar\MagicConst;
+
+class Line extends MagicConst
+{
+    public function getName() : string {
+        return '__LINE__';
+    }
+    
+    public function getType() : string {
+        return 'Scalar_MagicConst_Line';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Method.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Method.php
new file mode 100644
index 0000000000000000000000000000000000000000..d168d56f105a979afcb5702e18f4e0fe414afe5f
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Method.php
@@ -0,0 +1,16 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node\Scalar\MagicConst;
+
+use PhpParser\Node\Scalar\MagicConst;
+
+class Method extends MagicConst
+{
+    public function getName() : string {
+        return '__METHOD__';
+    }
+    
+    public function getType() : string {
+        return 'Scalar_MagicConst_Method';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Namespace_.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Namespace_.php
new file mode 100644
index 0000000000000000000000000000000000000000..4fabb751af361c4c4828987e76337c0048c21ee7
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Namespace_.php
@@ -0,0 +1,16 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node\Scalar\MagicConst;
+
+use PhpParser\Node\Scalar\MagicConst;
+
+class Namespace_ extends MagicConst
+{
+    public function getName() : string {
+        return '__NAMESPACE__';
+    }
+    
+    public function getType() : string {
+        return 'Scalar_MagicConst_Namespace';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Trait_.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Trait_.php
new file mode 100644
index 0000000000000000000000000000000000000000..5ee7e40a3c744357dd1492510b05bed6ec3a3989
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Trait_.php
@@ -0,0 +1,16 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node\Scalar\MagicConst;
+
+use PhpParser\Node\Scalar\MagicConst;
+
+class Trait_ extends MagicConst
+{
+    public function getName() : string {
+        return '__TRAIT__';
+    }
+    
+    public function getType() : string {
+        return 'Scalar_MagicConst_Trait';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Scalar/String_.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Scalar/String_.php
new file mode 100644
index 0000000000000000000000000000000000000000..8a6d93a47415a7de82b007dcf71490c526b8b19b
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Scalar/String_.php
@@ -0,0 +1,141 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node\Scalar;
+
+use PhpParser\Error;
+use PhpParser\Node\Scalar;
+
+class String_ extends Scalar
+{
+    /* For use in "kind" attribute */
+    const KIND_SINGLE_QUOTED = 1;
+    const KIND_DOUBLE_QUOTED = 2;
+    const KIND_HEREDOC = 3;
+    const KIND_NOWDOC = 4;
+
+    /** @var string String value */
+    public $value;
+
+    protected static $replacements = [
+        '\\' => '\\',
+        '$'  =>  '$',
+        'n'  => "\n",
+        'r'  => "\r",
+        't'  => "\t",
+        'f'  => "\f",
+        'v'  => "\v",
+        'e'  => "\x1B",
+    ];
+
+    /**
+     * Constructs a string scalar node.
+     *
+     * @param string $value      Value of the string
+     * @param array  $attributes Additional attributes
+     */
+    public function __construct(string $value, array $attributes = []) {
+        $this->attributes = $attributes;
+        $this->value = $value;
+    }
+
+    public function getSubNodeNames() : array {
+        return ['value'];
+    }
+
+    /**
+     * @internal
+     *
+     * Parses a string token.
+     *
+     * @param string $str String token content
+     * @param bool $parseUnicodeEscape Whether to parse PHP 7 \u escapes
+     *
+     * @return string The parsed string
+     */
+    public static function parse(string $str, bool $parseUnicodeEscape = true) : string {
+        $bLength = 0;
+        if ('b' === $str[0] || 'B' === $str[0]) {
+            $bLength = 1;
+        }
+
+        if ('\'' === $str[$bLength]) {
+            return str_replace(
+                ['\\\\', '\\\''],
+                ['\\', '\''],
+                substr($str, $bLength + 1, -1)
+            );
+        } else {
+            return self::parseEscapeSequences(
+                substr($str, $bLength + 1, -1), '"', $parseUnicodeEscape
+            );
+        }
+    }
+
+    /**
+     * @internal
+     *
+     * Parses escape sequences in strings (all string types apart from single quoted).
+     *
+     * @param string      $str   String without quotes
+     * @param null|string $quote Quote type
+     * @param bool $parseUnicodeEscape Whether to parse PHP 7 \u escapes
+     *
+     * @return string String with escape sequences parsed
+     */
+    public static function parseEscapeSequences(string $str, $quote, bool $parseUnicodeEscape = true) : string {
+        if (null !== $quote) {
+            $str = str_replace('\\' . $quote, $quote, $str);
+        }
+
+        $extra = '';
+        if ($parseUnicodeEscape) {
+            $extra = '|u\{([0-9a-fA-F]+)\}';
+        }
+
+        return preg_replace_callback(
+            '~\\\\([\\\\$nrtfve]|[xX][0-9a-fA-F]{1,2}|[0-7]{1,3}' . $extra . ')~',
+            function($matches) {
+                $str = $matches[1];
+
+                if (isset(self::$replacements[$str])) {
+                    return self::$replacements[$str];
+                } elseif ('x' === $str[0] || 'X' === $str[0]) {
+                    return chr(hexdec(substr($str, 1)));
+                } elseif ('u' === $str[0]) {
+                    return self::codePointToUtf8(hexdec($matches[2]));
+                } else {
+                    return chr(octdec($str));
+                }
+            },
+            $str
+        );
+    }
+
+    /**
+     * Converts a Unicode code point to its UTF-8 encoded representation.
+     *
+     * @param int $num Code point
+     *
+     * @return string UTF-8 representation of code point
+     */
+    private static function codePointToUtf8(int $num) : string {
+        if ($num <= 0x7F) {
+            return chr($num);
+        }
+        if ($num <= 0x7FF) {
+            return chr(($num>>6) + 0xC0) . chr(($num&0x3F) + 0x80);
+        }
+        if ($num <= 0xFFFF) {
+            return chr(($num>>12) + 0xE0) . chr((($num>>6)&0x3F) + 0x80) . chr(($num&0x3F) + 0x80);
+        }
+        if ($num <= 0x1FFFFF) {
+            return chr(($num>>18) + 0xF0) . chr((($num>>12)&0x3F) + 0x80)
+                 . chr((($num>>6)&0x3F) + 0x80) . chr(($num&0x3F) + 0x80);
+        }
+        throw new Error('Invalid UTF-8 codepoint escape sequence: Codepoint too large');
+    }
+
+    public function getType() : string {
+        return 'Scalar_String';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt.php
new file mode 100644
index 0000000000000000000000000000000000000000..69d33e5796066e0ec235a87b6f524bcc36b406f3
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt.php
@@ -0,0 +1,9 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node;
+
+use PhpParser\NodeAbstract;
+
+abstract class Stmt extends NodeAbstract
+{
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Break_.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Break_.php
new file mode 100644
index 0000000000000000000000000000000000000000..6adc5a6c6f716a0357696cbf8a9f7314c0af9d97
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Break_.php
@@ -0,0 +1,30 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node\Stmt;
+
+use PhpParser\Node;
+
+class Break_ extends Node\Stmt
+{
+    /** @var null|Node\Expr Number of loops to break */
+    public $num;
+
+    /**
+     * Constructs a break node.
+     *
+     * @param null|Node\Expr $num        Number of loops to break
+     * @param array          $attributes Additional attributes
+     */
+    public function __construct(Node\Expr $num = null, array $attributes = []) {
+        $this->attributes = $attributes;
+        $this->num = $num;
+    }
+
+    public function getSubNodeNames() : array {
+        return ['num'];
+    }
+    
+    public function getType() : string {
+        return 'Stmt_Break';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Case_.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Case_.php
new file mode 100644
index 0000000000000000000000000000000000000000..2bf044c90082e4b780af11983b6cb93f6e3dc808
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Case_.php
@@ -0,0 +1,34 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node\Stmt;
+
+use PhpParser\Node;
+
+class Case_ extends Node\Stmt
+{
+    /** @var null|Node\Expr Condition (null for default) */
+    public $cond;
+    /** @var Node\Stmt[] Statements */
+    public $stmts;
+
+    /**
+     * Constructs a case node.
+     *
+     * @param null|Node\Expr $cond       Condition (null for default)
+     * @param Node\Stmt[]    $stmts      Statements
+     * @param array          $attributes Additional attributes
+     */
+    public function __construct($cond, array $stmts = [], array $attributes = []) {
+        $this->attributes = $attributes;
+        $this->cond = $cond;
+        $this->stmts = $stmts;
+    }
+
+    public function getSubNodeNames() : array {
+        return ['cond', 'stmts'];
+    }
+    
+    public function getType() : string {
+        return 'Stmt_Case';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Catch_.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Catch_.php
new file mode 100644
index 0000000000000000000000000000000000000000..9b9c09478222def88a553b92d70092e166080b6a
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Catch_.php
@@ -0,0 +1,41 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node\Stmt;
+
+use PhpParser\Node;
+use PhpParser\Node\Expr;
+
+class Catch_ extends Node\Stmt
+{
+    /** @var Node\Name[] Types of exceptions to catch */
+    public $types;
+    /** @var Expr\Variable|null Variable for exception */
+    public $var;
+    /** @var Node\Stmt[] Statements */
+    public $stmts;
+
+    /**
+     * Constructs a catch node.
+     *
+     * @param Node\Name[]           $types      Types of exceptions to catch
+     * @param Expr\Variable|null    $var        Variable for exception
+     * @param Node\Stmt[]           $stmts      Statements
+     * @param array                 $attributes Additional attributes
+     */
+    public function __construct(
+        array $types, Expr\Variable $var = null, array $stmts = [], array $attributes = []
+    ) {
+        $this->attributes = $attributes;
+        $this->types = $types;
+        $this->var = $var;
+        $this->stmts = $stmts;
+    }
+
+    public function getSubNodeNames() : array {
+        return ['types', 'var', 'stmts'];
+    }
+
+    public function getType() : string {
+        return 'Stmt_Catch';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/ClassConst.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/ClassConst.php
new file mode 100644
index 0000000000000000000000000000000000000000..c459acb1527f04eb633296db96fcc9c7c4362768
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/ClassConst.php
@@ -0,0 +1,71 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node\Stmt;
+
+use PhpParser\Node;
+
+class ClassConst extends Node\Stmt
+{
+    /** @var int Modifiers */
+    public $flags;
+    /** @var Node\Const_[] Constant declarations */
+    public $consts;
+    /** @var Node\AttributeGroup[] */
+    public $attrGroups;
+
+    /**
+     * Constructs a class const list node.
+     *
+     * @param Node\Const_[]         $consts     Constant declarations
+     * @param int                   $flags      Modifiers
+     * @param array                 $attributes Additional attributes
+     * @param Node\AttributeGroup[] $attrGroups PHP attribute groups
+     */
+    public function __construct(
+        array $consts,
+        int $flags = 0,
+        array $attributes = [],
+        array $attrGroups = []
+    ) {
+        $this->attributes = $attributes;
+        $this->flags = $flags;
+        $this->consts = $consts;
+        $this->attrGroups = $attrGroups;
+    }
+
+    public function getSubNodeNames() : array {
+        return ['attrGroups', 'flags', 'consts'];
+    }
+
+    /**
+     * Whether constant is explicitly or implicitly public.
+     *
+     * @return bool
+     */
+    public function isPublic() : bool {
+        return ($this->flags & Class_::MODIFIER_PUBLIC) !== 0
+            || ($this->flags & Class_::VISIBILITY_MODIFIER_MASK) === 0;
+    }
+
+    /**
+     * Whether constant is protected.
+     *
+     * @return bool
+     */
+    public function isProtected() : bool {
+        return (bool) ($this->flags & Class_::MODIFIER_PROTECTED);
+    }
+
+    /**
+     * Whether constant is private.
+     *
+     * @return bool
+     */
+    public function isPrivate() : bool {
+        return (bool) ($this->flags & Class_::MODIFIER_PRIVATE);
+    }
+
+    public function getType() : string {
+        return 'Stmt_ClassConst';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/ClassLike.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/ClassLike.php
new file mode 100644
index 0000000000000000000000000000000000000000..840c4f67ec5f4b9691de3914321921e5abc76600
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/ClassLike.php
@@ -0,0 +1,109 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node\Stmt;
+
+use PhpParser\Node;
+
+/**
+ * @property Node\Name $namespacedName Namespaced name (if using NameResolver)
+ */
+abstract class ClassLike extends Node\Stmt
+{
+    /** @var Node\Identifier|null Name */
+    public $name;
+    /** @var Node\Stmt[] Statements */
+    public $stmts;
+    /** @var Node\AttributeGroup[] PHP attribute groups */
+    public $attrGroups;
+
+    /**
+     * @return TraitUse[]
+     */
+    public function getTraitUses() : array {
+        $traitUses = [];
+        foreach ($this->stmts as $stmt) {
+            if ($stmt instanceof TraitUse) {
+                $traitUses[] = $stmt;
+            }
+        }
+        return $traitUses;
+    }
+
+    /**
+     * @return ClassConst[]
+     */
+    public function getConstants() : array {
+        $constants = [];
+        foreach ($this->stmts as $stmt) {
+            if ($stmt instanceof ClassConst) {
+                $constants[] = $stmt;
+            }
+        }
+        return $constants;
+    }
+
+    /**
+     * @return Property[]
+     */
+    public function getProperties() : array {
+        $properties = [];
+        foreach ($this->stmts as $stmt) {
+            if ($stmt instanceof Property) {
+                $properties[] = $stmt;
+            }
+        }
+        return $properties;
+    }
+
+    /**
+     * Gets property with the given name defined directly in this class/interface/trait.
+     *
+     * @param string $name Name of the property
+     *
+     * @return Property|null Property node or null if the property does not exist
+     */
+    public function getProperty(string $name) {
+        foreach ($this->stmts as $stmt) {
+            if ($stmt instanceof Property) {
+                foreach ($stmt->props as $prop) {
+                    if ($prop instanceof PropertyProperty && $name === $prop->name->toString()) {
+                        return $stmt;
+                    }
+                }
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Gets all methods defined directly in this class/interface/trait
+     *
+     * @return ClassMethod[]
+     */
+    public function getMethods() : array {
+        $methods = [];
+        foreach ($this->stmts as $stmt) {
+            if ($stmt instanceof ClassMethod) {
+                $methods[] = $stmt;
+            }
+        }
+        return $methods;
+    }
+
+    /**
+     * Gets method with the given name defined directly in this class/interface/trait.
+     *
+     * @param string $name Name of the method (compared case-insensitively)
+     *
+     * @return ClassMethod|null Method node or null if the method does not exist
+     */
+    public function getMethod(string $name) {
+        $lowerName = strtolower($name);
+        foreach ($this->stmts as $stmt) {
+            if ($stmt instanceof ClassMethod && $lowerName === $stmt->name->toLowerString()) {
+                return $stmt;
+            }
+        }
+        return null;
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/ClassMethod.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/ClassMethod.php
new file mode 100644
index 0000000000000000000000000000000000000000..92157fab26b4f13da38d73a9d17bec892e84a913
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/ClassMethod.php
@@ -0,0 +1,159 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node\Stmt;
+
+use PhpParser\Node;
+use PhpParser\Node\FunctionLike;
+
+class ClassMethod extends Node\Stmt implements FunctionLike
+{
+    /** @var int Flags */
+    public $flags;
+    /** @var bool Whether to return by reference */
+    public $byRef;
+    /** @var Node\Identifier Name */
+    public $name;
+    /** @var Node\Param[] Parameters */
+    public $params;
+    /** @var null|Node\Identifier|Node\Name|Node\NullableType|Node\UnionType Return type */
+    public $returnType;
+    /** @var Node\Stmt[]|null Statements */
+    public $stmts;
+    /** @var Node\AttributeGroup[] PHP attribute groups */
+    public $attrGroups;
+
+    private static $magicNames = [
+        '__construct'  => true,
+        '__destruct'   => true,
+        '__call'       => true,
+        '__callstatic' => true,
+        '__get'        => true,
+        '__set'        => true,
+        '__isset'      => true,
+        '__unset'      => true,
+        '__sleep'      => true,
+        '__wakeup'     => true,
+        '__tostring'   => true,
+        '__set_state'  => true,
+        '__clone'      => true,
+        '__invoke'     => true,
+        '__debuginfo'  => true,
+    ];
+
+    /**
+     * Constructs a class method node.
+     *
+     * @param string|Node\Identifier $name Name
+     * @param array $subNodes   Array of the following optional subnodes:
+     *                          'flags       => MODIFIER_PUBLIC: Flags
+     *                          'byRef'      => false          : Whether to return by reference
+     *                          'params'     => array()        : Parameters
+     *                          'returnType' => null           : Return type
+     *                          'stmts'      => array()        : Statements
+     *                          'attrGroups' => array()        : PHP attribute groups
+     * @param array $attributes Additional attributes
+     */
+    public function __construct($name, array $subNodes = [], array $attributes = []) {
+        $this->attributes = $attributes;
+        $this->flags = $subNodes['flags'] ?? $subNodes['type'] ?? 0;
+        $this->byRef = $subNodes['byRef'] ?? false;
+        $this->name = \is_string($name) ? new Node\Identifier($name) : $name;
+        $this->params = $subNodes['params'] ?? [];
+        $returnType = $subNodes['returnType'] ?? null;
+        $this->returnType = \is_string($returnType) ? new Node\Identifier($returnType) : $returnType;
+        $this->stmts = array_key_exists('stmts', $subNodes) ? $subNodes['stmts'] : [];
+        $this->attrGroups = $subNodes['attrGroups'] ?? [];
+    }
+
+    public function getSubNodeNames() : array {
+        return ['attrGroups', 'flags', 'byRef', 'name', 'params', 'returnType', 'stmts'];
+    }
+
+    public function returnsByRef() : bool {
+        return $this->byRef;
+    }
+
+    public function getParams() : array {
+        return $this->params;
+    }
+
+    public function getReturnType() {
+        return $this->returnType;
+    }
+
+    public function getStmts() {
+        return $this->stmts;
+    }
+
+    public function getAttrGroups() : array {
+        return $this->attrGroups;
+    }
+
+    /**
+     * Whether the method is explicitly or implicitly public.
+     *
+     * @return bool
+     */
+    public function isPublic() : bool {
+        return ($this->flags & Class_::MODIFIER_PUBLIC) !== 0
+            || ($this->flags & Class_::VISIBILITY_MODIFIER_MASK) === 0;
+    }
+
+    /**
+     * Whether the method is protected.
+     *
+     * @return bool
+     */
+    public function isProtected() : bool {
+        return (bool) ($this->flags & Class_::MODIFIER_PROTECTED);
+    }
+
+    /**
+     * Whether the method is private.
+     *
+     * @return bool
+     */
+    public function isPrivate() : bool {
+        return (bool) ($this->flags & Class_::MODIFIER_PRIVATE);
+    }
+
+    /**
+     * Whether the method is abstract.
+     *
+     * @return bool
+     */
+    public function isAbstract() : bool {
+        return (bool) ($this->flags & Class_::MODIFIER_ABSTRACT);
+    }
+
+    /**
+     * Whether the method is final.
+     *
+     * @return bool
+     */
+    public function isFinal() : bool {
+        return (bool) ($this->flags & Class_::MODIFIER_FINAL);
+    }
+
+    /**
+     * Whether the method is static.
+     *
+     * @return bool
+     */
+    public function isStatic() : bool {
+        return (bool) ($this->flags & Class_::MODIFIER_STATIC);
+    }
+
+    /**
+     * Whether the method is magic.
+     *
+     * @return bool
+     */
+    public function isMagic() : bool {
+        return isset(self::$magicNames[$this->name->toLowerString()]);
+    }
+
+    public function getType() : string {
+        return 'Stmt_ClassMethod';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Class_.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Class_.php
new file mode 100644
index 0000000000000000000000000000000000000000..ace266f74b71cf554997b9c0c5beffd3f77690aa
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Class_.php
@@ -0,0 +1,107 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node\Stmt;
+
+use PhpParser\Error;
+use PhpParser\Node;
+
+class Class_ extends ClassLike
+{
+    const MODIFIER_PUBLIC    =  1;
+    const MODIFIER_PROTECTED =  2;
+    const MODIFIER_PRIVATE   =  4;
+    const MODIFIER_STATIC    =  8;
+    const MODIFIER_ABSTRACT  = 16;
+    const MODIFIER_FINAL     = 32;
+
+    const VISIBILITY_MODIFIER_MASK = 7; // 1 | 2 | 4
+
+    /** @var int Type */
+    public $flags;
+    /** @var null|Node\Name Name of extended class */
+    public $extends;
+    /** @var Node\Name[] Names of implemented interfaces */
+    public $implements;
+
+    /**
+     * Constructs a class node.
+     *
+     * @param string|Node\Identifier|null $name Name
+     * @param array       $subNodes   Array of the following optional subnodes:
+     *                                'flags'       => 0      : Flags
+     *                                'extends'     => null   : Name of extended class
+     *                                'implements'  => array(): Names of implemented interfaces
+     *                                'stmts'       => array(): Statements
+     *                                '$attrGroups' => array(): PHP attribute groups
+     * @param array       $attributes Additional attributes
+     */
+    public function __construct($name, array $subNodes = [], array $attributes = []) {
+        $this->attributes = $attributes;
+        $this->flags = $subNodes['flags'] ?? $subNodes['type'] ?? 0;
+        $this->name = \is_string($name) ? new Node\Identifier($name) : $name;
+        $this->extends = $subNodes['extends'] ?? null;
+        $this->implements = $subNodes['implements'] ?? [];
+        $this->stmts = $subNodes['stmts'] ?? [];
+        $this->attrGroups = $subNodes['attrGroups'] ?? [];
+    }
+
+    public function getSubNodeNames() : array {
+        return ['attrGroups', 'flags', 'name', 'extends', 'implements', 'stmts'];
+    }
+
+    /**
+     * Whether the class is explicitly abstract.
+     *
+     * @return bool
+     */
+    public function isAbstract() : bool {
+        return (bool) ($this->flags & self::MODIFIER_ABSTRACT);
+    }
+
+    /**
+     * Whether the class is final.
+     *
+     * @return bool
+     */
+    public function isFinal() : bool {
+        return (bool) ($this->flags & self::MODIFIER_FINAL);
+    }
+
+    /**
+     * Whether the class is anonymous.
+     *
+     * @return bool
+     */
+    public function isAnonymous() : bool {
+        return null === $this->name;
+    }
+
+    /**
+     * @internal
+     */
+    public static function verifyModifier($a, $b) {
+        if ($a & self::VISIBILITY_MODIFIER_MASK && $b & self::VISIBILITY_MODIFIER_MASK) {
+            throw new Error('Multiple access type modifiers are not allowed');
+        }
+
+        if ($a & self::MODIFIER_ABSTRACT && $b & self::MODIFIER_ABSTRACT) {
+            throw new Error('Multiple abstract modifiers are not allowed');
+        }
+
+        if ($a & self::MODIFIER_STATIC && $b & self::MODIFIER_STATIC) {
+            throw new Error('Multiple static modifiers are not allowed');
+        }
+
+        if ($a & self::MODIFIER_FINAL && $b & self::MODIFIER_FINAL) {
+            throw new Error('Multiple final modifiers are not allowed');
+        }
+
+        if ($a & 48 && $b & 48) {
+            throw new Error('Cannot use the final modifier on an abstract class member');
+        }
+    }
+
+    public function getType() : string {
+        return 'Stmt_Class';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Const_.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Const_.php
new file mode 100644
index 0000000000000000000000000000000000000000..e6316345ee34b9fe1ceb473027b4a18395d63471
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Const_.php
@@ -0,0 +1,30 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node\Stmt;
+
+use PhpParser\Node;
+
+class Const_ extends Node\Stmt
+{
+    /** @var Node\Const_[] Constant declarations */
+    public $consts;
+
+    /**
+     * Constructs a const list node.
+     *
+     * @param Node\Const_[] $consts     Constant declarations
+     * @param array         $attributes Additional attributes
+     */
+    public function __construct(array $consts, array $attributes = []) {
+        $this->attributes = $attributes;
+        $this->consts = $consts;
+    }
+
+    public function getSubNodeNames() : array {
+        return ['consts'];
+    }
+    
+    public function getType() : string {
+        return 'Stmt_Const';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Continue_.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Continue_.php
new file mode 100644
index 0000000000000000000000000000000000000000..24882683b37c607cff0ce1c20df9fb8e344ee10a
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Continue_.php
@@ -0,0 +1,30 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node\Stmt;
+
+use PhpParser\Node;
+
+class Continue_ extends Node\Stmt
+{
+    /** @var null|Node\Expr Number of loops to continue */
+    public $num;
+
+    /**
+     * Constructs a continue node.
+     *
+     * @param null|Node\Expr $num        Number of loops to continue
+     * @param array          $attributes Additional attributes
+     */
+    public function __construct(Node\Expr $num = null, array $attributes = []) {
+        $this->attributes = $attributes;
+        $this->num = $num;
+    }
+
+    public function getSubNodeNames() : array {
+        return ['num'];
+    }
+    
+    public function getType() : string {
+        return 'Stmt_Continue';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/DeclareDeclare.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/DeclareDeclare.php
new file mode 100644
index 0000000000000000000000000000000000000000..ac07f30c78f0cc91a873862cdf73051cd965182b
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/DeclareDeclare.php
@@ -0,0 +1,34 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node\Stmt;
+
+use PhpParser\Node;
+
+class DeclareDeclare extends Node\Stmt
+{
+    /** @var Node\Identifier Key */
+    public $key;
+    /** @var Node\Expr Value */
+    public $value;
+
+    /**
+     * Constructs a declare key=>value pair node.
+     *
+     * @param string|Node\Identifier $key        Key
+     * @param Node\Expr              $value      Value
+     * @param array                  $attributes Additional attributes
+     */
+    public function __construct($key, Node\Expr $value, array $attributes = []) {
+        $this->attributes = $attributes;
+        $this->key = \is_string($key) ? new Node\Identifier($key) : $key;
+        $this->value = $value;
+    }
+
+    public function getSubNodeNames() : array {
+        return ['key', 'value'];
+    }
+    
+    public function getType() : string {
+        return 'Stmt_DeclareDeclare';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Declare_.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Declare_.php
new file mode 100644
index 0000000000000000000000000000000000000000..f46ff0bafde696a6a74f25d9909f0a0044c67ab0
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Declare_.php
@@ -0,0 +1,34 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node\Stmt;
+
+use PhpParser\Node;
+
+class Declare_ extends Node\Stmt
+{
+    /** @var DeclareDeclare[] List of declares */
+    public $declares;
+    /** @var Node\Stmt[]|null Statements */
+    public $stmts;
+
+    /**
+     * Constructs a declare node.
+     *
+     * @param DeclareDeclare[] $declares   List of declares
+     * @param Node\Stmt[]|null $stmts      Statements
+     * @param array            $attributes Additional attributes
+     */
+    public function __construct(array $declares, array $stmts = null, array $attributes = []) {
+        $this->attributes = $attributes;
+        $this->declares = $declares;
+        $this->stmts = $stmts;
+    }
+
+    public function getSubNodeNames() : array {
+        return ['declares', 'stmts'];
+    }
+    
+    public function getType() : string {
+        return 'Stmt_Declare';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Do_.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Do_.php
new file mode 100644
index 0000000000000000000000000000000000000000..78e90da03a083c416b293662e1e4eee6d8466e37
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Do_.php
@@ -0,0 +1,34 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node\Stmt;
+
+use PhpParser\Node;
+
+class Do_ extends Node\Stmt
+{
+    /** @var Node\Stmt[] Statements */
+    public $stmts;
+    /** @var Node\Expr Condition */
+    public $cond;
+
+    /**
+     * Constructs a do while node.
+     *
+     * @param Node\Expr   $cond       Condition
+     * @param Node\Stmt[] $stmts      Statements
+     * @param array       $attributes Additional attributes
+     */
+    public function __construct(Node\Expr $cond, array $stmts = [], array $attributes = []) {
+        $this->attributes = $attributes;
+        $this->cond = $cond;
+        $this->stmts = $stmts;
+    }
+
+    public function getSubNodeNames() : array {
+        return ['stmts', 'cond'];
+    }
+    
+    public function getType() : string {
+        return 'Stmt_Do';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Echo_.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Echo_.php
new file mode 100644
index 0000000000000000000000000000000000000000..7cc50d5d6e805aab34a2485651487eb41dcbddd0
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Echo_.php
@@ -0,0 +1,30 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node\Stmt;
+
+use PhpParser\Node;
+
+class Echo_ extends Node\Stmt
+{
+    /** @var Node\Expr[] Expressions */
+    public $exprs;
+
+    /**
+     * Constructs an echo node.
+     *
+     * @param Node\Expr[] $exprs      Expressions
+     * @param array       $attributes Additional attributes
+     */
+    public function __construct(array $exprs, array $attributes = []) {
+        $this->attributes = $attributes;
+        $this->exprs = $exprs;
+    }
+
+    public function getSubNodeNames() : array {
+        return ['exprs'];
+    }
+    
+    public function getType() : string {
+        return 'Stmt_Echo';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/ElseIf_.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/ElseIf_.php
new file mode 100644
index 0000000000000000000000000000000000000000..eef1ece3242585e0d31a98a67a834a3b0f1019c7
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/ElseIf_.php
@@ -0,0 +1,34 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node\Stmt;
+
+use PhpParser\Node;
+
+class ElseIf_ extends Node\Stmt
+{
+    /** @var Node\Expr Condition */
+    public $cond;
+    /** @var Node\Stmt[] Statements */
+    public $stmts;
+
+    /**
+     * Constructs an elseif node.
+     *
+     * @param Node\Expr   $cond       Condition
+     * @param Node\Stmt[] $stmts      Statements
+     * @param array       $attributes Additional attributes
+     */
+    public function __construct(Node\Expr $cond, array $stmts = [], array $attributes = []) {
+        $this->attributes = $attributes;
+        $this->cond = $cond;
+        $this->stmts = $stmts;
+    }
+
+    public function getSubNodeNames() : array {
+        return ['cond', 'stmts'];
+    }
+    
+    public function getType() : string {
+        return 'Stmt_ElseIf';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Else_.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Else_.php
new file mode 100644
index 0000000000000000000000000000000000000000..0e61778e26021b4d739ff8517b3e5f00f5adef90
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Else_.php
@@ -0,0 +1,30 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node\Stmt;
+
+use PhpParser\Node;
+
+class Else_ extends Node\Stmt
+{
+    /** @var Node\Stmt[] Statements */
+    public $stmts;
+
+    /**
+     * Constructs an else node.
+     *
+     * @param Node\Stmt[] $stmts      Statements
+     * @param array       $attributes Additional attributes
+     */
+    public function __construct(array $stmts = [], array $attributes = []) {
+        $this->attributes = $attributes;
+        $this->stmts = $stmts;
+    }
+
+    public function getSubNodeNames() : array {
+        return ['stmts'];
+    }
+    
+    public function getType() : string {
+        return 'Stmt_Else';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Expression.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Expression.php
new file mode 100644
index 0000000000000000000000000000000000000000..99d1687deddbb37a41ac19e79324f3aee7091965
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Expression.php
@@ -0,0 +1,33 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node\Stmt;
+
+use PhpParser\Node;
+
+/**
+ * Represents statements of type "expr;"
+ */
+class Expression extends Node\Stmt
+{
+    /** @var Node\Expr Expression */
+    public $expr;
+
+    /**
+     * Constructs an expression statement.
+     *
+     * @param Node\Expr $expr       Expression
+     * @param array     $attributes Additional attributes
+     */
+    public function __construct(Node\Expr $expr, array $attributes = []) {
+        $this->attributes = $attributes;
+        $this->expr = $expr;
+    }
+
+    public function getSubNodeNames() : array {
+        return ['expr'];
+    }
+    
+    public function getType() : string {
+        return 'Stmt_Expression';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Finally_.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Finally_.php
new file mode 100644
index 0000000000000000000000000000000000000000..d55b8b687269b3eb42dd8493dd54f928a68d070a
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Finally_.php
@@ -0,0 +1,30 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node\Stmt;
+
+use PhpParser\Node;
+
+class Finally_ extends Node\Stmt
+{
+    /** @var Node\Stmt[] Statements */
+    public $stmts;
+
+    /**
+     * Constructs a finally node.
+     *
+     * @param Node\Stmt[] $stmts      Statements
+     * @param array       $attributes Additional attributes
+     */
+    public function __construct(array $stmts = [], array $attributes = []) {
+        $this->attributes = $attributes;
+        $this->stmts = $stmts;
+    }
+
+    public function getSubNodeNames() : array {
+        return ['stmts'];
+    }
+    
+    public function getType() : string {
+        return 'Stmt_Finally';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/For_.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/For_.php
new file mode 100644
index 0000000000000000000000000000000000000000..1323d37cf34ce5f5723c7fe16d2b0b27c6a89562
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/For_.php
@@ -0,0 +1,43 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node\Stmt;
+
+use PhpParser\Node;
+
+class For_ extends Node\Stmt
+{
+    /** @var Node\Expr[] Init expressions */
+    public $init;
+    /** @var Node\Expr[] Loop conditions */
+    public $cond;
+    /** @var Node\Expr[] Loop expressions */
+    public $loop;
+    /** @var Node\Stmt[] Statements */
+    public $stmts;
+
+    /**
+     * Constructs a for loop node.
+     *
+     * @param array $subNodes   Array of the following optional subnodes:
+     *                          'init'  => array(): Init expressions
+     *                          'cond'  => array(): Loop conditions
+     *                          'loop'  => array(): Loop expressions
+     *                          'stmts' => array(): Statements
+     * @param array $attributes Additional attributes
+     */
+    public function __construct(array $subNodes = [], array $attributes = []) {
+        $this->attributes = $attributes;
+        $this->init = $subNodes['init'] ?? [];
+        $this->cond = $subNodes['cond'] ?? [];
+        $this->loop = $subNodes['loop'] ?? [];
+        $this->stmts = $subNodes['stmts'] ?? [];
+    }
+
+    public function getSubNodeNames() : array {
+        return ['init', 'cond', 'loop', 'stmts'];
+    }
+    
+    public function getType() : string {
+        return 'Stmt_For';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Foreach_.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Foreach_.php
new file mode 100644
index 0000000000000000000000000000000000000000..0556a7ce5f6a8061cebd067bff90d696d58d3ea6
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Foreach_.php
@@ -0,0 +1,47 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node\Stmt;
+
+use PhpParser\Node;
+
+class Foreach_ extends Node\Stmt
+{
+    /** @var Node\Expr Expression to iterate */
+    public $expr;
+    /** @var null|Node\Expr Variable to assign key to */
+    public $keyVar;
+    /** @var bool Whether to assign value by reference */
+    public $byRef;
+    /** @var Node\Expr Variable to assign value to */
+    public $valueVar;
+    /** @var Node\Stmt[] Statements */
+    public $stmts;
+
+    /**
+     * Constructs a foreach node.
+     *
+     * @param Node\Expr $expr       Expression to iterate
+     * @param Node\Expr $valueVar   Variable to assign value to
+     * @param array     $subNodes   Array of the following optional subnodes:
+     *                              'keyVar' => null   : Variable to assign key to
+     *                              'byRef'  => false  : Whether to assign value by reference
+     *                              'stmts'  => array(): Statements
+     * @param array     $attributes Additional attributes
+     */
+    public function __construct(Node\Expr $expr, Node\Expr $valueVar, array $subNodes = [], array $attributes = []) {
+        $this->attributes = $attributes;
+        $this->expr = $expr;
+        $this->keyVar = $subNodes['keyVar'] ?? null;
+        $this->byRef = $subNodes['byRef'] ?? false;
+        $this->valueVar = $valueVar;
+        $this->stmts = $subNodes['stmts'] ?? [];
+    }
+
+    public function getSubNodeNames() : array {
+        return ['expr', 'keyVar', 'byRef', 'valueVar', 'stmts'];
+    }
+    
+    public function getType() : string {
+        return 'Stmt_Foreach';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Function_.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Function_.php
new file mode 100644
index 0000000000000000000000000000000000000000..f08481fae1c40e789ef32c6650d26b1b16dd200d
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Function_.php
@@ -0,0 +1,77 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node\Stmt;
+
+use PhpParser\Node;
+use PhpParser\Node\FunctionLike;
+
+/**
+ * @property Node\Name $namespacedName Namespaced name (if using NameResolver)
+ */
+class Function_ extends Node\Stmt implements FunctionLike
+{
+    /** @var bool Whether function returns by reference */
+    public $byRef;
+    /** @var Node\Identifier Name */
+    public $name;
+    /** @var Node\Param[] Parameters */
+    public $params;
+    /** @var null|Node\Identifier|Node\Name|Node\NullableType|Node\UnionType Return type */
+    public $returnType;
+    /** @var Node\Stmt[] Statements */
+    public $stmts;
+    /** @var Node\AttributeGroup[] PHP attribute groups */
+    public $attrGroups;
+
+    /**
+     * Constructs a function node.
+     *
+     * @param string|Node\Identifier $name Name
+     * @param array  $subNodes   Array of the following optional subnodes:
+     *                           'byRef'      => false  : Whether to return by reference
+     *                           'params'     => array(): Parameters
+     *                           'returnType' => null   : Return type
+     *                           'stmts'      => array(): Statements
+     *                           'attrGroups' => array(): PHP attribute groups
+     * @param array  $attributes Additional attributes
+     */
+    public function __construct($name, array $subNodes = [], array $attributes = []) {
+        $this->attributes = $attributes;
+        $this->byRef = $subNodes['byRef'] ?? false;
+        $this->name = \is_string($name) ? new Node\Identifier($name) : $name;
+        $this->params = $subNodes['params'] ?? [];
+        $returnType = $subNodes['returnType'] ?? null;
+        $this->returnType = \is_string($returnType) ? new Node\Identifier($returnType) : $returnType;
+        $this->stmts = $subNodes['stmts'] ?? [];
+        $this->attrGroups = $subNodes['attrGroups'] ?? [];
+    }
+
+    public function getSubNodeNames() : array {
+        return ['attrGroups', 'byRef', 'name', 'params', 'returnType', 'stmts'];
+    }
+
+    public function returnsByRef() : bool {
+        return $this->byRef;
+    }
+
+    public function getParams() : array {
+        return $this->params;
+    }
+
+    public function getReturnType() {
+        return $this->returnType;
+    }
+
+    public function getAttrGroups() : array {
+        return $this->attrGroups;
+    }
+
+    /** @return Node\Stmt[] */
+    public function getStmts() : array {
+        return $this->stmts;
+    }
+
+    public function getType() : string {
+        return 'Stmt_Function';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Global_.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Global_.php
new file mode 100644
index 0000000000000000000000000000000000000000..a0022ad9328f5ead35ea7b067f771c70ff388f96
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Global_.php
@@ -0,0 +1,30 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node\Stmt;
+
+use PhpParser\Node;
+
+class Global_ extends Node\Stmt
+{
+    /** @var Node\Expr[] Variables */
+    public $vars;
+
+    /**
+     * Constructs a global variables list node.
+     *
+     * @param Node\Expr[] $vars       Variables to unset
+     * @param array       $attributes Additional attributes
+     */
+    public function __construct(array $vars, array $attributes = []) {
+        $this->attributes = $attributes;
+        $this->vars = $vars;
+    }
+
+    public function getSubNodeNames() : array {
+        return ['vars'];
+    }
+    
+    public function getType() : string {
+        return 'Stmt_Global';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Goto_.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Goto_.php
new file mode 100644
index 0000000000000000000000000000000000000000..24a57f7807763aa2f6be834fd485363e1133da4a
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Goto_.php
@@ -0,0 +1,31 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node\Stmt;
+
+use PhpParser\Node\Identifier;
+use PhpParser\Node\Stmt;
+
+class Goto_ extends Stmt
+{
+    /** @var Identifier Name of label to jump to */
+    public $name;
+
+    /**
+     * Constructs a goto node.
+     *
+     * @param string|Identifier $name       Name of label to jump to
+     * @param array             $attributes Additional attributes
+     */
+    public function __construct($name, array $attributes = []) {
+        $this->attributes = $attributes;
+        $this->name = \is_string($name) ? new Identifier($name) : $name;
+    }
+
+    public function getSubNodeNames() : array {
+        return ['name'];
+    }
+    
+    public function getType() : string {
+        return 'Stmt_Goto';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/GroupUse.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/GroupUse.php
new file mode 100644
index 0000000000000000000000000000000000000000..24520d2233c77d6eb02238ed55e5e8c0c97612e0
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/GroupUse.php
@@ -0,0 +1,39 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node\Stmt;
+
+use PhpParser\Node\Name;
+use PhpParser\Node\Stmt;
+
+class GroupUse extends Stmt
+{
+    /** @var int Type of group use */
+    public $type;
+    /** @var Name Prefix for uses */
+    public $prefix;
+    /** @var UseUse[] Uses */
+    public $uses;
+
+    /**
+     * Constructs a group use node.
+     *
+     * @param Name     $prefix     Prefix for uses
+     * @param UseUse[] $uses       Uses
+     * @param int      $type       Type of group use
+     * @param array    $attributes Additional attributes
+     */
+    public function __construct(Name $prefix, array $uses, int $type = Use_::TYPE_NORMAL, array $attributes = []) {
+        $this->attributes = $attributes;
+        $this->type = $type;
+        $this->prefix = $prefix;
+        $this->uses = $uses;
+    }
+
+    public function getSubNodeNames() : array {
+        return ['type', 'prefix', 'uses'];
+    }
+    
+    public function getType() : string {
+        return 'Stmt_GroupUse';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/HaltCompiler.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/HaltCompiler.php
new file mode 100644
index 0000000000000000000000000000000000000000..8e624e0f1fb4f67b1bf18909b7ff706c0adeac75
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/HaltCompiler.php
@@ -0,0 +1,30 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node\Stmt;
+
+use PhpParser\Node\Stmt;
+
+class HaltCompiler extends Stmt
+{
+    /** @var string Remaining text after halt compiler statement. */
+    public $remaining;
+
+    /**
+     * Constructs a __halt_compiler node.
+     *
+     * @param string $remaining  Remaining text after halt compiler statement.
+     * @param array  $attributes Additional attributes
+     */
+    public function __construct(string $remaining, array $attributes = []) {
+        $this->attributes = $attributes;
+        $this->remaining = $remaining;
+    }
+
+    public function getSubNodeNames() : array {
+        return ['remaining'];
+    }
+    
+    public function getType() : string {
+        return 'Stmt_HaltCompiler';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/If_.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/If_.php
new file mode 100644
index 0000000000000000000000000000000000000000..a1bae4bf891e1384cf4cbc02fe6b5c344425bb91
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/If_.php
@@ -0,0 +1,43 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node\Stmt;
+
+use PhpParser\Node;
+
+class If_ extends Node\Stmt
+{
+    /** @var Node\Expr Condition expression */
+    public $cond;
+    /** @var Node\Stmt[] Statements */
+    public $stmts;
+    /** @var ElseIf_[] Elseif clauses */
+    public $elseifs;
+    /** @var null|Else_ Else clause */
+    public $else;
+
+    /**
+     * Constructs an if node.
+     *
+     * @param Node\Expr $cond       Condition
+     * @param array     $subNodes   Array of the following optional subnodes:
+     *                              'stmts'   => array(): Statements
+     *                              'elseifs' => array(): Elseif clauses
+     *                              'else'    => null   : Else clause
+     * @param array     $attributes Additional attributes
+     */
+    public function __construct(Node\Expr $cond, array $subNodes = [], array $attributes = []) {
+        $this->attributes = $attributes;
+        $this->cond = $cond;
+        $this->stmts = $subNodes['stmts'] ?? [];
+        $this->elseifs = $subNodes['elseifs'] ?? [];
+        $this->else = $subNodes['else'] ?? null;
+    }
+
+    public function getSubNodeNames() : array {
+        return ['cond', 'stmts', 'elseifs', 'else'];
+    }
+    
+    public function getType() : string {
+        return 'Stmt_If';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/InlineHTML.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/InlineHTML.php
new file mode 100644
index 0000000000000000000000000000000000000000..0711d2842c2147c206654a48d7fad8707435ae99
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/InlineHTML.php
@@ -0,0 +1,30 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node\Stmt;
+
+use PhpParser\Node\Stmt;
+
+class InlineHTML extends Stmt
+{
+    /** @var string String */
+    public $value;
+
+    /**
+     * Constructs an inline HTML node.
+     *
+     * @param string $value      String
+     * @param array  $attributes Additional attributes
+     */
+    public function __construct(string $value, array $attributes = []) {
+        $this->attributes = $attributes;
+        $this->value = $value;
+    }
+
+    public function getSubNodeNames() : array {
+        return ['value'];
+    }
+    
+    public function getType() : string {
+        return 'Stmt_InlineHTML';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Interface_.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Interface_.php
new file mode 100644
index 0000000000000000000000000000000000000000..4d587dd4843e7f2bff1ff68aa2fd98f4bcf10b4d
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Interface_.php
@@ -0,0 +1,37 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node\Stmt;
+
+use PhpParser\Node;
+
+class Interface_ extends ClassLike
+{
+    /** @var Node\Name[] Extended interfaces */
+    public $extends;
+
+    /**
+     * Constructs a class node.
+     *
+     * @param string|Node\Identifier $name Name
+     * @param array  $subNodes   Array of the following optional subnodes:
+     *                           'extends'    => array(): Name of extended interfaces
+     *                           'stmts'      => array(): Statements
+     *                           'attrGroups' => array(): PHP attribute groups
+     * @param array  $attributes Additional attributes
+     */
+    public function __construct($name, array $subNodes = [], array $attributes = []) {
+        $this->attributes = $attributes;
+        $this->name = \is_string($name) ? new Node\Identifier($name) : $name;
+        $this->extends = $subNodes['extends'] ?? [];
+        $this->stmts = $subNodes['stmts'] ?? [];
+        $this->attrGroups = $subNodes['attrGroups'] ?? [];
+    }
+
+    public function getSubNodeNames() : array {
+        return ['attrGroups', 'name', 'extends', 'stmts'];
+    }
+
+    public function getType() : string {
+        return 'Stmt_Interface';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Label.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Label.php
new file mode 100644
index 0000000000000000000000000000000000000000..3edcb3be7ead9126dbca75ce20d22f66d1a4a86a
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Label.php
@@ -0,0 +1,31 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node\Stmt;
+
+use PhpParser\Node\Identifier;
+use PhpParser\Node\Stmt;
+
+class Label extends Stmt
+{
+    /** @var Identifier Name */
+    public $name;
+
+    /**
+     * Constructs a label node.
+     *
+     * @param string|Identifier $name       Name
+     * @param array             $attributes Additional attributes
+     */
+    public function __construct($name, array $attributes = []) {
+        $this->attributes = $attributes;
+        $this->name = \is_string($name) ? new Identifier($name) : $name;
+    }
+
+    public function getSubNodeNames() : array {
+        return ['name'];
+    }
+    
+    public function getType() : string {
+        return 'Stmt_Label';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Namespace_.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Namespace_.php
new file mode 100644
index 0000000000000000000000000000000000000000..c63204577c3fba326847291c56f0ddffae7593d9
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Namespace_.php
@@ -0,0 +1,38 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node\Stmt;
+
+use PhpParser\Node;
+
+class Namespace_ extends Node\Stmt
+{
+    /* For use in the "kind" attribute */
+    const KIND_SEMICOLON = 1;
+    const KIND_BRACED = 2;
+
+    /** @var null|Node\Name Name */
+    public $name;
+    /** @var Node\Stmt[] Statements */
+    public $stmts;
+
+    /**
+     * Constructs a namespace node.
+     *
+     * @param null|Node\Name   $name       Name
+     * @param null|Node\Stmt[] $stmts      Statements
+     * @param array            $attributes Additional attributes
+     */
+    public function __construct(Node\Name $name = null, $stmts = [], array $attributes = []) {
+        $this->attributes = $attributes;
+        $this->name = $name;
+        $this->stmts = $stmts;
+    }
+
+    public function getSubNodeNames() : array {
+        return ['name', 'stmts'];
+    }
+    
+    public function getType() : string {
+        return 'Stmt_Namespace';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Nop.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Nop.php
new file mode 100644
index 0000000000000000000000000000000000000000..f86f8df7d324df84763fd2c70032750145c3f62d
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Nop.php
@@ -0,0 +1,17 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node\Stmt;
+
+use PhpParser\Node;
+
+/** Nop/empty statement (;). */
+class Nop extends Node\Stmt
+{
+    public function getSubNodeNames() : array {
+        return [];
+    }
+    
+    public function getType() : string {
+        return 'Stmt_Nop';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Property.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Property.php
new file mode 100644
index 0000000000000000000000000000000000000000..324345b85f992c9b3f4527831682f40af99ddea6
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Property.php
@@ -0,0 +1,83 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node\Stmt;
+
+use PhpParser\Node;
+use PhpParser\Node\Identifier;
+use PhpParser\Node\Name;
+use PhpParser\Node\NullableType;
+use PhpParser\Node\UnionType;
+
+class Property extends Node\Stmt
+{
+    /** @var int Modifiers */
+    public $flags;
+    /** @var PropertyProperty[] Properties */
+    public $props;
+    /** @var null|Identifier|Name|NullableType|UnionType Type declaration */
+    public $type;
+    /** @var Node\AttributeGroup[] PHP attribute groups */
+    public $attrGroups;
+
+    /**
+     * Constructs a class property list node.
+     *
+     * @param int                                                $flags      Modifiers
+     * @param PropertyProperty[]                                 $props      Properties
+     * @param array                                              $attributes Additional attributes
+     * @param null|string|Identifier|Name|NullableType|UnionType $type       Type declaration
+     * @param Node\AttributeGroup[]                              $attrGroups PHP attribute groups
+     */
+    public function __construct(int $flags, array $props, array $attributes = [], $type = null, array $attrGroups = []) {
+        $this->attributes = $attributes;
+        $this->flags = $flags;
+        $this->props = $props;
+        $this->type = \is_string($type) ? new Identifier($type) : $type;
+        $this->attrGroups = $attrGroups;
+    }
+
+    public function getSubNodeNames() : array {
+        return ['attrGroups', 'flags', 'type', 'props'];
+    }
+
+    /**
+     * Whether the property is explicitly or implicitly public.
+     *
+     * @return bool
+     */
+    public function isPublic() : bool {
+        return ($this->flags & Class_::MODIFIER_PUBLIC) !== 0
+            || ($this->flags & Class_::VISIBILITY_MODIFIER_MASK) === 0;
+    }
+
+    /**
+     * Whether the property is protected.
+     *
+     * @return bool
+     */
+    public function isProtected() : bool {
+        return (bool) ($this->flags & Class_::MODIFIER_PROTECTED);
+    }
+
+    /**
+     * Whether the property is private.
+     *
+     * @return bool
+     */
+    public function isPrivate() : bool {
+        return (bool) ($this->flags & Class_::MODIFIER_PRIVATE);
+    }
+
+    /**
+     * Whether the property is static.
+     *
+     * @return bool
+     */
+    public function isStatic() : bool {
+        return (bool) ($this->flags & Class_::MODIFIER_STATIC);
+    }
+
+    public function getType() : string {
+        return 'Stmt_Property';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/PropertyProperty.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/PropertyProperty.php
new file mode 100644
index 0000000000000000000000000000000000000000..205731e20eb772e298b7fec1721f432cf862a4ed
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/PropertyProperty.php
@@ -0,0 +1,34 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node\Stmt;
+
+use PhpParser\Node;
+
+class PropertyProperty extends Node\Stmt
+{
+    /** @var Node\VarLikeIdentifier Name */
+    public $name;
+    /** @var null|Node\Expr Default */
+    public $default;
+
+    /**
+     * Constructs a class property node.
+     *
+     * @param string|Node\VarLikeIdentifier $name       Name
+     * @param null|Node\Expr                $default    Default value
+     * @param array                         $attributes Additional attributes
+     */
+    public function __construct($name, Node\Expr $default = null, array $attributes = []) {
+        $this->attributes = $attributes;
+        $this->name = \is_string($name) ? new Node\VarLikeIdentifier($name) : $name;
+        $this->default = $default;
+    }
+
+    public function getSubNodeNames() : array {
+        return ['name', 'default'];
+    }
+    
+    public function getType() : string {
+        return 'Stmt_PropertyProperty';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Return_.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Return_.php
new file mode 100644
index 0000000000000000000000000000000000000000..efc578c58f6e89ec0cda9e8977d29812ddd99ac0
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Return_.php
@@ -0,0 +1,30 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node\Stmt;
+
+use PhpParser\Node;
+
+class Return_ extends Node\Stmt
+{
+    /** @var null|Node\Expr Expression */
+    public $expr;
+
+    /**
+     * Constructs a return node.
+     *
+     * @param null|Node\Expr $expr       Expression
+     * @param array          $attributes Additional attributes
+     */
+    public function __construct(Node\Expr $expr = null, array $attributes = []) {
+        $this->attributes = $attributes;
+        $this->expr = $expr;
+    }
+
+    public function getSubNodeNames() : array {
+        return ['expr'];
+    }
+    
+    public function getType() : string {
+        return 'Stmt_Return';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/StaticVar.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/StaticVar.php
new file mode 100644
index 0000000000000000000000000000000000000000..29584560d3de3b8a0b17dbd6af5c2b8389cd39da
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/StaticVar.php
@@ -0,0 +1,37 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node\Stmt;
+
+use PhpParser\Node;
+use PhpParser\Node\Expr;
+
+class StaticVar extends Node\Stmt
+{
+    /** @var Expr\Variable Variable */
+    public $var;
+    /** @var null|Node\Expr Default value */
+    public $default;
+
+    /**
+     * Constructs a static variable node.
+     *
+     * @param Expr\Variable  $var         Name
+     * @param null|Node\Expr $default    Default value
+     * @param array          $attributes Additional attributes
+     */
+    public function __construct(
+        Expr\Variable $var, Node\Expr $default = null, array $attributes = []
+    ) {
+        $this->attributes = $attributes;
+        $this->var = $var;
+        $this->default = $default;
+    }
+
+    public function getSubNodeNames() : array {
+        return ['var', 'default'];
+    }
+    
+    public function getType() : string {
+        return 'Stmt_StaticVar';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Static_.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Static_.php
new file mode 100644
index 0000000000000000000000000000000000000000..464898ffa66d5cd459a172f0434a2045178cd70b
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Static_.php
@@ -0,0 +1,30 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node\Stmt;
+
+use PhpParser\Node\Stmt;
+
+class Static_ extends Stmt
+{
+    /** @var StaticVar[] Variable definitions */
+    public $vars;
+
+    /**
+     * Constructs a static variables list node.
+     *
+     * @param StaticVar[] $vars       Variable definitions
+     * @param array       $attributes Additional attributes
+     */
+    public function __construct(array $vars, array $attributes = []) {
+        $this->attributes = $attributes;
+        $this->vars = $vars;
+    }
+
+    public function getSubNodeNames() : array {
+        return ['vars'];
+    }
+    
+    public function getType() : string {
+        return 'Stmt_Static';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Switch_.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Switch_.php
new file mode 100644
index 0000000000000000000000000000000000000000..2c8dae02215ed88ba7d918c5d3125df768748cca
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Switch_.php
@@ -0,0 +1,34 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node\Stmt;
+
+use PhpParser\Node;
+
+class Switch_ extends Node\Stmt
+{
+    /** @var Node\Expr Condition */
+    public $cond;
+    /** @var Case_[] Case list */
+    public $cases;
+
+    /**
+     * Constructs a case node.
+     *
+     * @param Node\Expr $cond       Condition
+     * @param Case_[]   $cases      Case list
+     * @param array     $attributes Additional attributes
+     */
+    public function __construct(Node\Expr $cond, array $cases, array $attributes = []) {
+        $this->attributes = $attributes;
+        $this->cond = $cond;
+        $this->cases = $cases;
+    }
+
+    public function getSubNodeNames() : array {
+        return ['cond', 'cases'];
+    }
+    
+    public function getType() : string {
+        return 'Stmt_Switch';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Throw_.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Throw_.php
new file mode 100644
index 0000000000000000000000000000000000000000..a34e2b362437f8ffc4ec9be123ca59fab938a142
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Throw_.php
@@ -0,0 +1,30 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node\Stmt;
+
+use PhpParser\Node;
+
+class Throw_ extends Node\Stmt
+{
+    /** @var Node\Expr Expression */
+    public $expr;
+
+    /**
+     * Constructs a legacy throw statement node.
+     *
+     * @param Node\Expr $expr       Expression
+     * @param array     $attributes Additional attributes
+     */
+    public function __construct(Node\Expr $expr, array $attributes = []) {
+        $this->attributes = $attributes;
+        $this->expr = $expr;
+    }
+
+    public function getSubNodeNames() : array {
+        return ['expr'];
+    }
+    
+    public function getType() : string {
+        return 'Stmt_Throw';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/TraitUse.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/TraitUse.php
new file mode 100644
index 0000000000000000000000000000000000000000..9e97053b40fe5df46c460a03f885763241874a30
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/TraitUse.php
@@ -0,0 +1,34 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node\Stmt;
+
+use PhpParser\Node;
+
+class TraitUse extends Node\Stmt
+{
+    /** @var Node\Name[] Traits */
+    public $traits;
+    /** @var TraitUseAdaptation[] Adaptations */
+    public $adaptations;
+
+    /**
+     * Constructs a trait use node.
+     *
+     * @param Node\Name[]          $traits      Traits
+     * @param TraitUseAdaptation[] $adaptations Adaptations
+     * @param array                $attributes  Additional attributes
+     */
+    public function __construct(array $traits, array $adaptations = [], array $attributes = []) {
+        $this->attributes = $attributes;
+        $this->traits = $traits;
+        $this->adaptations = $adaptations;
+    }
+
+    public function getSubNodeNames() : array {
+        return ['traits', 'adaptations'];
+    }
+    
+    public function getType() : string {
+        return 'Stmt_TraitUse';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/TraitUseAdaptation.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/TraitUseAdaptation.php
new file mode 100644
index 0000000000000000000000000000000000000000..8bdd2c041f582f2df42727cdc3d634d4f731b023
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/TraitUseAdaptation.php
@@ -0,0 +1,13 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node\Stmt;
+
+use PhpParser\Node;
+
+abstract class TraitUseAdaptation extends Node\Stmt
+{
+    /** @var Node\Name|null Trait name */
+    public $trait;
+    /** @var Node\Identifier Method name */
+    public $method;
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/TraitUseAdaptation/Alias.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/TraitUseAdaptation/Alias.php
new file mode 100644
index 0000000000000000000000000000000000000000..a3bccbd10c5ad70c847c3d6c9c9f379731c04e93
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/TraitUseAdaptation/Alias.php
@@ -0,0 +1,38 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node\Stmt\TraitUseAdaptation;
+
+use PhpParser\Node;
+
+class Alias extends Node\Stmt\TraitUseAdaptation
+{
+    /** @var null|int New modifier */
+    public $newModifier;
+    /** @var null|Node\Identifier New name */
+    public $newName;
+
+    /**
+     * Constructs a trait use precedence adaptation node.
+     *
+     * @param null|Node\Name              $trait       Trait name
+     * @param string|Node\Identifier      $method      Method name
+     * @param null|int                    $newModifier New modifier
+     * @param null|string|Node\Identifier $newName     New name
+     * @param array                       $attributes  Additional attributes
+     */
+    public function __construct($trait, $method, $newModifier, $newName, array $attributes = []) {
+        $this->attributes = $attributes;
+        $this->trait = $trait;
+        $this->method = \is_string($method) ? new Node\Identifier($method) : $method;
+        $this->newModifier = $newModifier;
+        $this->newName = \is_string($newName) ? new Node\Identifier($newName) : $newName;
+    }
+
+    public function getSubNodeNames() : array {
+        return ['trait', 'method', 'newModifier', 'newName'];
+    }
+    
+    public function getType() : string {
+        return 'Stmt_TraitUseAdaptation_Alias';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/TraitUseAdaptation/Precedence.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/TraitUseAdaptation/Precedence.php
new file mode 100644
index 0000000000000000000000000000000000000000..80385f64e32b3ce98168e98736abd26749db4906
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/TraitUseAdaptation/Precedence.php
@@ -0,0 +1,34 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node\Stmt\TraitUseAdaptation;
+
+use PhpParser\Node;
+
+class Precedence extends Node\Stmt\TraitUseAdaptation
+{
+    /** @var Node\Name[] Overwritten traits */
+    public $insteadof;
+
+    /**
+     * Constructs a trait use precedence adaptation node.
+     *
+     * @param Node\Name              $trait       Trait name
+     * @param string|Node\Identifier $method      Method name
+     * @param Node\Name[]            $insteadof   Overwritten traits
+     * @param array                  $attributes  Additional attributes
+     */
+    public function __construct(Node\Name $trait, $method, array $insteadof, array $attributes = []) {
+        $this->attributes = $attributes;
+        $this->trait = $trait;
+        $this->method = \is_string($method) ? new Node\Identifier($method) : $method;
+        $this->insteadof = $insteadof;
+    }
+
+    public function getSubNodeNames() : array {
+        return ['trait', 'method', 'insteadof'];
+    }
+    
+    public function getType() : string {
+        return 'Stmt_TraitUseAdaptation_Precedence';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Trait_.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Trait_.php
new file mode 100644
index 0000000000000000000000000000000000000000..0cec203ac71bf0a718e07facc0dcafed396a78c6
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Trait_.php
@@ -0,0 +1,32 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node\Stmt;
+
+use PhpParser\Node;
+
+class Trait_ extends ClassLike
+{
+    /**
+     * Constructs a trait node.
+     *
+     * @param string|Node\Identifier $name Name
+     * @param array  $subNodes   Array of the following optional subnodes:
+     *                           'stmts'      => array(): Statements
+     *                           'attrGroups' => array(): PHP attribute groups
+     * @param array  $attributes Additional attributes
+     */
+    public function __construct($name, array $subNodes = [], array $attributes = []) {
+        $this->attributes = $attributes;
+        $this->name = \is_string($name) ? new Node\Identifier($name) : $name;
+        $this->stmts = $subNodes['stmts'] ?? [];
+        $this->attrGroups = $subNodes['attrGroups'] ?? [];
+    }
+
+    public function getSubNodeNames() : array {
+        return ['attrGroups', 'name', 'stmts'];
+    }
+
+    public function getType() : string {
+        return 'Stmt_Trait';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/TryCatch.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/TryCatch.php
new file mode 100644
index 0000000000000000000000000000000000000000..7fc158c570b5b32c2d61933e2a9605d6709b3150
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/TryCatch.php
@@ -0,0 +1,38 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node\Stmt;
+
+use PhpParser\Node;
+
+class TryCatch extends Node\Stmt
+{
+    /** @var Node\Stmt[] Statements */
+    public $stmts;
+    /** @var Catch_[] Catches */
+    public $catches;
+    /** @var null|Finally_ Optional finally node */
+    public $finally;
+
+    /**
+     * Constructs a try catch node.
+     *
+     * @param Node\Stmt[]   $stmts      Statements
+     * @param Catch_[]      $catches    Catches
+     * @param null|Finally_ $finally    Optional finally node
+     * @param array         $attributes Additional attributes
+     */
+    public function __construct(array $stmts, array $catches, Finally_ $finally = null, array $attributes = []) {
+        $this->attributes = $attributes;
+        $this->stmts = $stmts;
+        $this->catches = $catches;
+        $this->finally = $finally;
+    }
+
+    public function getSubNodeNames() : array {
+        return ['stmts', 'catches', 'finally'];
+    }
+
+    public function getType() : string {
+        return 'Stmt_TryCatch';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Unset_.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Unset_.php
new file mode 100644
index 0000000000000000000000000000000000000000..310e427aa201f4d283f17b6e60adf9270ea41df1
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Unset_.php
@@ -0,0 +1,30 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node\Stmt;
+
+use PhpParser\Node;
+
+class Unset_ extends Node\Stmt
+{
+    /** @var Node\Expr[] Variables to unset */
+    public $vars;
+
+    /**
+     * Constructs an unset node.
+     *
+     * @param Node\Expr[] $vars       Variables to unset
+     * @param array       $attributes Additional attributes
+     */
+    public function __construct(array $vars, array $attributes = []) {
+        $this->attributes = $attributes;
+        $this->vars = $vars;
+    }
+
+    public function getSubNodeNames() : array {
+        return ['vars'];
+    }
+    
+    public function getType() : string {
+        return 'Stmt_Unset';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/UseUse.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/UseUse.php
new file mode 100644
index 0000000000000000000000000000000000000000..32bd7847da42a0c477003cbb28ebe6587a92a9cf
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/UseUse.php
@@ -0,0 +1,52 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node\Stmt;
+
+use PhpParser\Node;
+use PhpParser\Node\Identifier;
+
+class UseUse extends Node\Stmt
+{
+    /** @var int One of the Stmt\Use_::TYPE_* constants. Will only differ from TYPE_UNKNOWN for mixed group uses */
+    public $type;
+    /** @var Node\Name Namespace, class, function or constant to alias */
+    public $name;
+    /** @var Identifier|null Alias */
+    public $alias;
+
+    /**
+     * Constructs an alias (use) node.
+     *
+     * @param Node\Name              $name       Namespace/Class to alias
+     * @param null|string|Identifier $alias      Alias
+     * @param int                    $type       Type of the use element (for mixed group use only)
+     * @param array                  $attributes Additional attributes
+     */
+    public function __construct(Node\Name $name, $alias = null, int $type = Use_::TYPE_UNKNOWN, array $attributes = []) {
+        $this->attributes = $attributes;
+        $this->type = $type;
+        $this->name = $name;
+        $this->alias = \is_string($alias) ? new Identifier($alias) : $alias;
+    }
+
+    public function getSubNodeNames() : array {
+        return ['type', 'name', 'alias'];
+    }
+
+    /**
+     * Get alias. If not explicitly given this is the last component of the used name.
+     *
+     * @return Identifier
+     */
+    public function getAlias() : Identifier {
+        if (null !== $this->alias) {
+            return $this->alias;
+        }
+
+        return new Identifier($this->name->getLast());
+    }
+    
+    public function getType() : string {
+        return 'Stmt_UseUse';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Use_.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Use_.php
new file mode 100644
index 0000000000000000000000000000000000000000..8753da313dd588bbe981f80c846e49dd52a14dd3
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Use_.php
@@ -0,0 +1,47 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node\Stmt;
+
+use PhpParser\Node\Stmt;
+
+class Use_ extends Stmt
+{
+    /**
+     * Unknown type. Both Stmt\Use_ / Stmt\GroupUse and Stmt\UseUse have a $type property, one of them will always be
+     * TYPE_UNKNOWN while the other has one of the three other possible types. For normal use statements the type on the
+     * Stmt\UseUse is unknown. It's only the other way around for mixed group use declarations.
+     */
+    const TYPE_UNKNOWN = 0;
+    /** Class or namespace import */
+    const TYPE_NORMAL = 1;
+    /** Function import */
+    const TYPE_FUNCTION = 2;
+    /** Constant import */
+    const TYPE_CONSTANT = 3;
+
+    /** @var int Type of alias */
+    public $type;
+    /** @var UseUse[] Aliases */
+    public $uses;
+
+    /**
+     * Constructs an alias (use) list node.
+     *
+     * @param UseUse[] $uses       Aliases
+     * @param int      $type       Type of alias
+     * @param array    $attributes Additional attributes
+     */
+    public function __construct(array $uses, int $type = self::TYPE_NORMAL, array $attributes = []) {
+        $this->attributes = $attributes;
+        $this->type = $type;
+        $this->uses = $uses;
+    }
+
+    public function getSubNodeNames() : array {
+        return ['type', 'uses'];
+    }
+    
+    public function getType() : string {
+        return 'Stmt_Use';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/While_.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/While_.php
new file mode 100644
index 0000000000000000000000000000000000000000..f41034f8c24b624f3a53e8af4559a5ec908e12e7
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/While_.php
@@ -0,0 +1,34 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node\Stmt;
+
+use PhpParser\Node;
+
+class While_ extends Node\Stmt
+{
+    /** @var Node\Expr Condition */
+    public $cond;
+    /** @var Node\Stmt[] Statements */
+    public $stmts;
+
+    /**
+     * Constructs a while node.
+     *
+     * @param Node\Expr   $cond       Condition
+     * @param Node\Stmt[] $stmts      Statements
+     * @param array       $attributes Additional attributes
+     */
+    public function __construct(Node\Expr $cond, array $stmts = [], array $attributes = []) {
+        $this->attributes = $attributes;
+        $this->cond = $cond;
+        $this->stmts = $stmts;
+    }
+
+    public function getSubNodeNames() : array {
+        return ['cond', 'stmts'];
+    }
+    
+    public function getType() : string {
+        return 'Stmt_While';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/UnionType.php b/vendor/nikic/php-parser/lib/PhpParser/Node/UnionType.php
new file mode 100644
index 0000000000000000000000000000000000000000..c8f45235d6c627d0244eabc2674c231003e43662
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/UnionType.php
@@ -0,0 +1,30 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node;
+
+use PhpParser\NodeAbstract;
+
+class UnionType extends NodeAbstract
+{
+    /** @var (Identifier|Name)[] Types */
+    public $types;
+
+    /**
+     * Constructs a union type.
+     *
+     * @param (Identifier|Name)[] $types      Types
+     * @param array               $attributes Additional attributes
+     */
+    public function __construct(array $types, array $attributes = []) {
+        $this->attributes = $attributes;
+        $this->types = $types;
+    }
+
+    public function getSubNodeNames() : array {
+        return ['types'];
+    }
+    
+    public function getType() : string {
+        return 'UnionType';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/VarLikeIdentifier.php b/vendor/nikic/php-parser/lib/PhpParser/Node/VarLikeIdentifier.php
new file mode 100644
index 0000000000000000000000000000000000000000..a30807a6d58237f802f1768810ae5fc016de4357
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Node/VarLikeIdentifier.php
@@ -0,0 +1,17 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Node;
+
+/**
+ * Represents a name that is written in source code with a leading dollar,
+ * but is not a proper variable. The leading dollar is not stored as part of the name.
+ *
+ * Examples: Names in property declarations are formatted as variables. Names in static property
+ * lookups are also formatted as variables.
+ */
+class VarLikeIdentifier extends Identifier
+{
+    public function getType() : string {
+        return 'VarLikeIdentifier';
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/NodeAbstract.php b/vendor/nikic/php-parser/lib/PhpParser/NodeAbstract.php
new file mode 100644
index 0000000000000000000000000000000000000000..04514da116ce25961fb73f86a6f66eff85ef65ad
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/NodeAbstract.php
@@ -0,0 +1,178 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser;
+
+abstract class NodeAbstract implements Node, \JsonSerializable
+{
+    protected $attributes;
+
+    /**
+     * Creates a Node.
+     *
+     * @param array $attributes Array of attributes
+     */
+    public function __construct(array $attributes = []) {
+        $this->attributes = $attributes;
+    }
+
+    /**
+     * Gets line the node started in (alias of getStartLine).
+     *
+     * @return int Start line (or -1 if not available)
+     */
+    public function getLine() : int {
+        return $this->attributes['startLine'] ?? -1;
+    }
+
+    /**
+     * Gets line the node started in.
+     *
+     * Requires the 'startLine' attribute to be enabled in the lexer (enabled by default).
+     *
+     * @return int Start line (or -1 if not available)
+     */
+    public function getStartLine() : int {
+        return $this->attributes['startLine'] ?? -1;
+    }
+
+    /**
+     * Gets the line the node ended in.
+     *
+     * Requires the 'endLine' attribute to be enabled in the lexer (enabled by default).
+     *
+     * @return int End line (or -1 if not available)
+     */
+    public function getEndLine() : int {
+        return $this->attributes['endLine'] ?? -1;
+    }
+
+    /**
+     * Gets the token offset of the first token that is part of this node.
+     *
+     * The offset is an index into the array returned by Lexer::getTokens().
+     *
+     * Requires the 'startTokenPos' attribute to be enabled in the lexer (DISABLED by default).
+     *
+     * @return int Token start position (or -1 if not available)
+     */
+    public function getStartTokenPos() : int {
+        return $this->attributes['startTokenPos'] ?? -1;
+    }
+
+    /**
+     * Gets the token offset of the last token that is part of this node.
+     *
+     * The offset is an index into the array returned by Lexer::getTokens().
+     *
+     * Requires the 'endTokenPos' attribute to be enabled in the lexer (DISABLED by default).
+     *
+     * @return int Token end position (or -1 if not available)
+     */
+    public function getEndTokenPos() : int {
+        return $this->attributes['endTokenPos'] ?? -1;
+    }
+
+    /**
+     * Gets the file offset of the first character that is part of this node.
+     *
+     * Requires the 'startFilePos' attribute to be enabled in the lexer (DISABLED by default).
+     *
+     * @return int File start position (or -1 if not available)
+     */
+    public function getStartFilePos() : int {
+        return $this->attributes['startFilePos'] ?? -1;
+    }
+
+    /**
+     * Gets the file offset of the last character that is part of this node.
+     *
+     * Requires the 'endFilePos' attribute to be enabled in the lexer (DISABLED by default).
+     *
+     * @return int File end position (or -1 if not available)
+     */
+    public function getEndFilePos() : int {
+        return $this->attributes['endFilePos'] ?? -1;
+    }
+
+    /**
+     * Gets all comments directly preceding this node.
+     *
+     * The comments are also available through the "comments" attribute.
+     *
+     * @return Comment[]
+     */
+    public function getComments() : array {
+        return $this->attributes['comments'] ?? [];
+    }
+
+    /**
+     * Gets the doc comment of the node.
+     *
+     * @return null|Comment\Doc Doc comment object or null
+     */
+    public function getDocComment() {
+        $comments = $this->getComments();
+        for ($i = count($comments) - 1; $i >= 0; $i--) {
+            $comment = $comments[$i];
+            if ($comment instanceof Comment\Doc) {
+                return $comment;
+            }
+        }
+
+        return null;
+    }
+
+    /**
+     * Sets the doc comment of the node.
+     *
+     * This will either replace an existing doc comment or add it to the comments array.
+     *
+     * @param Comment\Doc $docComment Doc comment to set
+     */
+    public function setDocComment(Comment\Doc $docComment) {
+        $comments = $this->getComments();
+        for ($i = count($comments) - 1; $i >= 0; $i--) {
+            if ($comments[$i] instanceof Comment\Doc) {
+                // Replace existing doc comment.
+                $comments[$i] = $docComment;
+                $this->setAttribute('comments', $comments);
+                return;
+            }
+        }
+
+        // Append new doc comment.
+        $comments[] = $docComment;
+        $this->setAttribute('comments', $comments);
+    }
+
+    public function setAttribute(string $key, $value) {
+        $this->attributes[$key] = $value;
+    }
+
+    public function hasAttribute(string $key) : bool {
+        return array_key_exists($key, $this->attributes);
+    }
+
+    public function getAttribute(string $key, $default = null) {
+        if (array_key_exists($key, $this->attributes)) {
+            return $this->attributes[$key];
+        }
+
+        return $default;
+    }
+
+    public function getAttributes() : array {
+        return $this->attributes;
+    }
+
+    public function setAttributes(array $attributes) {
+        $this->attributes = $attributes;
+    }
+
+    /**
+     * @return array
+     */
+    public function jsonSerialize() : array {
+        return ['nodeType' => $this->getType()] + get_object_vars($this);
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/NodeDumper.php b/vendor/nikic/php-parser/lib/PhpParser/NodeDumper.php
new file mode 100644
index 0000000000000000000000000000000000000000..197ebc144cad3fc6c3102fbc22740ee4f03814a7
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/NodeDumper.php
@@ -0,0 +1,203 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser;
+
+use PhpParser\Node\Expr\Include_;
+use PhpParser\Node\Stmt\Class_;
+use PhpParser\Node\Stmt\GroupUse;
+use PhpParser\Node\Stmt\Use_;
+use PhpParser\Node\Stmt\UseUse;
+
+class NodeDumper
+{
+    private $dumpComments;
+    private $dumpPositions;
+    private $code;
+
+    /**
+     * Constructs a NodeDumper.
+     *
+     * Supported options:
+     *  * bool dumpComments: Whether comments should be dumped.
+     *  * bool dumpPositions: Whether line/offset information should be dumped. To dump offset
+     *                        information, the code needs to be passed to dump().
+     *
+     * @param array $options Options (see description)
+     */
+    public function __construct(array $options = []) {
+        $this->dumpComments = !empty($options['dumpComments']);
+        $this->dumpPositions = !empty($options['dumpPositions']);
+    }
+
+    /**
+     * Dumps a node or array.
+     *
+     * @param array|Node  $node Node or array to dump
+     * @param string|null $code Code corresponding to dumped AST. This only needs to be passed if
+     *                          the dumpPositions option is enabled and the dumping of node offsets
+     *                          is desired.
+     *
+     * @return string Dumped value
+     */
+    public function dump($node, string $code = null) : string {
+        $this->code = $code;
+        return $this->dumpRecursive($node);
+    }
+
+    protected function dumpRecursive($node) {
+        if ($node instanceof Node) {
+            $r = $node->getType();
+            if ($this->dumpPositions && null !== $p = $this->dumpPosition($node)) {
+                $r .= $p;
+            }
+            $r .= '(';
+
+            foreach ($node->getSubNodeNames() as $key) {
+                $r .= "\n    " . $key . ': ';
+
+                $value = $node->$key;
+                if (null === $value) {
+                    $r .= 'null';
+                } elseif (false === $value) {
+                    $r .= 'false';
+                } elseif (true === $value) {
+                    $r .= 'true';
+                } elseif (is_scalar($value)) {
+                    if ('flags' === $key || 'newModifier' === $key) {
+                        $r .= $this->dumpFlags($value);
+                    } elseif ('type' === $key && $node instanceof Include_) {
+                        $r .= $this->dumpIncludeType($value);
+                    } elseif ('type' === $key
+                            && ($node instanceof Use_ || $node instanceof UseUse || $node instanceof GroupUse)) {
+                        $r .= $this->dumpUseType($value);
+                    } else {
+                        $r .= $value;
+                    }
+                } else {
+                    $r .= str_replace("\n", "\n    ", $this->dumpRecursive($value));
+                }
+            }
+
+            if ($this->dumpComments && $comments = $node->getComments()) {
+                $r .= "\n    comments: " . str_replace("\n", "\n    ", $this->dumpRecursive($comments));
+            }
+        } elseif (is_array($node)) {
+            $r = 'array(';
+
+            foreach ($node as $key => $value) {
+                $r .= "\n    " . $key . ': ';
+
+                if (null === $value) {
+                    $r .= 'null';
+                } elseif (false === $value) {
+                    $r .= 'false';
+                } elseif (true === $value) {
+                    $r .= 'true';
+                } elseif (is_scalar($value)) {
+                    $r .= $value;
+                } else {
+                    $r .= str_replace("\n", "\n    ", $this->dumpRecursive($value));
+                }
+            }
+        } elseif ($node instanceof Comment) {
+            return $node->getReformattedText();
+        } else {
+            throw new \InvalidArgumentException('Can only dump nodes and arrays.');
+        }
+
+        return $r . "\n)";
+    }
+
+    protected function dumpFlags($flags) {
+        $strs = [];
+        if ($flags & Class_::MODIFIER_PUBLIC) {
+            $strs[] = 'MODIFIER_PUBLIC';
+        }
+        if ($flags & Class_::MODIFIER_PROTECTED) {
+            $strs[] = 'MODIFIER_PROTECTED';
+        }
+        if ($flags & Class_::MODIFIER_PRIVATE) {
+            $strs[] = 'MODIFIER_PRIVATE';
+        }
+        if ($flags & Class_::MODIFIER_ABSTRACT) {
+            $strs[] = 'MODIFIER_ABSTRACT';
+        }
+        if ($flags & Class_::MODIFIER_STATIC) {
+            $strs[] = 'MODIFIER_STATIC';
+        }
+        if ($flags & Class_::MODIFIER_FINAL) {
+            $strs[] = 'MODIFIER_FINAL';
+        }
+
+        if ($strs) {
+            return implode(' | ', $strs) . ' (' . $flags . ')';
+        } else {
+            return $flags;
+        }
+    }
+
+    protected function dumpIncludeType($type) {
+        $map = [
+            Include_::TYPE_INCLUDE      => 'TYPE_INCLUDE',
+            Include_::TYPE_INCLUDE_ONCE => 'TYPE_INCLUDE_ONCE',
+            Include_::TYPE_REQUIRE      => 'TYPE_REQUIRE',
+            Include_::TYPE_REQUIRE_ONCE => 'TYPE_REQUIRE_ONCE',
+        ];
+
+        if (!isset($map[$type])) {
+            return $type;
+        }
+        return $map[$type] . ' (' . $type . ')';
+    }
+
+    protected function dumpUseType($type) {
+        $map = [
+            Use_::TYPE_UNKNOWN  => 'TYPE_UNKNOWN',
+            Use_::TYPE_NORMAL   => 'TYPE_NORMAL',
+            Use_::TYPE_FUNCTION => 'TYPE_FUNCTION',
+            Use_::TYPE_CONSTANT => 'TYPE_CONSTANT',
+        ];
+
+        if (!isset($map[$type])) {
+            return $type;
+        }
+        return $map[$type] . ' (' . $type . ')';
+    }
+
+    /**
+     * Dump node position, if possible.
+     *
+     * @param Node $node Node for which to dump position
+     *
+     * @return string|null Dump of position, or null if position information not available
+     */
+    protected function dumpPosition(Node $node) {
+        if (!$node->hasAttribute('startLine') || !$node->hasAttribute('endLine')) {
+            return null;
+        }
+
+        $start = $node->getStartLine();
+        $end = $node->getEndLine();
+        if ($node->hasAttribute('startFilePos') && $node->hasAttribute('endFilePos')
+            && null !== $this->code
+        ) {
+            $start .= ':' . $this->toColumn($this->code, $node->getStartFilePos());
+            $end .= ':' . $this->toColumn($this->code, $node->getEndFilePos());
+        }
+        return "[$start - $end]";
+    }
+
+    // Copied from Error class
+    private function toColumn($code, $pos) {
+        if ($pos > strlen($code)) {
+            throw new \RuntimeException('Invalid position information');
+        }
+
+        $lineStartPos = strrpos($code, "\n", $pos - strlen($code));
+        if (false === $lineStartPos) {
+            $lineStartPos = -1;
+        }
+
+        return $pos - $lineStartPos;
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/NodeFinder.php b/vendor/nikic/php-parser/lib/PhpParser/NodeFinder.php
new file mode 100644
index 0000000000000000000000000000000000000000..2e7cfdad4dc982a76cf1e622a4bff25d5cdf0b7b
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/NodeFinder.php
@@ -0,0 +1,81 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser;
+
+use PhpParser\NodeVisitor\FindingVisitor;
+use PhpParser\NodeVisitor\FirstFindingVisitor;
+
+class NodeFinder
+{
+    /**
+     * Find all nodes satisfying a filter callback.
+     *
+     * @param Node|Node[] $nodes  Single node or array of nodes to search in
+     * @param callable    $filter Filter callback: function(Node $node) : bool
+     *
+     * @return Node[] Found nodes satisfying the filter callback
+     */
+    public function find($nodes, callable $filter) : array {
+        if (!is_array($nodes)) {
+            $nodes = [$nodes];
+        }
+
+        $visitor = new FindingVisitor($filter);
+
+        $traverser = new NodeTraverser;
+        $traverser->addVisitor($visitor);
+        $traverser->traverse($nodes);
+
+        return $visitor->getFoundNodes();
+    }
+
+    /**
+     * Find all nodes that are instances of a certain class.
+     *
+     * @param Node|Node[] $nodes Single node or array of nodes to search in
+     * @param string      $class Class name
+     *
+     * @return Node[] Found nodes (all instances of $class)
+     */
+    public function findInstanceOf($nodes, string $class) : array {
+        return $this->find($nodes, function ($node) use ($class) {
+            return $node instanceof $class;
+        });
+    }
+
+    /**
+     * Find first node satisfying a filter callback.
+     *
+     * @param Node|Node[] $nodes  Single node or array of nodes to search in
+     * @param callable    $filter Filter callback: function(Node $node) : bool
+     *
+     * @return null|Node Found node (or null if none found)
+     */
+    public function findFirst($nodes, callable $filter) {
+        if (!is_array($nodes)) {
+            $nodes = [$nodes];
+        }
+
+        $visitor = new FirstFindingVisitor($filter);
+
+        $traverser = new NodeTraverser;
+        $traverser->addVisitor($visitor);
+        $traverser->traverse($nodes);
+
+        return $visitor->getFoundNode();
+    }
+
+    /**
+     * Find first node that is an instance of a certain class.
+     *
+     * @param Node|Node[] $nodes  Single node or array of nodes to search in
+     * @param string      $class Class name
+     *
+     * @return null|Node Found node, which is an instance of $class (or null if none found)
+     */
+    public function findFirstInstanceOf($nodes, string $class) {
+        return $this->findFirst($nodes, function ($node) use ($class) {
+            return $node instanceof $class;
+        });
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/NodeTraverser.php b/vendor/nikic/php-parser/lib/PhpParser/NodeTraverser.php
new file mode 100644
index 0000000000000000000000000000000000000000..97d45bdaaa7c95ba7ecdae9580a83e3239732bd1
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/NodeTraverser.php
@@ -0,0 +1,291 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser;
+
+class NodeTraverser implements NodeTraverserInterface
+{
+    /**
+     * If NodeVisitor::enterNode() returns DONT_TRAVERSE_CHILDREN, child nodes
+     * of the current node will not be traversed for any visitors.
+     *
+     * For subsequent visitors enterNode() will still be called on the current
+     * node and leaveNode() will also be invoked for the current node.
+     */
+    const DONT_TRAVERSE_CHILDREN = 1;
+
+    /**
+     * If NodeVisitor::enterNode() or NodeVisitor::leaveNode() returns
+     * STOP_TRAVERSAL, traversal is aborted.
+     *
+     * The afterTraverse() method will still be invoked.
+     */
+    const STOP_TRAVERSAL = 2;
+
+    /**
+     * If NodeVisitor::leaveNode() returns REMOVE_NODE for a node that occurs
+     * in an array, it will be removed from the array.
+     *
+     * For subsequent visitors leaveNode() will still be invoked for the
+     * removed node.
+     */
+    const REMOVE_NODE = 3;
+
+    /**
+     * If NodeVisitor::enterNode() returns DONT_TRAVERSE_CURRENT_AND_CHILDREN, child nodes
+     * of the current node will not be traversed for any visitors.
+     *
+     * For subsequent visitors enterNode() will not be called as well.
+     * leaveNode() will be invoked for visitors that has enterNode() method invoked.
+     */
+    const DONT_TRAVERSE_CURRENT_AND_CHILDREN = 4;
+
+    /** @var NodeVisitor[] Visitors */
+    protected $visitors = [];
+
+    /** @var bool Whether traversal should be stopped */
+    protected $stopTraversal;
+
+    public function __construct() {
+        // for BC
+    }
+
+    /**
+     * Adds a visitor.
+     *
+     * @param NodeVisitor $visitor Visitor to add
+     */
+    public function addVisitor(NodeVisitor $visitor) {
+        $this->visitors[] = $visitor;
+    }
+
+    /**
+     * Removes an added visitor.
+     *
+     * @param NodeVisitor $visitor
+     */
+    public function removeVisitor(NodeVisitor $visitor) {
+        foreach ($this->visitors as $index => $storedVisitor) {
+            if ($storedVisitor === $visitor) {
+                unset($this->visitors[$index]);
+                break;
+            }
+        }
+    }
+
+    /**
+     * Traverses an array of nodes using the registered visitors.
+     *
+     * @param Node[] $nodes Array of nodes
+     *
+     * @return Node[] Traversed array of nodes
+     */
+    public function traverse(array $nodes) : array {
+        $this->stopTraversal = false;
+
+        foreach ($this->visitors as $visitor) {
+            if (null !== $return = $visitor->beforeTraverse($nodes)) {
+                $nodes = $return;
+            }
+        }
+
+        $nodes = $this->traverseArray($nodes);
+
+        foreach ($this->visitors as $visitor) {
+            if (null !== $return = $visitor->afterTraverse($nodes)) {
+                $nodes = $return;
+            }
+        }
+
+        return $nodes;
+    }
+
+    /**
+     * Recursively traverse a node.
+     *
+     * @param Node $node Node to traverse.
+     *
+     * @return Node Result of traversal (may be original node or new one)
+     */
+    protected function traverseNode(Node $node) : Node {
+        foreach ($node->getSubNodeNames() as $name) {
+            $subNode =& $node->$name;
+
+            if (\is_array($subNode)) {
+                $subNode = $this->traverseArray($subNode);
+                if ($this->stopTraversal) {
+                    break;
+                }
+            } elseif ($subNode instanceof Node) {
+                $traverseChildren = true;
+                $breakVisitorIndex = null;
+
+                foreach ($this->visitors as $visitorIndex => $visitor) {
+                    $return = $visitor->enterNode($subNode);
+                    if (null !== $return) {
+                        if ($return instanceof Node) {
+                            $this->ensureReplacementReasonable($subNode, $return);
+                            $subNode = $return;
+                        } elseif (self::DONT_TRAVERSE_CHILDREN === $return) {
+                            $traverseChildren = false;
+                        } elseif (self::DONT_TRAVERSE_CURRENT_AND_CHILDREN === $return) {
+                            $traverseChildren = false;
+                            $breakVisitorIndex = $visitorIndex;
+                            break;
+                        } elseif (self::STOP_TRAVERSAL === $return) {
+                            $this->stopTraversal = true;
+                            break 2;
+                        } else {
+                            throw new \LogicException(
+                                'enterNode() returned invalid value of type ' . gettype($return)
+                            );
+                        }
+                    }
+                }
+
+                if ($traverseChildren) {
+                    $subNode = $this->traverseNode($subNode);
+                    if ($this->stopTraversal) {
+                        break;
+                    }
+                }
+
+                foreach ($this->visitors as $visitorIndex => $visitor) {
+                    $return = $visitor->leaveNode($subNode);
+
+                    if (null !== $return) {
+                        if ($return instanceof Node) {
+                            $this->ensureReplacementReasonable($subNode, $return);
+                            $subNode = $return;
+                        } elseif (self::STOP_TRAVERSAL === $return) {
+                            $this->stopTraversal = true;
+                            break 2;
+                        } elseif (\is_array($return)) {
+                            throw new \LogicException(
+                                'leaveNode() may only return an array ' .
+                                'if the parent structure is an array'
+                            );
+                        } else {
+                            throw new \LogicException(
+                                'leaveNode() returned invalid value of type ' . gettype($return)
+                            );
+                        }
+                    }
+
+                    if ($breakVisitorIndex === $visitorIndex) {
+                        break;
+                    }
+                }
+            }
+        }
+
+        return $node;
+    }
+
+    /**
+     * Recursively traverse array (usually of nodes).
+     *
+     * @param array $nodes Array to traverse
+     *
+     * @return array Result of traversal (may be original array or changed one)
+     */
+    protected function traverseArray(array $nodes) : array {
+        $doNodes = [];
+
+        foreach ($nodes as $i => &$node) {
+            if ($node instanceof Node) {
+                $traverseChildren = true;
+                $breakVisitorIndex = null;
+
+                foreach ($this->visitors as $visitorIndex => $visitor) {
+                    $return = $visitor->enterNode($node);
+                    if (null !== $return) {
+                        if ($return instanceof Node) {
+                            $this->ensureReplacementReasonable($node, $return);
+                            $node = $return;
+                        } elseif (self::DONT_TRAVERSE_CHILDREN === $return) {
+                            $traverseChildren = false;
+                        } elseif (self::DONT_TRAVERSE_CURRENT_AND_CHILDREN === $return) {
+                            $traverseChildren = false;
+                            $breakVisitorIndex = $visitorIndex;
+                            break;
+                        } elseif (self::STOP_TRAVERSAL === $return) {
+                            $this->stopTraversal = true;
+                            break 2;
+                        } else {
+                            throw new \LogicException(
+                                'enterNode() returned invalid value of type ' . gettype($return)
+                            );
+                        }
+                    }
+                }
+
+                if ($traverseChildren) {
+                    $node = $this->traverseNode($node);
+                    if ($this->stopTraversal) {
+                        break;
+                    }
+                }
+
+                foreach ($this->visitors as $visitorIndex => $visitor) {
+                    $return = $visitor->leaveNode($node);
+
+                    if (null !== $return) {
+                        if ($return instanceof Node) {
+                            $this->ensureReplacementReasonable($node, $return);
+                            $node = $return;
+                        } elseif (\is_array($return)) {
+                            $doNodes[] = [$i, $return];
+                            break;
+                        } elseif (self::REMOVE_NODE === $return) {
+                            $doNodes[] = [$i, []];
+                            break;
+                        } elseif (self::STOP_TRAVERSAL === $return) {
+                            $this->stopTraversal = true;
+                            break 2;
+                        } elseif (false === $return) {
+                            throw new \LogicException(
+                                'bool(false) return from leaveNode() no longer supported. ' .
+                                'Return NodeTraverser::REMOVE_NODE instead'
+                            );
+                        } else {
+                            throw new \LogicException(
+                                'leaveNode() returned invalid value of type ' . gettype($return)
+                            );
+                        }
+                    }
+
+                    if ($breakVisitorIndex === $visitorIndex) {
+                        break;
+                    }
+                }
+            } elseif (\is_array($node)) {
+                throw new \LogicException('Invalid node structure: Contains nested arrays');
+            }
+        }
+
+        if (!empty($doNodes)) {
+            while (list($i, $replace) = array_pop($doNodes)) {
+                array_splice($nodes, $i, 1, $replace);
+            }
+        }
+
+        return $nodes;
+    }
+
+    private function ensureReplacementReasonable($old, $new) {
+        if ($old instanceof Node\Stmt && $new instanceof Node\Expr) {
+            throw new \LogicException(
+                "Trying to replace statement ({$old->getType()}) " .
+                "with expression ({$new->getType()}). Are you missing a " .
+                "Stmt_Expression wrapper?"
+            );
+        }
+
+        if ($old instanceof Node\Expr && $new instanceof Node\Stmt) {
+            throw new \LogicException(
+                "Trying to replace expression ({$old->getType()}) " .
+                "with statement ({$new->getType()})"
+            );
+        }
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/NodeTraverserInterface.php b/vendor/nikic/php-parser/lib/PhpParser/NodeTraverserInterface.php
new file mode 100644
index 0000000000000000000000000000000000000000..77ff3d27f65c61f555f75fc9595b172fae2b2165
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/NodeTraverserInterface.php
@@ -0,0 +1,29 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser;
+
+interface NodeTraverserInterface
+{
+    /**
+     * Adds a visitor.
+     *
+     * @param NodeVisitor $visitor Visitor to add
+     */
+    public function addVisitor(NodeVisitor $visitor);
+
+    /**
+     * Removes an added visitor.
+     *
+     * @param NodeVisitor $visitor
+     */
+    public function removeVisitor(NodeVisitor $visitor);
+
+    /**
+     * Traverses an array of nodes using the registered visitors.
+     *
+     * @param Node[] $nodes Array of nodes
+     *
+     * @return Node[] Traversed array of nodes
+     */
+    public function traverse(array $nodes) : array;
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/NodeVisitor.php b/vendor/nikic/php-parser/lib/PhpParser/NodeVisitor.php
new file mode 100644
index 0000000000000000000000000000000000000000..f1f7f3e3e34e0ed1fb84be2da83d4ad480a9e9b4
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/NodeVisitor.php
@@ -0,0 +1,72 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser;
+
+interface NodeVisitor
+{
+    /**
+     * Called once before traversal.
+     *
+     * Return value semantics:
+     *  * null:      $nodes stays as-is
+     *  * otherwise: $nodes is set to the return value
+     *
+     * @param Node[] $nodes Array of nodes
+     *
+     * @return null|Node[] Array of nodes
+     */
+    public function beforeTraverse(array $nodes);
+
+    /**
+     * Called when entering a node.
+     *
+     * Return value semantics:
+     *  * null
+     *        => $node stays as-is
+     *  * NodeTraverser::DONT_TRAVERSE_CHILDREN
+     *        => Children of $node are not traversed. $node stays as-is
+     *  * NodeTraverser::STOP_TRAVERSAL
+     *        => Traversal is aborted. $node stays as-is
+     *  * otherwise
+     *        => $node is set to the return value
+     *
+     * @param Node $node Node
+     *
+     * @return null|int|Node Replacement node (or special return value)
+     */
+    public function enterNode(Node $node);
+
+    /**
+     * Called when leaving a node.
+     *
+     * Return value semantics:
+     *  * null
+     *        => $node stays as-is
+     *  * NodeTraverser::REMOVE_NODE
+     *        => $node is removed from the parent array
+     *  * NodeTraverser::STOP_TRAVERSAL
+     *        => Traversal is aborted. $node stays as-is
+     *  * array (of Nodes)
+     *        => The return value is merged into the parent array (at the position of the $node)
+     *  * otherwise
+     *        => $node is set to the return value
+     *
+     * @param Node $node Node
+     *
+     * @return null|int|Node|Node[] Replacement node (or special return value)
+     */
+    public function leaveNode(Node $node);
+
+    /**
+     * Called once after traversal.
+     *
+     * Return value semantics:
+     *  * null:      $nodes stays as-is
+     *  * otherwise: $nodes is set to the return value
+     *
+     * @param Node[] $nodes Array of nodes
+     *
+     * @return null|Node[] Array of nodes
+     */
+    public function afterTraverse(array $nodes);
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/NodeVisitor/CloningVisitor.php b/vendor/nikic/php-parser/lib/PhpParser/NodeVisitor/CloningVisitor.php
new file mode 100644
index 0000000000000000000000000000000000000000..a85fa493b099c89ee024a987880175dd694458f4
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/NodeVisitor/CloningVisitor.php
@@ -0,0 +1,20 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\NodeVisitor;
+
+use PhpParser\Node;
+use PhpParser\NodeVisitorAbstract;
+
+/**
+ * Visitor cloning all nodes and linking to the original nodes using an attribute.
+ *
+ * This visitor is required to perform format-preserving pretty prints.
+ */
+class CloningVisitor extends NodeVisitorAbstract
+{
+    public function enterNode(Node $origNode) {
+        $node = clone $origNode;
+        $node->setAttribute('origNode', $origNode);
+        return $node;
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/NodeVisitor/FindingVisitor.php b/vendor/nikic/php-parser/lib/PhpParser/NodeVisitor/FindingVisitor.php
new file mode 100644
index 0000000000000000000000000000000000000000..9531edbce7c4dcbf3e6206444a20676e24c3acab
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/NodeVisitor/FindingVisitor.php
@@ -0,0 +1,48 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\NodeVisitor;
+
+use PhpParser\Node;
+use PhpParser\NodeVisitorAbstract;
+
+/**
+ * This visitor can be used to find and collect all nodes satisfying some criterion determined by
+ * a filter callback.
+ */
+class FindingVisitor extends NodeVisitorAbstract
+{
+    /** @var callable Filter callback */
+    protected $filterCallback;
+    /** @var Node[] Found nodes */
+    protected $foundNodes;
+
+    public function __construct(callable $filterCallback) {
+        $this->filterCallback = $filterCallback;
+    }
+
+    /**
+     * Get found nodes satisfying the filter callback.
+     *
+     * Nodes are returned in pre-order.
+     *
+     * @return Node[] Found nodes
+     */
+    public function getFoundNodes() : array {
+        return $this->foundNodes;
+    }
+
+    public function beforeTraverse(array $nodes) {
+        $this->foundNodes = [];
+
+        return null;
+    }
+
+    public function enterNode(Node $node) {
+        $filterCallback = $this->filterCallback;
+        if ($filterCallback($node)) {
+            $this->foundNodes[] = $node;
+        }
+
+        return null;
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/NodeVisitor/FirstFindingVisitor.php b/vendor/nikic/php-parser/lib/PhpParser/NodeVisitor/FirstFindingVisitor.php
new file mode 100644
index 0000000000000000000000000000000000000000..596a7d7fd5b33f69c338f4ed08708517bfd8dd96
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/NodeVisitor/FirstFindingVisitor.php
@@ -0,0 +1,50 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\NodeVisitor;
+
+use PhpParser\Node;
+use PhpParser\NodeTraverser;
+use PhpParser\NodeVisitorAbstract;
+
+/**
+ * This visitor can be used to find the first node satisfying some criterion determined by
+ * a filter callback.
+ */
+class FirstFindingVisitor extends NodeVisitorAbstract
+{
+    /** @var callable Filter callback */
+    protected $filterCallback;
+    /** @var null|Node Found node */
+    protected $foundNode;
+
+    public function __construct(callable $filterCallback) {
+        $this->filterCallback = $filterCallback;
+    }
+
+    /**
+     * Get found node satisfying the filter callback.
+     *
+     * Returns null if no node satisfies the filter callback.
+     *
+     * @return null|Node Found node (or null if not found)
+     */
+    public function getFoundNode() {
+        return $this->foundNode;
+    }
+
+    public function beforeTraverse(array $nodes) {
+        $this->foundNode = null;
+
+        return null;
+    }
+
+    public function enterNode(Node $node) {
+        $filterCallback = $this->filterCallback;
+        if ($filterCallback($node)) {
+            $this->foundNode = $node;
+            return NodeTraverser::STOP_TRAVERSAL;
+        }
+
+        return null;
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/NodeVisitor/NameResolver.php b/vendor/nikic/php-parser/lib/PhpParser/NodeVisitor/NameResolver.php
new file mode 100644
index 0000000000000000000000000000000000000000..c55532a5eae24c6734360a3c437e7cbfe1599f07
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/NodeVisitor/NameResolver.php
@@ -0,0 +1,246 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\NodeVisitor;
+
+use PhpParser\ErrorHandler;
+use PhpParser\NameContext;
+use PhpParser\Node;
+use PhpParser\Node\Expr;
+use PhpParser\Node\Name;
+use PhpParser\Node\Name\FullyQualified;
+use PhpParser\Node\Stmt;
+use PhpParser\NodeVisitorAbstract;
+
+class NameResolver extends NodeVisitorAbstract
+{
+    /** @var NameContext Naming context */
+    protected $nameContext;
+
+    /** @var bool Whether to preserve original names */
+    protected $preserveOriginalNames;
+
+    /** @var bool Whether to replace resolved nodes in place, or to add resolvedNode attributes */
+    protected $replaceNodes;
+
+    /**
+     * Constructs a name resolution visitor.
+     *
+     * Options:
+     *  * preserveOriginalNames (default false): An "originalName" attribute will be added to
+     *    all name nodes that underwent resolution.
+     *  * replaceNodes (default true): Resolved names are replaced in-place. Otherwise, a
+     *    resolvedName attribute is added. (Names that cannot be statically resolved receive a
+     *    namespacedName attribute, as usual.)
+     *
+     * @param ErrorHandler|null $errorHandler Error handler
+     * @param array $options Options
+     */
+    public function __construct(ErrorHandler $errorHandler = null, array $options = []) {
+        $this->nameContext = new NameContext($errorHandler ?? new ErrorHandler\Throwing);
+        $this->preserveOriginalNames = $options['preserveOriginalNames'] ?? false;
+        $this->replaceNodes = $options['replaceNodes'] ?? true;
+    }
+
+    /**
+     * Get name resolution context.
+     *
+     * @return NameContext
+     */
+    public function getNameContext() : NameContext {
+        return $this->nameContext;
+    }
+
+    public function beforeTraverse(array $nodes) {
+        $this->nameContext->startNamespace();
+        return null;
+    }
+
+    public function enterNode(Node $node) {
+        if ($node instanceof Stmt\Namespace_) {
+            $this->nameContext->startNamespace($node->name);
+        } elseif ($node instanceof Stmt\Use_) {
+            foreach ($node->uses as $use) {
+                $this->addAlias($use, $node->type, null);
+            }
+        } elseif ($node instanceof Stmt\GroupUse) {
+            foreach ($node->uses as $use) {
+                $this->addAlias($use, $node->type, $node->prefix);
+            }
+        } elseif ($node instanceof Stmt\Class_) {
+            if (null !== $node->extends) {
+                $node->extends = $this->resolveClassName($node->extends);
+            }
+
+            foreach ($node->implements as &$interface) {
+                $interface = $this->resolveClassName($interface);
+            }
+
+            $this->resolveAttrGroups($node);
+            if (null !== $node->name) {
+                $this->addNamespacedName($node);
+            }
+        } elseif ($node instanceof Stmt\Interface_) {
+            foreach ($node->extends as &$interface) {
+                $interface = $this->resolveClassName($interface);
+            }
+
+            $this->resolveAttrGroups($node);
+            $this->addNamespacedName($node);
+        } elseif ($node instanceof Stmt\Trait_) {
+            $this->resolveAttrGroups($node);
+            $this->addNamespacedName($node);
+        } elseif ($node instanceof Stmt\Function_) {
+            $this->resolveSignature($node);
+            $this->resolveAttrGroups($node);
+            $this->addNamespacedName($node);
+        } elseif ($node instanceof Stmt\ClassMethod
+                  || $node instanceof Expr\Closure
+                  || $node instanceof Expr\ArrowFunction
+        ) {
+            $this->resolveSignature($node);
+            $this->resolveAttrGroups($node);
+        } elseif ($node instanceof Stmt\Property) {
+            if (null !== $node->type) {
+                $node->type = $this->resolveType($node->type);
+            }
+            $this->resolveAttrGroups($node);
+        } elseif ($node instanceof Stmt\Const_) {
+            foreach ($node->consts as $const) {
+                $this->addNamespacedName($const);
+            }
+        } else if ($node instanceof Stmt\ClassConst) {
+            $this->resolveAttrGroups($node);
+        } elseif ($node instanceof Expr\StaticCall
+                  || $node instanceof Expr\StaticPropertyFetch
+                  || $node instanceof Expr\ClassConstFetch
+                  || $node instanceof Expr\New_
+                  || $node instanceof Expr\Instanceof_
+        ) {
+            if ($node->class instanceof Name) {
+                $node->class = $this->resolveClassName($node->class);
+            }
+        } elseif ($node instanceof Stmt\Catch_) {
+            foreach ($node->types as &$type) {
+                $type = $this->resolveClassName($type);
+            }
+        } elseif ($node instanceof Expr\FuncCall) {
+            if ($node->name instanceof Name) {
+                $node->name = $this->resolveName($node->name, Stmt\Use_::TYPE_FUNCTION);
+            }
+        } elseif ($node instanceof Expr\ConstFetch) {
+            $node->name = $this->resolveName($node->name, Stmt\Use_::TYPE_CONSTANT);
+        } elseif ($node instanceof Stmt\TraitUse) {
+            foreach ($node->traits as &$trait) {
+                $trait = $this->resolveClassName($trait);
+            }
+
+            foreach ($node->adaptations as $adaptation) {
+                if (null !== $adaptation->trait) {
+                    $adaptation->trait = $this->resolveClassName($adaptation->trait);
+                }
+
+                if ($adaptation instanceof Stmt\TraitUseAdaptation\Precedence) {
+                    foreach ($adaptation->insteadof as &$insteadof) {
+                        $insteadof = $this->resolveClassName($insteadof);
+                    }
+                }
+            }
+        }
+
+        return null;
+    }
+
+    private function addAlias(Stmt\UseUse $use, $type, Name $prefix = null) {
+        // Add prefix for group uses
+        $name = $prefix ? Name::concat($prefix, $use->name) : $use->name;
+        // Type is determined either by individual element or whole use declaration
+        $type |= $use->type;
+
+        $this->nameContext->addAlias(
+            $name, (string) $use->getAlias(), $type, $use->getAttributes()
+        );
+    }
+
+    /** @param Stmt\Function_|Stmt\ClassMethod|Expr\Closure $node */
+    private function resolveSignature($node) {
+        foreach ($node->params as $param) {
+            $param->type = $this->resolveType($param->type);
+            $this->resolveAttrGroups($param);
+        }
+        $node->returnType = $this->resolveType($node->returnType);
+    }
+
+    private function resolveType($node) {
+        if ($node instanceof Name) {
+            return $this->resolveClassName($node);
+        }
+        if ($node instanceof Node\NullableType) {
+            $node->type = $this->resolveType($node->type);
+            return $node;
+        }
+        if ($node instanceof Node\UnionType) {
+            foreach ($node->types as &$type) {
+                $type = $this->resolveType($type);
+            }
+            return $node;
+        }
+        return $node;
+    }
+
+    /**
+     * Resolve name, according to name resolver options.
+     *
+     * @param Name $name Function or constant name to resolve
+     * @param int  $type One of Stmt\Use_::TYPE_*
+     *
+     * @return Name Resolved name, or original name with attribute
+     */
+    protected function resolveName(Name $name, int $type) : Name {
+        if (!$this->replaceNodes) {
+            $resolvedName = $this->nameContext->getResolvedName($name, $type);
+            if (null !== $resolvedName) {
+                $name->setAttribute('resolvedName', $resolvedName);
+            } else {
+                $name->setAttribute('namespacedName', FullyQualified::concat(
+                    $this->nameContext->getNamespace(), $name, $name->getAttributes()));
+            }
+            return $name;
+        }
+
+        if ($this->preserveOriginalNames) {
+            // Save the original name
+            $originalName = $name;
+            $name = clone $originalName;
+            $name->setAttribute('originalName', $originalName);
+        }
+
+        $resolvedName = $this->nameContext->getResolvedName($name, $type);
+        if (null !== $resolvedName) {
+            return $resolvedName;
+        }
+
+        // unqualified names inside a namespace cannot be resolved at compile-time
+        // add the namespaced version of the name as an attribute
+        $name->setAttribute('namespacedName', FullyQualified::concat(
+            $this->nameContext->getNamespace(), $name, $name->getAttributes()));
+        return $name;
+    }
+
+    protected function resolveClassName(Name $name) {
+        return $this->resolveName($name, Stmt\Use_::TYPE_NORMAL);
+    }
+
+    protected function addNamespacedName(Node $node) {
+        $node->namespacedName = Name::concat(
+            $this->nameContext->getNamespace(), (string) $node->name);
+    }
+
+    protected function resolveAttrGroups(Node $node)
+    {
+        foreach ($node->attrGroups as $attrGroup) {
+            foreach ($attrGroup->attrs as $attr) {
+                $attr->name = $this->resolveClassName($attr->name);
+            }
+        }
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/NodeVisitor/NodeConnectingVisitor.php b/vendor/nikic/php-parser/lib/PhpParser/NodeVisitor/NodeConnectingVisitor.php
new file mode 100644
index 0000000000000000000000000000000000000000..ea372e5b991c3e601c20d2fd7ccbe40469179a2a
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/NodeVisitor/NodeConnectingVisitor.php
@@ -0,0 +1,52 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\NodeVisitor;
+
+use PhpParser\Node;
+use PhpParser\NodeVisitorAbstract;
+
+/**
+ * Visitor that connects a child node to its parent node
+ * as well as its sibling nodes.
+ *
+ * On the child node, the parent node can be accessed through
+ * <code>$node->getAttribute('parent')</code>, the previous
+ * node can be accessed through <code>$node->getAttribute('previous')</code>,
+ * and the next node can be accessed through <code>$node->getAttribute('next')</code>.
+ */
+final class NodeConnectingVisitor extends NodeVisitorAbstract
+{
+    /**
+     * @var Node[]
+     */
+    private $stack = [];
+
+    /**
+     * @var ?Node
+     */
+    private $previous;
+
+    public function beforeTraverse(array $nodes) {
+        $this->stack    = [];
+        $this->previous = null;
+    }
+
+    public function enterNode(Node $node) {
+        if (!empty($this->stack)) {
+            $node->setAttribute('parent', $this->stack[count($this->stack) - 1]);
+        }
+
+        if ($this->previous !== null && $this->previous->getAttribute('parent') === $node->getAttribute('parent')) {
+            $node->setAttribute('previous', $this->previous);
+            $this->previous->setAttribute('next', $node);
+        }
+
+        $this->stack[] = $node;
+    }
+
+    public function leaveNode(Node $node) {
+        $this->previous = $node;
+
+        array_pop($this->stack);
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/NodeVisitor/ParentConnectingVisitor.php b/vendor/nikic/php-parser/lib/PhpParser/NodeVisitor/ParentConnectingVisitor.php
new file mode 100644
index 0000000000000000000000000000000000000000..b98d2bfa6fc3c271150e94981c7248061b6504c6
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/NodeVisitor/ParentConnectingVisitor.php
@@ -0,0 +1,41 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\NodeVisitor;
+
+use function array_pop;
+use function count;
+use PhpParser\Node;
+use PhpParser\NodeVisitorAbstract;
+
+/**
+ * Visitor that connects a child node to its parent node.
+ *
+ * On the child node, the parent node can be accessed through
+ * <code>$node->getAttribute('parent')</code>.
+ */
+final class ParentConnectingVisitor extends NodeVisitorAbstract
+{
+    /**
+     * @var Node[]
+     */
+    private $stack = [];
+
+    public function beforeTraverse(array $nodes)
+    {
+        $this->stack = [];
+    }
+
+    public function enterNode(Node $node)
+    {
+        if (!empty($this->stack)) {
+            $node->setAttribute('parent', $this->stack[count($this->stack) - 1]);
+        }
+
+        $this->stack[] = $node;
+    }
+
+    public function leaveNode(Node $node)
+    {
+        array_pop($this->stack);
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/NodeVisitorAbstract.php b/vendor/nikic/php-parser/lib/PhpParser/NodeVisitorAbstract.php
new file mode 100644
index 0000000000000000000000000000000000000000..d378d6709628e4df1e216af18423d6960ab3644c
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/NodeVisitorAbstract.php
@@ -0,0 +1,25 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser;
+
+/**
+ * @codeCoverageIgnore
+ */
+class NodeVisitorAbstract implements NodeVisitor
+{
+    public function beforeTraverse(array $nodes) {
+        return null;
+    }
+
+    public function enterNode(Node $node) {
+        return null;
+    }
+
+    public function leaveNode(Node $node) {
+        return null;
+    }
+
+    public function afterTraverse(array $nodes) {
+        return null;
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Parser.php b/vendor/nikic/php-parser/lib/PhpParser/Parser.php
new file mode 100644
index 0000000000000000000000000000000000000000..8956c767187d317be1fc4621794e5d7ba30a7d0a
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Parser.php
@@ -0,0 +1,18 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser;
+
+interface Parser
+{
+    /**
+     * Parses PHP code into a node tree.
+     *
+     * @param string $code The source code to parse
+     * @param ErrorHandler|null $errorHandler Error handler to use for lexer/parser errors, defaults
+     *                                        to ErrorHandler\Throwing.
+     *
+     * @return Node\Stmt[]|null Array of statements (or null non-throwing error handler is used and
+     *                          the parser was unable to recover from an error).
+     */
+    public function parse(string $code, ErrorHandler $errorHandler = null);
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Parser/Multiple.php b/vendor/nikic/php-parser/lib/PhpParser/Parser/Multiple.php
new file mode 100644
index 0000000000000000000000000000000000000000..77fd1f3fbb63ce9fda87dc1a340a378f71209830
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Parser/Multiple.php
@@ -0,0 +1,55 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\Parser;
+
+use PhpParser\Error;
+use PhpParser\ErrorHandler;
+use PhpParser\Parser;
+
+class Multiple implements Parser
+{
+    /** @var Parser[] List of parsers to try, in order of preference */
+    private $parsers;
+
+    /**
+     * Create a parser which will try multiple parsers in an order of preference.
+     *
+     * Parsers will be invoked in the order they're provided to the constructor. If one of the
+     * parsers runs without throwing, it's output is returned. Otherwise the exception that the
+     * first parser generated is thrown.
+     *
+     * @param Parser[] $parsers
+     */
+    public function __construct(array $parsers) {
+        $this->parsers = $parsers;
+    }
+
+    public function parse(string $code, ErrorHandler $errorHandler = null) {
+        if (null === $errorHandler) {
+            $errorHandler = new ErrorHandler\Throwing;
+        }
+
+        list($firstStmts, $firstError) = $this->tryParse($this->parsers[0], $errorHandler, $code);
+        if ($firstError === null) {
+            return $firstStmts;
+        }
+
+        for ($i = 1, $c = count($this->parsers); $i < $c; ++$i) {
+            list($stmts, $error) = $this->tryParse($this->parsers[$i], $errorHandler, $code);
+            if ($error === null) {
+                return $stmts;
+            }
+        }
+
+        throw $firstError;
+    }
+
+    private function tryParse(Parser $parser, ErrorHandler $errorHandler, $code) {
+        $stmts = null;
+        $error = null;
+        try {
+            $stmts = $parser->parse($code, $errorHandler);
+        } catch (Error $error) {}
+        return [$stmts, $error];
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Parser/Php5.php b/vendor/nikic/php-parser/lib/PhpParser/Parser/Php5.php
new file mode 100644
index 0000000000000000000000000000000000000000..c67a5e707a0f2001d9d09f8d99c104c6abf723fc
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Parser/Php5.php
@@ -0,0 +1,2629 @@
+<?php
+
+namespace PhpParser\Parser;
+
+use PhpParser\Error;
+use PhpParser\Node;
+use PhpParser\Node\Expr;
+use PhpParser\Node\Name;
+use PhpParser\Node\Scalar;
+use PhpParser\Node\Stmt;
+
+/* This is an automatically GENERATED file, which should not be manually edited.
+ * Instead edit one of the following:
+ *  * the grammar files grammar/php5.y or grammar/php7.y
+ *  * the skeleton file grammar/parser.template
+ *  * the preprocessing script grammar/rebuildParsers.php
+ */
+class Php5 extends \PhpParser\ParserAbstract
+{
+    protected $tokenToSymbolMapSize = 392;
+    protected $actionTableSize = 1069;
+    protected $gotoTableSize = 580;
+
+    protected $invalidSymbol = 165;
+    protected $errorSymbol = 1;
+    protected $defaultAction = -32766;
+    protected $unexpectedTokenRule = 32767;
+
+    protected $YY2TBLSTATE = 405;
+    protected $numNonLeafStates = 658;
+
+    protected $symbolToName = array(
+        "EOF",
+        "error",
+        "T_THROW",
+        "T_INCLUDE",
+        "T_INCLUDE_ONCE",
+        "T_EVAL",
+        "T_REQUIRE",
+        "T_REQUIRE_ONCE",
+        "','",
+        "T_LOGICAL_OR",
+        "T_LOGICAL_XOR",
+        "T_LOGICAL_AND",
+        "T_PRINT",
+        "T_YIELD",
+        "T_DOUBLE_ARROW",
+        "T_YIELD_FROM",
+        "'='",
+        "T_PLUS_EQUAL",
+        "T_MINUS_EQUAL",
+        "T_MUL_EQUAL",
+        "T_DIV_EQUAL",
+        "T_CONCAT_EQUAL",
+        "T_MOD_EQUAL",
+        "T_AND_EQUAL",
+        "T_OR_EQUAL",
+        "T_XOR_EQUAL",
+        "T_SL_EQUAL",
+        "T_SR_EQUAL",
+        "T_POW_EQUAL",
+        "T_COALESCE_EQUAL",
+        "'?'",
+        "':'",
+        "T_COALESCE",
+        "T_BOOLEAN_OR",
+        "T_BOOLEAN_AND",
+        "'|'",
+        "'^'",
+        "'&'",
+        "T_IS_EQUAL",
+        "T_IS_NOT_EQUAL",
+        "T_IS_IDENTICAL",
+        "T_IS_NOT_IDENTICAL",
+        "T_SPACESHIP",
+        "'<'",
+        "T_IS_SMALLER_OR_EQUAL",
+        "'>'",
+        "T_IS_GREATER_OR_EQUAL",
+        "T_SL",
+        "T_SR",
+        "'+'",
+        "'-'",
+        "'.'",
+        "'*'",
+        "'/'",
+        "'%'",
+        "'!'",
+        "T_INSTANCEOF",
+        "'~'",
+        "T_INC",
+        "T_DEC",
+        "T_INT_CAST",
+        "T_DOUBLE_CAST",
+        "T_STRING_CAST",
+        "T_ARRAY_CAST",
+        "T_OBJECT_CAST",
+        "T_BOOL_CAST",
+        "T_UNSET_CAST",
+        "'@'",
+        "T_POW",
+        "'['",
+        "T_NEW",
+        "T_CLONE",
+        "T_EXIT",
+        "T_IF",
+        "T_ELSEIF",
+        "T_ELSE",
+        "T_ENDIF",
+        "T_LNUMBER",
+        "T_DNUMBER",
+        "T_STRING",
+        "T_STRING_VARNAME",
+        "T_VARIABLE",
+        "T_NUM_STRING",
+        "T_INLINE_HTML",
+        "T_ENCAPSED_AND_WHITESPACE",
+        "T_CONSTANT_ENCAPSED_STRING",
+        "T_ECHO",
+        "T_DO",
+        "T_WHILE",
+        "T_ENDWHILE",
+        "T_FOR",
+        "T_ENDFOR",
+        "T_FOREACH",
+        "T_ENDFOREACH",
+        "T_DECLARE",
+        "T_ENDDECLARE",
+        "T_AS",
+        "T_SWITCH",
+        "T_MATCH",
+        "T_ENDSWITCH",
+        "T_CASE",
+        "T_DEFAULT",
+        "T_BREAK",
+        "T_CONTINUE",
+        "T_GOTO",
+        "T_FUNCTION",
+        "T_FN",
+        "T_CONST",
+        "T_RETURN",
+        "T_TRY",
+        "T_CATCH",
+        "T_FINALLY",
+        "T_USE",
+        "T_INSTEADOF",
+        "T_GLOBAL",
+        "T_STATIC",
+        "T_ABSTRACT",
+        "T_FINAL",
+        "T_PRIVATE",
+        "T_PROTECTED",
+        "T_PUBLIC",
+        "T_VAR",
+        "T_UNSET",
+        "T_ISSET",
+        "T_EMPTY",
+        "T_HALT_COMPILER",
+        "T_CLASS",
+        "T_TRAIT",
+        "T_INTERFACE",
+        "T_EXTENDS",
+        "T_IMPLEMENTS",
+        "T_OBJECT_OPERATOR",
+        "T_LIST",
+        "T_ARRAY",
+        "T_CALLABLE",
+        "T_CLASS_C",
+        "T_TRAIT_C",
+        "T_METHOD_C",
+        "T_FUNC_C",
+        "T_LINE",
+        "T_FILE",
+        "T_START_HEREDOC",
+        "T_END_HEREDOC",
+        "T_DOLLAR_OPEN_CURLY_BRACES",
+        "T_CURLY_OPEN",
+        "T_PAAMAYIM_NEKUDOTAYIM",
+        "T_NAMESPACE",
+        "T_NS_C",
+        "T_DIR",
+        "T_NS_SEPARATOR",
+        "T_ELLIPSIS",
+        "T_NAME_FULLY_QUALIFIED",
+        "T_NAME_QUALIFIED",
+        "T_NAME_RELATIVE",
+        "';'",
+        "'{'",
+        "'}'",
+        "'('",
+        "')'",
+        "'$'",
+        "'`'",
+        "']'",
+        "'\"'",
+        "T_NULLSAFE_OBJECT_OPERATOR",
+        "T_ATTRIBUTE"
+    );
+
+    protected $tokenToSymbol = array(
+            0,  165,  165,  165,  165,  165,  165,  165,  165,  165,
+          165,  165,  165,  165,  165,  165,  165,  165,  165,  165,
+          165,  165,  165,  165,  165,  165,  165,  165,  165,  165,
+          165,  165,  165,   55,  162,  165,  159,   54,   37,  165,
+          157,  158,   52,   49,    8,   50,   51,   53,  165,  165,
+          165,  165,  165,  165,  165,  165,  165,  165,   31,  154,
+           43,   16,   45,   30,   67,  165,  165,  165,  165,  165,
+          165,  165,  165,  165,  165,  165,  165,  165,  165,  165,
+          165,  165,  165,  165,  165,  165,  165,  165,  165,  165,
+          165,   69,  165,  161,   36,  165,  160,  165,  165,  165,
+          165,  165,  165,  165,  165,  165,  165,  165,  165,  165,
+          165,  165,  165,  165,  165,  165,  165,  165,  165,  165,
+          165,  165,  165,  155,   35,  156,   57,  165,  165,  165,
+          165,  165,  165,  165,  165,  165,  165,  165,  165,  165,
+          165,  165,  165,  165,  165,  165,  165,  165,  165,  165,
+          165,  165,  165,  165,  165,  165,  165,  165,  165,  165,
+          165,  165,  165,  165,  165,  165,  165,  165,  165,  165,
+          165,  165,  165,  165,  165,  165,  165,  165,  165,  165,
+          165,  165,  165,  165,  165,  165,  165,  165,  165,  165,
+          165,  165,  165,  165,  165,  165,  165,  165,  165,  165,
+          165,  165,  165,  165,  165,  165,  165,  165,  165,  165,
+          165,  165,  165,  165,  165,  165,  165,  165,  165,  165,
+          165,  165,  165,  165,  165,  165,  165,  165,  165,  165,
+          165,  165,  165,  165,  165,  165,  165,  165,  165,  165,
+          165,  165,  165,  165,  165,  165,  165,  165,  165,  165,
+          165,  165,  165,  165,  165,  165,    1,    2,    3,    4,
+            5,    6,    7,    9,   10,   11,   12,   13,   14,   15,
+           17,   18,   19,   20,   21,   22,   23,   24,   25,   26,
+           27,   28,   29,   32,   33,   34,   38,   39,   40,   41,
+           42,   44,   46,   47,   48,   56,   58,   59,   60,   61,
+           62,   63,   64,   65,   66,   68,   70,   71,   72,   73,
+           74,   75,   76,   77,   78,   79,   80,   81,   82,   83,
+           84,   85,   86,   87,   88,   89,   90,   91,   92,   93,
+           94,   95,   96,   97,   98,   99,  100,  101,  102,  103,
+          104,  105,  106,  107,  108,  109,  110,  111,  112,  113,
+          114,  115,  116,  117,  118,  119,  120,  121,  122,  123,
+          124,  125,  126,  127,  128,  129,  130,  131,  163,  132,
+          133,  134,  135,  136,  137,  138,  139,  140,  141,  142,
+          143,  144,  145,  146,  147,  148,  149,  150,  151,  152,
+          153,  164
+    );
+
+    protected $action = array(
+          693,  663,  664,  665,  666,  667,  282,  668,  669,  670,
+          706,  707,  221,  222,  223,  224,  225,  226,  227,  228,
+          229,    0,  230,  231,  232,  233,  234,  235,  236,  237,
+          238,  239,  240,  241,-32766,-32766,-32766,-32766,-32766,-32766,
+        -32766,-32766,-32767,-32767,-32767,-32767,   27,  242,  243,-32766,
+        -32766,-32766,-32766,-32766,  671,-32766,  333,-32766,-32766,-32766,
+        -32766,-32766,-32766,-32767,-32767,-32767,-32767,-32767,  672,  673,
+          674,  675,  676,  677,  678, 1034,  816,  740,  941,  942,
+          943,  940,  939,  938,  679,  680,  681,  682,  683,  684,
+          685,  686,  687,  688,  689,  709,  732,  710,  711,  712,
+          713,  701,  702,  703,  731,  704,  705,  690,  691,  692,
+          694,  695,  696,  734,  735,  736,  737,  738,  739,  697,
+          698,  699,  700,  730,  721,  719,  720,  716,  717,  437,
+          708,  714,  715,  722,  723,  725,  724,  726,  727,   55,
+           56,  417,   57,   58,  718,  729,  728,   28,   59,   60,
+         -220,   61,-32766,-32766,-32766,-32766,-32766,-32766,-32766,-32766,
+        -32766,   36,-32767,-32767,-32767,-32767, 1034,   35,  106,  107,
+          108,  109,  110,  111,  112,  113,  114,  115,  116,  117,
+          118,-32766,-32766,-32766,-32766,   62,   63, 1034,  125,  285,
+          292,   64,  748,   65,  290,  291,   66,   67,   68,   69,
+           70,   71,   72,   73,  763,   25,  298,   74,  409,  973,
+          975,  294,  294, 1086, 1087, 1064,  796,  748,  218,  219,
+          220,  465,-32766,-32766,-32766,  742,  864,  817,   54,  807,
+            9,-32766,-32766,-32766,  760,  320,  761,  410,   10,  202,
+          246,  428,  209,-32766,  933,-32766,-32766,-32766,-32766,-32766,
+        -32766,  488,-32766,  438,-32766,-32766,-32766,-32766,-32766,  473,
+          474,  941,  942,  943,  940,  939,  938,-32766,  475,  476,
+          337, 1092, 1093, 1094, 1095, 1089, 1090,  315, 1214, -255,
+          747, 1215, -505, 1096, 1091,  888,  889, 1066, 1065, 1067,
+          218,  219,  220,   41,  414,  337,  330,  895,  332,  418,
+         -126, -126, -126,   75,   52,  464,   -4,  817,   54,  805,
+         -224,  202,   40,   21,  419, -126,  466, -126,  467, -126,
+          468, -126,  359,  420,  128,  128,  748, 1171,   31,   32,
+          421,  422, 1034,  894,   33,  469,-32766,-32766,-32766, 1186,
+          351,  352,  470,  471,-32766,-32766,-32766,  309,  472,  865,
+          323,  788,  835,  423,  424,-32767,-32767,-32767,-32767,   97,
+           98,   99,  100,  101,  615,-32766,  313,-32766,-32766,-32766,
+        -32766,  354, 1185, 1171,  218,  219,  220,  475,  748,  418,
+          819,  629, -126,  297,  915,  464,  817,   54,-32766,  805,
+          124,  748,   40,   21,  419,  202,  466,   48,  467,  534,
+          468,  129,  429,  420,  337,  341,  888,  889,   31,   32,
+          421,  422,  416,  405,   33,  469,-32766,-32766,  311,  298,
+          351,  352,  470,  471,-32766,-32766,-32766,  748,  472,  412,
+          748,  752,  835,  423,  424,  338, 1066, 1065, 1067,  219,
+          220,  919, 1136,  296,   20,-32766,  576,-32766,-32766,-32766,
+          742,  341,  342,  413,  429, 1064,  337,  512,  418,  202,
+          819,  629,   -4, 1034,  464,  817,   54,   49,  805,  337,
+          762,   40,   21,  419,   51,  466, 1034,  467,  475,  468,
+          340,  748,  420,  120, -205, -205, -205,   31,   32,  421,
+          422, 1062,-32766,   33,  469,-32766,-32766,-32766,  744,  351,
+          352,  470,  471,  429, 1098,  337,  429,  472,  337, 1034,
+          788,  835,  423,  424,  415, 1098,-32766,  802,-32766,-32766,
+          102,  103,  104, 1137,  303,  202,  130, 1066, 1065, 1067,
+          337,  123,  239,  240,  241,  748,  105,  418, 1205,  819,
+          629, -205,  440,  464,-32766,-32766,-32766,  805,  242,  243,
+           40,   21,  419,  121,  466,  126,  467,  429,  468,  337,
+          122,  420, 1052, -204, -204, -204,   31,   32,  421,  422,
+         1034,  745,   33,  469,  220,  759,  817,   54,  351,  352,
+          470,  471,  218,  219,  220,  119,  472,  244,  127,  788,
+          835,  423,  424,  202,-32766,-32766,-32766,   30,  293,  803,
+           79,   80,   81,  202,  798,  210,  632,   99,  100,  101,
+          236,  237,  238,  817,   54,-32766,  211,  800,  819,  629,
+         -204,   34, 1034,   82,   83,   84,   85,   86,   87,   88,
+           89,   90,   91,   92,   93,   94,   95,   96,   97,   98,
+           99,  100,  101,  102,  103,  104,  286,  303,  418, 1034,
+          817,   54,-32766,-32766,  464,  218,  219,  220,  805,  105,
+          914,   40,   21,  419,   78,  466,  212,  467,  337,  468,
+          133,  247,  420,  295,  567,  248,  202,   31,   32,  421,
+          633,  242,  243,   33,  469,  418,  249,  817,   54,  351,
+          352,  464,  760,  -84,  761,  805,  310,  472,   40,   21,
+          419,-32766,  466,  640,  467,  643,  468,  447,   22,  420,
+          815,  452,  584,  132,   31,   32,  421,  637,  134,  364,
+           33,  469,  418,  303,  817,   54,  351,  352,  464,  819,
+          629,  828,  805,   43,  472,   40,   21,  419,   44,  466,
+           45,  467,   46,  468,  591,  592,  420,  753,  635,  930,
+          649,   31,   32,  421,  641,  918,  657,   33,  469,  418,
+          105,  817,   54,  351,  352,  464,  819,  629,   47,  805,
+           50,  472,   40,   21,  419,   53,  466,  131,  467,  298,
+          468,  599,  742,  420,-32766, -274,  516,  570,   31,   32,
+          421,  646,  748,  946,   33,  469,  418,  589,  436,-32766,
+          351,  352,  464,  819,  629,  623,  805,  836,  472,   40,
+           21,  419,  611,  466,  -82,  467,  603,  468,   11,  573,
+          420,  439,  456,  281,  318,   31,   32,  421,  588,  432,
+          321,   33,  469,  418, -414,  458,  322,  351,  352,  464,
+          851,  629,  837,  805, -505,  472,   40,   21,  419,  654,
+          466,   38,  467,   24,  468,    0,    0,  420,  319,    0,
+         -405,    0,   31,   32,  421,  245,  312,  314,   33,  469,
+         -506,    0,    0, 1097,  351,  352, 1143,  819,  629,    0,
+            0,  527,  472,  213,  214,    6,    7,   12,   14,  215,
+          363,  216, -415,  558,  789, -221,  830,    0,    0,  747,
+            0,    0,    0,  207,   39,  652,  653,  758,  806,  814,
+          793, 1086, 1087,  808,  819,  629,  213,  214,  867, 1088,
+          858,  859,  215,  791,  216,  852,  849,  847,  925,  926,
+          923,  813,  797,  799,  801,  804,  207,  922,  756,  757,
+          924,  287,   78,  331, 1086, 1087,  353,  630,  634,  636,
+          638,  639, 1088,  642,  644,  645,  647,  648,  631, 1142,
+         1211, 1213,  755,  834,  754,  833, 1212,  554,  832, 1092,
+         1093, 1094, 1095, 1089, 1090,  388, 1048,  824, 1036,  831,
+         1037, 1096, 1091,  822,  931,  856,  857,  451, 1210, 1179,
+            0,  217, 1177, 1162, 1175, 1077,  906, 1183, 1173,    0,
+          554,   26, 1092, 1093, 1094, 1095, 1089, 1090,  388,   29,
+           37,   42,   76,   77, 1096, 1091,  208,  284,  288,  289,
+          304,  305,  306,  307,  217,  335,  406,  408,    0, -220,
+           16,   17,   18,  383,  448,  455,  457,  462,  548,  620,
+         1039, 1042,  896, 1102, 1038, 1014,  559, 1013, 1079,    0,
+            0, -424, 1032,    0, 1043, 1045, 1044, 1047, 1046, 1061,
+         1176, 1161, 1157, 1174, 1076, 1208, 1103, 1156,  595
+    );
+
+    protected $actionCheck = array(
+            2,    3,    4,    5,    6,    7,   14,    9,   10,   11,
+           12,   13,   33,   34,   35,   36,   37,   38,   39,   40,
+           41,    0,   43,   44,   45,   46,   47,   48,   49,   50,
+           51,   52,   53,   54,    9,   10,   11,   33,   34,   35,
+           36,   37,   38,   39,   40,   41,    8,   68,   69,   33,
+           34,   35,   36,   37,   56,   30,    8,   32,   33,   34,
+           35,   36,   37,   38,   39,   40,   41,   42,   70,   71,
+           72,   73,   74,   75,   76,   13,    1,   79,  115,  116,
+          117,  118,  119,  120,   86,   87,   88,   89,   90,   91,
+           92,   93,   94,   95,   96,   97,   98,   99,  100,  101,
+          102,  103,  104,  105,  106,  107,  108,  109,  110,  111,
+          112,  113,  114,  115,  116,  117,  118,  119,  120,  121,
+          122,  123,  124,  125,  126,  127,  128,  129,  130,   31,
+          132,  133,  134,  135,  136,  137,  138,  139,  140,    3,
+            4,    5,    6,    7,  146,  147,  148,    8,   12,   13,
+          158,   15,   33,   34,   35,   36,   37,   38,   39,   40,
+           41,   14,   43,   44,   45,   46,   13,   16,   17,   18,
+           19,   20,   21,   22,   23,   24,   25,   26,   27,   28,
+           29,   33,   34,   35,   36,   49,   50,   13,    8,    8,
+           37,   55,   81,   57,   58,   59,   60,   61,   62,   63,
+           64,   65,   66,   67,  156,   69,   70,   71,   72,   58,
+           59,   37,   37,   77,   78,   79,  154,   81,    9,   10,
+           11,   85,    9,   10,   11,   79,   31,    1,    2,  154,
+          107,    9,   10,   11,  105,  112,  107,  126,    8,   30,
+           31,  105,    8,   30,  121,   32,   33,   34,   35,   36,
+           37,  115,   30,  155,   32,   33,   34,   35,   36,  123,
+          124,  115,  116,  117,  118,  119,  120,  115,  132,  133,
+          159,  135,  136,  137,  138,  139,  140,  141,   79,  156,
+          151,   82,  131,  147,  148,  133,  134,  151,  152,  153,
+            9,   10,   11,  157,    8,  159,  160,  158,  162,   73,
+           74,   75,   76,  150,   69,   79,    0,    1,    2,   83,
+          158,   30,   86,   87,   88,   89,   90,   91,   92,   93,
+           94,   95,    8,   97,  150,  150,   81,   81,  102,  103,
+          104,  105,   13,  158,  108,  109,    9,   10,   11,  158,
+          114,  115,  116,  117,    9,   10,   11,    8,  122,  154,
+            8,  125,  126,  127,  128,   43,   44,   45,   46,   47,
+           48,   49,   50,   51,   79,   30,  131,   32,   33,   34,
+           35,    8,    1,   81,    9,   10,   11,  132,   81,   73,
+          154,  155,  156,   37,  154,   79,    1,    2,  115,   83,
+          155,   81,   86,   87,   88,   30,   90,   69,   92,   80,
+           94,  155,  157,   97,  159,  159,  133,  134,  102,  103,
+          104,  105,    8,  107,  108,  109,    9,   10,  112,   70,
+          114,  115,  116,  117,    9,   10,   11,   81,  122,    8,
+           81,  125,  126,  127,  128,    8,  151,  152,  153,   10,
+           11,  156,  161,    8,  158,   30,   84,   32,   33,   34,
+           79,  159,  146,    8,  157,   79,  159,   84,   73,   30,
+          154,  155,  156,   13,   79,    1,    2,   69,   83,  159,
+          156,   86,   87,   88,   69,   90,   13,   92,  132,   94,
+           69,   81,   97,  155,   99,  100,  101,  102,  103,  104,
+          105,  115,    9,  108,  109,    9,   10,   11,   79,  114,
+          115,  116,  117,  157,  142,  159,  157,  122,  159,   13,
+          125,  126,  127,  128,    8,  142,   30,  154,   32,   33,
+           52,   53,   54,  158,   56,   30,  155,  151,  152,  153,
+          159,   14,   52,   53,   54,   81,   68,   73,   84,  154,
+          155,  156,  131,   79,   33,   34,   35,   83,   68,   69,
+           86,   87,   88,  155,   90,  155,   92,  157,   94,  159,
+          155,   97,  158,   99,  100,  101,  102,  103,  104,  105,
+           13,  152,  108,  109,   11,  154,    1,    2,  114,  115,
+          116,  117,    9,   10,   11,   16,  122,   14,   31,  125,
+          126,  127,  128,   30,    9,   10,   11,  143,  144,  154,
+            9,   10,   11,   30,  154,   16,   31,   49,   50,   51,
+           49,   50,   51,    1,    2,   30,   16,  154,  154,  155,
+          156,   30,   13,   32,   33,   34,   35,   36,   37,   38,
+           39,   40,   41,   42,   43,   44,   45,   46,   47,   48,
+           49,   50,   51,   52,   53,   54,   37,   56,   73,   13,
+            1,    2,   33,   34,   79,    9,   10,   11,   83,   68,
+          154,   86,   87,   88,  155,   90,   16,   92,  159,   94,
+          155,   16,   97,   37,  159,   16,   30,  102,  103,  104,
+           31,   68,   69,  108,  109,   73,   16,    1,    2,  114,
+          115,   79,  105,   31,  107,   83,   31,  122,   86,   87,
+           88,   33,   90,   31,   92,   31,   94,   74,   75,   97,
+           31,   74,   75,   31,  102,  103,  104,   31,  100,  101,
+          108,  109,   73,   56,    1,    2,  114,  115,   79,  154,
+          155,   37,   83,   69,  122,   86,   87,   88,   69,   90,
+           69,   92,   69,   94,  110,  111,   97,  154,  155,  154,
+          155,  102,  103,  104,   31,  154,  155,  108,  109,   73,
+           68,    1,    2,  114,  115,   79,  154,  155,   69,   83,
+           69,  122,   86,   87,   88,   69,   90,   69,   92,   70,
+           94,   76,   79,   97,   84,   81,   84,   89,  102,  103,
+          104,   31,   81,   81,  108,  109,   73,  112,   88,  115,
+          114,  115,   79,  154,  155,   91,   83,  126,  122,   86,
+           87,   88,   93,   90,   96,   92,   95,   94,   96,   99,
+           97,   96,   96,   96,  129,  102,  103,  104,   99,  105,
+          113,  108,  109,   73,  145,  105,  129,  114,  115,   79,
+          154,  155,  126,   83,  131,  122,   86,   87,   88,  156,
+           90,  154,   92,  157,   94,   -1,   -1,   97,  130,   -1,
+          145,   -1,  102,  103,  104,   31,  131,  131,  108,  109,
+          131,   -1,   -1,  142,  114,  115,  142,  154,  155,   -1,
+           -1,  149,  122,   49,   50,  145,  145,  145,  145,   55,
+          145,   57,  145,  149,  156,  158,  150,   -1,   -1,  151,
+           -1,   -1,   -1,   69,  154,  154,  154,  154,  154,  154,
+          154,   77,   78,  154,  154,  155,   49,   50,  154,   85,
+          154,  154,   55,  154,   57,  154,  154,  154,  154,  154,
+          154,  154,  154,  154,  154,  154,   69,  154,  154,  154,
+          154,  159,  155,  155,   77,   78,  155,  155,  155,  155,
+          155,  155,   85,  155,  155,  155,  155,  155,  155,  162,
+          156,  156,  156,  156,  156,  156,  156,  133,  156,  135,
+          136,  137,  138,  139,  140,  141,  156,  156,  156,  156,
+          156,  147,  148,  156,  156,  156,  156,  156,  156,  156,
+           -1,  157,  156,  156,  156,  156,  156,  156,  156,   -1,
+          133,  157,  135,  136,  137,  138,  139,  140,  141,  157,
+          157,  157,  157,  157,  147,  148,  157,  157,  157,  157,
+          157,  157,  157,  157,  157,  157,  157,  157,   -1,  158,
+          158,  158,  158,  158,  158,  158,  158,  158,  158,  158,
+          158,  158,  158,  158,  158,  158,  158,  158,  158,   -1,
+           -1,  160,  160,   -1,  161,  161,  161,  161,  161,  161,
+          161,  161,  161,  161,  161,  161,  161,  161,  161
+    );
+
+    protected $actionBase = array(
+            0,  226,  306,  385,  464,  285,  246,  246,  786,   -2,
+           -2,  146,   -2,   -2,   -2,  649,  723,  760,  723,  575,
+          686,  612,  612,  612,  175,  153,  153,  153,  174,  890,
+          319,   62,  450,  463,  557,  609,  636,  496,  496,  496,
+          496,  136,  136,  496,  496,  496,  496,  496,  496,  496,
+          496,  496,  496,  496,  496,  496,  496,  496,  496,  496,
+          496,  496,  496,  496,  496,  496,  496,  496,  496,  496,
+          496,  496,  496,  496,  496,  496,  496,  496,  496,  496,
+          496,  496,  496,  496,  496,  496,  496,  496,  496,  496,
+          496,  496,  496,  496,  496,  496,  496,  496,  496,  496,
+          496,  496,  496,  496,  496,  496,  496,  496,  496,  496,
+          496,  496,  496,  496,  496,  496,  496,  496,  496,  496,
+          496,  496,  496,  496,  496,  496,  496,  496,  496,  496,
+          496,  496,  496,  496,  496,  195,   75,  777,  517,  147,
+          778,  779,  780,  886,  727,  887,  832,  833,  682,  836,
+          837,  838,  839,  840,  831,  841,  907,  842,  591,  591,
+          591,  591,  591,  591,  591,  591,  591,  591,  591,  591,
+          483,  573,  365,  209,  281,  407,  646,  646,  646,  646,
+          646,  646,  646,  327,  327,  327,  327,  327,  327,  327,
+          327,  327,  327,  327,  327,  327,  327,  327,  327,  327,
+          327,  429,  834,  585,  585,  585,  563,  867,  867,  867,
+          867,  867,  867,  867,  867,  867,  867,  867,  867,  867,
+          867,  867,  867,  867,  867,  867,  867,  867,  867,  867,
+          867,  867,  867,  867,  867,  867,  867,  867,  867,  867,
+          867,  867,  867,  867,  867,  867,  867,  867,  867,  867,
+          495,  486,  -21,  -21,  415,  668,  335,  619,  222,  511,
+          213,   25,   25,   25,   25,   25,  148,   16,    4,    4,
+            4,    4,  151,  312,  312,  312,  312,  119,  119,  119,
+          119,  346,  346,  123,  245,  245,  349,  400,  297,  297,
+          297,  297,  297,  297,  297,  297,  297,  297,  111,  558,
+          558,  561,  561,  310,  152,  152,  152,  152,  704,  273,
+          273,  129,  371,  371,  371,  373,  734,  797,  376,  376,
+          376,  376,  376,  376,  468,  468,  468,  480,  480,  480,
+          702,  587,  454,  587,  454,  684,  748,  509,  748,  700,
+          199,  515,  803,  398,  720,  829,  729,  830,  601,  747,
+          235,  782,  724,  419,  782,  633,  637,  634,  419,  419,
+          715,   98,  863,  292,  195,  595,  405,  667,  781,  421,
+          732,  784,  363,  445,  411,  593,  328,  286,  744,  785,
+          888,  889,  181,  739,  667,  667,  667,  139,  362,  328,
+           -8,  613,  613,  613,  613,   48,  613,  613,  613,  613,
+          314,  230,  506,  404,  783,  703,  703,  712,  694,  852,
+          696,  696,  703,  711,  703,  712,  694,  854,  854,  854,
+          854,  703,  694,  703,  703,  703,  696,  696,  694,  709,
+          696,   38,  694,  695,  707,  707,  854,  751,  752,  703,
+          703,  728,  696,  696,  696,  728,  694,  854,  685,  746,
+          234,  696,  854,  665,  711,  665,  703,  685,  694,  665,
+          711,  711,  665,   21,  662,  664,  853,  855,  869,  792,
+          681,  716,  861,  862,  856,  860,  844,  679,  753,  754,
+          569,  669,  671,  673,  699,  740,  701,  735,  724,  692,
+          692,  692,  713,  741,  713,  692,  692,  692,  692,  692,
+          692,  692,  692,  893,  689,  745,  736,  710,  755,  589,
+          600,  793,  731,  738,  882,  875,  891,  892,  863,  880,
+          713,  894,  697,  180,  650,  864,  693,  788,  713,  865,
+          713,  794,  713,  883,  804,  708,  805,  806,  692,  884,
+          895,  896,  897,  898,  899,  900,  901,  902,  706,  903,
+          756,  698,  876,  339,  859,  715,  742,  725,  791,  759,
+          807,  342,  904,  808,  713,  713,  795,  787,  713,  796,
+          764,  750,  872,  766,  877,  905,  731,  726,  878,  713,
+          730,  809,  906,  342,  672,  705,  737,  721,  767,  870,
+          885,  868,  798,  655,  659,  810,  812,  820,  674,  769,
+          873,  874,  871,  771,  799,  670,  800,  719,  821,  801,
+          866,  772,  822,  823,  881,  718,  743,  717,  722,  714,
+          802,  824,  879,  773,  774,  775,  827,  776,  828,    0,
+            0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+            0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+            0,    0,    0,    0,    0,    0,    0,    0,    0,  136,
+          136,  136,  136,   -2,   -2,   -2,   -2,    0,    0,   -2,
+            0,    0,    0,  136,  136,  136,  136,  136,  136,  136,
+          136,  136,  136,  136,  136,  136,  136,  136,  136,  136,
+          136,  136,  136,  136,  136,  136,  136,  136,  136,    0,
+            0,  136,  136,  136,  136,  136,  136,  136,  136,  136,
+          136,  136,  136,  136,  136,  136,  136,  136,  136,  136,
+          136,  136,  136,  136,  136,  136,  136,  136,  136,  136,
+          136,  136,  136,  136,  136,  136,  136,  136,  136,  136,
+          136,  136,  136,  136,  136,  136,  136,  136,  136,  136,
+          136,  136,  136,  136,  136,  136,  136,  136,  136,  136,
+          136,  136,  136,  136,  136,  136,  136,  136,  136,  136,
+          136,  136,  136,  136,  136,  136,  136,  136,  136,  136,
+          136,  136,  136,  136,  136,  136,  136,  136,  136,  136,
+          136,  136,  136,  591,  591,  591,  591,  591,  591,  591,
+          591,  591,  591,  591,  591,  591,  591,  591,  591,  591,
+          591,  591,  591,  591,  591,  591,    0,    0,    0,    0,
+            0,    0,    0,    0,    0,    0,    0,    0,  591,  -21,
+          -21,  -21,  -21,  591,  -21,  -21,  -21,  -21,  -21,  -21,
+          -21,  591,  591,  591,  591,  591,  591,  591,  591,  591,
+          591,  591,  591,  591,  591,  591,  591,  591,  591,  -21,
+          376,  591,  591,  591,  -21,  376,  376,  376,  376,  376,
+          376,  376,  376,  376,  376,  376,  376,  376,  376,  376,
+          376,  376,  376,  376,  376,  376,  376,  376,  376,  376,
+          376,  376,  376,  376,  376,  376,  376,  376,  376,  376,
+          376,  376,  376,  376,  376,  376,  376,  376,  -21,  591,
+            0,    0,  591,  -21,  591,  -21,  591,  -21,  591,  591,
+          591,  591,  591,  591,  -21,  -21,  -21,  -21,  -21,  -21,
+            0,  468,  468,  468,  468,  -21,  -21,  -21,  -21,  376,
+          376,  -37,  376,  376,  376,  376,  376,  376,  376,  376,
+          376,  376,  376,  376,  376,  376,  376,  468,  468,  480,
+          480,  376,  376,  376,  376,  376,  -37,  376,  376,  419,
+          711,  711,  711,  454,  454,  454,    0,    0,    0,    0,
+            0,    0,    0,    0,    0,    0,    0,    0,  454,  419,
+            0,  419,    0,  376,  419,  711,  419,  454,  711,  711,
+          419,  696,  618,  618,  618,  618,  342,  328,    0,  711,
+          711,    0,  711,    0,    0,    0,    0,    0,  696,    0,
+          703,    0,    0,    0,    0,  692,  180,    0,  725,  427,
+            0,    0,    0,    0,    0,    0,  725,  427,  435,  435,
+            0,  706,  692,  692,  692,    0,    0,    0,    0,    0,
+            0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+            0,    0,  342
+    );
+
+    protected $actionDefault = array(
+            3,32767,32767,32767,32767,32767,32767,32767,32767,32767,
+        32767,32767,32767,32767,32767,32767,32767,32767,32767,32767,
+        32767,32767,32767,32767,32767,  534,  534,  489,32767,32767,
+        32767,32767,32767,32767,32767,32767,32767,  293,  293,  293,
+        32767,32767,32767,  522,  522,  522,  522,  522,  522,  522,
+          522,  522,  522,  522,32767,32767,32767,32767,32767,32767,
+          376,32767,32767,32767,32767,32767,32767,32767,32767,32767,
+        32767,32767,32767,32767,32767,32767,32767,32767,32767,32767,
+        32767,32767,32767,32767,32767,32767,32767,32767,32767,32767,
+        32767,32767,32767,32767,32767,32767,32767,32767,32767,32767,
+        32767,32767,32767,32767,32767,32767,32767,32767,32767,32767,
+        32767,32767,32767,32767,32767,32767,32767,32767,32767,32767,
+        32767,32767,32767,32767,32767,32767,32767,32767,32767,32767,
+        32767,32767,32767,32767,32767,32767,32767,32767,  382,  539,
+        32767,32767,32767,32767,32767,32767,32767,32767,32767,32767,
+        32767,32767,32767,32767,32767,32767,32767,32767,  357,  358,
+          360,  361,  292,  542,  523,  241,  383,  538,  291,  243,
+          321,  493,32767,32767,32767,  323,  120,  252,  197,  492,
+          123,  290,  228,  375,  377,  322,  297,  302,  303,  304,
+          305,  306,  307,  308,  309,  310,  311,  312,  313,  314,
+          296,  449,32767,  354,  353,  352,  451,  486,  486,  489,
+        32767,32767,32767,32767,32767,32767,32767,32767,32767,32767,
+        32767,32767,32767,32767,32767,32767,32767,32767,32767,32767,
+        32767,32767,32767,32767,32767,32767,32767,32767,32767,32767,
+        32767,32767,32767,32767,32767,32767,32767,32767,32767,32767,
+          450,  319,  477,  476,  320,  447,  324,  448,  326,  452,
+          325,  342,  343,  340,  341,  344,  454,  453,  470,  471,
+          468,  469,  295,  345,  346,  347,  348,  472,  473,  474,
+          475,32767,32767,  276,  533,  533,32767,32767,32767,32767,
+        32767,32767,32767,32767,32767,32767,32767,32767,32767,  333,
+          334,  461,  462,32767,  232,  232,  232,  232,  277,  232,
+        32767,32767,32767,32767,32767,32767,32767,32767,32767,32767,
+        32767,32767,32767,32767,  328,  329,  327,  456,  457,  455,
+          423,32767,32767,32767,  425,32767,32767,32767,32767,32767,
+        32767,32767,32767,  494,32767,32767,32767,32767,32767,  507,
+          412,32767,  404,32767,32767,  216,  218,  165,32767,32767,
+          480,32767,32767,32767,32767,32767,  512,  338,32767,32767,
+          114,32767,32767,32767,  549,32767,  507,32767,  114,32767,
+        32767,32767,32767,  351,  330,  331,  332,32767,32767,  511,
+          505,  464,  465,  466,  467,32767,  458,  459,  460,  463,
+        32767,32767,32767,32767,32767,32767,32767,32767,  169,  420,
+          426,  426,32767,32767,32767,32767,  169,32767,32767,32767,
+        32767,32767,  169,32767,32767,32767,  510,  509,  169,32767,
+          405,  488,  169,  182,  180,  180,32767,  202,  202,32767,
+        32767,  184,  481,  500,32767,  184,  169,32767,  393,  171,
+          488,32767,32767,  234,32767,  234,32767,  393,  169,  234,
+        32767,32767,  234,32767,  406,  430,32767,32767,32767,32767,
+        32767,32767,32767,32767,32767,32767,32767,32767,32767,32767,
+        32767,  372,  373,  483,  496,32767,  497,32767,  404,  336,
+          337,  339,  316,32767,  318,  362,  363,  364,  365,  366,
+          367,  368,  370,32767,  410,32767,  413,32767,32767,32767,
+          251,32767,  547,32767,32767,  300,  547,32767,32767,32767,
+          541,32767,32767,  294,32767,32767,32767,32767,  247,32767,
+          167,32767,  531,32767,  548,32767,  505,32767,  335,32767,
+        32767,32767,32767,32767,32767,32767,32767,32767,  506,32767,
+        32767,32767,32767,  223,32767,  443,32767,  114,32767,32767,
+        32767,  183,32767,32767,  298,  242,32767,32767,  540,32767,
+        32767,32767,32767,32767,32767,32767,32767,  112,32767,  168,
+        32767,32767,32767,  185,32767,32767,  505,32767,32767,32767,
+        32767,32767,32767,32767,  289,32767,32767,32767,32767,32767,
+        32767,32767,  505,32767,32767,  227,32767,32767,32767,32767,
+        32767,32767,32767,32767,32767,  406,32767,  270,32767,32767,
+        32767,32767,32767,32767,32767,32767,32767,32767,32767,  125,
+          125,    3,  125,  125,  254,    3,  254,  125,  254,  254,
+          125,  125,  125,  125,  125,  125,  125,  125,  125,  125,
+          210,  213,  202,  202,  162,  125,  125,  262
+    );
+
+    protected $goto = array(
+          165,  139,  139,  139,  165,  143,  146,  140,  141,  142,
+          148,  186,  167,  162,  162,  162,  162,  143,  143,  164,
+          164,  164,  164,  164,  164,  164,  164,  164,  164,  164,
+          137,  158,  159,  160,  161,  183,  138,  184,  489,  490,
+          367,  491,  495,  496,  497,  498,  499,  500,  501,  502,
+          959,  163,  144,  145,  147,  170,  175,  185,  203,  251,
+          254,  256,  258,  260,  261,  262,  263,  264,  265,  273,
+          274,  275,  276,  299,  300,  324,  325,  326,  384,  385,
+          386,  538,  187,  188,  189,  190,  191,  192,  193,  194,
+          195,  196,  197,  198,  199,  200,  149,  150,  151,  166,
+          152,  168,  153,  204,  169,  154,  155,  156,  205,  157,
+          135,  616,  556,  574,  578,  622,  624,  556,  556,  556,
+          556,  556,  556,  556,  556,  556,  556,  556,  556,  556,
+          556,  556,  556,  556,  556,  556,  556,  556,  556,  556,
+          556,  556,  556,  556,  556,  556,  556,  556,  556,  556,
+          556,  556,  556,  556,  556,  556,  556,  556,  556,  556,
+         1099,  515,  345,  571,  600, 1099, 1099, 1099, 1099, 1099,
+         1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099,
+         1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099,
+         1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099,
+         1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099,  504, 1202,
+         1202, 1075, 1074,  504,  540,  541,  542,  543,  544,  545,
+          546,  547,  549,  582,    3,    4,  173, 1202,  844,  844,
+          844,  844,  839,  845,  176,  177,  178,  391,  392,  393,
+          394,  172,  201,  206,  250,  255,  257,  259,  266,  267,
+          268,  269,  270,  271,  277,  278,  279,  280,  301,  302,
+          327,  328,  329,  396,  397,  398,  399,  174,  179,  252,
+          253,  180,  181,  182,  493,  493,  750,  493,  493,  493,
+          493,  493,  493,  493,  493,  493,  493,  493,  493,  493,
+          493,  505,  929,  442,  444,  627,  505,  751,  779, 1100,
+          610,  927,  880,  880,  765, 1190, 1190, 1168,  555,  775,
+          764,  743, 1168,  555,  555,  555,  555,  555,  555,  555,
+          555,  555,  555,  555,  555,  555,  555,  555,  555,  555,
+          555,  555,  555,  555,  555,  555,  555,  555,  555,  555,
+          555,  555,  555,  555,  555,  555,  555,  555,  555,  555,
+          555,  555,  555,  555,  555,  555,  390,  602,  746,  532,
+          532,  564,  528,  530,  530,  492,  494,  520,  536,  565,
+          568,  579,  586,  810,  606,  506,  346,  347,  609,  850,
+          506,  365,  537,  746,  533,  746,  563,  430,  430,  375,
+          430,  430,  430,  430,  430,  430,  430,  430,  430,  430,
+          430,  430,  430,  430, 1063,  581,  957,  596,  597, 1063,
+          887,  887,  887,  887, 1160,  887,  887, 1182, 1182, 1182,
+          376,  376,  376,  749, 1063, 1063, 1063, 1063, 1063, 1063,
+          334, 1056,  317,  374,  374,  374,  866,  848,  846,  848,
+          650,  461,  507,  875,  870,  376, 1194,  368,  374,  389,
+          374,  898,  374, 1080,  583,  348,  404,  374, 1216,  590,
+          601, 1017,   19,   15,  361, 1148, 1187,  525,  936,  904,
+          510,  526,  904,  651,  551,  381, 1201, 1201,  587, 1007,
+          550,  877,  607,  608,  873,  612,  613,  619,  621,  626,
+          628,   23,  884,  937, 1201,  336,  598, 1059, 1060, 1204,
+          378, 1056,  557,  539,  893,  768,  766,  379,  514,  902,
+          509,  524,  655, 1057, 1159, 1057,  776,  509, 1167,  524,
+          514,  514, 1058, 1167, 1049,  907,  508, 1054,  511,  433,
+          434,  510, 1184, 1184, 1184,  854,  445,  945,  569, 1145,
+          459,  362,    0,    0,  773, 1209,    0,  518,    0,  519,
+            0,  529,    0,    0,    0,    0,    0, 1166,    0,    0,
+            0,  771,    0,    0,    0,  449,    0,    0,    0,    0,
+            0,    0,  605,    0,    0,    0,    0,   13, 1055,  614
+    );
+
+    protected $gotoCheck = array(
+           42,   42,   42,   42,   42,   42,   42,   42,   42,   42,
+           42,   42,   42,   42,   42,   42,   42,   42,   42,   42,
+           42,   42,   42,   42,   42,   42,   42,   42,   42,   42,
+           42,   42,   42,   42,   42,   42,   42,   42,   42,   42,
+           42,   42,   42,   42,   42,   42,   42,   42,   42,   42,
+           42,   42,   42,   42,   42,   42,   42,   42,   42,   42,
+           42,   42,   42,   42,   42,   42,   42,   42,   42,   42,
+           42,   42,   42,   42,   42,   42,   42,   42,   42,   42,
+           42,   42,   42,   42,   42,   42,   42,   42,   42,   42,
+           42,   42,   42,   42,   42,   42,   42,   42,   42,   42,
+           42,   42,   42,   42,   42,   42,   42,   42,   42,   42,
+           42,   56,   66,   59,   59,   59,    8,   66,   66,   66,
+           66,   66,   66,   66,   66,   66,   66,   66,   66,   66,
+           66,   66,   66,   66,   66,   66,   66,   66,   66,   66,
+           66,   66,   66,   66,   66,   66,   66,   66,   66,   66,
+           66,   66,   66,   66,   66,   66,   66,   66,   66,   66,
+          124,   99,   69,   39,   39,  124,  124,  124,  124,  124,
+          124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
+          124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
+          124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
+          124,  124,  124,  124,  124,  124,  124,  124,   66,  140,
+          140,  122,  122,   66,  108,  108,  108,  108,  108,  108,
+          108,  108,  108,  108,   29,   29,   26,  140,   66,   66,
+           66,   66,   66,   66,   26,   26,   26,   26,   26,   26,
+           26,   26,   26,   26,   26,   26,   26,   26,   26,   26,
+           26,   26,   26,   26,   26,   26,   26,   26,   26,   26,
+           26,   26,   26,   26,   26,   26,   26,   26,   26,   26,
+           26,   26,   26,   26,  115,  115,   14,  115,  115,  115,
+          115,  115,  115,  115,  115,  115,  115,  115,  115,  115,
+          115,  115,    7,    7,    7,    7,  115,   15,   28,    7,
+            7,    7,   74,   74,   22,   74,   74,  116,   56,   22,
+           22,    5,  116,   56,   56,   56,   56,   56,   56,   56,
+           56,   56,   56,   56,   56,   56,   56,   56,   56,   56,
+           56,   56,   56,   56,   56,   56,   56,   56,   56,   56,
+           56,   56,   56,   56,   56,   56,   56,   56,   56,   56,
+           56,   56,   56,   56,   56,   56,   50,   50,   10,   50,
+           50,   50,   50,   50,   50,   50,   50,   50,   50,   50,
+           50,   50,   50,   49,   60,  120,   69,   69,   60,   32,
+          120,   60,    2,   10,  107,   10,    2,   56,   56,   10,
+           56,   56,   56,   56,   56,   56,   56,   56,   56,   56,
+           56,   56,   56,   56,   56,   64,   99,   64,   64,   56,
+           56,   56,   56,   56,   79,   56,   56,    8,    8,    8,
+          121,  121,  121,   13,   56,   56,   56,   56,   56,   56,
+          123,   79,  123,   12,   12,   12,   13,   13,   13,   13,
+           13,   56,   13,   13,   13,  121,  138,   45,   12,  121,
+           12,   81,   12,   33,   67,   67,   67,   12,   12,  125,
+           48,   33,   33,   33,   33,  129,  136,    8,   95,   12,
+           12,   31,   12,   31,   31,   47,  139,  139,   31,  100,
+           33,   31,   31,   31,   31,   31,   31,   31,   31,   31,
+           31,   33,   76,   95,  139,   17,   33,   79,   79,  139,
+           11,   79,   11,   46,   78,   24,   23,   16,   46,   82,
+            8,    8,   71,   79,   79,   79,   25,    8,  117,    8,
+           46,   46,   79,  117,  111,   83,    8,  113,    8,    8,
+            8,   12,  117,  117,  117,   68,   62,   97,   63,  128,
+          106,   57,   -1,   -1,    8,    8,   -1,   57,   -1,   99,
+           -1,   57,   -1,   -1,   -1,   -1,   -1,  117,   -1,   -1,
+           -1,    8,   -1,   -1,   -1,   57,   -1,   -1,   -1,   -1,
+           -1,   -1,   12,   -1,   -1,   -1,   -1,   57,   12,   12
+    );
+
+    protected $gotoBase = array(
+            0,    0, -249,    0,    0,  300,    0,  287,  105,    0,
+           47,  164,  118,  421,  274,  295,  171,  184,    0,    0,
+            0,    0,  -49,  168,  172,  104,   24,    0,  288, -431,
+            0, -159,  359,   44,    0,    0,    0,    0,    0,  125,
+            0,    0,  -24,    0,    0,  407,  479,  186,  178,  355,
+           75,    0,    0,    0,    0,    0,  106,  119,    0, -192,
+          -81,    0,  101,   93, -231,    0,  -90,  135,  121, -276,
+            0,  148,    0,    0,   21,    0,  183,    0,  194,   71,
+            0,  423,  155,  112,    0,    0,    0,    0,    0,    0,
+            0,    0,    0,    0,    0,  185,    0,  122,    0,  120,
+          176,    0,    0,    0,    0,    0,   83,  358,  170,    0,
+            0,  113,    0,  111,    0,   -7,    9,  220,    0,    0,
+           77,  108, -102,  100,  -42,  251,    0,    0,   89,  256,
+            0,    0,    0,    0,    0,    0,  181,    0,  419,  160,
+         -107,    0,    0
+    );
+
+    protected $gotoDefault = array(
+        -32768,  463,  659,    2,  660,  733,  741,  593,  477,  625,
+          577,  370, 1178,  785,  786,  787,  371,  358,  478,  369,
+          400,  395,  774,  767,  769,  777,  171,  401,  780,    1,
+          782,  513,  818, 1008,  355,  790,  356,  585,  792,  522,
+          794,  795,  136,  372,  373,  523,  479,  380,  572,  809,
+          272,  377,  811,  357,  812,  821,  360,  460,  454,  552,
+          604,  425,  441,  566,  560,  531, 1072,  561,  853,  344,
+          861,  656,  869,  872,  480,  553,  883,  446,  891, 1085,
+          387,  897,  903,  908,  283,  911,  407,  402,  580,  916,
+          917,    5,  921,  617,  618,    8,  308,  944,  594,  958,
+          411, 1027, 1029,  481,  482,  517,  453,  503,  521,  483,
+         1050,  435,  403, 1053,  484,  485,  426,  427, 1069,  350,
+         1153,  349,  443,  316, 1140,  575, 1104,  450, 1193, 1149,
+          343,  486,  487,  366, 1172,  382, 1188,  431, 1195, 1203,
+          339,  535,  562
+    );
+
+    protected $ruleToNonTerminal = array(
+            0,    1,    3,    3,    2,    5,    5,    5,    5,    5,
+            5,    5,    5,    5,    5,    5,    5,    5,    5,    5,
+            5,    5,    5,    5,    5,    5,    5,    5,    5,    5,
+            5,    5,    5,    5,    5,    5,    5,    5,    5,    5,
+            5,    5,    5,    5,    5,    5,    5,    5,    5,    5,
+            5,    5,    5,    5,    5,    5,    5,    5,    5,    5,
+            5,    5,    5,    5,    5,    5,    5,    5,    5,    5,
+            5,    5,    5,    5,    5,    6,    6,    6,    6,    6,
+            6,    6,    7,    7,    8,    9,   10,   10,   11,   11,
+           12,    4,    4,    4,    4,    4,    4,    4,    4,    4,
+            4,    4,   17,   17,   18,   18,   20,   20,   16,   16,
+           21,   21,   22,   22,   23,   23,   24,   24,   19,   19,
+           25,   27,   27,   28,   29,   29,   31,   30,   30,   30,
+           30,   32,   32,   32,   32,   32,   32,   32,   32,   32,
+           32,   32,   32,   32,   32,   32,   32,   32,   32,   32,
+           32,   32,   32,   32,   32,   32,   32,   32,   32,   32,
+           13,   13,   53,   53,   55,   54,   54,   47,   47,   57,
+           57,   58,   58,   14,   15,   15,   15,   61,   61,   61,
+           62,   62,   65,   65,   63,   63,   67,   67,   40,   40,
+           49,   49,   52,   52,   52,   51,   51,   68,   41,   41,
+           41,   41,   69,   69,   70,   70,   71,   71,   38,   38,
+           34,   34,   72,   36,   36,   73,   35,   35,   37,   37,
+           48,   48,   48,   59,   59,   75,   75,   76,   76,   78,
+           78,   78,   77,   77,   60,   60,   79,   79,   79,   80,
+           80,   81,   81,   81,   43,   43,   82,   82,   82,   44,
+           44,   83,   83,   84,   84,   64,   85,   85,   85,   85,
+           90,   90,   91,   91,   92,   92,   92,   92,   92,   93,
+           94,   94,   89,   89,   86,   86,   88,   88,   96,   96,
+           95,   95,   95,   95,   95,   95,   87,   87,   98,   97,
+           97,   45,   45,   39,   39,   42,   42,   42,   42,   42,
+           42,   42,   42,   42,   42,   42,   42,   42,   42,   42,
+           42,   42,   42,   42,   42,   42,   42,   42,   42,   42,
+           42,   42,   42,   42,   42,   42,   42,   42,   42,   42,
+           42,   42,   42,   42,   42,   42,   42,   42,   42,   42,
+           42,   42,   42,   42,   42,   42,   42,   42,   42,   42,
+           42,   42,   42,   42,   42,   42,   42,   42,   42,   42,
+           42,   42,   42,   42,   42,   42,   42,   42,   42,   42,
+           42,   42,   42,   42,   42,   42,   42,   42,   42,   42,
+           33,   33,   46,   46,  103,  103,  104,  104,  104,  104,
+          110,   99,   99,  106,  106,  112,  112,  113,  114,  114,
+          114,  114,  114,  114,   66,   66,   56,   56,   56,   56,
+          100,  100,  118,  118,  115,  115,  119,  119,  119,  119,
+          101,  101,  101,  105,  105,  105,  111,  111,  124,  124,
+          124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
+          124,   26,   26,   26,   26,   26,   26,  126,  126,  126,
+          126,  126,  126,  126,  126,  126,  126,  126,  126,  126,
+          126,  126,  126,  126,  126,  126,  126,  126,  126,  126,
+          126,  126,  126,  126,  126,  126,  126,  126,  126,  126,
+          109,  109,  102,  102,  102,  102,  125,  125,  128,  128,
+          127,  127,  129,  129,   50,   50,   50,   50,  131,  131,
+          130,  130,  130,  130,  130,  132,  132,  117,  117,  120,
+          120,  116,  116,  134,  133,  133,  133,  133,  121,  121,
+          121,  121,  108,  108,  122,  122,  122,  122,   74,  135,
+          135,  136,  136,  136,  107,  107,  137,  137,  138,  138,
+          138,  138,  138,  123,  123,  123,  123,  140,  141,  139,
+          139,  139,  139,  139,  139,  139,  142,  142,  142
+    );
+
+    protected $ruleToLength = array(
+            1,    1,    2,    0,    1,    1,    1,    1,    1,    1,
+            1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+            1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+            1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+            1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+            1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+            1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+            1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+            1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+            1,    1,    1,    1,    1,    3,    5,    4,    3,    4,
+            2,    3,    1,    1,    7,    6,    3,    1,    3,    1,
+            3,    1,    1,    3,    1,    3,    1,    2,    3,    1,
+            3,    3,    1,    3,    2,    0,    1,    1,    1,    1,
+            1,    3,    5,    8,    3,    5,    9,    3,    2,    3,
+            2,    3,    2,    3,    3,    3,    3,    1,    2,    2,
+            5,    7,    9,    5,    6,    3,    3,    2,    2,    1,
+            1,    1,    0,    2,    8,    0,    4,    1,    3,    0,
+            1,    0,    1,   10,    7,    6,    5,    1,    2,    2,
+            0,    2,    0,    2,    0,    2,    1,    3,    1,    4,
+            1,    4,    1,    1,    4,    1,    3,    3,    3,    4,
+            4,    5,    0,    2,    4,    3,    1,    1,    1,    4,
+            0,    2,    3,    0,    2,    4,    0,    2,    0,    3,
+            1,    2,    1,    1,    0,    1,    3,    4,    6,    1,
+            1,    1,    0,    1,    0,    2,    2,    3,    3,    1,
+            3,    1,    2,    2,    3,    1,    1,    2,    4,    3,
+            1,    1,    3,    2,    0,    1,    3,    3,    9,    3,
+            1,    3,    0,    2,    4,    5,    4,    4,    4,    3,
+            1,    1,    1,    3,    1,    1,    0,    1,    1,    2,
+            1,    1,    1,    1,    1,    1,    1,    3,    1,    1,
+            3,    3,    1,    0,    1,    1,    3,    3,    4,    4,
+            1,    2,    3,    3,    3,    3,    3,    3,    3,    3,
+            3,    3,    3,    3,    3,    2,    2,    2,    2,    3,
+            3,    3,    3,    3,    3,    3,    3,    3,    3,    3,
+            3,    3,    3,    3,    3,    3,    2,    2,    2,    2,
+            3,    3,    3,    3,    3,    3,    3,    3,    3,    3,
+            1,    3,    5,    4,    3,    4,    4,    2,    2,    2,
+            2,    2,    2,    2,    2,    2,    2,    2,    2,    2,
+            2,    1,    1,    1,    3,    2,    1,    2,   10,   11,
+            3,    3,    2,    4,    4,    3,    4,    4,    4,    4,
+            7,    3,    2,    0,    4,    1,    3,    2,    2,    4,
+            6,    2,    2,    4,    1,    1,    1,    1,    1,    1,
+            1,    1,    1,    1,    1,    1,    3,    3,    4,    4,
+            0,    2,    1,    0,    1,    1,    0,    1,    1,    1,
+            1,    1,    1,    1,    1,    1,    1,    1,    1,    3,
+            2,    1,    3,    1,    4,    3,    1,    3,    3,    3,
+            3,    3,    3,    3,    3,    3,    3,    3,    3,    3,
+            3,    3,    3,    3,    2,    2,    2,    2,    3,    3,
+            3,    3,    3,    3,    3,    3,    5,    4,    4,    3,
+            1,    3,    1,    1,    3,    3,    0,    2,    0,    1,
+            3,    1,    3,    1,    1,    1,    1,    1,    6,    4,
+            3,    4,    2,    4,    4,    1,    3,    1,    2,    1,
+            1,    4,    1,    1,    3,    6,    4,    4,    4,    4,
+            1,    4,    0,    1,    1,    3,    1,    1,    4,    3,
+            1,    1,    1,    0,    0,    2,    3,    1,    3,    1,
+            4,    2,    2,    2,    2,    1,    2,    1,    1,    1,
+            4,    3,    3,    3,    6,    3,    1,    1,    1
+    );
+
+    protected function initReduceCallbacks() {
+        $this->reduceCallbacks = [
+            0 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            1 => function ($stackPos) {
+                 $this->semValue = $this->handleNamespaces($this->semStack[$stackPos-(1-1)]);
+            },
+            2 => function ($stackPos) {
+                 if (is_array($this->semStack[$stackPos-(2-2)])) { $this->semValue = array_merge($this->semStack[$stackPos-(2-1)], $this->semStack[$stackPos-(2-2)]); } else { $this->semStack[$stackPos-(2-1)][] = $this->semStack[$stackPos-(2-2)]; $this->semValue = $this->semStack[$stackPos-(2-1)]; };
+            },
+            3 => function ($stackPos) {
+                 $this->semValue = array();
+            },
+            4 => function ($stackPos) {
+                 $startAttributes = $this->lookaheadStartAttributes; if (isset($startAttributes['comments'])) { $nop = new Stmt\Nop($this->createCommentNopAttributes($startAttributes['comments'])); } else { $nop = null; };
+            if ($nop !== null) { $this->semStack[$stackPos-(1-1)][] = $nop; } $this->semValue = $this->semStack[$stackPos-(1-1)];
+            },
+            5 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            6 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            7 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            8 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            9 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            10 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            11 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            12 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            13 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            14 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            15 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            16 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            17 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            18 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            19 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            20 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            21 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            22 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            23 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            24 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            25 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            26 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            27 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            28 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            29 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            30 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            31 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            32 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            33 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            34 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            35 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            36 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            37 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            38 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            39 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            40 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            41 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            42 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            43 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            44 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            45 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            46 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            47 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            48 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            49 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            50 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            51 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            52 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            53 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            54 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            55 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            56 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            57 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            58 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            59 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            60 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            61 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            62 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            63 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            64 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            65 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            66 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            67 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            68 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            69 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            70 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            71 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            72 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            73 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            74 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            75 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            76 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            77 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            78 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            79 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            80 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            81 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            82 => function ($stackPos) {
+                 $this->semValue = new Node\Identifier($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes);
+            },
+            83 => function ($stackPos) {
+                 $this->semValue = new Node\Identifier($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes);
+            },
+            84 => function ($stackPos) {
+                 $this->semValue = new Node\Identifier($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes);
+            },
+            85 => function ($stackPos) {
+                 $this->semValue = new Node\Identifier($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes);
+            },
+            86 => function ($stackPos) {
+                 $this->semValue = new Name($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes);
+            },
+            87 => function ($stackPos) {
+                 $this->semValue = new Name($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes);
+            },
+            88 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(1-1)];
+            },
+            89 => function ($stackPos) {
+                 $this->semValue = new Name(substr($this->semStack[$stackPos-(1-1)], 1), $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes);
+            },
+            90 => function ($stackPos) {
+                 $this->semValue = new Expr\Variable(substr($this->semStack[$stackPos-(1-1)], 1), $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes);
+            },
+            91 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(1-1)];
+            },
+            92 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(1-1)];
+            },
+            93 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(1-1)];
+            },
+            94 => function ($stackPos) {
+                 $this->semValue = new Stmt\HaltCompiler($this->lexer->handleHaltCompiler(), $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes);
+            },
+            95 => function ($stackPos) {
+                 $this->semValue = new Stmt\Namespace_($this->semStack[$stackPos-(3-2)], null, $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            $this->semValue->setAttribute('kind', Stmt\Namespace_::KIND_SEMICOLON);
+            $this->checkNamespace($this->semValue);
+            },
+            96 => function ($stackPos) {
+                 $this->semValue = new Stmt\Namespace_($this->semStack[$stackPos-(5-2)], $this->semStack[$stackPos-(5-4)], $this->startAttributeStack[$stackPos-(5-1)] + $this->endAttributes);
+            $this->semValue->setAttribute('kind', Stmt\Namespace_::KIND_BRACED);
+            $this->checkNamespace($this->semValue);
+            },
+            97 => function ($stackPos) {
+                 $this->semValue = new Stmt\Namespace_(null, $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes);
+            $this->semValue->setAttribute('kind', Stmt\Namespace_::KIND_BRACED);
+            $this->checkNamespace($this->semValue);
+            },
+            98 => function ($stackPos) {
+                 $this->semValue = new Stmt\Use_($this->semStack[$stackPos-(3-2)], Stmt\Use_::TYPE_NORMAL, $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            99 => function ($stackPos) {
+                 $this->semValue = new Stmt\Use_($this->semStack[$stackPos-(4-3)], $this->semStack[$stackPos-(4-2)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes);
+            },
+            100 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(2-1)];
+            },
+            101 => function ($stackPos) {
+                 $this->semValue = new Stmt\Const_($this->semStack[$stackPos-(3-2)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            102 => function ($stackPos) {
+                 $this->semValue = Stmt\Use_::TYPE_FUNCTION;
+            },
+            103 => function ($stackPos) {
+                 $this->semValue = Stmt\Use_::TYPE_CONSTANT;
+            },
+            104 => function ($stackPos) {
+                 $this->semValue = new Stmt\GroupUse($this->semStack[$stackPos-(7-3)], $this->semStack[$stackPos-(7-6)], $this->semStack[$stackPos-(7-2)], $this->startAttributeStack[$stackPos-(7-1)] + $this->endAttributes);
+            },
+            105 => function ($stackPos) {
+                 $this->semValue = new Stmt\GroupUse($this->semStack[$stackPos-(6-2)], $this->semStack[$stackPos-(6-5)], Stmt\Use_::TYPE_UNKNOWN, $this->startAttributeStack[$stackPos-(6-1)] + $this->endAttributes);
+            },
+            106 => function ($stackPos) {
+                 $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)];
+            },
+            107 => function ($stackPos) {
+                 $this->semValue = array($this->semStack[$stackPos-(1-1)]);
+            },
+            108 => function ($stackPos) {
+                 $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)];
+            },
+            109 => function ($stackPos) {
+                 $this->semValue = array($this->semStack[$stackPos-(1-1)]);
+            },
+            110 => function ($stackPos) {
+                 $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)];
+            },
+            111 => function ($stackPos) {
+                 $this->semValue = array($this->semStack[$stackPos-(1-1)]);
+            },
+            112 => function ($stackPos) {
+                 $this->semValue = new Stmt\UseUse($this->semStack[$stackPos-(1-1)], null, Stmt\Use_::TYPE_UNKNOWN, $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); $this->checkUseUse($this->semValue, $stackPos-(1-1));
+            },
+            113 => function ($stackPos) {
+                 $this->semValue = new Stmt\UseUse($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], Stmt\Use_::TYPE_UNKNOWN, $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); $this->checkUseUse($this->semValue, $stackPos-(3-3));
+            },
+            114 => function ($stackPos) {
+                 $this->semValue = new Stmt\UseUse($this->semStack[$stackPos-(1-1)], null, Stmt\Use_::TYPE_UNKNOWN, $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); $this->checkUseUse($this->semValue, $stackPos-(1-1));
+            },
+            115 => function ($stackPos) {
+                 $this->semValue = new Stmt\UseUse($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], Stmt\Use_::TYPE_UNKNOWN, $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); $this->checkUseUse($this->semValue, $stackPos-(3-3));
+            },
+            116 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(1-1)]; $this->semValue->type = Stmt\Use_::TYPE_NORMAL;
+            },
+            117 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(2-2)]; $this->semValue->type = $this->semStack[$stackPos-(2-1)];
+            },
+            118 => function ($stackPos) {
+                 $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)];
+            },
+            119 => function ($stackPos) {
+                 $this->semValue = array($this->semStack[$stackPos-(1-1)]);
+            },
+            120 => function ($stackPos) {
+                 $this->semValue = new Node\Const_($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            121 => function ($stackPos) {
+                 $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)];
+            },
+            122 => function ($stackPos) {
+                 $this->semValue = array($this->semStack[$stackPos-(1-1)]);
+            },
+            123 => function ($stackPos) {
+                 $this->semValue = new Node\Const_($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            124 => function ($stackPos) {
+                 if (is_array($this->semStack[$stackPos-(2-2)])) { $this->semValue = array_merge($this->semStack[$stackPos-(2-1)], $this->semStack[$stackPos-(2-2)]); } else { $this->semStack[$stackPos-(2-1)][] = $this->semStack[$stackPos-(2-2)]; $this->semValue = $this->semStack[$stackPos-(2-1)]; };
+            },
+            125 => function ($stackPos) {
+                 $this->semValue = array();
+            },
+            126 => function ($stackPos) {
+                 $startAttributes = $this->lookaheadStartAttributes; if (isset($startAttributes['comments'])) { $nop = new Stmt\Nop($this->createCommentNopAttributes($startAttributes['comments'])); } else { $nop = null; };
+            if ($nop !== null) { $this->semStack[$stackPos-(1-1)][] = $nop; } $this->semValue = $this->semStack[$stackPos-(1-1)];
+            },
+            127 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(1-1)];
+            },
+            128 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(1-1)];
+            },
+            129 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(1-1)];
+            },
+            130 => function ($stackPos) {
+                 throw new Error('__HALT_COMPILER() can only be used from the outermost scope', $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes);
+            },
+            131 => function ($stackPos) {
+
+        if ($this->semStack[$stackPos-(3-2)]) {
+            $this->semValue = $this->semStack[$stackPos-(3-2)]; $attrs = $this->startAttributeStack[$stackPos-(3-1)]; $stmts = $this->semValue; if (!empty($attrs['comments'])) {$stmts[0]->setAttribute('comments', array_merge($attrs['comments'], $stmts[0]->getAttribute('comments', []))); };
+        } else {
+            $startAttributes = $this->startAttributeStack[$stackPos-(3-1)]; if (isset($startAttributes['comments'])) { $this->semValue = new Stmt\Nop($startAttributes + $this->endAttributes); } else { $this->semValue = null; };
+            if (null === $this->semValue) { $this->semValue = array(); }
+        }
+
+            },
+            132 => function ($stackPos) {
+                 $this->semValue = new Stmt\If_($this->semStack[$stackPos-(5-2)], ['stmts' => is_array($this->semStack[$stackPos-(5-3)]) ? $this->semStack[$stackPos-(5-3)] : array($this->semStack[$stackPos-(5-3)]), 'elseifs' => $this->semStack[$stackPos-(5-4)], 'else' => $this->semStack[$stackPos-(5-5)]], $this->startAttributeStack[$stackPos-(5-1)] + $this->endAttributes);
+            },
+            133 => function ($stackPos) {
+                 $this->semValue = new Stmt\If_($this->semStack[$stackPos-(8-2)], ['stmts' => $this->semStack[$stackPos-(8-4)], 'elseifs' => $this->semStack[$stackPos-(8-5)], 'else' => $this->semStack[$stackPos-(8-6)]], $this->startAttributeStack[$stackPos-(8-1)] + $this->endAttributes);
+            },
+            134 => function ($stackPos) {
+                 $this->semValue = new Stmt\While_($this->semStack[$stackPos-(3-2)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            135 => function ($stackPos) {
+                 $this->semValue = new Stmt\Do_($this->semStack[$stackPos-(5-4)], is_array($this->semStack[$stackPos-(5-2)]) ? $this->semStack[$stackPos-(5-2)] : array($this->semStack[$stackPos-(5-2)]), $this->startAttributeStack[$stackPos-(5-1)] + $this->endAttributes);
+            },
+            136 => function ($stackPos) {
+                 $this->semValue = new Stmt\For_(['init' => $this->semStack[$stackPos-(9-3)], 'cond' => $this->semStack[$stackPos-(9-5)], 'loop' => $this->semStack[$stackPos-(9-7)], 'stmts' => $this->semStack[$stackPos-(9-9)]], $this->startAttributeStack[$stackPos-(9-1)] + $this->endAttributes);
+            },
+            137 => function ($stackPos) {
+                 $this->semValue = new Stmt\Switch_($this->semStack[$stackPos-(3-2)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            138 => function ($stackPos) {
+                 $this->semValue = new Stmt\Break_(null, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes);
+            },
+            139 => function ($stackPos) {
+                 $this->semValue = new Stmt\Break_($this->semStack[$stackPos-(3-2)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            140 => function ($stackPos) {
+                 $this->semValue = new Stmt\Continue_(null, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes);
+            },
+            141 => function ($stackPos) {
+                 $this->semValue = new Stmt\Continue_($this->semStack[$stackPos-(3-2)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            142 => function ($stackPos) {
+                 $this->semValue = new Stmt\Return_(null, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes);
+            },
+            143 => function ($stackPos) {
+                 $this->semValue = new Stmt\Return_($this->semStack[$stackPos-(3-2)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            144 => function ($stackPos) {
+                 $this->semValue = new Stmt\Global_($this->semStack[$stackPos-(3-2)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            145 => function ($stackPos) {
+                 $this->semValue = new Stmt\Static_($this->semStack[$stackPos-(3-2)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            146 => function ($stackPos) {
+                 $this->semValue = new Stmt\Echo_($this->semStack[$stackPos-(3-2)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            147 => function ($stackPos) {
+                 $this->semValue = new Stmt\InlineHTML($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes);
+            },
+            148 => function ($stackPos) {
+                 $this->semValue = new Stmt\Expression($this->semStack[$stackPos-(2-1)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes);
+            },
+            149 => function ($stackPos) {
+                 $this->semValue = new Stmt\Expression($this->semStack[$stackPos-(2-1)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes);
+            },
+            150 => function ($stackPos) {
+                 $this->semValue = new Stmt\Unset_($this->semStack[$stackPos-(5-3)], $this->startAttributeStack[$stackPos-(5-1)] + $this->endAttributes);
+            },
+            151 => function ($stackPos) {
+                 $this->semValue = new Stmt\Foreach_($this->semStack[$stackPos-(7-3)], $this->semStack[$stackPos-(7-5)][0], ['keyVar' => null, 'byRef' => $this->semStack[$stackPos-(7-5)][1], 'stmts' => $this->semStack[$stackPos-(7-7)]], $this->startAttributeStack[$stackPos-(7-1)] + $this->endAttributes);
+            },
+            152 => function ($stackPos) {
+                 $this->semValue = new Stmt\Foreach_($this->semStack[$stackPos-(9-3)], $this->semStack[$stackPos-(9-7)][0], ['keyVar' => $this->semStack[$stackPos-(9-5)], 'byRef' => $this->semStack[$stackPos-(9-7)][1], 'stmts' => $this->semStack[$stackPos-(9-9)]], $this->startAttributeStack[$stackPos-(9-1)] + $this->endAttributes);
+            },
+            153 => function ($stackPos) {
+                 $this->semValue = new Stmt\Declare_($this->semStack[$stackPos-(5-3)], $this->semStack[$stackPos-(5-5)], $this->startAttributeStack[$stackPos-(5-1)] + $this->endAttributes);
+            },
+            154 => function ($stackPos) {
+                 $this->semValue = new Stmt\TryCatch($this->semStack[$stackPos-(6-3)], $this->semStack[$stackPos-(6-5)], $this->semStack[$stackPos-(6-6)], $this->startAttributeStack[$stackPos-(6-1)] + $this->endAttributes); $this->checkTryCatch($this->semValue);
+            },
+            155 => function ($stackPos) {
+                 $this->semValue = new Stmt\Throw_($this->semStack[$stackPos-(3-2)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            156 => function ($stackPos) {
+                 $this->semValue = new Stmt\Goto_($this->semStack[$stackPos-(3-2)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            157 => function ($stackPos) {
+                 $this->semValue = new Stmt\Label($this->semStack[$stackPos-(2-1)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes);
+            },
+            158 => function ($stackPos) {
+                 $this->semValue = new Stmt\Expression($this->semStack[$stackPos-(2-1)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes);
+            },
+            159 => function ($stackPos) {
+                 $this->semValue = array(); /* means: no statement */
+            },
+            160 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(1-1)];
+            },
+            161 => function ($stackPos) {
+                 $startAttributes = $this->startAttributeStack[$stackPos-(1-1)]; if (isset($startAttributes['comments'])) { $this->semValue = new Stmt\Nop($startAttributes + $this->endAttributes); } else { $this->semValue = null; };
+            if ($this->semValue === null) $this->semValue = array(); /* means: no statement */
+            },
+            162 => function ($stackPos) {
+                 $this->semValue = array();
+            },
+            163 => function ($stackPos) {
+                 $this->semStack[$stackPos-(2-1)][] = $this->semStack[$stackPos-(2-2)]; $this->semValue = $this->semStack[$stackPos-(2-1)];
+            },
+            164 => function ($stackPos) {
+                 $this->semValue = new Stmt\Catch_(array($this->semStack[$stackPos-(8-3)]), $this->semStack[$stackPos-(8-4)], $this->semStack[$stackPos-(8-7)], $this->startAttributeStack[$stackPos-(8-1)] + $this->endAttributes);
+            },
+            165 => function ($stackPos) {
+                 $this->semValue = null;
+            },
+            166 => function ($stackPos) {
+                 $this->semValue = new Stmt\Finally_($this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes);
+            },
+            167 => function ($stackPos) {
+                 $this->semValue = array($this->semStack[$stackPos-(1-1)]);
+            },
+            168 => function ($stackPos) {
+                 $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)];
+            },
+            169 => function ($stackPos) {
+                 $this->semValue = false;
+            },
+            170 => function ($stackPos) {
+                 $this->semValue = true;
+            },
+            171 => function ($stackPos) {
+                 $this->semValue = false;
+            },
+            172 => function ($stackPos) {
+                 $this->semValue = true;
+            },
+            173 => function ($stackPos) {
+                 $this->semValue = new Stmt\Function_($this->semStack[$stackPos-(10-3)], ['byRef' => $this->semStack[$stackPos-(10-2)], 'params' => $this->semStack[$stackPos-(10-5)], 'returnType' => $this->semStack[$stackPos-(10-7)], 'stmts' => $this->semStack[$stackPos-(10-9)]], $this->startAttributeStack[$stackPos-(10-1)] + $this->endAttributes);
+            },
+            174 => function ($stackPos) {
+                 $this->semValue = new Stmt\Class_($this->semStack[$stackPos-(7-2)], ['type' => $this->semStack[$stackPos-(7-1)], 'extends' => $this->semStack[$stackPos-(7-3)], 'implements' => $this->semStack[$stackPos-(7-4)], 'stmts' => $this->semStack[$stackPos-(7-6)]], $this->startAttributeStack[$stackPos-(7-1)] + $this->endAttributes);
+            $this->checkClass($this->semValue, $stackPos-(7-2));
+            },
+            175 => function ($stackPos) {
+                 $this->semValue = new Stmt\Interface_($this->semStack[$stackPos-(6-2)], ['extends' => $this->semStack[$stackPos-(6-3)], 'stmts' => $this->semStack[$stackPos-(6-5)]], $this->startAttributeStack[$stackPos-(6-1)] + $this->endAttributes);
+            $this->checkInterface($this->semValue, $stackPos-(6-2));
+            },
+            176 => function ($stackPos) {
+                 $this->semValue = new Stmt\Trait_($this->semStack[$stackPos-(5-2)], ['stmts' => $this->semStack[$stackPos-(5-4)]], $this->startAttributeStack[$stackPos-(5-1)] + $this->endAttributes);
+            },
+            177 => function ($stackPos) {
+                 $this->semValue = 0;
+            },
+            178 => function ($stackPos) {
+                 $this->semValue = Stmt\Class_::MODIFIER_ABSTRACT;
+            },
+            179 => function ($stackPos) {
+                 $this->semValue = Stmt\Class_::MODIFIER_FINAL;
+            },
+            180 => function ($stackPos) {
+                 $this->semValue = null;
+            },
+            181 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(2-2)];
+            },
+            182 => function ($stackPos) {
+                 $this->semValue = array();
+            },
+            183 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(2-2)];
+            },
+            184 => function ($stackPos) {
+                 $this->semValue = array();
+            },
+            185 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(2-2)];
+            },
+            186 => function ($stackPos) {
+                 $this->semValue = array($this->semStack[$stackPos-(1-1)]);
+            },
+            187 => function ($stackPos) {
+                 $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)];
+            },
+            188 => function ($stackPos) {
+                 $this->semValue = is_array($this->semStack[$stackPos-(1-1)]) ? $this->semStack[$stackPos-(1-1)] : array($this->semStack[$stackPos-(1-1)]);
+            },
+            189 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(4-2)];
+            },
+            190 => function ($stackPos) {
+                 $this->semValue = is_array($this->semStack[$stackPos-(1-1)]) ? $this->semStack[$stackPos-(1-1)] : array($this->semStack[$stackPos-(1-1)]);
+            },
+            191 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(4-2)];
+            },
+            192 => function ($stackPos) {
+                 $this->semValue = is_array($this->semStack[$stackPos-(1-1)]) ? $this->semStack[$stackPos-(1-1)] : array($this->semStack[$stackPos-(1-1)]);
+            },
+            193 => function ($stackPos) {
+                 $this->semValue = null;
+            },
+            194 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(4-2)];
+            },
+            195 => function ($stackPos) {
+                 $this->semValue = array($this->semStack[$stackPos-(1-1)]);
+            },
+            196 => function ($stackPos) {
+                 $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)];
+            },
+            197 => function ($stackPos) {
+                 $this->semValue = new Stmt\DeclareDeclare($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            198 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(3-2)];
+            },
+            199 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(4-3)];
+            },
+            200 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(4-2)];
+            },
+            201 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(5-3)];
+            },
+            202 => function ($stackPos) {
+                 $this->semValue = array();
+            },
+            203 => function ($stackPos) {
+                 $this->semStack[$stackPos-(2-1)][] = $this->semStack[$stackPos-(2-2)]; $this->semValue = $this->semStack[$stackPos-(2-1)];
+            },
+            204 => function ($stackPos) {
+                 $this->semValue = new Stmt\Case_($this->semStack[$stackPos-(4-2)], $this->semStack[$stackPos-(4-4)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes);
+            },
+            205 => function ($stackPos) {
+                 $this->semValue = new Stmt\Case_(null, $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            206 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            207 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            208 => function ($stackPos) {
+                 $this->semValue = is_array($this->semStack[$stackPos-(1-1)]) ? $this->semStack[$stackPos-(1-1)] : array($this->semStack[$stackPos-(1-1)]);
+            },
+            209 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(4-2)];
+            },
+            210 => function ($stackPos) {
+                 $this->semValue = array();
+            },
+            211 => function ($stackPos) {
+                 $this->semStack[$stackPos-(2-1)][] = $this->semStack[$stackPos-(2-2)]; $this->semValue = $this->semStack[$stackPos-(2-1)];
+            },
+            212 => function ($stackPos) {
+                 $this->semValue = new Stmt\ElseIf_($this->semStack[$stackPos-(3-2)], is_array($this->semStack[$stackPos-(3-3)]) ? $this->semStack[$stackPos-(3-3)] : array($this->semStack[$stackPos-(3-3)]), $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            213 => function ($stackPos) {
+                 $this->semValue = array();
+            },
+            214 => function ($stackPos) {
+                 $this->semStack[$stackPos-(2-1)][] = $this->semStack[$stackPos-(2-2)]; $this->semValue = $this->semStack[$stackPos-(2-1)];
+            },
+            215 => function ($stackPos) {
+                 $this->semValue = new Stmt\ElseIf_($this->semStack[$stackPos-(4-2)], $this->semStack[$stackPos-(4-4)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes);
+            },
+            216 => function ($stackPos) {
+                 $this->semValue = null;
+            },
+            217 => function ($stackPos) {
+                 $this->semValue = new Stmt\Else_(is_array($this->semStack[$stackPos-(2-2)]) ? $this->semStack[$stackPos-(2-2)] : array($this->semStack[$stackPos-(2-2)]), $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes);
+            },
+            218 => function ($stackPos) {
+                 $this->semValue = null;
+            },
+            219 => function ($stackPos) {
+                 $this->semValue = new Stmt\Else_($this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            220 => function ($stackPos) {
+                 $this->semValue = array($this->semStack[$stackPos-(1-1)], false);
+            },
+            221 => function ($stackPos) {
+                 $this->semValue = array($this->semStack[$stackPos-(2-2)], true);
+            },
+            222 => function ($stackPos) {
+                 $this->semValue = array($this->semStack[$stackPos-(1-1)], false);
+            },
+            223 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(1-1)];
+            },
+            224 => function ($stackPos) {
+                 $this->semValue = array();
+            },
+            225 => function ($stackPos) {
+                 $this->semValue = array($this->semStack[$stackPos-(1-1)]);
+            },
+            226 => function ($stackPos) {
+                 $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)];
+            },
+            227 => function ($stackPos) {
+                 $this->semValue = new Node\Param($this->semStack[$stackPos-(4-4)], null, $this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-2)], $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); $this->checkParam($this->semValue);
+            },
+            228 => function ($stackPos) {
+                 $this->semValue = new Node\Param($this->semStack[$stackPos-(6-4)], $this->semStack[$stackPos-(6-6)], $this->semStack[$stackPos-(6-1)], $this->semStack[$stackPos-(6-2)], $this->semStack[$stackPos-(6-3)], $this->startAttributeStack[$stackPos-(6-1)] + $this->endAttributes); $this->checkParam($this->semValue);
+            },
+            229 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(1-1)];
+            },
+            230 => function ($stackPos) {
+                 $this->semValue = new Node\Identifier('array', $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes);
+            },
+            231 => function ($stackPos) {
+                 $this->semValue = new Node\Identifier('callable', $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes);
+            },
+            232 => function ($stackPos) {
+                 $this->semValue = null;
+            },
+            233 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(1-1)];
+            },
+            234 => function ($stackPos) {
+                 $this->semValue = null;
+            },
+            235 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(2-2)];
+            },
+            236 => function ($stackPos) {
+                 $this->semValue = array();
+            },
+            237 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(3-2)];
+            },
+            238 => function ($stackPos) {
+                 $this->semValue = array(new Node\Arg($this->semStack[$stackPos-(3-2)], false, false, $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes));
+            },
+            239 => function ($stackPos) {
+                 $this->semValue = array($this->semStack[$stackPos-(1-1)]);
+            },
+            240 => function ($stackPos) {
+                 $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)];
+            },
+            241 => function ($stackPos) {
+                 $this->semValue = new Node\Arg($this->semStack[$stackPos-(1-1)], false, false, $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes);
+            },
+            242 => function ($stackPos) {
+                 $this->semValue = new Node\Arg($this->semStack[$stackPos-(2-2)], true, false, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes);
+            },
+            243 => function ($stackPos) {
+                 $this->semValue = new Node\Arg($this->semStack[$stackPos-(2-2)], false, true, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes);
+            },
+            244 => function ($stackPos) {
+                 $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)];
+            },
+            245 => function ($stackPos) {
+                 $this->semValue = array($this->semStack[$stackPos-(1-1)]);
+            },
+            246 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(1-1)];
+            },
+            247 => function ($stackPos) {
+                 $this->semValue = new Expr\Variable($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes);
+            },
+            248 => function ($stackPos) {
+                 $this->semValue = new Expr\Variable($this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes);
+            },
+            249 => function ($stackPos) {
+                 $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)];
+            },
+            250 => function ($stackPos) {
+                 $this->semValue = array($this->semStack[$stackPos-(1-1)]);
+            },
+            251 => function ($stackPos) {
+                 $this->semValue = new Stmt\StaticVar($this->semStack[$stackPos-(1-1)], null, $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes);
+            },
+            252 => function ($stackPos) {
+                 $this->semValue = new Stmt\StaticVar($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            253 => function ($stackPos) {
+                 if ($this->semStack[$stackPos-(2-2)] !== null) { $this->semStack[$stackPos-(2-1)][] = $this->semStack[$stackPos-(2-2)]; $this->semValue = $this->semStack[$stackPos-(2-1)]; }
+            },
+            254 => function ($stackPos) {
+                 $this->semValue = array();
+            },
+            255 => function ($stackPos) {
+                 $startAttributes = $this->lookaheadStartAttributes; if (isset($startAttributes['comments'])) { $nop = new Stmt\Nop($this->createCommentNopAttributes($startAttributes['comments'])); } else { $nop = null; };
+            if ($nop !== null) { $this->semStack[$stackPos-(1-1)][] = $nop; } $this->semValue = $this->semStack[$stackPos-(1-1)];
+            },
+            256 => function ($stackPos) {
+                 $this->semValue = new Stmt\Property($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-2)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); $this->checkProperty($this->semValue, $stackPos-(3-1));
+            },
+            257 => function ($stackPos) {
+                 $this->semValue = new Stmt\ClassConst($this->semStack[$stackPos-(3-2)], 0, $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            258 => function ($stackPos) {
+                 $this->semValue = new Stmt\ClassMethod($this->semStack[$stackPos-(9-4)], ['type' => $this->semStack[$stackPos-(9-1)], 'byRef' => $this->semStack[$stackPos-(9-3)], 'params' => $this->semStack[$stackPos-(9-6)], 'returnType' => $this->semStack[$stackPos-(9-8)], 'stmts' => $this->semStack[$stackPos-(9-9)]], $this->startAttributeStack[$stackPos-(9-1)] + $this->endAttributes);
+            $this->checkClassMethod($this->semValue, $stackPos-(9-1));
+            },
+            259 => function ($stackPos) {
+                 $this->semValue = new Stmt\TraitUse($this->semStack[$stackPos-(3-2)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            260 => function ($stackPos) {
+                 $this->semValue = array();
+            },
+            261 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(3-2)];
+            },
+            262 => function ($stackPos) {
+                 $this->semValue = array();
+            },
+            263 => function ($stackPos) {
+                 $this->semStack[$stackPos-(2-1)][] = $this->semStack[$stackPos-(2-2)]; $this->semValue = $this->semStack[$stackPos-(2-1)];
+            },
+            264 => function ($stackPos) {
+                 $this->semValue = new Stmt\TraitUseAdaptation\Precedence($this->semStack[$stackPos-(4-1)][0], $this->semStack[$stackPos-(4-1)][1], $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes);
+            },
+            265 => function ($stackPos) {
+                 $this->semValue = new Stmt\TraitUseAdaptation\Alias($this->semStack[$stackPos-(5-1)][0], $this->semStack[$stackPos-(5-1)][1], $this->semStack[$stackPos-(5-3)], $this->semStack[$stackPos-(5-4)], $this->startAttributeStack[$stackPos-(5-1)] + $this->endAttributes);
+            },
+            266 => function ($stackPos) {
+                 $this->semValue = new Stmt\TraitUseAdaptation\Alias($this->semStack[$stackPos-(4-1)][0], $this->semStack[$stackPos-(4-1)][1], $this->semStack[$stackPos-(4-3)], null, $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes);
+            },
+            267 => function ($stackPos) {
+                 $this->semValue = new Stmt\TraitUseAdaptation\Alias($this->semStack[$stackPos-(4-1)][0], $this->semStack[$stackPos-(4-1)][1], null, $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes);
+            },
+            268 => function ($stackPos) {
+                 $this->semValue = new Stmt\TraitUseAdaptation\Alias($this->semStack[$stackPos-(4-1)][0], $this->semStack[$stackPos-(4-1)][1], null, $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes);
+            },
+            269 => function ($stackPos) {
+                 $this->semValue = array($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)]);
+            },
+            270 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(1-1)];
+            },
+            271 => function ($stackPos) {
+                 $this->semValue = array(null, $this->semStack[$stackPos-(1-1)]);
+            },
+            272 => function ($stackPos) {
+                 $this->semValue = null;
+            },
+            273 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(3-2)];
+            },
+            274 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(1-1)];
+            },
+            275 => function ($stackPos) {
+                 $this->semValue = 0;
+            },
+            276 => function ($stackPos) {
+                 $this->semValue = 0;
+            },
+            277 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(1-1)];
+            },
+            278 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(1-1)];
+            },
+            279 => function ($stackPos) {
+                 $this->checkModifier($this->semStack[$stackPos-(2-1)], $this->semStack[$stackPos-(2-2)], $stackPos-(2-2)); $this->semValue = $this->semStack[$stackPos-(2-1)] | $this->semStack[$stackPos-(2-2)];
+            },
+            280 => function ($stackPos) {
+                 $this->semValue = Stmt\Class_::MODIFIER_PUBLIC;
+            },
+            281 => function ($stackPos) {
+                 $this->semValue = Stmt\Class_::MODIFIER_PROTECTED;
+            },
+            282 => function ($stackPos) {
+                 $this->semValue = Stmt\Class_::MODIFIER_PRIVATE;
+            },
+            283 => function ($stackPos) {
+                 $this->semValue = Stmt\Class_::MODIFIER_STATIC;
+            },
+            284 => function ($stackPos) {
+                 $this->semValue = Stmt\Class_::MODIFIER_ABSTRACT;
+            },
+            285 => function ($stackPos) {
+                 $this->semValue = Stmt\Class_::MODIFIER_FINAL;
+            },
+            286 => function ($stackPos) {
+                 $this->semValue = array($this->semStack[$stackPos-(1-1)]);
+            },
+            287 => function ($stackPos) {
+                 $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)];
+            },
+            288 => function ($stackPos) {
+                 $this->semValue = new Node\VarLikeIdentifier(substr($this->semStack[$stackPos-(1-1)], 1), $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes);
+            },
+            289 => function ($stackPos) {
+                 $this->semValue = new Stmt\PropertyProperty($this->semStack[$stackPos-(1-1)], null, $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes);
+            },
+            290 => function ($stackPos) {
+                 $this->semValue = new Stmt\PropertyProperty($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            291 => function ($stackPos) {
+                 $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)];
+            },
+            292 => function ($stackPos) {
+                 $this->semValue = array($this->semStack[$stackPos-(1-1)]);
+            },
+            293 => function ($stackPos) {
+                 $this->semValue = array();
+            },
+            294 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(1-1)];
+            },
+            295 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(1-1)];
+            },
+            296 => function ($stackPos) {
+                 $this->semValue = new Expr\Assign($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            297 => function ($stackPos) {
+                 $this->semValue = new Expr\Assign($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            298 => function ($stackPos) {
+                 $this->semValue = new Expr\AssignRef($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-4)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes);
+            },
+            299 => function ($stackPos) {
+                 $this->semValue = new Expr\AssignRef($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-4)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes);
+            },
+            300 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(1-1)];
+            },
+            301 => function ($stackPos) {
+                 $this->semValue = new Expr\Clone_($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes);
+            },
+            302 => function ($stackPos) {
+                 $this->semValue = new Expr\AssignOp\Plus($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            303 => function ($stackPos) {
+                 $this->semValue = new Expr\AssignOp\Minus($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            304 => function ($stackPos) {
+                 $this->semValue = new Expr\AssignOp\Mul($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            305 => function ($stackPos) {
+                 $this->semValue = new Expr\AssignOp\Div($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            306 => function ($stackPos) {
+                 $this->semValue = new Expr\AssignOp\Concat($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            307 => function ($stackPos) {
+                 $this->semValue = new Expr\AssignOp\Mod($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            308 => function ($stackPos) {
+                 $this->semValue = new Expr\AssignOp\BitwiseAnd($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            309 => function ($stackPos) {
+                 $this->semValue = new Expr\AssignOp\BitwiseOr($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            310 => function ($stackPos) {
+                 $this->semValue = new Expr\AssignOp\BitwiseXor($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            311 => function ($stackPos) {
+                 $this->semValue = new Expr\AssignOp\ShiftLeft($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            312 => function ($stackPos) {
+                 $this->semValue = new Expr\AssignOp\ShiftRight($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            313 => function ($stackPos) {
+                 $this->semValue = new Expr\AssignOp\Pow($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            314 => function ($stackPos) {
+                 $this->semValue = new Expr\AssignOp\Coalesce($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            315 => function ($stackPos) {
+                 $this->semValue = new Expr\PostInc($this->semStack[$stackPos-(2-1)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes);
+            },
+            316 => function ($stackPos) {
+                 $this->semValue = new Expr\PreInc($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes);
+            },
+            317 => function ($stackPos) {
+                 $this->semValue = new Expr\PostDec($this->semStack[$stackPos-(2-1)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes);
+            },
+            318 => function ($stackPos) {
+                 $this->semValue = new Expr\PreDec($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes);
+            },
+            319 => function ($stackPos) {
+                 $this->semValue = new Expr\BinaryOp\BooleanOr($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            320 => function ($stackPos) {
+                 $this->semValue = new Expr\BinaryOp\BooleanAnd($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            321 => function ($stackPos) {
+                 $this->semValue = new Expr\BinaryOp\LogicalOr($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            322 => function ($stackPos) {
+                 $this->semValue = new Expr\BinaryOp\LogicalAnd($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            323 => function ($stackPos) {
+                 $this->semValue = new Expr\BinaryOp\LogicalXor($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            324 => function ($stackPos) {
+                 $this->semValue = new Expr\BinaryOp\BitwiseOr($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            325 => function ($stackPos) {
+                 $this->semValue = new Expr\BinaryOp\BitwiseAnd($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            326 => function ($stackPos) {
+                 $this->semValue = new Expr\BinaryOp\BitwiseXor($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            327 => function ($stackPos) {
+                 $this->semValue = new Expr\BinaryOp\Concat($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            328 => function ($stackPos) {
+                 $this->semValue = new Expr\BinaryOp\Plus($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            329 => function ($stackPos) {
+                 $this->semValue = new Expr\BinaryOp\Minus($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            330 => function ($stackPos) {
+                 $this->semValue = new Expr\BinaryOp\Mul($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            331 => function ($stackPos) {
+                 $this->semValue = new Expr\BinaryOp\Div($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            332 => function ($stackPos) {
+                 $this->semValue = new Expr\BinaryOp\Mod($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            333 => function ($stackPos) {
+                 $this->semValue = new Expr\BinaryOp\ShiftLeft($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            334 => function ($stackPos) {
+                 $this->semValue = new Expr\BinaryOp\ShiftRight($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            335 => function ($stackPos) {
+                 $this->semValue = new Expr\BinaryOp\Pow($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            336 => function ($stackPos) {
+                 $this->semValue = new Expr\UnaryPlus($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes);
+            },
+            337 => function ($stackPos) {
+                 $this->semValue = new Expr\UnaryMinus($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes);
+            },
+            338 => function ($stackPos) {
+                 $this->semValue = new Expr\BooleanNot($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes);
+            },
+            339 => function ($stackPos) {
+                 $this->semValue = new Expr\BitwiseNot($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes);
+            },
+            340 => function ($stackPos) {
+                 $this->semValue = new Expr\BinaryOp\Identical($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            341 => function ($stackPos) {
+                 $this->semValue = new Expr\BinaryOp\NotIdentical($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            342 => function ($stackPos) {
+                 $this->semValue = new Expr\BinaryOp\Equal($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            343 => function ($stackPos) {
+                 $this->semValue = new Expr\BinaryOp\NotEqual($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            344 => function ($stackPos) {
+                 $this->semValue = new Expr\BinaryOp\Spaceship($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            345 => function ($stackPos) {
+                 $this->semValue = new Expr\BinaryOp\Smaller($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            346 => function ($stackPos) {
+                 $this->semValue = new Expr\BinaryOp\SmallerOrEqual($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            347 => function ($stackPos) {
+                 $this->semValue = new Expr\BinaryOp\Greater($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            348 => function ($stackPos) {
+                 $this->semValue = new Expr\BinaryOp\GreaterOrEqual($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            349 => function ($stackPos) {
+                 $this->semValue = new Expr\Instanceof_($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            350 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(1-1)];
+            },
+            351 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(3-2)];
+            },
+            352 => function ($stackPos) {
+                 $this->semValue = new Expr\Ternary($this->semStack[$stackPos-(5-1)], $this->semStack[$stackPos-(5-3)], $this->semStack[$stackPos-(5-5)], $this->startAttributeStack[$stackPos-(5-1)] + $this->endAttributes);
+            },
+            353 => function ($stackPos) {
+                 $this->semValue = new Expr\Ternary($this->semStack[$stackPos-(4-1)], null, $this->semStack[$stackPos-(4-4)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes);
+            },
+            354 => function ($stackPos) {
+                 $this->semValue = new Expr\BinaryOp\Coalesce($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            355 => function ($stackPos) {
+                 $this->semValue = new Expr\Isset_($this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes);
+            },
+            356 => function ($stackPos) {
+                 $this->semValue = new Expr\Empty_($this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes);
+            },
+            357 => function ($stackPos) {
+                 $this->semValue = new Expr\Include_($this->semStack[$stackPos-(2-2)], Expr\Include_::TYPE_INCLUDE, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes);
+            },
+            358 => function ($stackPos) {
+                 $this->semValue = new Expr\Include_($this->semStack[$stackPos-(2-2)], Expr\Include_::TYPE_INCLUDE_ONCE, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes);
+            },
+            359 => function ($stackPos) {
+                 $this->semValue = new Expr\Eval_($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes);
+            },
+            360 => function ($stackPos) {
+                 $this->semValue = new Expr\Include_($this->semStack[$stackPos-(2-2)], Expr\Include_::TYPE_REQUIRE, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes);
+            },
+            361 => function ($stackPos) {
+                 $this->semValue = new Expr\Include_($this->semStack[$stackPos-(2-2)], Expr\Include_::TYPE_REQUIRE_ONCE, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes);
+            },
+            362 => function ($stackPos) {
+                 $this->semValue = new Expr\Cast\Int_($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes);
+            },
+            363 => function ($stackPos) {
+                 $attrs = $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes;
+            $attrs['kind'] = $this->getFloatCastKind($this->semStack[$stackPos-(2-1)]);
+            $this->semValue = new Expr\Cast\Double($this->semStack[$stackPos-(2-2)], $attrs);
+            },
+            364 => function ($stackPos) {
+                 $this->semValue = new Expr\Cast\String_($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes);
+            },
+            365 => function ($stackPos) {
+                 $this->semValue = new Expr\Cast\Array_($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes);
+            },
+            366 => function ($stackPos) {
+                 $this->semValue = new Expr\Cast\Object_($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes);
+            },
+            367 => function ($stackPos) {
+                 $this->semValue = new Expr\Cast\Bool_($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes);
+            },
+            368 => function ($stackPos) {
+                 $this->semValue = new Expr\Cast\Unset_($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes);
+            },
+            369 => function ($stackPos) {
+                 $attrs = $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes;
+            $attrs['kind'] = strtolower($this->semStack[$stackPos-(2-1)]) === 'exit' ? Expr\Exit_::KIND_EXIT : Expr\Exit_::KIND_DIE;
+            $this->semValue = new Expr\Exit_($this->semStack[$stackPos-(2-2)], $attrs);
+            },
+            370 => function ($stackPos) {
+                 $this->semValue = new Expr\ErrorSuppress($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes);
+            },
+            371 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(1-1)];
+            },
+            372 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(1-1)];
+            },
+            373 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(1-1)];
+            },
+            374 => function ($stackPos) {
+                 $this->semValue = new Expr\ShellExec($this->semStack[$stackPos-(3-2)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            375 => function ($stackPos) {
+                 $this->semValue = new Expr\Print_($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes);
+            },
+            376 => function ($stackPos) {
+                 $this->semValue = new Expr\Yield_(null, null, $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes);
+            },
+            377 => function ($stackPos) {
+                 $this->semValue = new Expr\YieldFrom($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes);
+            },
+            378 => function ($stackPos) {
+                 $this->semValue = new Expr\Closure(['static' => false, 'byRef' => $this->semStack[$stackPos-(10-2)], 'params' => $this->semStack[$stackPos-(10-4)], 'uses' => $this->semStack[$stackPos-(10-6)], 'returnType' => $this->semStack[$stackPos-(10-7)], 'stmts' => $this->semStack[$stackPos-(10-9)]], $this->startAttributeStack[$stackPos-(10-1)] + $this->endAttributes);
+            },
+            379 => function ($stackPos) {
+                 $this->semValue = new Expr\Closure(['static' => true, 'byRef' => $this->semStack[$stackPos-(11-3)], 'params' => $this->semStack[$stackPos-(11-5)], 'uses' => $this->semStack[$stackPos-(11-7)], 'returnType' => $this->semStack[$stackPos-(11-8)], 'stmts' => $this->semStack[$stackPos-(11-10)]], $this->startAttributeStack[$stackPos-(11-1)] + $this->endAttributes);
+            },
+            380 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(3-2)];
+            },
+            381 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(3-2)];
+            },
+            382 => function ($stackPos) {
+                 $this->semValue = new Expr\Yield_($this->semStack[$stackPos-(2-2)], null, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes);
+            },
+            383 => function ($stackPos) {
+                 $this->semValue = new Expr\Yield_($this->semStack[$stackPos-(4-4)], $this->semStack[$stackPos-(4-2)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes);
+            },
+            384 => function ($stackPos) {
+                 $attrs = $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes; $attrs['kind'] = Expr\Array_::KIND_LONG;
+            $this->semValue = new Expr\Array_($this->semStack[$stackPos-(4-3)], $attrs);
+            },
+            385 => function ($stackPos) {
+                 $attrs = $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes; $attrs['kind'] = Expr\Array_::KIND_SHORT;
+            $this->semValue = new Expr\Array_($this->semStack[$stackPos-(3-2)], $attrs);
+            },
+            386 => function ($stackPos) {
+                 $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes);
+            },
+            387 => function ($stackPos) {
+                 $attrs = $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes; $attrs['kind'] = ($this->semStack[$stackPos-(4-1)][0] === "'" || ($this->semStack[$stackPos-(4-1)][1] === "'" && ($this->semStack[$stackPos-(4-1)][0] === 'b' || $this->semStack[$stackPos-(4-1)][0] === 'B')) ? Scalar\String_::KIND_SINGLE_QUOTED : Scalar\String_::KIND_DOUBLE_QUOTED);
+            $this->semValue = new Expr\ArrayDimFetch(new Scalar\String_(Scalar\String_::parse($this->semStack[$stackPos-(4-1)]), $attrs), $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes);
+            },
+            388 => function ($stackPos) {
+                 $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes);
+            },
+            389 => function ($stackPos) {
+                 $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes);
+            },
+            390 => function ($stackPos) {
+                 $this->semValue = array(new Stmt\Class_(null, ['type' => 0, 'extends' => $this->semStack[$stackPos-(7-3)], 'implements' => $this->semStack[$stackPos-(7-4)], 'stmts' => $this->semStack[$stackPos-(7-6)]], $this->startAttributeStack[$stackPos-(7-1)] + $this->endAttributes), $this->semStack[$stackPos-(7-2)]);
+            $this->checkClass($this->semValue[0], -1);
+            },
+            391 => function ($stackPos) {
+                 $this->semValue = new Expr\New_($this->semStack[$stackPos-(3-2)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            392 => function ($stackPos) {
+                 list($class, $ctorArgs) = $this->semStack[$stackPos-(2-2)]; $this->semValue = new Expr\New_($class, $ctorArgs, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes);
+            },
+            393 => function ($stackPos) {
+                 $this->semValue = array();
+            },
+            394 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(4-3)];
+            },
+            395 => function ($stackPos) {
+                 $this->semValue = array($this->semStack[$stackPos-(1-1)]);
+            },
+            396 => function ($stackPos) {
+                 $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)];
+            },
+            397 => function ($stackPos) {
+                 $this->semValue = new Expr\ClosureUse($this->semStack[$stackPos-(2-2)], $this->semStack[$stackPos-(2-1)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes);
+            },
+            398 => function ($stackPos) {
+                 $this->semValue = new Expr\FuncCall($this->semStack[$stackPos-(2-1)], $this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes);
+            },
+            399 => function ($stackPos) {
+                 $this->semValue = new Expr\StaticCall($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-3)], $this->semStack[$stackPos-(4-4)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes);
+            },
+            400 => function ($stackPos) {
+                 $this->semValue = new Expr\StaticCall($this->semStack[$stackPos-(6-1)], $this->semStack[$stackPos-(6-4)], $this->semStack[$stackPos-(6-6)], $this->startAttributeStack[$stackPos-(6-1)] + $this->endAttributes);
+            },
+            401 => function ($stackPos) {
+                 $this->semValue = $this->fixupPhp5StaticPropCall($this->semStack[$stackPos-(2-1)], $this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes);
+            },
+            402 => function ($stackPos) {
+                 $this->semValue = new Expr\FuncCall($this->semStack[$stackPos-(2-1)], $this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes);
+            },
+            403 => function ($stackPos) {
+                 $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes);
+            },
+            404 => function ($stackPos) {
+                 $this->semValue = new Name($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes);
+            },
+            405 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(1-1)];
+            },
+            406 => function ($stackPos) {
+                 $this->semValue = new Name($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes);
+            },
+            407 => function ($stackPos) {
+                 $this->semValue = new Name($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes);
+            },
+            408 => function ($stackPos) {
+                 $this->semValue = new Name\FullyQualified(substr($this->semStack[$stackPos-(1-1)], 1), $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes);
+            },
+            409 => function ($stackPos) {
+                 $this->semValue = new Name\Relative(substr($this->semStack[$stackPos-(1-1)], 10), $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes);
+            },
+            410 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(1-1)];
+            },
+            411 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(1-1)];
+            },
+            412 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(1-1)];
+            },
+            413 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(1-1)];
+            },
+            414 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(1-1)];
+            },
+            415 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(1-1)];
+            },
+            416 => function ($stackPos) {
+                 $this->semValue = new Expr\PropertyFetch($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            417 => function ($stackPos) {
+                 $this->semValue = new Expr\PropertyFetch($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            418 => function ($stackPos) {
+                 $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes);
+            },
+            419 => function ($stackPos) {
+                 $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes);
+            },
+            420 => function ($stackPos) {
+                 $this->semValue = null;
+            },
+            421 => function ($stackPos) {
+                 $this->semValue = null;
+            },
+            422 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(1-1)];
+            },
+            423 => function ($stackPos) {
+                 $this->semValue = array();
+            },
+            424 => function ($stackPos) {
+                 $this->semValue = array(new Scalar\EncapsedStringPart(Scalar\String_::parseEscapeSequences($this->semStack[$stackPos-(1-1)], '`', false), $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes));
+            },
+            425 => function ($stackPos) {
+                 foreach ($this->semStack[$stackPos-(1-1)] as $s) { if ($s instanceof Node\Scalar\EncapsedStringPart) { $s->value = Node\Scalar\String_::parseEscapeSequences($s->value, '`', false); } }; $this->semValue = $this->semStack[$stackPos-(1-1)];
+            },
+            426 => function ($stackPos) {
+                 $this->semValue = array();
+            },
+            427 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(1-1)];
+            },
+            428 => function ($stackPos) {
+                 $this->semValue = $this->parseLNumber($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes, true);
+            },
+            429 => function ($stackPos) {
+                 $this->semValue = new Scalar\DNumber(Scalar\DNumber::parse($this->semStack[$stackPos-(1-1)]), $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes);
+            },
+            430 => function ($stackPos) {
+                 $attrs = $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes; $attrs['kind'] = ($this->semStack[$stackPos-(1-1)][0] === "'" || ($this->semStack[$stackPos-(1-1)][1] === "'" && ($this->semStack[$stackPos-(1-1)][0] === 'b' || $this->semStack[$stackPos-(1-1)][0] === 'B')) ? Scalar\String_::KIND_SINGLE_QUOTED : Scalar\String_::KIND_DOUBLE_QUOTED);
+            $this->semValue = new Scalar\String_(Scalar\String_::parse($this->semStack[$stackPos-(1-1)], false), $attrs);
+            },
+            431 => function ($stackPos) {
+                 $this->semValue = new Scalar\MagicConst\Line($this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes);
+            },
+            432 => function ($stackPos) {
+                 $this->semValue = new Scalar\MagicConst\File($this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes);
+            },
+            433 => function ($stackPos) {
+                 $this->semValue = new Scalar\MagicConst\Dir($this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes);
+            },
+            434 => function ($stackPos) {
+                 $this->semValue = new Scalar\MagicConst\Class_($this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes);
+            },
+            435 => function ($stackPos) {
+                 $this->semValue = new Scalar\MagicConst\Trait_($this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes);
+            },
+            436 => function ($stackPos) {
+                 $this->semValue = new Scalar\MagicConst\Method($this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes);
+            },
+            437 => function ($stackPos) {
+                 $this->semValue = new Scalar\MagicConst\Function_($this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes);
+            },
+            438 => function ($stackPos) {
+                 $this->semValue = new Scalar\MagicConst\Namespace_($this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes);
+            },
+            439 => function ($stackPos) {
+                 $this->semValue = $this->parseDocString($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-2)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes, $this->startAttributeStack[$stackPos-(3-3)] + $this->endAttributeStack[$stackPos-(3-3)], false);
+            },
+            440 => function ($stackPos) {
+                 $this->semValue = $this->parseDocString($this->semStack[$stackPos-(2-1)], '', $this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes, $this->startAttributeStack[$stackPos-(2-2)] + $this->endAttributeStack[$stackPos-(2-2)], false);
+            },
+            441 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(1-1)];
+            },
+            442 => function ($stackPos) {
+                 $this->semValue = new Expr\ClassConstFetch($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            443 => function ($stackPos) {
+                 $this->semValue = new Expr\ConstFetch($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes);
+            },
+            444 => function ($stackPos) {
+                 $this->semValue = new Expr\Array_($this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes);
+            },
+            445 => function ($stackPos) {
+                 $this->semValue = new Expr\Array_($this->semStack[$stackPos-(3-2)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            446 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(1-1)];
+            },
+            447 => function ($stackPos) {
+                 $this->semValue = new Expr\BinaryOp\BooleanOr($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            448 => function ($stackPos) {
+                 $this->semValue = new Expr\BinaryOp\BooleanAnd($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            449 => function ($stackPos) {
+                 $this->semValue = new Expr\BinaryOp\LogicalOr($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            450 => function ($stackPos) {
+                 $this->semValue = new Expr\BinaryOp\LogicalAnd($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            451 => function ($stackPos) {
+                 $this->semValue = new Expr\BinaryOp\LogicalXor($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            452 => function ($stackPos) {
+                 $this->semValue = new Expr\BinaryOp\BitwiseOr($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            453 => function ($stackPos) {
+                 $this->semValue = new Expr\BinaryOp\BitwiseAnd($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            454 => function ($stackPos) {
+                 $this->semValue = new Expr\BinaryOp\BitwiseXor($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            455 => function ($stackPos) {
+                 $this->semValue = new Expr\BinaryOp\Concat($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            456 => function ($stackPos) {
+                 $this->semValue = new Expr\BinaryOp\Plus($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            457 => function ($stackPos) {
+                 $this->semValue = new Expr\BinaryOp\Minus($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            458 => function ($stackPos) {
+                 $this->semValue = new Expr\BinaryOp\Mul($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            459 => function ($stackPos) {
+                 $this->semValue = new Expr\BinaryOp\Div($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            460 => function ($stackPos) {
+                 $this->semValue = new Expr\BinaryOp\Mod($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            461 => function ($stackPos) {
+                 $this->semValue = new Expr\BinaryOp\ShiftLeft($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            462 => function ($stackPos) {
+                 $this->semValue = new Expr\BinaryOp\ShiftRight($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            463 => function ($stackPos) {
+                 $this->semValue = new Expr\BinaryOp\Pow($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            464 => function ($stackPos) {
+                 $this->semValue = new Expr\UnaryPlus($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes);
+            },
+            465 => function ($stackPos) {
+                 $this->semValue = new Expr\UnaryMinus($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes);
+            },
+            466 => function ($stackPos) {
+                 $this->semValue = new Expr\BooleanNot($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes);
+            },
+            467 => function ($stackPos) {
+                 $this->semValue = new Expr\BitwiseNot($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes);
+            },
+            468 => function ($stackPos) {
+                 $this->semValue = new Expr\BinaryOp\Identical($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            469 => function ($stackPos) {
+                 $this->semValue = new Expr\BinaryOp\NotIdentical($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            470 => function ($stackPos) {
+                 $this->semValue = new Expr\BinaryOp\Equal($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            471 => function ($stackPos) {
+                 $this->semValue = new Expr\BinaryOp\NotEqual($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            472 => function ($stackPos) {
+                 $this->semValue = new Expr\BinaryOp\Smaller($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            473 => function ($stackPos) {
+                 $this->semValue = new Expr\BinaryOp\SmallerOrEqual($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            474 => function ($stackPos) {
+                 $this->semValue = new Expr\BinaryOp\Greater($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            475 => function ($stackPos) {
+                 $this->semValue = new Expr\BinaryOp\GreaterOrEqual($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            476 => function ($stackPos) {
+                 $this->semValue = new Expr\Ternary($this->semStack[$stackPos-(5-1)], $this->semStack[$stackPos-(5-3)], $this->semStack[$stackPos-(5-5)], $this->startAttributeStack[$stackPos-(5-1)] + $this->endAttributes);
+            },
+            477 => function ($stackPos) {
+                 $this->semValue = new Expr\Ternary($this->semStack[$stackPos-(4-1)], null, $this->semStack[$stackPos-(4-4)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes);
+            },
+            478 => function ($stackPos) {
+                 $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes);
+            },
+            479 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(3-2)];
+            },
+            480 => function ($stackPos) {
+                 $this->semValue = new Expr\ConstFetch($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes);
+            },
+            481 => function ($stackPos) {
+                 $this->semValue = new Expr\ClassConstFetch($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            482 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(1-1)];
+            },
+            483 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(1-1)];
+            },
+            484 => function ($stackPos) {
+                 $attrs = $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes; $attrs['kind'] = Scalar\String_::KIND_DOUBLE_QUOTED;
+            foreach ($this->semStack[$stackPos-(3-2)] as $s) { if ($s instanceof Node\Scalar\EncapsedStringPart) { $s->value = Node\Scalar\String_::parseEscapeSequences($s->value, '"', true); } }; $this->semValue = new Scalar\Encapsed($this->semStack[$stackPos-(3-2)], $attrs);
+            },
+            485 => function ($stackPos) {
+                 $this->semValue = $this->parseDocString($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-2)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes, $this->startAttributeStack[$stackPos-(3-3)] + $this->endAttributeStack[$stackPos-(3-3)], true);
+            },
+            486 => function ($stackPos) {
+                 $this->semValue = array();
+            },
+            487 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(2-1)];
+            },
+            488 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            489 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            490 => function ($stackPos) {
+                 $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)];
+            },
+            491 => function ($stackPos) {
+                 $this->semValue = array($this->semStack[$stackPos-(1-1)]);
+            },
+            492 => function ($stackPos) {
+                 $this->semValue = new Expr\ArrayItem($this->semStack[$stackPos-(3-3)], $this->semStack[$stackPos-(3-1)], false, $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            493 => function ($stackPos) {
+                 $this->semValue = new Expr\ArrayItem($this->semStack[$stackPos-(1-1)], null, false, $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes);
+            },
+            494 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(1-1)];
+            },
+            495 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(1-1)];
+            },
+            496 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(1-1)];
+            },
+            497 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(1-1)];
+            },
+            498 => function ($stackPos) {
+                 $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos-(6-2)], $this->semStack[$stackPos-(6-5)], $this->startAttributeStack[$stackPos-(6-1)] + $this->endAttributes);
+            },
+            499 => function ($stackPos) {
+                 $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes);
+            },
+            500 => function ($stackPos) {
+                 $this->semValue = new Expr\PropertyFetch($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            501 => function ($stackPos) {
+                 $this->semValue = new Expr\MethodCall($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-3)], $this->semStack[$stackPos-(4-4)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes);
+            },
+            502 => function ($stackPos) {
+                 $this->semValue = new Expr\FuncCall($this->semStack[$stackPos-(2-1)], $this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes);
+            },
+            503 => function ($stackPos) {
+                 $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes);
+            },
+            504 => function ($stackPos) {
+                 $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes);
+            },
+            505 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(1-1)];
+            },
+            506 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(3-2)];
+            },
+            507 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(1-1)];
+            },
+            508 => function ($stackPos) {
+                 $this->semValue = new Expr\Variable($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes);
+            },
+            509 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(1-1)];
+            },
+            510 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(1-1)];
+            },
+            511 => function ($stackPos) {
+                 $this->semValue = new Expr\StaticPropertyFetch($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-4)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes);
+            },
+            512 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(1-1)];
+            },
+            513 => function ($stackPos) {
+                 $var = substr($this->semStack[$stackPos-(1-1)], 1); $this->semValue = \is_string($var) ? new Node\VarLikeIdentifier($var, $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes) : $var;
+            },
+            514 => function ($stackPos) {
+                 $this->semValue = new Expr\StaticPropertyFetch($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            515 => function ($stackPos) {
+                 $this->semValue = new Expr\StaticPropertyFetch($this->semStack[$stackPos-(6-1)], $this->semStack[$stackPos-(6-5)], $this->startAttributeStack[$stackPos-(6-1)] + $this->endAttributes);
+            },
+            516 => function ($stackPos) {
+                 $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes);
+            },
+            517 => function ($stackPos) {
+                 $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes);
+            },
+            518 => function ($stackPos) {
+                 $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes);
+            },
+            519 => function ($stackPos) {
+                 $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes);
+            },
+            520 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(1-1)];
+            },
+            521 => function ($stackPos) {
+                 $this->semValue = new Expr\Variable($this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes);
+            },
+            522 => function ($stackPos) {
+                 $this->semValue = null;
+            },
+            523 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(1-1)];
+            },
+            524 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(1-1)];
+            },
+            525 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(3-2)];
+            },
+            526 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(1-1)];
+            },
+            527 => function ($stackPos) {
+                 $this->semValue = new Expr\Error($this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); $this->errorState = 2;
+            },
+            528 => function ($stackPos) {
+                 $this->semValue = new Expr\List_($this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes);
+            },
+            529 => function ($stackPos) {
+                 $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)];
+            },
+            530 => function ($stackPos) {
+                 $this->semValue = array($this->semStack[$stackPos-(1-1)]);
+            },
+            531 => function ($stackPos) {
+                 $this->semValue = new Expr\ArrayItem($this->semStack[$stackPos-(1-1)], null, false, $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes);
+            },
+            532 => function ($stackPos) {
+                 $this->semValue = new Expr\ArrayItem($this->semStack[$stackPos-(1-1)], null, false, $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes);
+            },
+            533 => function ($stackPos) {
+                 $this->semValue = null;
+            },
+            534 => function ($stackPos) {
+                 $this->semValue = array();
+            },
+            535 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(2-1)];
+            },
+            536 => function ($stackPos) {
+                 $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)];
+            },
+            537 => function ($stackPos) {
+                 $this->semValue = array($this->semStack[$stackPos-(1-1)]);
+            },
+            538 => function ($stackPos) {
+                 $this->semValue = new Expr\ArrayItem($this->semStack[$stackPos-(3-3)], $this->semStack[$stackPos-(3-1)], false, $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            539 => function ($stackPos) {
+                 $this->semValue = new Expr\ArrayItem($this->semStack[$stackPos-(1-1)], null, false, $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes);
+            },
+            540 => function ($stackPos) {
+                 $this->semValue = new Expr\ArrayItem($this->semStack[$stackPos-(4-4)], $this->semStack[$stackPos-(4-1)], true, $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes);
+            },
+            541 => function ($stackPos) {
+                 $this->semValue = new Expr\ArrayItem($this->semStack[$stackPos-(2-2)], null, true, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes);
+            },
+            542 => function ($stackPos) {
+                 $this->semValue = new Expr\ArrayItem($this->semStack[$stackPos-(2-2)], null, false, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes, true, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes);
+            },
+            543 => function ($stackPos) {
+                 $this->semStack[$stackPos-(2-1)][] = $this->semStack[$stackPos-(2-2)]; $this->semValue = $this->semStack[$stackPos-(2-1)];
+            },
+            544 => function ($stackPos) {
+                 $this->semStack[$stackPos-(2-1)][] = $this->semStack[$stackPos-(2-2)]; $this->semValue = $this->semStack[$stackPos-(2-1)];
+            },
+            545 => function ($stackPos) {
+                 $this->semValue = array($this->semStack[$stackPos-(1-1)]);
+            },
+            546 => function ($stackPos) {
+                 $this->semValue = array($this->semStack[$stackPos-(2-1)], $this->semStack[$stackPos-(2-2)]);
+            },
+            547 => function ($stackPos) {
+                 $this->semValue = new Scalar\EncapsedStringPart($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes);
+            },
+            548 => function ($stackPos) {
+                 $this->semValue = new Expr\Variable($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes);
+            },
+            549 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(1-1)];
+            },
+            550 => function ($stackPos) {
+                 $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes);
+            },
+            551 => function ($stackPos) {
+                 $this->semValue = new Expr\PropertyFetch($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            552 => function ($stackPos) {
+                 $this->semValue = new Expr\Variable($this->semStack[$stackPos-(3-2)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            553 => function ($stackPos) {
+                 $this->semValue = new Expr\Variable($this->semStack[$stackPos-(3-2)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            554 => function ($stackPos) {
+                 $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos-(6-2)], $this->semStack[$stackPos-(6-4)], $this->startAttributeStack[$stackPos-(6-1)] + $this->endAttributes);
+            },
+            555 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(3-2)];
+            },
+            556 => function ($stackPos) {
+                 $this->semValue = new Scalar\String_($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes);
+            },
+            557 => function ($stackPos) {
+                 $this->semValue = $this->parseNumString($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes);
+            },
+            558 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(1-1)];
+            },
+        ];
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Parser/Php7.php b/vendor/nikic/php-parser/lib/PhpParser/Parser/Php7.php
new file mode 100644
index 0000000000000000000000000000000000000000..55d16585b45b1ecb5b28df5596550d338e3ed44f
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Parser/Php7.php
@@ -0,0 +1,2718 @@
+<?php
+
+namespace PhpParser\Parser;
+
+use PhpParser\Error;
+use PhpParser\Node;
+use PhpParser\Node\Expr;
+use PhpParser\Node\Name;
+use PhpParser\Node\Scalar;
+use PhpParser\Node\Stmt;
+
+/* This is an automatically GENERATED file, which should not be manually edited.
+ * Instead edit one of the following:
+ *  * the grammar files grammar/php5.y or grammar/php7.y
+ *  * the skeleton file grammar/parser.template
+ *  * the preprocessing script grammar/rebuildParsers.php
+ */
+class Php7 extends \PhpParser\ParserAbstract
+{
+    protected $tokenToSymbolMapSize = 392;
+    protected $actionTableSize = 1162;
+    protected $gotoTableSize = 588;
+
+    protected $invalidSymbol = 165;
+    protected $errorSymbol = 1;
+    protected $defaultAction = -32766;
+    protected $unexpectedTokenRule = 32767;
+
+    protected $YY2TBLSTATE = 397;
+    protected $numNonLeafStates = 688;
+
+    protected $symbolToName = array(
+        "EOF",
+        "error",
+        "T_THROW",
+        "T_INCLUDE",
+        "T_INCLUDE_ONCE",
+        "T_EVAL",
+        "T_REQUIRE",
+        "T_REQUIRE_ONCE",
+        "','",
+        "T_LOGICAL_OR",
+        "T_LOGICAL_XOR",
+        "T_LOGICAL_AND",
+        "T_PRINT",
+        "T_YIELD",
+        "T_DOUBLE_ARROW",
+        "T_YIELD_FROM",
+        "'='",
+        "T_PLUS_EQUAL",
+        "T_MINUS_EQUAL",
+        "T_MUL_EQUAL",
+        "T_DIV_EQUAL",
+        "T_CONCAT_EQUAL",
+        "T_MOD_EQUAL",
+        "T_AND_EQUAL",
+        "T_OR_EQUAL",
+        "T_XOR_EQUAL",
+        "T_SL_EQUAL",
+        "T_SR_EQUAL",
+        "T_POW_EQUAL",
+        "T_COALESCE_EQUAL",
+        "'?'",
+        "':'",
+        "T_COALESCE",
+        "T_BOOLEAN_OR",
+        "T_BOOLEAN_AND",
+        "'|'",
+        "'^'",
+        "'&'",
+        "T_IS_EQUAL",
+        "T_IS_NOT_EQUAL",
+        "T_IS_IDENTICAL",
+        "T_IS_NOT_IDENTICAL",
+        "T_SPACESHIP",
+        "'<'",
+        "T_IS_SMALLER_OR_EQUAL",
+        "'>'",
+        "T_IS_GREATER_OR_EQUAL",
+        "T_SL",
+        "T_SR",
+        "'+'",
+        "'-'",
+        "'.'",
+        "'*'",
+        "'/'",
+        "'%'",
+        "'!'",
+        "T_INSTANCEOF",
+        "'~'",
+        "T_INC",
+        "T_DEC",
+        "T_INT_CAST",
+        "T_DOUBLE_CAST",
+        "T_STRING_CAST",
+        "T_ARRAY_CAST",
+        "T_OBJECT_CAST",
+        "T_BOOL_CAST",
+        "T_UNSET_CAST",
+        "'@'",
+        "T_POW",
+        "'['",
+        "T_NEW",
+        "T_CLONE",
+        "T_EXIT",
+        "T_IF",
+        "T_ELSEIF",
+        "T_ELSE",
+        "T_ENDIF",
+        "T_LNUMBER",
+        "T_DNUMBER",
+        "T_STRING",
+        "T_STRING_VARNAME",
+        "T_VARIABLE",
+        "T_NUM_STRING",
+        "T_INLINE_HTML",
+        "T_ENCAPSED_AND_WHITESPACE",
+        "T_CONSTANT_ENCAPSED_STRING",
+        "T_ECHO",
+        "T_DO",
+        "T_WHILE",
+        "T_ENDWHILE",
+        "T_FOR",
+        "T_ENDFOR",
+        "T_FOREACH",
+        "T_ENDFOREACH",
+        "T_DECLARE",
+        "T_ENDDECLARE",
+        "T_AS",
+        "T_SWITCH",
+        "T_MATCH",
+        "T_ENDSWITCH",
+        "T_CASE",
+        "T_DEFAULT",
+        "T_BREAK",
+        "T_CONTINUE",
+        "T_GOTO",
+        "T_FUNCTION",
+        "T_FN",
+        "T_CONST",
+        "T_RETURN",
+        "T_TRY",
+        "T_CATCH",
+        "T_FINALLY",
+        "T_USE",
+        "T_INSTEADOF",
+        "T_GLOBAL",
+        "T_STATIC",
+        "T_ABSTRACT",
+        "T_FINAL",
+        "T_PRIVATE",
+        "T_PROTECTED",
+        "T_PUBLIC",
+        "T_VAR",
+        "T_UNSET",
+        "T_ISSET",
+        "T_EMPTY",
+        "T_HALT_COMPILER",
+        "T_CLASS",
+        "T_TRAIT",
+        "T_INTERFACE",
+        "T_EXTENDS",
+        "T_IMPLEMENTS",
+        "T_OBJECT_OPERATOR",
+        "T_NULLSAFE_OBJECT_OPERATOR",
+        "T_LIST",
+        "T_ARRAY",
+        "T_CALLABLE",
+        "T_CLASS_C",
+        "T_TRAIT_C",
+        "T_METHOD_C",
+        "T_FUNC_C",
+        "T_LINE",
+        "T_FILE",
+        "T_START_HEREDOC",
+        "T_END_HEREDOC",
+        "T_DOLLAR_OPEN_CURLY_BRACES",
+        "T_CURLY_OPEN",
+        "T_PAAMAYIM_NEKUDOTAYIM",
+        "T_NAMESPACE",
+        "T_NS_C",
+        "T_DIR",
+        "T_NS_SEPARATOR",
+        "T_ELLIPSIS",
+        "T_NAME_FULLY_QUALIFIED",
+        "T_NAME_QUALIFIED",
+        "T_NAME_RELATIVE",
+        "T_ATTRIBUTE",
+        "';'",
+        "']'",
+        "'{'",
+        "'}'",
+        "'('",
+        "')'",
+        "'`'",
+        "'\"'",
+        "'$'"
+    );
+
+    protected $tokenToSymbol = array(
+            0,  165,  165,  165,  165,  165,  165,  165,  165,  165,
+          165,  165,  165,  165,  165,  165,  165,  165,  165,  165,
+          165,  165,  165,  165,  165,  165,  165,  165,  165,  165,
+          165,  165,  165,   55,  163,  165,  164,   54,   37,  165,
+          160,  161,   52,   49,    8,   50,   51,   53,  165,  165,
+          165,  165,  165,  165,  165,  165,  165,  165,   31,  156,
+           43,   16,   45,   30,   67,  165,  165,  165,  165,  165,
+          165,  165,  165,  165,  165,  165,  165,  165,  165,  165,
+          165,  165,  165,  165,  165,  165,  165,  165,  165,  165,
+          165,   69,  165,  157,   36,  165,  162,  165,  165,  165,
+          165,  165,  165,  165,  165,  165,  165,  165,  165,  165,
+          165,  165,  165,  165,  165,  165,  165,  165,  165,  165,
+          165,  165,  165,  158,   35,  159,   57,  165,  165,  165,
+          165,  165,  165,  165,  165,  165,  165,  165,  165,  165,
+          165,  165,  165,  165,  165,  165,  165,  165,  165,  165,
+          165,  165,  165,  165,  165,  165,  165,  165,  165,  165,
+          165,  165,  165,  165,  165,  165,  165,  165,  165,  165,
+          165,  165,  165,  165,  165,  165,  165,  165,  165,  165,
+          165,  165,  165,  165,  165,  165,  165,  165,  165,  165,
+          165,  165,  165,  165,  165,  165,  165,  165,  165,  165,
+          165,  165,  165,  165,  165,  165,  165,  165,  165,  165,
+          165,  165,  165,  165,  165,  165,  165,  165,  165,  165,
+          165,  165,  165,  165,  165,  165,  165,  165,  165,  165,
+          165,  165,  165,  165,  165,  165,  165,  165,  165,  165,
+          165,  165,  165,  165,  165,  165,  165,  165,  165,  165,
+          165,  165,  165,  165,  165,  165,    1,    2,    3,    4,
+            5,    6,    7,    9,   10,   11,   12,   13,   14,   15,
+           17,   18,   19,   20,   21,   22,   23,   24,   25,   26,
+           27,   28,   29,   32,   33,   34,   38,   39,   40,   41,
+           42,   44,   46,   47,   48,   56,   58,   59,   60,   61,
+           62,   63,   64,   65,   66,   68,   70,   71,   72,   73,
+           74,   75,   76,   77,   78,   79,   80,   81,   82,   83,
+           84,   85,   86,   87,   88,   89,   90,   91,   92,   93,
+           94,   95,   96,   97,   98,   99,  100,  101,  102,  103,
+          104,  105,  106,  107,  108,  109,  110,  111,  112,  113,
+          114,  115,  116,  117,  118,  119,  120,  121,  122,  123,
+          124,  125,  126,  127,  128,  129,  130,  131,  132,  133,
+          134,  135,  136,  137,  138,  139,  140,  141,  142,  143,
+          144,  145,  146,  147,  148,  149,  150,  151,  152,  153,
+          154,  155
+    );
+
+    protected $action = array(
+          130,  131,  132,  552,  133,  134,    0,  698,  699,  700,
+          135,   36,  883,  528,  529,-32766, 1212,-32766,-32766,-32766,
+         -551, 1145,  772,  889,  430,  431, 1232, -551,-32766,-32766,
+        -32766, -293,-32766, 1231,-32766,  245,-32766, -189,-32766,-32766,
+        -32766,-32766,-32766,  458,-32766,-32766,-32766,-32766,-32766,-32766,
+        -32766,-32766,  124,  783,  701,  777,-32766,  388, 1024, 1025,
+         1026, 1023, 1022, 1021,-32766,  428,  429,  955,  261,  136,
+          372,  705,  706,  707,  708,  391, -188,  397, 1024, 1025,
+         1026, 1023, 1022, 1021,  709,  710,  711,  712,  713,  714,
+          715,  716,  717,  718,  719,  739,  553,  740,  741,  742,
+          743,  731,  732,  373,  374,  734,  735,  720,  721,  722,
+          724,  725,  726,  333,  765,  766,  767,  768,  769,  727,
+          728,  554,  555,  760,  751,  749,  750,  746,  747,  778,
+            2,  556,  557,  745,  558,  559,  560,  561,  562,  563,
+         -542, -548,   19, -502, -542,  748,  564,  565, -548,  137,
+        -32766,-32766,-32766,  130,  131,  132,  552,  133,  134,  976,
+          698,  699,  700,  135,   36,-32766,-32766,-32766,-32766,  675,
+        -32766,-32766,-32766,   80, 1145,  544, -551,-32766,-32766,  309,
+         -551,-32766,-32766,-32766, -293,-32766,-32766,-32766,  245,-32766,
+         -189,-32766,-32766,-32766,-32766,-32766,-32766,-32766,-32766,-32766,
+           31,  433,  429,-32766,-32766, -502, -502,  701,  782,-32766,
+          388,  391,-32766,-32766,-32766,  235,  126,-32766,  -82,  142,
+         -502,  261,  136,  372,  705,  706,  707,  708,  247, -188,
+          397,  292, -502,-32766, -508,-32766,-32766,  709,  710,  711,
+          712,  713,  714,  715,  716,  717,  718,  719,  739,  553,
+          740,  741,  742,  743,  731,  732,  373,  374,  734,  735,
+          720,  721,  722,  724,  725,  726,  333,  765,  766,  767,
+          768,  769,  727,  728,  554,  555,  760,  751,  749,  750,
+          746,  747,  294,  -82,  556,  557,  745,  558,  559,  560,
+          561,  562,  563,  310,   81,   82,   83, -548,  748,  564,
+          565, -548,  137,  723,  693,  694,  695,  696,  697,-32766,
+          698,  699,  700,  736,  737,   33,  307,   84,   85,   86,
+           87,   88,   89,   90,   91,   92,   93,   94,   95,   96,
+           97,   98,   99,  100,  101,  102,  103,  104,  105,  106,
+          322,  263,-32766,-32766,-32766,  104,  105,  106,  346,  263,
+          952,  951,  950,  107,  350,  438,  439,  701,-32766,-32766,
+        -32766,  107, -253,-32766,  355,-32766,-32766,-32766,-32766,-32766,
+        -32766,  702,  703,  704,  705,  706,  707,  708,  452,-32766,
+          770,-32766,-32766,-32766,-32766,-32766,  357,  709,  710,  711,
+          712,  713,  714,  715,  716,  717,  718,  719,  739,  762,
+          740,  741,  742,  743,  731,  732,  733,  761,  734,  735,
+          720,  721,  722,  724,  725,  726,  764,  765,  766,  767,
+          768,  769,  727,  728,  729,  730,  760,  751,  749,  750,
+          746,  747,  619,   24,  738,  744,  745,  752,  753,  755,
+          754,  756,  757,  524,-32766,-32766,-32766,  574,  748,  759,
+          758,   48,   49,   50,  483,   51,   52,  147,  397,  580,
+          408,   53,   54,  409,   55,-32766,  975,-32766,-32766,-32766,
+        -32766,-32766,-32766,-32767,-32767,-32767,-32767,-32767,  865,-32767,
+        -32767,-32767,-32767,   99,  100,  101,  102,  103, 1257,  410,
+         1172, 1258,  411, 1145,  865,  271,  634,  635,   56,   57,
+          148,  808, 1184,  809,   58,  453,   59,  240,  241,   60,
+           61,   62,   63,   64,   65,   66,   67,  787,   26,  262,
+           68,  412,  484,  121,  667,-32766, 1178, 1179,  485, 1143,
+          781, 1147, 1146, 1148, 1176,   40,   23,  486, 1002,  487,
+          150,  488,  234,  489,  962,  963,  490,  491,  780,  423,
+          424,   42,   43,  413,  417,  415,  865,   44,  492,  151,
+          855,  920,  248,  345,  321, 1152, 1147, 1146, 1148,  122,
+          781,  493,  494,  495,  152, -330,  855, -330,  127, -505,
+          960,  154,  496,  497,   35, 1166, 1167, 1168, 1169, 1163,
+         1164,  280,  146,  377,   26,  -14,  128, 1170, 1165,  962,
+          963, 1147, 1146, 1148,  281,  141,  781, -501,  155,   69,
+         1176,  305,  306,  309,   34,  108,  109,  110,  111,  112,
+          113,  114,  115,  116,  117,  118,  119,  120,  156, -149,
+         -149, -149,  478,  867,   18,  662, 1152, 1152,  855,  440,
+          441, -505, -505,  157, -149,  781, -149,  138, -149,  867,
+         -149,  662,  808,  309,  809,  242, 1060, 1062,  496,  497,
+          414, 1166, 1167, 1168, 1169, 1163, 1164, -500, -505, -501,
+         -501, -107, -107, 1170, 1165, -503, 1228,  865,  611,  612,
+          841, -107, -107, -107, -501,   71,  921,  -84,  306,  309,
+         -107,-32766,  -76, 1001,  -49,  686, -501, 1145, -507,  -73,
+          -71,  774,  -70,  -69,-32766,-32766,-32766,  668,-32766,  -68,
+        -32766,  867,-32766,  662, -149,-32766,  781,  781,  -67,  281,
+        -32766,-32766,-32766,  -66,   73,  -65,-32766,-32766,  309, -500,
+         -500,  129,-32766,  388,  -64,  -45,-32766, -503, -503,  -16,
+        -32766,  145, 1145,  264, -500,  676,  865,  679,  864,-32766,
+        -32766,-32766, -503,-32766,  772,-32766, -500,-32766,  144,  855,
+        -32766,  272, -107,  273, -503,-32766,-32766,-32766,  879,   72,
+          244,-32766,-32766,-32766,  275,  776,  669,-32766,  388, 1145,
+          664,  865, -500,  274,  276,-32766,-32766,-32766,-32766,  315,
+        -32766,  281,-32766,  263,-32766,   73,   73,-32766,  107,  309,
+          309,  143,-32766,-32766,-32766,  642,-32766,  246,-32766,-32766,
+          532,  671, 1145,  772,-32766,  388,   -4,  865, 1259,-32766,
+        -32766,-32766,-32766,-32766,  781,-32766,-32766,-32766,  855, 1030,
+        -32766,  865,  867,  139,  662,-32766,-32766,-32766,  655,  309,
+          865,-32766,-32766,-32766, -500, -500,  526,-32766,  388, 1145,
+          101,  102,  103,  620,  637,-32766,-32766,-32766,-32766, -500,
+        -32766,  960,-32766,  855,-32766,   20,  865,-32766,-32766,  625,
+          677, -500,-32766,-32766,-32766,  435,-32766,  463,-32766,-32766,
+          962,  963, 1145,  626,-32766,  388,  638,  962,  963,-32766,
+        -32766,-32766,-32766,-32766,  609,-32766,  289,-32766,   46,  855,
+        -32766,  906,  407,  662,-32766,-32766,-32766,-32766,  287, 1016,
+         1183,-32766,-32766,  855,  286,  293,  781,-32766,  388, 1247,
+          890,  414,  855,  402,  891,-32766,  881,  538,  279, -231,
+         -231, -231, -107, -107, 1000,  414,  867,   26,  662, 1185,
+          578,  800, -107, -107, -107, -466, -107, -107,  855,  781,
+           47, -456,    7, 1176,   22,  841, -107, -107, -107,  348,
+          282,  283,  780,    9, -230, -230, -230,  281, 1173, -536,
+          414,   38,  867,   39,  662,   -4,  683,  684,  846,   32,
+          243, -107, -107,  930,  907,  680,  867,  123,  662, -231,
+          841, -107, -107, -107,  914,  867,  904,  662,  915,  844,
+          902, 1005,  497, 1008, 1166, 1167, 1168, 1169, 1163, 1164,
+         1009, 1006,  284,  285, 1007, 1013, 1170, 1165,  792, 1198,
+         1216,  867,   30,  662, -230,  304, 1250,  349,   71,  614,
+          842,  306,  309,  347,  663,  666,  670,  672, -107,  125,
+         -107,  673,  674,  678,  665,  288, 1254, 1256, -107, -107,
+         -107, -107, -107, -107, -107,  803,  802,  811,  888,  922,
+          810, 1255,  887,  886, 1131,  874,  882,  872,  912,  913,
+         1253, 1210, 1199, 1217, 1223, 1226,    0, -534, -508, -507,
+         -506,    1,   27,   28,   37,   41,   45,   70,   74,   75,
+           76,   77, -307, -256,   78,   79,  140,  149,  153,  239,
+          311,  334,  335,  336,  337,  338,  339,  340,  341,  342,
+          343,  344,  403,  404,    0, -254, -253,   12,   13,   14,
+           15,   17,  376,  454,  455,  462,  465,  466,  467,  468,
+          472,  473,  474,  481,  649, 1156, 1099, 1174,  977, 1135,
+         -258,  -99,   11,   16,   25,  278,  375,  571,  575,  601,
+          654, 1103, 1151, 1100, 1229,    0, -470, 1116,    0, 1177,
+            0,  309
+    );
+
+    protected $actionCheck = array(
+            2,    3,    4,    5,    6,    7,    0,    9,   10,   11,
+           12,   13,    1,  116,  117,   73,    1,    9,   10,   11,
+            1,   79,   79,  126,  127,  128,    1,    8,   86,   87,
+           88,    8,   90,    8,   92,   37,   94,    8,   30,   97,
+           32,   33,   34,  101,  102,  103,  104,    9,   10,   11,
+          108,  109,   14,    1,   56,   79,  114,  115,  115,  116,
+          117,  118,  119,  120,  122,  105,  106,    1,   70,   71,
+           72,   73,   74,   75,   76,  115,    8,   79,  115,  116,
+          117,  118,  119,  120,   86,   87,   88,   89,   90,   91,
+           92,   93,   94,   95,   96,   97,   98,   99,  100,  101,
+          102,  103,  104,  105,  106,  107,  108,  109,  110,  111,
+          112,  113,  114,  115,  116,  117,  118,  119,  120,  121,
+          122,  123,  124,  125,  126,  127,  128,  129,  130,  153,
+            8,  133,  134,  135,  136,  137,  138,  139,  140,  141,
+          157,    1,    8,   69,  161,  147,  148,  149,    8,  151,
+            9,   10,   11,    2,    3,    4,    5,    6,    7,  161,
+            9,   10,   11,   12,   13,    9,   10,   11,   73,  158,
+            9,   10,   11,  158,   79,   80,  157,    9,   10,  164,
+          161,   86,   87,   88,  161,   90,   30,   92,   37,   94,
+          161,   30,   97,   32,   33,   34,   35,  102,  103,  104,
+            8,  105,  106,  108,  109,  131,  132,   56,  156,  114,
+          115,  115,    9,   10,   11,   14,    8,  122,   31,    8,
+          146,   70,   71,   72,   73,   74,   75,   76,    8,  161,
+           79,    8,  158,   30,  160,   32,   33,   86,   87,   88,
+           89,   90,   91,   92,   93,   94,   95,   96,   97,   98,
+           99,  100,  101,  102,  103,  104,  105,  106,  107,  108,
+          109,  110,  111,  112,  113,  114,  115,  116,  117,  118,
+          119,  120,  121,  122,  123,  124,  125,  126,  127,  128,
+          129,  130,    8,   96,  133,  134,  135,  136,  137,  138,
+          139,  140,  141,   69,    9,   10,   11,  157,  147,  148,
+          149,  161,  151,    2,    3,    4,    5,    6,    7,    9,
+            9,   10,   11,   12,   13,   30,    8,   32,   33,   34,
+           35,   36,   37,   38,   39,   40,   41,   42,   43,   44,
+           45,   46,   47,   48,   49,   50,   51,   52,   53,   54,
+            8,   56,    9,   10,   11,   52,   53,   54,    8,   56,
+          118,  119,  120,   68,    8,  131,  132,   56,    9,   10,
+           11,   68,  161,   30,    8,   32,   33,   34,   35,   36,
+           37,   70,   71,   72,   73,   74,   75,   76,   31,   30,
+           79,   32,   33,   34,   35,   36,    8,   86,   87,   88,
+           89,   90,   91,   92,   93,   94,   95,   96,   97,   98,
+           99,  100,  101,  102,  103,  104,  105,  106,  107,  108,
+          109,  110,  111,  112,  113,  114,  115,  116,  117,  118,
+          119,  120,  121,  122,  123,  124,  125,  126,  127,  128,
+          129,  130,   74,   75,  133,  134,  135,  136,  137,  138,
+          139,  140,  141,   84,    9,   10,   11,    1,  147,  148,
+          149,    2,    3,    4,    5,    6,    7,   14,   79,   50,
+            8,   12,   13,    8,   15,   30,    1,   32,   33,   34,
+           35,   36,   37,   38,   39,   40,   41,   42,    1,   43,
+           44,   45,   46,   47,   48,   49,   50,   51,   79,    8,
+            1,   82,    8,   79,    1,   30,   74,   75,   49,   50,
+           14,  105,  143,  107,   55,  158,   57,   58,   59,   60,
+           61,   62,   63,   64,   65,   66,   67,    8,   69,   70,
+           71,   72,   73,   16,   31,  115,   77,   78,   79,  115,
+           81,  152,  153,  154,   85,   86,   87,   88,  159,   90,
+           14,   92,   96,   94,  134,  135,   97,   98,  152,  105,
+          106,  102,  103,  104,  105,  106,    1,  108,  109,   14,
+           83,   31,   37,  114,  115,    1,  152,  153,  154,   16,
+           81,  122,  123,  124,   14,  105,   83,  107,   16,   69,
+          115,   14,  133,  134,   14,  136,  137,  138,  139,  140,
+          141,  142,  100,  101,   69,   31,   16,  148,  149,  134,
+          135,  152,  153,  154,  155,   16,   81,   69,   16,  160,
+           85,  162,  163,  164,   16,   17,   18,   19,   20,   21,
+           22,   23,   24,   25,   26,   27,   28,   29,   16,   74,
+           75,   76,  105,  156,  107,  158,    1,    1,   83,  105,
+          106,  131,  132,   16,   89,   81,   91,  158,   93,  156,
+           95,  158,  105,  164,  107,   37,   58,   59,  133,  134,
+          105,  136,  137,  138,  139,  140,  141,   69,  158,  131,
+          132,  116,  117,  148,  149,   69,    1,    1,  110,  111,
+          125,  126,  127,  128,  146,  160,  156,   31,  163,  164,
+          126,   73,   31,  156,   31,  158,  158,   79,  160,   31,
+           31,   79,   31,   31,   86,   87,   88,   31,   90,   31,
+           92,  156,   94,  158,  159,   97,   81,   81,   31,  155,
+          102,  103,  104,   31,  160,   31,  108,  109,  164,  131,
+          132,   31,  114,  115,   31,   31,   73,  131,  132,   31,
+          122,   31,   79,   31,  146,   31,    1,   31,   31,   86,
+           87,   88,  146,   90,   79,   92,  158,   94,   31,   83,
+           97,   35,  126,   35,  158,  102,  103,  104,   37,  151,
+           37,  108,  109,   73,   35,  153,   31,  114,  115,   79,
+          158,    1,   69,   30,   35,  122,   86,   87,   88,   35,
+           90,  155,   92,   56,   94,  160,  160,   97,   68,  164,
+          164,   69,  102,  103,  104,   76,   73,   37,  108,  109,
+           88,   31,   79,   79,  114,  115,    0,    1,   82,   86,
+           87,   88,  122,   90,   81,   92,   84,   94,   83,   81,
+           97,    1,  156,  158,  158,  102,  103,  104,   91,  164,
+            1,  108,  109,   73,  131,  132,   84,  114,  115,   79,
+           49,   50,   51,   89,   93,  122,   86,   87,   88,  146,
+           90,  115,   92,   83,   94,   96,    1,   97,  115,   95,
+           31,  158,  102,  103,  104,   96,   73,   96,  108,  109,
+          134,  135,   79,   99,  114,  115,   99,  134,  135,   86,
+           87,   88,  122,   90,  112,   92,  113,   94,   69,   83,
+           97,  156,  126,  158,  115,  102,  103,  104,  130,  121,
+          143,  108,  109,   83,  129,  129,   81,  114,  115,   84,
+          126,  105,   83,  107,  126,  122,  151,  150,  112,   99,
+          100,  101,  116,  117,    1,  105,  156,   69,  158,  143,
+          150,  125,  126,  127,  128,  146,  116,  117,   83,   81,
+           69,  146,  146,   85,  146,  125,  126,  127,  128,  146,
+          131,  132,  152,  147,   99,  100,  101,  155,  157,  160,
+          105,  156,  156,  156,  158,  159,  156,  156,  156,  144,
+          145,  116,  117,  156,  156,  159,  156,  158,  158,  159,
+          125,  126,  127,  128,  156,  156,  156,  158,  156,  156,
+          156,  156,  134,  156,  136,  137,  138,  139,  140,  141,
+          156,  156,  131,  132,  156,  156,  148,  149,  157,  157,
+          157,  156,  158,  158,  159,  158,  157,  146,  160,  157,
+          159,  163,  164,  158,  158,  158,  158,  158,  105,  158,
+          107,  158,  158,  158,  158,  112,  159,  159,  115,  116,
+          117,  118,  119,  120,  121,  159,  159,  159,  159,  159,
+          159,  159,  159,  159,  159,  159,  159,  159,  159,  159,
+          159,  159,  159,  159,  159,  159,   -1,  160,  160,  160,
+          160,  160,  160,  160,  160,  160,  160,  160,  160,  160,
+          160,  160,  159,  161,  160,  160,  160,  160,  160,  160,
+          160,  160,  160,  160,  160,  160,  160,  160,  160,  160,
+          160,  160,  160,  160,   -1,  161,  161,  161,  161,  161,
+          161,  161,  161,  161,  161,  161,  161,  161,  161,  161,
+          161,  161,  161,  161,  161,  161,  161,  161,  161,  161,
+          161,  161,  161,  161,  161,  161,  161,  161,  161,  161,
+          161,  161,  161,  161,  161,   -1,  162,  162,   -1,  163,
+           -1,  164
+    );
+
+    protected $actionBase = array(
+            0,   -2,  151,  555,  816,  830,  865,  489,  379,  622,
+          858,  676,  780,  780,  839,  780,  493,  745,  301,  301,
+          -57,  301,  301,  477,  477,  477,  618,  618,  618,  618,
+          -58,  -58,   95,  700,  733,  770,  663,  803,  803,  803,
+          803,  803,  803,  803,  803,  803,  803,  803,  803,  803,
+          803,  803,  803,  803,  803,  803,  803,  803,  803,  803,
+          803,  803,  803,  803,  803,  803,  803,  803,  803,  803,
+          803,  803,  803,  803,  803,  803,  803,  803,  803,  803,
+          803,  803,  803,  803,  803,  803,  803,  803,  803,  803,
+          803,  803,  803,  803,  803,  803,  803,  803,  803,  803,
+          803,  803,  803,  803,  803,  803,  803,  803,  803,  803,
+          803,  803,  803,  803,  803,  803,  803,  803,  803,  803,
+          803,  803,  803,  803,  803,  803,  803,  803,  803,  803,
+          803,  803,  803,  803,  803,  803,  803,  803,  803,  803,
+          803,  803,  803,  803,  803,  803,  803,  803,  803,  803,
+          803,  803,  803,  803,  803,  803,  803,  803,   52,  530,
+          446,  570,  984,  990,  986,  991,  982,  981,  985,  987,
+          992,  911,  912,  727,  913,  914,  915,  916,  988,  872,
+          983,  989,  285,  285,  285,  285,  285,  285,  285,  285,
+          285,  285,  285,  285,  285,  285,  285,  285,  285,  285,
+          285,  285,  285,  300,   38,  168,  141,  141,  141,  141,
+          141,  141,  141,  141,  141,  141,  141,  141,  141,  141,
+          141,  141,  141,  141,  141,  141,  141,  141,  141,  141,
+          156,  156,  156,  203,  525,  525,    8,  598,  161,  868,
+          868,  868,  868,  868,  868,  868,  868,  868,  868,  349,
+          333,  435,  435,  435,  435,  435,  436,  436,  436,  436,
+          933,  564,  636,  635,  465,  470,  801,  801,  753,  753,
+          788,  746,  746,  746,  410,  410,  410,   74,  538,  396,
+          359,  414,  675,  675,  675,  675,  414,  414,  414,  414,
+          796,  996,  414,  414,  414, -103,  606,  713,  713,  881,
+          293,  293,  293,  713,  547,  762,  835,  547,  835,   15,
+          409,  789,  -40,   96,  -17,  789,  510,  829,  140,   19,
+          810,  444,  810,  742,  859,  886,  993,  232,  784,  909,
+          787,  910,  224,  661,  979,  979,  979,  979,  979,  979,
+          979,  979,  979,  979,  979,  997,  980,  -24,  997,  997,
+          997,  568,  -24,  358,  422,  -24,  754,  980,   52,  805,
+           52,   52,   52,   52,  941,   52,   52,   52,   52,   52,
+           52,  946,  708,  704,  668,  347,   52,  530,   11,   11,
+          537,   66,   11,   11,   11,   11,   52,   52,  444,  737,
+          777,  534,  790,   68,  737,  737,  737,  187,   23,  201,
+           29,  527,  734,  734,  731,  748,  921,  921,  734,  743,
+          734,  748,  926,  734,  731,  731,  921,  731,  812,  208,
+          452,  332,  346,  731,  731,  455,  921,  223,  731,  731,
+          734,  734,  734,  731,  481,  734,  220,  211,  734,  734,
+          731,  731,  785,  786,  122,  921,  921,  921,  786,  340,
+          778,  778,  820,  821,  782,  712,  308,  274,  509,  192,
+          731,  712,  712,  734,  356,  782,  712,  782,  712,  775,
+          712,  712,  712,  782,  712,  743,  378,  712,  731,  484,
+          134,  712,    6,  927,  928,  656,  929,  924,  930,  952,
+          931,  934,  876,  939,  925,  935,  923,  922,  717,  507,
+          553,  806,  799,  920,  730,  730,  730,  918,  730,  730,
+          730,  730,  730,  730,  730,  730,  507,  811,  813,  776,
+          722,  942,  562,  580,  767,  871,  994,  995,  794,  798,
+          941,  974,  936,  815,  589,  960,  943,  826,  867,  944,
+          945,  961,  975,  976,  887,  732,  888,  896,  861,  947,
+          877,  730,  927,  934,  925,  935,  923,  922,  703,  694,
+          687,  692,  678,  672,  669,  671,  710,  917,  809,  862,
+          946,  919,  507,  863,  956,  864,  962,  963,  875,  779,
+          736,  869,  897,  948,  949,  950,  878,  977,  817,  957,
+          932,  964,  781,  898,  965,  966,  967,  968,  899,  879,
+          883,  822,  764,  954,  774,  900,  443,  739,  749,  953,
+          486,  940,  884,  901,  902,  969,  970,  971,  903,  937,
+          827,  958,  761,  959,  955,  828,  838,  526,  726,  728,
+          545,  560,  904,  905,  938,  714,  729,  840,  842,  978,
+          906,  567,  843,  592,  907,  973,  612,  627,  747,  885,
+          808,  783,  769,  951,  716,  844,  908,  845,  847,  854,
+          972,  855,    0,    0,    0,    0,    0,    0,    0,    0,
+            0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+            0,    0,    0,    0,    0,    0,    0,    0,    0,  449,
+          449,  449,  449,  449,  449,  301,  301,  301,  301,  449,
+          449,  449,  449,  449,  449,  449,    0,    0,  301,    0,
+            0,  449,  449,  449,  449,  449,  449,  449,  449,  449,
+          449,  449,  449,  449,  449,  449,  449,  449,  449,  449,
+          449,  449,  449,  449,  449,  449,  449,  449,  449,  449,
+          449,  449,  449,  449,  449,  449,  449,  449,  449,  449,
+          449,  449,  449,  449,  449,  449,  449,  449,  449,  449,
+          449,  449,  449,  449,  449,  449,  449,  449,  449,  449,
+          449,  449,  449,  449,  449,  449,  449,  449,  449,  449,
+          449,  449,  449,  449,  449,  449,  449,  449,  449,  449,
+          449,  449,  449,  449,  449,  449,  449,  449,  449,  449,
+          449,  449,  449,  449,  449,  449,  449,  449,  449,  449,
+          449,  449,  449,  449,  449,  449,  449,  449,  449,  449,
+          449,  449,  449,  449,  449,  449,  449,  449,  449,  449,
+          449,  449,  449,  449,  449,  449,  449,  449,  449,  449,
+          449,  449,  449,  449,  449,  449,  285,  285,  285,  285,
+          285,  285,  285,  285,  285,  285,  285,  285,  285,  285,
+          285,  285,  285,  285,  285,  285,  285,  285,  285,  285,
+            0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+            0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+            0,  285,  285,  285,  285,  285,  285,  285,  285,  285,
+          285,  285,  285,  285,  285,  285,  285,  285,  285,  285,
+          285,  285,  285,  285,  285,  285,  285,  285,  285,  285,
+          285,  285,  414,  414,  285,    0,  285,  414,  414,  414,
+          414,  414,  414,  414,  414,  414,  414,  285,  285,  285,
+          285,  285,  285,  285,  293,  293,  293,  293,  812,  414,
+          414,  414,  414,  -37,  293,  293,  414,  414,  -37,  414,
+          414,  414,  414,  414,  414,    0,    0,  -24,  835,    0,
+          743,  743,  743,  743,    0,    0,    0,    0,  835,  835,
+            0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+            0,    0,  -24,  835,    0,  -24,    0,  743,  743,  414,
+          812,  812,   25,  414,    0,    0,    0,    0,  -24,  743,
+          -24,  835,   11,   52,   25,    0,  492,  492,  492,  492,
+            0,  444,  812,  812,  812,  812,  812,  812,  812,  812,
+          812,  812,  812,  743,  812,    0,  743,  743,  743,    0,
+            0,    0,    0,    0,  743,  731,    0,  921,    0,    0,
+            0,    0,  734,    0,    0,    0,    0,    0,    0,  734,
+          926,  731,  731,    0,    0,    0,    0,    0,    0,  743,
+            0,    0,    0,    0,    0,    0,    0,  730,  779,    0,
+          779,    0,  730,  730,  730
+    );
+
+    protected $actionDefault = array(
+            3,32767,   99,32767,32767,32767,32767,32767,32767,32767,
+        32767,32767,32767,32767,32767,32767,32767,32767,32767,   97,
+        32767,32767,32767,32767,32767,32767,  554,  554,  554,  554,
+          235,   99,32767,32767,32767,32767,  430,  349,  349,  349,
+        32767,32767,  498,  498,  498,  498,  498,  498,32767,32767,
+        32767,32767,32767,32767,  430,32767,32767,32767,32767,32767,
+        32767,32767,32767,32767,32767,32767,32767,32767,32767,32767,
+        32767,32767,32767,32767,32767,32767,32767,32767,32767,32767,
+        32767,32767,32767,32767,32767,32767,32767,32767,32767,32767,
+        32767,32767,32767,32767,32767,32767,32767,32767,32767,32767,
+        32767,32767,32767,32767,32767,32767,32767,32767,32767,32767,
+        32767,32767,32767,32767,32767,32767,32767,32767,32767,32767,
+        32767,32767,32767,32767,32767,32767,   97,32767,32767,32767,
+           35,    5,    6,    8,    9,   48,   15,32767,32767,32767,
+        32767,32767,   99,32767,32767,32767,32767,32767,32767,32767,
+        32767,32767,32767,32767,32767,32767,32767,32767,32767,32767,
+        32767,  547,32767,32767,32767,32767,32767,32767,32767,32767,
+        32767,32767,32767,32767,32767,32767,32767,32767,32767,32767,
+        32767,32767,  434,  413,  414,  416,  417,  348,  499,  553,
+          292,  550,  347,  142,  304,  294,  223,  295,  239,  240,
+          266,  344,  146,  378,  431,  380,  429,  433,  379,  354,
+          359,  360,  361,  362,  363,  364,  365,  366,  367,  368,
+          369,  370,  371,  352,  353,  432,  435,  436,  439,  440,
+          410,  409,  408,  376,32767,32767,  377,  351,  381,32767,
+        32767,32767,32767,32767,32767,32767,32767,   99,32767,  383,
+          382,  399,  400,  397,  398,  401,  402,  403,  404,  405,
+        32767,32767,32767,32767,32767,  327,  390,  391,  283,  283,
+          329,32767,32767,32767,32767,32767,32767,  492,  407,32767,
+        32767,32767,32767,32767,32767,32767,32767,32767,32767,32767,
+        32767,32767,   99,32767,   97,32767,  494,  373,  375,  462,
+          385,  386,  384,  355,32767,  469,32767,   99,  471,32767,
+        32767,32767,  108,32767,32767,32767,  493,32767,  500,  500,
+        32767,  455,   97,32767,32767,32767,32767,  261,32767,32767,
+        32767,32767,  561,  455,  107,  107,  107,  107,  107,  107,
+          107,  107,  107,  107,  107,32767,  107,32767,32767,32767,
+           97,  185,32767,  249,  251,   99,  515,  190,32767,  474,
+        32767,32767,32767,32767,32767,32767,32767,32767,32767,32767,
+        32767,32767,  467,  190,  190,32767,32767,32767,32767,32767,
+        32767,32767,32767,32767,32767,32767,32767,32767,  455,  395,
+          135,32767,  135,  500,  387,  388,  389,  457,  500,  500,
+          500,32767,32767,32767,  190,32767,  472,  472,   97,   97,
+           97,   97,  467,32767,  190,  190,32767,  190,  108,   96,
+           96,   96,   96,  190,  190,   96,  100,   98,  190,  190,
+        32767,32767,32767,  190,   96,32767,   98,   98,32767,32767,
+          190,  190,  206,  204,   98,32767,  519,  520,  204,   98,
+          208,  208,  228,  228,  446,  285,   98,   96,   98,   98,
+          190,  285,  285,32767,   98,  446,  285,  446,  285,  192,
+          285,  285,  285,  446,  285,32767,   98,  285,  190,   96,
+           96,  285,32767,32767,32767,  457,32767,32767,32767,32767,
+        32767,32767,32767,32767,32767,32767,32767,32767,32767,32767,
+          487,32767,  504,  517,  393,  394,  396,  502,  418,  419,
+          420,  421,  422,  423,  424,  426,  549,32767,  461,32767,
+        32767,32767,32767,  303,  559,32767,  559,32767,32767,32767,
+        32767,32767,32767,32767,32767,32767,32767,32767,32767,32767,
+        32767,32767,32767,32767,  560,32767,  500,32767,32767,32767,
+        32767,  392,    7,   74,   41,   42,   50,   56,  478,  479,
+          480,  481,  475,  476,  482,  477,32767,  483,  525,32767,
+        32767,  501,  552,32767,32767,32767,32767,32767,32767,  135,
+        32767,32767,32767,32767,32767,32767,32767,32767,32767,32767,
+          487,32767,  133,32767,32767,32767,32767,32767,32767,32767,
+        32767,32767,32767,  500,32767,32767,32767,  280,  282,32767,
+        32767,32767,32767,32767,32767,32767,32767,32767,32767,32767,
+        32767,32767,32767,32767,  500,32767,32767,32767,  268,  270,
+        32767,32767,32767,32767,32767,32767,32767,32767,32767,32767,
+        32767,32767,32767,  265,32767,32767,  343,32767,32767,32767,
+        32767,  323,32767,32767,32767,32767,32767,32767,32767,32767,
+        32767,32767,  148,  148,    3,    3,  306,  148,  148,  148,
+          306,  148,  306,  306,  148,  148,  148,  148,  148,  148,
+          180,  243,  246,  228,  228,  148,  315,  148
+    );
+
+    protected $goto = array(
+          190,  190,  650, 1020,  979,  399,  624,  798, 1019,  658,
+          393,  297,  298,  318,  546,  303,  398,  319,  400,  603,
+          362,  366,  531,  569,  573,  161,  161,  161,  161,  187,
+          187,  171,  173,  209,  191,  204,  187,  187,  187,  187,
+          187,  188,  188,  188,  188,  188,  188,  182,  183,  184,
+          185,  186,  206,  204,  207,  504,  505,  389,  506,  508,
+          509,  510,  511,  512,  513,  514,  515, 1046,  162,  163,
+          164,  189,  165,  166,  167,  160,  168,  169,  170,  172,
+          203,  205,  208,  230,  233,  236,  238,  249,  250,  251,
+          252,  253,  254,  255,  256,  257,  258,  259,  266,  267,
+          300,  301,  302,  394,  395,  396,  551,  210,  211,  212,
+          213,  214,  215,  216,  217,  218,  219,  220,  221,  222,
+          223,  224,  174,  225,  175,  192,  193,  194,  231,  182,
+          183,  184,  185,  186,  206, 1046,  195,  176,  177,  178,
+          196,  192,  179,  232,  197,  159,  198,  226,  180,  199,
+          227,  228,  181,  229,  200,  201,  202,  312,  312,  312,
+          312,  801,  577,  591,  594,  595,  596,  597,  615,  616,
+          617,  660,  799,  329,  530,  521,  590,  590,  568,  794,
+          794, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175,
+         1175,  858,  779,  859,  806,  775,  854,  849,  850,  863,
+          905,  807,  851,  804,  852,  853,  805,  295,  295,  295,
+          295,  832,  857,  607,  607,  364,  521,  773,  530,  969,
+          966,  967,  996,  997,  539,  540,  957,  964,  965,  371,
+          549,  588,  621,  779,  570,  779, 1244, 1244, 1193, 1193,
+          543,  584,  585, 1193, 1193, 1193, 1193, 1193, 1193, 1193,
+         1193, 1193, 1193,  326, 1244, 1144, 1144, 1144,  961, 1140,
+         1233,  469,  961,  961,  926,  961,  961,  961,  961,  961,
+          961, 1225, 1225, 1225, 1225, 1144,  470,  360,  471,   21,
+         1144, 1144, 1144, 1144,  477,  794, 1144, 1144, 1144,  332,
+          437,  437,  567, 1012,  618,  661,  632,  633,  542,  332,
+          332,  437,  623,  647,  647,  870,  653, 1010, 1094,  871,
+          447, 1218, 1219,  814,  332,  332, 1141,  332,  826, 1260,
+            5,  813,    6,  518,  518,  518,  789,  320, 1191, 1191,
+          523,  791,  332, 1191, 1191, 1191, 1191, 1191, 1191, 1191,
+         1191, 1191, 1191,  426,  405, 1142, 1201, 1202,  899,  899,
+          899,  899,  370,  536,  426,  893,  900,  897,  380,  657,
+          583,  507,  507,  308,  291, 1204,  507,  507,  507,  507,
+          507,  507,  507,  507,  507,  507, 1243, 1243,  516,  516,
+          516,  516, 1220, 1221,  819,  875, 1034,  572,  547,  582,
+          643,  522,  534,  587, 1243,  816,  948,  522,  945,  534,
+          685,  985,  363,  330,  331,  818,  828,  627,  924, 1246,
+          392, 1137,  579,  812,  418,  418,  418,  448,  523,  550,
+          442,  443,  989, 1029,  824, 1136,  910, 1251, 1252,  451,
+          600,  537, 1215, 1215, 1215,  682,  602,  604,    0,  622,
+            0,    0,  640,  644,  940,  648,  656,  936,    0,    0,
+          797,    0,  822, 1227, 1227, 1227, 1227,  929,  903,  903,
+          901,  903,  681,    0,  270,  519,  519,    0,    0,  520,
+          938,  933,    0,  827,  815,  984,    0,    0,  988,    0,
+         1211,    0,    0,    0, 1139,    0,    0,  908,  418,  418,
+          418,  418,  418,  418,  418,  418,  418,  418,  418,    0,
+          418,    0,  378,  379,    0,    0,    0,  630,    0,  631,
+          898,  382,  383,  384,    0,  641,  987,    0,  385, 1213,
+         1213,  987,  324, 1125,  884,    0,    0, 1126, 1129,  885,
+         1130,    0, 1027,  831,    0,    0,    0,    0,    0,    0,
+            0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+            0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+            0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+            0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+            0,    0,    0,    0,    0,    0,  943,  943
+    );
+
+    protected $gotoCheck = array(
+           41,   41,   71,  128,  111,   64,   64,   25,  128,    8,
+           64,   64,   64,   64,   64,   64,   64,   64,   64,   64,
+           57,   57,   57,   57,   57,   41,   41,   41,   41,   41,
+           41,   41,   41,   41,   41,   41,   41,   41,   41,   41,
+           41,   41,   41,   41,   41,   41,   41,   41,   41,   41,
+           41,   41,   41,   41,   41,   41,   41,   41,   41,   41,
+           41,   41,   41,   41,   41,   41,   41,   41,   41,   41,
+           41,   41,   41,   41,   41,   41,   41,   41,   41,   41,
+           41,   41,   41,   41,   41,   41,   41,   41,   41,   41,
+           41,   41,   41,   41,   41,   41,   41,   41,   41,   41,
+           41,   41,   41,   41,   41,   41,   41,   41,   41,   41,
+           41,   41,   41,   41,   41,   41,   41,   41,   41,   41,
+           41,   41,   41,   41,   41,   41,   41,   41,   41,   41,
+           41,   41,   41,   41,   41,   41,   41,   41,   41,   41,
+           41,   41,   41,   41,   41,   41,   41,   41,   41,   41,
+           41,   41,   41,   41,   41,   41,   41,   22,   22,   22,
+           22,   14,   77,   77,   77,   77,   77,   77,   77,   77,
+           77,   77,   26,   88,   74,   74,   99,   99,  114,   21,
+           21,   99,   99,   99,   99,   99,   99,   99,   99,   99,
+           99,   63,   11,   63,   14,    6,   14,   14,   14,   14,
+           48,   14,   14,   14,   14,   14,   14,   23,   23,   23,
+           23,   44,   14,  107,  107,   74,   74,    5,   74,  107,
+          107,  107,   14,   14,   74,   74,  105,  105,  105,   74,
+           74,   54,   54,   11,   74,   11,  165,  165,  152,  152,
+          154,   74,   74,  152,  152,  152,  152,  152,  152,  152,
+          152,  152,  152,  161,  165,   71,   71,   71,   71,   19,
+          163,   74,   71,   71,   94,   71,   71,   71,   71,   71,
+           71,    8,    8,    8,    8,   71,  139,   60,  139,   74,
+           71,   71,   71,   71,  139,   21,   71,   71,   71,   13,
+          133,  133,    7,    7,   82,    7,   82,   82,   95,   13,
+           13,  133,   62,    7,    7,   71,    7,    7,  135,   71,
+          158,  158,  158,   34,   13,   13,   19,   13,   34,   13,
+           45,   34,   45,   18,   18,   18,   19,   28,  153,  153,
+           13,   17,   13,  153,  153,  153,  153,  153,  153,  153,
+          153,  153,  153,   18,  103,   19,   19,   19,   18,   18,
+           18,   18,   27,    8,   18,   18,   18,   84,   84,   84,
+            8,  155,  155,  151,  151,   13,  155,  155,  155,  155,
+          155,  155,  155,  155,  155,  155,  164,  164,   98,   98,
+           98,   98,  160,  160,   38,   16,   16,   98,    2,    2,
+           13,    8,    8,   16,  164,   36,  101,    8,   16,    8,
+           90,  113,    8,   88,   88,   16,   40,   16,   16,  164,
+           12,  144,   12,   16,   22,   22,   22,  141,   13,    8,
+            8,    8,  116,  131,    8,   16,   87,    8,    8,   80,
+           81,   47,  114,  114,  114,   47,   47,   47,   -1,   47,
+           -1,   -1,   47,   47,   47,   47,   47,   47,   -1,   -1,
+           24,   -1,    8,  114,  114,  114,  114,   24,   24,   24,
+           24,   24,   24,   -1,   23,   23,   23,   -1,   -1,   24,
+           24,   24,   -1,   15,   15,   15,   -1,   -1,   15,   -1,
+          114,   -1,   -1,   -1,   13,   -1,   -1,   15,   22,   22,
+           22,   22,   22,   22,   22,   22,   22,   22,   22,   -1,
+           22,   -1,   78,   78,   -1,   -1,   -1,   78,   -1,   78,
+           15,   78,   78,   78,   -1,   78,  114,   -1,   78,  114,
+          114,  114,   78,   76,   76,   -1,   -1,   76,   76,   76,
+           76,   -1,   15,   15,   -1,   -1,   -1,   -1,   -1,   -1,
+           -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
+           -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
+           -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
+           -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
+           -1,   -1,   -1,   -1,   -1,   -1,   98,   98
+    );
+
+    protected $gotoBase = array(
+            0,    0, -276,    0,    0,  197,  186,  285,  -11,    0,
+            0,  -87,   90,    9, -164,   53,  -51,   39,   62, -100,
+            0, -133,  154,  204,  446,    3,  168,   32,   48,    0,
+            0,    0,    0,    0,  -34,    0,   73,    0,   77,    0,
+           -2,   -1,    0,    0,  192, -365,    0, -232,  183,    0,
+            0,    0,    0,    0,  193,    0,    0,  -23,    0,    0,
+          237,    0,   67,  178, -229,    0,    0,    0,    0,    0,
+            0,   -6,    0,    0, -199,    0,  145, -173,   41,    0,
+          -19,  -21, -376,    0,   70,    0,    0,   16, -280,    0,
+           23,    0,    0,    0,  233,  257,    0,    0,  352,  -58,
+            0,   50,    0,   75,    0,  -45,    0,  -55,    0,    0,
+            0,    2,    0,   51,  171,    0,   13,    0,    0,    0,
+            0,    0,    0,    0,    0,    0,    0,    0, -262,    0,
+            0,   12,    0,  260,    0,   45,    0,    0,    0, -189,
+            0,   10,    0,    0,    7,    0,    0,    0,    0,    0,
+            0,   58,    4,   94,  213,  127,    0,    0,   27,    0,
+           34,  225,    0,  231,   86,  -54,    0,    0
+    );
+
+    protected $gotoDefault = array(
+        -32768,  482,  689,    4,  690,  763,  771,  566,  498,  659,
+          325,  592,  390, 1209,  856, 1033,  548,  790, 1153, 1161,
+          427,  793,  313,  327,  838,  839,  840,  367,  352,  358,
+          365,  613,  593,  464,  825,  421,  817,  456,  820,  420,
+          829,  158,  387,  480,  833,    3,  835,  525,  866,  353,
+          843,  354,  636,  845,  533,  847,  848,  361,  368,  369,
+         1038,  541,  589,  860,  237,  535,  861,  351,  862,  869,
+          356,  359,  645,  436,  475,  381, 1014,  576,  610,  432,
+          450,  599,  598,  586,  895,  457,  434,  909,  328,  917,
+          687, 1045,  605,  459,  925,  606,  932,  935,  499,  500,
+          449,  947,  268,  460,  974,  628,  629,  959,  608,  972,
+          444,  978,  422,  986, 1197,  425,  990,  260,  993,  269,
+          386,  401,  998,  999,    8, 1004,  651,  652,   10,  265,
+          479, 1028,  646,  419, 1044,  406, 1113, 1115,  527,  461,
+         1133, 1132,  639,  476, 1138, 1200,  416,  501,  445,  299,
+          502,  290,  316,  296,  517,  277,  317,  503,  446, 1206,
+         1214,  314,   29, 1234, 1245,  323,  545,  581
+    );
+
+    protected $ruleToNonTerminal = array(
+            0,    1,    3,    3,    2,    5,    5,    5,    5,    5,
+            5,    5,    5,    5,    5,    5,    5,    5,    5,    5,
+            5,    5,    5,    5,    5,    5,    5,    5,    5,    5,
+            5,    5,    5,    5,    5,    5,    5,    5,    5,    5,
+            5,    5,    5,    5,    5,    5,    5,    5,    5,    5,
+            5,    5,    5,    5,    5,    5,    5,    5,    5,    5,
+            5,    5,    5,    5,    5,    5,    5,    5,    5,    5,
+            5,    5,    5,    5,    5,    6,    6,    6,    6,    6,
+            6,    6,    7,    7,    8,    9,   10,   10,   10,   11,
+           11,   12,   12,   13,   14,   14,   15,   15,   16,   16,
+           17,   17,   20,   20,   21,   22,   22,   23,   23,    4,
+            4,    4,    4,    4,    4,    4,    4,    4,    4,    4,
+           28,   28,   29,   29,   31,   33,   33,   27,   35,   35,
+           32,   37,   37,   34,   34,   36,   36,   38,   38,   30,
+           39,   39,   40,   42,   43,   43,   44,   45,   45,   47,
+           46,   46,   46,   46,   48,   48,   48,   48,   48,   48,
+           48,   48,   48,   48,   48,   48,   48,   48,   48,   48,
+           48,   48,   48,   48,   48,   48,   48,   48,   24,   24,
+           67,   67,   70,   70,   69,   68,   68,   61,   73,   73,
+           74,   74,   75,   75,   76,   76,   25,   25,   26,   26,
+           26,   79,   79,   79,   80,   80,   83,   83,   81,   81,
+           84,   85,   85,   55,   55,   63,   63,   66,   66,   66,
+           65,   86,   86,   87,   56,   56,   56,   56,   88,   88,
+           89,   89,   90,   90,   91,   92,   92,   93,   93,   94,
+           94,   53,   53,   49,   49,   96,   51,   51,   97,   50,
+           50,   52,   52,   62,   62,   62,   62,   77,   77,  100,
+          100,  102,  102,  102,  102,  101,  101,  101,  104,  104,
+          104,  105,  105,  107,  107,  107,  106,  106,  108,  108,
+          109,  109,  109,  103,  103,   78,   78,   78,   19,   19,
+          110,  110,  111,  111,  111,  111,   58,  112,  112,  113,
+           59,  115,  115,  116,  116,  117,  117,   82,  118,  118,
+          118,  118,  118,  123,  123,  124,  124,  125,  125,  125,
+          125,  125,  126,  127,  127,  122,  122,  119,  119,  121,
+          121,  129,  129,  128,  128,  128,  128,  128,  128,  120,
+          130,  130,  132,  131,  131,   60,   95,  133,  133,   54,
+           54,   41,   41,   41,   41,   41,   41,   41,   41,   41,
+           41,   41,   41,   41,   41,   41,   41,   41,   41,   41,
+           41,   41,   41,   41,   41,   41,   41,   41,   41,   41,
+           41,   41,   41,   41,   41,   41,   41,   41,   41,   41,
+           41,   41,   41,   41,   41,   41,   41,   41,   41,   41,
+           41,   41,   41,   41,   41,   41,   41,   41,   41,   41,
+           41,   41,   41,   41,   41,   41,   41,   41,   41,   41,
+           41,   41,   41,   41,   41,   41,   41,   41,   41,   41,
+           41,   41,   41,   41,   41,   41,   41,   41,   41,   41,
+           41,   41,   41,  140,  134,  134,  139,  139,  142,  143,
+          143,  144,  145,  145,  145,   18,   18,   71,   71,   71,
+           71,  135,  135,  135,  135,  147,  147,  136,  136,  138,
+          138,  138,  141,  141,  152,  152,  152,  152,  152,  152,
+          152,  152,  152,  153,  153,   99,  155,  155,  155,  155,
+          137,  137,  137,  137,  137,  137,  137,  137,   57,   57,
+          150,  150,  150,  150,  156,  156,  146,  146,  146,  157,
+          157,  157,  157,  157,  157,   72,   72,   64,   64,   64,
+           64,  114,  114,  114,  114,  160,  159,  149,  149,  149,
+          149,  149,  149,  149,  148,  148,  148,  158,  158,  158,
+          158,   98,  154,  162,  162,  161,  161,  163,  163,  163,
+          163,  163,  163,  163,  163,  151,  151,  151,  151,  165,
+          166,  164,  164,  164,  164,  164,  164,  164,  164,  167,
+          167,  167,  167
+    );
+
+    protected $ruleToLength = array(
+            1,    1,    2,    0,    1,    1,    1,    1,    1,    1,
+            1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+            1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+            1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+            1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+            1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+            1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+            1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+            1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+            1,    1,    1,    1,    1,    1,    0,    1,    0,    1,
+            1,    2,    1,    3,    4,    1,    2,    0,    1,    1,
+            1,    1,    1,    3,    5,    4,    3,    4,    2,    3,
+            1,    1,    7,    6,    2,    3,    1,    2,    3,    1,
+            2,    3,    1,    1,    3,    1,    3,    1,    2,    2,
+            3,    1,    3,    2,    3,    1,    3,    2,    0,    1,
+            1,    1,    1,    1,    3,    7,   10,    5,    7,    9,
+            5,    3,    3,    3,    3,    3,    3,    1,    2,    5,
+            7,    9,    6,    5,    6,    3,    2,    1,    1,    1,
+            0,    2,    1,    3,    8,    0,    4,    2,    1,    3,
+            0,    1,    0,    1,    3,    1,    8,    9,    8,    7,
+            6,    1,    2,    2,    0,    2,    0,    2,    0,    2,
+            2,    1,    3,    1,    4,    1,    4,    1,    1,    4,
+            2,    1,    3,    3,    3,    4,    4,    5,    0,    2,
+            4,    3,    1,    1,    7,    0,    2,    1,    3,    3,
+            4,    1,    4,    0,    2,    5,    0,    2,    6,    0,
+            2,    0,    3,    1,    2,    1,    1,    2,    0,    1,
+            3,    0,    1,    1,    1,    6,    8,    6,    1,    2,
+            1,    1,    1,    1,    1,    1,    3,    3,    3,    3,
+            1,    2,    1,    0,    1,    0,    2,    2,    2,    4,
+            1,    3,    1,    2,    2,    3,    2,    3,    1,    1,
+            2,    3,    1,    1,    3,    2,    0,    1,    5,    5,
+           10,    3,    1,    1,    3,    0,    2,    4,    5,    4,
+            4,    4,    3,    1,    1,    1,    1,    1,    1,    0,
+            1,    1,    2,    1,    1,    1,    1,    1,    1,    2,
+            1,    3,    1,    1,    3,    2,    2,    3,    1,    0,
+            1,    1,    3,    3,    3,    4,    1,    1,    2,    3,
+            3,    3,    3,    3,    3,    3,    3,    3,    3,    3,
+            3,    3,    2,    2,    2,    2,    3,    3,    3,    3,
+            3,    3,    3,    3,    3,    3,    3,    3,    3,    3,
+            3,    3,    3,    2,    2,    2,    2,    3,    3,    3,
+            3,    3,    3,    3,    3,    3,    3,    3,    5,    4,
+            3,    4,    4,    2,    2,    4,    2,    2,    2,    2,
+            2,    2,    2,    2,    2,    2,    2,    1,    3,    2,
+            1,    2,    4,    2,    2,    8,    9,    8,    9,    9,
+           10,    9,   10,    8,    3,    2,    0,    4,    2,    1,
+            3,    2,    2,    2,    4,    1,    1,    1,    1,    1,
+            1,    1,    1,    3,    1,    1,    1,    0,    3,    0,
+            1,    1,    0,    1,    1,    1,    1,    1,    1,    1,
+            1,    1,    1,    3,    3,    3,    4,    1,    1,    3,
+            1,    1,    1,    1,    1,    3,    2,    3,    0,    1,
+            1,    3,    1,    1,    1,    1,    1,    3,    1,    1,
+            4,    4,    1,    4,    4,    0,    1,    1,    1,    3,
+            3,    1,    4,    2,    2,    1,    3,    1,    4,    4,
+            3,    3,    3,    3,    1,    3,    1,    1,    3,    1,
+            1,    4,    1,    1,    1,    3,    1,    1,    2,    1,
+            3,    4,    3,    2,    0,    2,    2,    1,    2,    1,
+            1,    1,    4,    3,    3,    3,    3,    6,    3,    1,
+            1,    2,    1
+    );
+
+    protected function initReduceCallbacks() {
+        $this->reduceCallbacks = [
+            0 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            1 => function ($stackPos) {
+                 $this->semValue = $this->handleNamespaces($this->semStack[$stackPos-(1-1)]);
+            },
+            2 => function ($stackPos) {
+                 if (is_array($this->semStack[$stackPos-(2-2)])) { $this->semValue = array_merge($this->semStack[$stackPos-(2-1)], $this->semStack[$stackPos-(2-2)]); } else { $this->semStack[$stackPos-(2-1)][] = $this->semStack[$stackPos-(2-2)]; $this->semValue = $this->semStack[$stackPos-(2-1)]; };
+            },
+            3 => function ($stackPos) {
+                 $this->semValue = array();
+            },
+            4 => function ($stackPos) {
+                 $startAttributes = $this->lookaheadStartAttributes; if (isset($startAttributes['comments'])) { $nop = new Stmt\Nop($this->createCommentNopAttributes($startAttributes['comments'])); } else { $nop = null; };
+            if ($nop !== null) { $this->semStack[$stackPos-(1-1)][] = $nop; } $this->semValue = $this->semStack[$stackPos-(1-1)];
+            },
+            5 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            6 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            7 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            8 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            9 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            10 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            11 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            12 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            13 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            14 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            15 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            16 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            17 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            18 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            19 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            20 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            21 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            22 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            23 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            24 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            25 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            26 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            27 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            28 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            29 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            30 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            31 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            32 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            33 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            34 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            35 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            36 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            37 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            38 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            39 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            40 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            41 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            42 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            43 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            44 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            45 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            46 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            47 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            48 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            49 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            50 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            51 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            52 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            53 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            54 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            55 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            56 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            57 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            58 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            59 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            60 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            61 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            62 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            63 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            64 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            65 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            66 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            67 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            68 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            69 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            70 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            71 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            72 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            73 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            74 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            75 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            76 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            77 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            78 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            79 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            80 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            81 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            82 => function ($stackPos) {
+                 $this->semValue = new Node\Identifier($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes);
+            },
+            83 => function ($stackPos) {
+                 $this->semValue = new Node\Identifier($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes);
+            },
+            84 => function ($stackPos) {
+                 $this->semValue = new Node\Identifier($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes);
+            },
+            85 => function ($stackPos) {
+                 $this->semValue = new Node\Identifier($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes);
+            },
+            86 => function ($stackPos) {
+                 $this->semValue = new Name($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes);
+            },
+            87 => function ($stackPos) {
+                 $this->semValue = new Name($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes);
+            },
+            88 => function ($stackPos) {
+                 $this->semValue = new Name($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes);
+            },
+            89 => function ($stackPos) {
+                 $this->semValue = new Name($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes);
+            },
+            90 => function ($stackPos) {
+                 $this->semValue = new Name($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes);
+            },
+            91 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(1-1)];
+            },
+            92 => function ($stackPos) {
+                 $this->semValue = new Name(substr($this->semStack[$stackPos-(1-1)], 1), $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes);
+            },
+            93 => function ($stackPos) {
+                 $this->semValue = new Expr\Variable(substr($this->semStack[$stackPos-(1-1)], 1), $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes);
+            },
+            94 => function ($stackPos) {
+                 /* nothing */
+            },
+            95 => function ($stackPos) {
+                 /* nothing */
+            },
+            96 => function ($stackPos) {
+                 /* nothing */
+            },
+            97 => function ($stackPos) {
+                 $this->emitError(new Error('A trailing comma is not allowed here', $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes));
+            },
+            98 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            99 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            100 => function ($stackPos) {
+                 $this->semValue = new Node\Attribute($this->semStack[$stackPos-(1-1)], [], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes);
+            },
+            101 => function ($stackPos) {
+                 $this->semValue = new Node\Attribute($this->semStack[$stackPos-(2-1)], $this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes);
+            },
+            102 => function ($stackPos) {
+                 $this->semValue = array($this->semStack[$stackPos-(1-1)]);
+            },
+            103 => function ($stackPos) {
+                 $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)];
+            },
+            104 => function ($stackPos) {
+                 $this->semValue = new Node\AttributeGroup($this->semStack[$stackPos-(4-2)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes);
+            },
+            105 => function ($stackPos) {
+                 $this->semValue = array($this->semStack[$stackPos-(1-1)]);
+            },
+            106 => function ($stackPos) {
+                 $this->semStack[$stackPos-(2-1)][] = $this->semStack[$stackPos-(2-2)]; $this->semValue = $this->semStack[$stackPos-(2-1)];
+            },
+            107 => function ($stackPos) {
+                 $this->semValue = [];
+            },
+            108 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(1-1)];
+            },
+            109 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(1-1)];
+            },
+            110 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(1-1)];
+            },
+            111 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(1-1)];
+            },
+            112 => function ($stackPos) {
+                 $this->semValue = new Stmt\HaltCompiler($this->lexer->handleHaltCompiler(), $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes);
+            },
+            113 => function ($stackPos) {
+                 $this->semValue = new Stmt\Namespace_($this->semStack[$stackPos-(3-2)], null, $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            $this->semValue->setAttribute('kind', Stmt\Namespace_::KIND_SEMICOLON);
+            $this->checkNamespace($this->semValue);
+            },
+            114 => function ($stackPos) {
+                 $this->semValue = new Stmt\Namespace_($this->semStack[$stackPos-(5-2)], $this->semStack[$stackPos-(5-4)], $this->startAttributeStack[$stackPos-(5-1)] + $this->endAttributes);
+            $this->semValue->setAttribute('kind', Stmt\Namespace_::KIND_BRACED);
+            $this->checkNamespace($this->semValue);
+            },
+            115 => function ($stackPos) {
+                 $this->semValue = new Stmt\Namespace_(null, $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes);
+            $this->semValue->setAttribute('kind', Stmt\Namespace_::KIND_BRACED);
+            $this->checkNamespace($this->semValue);
+            },
+            116 => function ($stackPos) {
+                 $this->semValue = new Stmt\Use_($this->semStack[$stackPos-(3-2)], Stmt\Use_::TYPE_NORMAL, $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            117 => function ($stackPos) {
+                 $this->semValue = new Stmt\Use_($this->semStack[$stackPos-(4-3)], $this->semStack[$stackPos-(4-2)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes);
+            },
+            118 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(2-1)];
+            },
+            119 => function ($stackPos) {
+                 $this->semValue = new Stmt\Const_($this->semStack[$stackPos-(3-2)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            120 => function ($stackPos) {
+                 $this->semValue = Stmt\Use_::TYPE_FUNCTION;
+            },
+            121 => function ($stackPos) {
+                 $this->semValue = Stmt\Use_::TYPE_CONSTANT;
+            },
+            122 => function ($stackPos) {
+                 $this->semValue = new Stmt\GroupUse($this->semStack[$stackPos-(7-3)], $this->semStack[$stackPos-(7-6)], $this->semStack[$stackPos-(7-2)], $this->startAttributeStack[$stackPos-(7-1)] + $this->endAttributes);
+            },
+            123 => function ($stackPos) {
+                 $this->semValue = new Stmt\GroupUse($this->semStack[$stackPos-(6-2)], $this->semStack[$stackPos-(6-5)], Stmt\Use_::TYPE_UNKNOWN, $this->startAttributeStack[$stackPos-(6-1)] + $this->endAttributes);
+            },
+            124 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(2-1)];
+            },
+            125 => function ($stackPos) {
+                 $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)];
+            },
+            126 => function ($stackPos) {
+                 $this->semValue = array($this->semStack[$stackPos-(1-1)]);
+            },
+            127 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(2-1)];
+            },
+            128 => function ($stackPos) {
+                 $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)];
+            },
+            129 => function ($stackPos) {
+                 $this->semValue = array($this->semStack[$stackPos-(1-1)]);
+            },
+            130 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(2-1)];
+            },
+            131 => function ($stackPos) {
+                 $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)];
+            },
+            132 => function ($stackPos) {
+                 $this->semValue = array($this->semStack[$stackPos-(1-1)]);
+            },
+            133 => function ($stackPos) {
+                 $this->semValue = new Stmt\UseUse($this->semStack[$stackPos-(1-1)], null, Stmt\Use_::TYPE_UNKNOWN, $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); $this->checkUseUse($this->semValue, $stackPos-(1-1));
+            },
+            134 => function ($stackPos) {
+                 $this->semValue = new Stmt\UseUse($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], Stmt\Use_::TYPE_UNKNOWN, $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); $this->checkUseUse($this->semValue, $stackPos-(3-3));
+            },
+            135 => function ($stackPos) {
+                 $this->semValue = new Stmt\UseUse($this->semStack[$stackPos-(1-1)], null, Stmt\Use_::TYPE_UNKNOWN, $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); $this->checkUseUse($this->semValue, $stackPos-(1-1));
+            },
+            136 => function ($stackPos) {
+                 $this->semValue = new Stmt\UseUse($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], Stmt\Use_::TYPE_UNKNOWN, $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); $this->checkUseUse($this->semValue, $stackPos-(3-3));
+            },
+            137 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(1-1)]; $this->semValue->type = Stmt\Use_::TYPE_NORMAL;
+            },
+            138 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(2-2)]; $this->semValue->type = $this->semStack[$stackPos-(2-1)];
+            },
+            139 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(2-1)];
+            },
+            140 => function ($stackPos) {
+                 $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)];
+            },
+            141 => function ($stackPos) {
+                 $this->semValue = array($this->semStack[$stackPos-(1-1)]);
+            },
+            142 => function ($stackPos) {
+                 $this->semValue = new Node\Const_($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            143 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(2-1)];
+            },
+            144 => function ($stackPos) {
+                 $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)];
+            },
+            145 => function ($stackPos) {
+                 $this->semValue = array($this->semStack[$stackPos-(1-1)]);
+            },
+            146 => function ($stackPos) {
+                 $this->semValue = new Node\Const_($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            147 => function ($stackPos) {
+                 if (is_array($this->semStack[$stackPos-(2-2)])) { $this->semValue = array_merge($this->semStack[$stackPos-(2-1)], $this->semStack[$stackPos-(2-2)]); } else { $this->semStack[$stackPos-(2-1)][] = $this->semStack[$stackPos-(2-2)]; $this->semValue = $this->semStack[$stackPos-(2-1)]; };
+            },
+            148 => function ($stackPos) {
+                 $this->semValue = array();
+            },
+            149 => function ($stackPos) {
+                 $startAttributes = $this->lookaheadStartAttributes; if (isset($startAttributes['comments'])) { $nop = new Stmt\Nop($this->createCommentNopAttributes($startAttributes['comments'])); } else { $nop = null; };
+            if ($nop !== null) { $this->semStack[$stackPos-(1-1)][] = $nop; } $this->semValue = $this->semStack[$stackPos-(1-1)];
+            },
+            150 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(1-1)];
+            },
+            151 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(1-1)];
+            },
+            152 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(1-1)];
+            },
+            153 => function ($stackPos) {
+                 throw new Error('__HALT_COMPILER() can only be used from the outermost scope', $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes);
+            },
+            154 => function ($stackPos) {
+
+        if ($this->semStack[$stackPos-(3-2)]) {
+            $this->semValue = $this->semStack[$stackPos-(3-2)]; $attrs = $this->startAttributeStack[$stackPos-(3-1)]; $stmts = $this->semValue; if (!empty($attrs['comments'])) {$stmts[0]->setAttribute('comments', array_merge($attrs['comments'], $stmts[0]->getAttribute('comments', []))); };
+        } else {
+            $startAttributes = $this->startAttributeStack[$stackPos-(3-1)]; if (isset($startAttributes['comments'])) { $this->semValue = new Stmt\Nop($startAttributes + $this->endAttributes); } else { $this->semValue = null; };
+            if (null === $this->semValue) { $this->semValue = array(); }
+        }
+
+            },
+            155 => function ($stackPos) {
+                 $this->semValue = new Stmt\If_($this->semStack[$stackPos-(7-3)], ['stmts' => is_array($this->semStack[$stackPos-(7-5)]) ? $this->semStack[$stackPos-(7-5)] : array($this->semStack[$stackPos-(7-5)]), 'elseifs' => $this->semStack[$stackPos-(7-6)], 'else' => $this->semStack[$stackPos-(7-7)]], $this->startAttributeStack[$stackPos-(7-1)] + $this->endAttributes);
+            },
+            156 => function ($stackPos) {
+                 $this->semValue = new Stmt\If_($this->semStack[$stackPos-(10-3)], ['stmts' => $this->semStack[$stackPos-(10-6)], 'elseifs' => $this->semStack[$stackPos-(10-7)], 'else' => $this->semStack[$stackPos-(10-8)]], $this->startAttributeStack[$stackPos-(10-1)] + $this->endAttributes);
+            },
+            157 => function ($stackPos) {
+                 $this->semValue = new Stmt\While_($this->semStack[$stackPos-(5-3)], $this->semStack[$stackPos-(5-5)], $this->startAttributeStack[$stackPos-(5-1)] + $this->endAttributes);
+            },
+            158 => function ($stackPos) {
+                 $this->semValue = new Stmt\Do_($this->semStack[$stackPos-(7-5)], is_array($this->semStack[$stackPos-(7-2)]) ? $this->semStack[$stackPos-(7-2)] : array($this->semStack[$stackPos-(7-2)]), $this->startAttributeStack[$stackPos-(7-1)] + $this->endAttributes);
+            },
+            159 => function ($stackPos) {
+                 $this->semValue = new Stmt\For_(['init' => $this->semStack[$stackPos-(9-3)], 'cond' => $this->semStack[$stackPos-(9-5)], 'loop' => $this->semStack[$stackPos-(9-7)], 'stmts' => $this->semStack[$stackPos-(9-9)]], $this->startAttributeStack[$stackPos-(9-1)] + $this->endAttributes);
+            },
+            160 => function ($stackPos) {
+                 $this->semValue = new Stmt\Switch_($this->semStack[$stackPos-(5-3)], $this->semStack[$stackPos-(5-5)], $this->startAttributeStack[$stackPos-(5-1)] + $this->endAttributes);
+            },
+            161 => function ($stackPos) {
+                 $this->semValue = new Stmt\Break_($this->semStack[$stackPos-(3-2)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            162 => function ($stackPos) {
+                 $this->semValue = new Stmt\Continue_($this->semStack[$stackPos-(3-2)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            163 => function ($stackPos) {
+                 $this->semValue = new Stmt\Return_($this->semStack[$stackPos-(3-2)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            164 => function ($stackPos) {
+                 $this->semValue = new Stmt\Global_($this->semStack[$stackPos-(3-2)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            165 => function ($stackPos) {
+                 $this->semValue = new Stmt\Static_($this->semStack[$stackPos-(3-2)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            166 => function ($stackPos) {
+                 $this->semValue = new Stmt\Echo_($this->semStack[$stackPos-(3-2)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            167 => function ($stackPos) {
+                 $this->semValue = new Stmt\InlineHTML($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes);
+            },
+            168 => function ($stackPos) {
+
+        $e = $this->semStack[$stackPos-(2-1)];
+        if ($e instanceof Expr\Throw_) {
+            // For backwards-compatibility reasons, convert throw in statement position into
+            // Stmt\Throw_ rather than Stmt\Expression(Expr\Throw_).
+            $this->semValue = new Stmt\Throw_($e->expr, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes);
+        } else {
+            $this->semValue = new Stmt\Expression($e, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes);
+        }
+
+            },
+            169 => function ($stackPos) {
+                 $this->semValue = new Stmt\Unset_($this->semStack[$stackPos-(5-3)], $this->startAttributeStack[$stackPos-(5-1)] + $this->endAttributes);
+            },
+            170 => function ($stackPos) {
+                 $this->semValue = new Stmt\Foreach_($this->semStack[$stackPos-(7-3)], $this->semStack[$stackPos-(7-5)][0], ['keyVar' => null, 'byRef' => $this->semStack[$stackPos-(7-5)][1], 'stmts' => $this->semStack[$stackPos-(7-7)]], $this->startAttributeStack[$stackPos-(7-1)] + $this->endAttributes);
+            },
+            171 => function ($stackPos) {
+                 $this->semValue = new Stmt\Foreach_($this->semStack[$stackPos-(9-3)], $this->semStack[$stackPos-(9-7)][0], ['keyVar' => $this->semStack[$stackPos-(9-5)], 'byRef' => $this->semStack[$stackPos-(9-7)][1], 'stmts' => $this->semStack[$stackPos-(9-9)]], $this->startAttributeStack[$stackPos-(9-1)] + $this->endAttributes);
+            },
+            172 => function ($stackPos) {
+                 $this->semValue = new Stmt\Foreach_($this->semStack[$stackPos-(6-3)], new Expr\Error($this->startAttributeStack[$stackPos-(6-4)] + $this->endAttributeStack[$stackPos-(6-4)]), ['stmts' => $this->semStack[$stackPos-(6-6)]], $this->startAttributeStack[$stackPos-(6-1)] + $this->endAttributes);
+            },
+            173 => function ($stackPos) {
+                 $this->semValue = new Stmt\Declare_($this->semStack[$stackPos-(5-3)], $this->semStack[$stackPos-(5-5)], $this->startAttributeStack[$stackPos-(5-1)] + $this->endAttributes);
+            },
+            174 => function ($stackPos) {
+                 $this->semValue = new Stmt\TryCatch($this->semStack[$stackPos-(6-3)], $this->semStack[$stackPos-(6-5)], $this->semStack[$stackPos-(6-6)], $this->startAttributeStack[$stackPos-(6-1)] + $this->endAttributes); $this->checkTryCatch($this->semValue);
+            },
+            175 => function ($stackPos) {
+                 $this->semValue = new Stmt\Goto_($this->semStack[$stackPos-(3-2)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            176 => function ($stackPos) {
+                 $this->semValue = new Stmt\Label($this->semStack[$stackPos-(2-1)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes);
+            },
+            177 => function ($stackPos) {
+                 $this->semValue = array(); /* means: no statement */
+            },
+            178 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(1-1)];
+            },
+            179 => function ($stackPos) {
+                 $startAttributes = $this->startAttributeStack[$stackPos-(1-1)]; if (isset($startAttributes['comments'])) { $this->semValue = new Stmt\Nop($startAttributes + $this->endAttributes); } else { $this->semValue = null; };
+            if ($this->semValue === null) $this->semValue = array(); /* means: no statement */
+            },
+            180 => function ($stackPos) {
+                 $this->semValue = array();
+            },
+            181 => function ($stackPos) {
+                 $this->semStack[$stackPos-(2-1)][] = $this->semStack[$stackPos-(2-2)]; $this->semValue = $this->semStack[$stackPos-(2-1)];
+            },
+            182 => function ($stackPos) {
+                 $this->semValue = array($this->semStack[$stackPos-(1-1)]);
+            },
+            183 => function ($stackPos) {
+                 $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)];
+            },
+            184 => function ($stackPos) {
+                 $this->semValue = new Stmt\Catch_($this->semStack[$stackPos-(8-3)], $this->semStack[$stackPos-(8-4)], $this->semStack[$stackPos-(8-7)], $this->startAttributeStack[$stackPos-(8-1)] + $this->endAttributes);
+            },
+            185 => function ($stackPos) {
+                 $this->semValue = null;
+            },
+            186 => function ($stackPos) {
+                 $this->semValue = new Stmt\Finally_($this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes);
+            },
+            187 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(2-1)];
+            },
+            188 => function ($stackPos) {
+                 $this->semValue = array($this->semStack[$stackPos-(1-1)]);
+            },
+            189 => function ($stackPos) {
+                 $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)];
+            },
+            190 => function ($stackPos) {
+                 $this->semValue = false;
+            },
+            191 => function ($stackPos) {
+                 $this->semValue = true;
+            },
+            192 => function ($stackPos) {
+                 $this->semValue = false;
+            },
+            193 => function ($stackPos) {
+                 $this->semValue = true;
+            },
+            194 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(3-2)];
+            },
+            195 => function ($stackPos) {
+                 $this->semValue = [];
+            },
+            196 => function ($stackPos) {
+                 $this->semValue = new Stmt\Function_($this->semStack[$stackPos-(8-3)], ['byRef' => $this->semStack[$stackPos-(8-2)], 'params' => $this->semStack[$stackPos-(8-5)], 'returnType' => $this->semStack[$stackPos-(8-7)], 'stmts' => $this->semStack[$stackPos-(8-8)], 'attrGroups' => []], $this->startAttributeStack[$stackPos-(8-1)] + $this->endAttributes);
+            },
+            197 => function ($stackPos) {
+                 $this->semValue = new Stmt\Function_($this->semStack[$stackPos-(9-4)], ['byRef' => $this->semStack[$stackPos-(9-3)], 'params' => $this->semStack[$stackPos-(9-6)], 'returnType' => $this->semStack[$stackPos-(9-8)], 'stmts' => $this->semStack[$stackPos-(9-9)], 'attrGroups' => $this->semStack[$stackPos-(9-1)]], $this->startAttributeStack[$stackPos-(9-1)] + $this->endAttributes);
+            },
+            198 => function ($stackPos) {
+                 $this->semValue = new Stmt\Class_($this->semStack[$stackPos-(8-3)], ['type' => $this->semStack[$stackPos-(8-2)], 'extends' => $this->semStack[$stackPos-(8-4)], 'implements' => $this->semStack[$stackPos-(8-5)], 'stmts' => $this->semStack[$stackPos-(8-7)], 'attrGroups' => $this->semStack[$stackPos-(8-1)]], $this->startAttributeStack[$stackPos-(8-1)] + $this->endAttributes);
+            $this->checkClass($this->semValue, $stackPos-(8-3));
+            },
+            199 => function ($stackPos) {
+                 $this->semValue = new Stmt\Interface_($this->semStack[$stackPos-(7-3)], ['extends' => $this->semStack[$stackPos-(7-4)], 'stmts' => $this->semStack[$stackPos-(7-6)], 'attrGroups' => $this->semStack[$stackPos-(7-1)]], $this->startAttributeStack[$stackPos-(7-1)] + $this->endAttributes);
+            $this->checkInterface($this->semValue, $stackPos-(7-3));
+            },
+            200 => function ($stackPos) {
+                 $this->semValue = new Stmt\Trait_($this->semStack[$stackPos-(6-3)], ['stmts' => $this->semStack[$stackPos-(6-5)], 'attrGroups' => $this->semStack[$stackPos-(6-1)]], $this->startAttributeStack[$stackPos-(6-1)] + $this->endAttributes);
+            },
+            201 => function ($stackPos) {
+                 $this->semValue = 0;
+            },
+            202 => function ($stackPos) {
+                 $this->semValue = Stmt\Class_::MODIFIER_ABSTRACT;
+            },
+            203 => function ($stackPos) {
+                 $this->semValue = Stmt\Class_::MODIFIER_FINAL;
+            },
+            204 => function ($stackPos) {
+                 $this->semValue = null;
+            },
+            205 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(2-2)];
+            },
+            206 => function ($stackPos) {
+                 $this->semValue = array();
+            },
+            207 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(2-2)];
+            },
+            208 => function ($stackPos) {
+                 $this->semValue = array();
+            },
+            209 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(2-2)];
+            },
+            210 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(2-1)];
+            },
+            211 => function ($stackPos) {
+                 $this->semValue = array($this->semStack[$stackPos-(1-1)]);
+            },
+            212 => function ($stackPos) {
+                 $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)];
+            },
+            213 => function ($stackPos) {
+                 $this->semValue = is_array($this->semStack[$stackPos-(1-1)]) ? $this->semStack[$stackPos-(1-1)] : array($this->semStack[$stackPos-(1-1)]);
+            },
+            214 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(4-2)];
+            },
+            215 => function ($stackPos) {
+                 $this->semValue = is_array($this->semStack[$stackPos-(1-1)]) ? $this->semStack[$stackPos-(1-1)] : array($this->semStack[$stackPos-(1-1)]);
+            },
+            216 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(4-2)];
+            },
+            217 => function ($stackPos) {
+                 $this->semValue = is_array($this->semStack[$stackPos-(1-1)]) ? $this->semStack[$stackPos-(1-1)] : array($this->semStack[$stackPos-(1-1)]);
+            },
+            218 => function ($stackPos) {
+                 $this->semValue = null;
+            },
+            219 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(4-2)];
+            },
+            220 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(2-1)];
+            },
+            221 => function ($stackPos) {
+                 $this->semValue = array($this->semStack[$stackPos-(1-1)]);
+            },
+            222 => function ($stackPos) {
+                 $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)];
+            },
+            223 => function ($stackPos) {
+                 $this->semValue = new Stmt\DeclareDeclare($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            224 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(3-2)];
+            },
+            225 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(4-3)];
+            },
+            226 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(4-2)];
+            },
+            227 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(5-3)];
+            },
+            228 => function ($stackPos) {
+                 $this->semValue = array();
+            },
+            229 => function ($stackPos) {
+                 $this->semStack[$stackPos-(2-1)][] = $this->semStack[$stackPos-(2-2)]; $this->semValue = $this->semStack[$stackPos-(2-1)];
+            },
+            230 => function ($stackPos) {
+                 $this->semValue = new Stmt\Case_($this->semStack[$stackPos-(4-2)], $this->semStack[$stackPos-(4-4)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes);
+            },
+            231 => function ($stackPos) {
+                 $this->semValue = new Stmt\Case_(null, $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            232 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            233 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            234 => function ($stackPos) {
+                 $this->semValue = new Expr\Match_($this->semStack[$stackPos-(7-3)], $this->semStack[$stackPos-(7-6)], $this->startAttributeStack[$stackPos-(7-1)] + $this->endAttributes);
+            },
+            235 => function ($stackPos) {
+                 $this->semValue = [];
+            },
+            236 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(2-1)];
+            },
+            237 => function ($stackPos) {
+                 $this->semValue = array($this->semStack[$stackPos-(1-1)]);
+            },
+            238 => function ($stackPos) {
+                 $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)];
+            },
+            239 => function ($stackPos) {
+                 $this->semValue = new Node\MatchArm($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            240 => function ($stackPos) {
+                 $this->semValue = new Node\MatchArm(null, $this->semStack[$stackPos-(4-4)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes);
+            },
+            241 => function ($stackPos) {
+                 $this->semValue = is_array($this->semStack[$stackPos-(1-1)]) ? $this->semStack[$stackPos-(1-1)] : array($this->semStack[$stackPos-(1-1)]);
+            },
+            242 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(4-2)];
+            },
+            243 => function ($stackPos) {
+                 $this->semValue = array();
+            },
+            244 => function ($stackPos) {
+                 $this->semStack[$stackPos-(2-1)][] = $this->semStack[$stackPos-(2-2)]; $this->semValue = $this->semStack[$stackPos-(2-1)];
+            },
+            245 => function ($stackPos) {
+                 $this->semValue = new Stmt\ElseIf_($this->semStack[$stackPos-(5-3)], is_array($this->semStack[$stackPos-(5-5)]) ? $this->semStack[$stackPos-(5-5)] : array($this->semStack[$stackPos-(5-5)]), $this->startAttributeStack[$stackPos-(5-1)] + $this->endAttributes);
+            },
+            246 => function ($stackPos) {
+                 $this->semValue = array();
+            },
+            247 => function ($stackPos) {
+                 $this->semStack[$stackPos-(2-1)][] = $this->semStack[$stackPos-(2-2)]; $this->semValue = $this->semStack[$stackPos-(2-1)];
+            },
+            248 => function ($stackPos) {
+                 $this->semValue = new Stmt\ElseIf_($this->semStack[$stackPos-(6-3)], $this->semStack[$stackPos-(6-6)], $this->startAttributeStack[$stackPos-(6-1)] + $this->endAttributes);
+            },
+            249 => function ($stackPos) {
+                 $this->semValue = null;
+            },
+            250 => function ($stackPos) {
+                 $this->semValue = new Stmt\Else_(is_array($this->semStack[$stackPos-(2-2)]) ? $this->semStack[$stackPos-(2-2)] : array($this->semStack[$stackPos-(2-2)]), $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes);
+            },
+            251 => function ($stackPos) {
+                 $this->semValue = null;
+            },
+            252 => function ($stackPos) {
+                 $this->semValue = new Stmt\Else_($this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            253 => function ($stackPos) {
+                 $this->semValue = array($this->semStack[$stackPos-(1-1)], false);
+            },
+            254 => function ($stackPos) {
+                 $this->semValue = array($this->semStack[$stackPos-(2-2)], true);
+            },
+            255 => function ($stackPos) {
+                 $this->semValue = array($this->semStack[$stackPos-(1-1)], false);
+            },
+            256 => function ($stackPos) {
+                 $this->semValue = array($this->semStack[$stackPos-(1-1)], false);
+            },
+            257 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(2-1)];
+            },
+            258 => function ($stackPos) {
+                 $this->semValue = array();
+            },
+            259 => function ($stackPos) {
+                 $this->semValue = array($this->semStack[$stackPos-(1-1)]);
+            },
+            260 => function ($stackPos) {
+                 $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)];
+            },
+            261 => function ($stackPos) {
+                 $this->semValue = 0;
+            },
+            262 => function ($stackPos) {
+                 $this->semValue = Stmt\Class_::MODIFIER_PUBLIC;
+            },
+            263 => function ($stackPos) {
+                 $this->semValue = Stmt\Class_::MODIFIER_PROTECTED;
+            },
+            264 => function ($stackPos) {
+                 $this->semValue = Stmt\Class_::MODIFIER_PRIVATE;
+            },
+            265 => function ($stackPos) {
+                 $this->semValue = new Node\Param($this->semStack[$stackPos-(6-6)], null, $this->semStack[$stackPos-(6-3)], $this->semStack[$stackPos-(6-4)], $this->semStack[$stackPos-(6-5)], $this->startAttributeStack[$stackPos-(6-1)] + $this->endAttributes, $this->semStack[$stackPos-(6-2)], $this->semStack[$stackPos-(6-1)]);
+            $this->checkParam($this->semValue);
+            },
+            266 => function ($stackPos) {
+                 $this->semValue = new Node\Param($this->semStack[$stackPos-(8-6)], $this->semStack[$stackPos-(8-8)], $this->semStack[$stackPos-(8-3)], $this->semStack[$stackPos-(8-4)], $this->semStack[$stackPos-(8-5)], $this->startAttributeStack[$stackPos-(8-1)] + $this->endAttributes, $this->semStack[$stackPos-(8-2)], $this->semStack[$stackPos-(8-1)]);
+            $this->checkParam($this->semValue);
+            },
+            267 => function ($stackPos) {
+                 $this->semValue = new Node\Param(new Expr\Error($this->startAttributeStack[$stackPos-(6-1)] + $this->endAttributes), null, $this->semStack[$stackPos-(6-3)], $this->semStack[$stackPos-(6-4)], $this->semStack[$stackPos-(6-5)], $this->startAttributeStack[$stackPos-(6-1)] + $this->endAttributes, $this->semStack[$stackPos-(6-2)], $this->semStack[$stackPos-(6-1)]);
+            },
+            268 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(1-1)];
+            },
+            269 => function ($stackPos) {
+                 $this->semValue = new Node\NullableType($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes);
+            },
+            270 => function ($stackPos) {
+                 $this->semValue = new Node\UnionType($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes);
+            },
+            271 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(1-1)];
+            },
+            272 => function ($stackPos) {
+                 $this->semValue = new Node\Name('static', $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes);
+            },
+            273 => function ($stackPos) {
+                 $this->semValue = $this->handleBuiltinTypes($this->semStack[$stackPos-(1-1)]);
+            },
+            274 => function ($stackPos) {
+                 $this->semValue = new Node\Identifier('array', $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes);
+            },
+            275 => function ($stackPos) {
+                 $this->semValue = new Node\Identifier('callable', $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes);
+            },
+            276 => function ($stackPos) {
+                 $this->semValue = array($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)]);
+            },
+            277 => function ($stackPos) {
+                 $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)];
+            },
+            278 => function ($stackPos) {
+                 $this->semValue = array($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)]);
+            },
+            279 => function ($stackPos) {
+                 $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)];
+            },
+            280 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(1-1)];
+            },
+            281 => function ($stackPos) {
+                 $this->semValue = new Node\NullableType($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes);
+            },
+            282 => function ($stackPos) {
+                 $this->semValue = new Node\UnionType($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes);
+            },
+            283 => function ($stackPos) {
+                 $this->semValue = null;
+            },
+            284 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(1-1)];
+            },
+            285 => function ($stackPos) {
+                 $this->semValue = null;
+            },
+            286 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(2-2)];
+            },
+            287 => function ($stackPos) {
+                 $this->semValue = null;
+            },
+            288 => function ($stackPos) {
+                 $this->semValue = array();
+            },
+            289 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(4-2)];
+            },
+            290 => function ($stackPos) {
+                 $this->semValue = array($this->semStack[$stackPos-(1-1)]);
+            },
+            291 => function ($stackPos) {
+                 $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)];
+            },
+            292 => function ($stackPos) {
+                 $this->semValue = new Node\Arg($this->semStack[$stackPos-(1-1)], false, false, $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes);
+            },
+            293 => function ($stackPos) {
+                 $this->semValue = new Node\Arg($this->semStack[$stackPos-(2-2)], true, false, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes);
+            },
+            294 => function ($stackPos) {
+                 $this->semValue = new Node\Arg($this->semStack[$stackPos-(2-2)], false, true, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes);
+            },
+            295 => function ($stackPos) {
+                 $this->semValue = new Node\Arg($this->semStack[$stackPos-(3-3)], false, false, $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes, $this->semStack[$stackPos-(3-1)]);
+            },
+            296 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(2-1)];
+            },
+            297 => function ($stackPos) {
+                 $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)];
+            },
+            298 => function ($stackPos) {
+                 $this->semValue = array($this->semStack[$stackPos-(1-1)]);
+            },
+            299 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(1-1)];
+            },
+            300 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(2-1)];
+            },
+            301 => function ($stackPos) {
+                 $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)];
+            },
+            302 => function ($stackPos) {
+                 $this->semValue = array($this->semStack[$stackPos-(1-1)]);
+            },
+            303 => function ($stackPos) {
+                 $this->semValue = new Stmt\StaticVar($this->semStack[$stackPos-(1-1)], null, $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes);
+            },
+            304 => function ($stackPos) {
+                 $this->semValue = new Stmt\StaticVar($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            305 => function ($stackPos) {
+                 if ($this->semStack[$stackPos-(2-2)] !== null) { $this->semStack[$stackPos-(2-1)][] = $this->semStack[$stackPos-(2-2)]; $this->semValue = $this->semStack[$stackPos-(2-1)]; }
+            },
+            306 => function ($stackPos) {
+                 $this->semValue = array();
+            },
+            307 => function ($stackPos) {
+                 $startAttributes = $this->lookaheadStartAttributes; if (isset($startAttributes['comments'])) { $nop = new Stmt\Nop($this->createCommentNopAttributes($startAttributes['comments'])); } else { $nop = null; };
+            if ($nop !== null) { $this->semStack[$stackPos-(1-1)][] = $nop; } $this->semValue = $this->semStack[$stackPos-(1-1)];
+            },
+            308 => function ($stackPos) {
+                 $this->semValue = new Stmt\Property($this->semStack[$stackPos-(5-2)], $this->semStack[$stackPos-(5-4)], $this->startAttributeStack[$stackPos-(5-1)] + $this->endAttributes, $this->semStack[$stackPos-(5-3)], $this->semStack[$stackPos-(5-1)]);
+            $this->checkProperty($this->semValue, $stackPos-(5-2));
+            },
+            309 => function ($stackPos) {
+                 $this->semValue = new Stmt\ClassConst($this->semStack[$stackPos-(5-4)], $this->semStack[$stackPos-(5-2)], $this->startAttributeStack[$stackPos-(5-1)] + $this->endAttributes, $this->semStack[$stackPos-(5-1)]);
+            $this->checkClassConst($this->semValue, $stackPos-(5-2));
+            },
+            310 => function ($stackPos) {
+                 $this->semValue = new Stmt\ClassMethod($this->semStack[$stackPos-(10-5)], ['type' => $this->semStack[$stackPos-(10-2)], 'byRef' => $this->semStack[$stackPos-(10-4)], 'params' => $this->semStack[$stackPos-(10-7)], 'returnType' => $this->semStack[$stackPos-(10-9)], 'stmts' => $this->semStack[$stackPos-(10-10)], 'attrGroups' => $this->semStack[$stackPos-(10-1)]], $this->startAttributeStack[$stackPos-(10-1)] + $this->endAttributes);
+            $this->checkClassMethod($this->semValue, $stackPos-(10-2));
+            },
+            311 => function ($stackPos) {
+                 $this->semValue = new Stmt\TraitUse($this->semStack[$stackPos-(3-2)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            312 => function ($stackPos) {
+                 $this->semValue = null; /* will be skipped */
+            },
+            313 => function ($stackPos) {
+                 $this->semValue = array();
+            },
+            314 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(3-2)];
+            },
+            315 => function ($stackPos) {
+                 $this->semValue = array();
+            },
+            316 => function ($stackPos) {
+                 $this->semStack[$stackPos-(2-1)][] = $this->semStack[$stackPos-(2-2)]; $this->semValue = $this->semStack[$stackPos-(2-1)];
+            },
+            317 => function ($stackPos) {
+                 $this->semValue = new Stmt\TraitUseAdaptation\Precedence($this->semStack[$stackPos-(4-1)][0], $this->semStack[$stackPos-(4-1)][1], $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes);
+            },
+            318 => function ($stackPos) {
+                 $this->semValue = new Stmt\TraitUseAdaptation\Alias($this->semStack[$stackPos-(5-1)][0], $this->semStack[$stackPos-(5-1)][1], $this->semStack[$stackPos-(5-3)], $this->semStack[$stackPos-(5-4)], $this->startAttributeStack[$stackPos-(5-1)] + $this->endAttributes);
+            },
+            319 => function ($stackPos) {
+                 $this->semValue = new Stmt\TraitUseAdaptation\Alias($this->semStack[$stackPos-(4-1)][0], $this->semStack[$stackPos-(4-1)][1], $this->semStack[$stackPos-(4-3)], null, $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes);
+            },
+            320 => function ($stackPos) {
+                 $this->semValue = new Stmt\TraitUseAdaptation\Alias($this->semStack[$stackPos-(4-1)][0], $this->semStack[$stackPos-(4-1)][1], null, $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes);
+            },
+            321 => function ($stackPos) {
+                 $this->semValue = new Stmt\TraitUseAdaptation\Alias($this->semStack[$stackPos-(4-1)][0], $this->semStack[$stackPos-(4-1)][1], null, $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes);
+            },
+            322 => function ($stackPos) {
+                 $this->semValue = array($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)]);
+            },
+            323 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(1-1)];
+            },
+            324 => function ($stackPos) {
+                 $this->semValue = array(null, $this->semStack[$stackPos-(1-1)]);
+            },
+            325 => function ($stackPos) {
+                 $this->semValue = null;
+            },
+            326 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(1-1)];
+            },
+            327 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(1-1)];
+            },
+            328 => function ($stackPos) {
+                 $this->semValue = 0;
+            },
+            329 => function ($stackPos) {
+                 $this->semValue = 0;
+            },
+            330 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(1-1)];
+            },
+            331 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(1-1)];
+            },
+            332 => function ($stackPos) {
+                 $this->checkModifier($this->semStack[$stackPos-(2-1)], $this->semStack[$stackPos-(2-2)], $stackPos-(2-2)); $this->semValue = $this->semStack[$stackPos-(2-1)] | $this->semStack[$stackPos-(2-2)];
+            },
+            333 => function ($stackPos) {
+                 $this->semValue = Stmt\Class_::MODIFIER_PUBLIC;
+            },
+            334 => function ($stackPos) {
+                 $this->semValue = Stmt\Class_::MODIFIER_PROTECTED;
+            },
+            335 => function ($stackPos) {
+                 $this->semValue = Stmt\Class_::MODIFIER_PRIVATE;
+            },
+            336 => function ($stackPos) {
+                 $this->semValue = Stmt\Class_::MODIFIER_STATIC;
+            },
+            337 => function ($stackPos) {
+                 $this->semValue = Stmt\Class_::MODIFIER_ABSTRACT;
+            },
+            338 => function ($stackPos) {
+                 $this->semValue = Stmt\Class_::MODIFIER_FINAL;
+            },
+            339 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(2-1)];
+            },
+            340 => function ($stackPos) {
+                 $this->semValue = array($this->semStack[$stackPos-(1-1)]);
+            },
+            341 => function ($stackPos) {
+                 $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)];
+            },
+            342 => function ($stackPos) {
+                 $this->semValue = new Node\VarLikeIdentifier(substr($this->semStack[$stackPos-(1-1)], 1), $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes);
+            },
+            343 => function ($stackPos) {
+                 $this->semValue = new Stmt\PropertyProperty($this->semStack[$stackPos-(1-1)], null, $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes);
+            },
+            344 => function ($stackPos) {
+                 $this->semValue = new Stmt\PropertyProperty($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            345 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(2-1)];
+            },
+            346 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(2-1)];
+            },
+            347 => function ($stackPos) {
+                 $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)];
+            },
+            348 => function ($stackPos) {
+                 $this->semValue = array($this->semStack[$stackPos-(1-1)]);
+            },
+            349 => function ($stackPos) {
+                 $this->semValue = array();
+            },
+            350 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(1-1)];
+            },
+            351 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(1-1)];
+            },
+            352 => function ($stackPos) {
+                 $this->semValue = new Expr\Assign($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            353 => function ($stackPos) {
+                 $this->semValue = new Expr\Assign($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            354 => function ($stackPos) {
+                 $this->semValue = new Expr\Assign($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            355 => function ($stackPos) {
+                 $this->semValue = new Expr\AssignRef($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-4)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes);
+            },
+            356 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(1-1)];
+            },
+            357 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(1-1)];
+            },
+            358 => function ($stackPos) {
+                 $this->semValue = new Expr\Clone_($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes);
+            },
+            359 => function ($stackPos) {
+                 $this->semValue = new Expr\AssignOp\Plus($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            360 => function ($stackPos) {
+                 $this->semValue = new Expr\AssignOp\Minus($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            361 => function ($stackPos) {
+                 $this->semValue = new Expr\AssignOp\Mul($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            362 => function ($stackPos) {
+                 $this->semValue = new Expr\AssignOp\Div($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            363 => function ($stackPos) {
+                 $this->semValue = new Expr\AssignOp\Concat($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            364 => function ($stackPos) {
+                 $this->semValue = new Expr\AssignOp\Mod($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            365 => function ($stackPos) {
+                 $this->semValue = new Expr\AssignOp\BitwiseAnd($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            366 => function ($stackPos) {
+                 $this->semValue = new Expr\AssignOp\BitwiseOr($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            367 => function ($stackPos) {
+                 $this->semValue = new Expr\AssignOp\BitwiseXor($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            368 => function ($stackPos) {
+                 $this->semValue = new Expr\AssignOp\ShiftLeft($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            369 => function ($stackPos) {
+                 $this->semValue = new Expr\AssignOp\ShiftRight($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            370 => function ($stackPos) {
+                 $this->semValue = new Expr\AssignOp\Pow($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            371 => function ($stackPos) {
+                 $this->semValue = new Expr\AssignOp\Coalesce($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            372 => function ($stackPos) {
+                 $this->semValue = new Expr\PostInc($this->semStack[$stackPos-(2-1)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes);
+            },
+            373 => function ($stackPos) {
+                 $this->semValue = new Expr\PreInc($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes);
+            },
+            374 => function ($stackPos) {
+                 $this->semValue = new Expr\PostDec($this->semStack[$stackPos-(2-1)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes);
+            },
+            375 => function ($stackPos) {
+                 $this->semValue = new Expr\PreDec($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes);
+            },
+            376 => function ($stackPos) {
+                 $this->semValue = new Expr\BinaryOp\BooleanOr($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            377 => function ($stackPos) {
+                 $this->semValue = new Expr\BinaryOp\BooleanAnd($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            378 => function ($stackPos) {
+                 $this->semValue = new Expr\BinaryOp\LogicalOr($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            379 => function ($stackPos) {
+                 $this->semValue = new Expr\BinaryOp\LogicalAnd($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            380 => function ($stackPos) {
+                 $this->semValue = new Expr\BinaryOp\LogicalXor($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            381 => function ($stackPos) {
+                 $this->semValue = new Expr\BinaryOp\BitwiseOr($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            382 => function ($stackPos) {
+                 $this->semValue = new Expr\BinaryOp\BitwiseAnd($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            383 => function ($stackPos) {
+                 $this->semValue = new Expr\BinaryOp\BitwiseXor($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            384 => function ($stackPos) {
+                 $this->semValue = new Expr\BinaryOp\Concat($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            385 => function ($stackPos) {
+                 $this->semValue = new Expr\BinaryOp\Plus($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            386 => function ($stackPos) {
+                 $this->semValue = new Expr\BinaryOp\Minus($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            387 => function ($stackPos) {
+                 $this->semValue = new Expr\BinaryOp\Mul($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            388 => function ($stackPos) {
+                 $this->semValue = new Expr\BinaryOp\Div($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            389 => function ($stackPos) {
+                 $this->semValue = new Expr\BinaryOp\Mod($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            390 => function ($stackPos) {
+                 $this->semValue = new Expr\BinaryOp\ShiftLeft($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            391 => function ($stackPos) {
+                 $this->semValue = new Expr\BinaryOp\ShiftRight($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            392 => function ($stackPos) {
+                 $this->semValue = new Expr\BinaryOp\Pow($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            393 => function ($stackPos) {
+                 $this->semValue = new Expr\UnaryPlus($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes);
+            },
+            394 => function ($stackPos) {
+                 $this->semValue = new Expr\UnaryMinus($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes);
+            },
+            395 => function ($stackPos) {
+                 $this->semValue = new Expr\BooleanNot($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes);
+            },
+            396 => function ($stackPos) {
+                 $this->semValue = new Expr\BitwiseNot($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes);
+            },
+            397 => function ($stackPos) {
+                 $this->semValue = new Expr\BinaryOp\Identical($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            398 => function ($stackPos) {
+                 $this->semValue = new Expr\BinaryOp\NotIdentical($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            399 => function ($stackPos) {
+                 $this->semValue = new Expr\BinaryOp\Equal($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            400 => function ($stackPos) {
+                 $this->semValue = new Expr\BinaryOp\NotEqual($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            401 => function ($stackPos) {
+                 $this->semValue = new Expr\BinaryOp\Spaceship($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            402 => function ($stackPos) {
+                 $this->semValue = new Expr\BinaryOp\Smaller($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            403 => function ($stackPos) {
+                 $this->semValue = new Expr\BinaryOp\SmallerOrEqual($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            404 => function ($stackPos) {
+                 $this->semValue = new Expr\BinaryOp\Greater($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            405 => function ($stackPos) {
+                 $this->semValue = new Expr\BinaryOp\GreaterOrEqual($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            406 => function ($stackPos) {
+                 $this->semValue = new Expr\Instanceof_($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            407 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(3-2)];
+            },
+            408 => function ($stackPos) {
+                 $this->semValue = new Expr\Ternary($this->semStack[$stackPos-(5-1)], $this->semStack[$stackPos-(5-3)], $this->semStack[$stackPos-(5-5)], $this->startAttributeStack[$stackPos-(5-1)] + $this->endAttributes);
+            },
+            409 => function ($stackPos) {
+                 $this->semValue = new Expr\Ternary($this->semStack[$stackPos-(4-1)], null, $this->semStack[$stackPos-(4-4)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes);
+            },
+            410 => function ($stackPos) {
+                 $this->semValue = new Expr\BinaryOp\Coalesce($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            411 => function ($stackPos) {
+                 $this->semValue = new Expr\Isset_($this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes);
+            },
+            412 => function ($stackPos) {
+                 $this->semValue = new Expr\Empty_($this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes);
+            },
+            413 => function ($stackPos) {
+                 $this->semValue = new Expr\Include_($this->semStack[$stackPos-(2-2)], Expr\Include_::TYPE_INCLUDE, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes);
+            },
+            414 => function ($stackPos) {
+                 $this->semValue = new Expr\Include_($this->semStack[$stackPos-(2-2)], Expr\Include_::TYPE_INCLUDE_ONCE, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes);
+            },
+            415 => function ($stackPos) {
+                 $this->semValue = new Expr\Eval_($this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes);
+            },
+            416 => function ($stackPos) {
+                 $this->semValue = new Expr\Include_($this->semStack[$stackPos-(2-2)], Expr\Include_::TYPE_REQUIRE, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes);
+            },
+            417 => function ($stackPos) {
+                 $this->semValue = new Expr\Include_($this->semStack[$stackPos-(2-2)], Expr\Include_::TYPE_REQUIRE_ONCE, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes);
+            },
+            418 => function ($stackPos) {
+                 $this->semValue = new Expr\Cast\Int_($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes);
+            },
+            419 => function ($stackPos) {
+                 $attrs = $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes;
+            $attrs['kind'] = $this->getFloatCastKind($this->semStack[$stackPos-(2-1)]);
+            $this->semValue = new Expr\Cast\Double($this->semStack[$stackPos-(2-2)], $attrs);
+            },
+            420 => function ($stackPos) {
+                 $this->semValue = new Expr\Cast\String_($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes);
+            },
+            421 => function ($stackPos) {
+                 $this->semValue = new Expr\Cast\Array_($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes);
+            },
+            422 => function ($stackPos) {
+                 $this->semValue = new Expr\Cast\Object_($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes);
+            },
+            423 => function ($stackPos) {
+                 $this->semValue = new Expr\Cast\Bool_($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes);
+            },
+            424 => function ($stackPos) {
+                 $this->semValue = new Expr\Cast\Unset_($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes);
+            },
+            425 => function ($stackPos) {
+                 $attrs = $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes;
+            $attrs['kind'] = strtolower($this->semStack[$stackPos-(2-1)]) === 'exit' ? Expr\Exit_::KIND_EXIT : Expr\Exit_::KIND_DIE;
+            $this->semValue = new Expr\Exit_($this->semStack[$stackPos-(2-2)], $attrs);
+            },
+            426 => function ($stackPos) {
+                 $this->semValue = new Expr\ErrorSuppress($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes);
+            },
+            427 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(1-1)];
+            },
+            428 => function ($stackPos) {
+                 $this->semValue = new Expr\ShellExec($this->semStack[$stackPos-(3-2)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            429 => function ($stackPos) {
+                 $this->semValue = new Expr\Print_($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes);
+            },
+            430 => function ($stackPos) {
+                 $this->semValue = new Expr\Yield_(null, null, $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes);
+            },
+            431 => function ($stackPos) {
+                 $this->semValue = new Expr\Yield_($this->semStack[$stackPos-(2-2)], null, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes);
+            },
+            432 => function ($stackPos) {
+                 $this->semValue = new Expr\Yield_($this->semStack[$stackPos-(4-4)], $this->semStack[$stackPos-(4-2)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes);
+            },
+            433 => function ($stackPos) {
+                 $this->semValue = new Expr\YieldFrom($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes);
+            },
+            434 => function ($stackPos) {
+                 $this->semValue = new Expr\Throw_($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes);
+            },
+            435 => function ($stackPos) {
+                 $this->semValue = new Expr\ArrowFunction(['static' => false, 'byRef' => $this->semStack[$stackPos-(8-2)], 'params' => $this->semStack[$stackPos-(8-4)], 'returnType' => $this->semStack[$stackPos-(8-6)], 'expr' => $this->semStack[$stackPos-(8-8)], 'attrGroups' => []], $this->startAttributeStack[$stackPos-(8-1)] + $this->endAttributes);
+            },
+            436 => function ($stackPos) {
+                 $this->semValue = new Expr\ArrowFunction(['static' => true, 'byRef' => $this->semStack[$stackPos-(9-3)], 'params' => $this->semStack[$stackPos-(9-5)], 'returnType' => $this->semStack[$stackPos-(9-7)], 'expr' => $this->semStack[$stackPos-(9-9)], 'attrGroups' => []], $this->startAttributeStack[$stackPos-(9-1)] + $this->endAttributes);
+            },
+            437 => function ($stackPos) {
+                 $this->semValue = new Expr\Closure(['static' => false, 'byRef' => $this->semStack[$stackPos-(8-2)], 'params' => $this->semStack[$stackPos-(8-4)], 'uses' => $this->semStack[$stackPos-(8-6)], 'returnType' => $this->semStack[$stackPos-(8-7)], 'stmts' => $this->semStack[$stackPos-(8-8)], 'attrGroups' => []], $this->startAttributeStack[$stackPos-(8-1)] + $this->endAttributes);
+            },
+            438 => function ($stackPos) {
+                 $this->semValue = new Expr\Closure(['static' => true, 'byRef' => $this->semStack[$stackPos-(9-3)], 'params' => $this->semStack[$stackPos-(9-5)], 'uses' => $this->semStack[$stackPos-(9-7)], 'returnType' => $this->semStack[$stackPos-(9-8)], 'stmts' => $this->semStack[$stackPos-(9-9)], 'attrGroups' => []], $this->startAttributeStack[$stackPos-(9-1)] + $this->endAttributes);
+            },
+            439 => function ($stackPos) {
+                 $this->semValue = new Expr\ArrowFunction(['static' => false, 'byRef' => $this->semStack[$stackPos-(9-3)], 'params' => $this->semStack[$stackPos-(9-5)], 'returnType' => $this->semStack[$stackPos-(9-7)], 'expr' => $this->semStack[$stackPos-(9-9)], 'attrGroups' => $this->semStack[$stackPos-(9-1)]], $this->startAttributeStack[$stackPos-(9-1)] + $this->endAttributes);
+            },
+            440 => function ($stackPos) {
+                 $this->semValue = new Expr\ArrowFunction(['static' => true, 'byRef' => $this->semStack[$stackPos-(10-4)], 'params' => $this->semStack[$stackPos-(10-6)], 'returnType' => $this->semStack[$stackPos-(10-8)], 'expr' => $this->semStack[$stackPos-(10-10)], 'attrGroups' => $this->semStack[$stackPos-(10-1)]], $this->startAttributeStack[$stackPos-(10-1)] + $this->endAttributes);
+            },
+            441 => function ($stackPos) {
+                 $this->semValue = new Expr\Closure(['static' => false, 'byRef' => $this->semStack[$stackPos-(9-3)], 'params' => $this->semStack[$stackPos-(9-5)], 'uses' => $this->semStack[$stackPos-(9-7)], 'returnType' => $this->semStack[$stackPos-(9-8)], 'stmts' => $this->semStack[$stackPos-(9-9)], 'attrGroups' => $this->semStack[$stackPos-(9-1)]], $this->startAttributeStack[$stackPos-(9-1)] + $this->endAttributes);
+            },
+            442 => function ($stackPos) {
+                 $this->semValue = new Expr\Closure(['static' => true, 'byRef' => $this->semStack[$stackPos-(10-4)], 'params' => $this->semStack[$stackPos-(10-6)], 'uses' => $this->semStack[$stackPos-(10-8)], 'returnType' => $this->semStack[$stackPos-(10-9)], 'stmts' => $this->semStack[$stackPos-(10-10)], 'attrGroups' => $this->semStack[$stackPos-(10-1)]], $this->startAttributeStack[$stackPos-(10-1)] + $this->endAttributes);
+            },
+            443 => function ($stackPos) {
+                 $this->semValue = array(new Stmt\Class_(null, ['type' => 0, 'extends' => $this->semStack[$stackPos-(8-4)], 'implements' => $this->semStack[$stackPos-(8-5)], 'stmts' => $this->semStack[$stackPos-(8-7)], 'attrGroups' => $this->semStack[$stackPos-(8-1)]], $this->startAttributeStack[$stackPos-(8-1)] + $this->endAttributes), $this->semStack[$stackPos-(8-3)]);
+            $this->checkClass($this->semValue[0], -1);
+            },
+            444 => function ($stackPos) {
+                 $this->semValue = new Expr\New_($this->semStack[$stackPos-(3-2)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            445 => function ($stackPos) {
+                 list($class, $ctorArgs) = $this->semStack[$stackPos-(2-2)]; $this->semValue = new Expr\New_($class, $ctorArgs, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes);
+            },
+            446 => function ($stackPos) {
+                 $this->semValue = array();
+            },
+            447 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(4-3)];
+            },
+            448 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(2-1)];
+            },
+            449 => function ($stackPos) {
+                 $this->semValue = array($this->semStack[$stackPos-(1-1)]);
+            },
+            450 => function ($stackPos) {
+                 $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)];
+            },
+            451 => function ($stackPos) {
+                 $this->semValue = new Expr\ClosureUse($this->semStack[$stackPos-(2-2)], $this->semStack[$stackPos-(2-1)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes);
+            },
+            452 => function ($stackPos) {
+                 $this->semValue = new Expr\FuncCall($this->semStack[$stackPos-(2-1)], $this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes);
+            },
+            453 => function ($stackPos) {
+                 $this->semValue = new Expr\FuncCall($this->semStack[$stackPos-(2-1)], $this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes);
+            },
+            454 => function ($stackPos) {
+                 $this->semValue = new Expr\StaticCall($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-3)], $this->semStack[$stackPos-(4-4)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes);
+            },
+            455 => function ($stackPos) {
+                 $this->semValue = new Name($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes);
+            },
+            456 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(1-1)];
+            },
+            457 => function ($stackPos) {
+                 $this->semValue = new Name($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes);
+            },
+            458 => function ($stackPos) {
+                 $this->semValue = new Name($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes);
+            },
+            459 => function ($stackPos) {
+                 $this->semValue = new Name\FullyQualified(substr($this->semStack[$stackPos-(1-1)], 1), $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes);
+            },
+            460 => function ($stackPos) {
+                 $this->semValue = new Name\Relative(substr($this->semStack[$stackPos-(1-1)], 10), $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes);
+            },
+            461 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(1-1)];
+            },
+            462 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(1-1)];
+            },
+            463 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(3-2)];
+            },
+            464 => function ($stackPos) {
+                 $this->semValue = new Expr\Error($this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); $this->errorState = 2;
+            },
+            465 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(1-1)];
+            },
+            466 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(1-1)];
+            },
+            467 => function ($stackPos) {
+                 $this->semValue = null;
+            },
+            468 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(3-2)];
+            },
+            469 => function ($stackPos) {
+                 $this->semValue = array();
+            },
+            470 => function ($stackPos) {
+                 $this->semValue = array(new Scalar\EncapsedStringPart(Scalar\String_::parseEscapeSequences($this->semStack[$stackPos-(1-1)], '`'), $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes));
+            },
+            471 => function ($stackPos) {
+                 foreach ($this->semStack[$stackPos-(1-1)] as $s) { if ($s instanceof Node\Scalar\EncapsedStringPart) { $s->value = Node\Scalar\String_::parseEscapeSequences($s->value, '`', true); } }; $this->semValue = $this->semStack[$stackPos-(1-1)];
+            },
+            472 => function ($stackPos) {
+                 $this->semValue = array();
+            },
+            473 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(1-1)];
+            },
+            474 => function ($stackPos) {
+                 $this->semValue = new Expr\ConstFetch($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes);
+            },
+            475 => function ($stackPos) {
+                 $this->semValue = new Scalar\MagicConst\Line($this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes);
+            },
+            476 => function ($stackPos) {
+                 $this->semValue = new Scalar\MagicConst\File($this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes);
+            },
+            477 => function ($stackPos) {
+                 $this->semValue = new Scalar\MagicConst\Dir($this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes);
+            },
+            478 => function ($stackPos) {
+                 $this->semValue = new Scalar\MagicConst\Class_($this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes);
+            },
+            479 => function ($stackPos) {
+                 $this->semValue = new Scalar\MagicConst\Trait_($this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes);
+            },
+            480 => function ($stackPos) {
+                 $this->semValue = new Scalar\MagicConst\Method($this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes);
+            },
+            481 => function ($stackPos) {
+                 $this->semValue = new Scalar\MagicConst\Function_($this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes);
+            },
+            482 => function ($stackPos) {
+                 $this->semValue = new Scalar\MagicConst\Namespace_($this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes);
+            },
+            483 => function ($stackPos) {
+                 $this->semValue = new Expr\ClassConstFetch($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            484 => function ($stackPos) {
+                 $this->semValue = new Expr\ClassConstFetch($this->semStack[$stackPos-(3-1)], new Expr\Error($this->startAttributeStack[$stackPos-(3-3)] + $this->endAttributeStack[$stackPos-(3-3)]), $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); $this->errorState = 2;
+            },
+            485 => function ($stackPos) {
+                 $attrs = $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes; $attrs['kind'] = Expr\Array_::KIND_SHORT;
+            $this->semValue = new Expr\Array_($this->semStack[$stackPos-(3-2)], $attrs);
+            },
+            486 => function ($stackPos) {
+                 $attrs = $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes; $attrs['kind'] = Expr\Array_::KIND_LONG;
+            $this->semValue = new Expr\Array_($this->semStack[$stackPos-(4-3)], $attrs);
+            },
+            487 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(1-1)];
+            },
+            488 => function ($stackPos) {
+                 $attrs = $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes; $attrs['kind'] = ($this->semStack[$stackPos-(1-1)][0] === "'" || ($this->semStack[$stackPos-(1-1)][1] === "'" && ($this->semStack[$stackPos-(1-1)][0] === 'b' || $this->semStack[$stackPos-(1-1)][0] === 'B')) ? Scalar\String_::KIND_SINGLE_QUOTED : Scalar\String_::KIND_DOUBLE_QUOTED);
+            $this->semValue = new Scalar\String_(Scalar\String_::parse($this->semStack[$stackPos-(1-1)]), $attrs);
+            },
+            489 => function ($stackPos) {
+                 $attrs = $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes; $attrs['kind'] = Scalar\String_::KIND_DOUBLE_QUOTED;
+            foreach ($this->semStack[$stackPos-(3-2)] as $s) { if ($s instanceof Node\Scalar\EncapsedStringPart) { $s->value = Node\Scalar\String_::parseEscapeSequences($s->value, '"', true); } }; $this->semValue = new Scalar\Encapsed($this->semStack[$stackPos-(3-2)], $attrs);
+            },
+            490 => function ($stackPos) {
+                 $this->semValue = $this->parseLNumber($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes);
+            },
+            491 => function ($stackPos) {
+                 $this->semValue = new Scalar\DNumber(Scalar\DNumber::parse($this->semStack[$stackPos-(1-1)]), $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes);
+            },
+            492 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(1-1)];
+            },
+            493 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(1-1)];
+            },
+            494 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(1-1)];
+            },
+            495 => function ($stackPos) {
+                 $this->semValue = $this->parseDocString($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-2)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes, $this->startAttributeStack[$stackPos-(3-3)] + $this->endAttributeStack[$stackPos-(3-3)], true);
+            },
+            496 => function ($stackPos) {
+                 $this->semValue = $this->parseDocString($this->semStack[$stackPos-(2-1)], '', $this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes, $this->startAttributeStack[$stackPos-(2-2)] + $this->endAttributeStack[$stackPos-(2-2)], true);
+            },
+            497 => function ($stackPos) {
+                 $this->semValue = $this->parseDocString($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-2)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes, $this->startAttributeStack[$stackPos-(3-3)] + $this->endAttributeStack[$stackPos-(3-3)], true);
+            },
+            498 => function ($stackPos) {
+                 $this->semValue = null;
+            },
+            499 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(1-1)];
+            },
+            500 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(1-1)];
+            },
+            501 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(3-2)];
+            },
+            502 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(1-1)];
+            },
+            503 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(1-1)];
+            },
+            504 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(1-1)];
+            },
+            505 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(1-1)];
+            },
+            506 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(1-1)];
+            },
+            507 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(3-2)];
+            },
+            508 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(1-1)];
+            },
+            509 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(1-1)];
+            },
+            510 => function ($stackPos) {
+                 $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes);
+            },
+            511 => function ($stackPos) {
+                 $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes);
+            },
+            512 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(1-1)];
+            },
+            513 => function ($stackPos) {
+                 $this->semValue = new Expr\MethodCall($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-3)], $this->semStack[$stackPos-(4-4)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes);
+            },
+            514 => function ($stackPos) {
+                 $this->semValue = new Expr\NullsafeMethodCall($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-3)], $this->semStack[$stackPos-(4-4)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes);
+            },
+            515 => function ($stackPos) {
+                 $this->semValue = null;
+            },
+            516 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(1-1)];
+            },
+            517 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(1-1)];
+            },
+            518 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(1-1)];
+            },
+            519 => function ($stackPos) {
+                 $this->semValue = new Expr\PropertyFetch($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            520 => function ($stackPos) {
+                 $this->semValue = new Expr\NullsafePropertyFetch($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            521 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(1-1)];
+            },
+            522 => function ($stackPos) {
+                 $this->semValue = new Expr\Variable($this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes);
+            },
+            523 => function ($stackPos) {
+                 $this->semValue = new Expr\Variable($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes);
+            },
+            524 => function ($stackPos) {
+                 $this->semValue = new Expr\Variable(new Expr\Error($this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes), $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); $this->errorState = 2;
+            },
+            525 => function ($stackPos) {
+                 $var = $this->semStack[$stackPos-(1-1)]->name; $this->semValue = \is_string($var) ? new Node\VarLikeIdentifier($var, $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes) : $var;
+            },
+            526 => function ($stackPos) {
+                 $this->semValue = new Expr\StaticPropertyFetch($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            527 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(1-1)];
+            },
+            528 => function ($stackPos) {
+                 $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes);
+            },
+            529 => function ($stackPos) {
+                 $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes);
+            },
+            530 => function ($stackPos) {
+                 $this->semValue = new Expr\PropertyFetch($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            531 => function ($stackPos) {
+                 $this->semValue = new Expr\NullsafePropertyFetch($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            532 => function ($stackPos) {
+                 $this->semValue = new Expr\StaticPropertyFetch($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            533 => function ($stackPos) {
+                 $this->semValue = new Expr\StaticPropertyFetch($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            534 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(1-1)];
+            },
+            535 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(3-2)];
+            },
+            536 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(1-1)];
+            },
+            537 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(1-1)];
+            },
+            538 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(3-2)];
+            },
+            539 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(1-1)];
+            },
+            540 => function ($stackPos) {
+                 $this->semValue = new Expr\Error($this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); $this->errorState = 2;
+            },
+            541 => function ($stackPos) {
+                 $this->semValue = new Expr\List_($this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes);
+            },
+            542 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(1-1)]; $end = count($this->semValue)-1; if ($this->semValue[$end] === null) array_pop($this->semValue);
+            },
+            543 => function ($stackPos) {
+                $this->semValue = $this->semStack[$stackPos];
+            },
+            544 => function ($stackPos) {
+                 /* do nothing -- prevent default action of $$=$this->semStack[$1]. See $551. */
+            },
+            545 => function ($stackPos) {
+                 $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)];
+            },
+            546 => function ($stackPos) {
+                 $this->semValue = array($this->semStack[$stackPos-(1-1)]);
+            },
+            547 => function ($stackPos) {
+                 $this->semValue = new Expr\ArrayItem($this->semStack[$stackPos-(1-1)], null, false, $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes);
+            },
+            548 => function ($stackPos) {
+                 $this->semValue = new Expr\ArrayItem($this->semStack[$stackPos-(2-2)], null, true, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes);
+            },
+            549 => function ($stackPos) {
+                 $this->semValue = new Expr\ArrayItem($this->semStack[$stackPos-(1-1)], null, false, $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes);
+            },
+            550 => function ($stackPos) {
+                 $this->semValue = new Expr\ArrayItem($this->semStack[$stackPos-(3-3)], $this->semStack[$stackPos-(3-1)], false, $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            551 => function ($stackPos) {
+                 $this->semValue = new Expr\ArrayItem($this->semStack[$stackPos-(4-4)], $this->semStack[$stackPos-(4-1)], true, $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes);
+            },
+            552 => function ($stackPos) {
+                 $this->semValue = new Expr\ArrayItem($this->semStack[$stackPos-(3-3)], $this->semStack[$stackPos-(3-1)], false, $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            553 => function ($stackPos) {
+                 $this->semValue = new Expr\ArrayItem($this->semStack[$stackPos-(2-2)], null, false, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes, true, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes);
+            },
+            554 => function ($stackPos) {
+                 $this->semValue = null;
+            },
+            555 => function ($stackPos) {
+                 $this->semStack[$stackPos-(2-1)][] = $this->semStack[$stackPos-(2-2)]; $this->semValue = $this->semStack[$stackPos-(2-1)];
+            },
+            556 => function ($stackPos) {
+                 $this->semStack[$stackPos-(2-1)][] = $this->semStack[$stackPos-(2-2)]; $this->semValue = $this->semStack[$stackPos-(2-1)];
+            },
+            557 => function ($stackPos) {
+                 $this->semValue = array($this->semStack[$stackPos-(1-1)]);
+            },
+            558 => function ($stackPos) {
+                 $this->semValue = array($this->semStack[$stackPos-(2-1)], $this->semStack[$stackPos-(2-2)]);
+            },
+            559 => function ($stackPos) {
+                 $this->semValue = new Scalar\EncapsedStringPart($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes);
+            },
+            560 => function ($stackPos) {
+                 $this->semValue = new Expr\Variable($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes);
+            },
+            561 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(1-1)];
+            },
+            562 => function ($stackPos) {
+                 $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes);
+            },
+            563 => function ($stackPos) {
+                 $this->semValue = new Expr\PropertyFetch($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            564 => function ($stackPos) {
+                 $this->semValue = new Expr\NullsafePropertyFetch($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            565 => function ($stackPos) {
+                 $this->semValue = new Expr\Variable($this->semStack[$stackPos-(3-2)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            566 => function ($stackPos) {
+                 $this->semValue = new Expr\Variable($this->semStack[$stackPos-(3-2)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes);
+            },
+            567 => function ($stackPos) {
+                 $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos-(6-2)], $this->semStack[$stackPos-(6-4)], $this->startAttributeStack[$stackPos-(6-1)] + $this->endAttributes);
+            },
+            568 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(3-2)];
+            },
+            569 => function ($stackPos) {
+                 $this->semValue = new Scalar\String_($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes);
+            },
+            570 => function ($stackPos) {
+                 $this->semValue = $this->parseNumString($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes);
+            },
+            571 => function ($stackPos) {
+                 $this->semValue = $this->parseNumString('-' . $this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes);
+            },
+            572 => function ($stackPos) {
+                 $this->semValue = $this->semStack[$stackPos-(1-1)];
+            },
+        ];
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Parser/Tokens.php b/vendor/nikic/php-parser/lib/PhpParser/Parser/Tokens.php
new file mode 100644
index 0000000000000000000000000000000000000000..ed2062b46d0207d99cda31bb23184c56bbad2d0a
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/Parser/Tokens.php
@@ -0,0 +1,144 @@
+<?php
+
+namespace PhpParser\Parser;
+
+/* GENERATED file based on grammar/tokens.y */
+final class Tokens
+{
+    const YYERRTOK = 256;
+    const T_THROW = 257;
+    const T_INCLUDE = 258;
+    const T_INCLUDE_ONCE = 259;
+    const T_EVAL = 260;
+    const T_REQUIRE = 261;
+    const T_REQUIRE_ONCE = 262;
+    const T_LOGICAL_OR = 263;
+    const T_LOGICAL_XOR = 264;
+    const T_LOGICAL_AND = 265;
+    const T_PRINT = 266;
+    const T_YIELD = 267;
+    const T_DOUBLE_ARROW = 268;
+    const T_YIELD_FROM = 269;
+    const T_PLUS_EQUAL = 270;
+    const T_MINUS_EQUAL = 271;
+    const T_MUL_EQUAL = 272;
+    const T_DIV_EQUAL = 273;
+    const T_CONCAT_EQUAL = 274;
+    const T_MOD_EQUAL = 275;
+    const T_AND_EQUAL = 276;
+    const T_OR_EQUAL = 277;
+    const T_XOR_EQUAL = 278;
+    const T_SL_EQUAL = 279;
+    const T_SR_EQUAL = 280;
+    const T_POW_EQUAL = 281;
+    const T_COALESCE_EQUAL = 282;
+    const T_COALESCE = 283;
+    const T_BOOLEAN_OR = 284;
+    const T_BOOLEAN_AND = 285;
+    const T_IS_EQUAL = 286;
+    const T_IS_NOT_EQUAL = 287;
+    const T_IS_IDENTICAL = 288;
+    const T_IS_NOT_IDENTICAL = 289;
+    const T_SPACESHIP = 290;
+    const T_IS_SMALLER_OR_EQUAL = 291;
+    const T_IS_GREATER_OR_EQUAL = 292;
+    const T_SL = 293;
+    const T_SR = 294;
+    const T_INSTANCEOF = 295;
+    const T_INC = 296;
+    const T_DEC = 297;
+    const T_INT_CAST = 298;
+    const T_DOUBLE_CAST = 299;
+    const T_STRING_CAST = 300;
+    const T_ARRAY_CAST = 301;
+    const T_OBJECT_CAST = 302;
+    const T_BOOL_CAST = 303;
+    const T_UNSET_CAST = 304;
+    const T_POW = 305;
+    const T_NEW = 306;
+    const T_CLONE = 307;
+    const T_EXIT = 308;
+    const T_IF = 309;
+    const T_ELSEIF = 310;
+    const T_ELSE = 311;
+    const T_ENDIF = 312;
+    const T_LNUMBER = 313;
+    const T_DNUMBER = 314;
+    const T_STRING = 315;
+    const T_STRING_VARNAME = 316;
+    const T_VARIABLE = 317;
+    const T_NUM_STRING = 318;
+    const T_INLINE_HTML = 319;
+    const T_ENCAPSED_AND_WHITESPACE = 320;
+    const T_CONSTANT_ENCAPSED_STRING = 321;
+    const T_ECHO = 322;
+    const T_DO = 323;
+    const T_WHILE = 324;
+    const T_ENDWHILE = 325;
+    const T_FOR = 326;
+    const T_ENDFOR = 327;
+    const T_FOREACH = 328;
+    const T_ENDFOREACH = 329;
+    const T_DECLARE = 330;
+    const T_ENDDECLARE = 331;
+    const T_AS = 332;
+    const T_SWITCH = 333;
+    const T_MATCH = 334;
+    const T_ENDSWITCH = 335;
+    const T_CASE = 336;
+    const T_DEFAULT = 337;
+    const T_BREAK = 338;
+    const T_CONTINUE = 339;
+    const T_GOTO = 340;
+    const T_FUNCTION = 341;
+    const T_FN = 342;
+    const T_CONST = 343;
+    const T_RETURN = 344;
+    const T_TRY = 345;
+    const T_CATCH = 346;
+    const T_FINALLY = 347;
+    const T_USE = 348;
+    const T_INSTEADOF = 349;
+    const T_GLOBAL = 350;
+    const T_STATIC = 351;
+    const T_ABSTRACT = 352;
+    const T_FINAL = 353;
+    const T_PRIVATE = 354;
+    const T_PROTECTED = 355;
+    const T_PUBLIC = 356;
+    const T_VAR = 357;
+    const T_UNSET = 358;
+    const T_ISSET = 359;
+    const T_EMPTY = 360;
+    const T_HALT_COMPILER = 361;
+    const T_CLASS = 362;
+    const T_TRAIT = 363;
+    const T_INTERFACE = 364;
+    const T_EXTENDS = 365;
+    const T_IMPLEMENTS = 366;
+    const T_OBJECT_OPERATOR = 367;
+    const T_NULLSAFE_OBJECT_OPERATOR = 368;
+    const T_LIST = 369;
+    const T_ARRAY = 370;
+    const T_CALLABLE = 371;
+    const T_CLASS_C = 372;
+    const T_TRAIT_C = 373;
+    const T_METHOD_C = 374;
+    const T_FUNC_C = 375;
+    const T_LINE = 376;
+    const T_FILE = 377;
+    const T_START_HEREDOC = 378;
+    const T_END_HEREDOC = 379;
+    const T_DOLLAR_OPEN_CURLY_BRACES = 380;
+    const T_CURLY_OPEN = 381;
+    const T_PAAMAYIM_NEKUDOTAYIM = 382;
+    const T_NAMESPACE = 383;
+    const T_NS_C = 384;
+    const T_DIR = 385;
+    const T_NS_SEPARATOR = 386;
+    const T_ELLIPSIS = 387;
+    const T_NAME_FULLY_QUALIFIED = 388;
+    const T_NAME_QUALIFIED = 389;
+    const T_NAME_RELATIVE = 390;
+    const T_ATTRIBUTE = 391;
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/ParserAbstract.php b/vendor/nikic/php-parser/lib/PhpParser/ParserAbstract.php
new file mode 100644
index 0000000000000000000000000000000000000000..3ff474264e3be107e902be4fbdb8de16afe0038d
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/ParserAbstract.php
@@ -0,0 +1,1021 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser;
+
+/*
+ * This parser is based on a skeleton written by Moriyoshi Koizumi, which in
+ * turn is based on work by Masato Bito.
+ */
+use PhpParser\Node\Expr;
+use PhpParser\Node\Expr\Cast\Double;
+use PhpParser\Node\Name;
+use PhpParser\Node\Param;
+use PhpParser\Node\Scalar\Encapsed;
+use PhpParser\Node\Scalar\LNumber;
+use PhpParser\Node\Scalar\String_;
+use PhpParser\Node\Stmt\Class_;
+use PhpParser\Node\Stmt\ClassConst;
+use PhpParser\Node\Stmt\ClassMethod;
+use PhpParser\Node\Stmt\Interface_;
+use PhpParser\Node\Stmt\Namespace_;
+use PhpParser\Node\Stmt\Property;
+use PhpParser\Node\Stmt\TryCatch;
+use PhpParser\Node\Stmt\UseUse;
+use PhpParser\Node\VarLikeIdentifier;
+
+abstract class ParserAbstract implements Parser
+{
+    const SYMBOL_NONE = -1;
+
+    /*
+     * The following members will be filled with generated parsing data:
+     */
+
+    /** @var int Size of $tokenToSymbol map */
+    protected $tokenToSymbolMapSize;
+    /** @var int Size of $action table */
+    protected $actionTableSize;
+    /** @var int Size of $goto table */
+    protected $gotoTableSize;
+
+    /** @var int Symbol number signifying an invalid token */
+    protected $invalidSymbol;
+    /** @var int Symbol number of error recovery token */
+    protected $errorSymbol;
+    /** @var int Action number signifying default action */
+    protected $defaultAction;
+    /** @var int Rule number signifying that an unexpected token was encountered */
+    protected $unexpectedTokenRule;
+
+    protected $YY2TBLSTATE;
+    /** @var int Number of non-leaf states */
+    protected $numNonLeafStates;
+
+    /** @var int[] Map of lexer tokens to internal symbols */
+    protected $tokenToSymbol;
+    /** @var string[] Map of symbols to their names */
+    protected $symbolToName;
+    /** @var array Names of the production rules (only necessary for debugging) */
+    protected $productions;
+
+    /** @var int[] Map of states to a displacement into the $action table. The corresponding action for this
+     *             state/symbol pair is $action[$actionBase[$state] + $symbol]. If $actionBase[$state] is 0, the
+                   action is defaulted, i.e. $actionDefault[$state] should be used instead. */
+    protected $actionBase;
+    /** @var int[] Table of actions. Indexed according to $actionBase comment. */
+    protected $action;
+    /** @var int[] Table indexed analogously to $action. If $actionCheck[$actionBase[$state] + $symbol] != $symbol
+     *             then the action is defaulted, i.e. $actionDefault[$state] should be used instead. */
+    protected $actionCheck;
+    /** @var int[] Map of states to their default action */
+    protected $actionDefault;
+    /** @var callable[] Semantic action callbacks */
+    protected $reduceCallbacks;
+
+    /** @var int[] Map of non-terminals to a displacement into the $goto table. The corresponding goto state for this
+     *             non-terminal/state pair is $goto[$gotoBase[$nonTerminal] + $state] (unless defaulted) */
+    protected $gotoBase;
+    /** @var int[] Table of states to goto after reduction. Indexed according to $gotoBase comment. */
+    protected $goto;
+    /** @var int[] Table indexed analogously to $goto. If $gotoCheck[$gotoBase[$nonTerminal] + $state] != $nonTerminal
+     *             then the goto state is defaulted, i.e. $gotoDefault[$nonTerminal] should be used. */
+    protected $gotoCheck;
+    /** @var int[] Map of non-terminals to the default state to goto after their reduction */
+    protected $gotoDefault;
+
+    /** @var int[] Map of rules to the non-terminal on their left-hand side, i.e. the non-terminal to use for
+     *             determining the state to goto after reduction. */
+    protected $ruleToNonTerminal;
+    /** @var int[] Map of rules to the length of their right-hand side, which is the number of elements that have to
+     *             be popped from the stack(s) on reduction. */
+    protected $ruleToLength;
+
+    /*
+     * The following members are part of the parser state:
+     */
+
+    /** @var Lexer Lexer that is used when parsing */
+    protected $lexer;
+    /** @var mixed Temporary value containing the result of last semantic action (reduction) */
+    protected $semValue;
+    /** @var array Semantic value stack (contains values of tokens and semantic action results) */
+    protected $semStack;
+    /** @var array[] Start attribute stack */
+    protected $startAttributeStack;
+    /** @var array[] End attribute stack */
+    protected $endAttributeStack;
+    /** @var array End attributes of last *shifted* token */
+    protected $endAttributes;
+    /** @var array Start attributes of last *read* token */
+    protected $lookaheadStartAttributes;
+
+    /** @var ErrorHandler Error handler */
+    protected $errorHandler;
+    /** @var int Error state, used to avoid error floods */
+    protected $errorState;
+
+    /**
+     * Initialize $reduceCallbacks map.
+     */
+    abstract protected function initReduceCallbacks();
+
+    /**
+     * Creates a parser instance.
+     *
+     * Options: Currently none.
+     *
+     * @param Lexer $lexer A lexer
+     * @param array $options Options array.
+     */
+    public function __construct(Lexer $lexer, array $options = []) {
+        $this->lexer = $lexer;
+
+        if (isset($options['throwOnError'])) {
+            throw new \LogicException(
+                '"throwOnError" is no longer supported, use "errorHandler" instead');
+        }
+
+        $this->initReduceCallbacks();
+    }
+
+    /**
+     * Parses PHP code into a node tree.
+     *
+     * If a non-throwing error handler is used, the parser will continue parsing after an error
+     * occurred and attempt to build a partial AST.
+     *
+     * @param string $code The source code to parse
+     * @param ErrorHandler|null $errorHandler Error handler to use for lexer/parser errors, defaults
+     *                                        to ErrorHandler\Throwing.
+     *
+     * @return Node\Stmt[]|null Array of statements (or null non-throwing error handler is used and
+     *                          the parser was unable to recover from an error).
+     */
+    public function parse(string $code, ErrorHandler $errorHandler = null) {
+        $this->errorHandler = $errorHandler ?: new ErrorHandler\Throwing;
+
+        $this->lexer->startLexing($code, $this->errorHandler);
+        $result = $this->doParse();
+
+        // Clear out some of the interior state, so we don't hold onto unnecessary
+        // memory between uses of the parser
+        $this->startAttributeStack = [];
+        $this->endAttributeStack = [];
+        $this->semStack = [];
+        $this->semValue = null;
+
+        return $result;
+    }
+
+    protected function doParse() {
+        // We start off with no lookahead-token
+        $symbol = self::SYMBOL_NONE;
+
+        // The attributes for a node are taken from the first and last token of the node.
+        // From the first token only the startAttributes are taken and from the last only
+        // the endAttributes. Both are merged using the array union operator (+).
+        $startAttributes = [];
+        $endAttributes = [];
+        $this->endAttributes = $endAttributes;
+
+        // Keep stack of start and end attributes
+        $this->startAttributeStack = [];
+        $this->endAttributeStack = [$endAttributes];
+
+        // Start off in the initial state and keep a stack of previous states
+        $state = 0;
+        $stateStack = [$state];
+
+        // Semantic value stack (contains values of tokens and semantic action results)
+        $this->semStack = [];
+
+        // Current position in the stack(s)
+        $stackPos = 0;
+
+        $this->errorState = 0;
+
+        for (;;) {
+            //$this->traceNewState($state, $symbol);
+
+            if ($this->actionBase[$state] === 0) {
+                $rule = $this->actionDefault[$state];
+            } else {
+                if ($symbol === self::SYMBOL_NONE) {
+                    // Fetch the next token id from the lexer and fetch additional info by-ref.
+                    // The end attributes are fetched into a temporary variable and only set once the token is really
+                    // shifted (not during read). Otherwise you would sometimes get off-by-one errors, when a rule is
+                    // reduced after a token was read but not yet shifted.
+                    $tokenId = $this->lexer->getNextToken($tokenValue, $startAttributes, $endAttributes);
+
+                    // map the lexer token id to the internally used symbols
+                    $symbol = $tokenId >= 0 && $tokenId < $this->tokenToSymbolMapSize
+                        ? $this->tokenToSymbol[$tokenId]
+                        : $this->invalidSymbol;
+
+                    if ($symbol === $this->invalidSymbol) {
+                        throw new \RangeException(sprintf(
+                            'The lexer returned an invalid token (id=%d, value=%s)',
+                            $tokenId, $tokenValue
+                        ));
+                    }
+
+                    // Allow productions to access the start attributes of the lookahead token.
+                    $this->lookaheadStartAttributes = $startAttributes;
+
+                    //$this->traceRead($symbol);
+                }
+
+                $idx = $this->actionBase[$state] + $symbol;
+                if ((($idx >= 0 && $idx < $this->actionTableSize && $this->actionCheck[$idx] === $symbol)
+                     || ($state < $this->YY2TBLSTATE
+                         && ($idx = $this->actionBase[$state + $this->numNonLeafStates] + $symbol) >= 0
+                         && $idx < $this->actionTableSize && $this->actionCheck[$idx] === $symbol))
+                    && ($action = $this->action[$idx]) !== $this->defaultAction) {
+                    /*
+                     * >= numNonLeafStates: shift and reduce
+                     * > 0: shift
+                     * = 0: accept
+                     * < 0: reduce
+                     * = -YYUNEXPECTED: error
+                     */
+                    if ($action > 0) {
+                        /* shift */
+                        //$this->traceShift($symbol);
+
+                        ++$stackPos;
+                        $stateStack[$stackPos] = $state = $action;
+                        $this->semStack[$stackPos] = $tokenValue;
+                        $this->startAttributeStack[$stackPos] = $startAttributes;
+                        $this->endAttributeStack[$stackPos] = $endAttributes;
+                        $this->endAttributes = $endAttributes;
+                        $symbol = self::SYMBOL_NONE;
+
+                        if ($this->errorState) {
+                            --$this->errorState;
+                        }
+
+                        if ($action < $this->numNonLeafStates) {
+                            continue;
+                        }
+
+                        /* $yyn >= numNonLeafStates means shift-and-reduce */
+                        $rule = $action - $this->numNonLeafStates;
+                    } else {
+                        $rule = -$action;
+                    }
+                } else {
+                    $rule = $this->actionDefault[$state];
+                }
+            }
+
+            for (;;) {
+                if ($rule === 0) {
+                    /* accept */
+                    //$this->traceAccept();
+                    return $this->semValue;
+                } elseif ($rule !== $this->unexpectedTokenRule) {
+                    /* reduce */
+                    //$this->traceReduce($rule);
+
+                    try {
+                        $this->reduceCallbacks[$rule]($stackPos);
+                    } catch (Error $e) {
+                        if (-1 === $e->getStartLine() && isset($startAttributes['startLine'])) {
+                            $e->setStartLine($startAttributes['startLine']);
+                        }
+
+                        $this->emitError($e);
+                        // Can't recover from this type of error
+                        return null;
+                    }
+
+                    /* Goto - shift nonterminal */
+                    $lastEndAttributes = $this->endAttributeStack[$stackPos];
+                    $ruleLength = $this->ruleToLength[$rule];
+                    $stackPos -= $ruleLength;
+                    $nonTerminal = $this->ruleToNonTerminal[$rule];
+                    $idx = $this->gotoBase[$nonTerminal] + $stateStack[$stackPos];
+                    if ($idx >= 0 && $idx < $this->gotoTableSize && $this->gotoCheck[$idx] === $nonTerminal) {
+                        $state = $this->goto[$idx];
+                    } else {
+                        $state = $this->gotoDefault[$nonTerminal];
+                    }
+
+                    ++$stackPos;
+                    $stateStack[$stackPos]     = $state;
+                    $this->semStack[$stackPos] = $this->semValue;
+                    $this->endAttributeStack[$stackPos] = $lastEndAttributes;
+                    if ($ruleLength === 0) {
+                        // Empty productions use the start attributes of the lookahead token.
+                        $this->startAttributeStack[$stackPos] = $this->lookaheadStartAttributes;
+                    }
+                } else {
+                    /* error */
+                    switch ($this->errorState) {
+                        case 0:
+                            $msg = $this->getErrorMessage($symbol, $state);
+                            $this->emitError(new Error($msg, $startAttributes + $endAttributes));
+                            // Break missing intentionally
+                        case 1:
+                        case 2:
+                            $this->errorState = 3;
+
+                            // Pop until error-expecting state uncovered
+                            while (!(
+                                (($idx = $this->actionBase[$state] + $this->errorSymbol) >= 0
+                                    && $idx < $this->actionTableSize && $this->actionCheck[$idx] === $this->errorSymbol)
+                                || ($state < $this->YY2TBLSTATE
+                                    && ($idx = $this->actionBase[$state + $this->numNonLeafStates] + $this->errorSymbol) >= 0
+                                    && $idx < $this->actionTableSize && $this->actionCheck[$idx] === $this->errorSymbol)
+                            ) || ($action = $this->action[$idx]) === $this->defaultAction) { // Not totally sure about this
+                                if ($stackPos <= 0) {
+                                    // Could not recover from error
+                                    return null;
+                                }
+                                $state = $stateStack[--$stackPos];
+                                //$this->tracePop($state);
+                            }
+
+                            //$this->traceShift($this->errorSymbol);
+                            ++$stackPos;
+                            $stateStack[$stackPos] = $state = $action;
+
+                            // We treat the error symbol as being empty, so we reset the end attributes
+                            // to the end attributes of the last non-error symbol
+                            $this->startAttributeStack[$stackPos] = $this->lookaheadStartAttributes;
+                            $this->endAttributeStack[$stackPos] = $this->endAttributeStack[$stackPos - 1];
+                            $this->endAttributes = $this->endAttributeStack[$stackPos - 1];
+                            break;
+
+                        case 3:
+                            if ($symbol === 0) {
+                                // Reached EOF without recovering from error
+                                return null;
+                            }
+
+                            //$this->traceDiscard($symbol);
+                            $symbol = self::SYMBOL_NONE;
+                            break 2;
+                    }
+                }
+
+                if ($state < $this->numNonLeafStates) {
+                    break;
+                }
+
+                /* >= numNonLeafStates means shift-and-reduce */
+                $rule = $state - $this->numNonLeafStates;
+            }
+        }
+
+        throw new \RuntimeException('Reached end of parser loop');
+    }
+
+    protected function emitError(Error $error) {
+        $this->errorHandler->handleError($error);
+    }
+
+    /**
+     * Format error message including expected tokens.
+     *
+     * @param int $symbol Unexpected symbol
+     * @param int $state  State at time of error
+     *
+     * @return string Formatted error message
+     */
+    protected function getErrorMessage(int $symbol, int $state) : string {
+        $expectedString = '';
+        if ($expected = $this->getExpectedTokens($state)) {
+            $expectedString = ', expecting ' . implode(' or ', $expected);
+        }
+
+        return 'Syntax error, unexpected ' . $this->symbolToName[$symbol] . $expectedString;
+    }
+
+    /**
+     * Get limited number of expected tokens in given state.
+     *
+     * @param int $state State
+     *
+     * @return string[] Expected tokens. If too many, an empty array is returned.
+     */
+    protected function getExpectedTokens(int $state) : array {
+        $expected = [];
+
+        $base = $this->actionBase[$state];
+        foreach ($this->symbolToName as $symbol => $name) {
+            $idx = $base + $symbol;
+            if ($idx >= 0 && $idx < $this->actionTableSize && $this->actionCheck[$idx] === $symbol
+                || $state < $this->YY2TBLSTATE
+                && ($idx = $this->actionBase[$state + $this->numNonLeafStates] + $symbol) >= 0
+                && $idx < $this->actionTableSize && $this->actionCheck[$idx] === $symbol
+            ) {
+                if ($this->action[$idx] !== $this->unexpectedTokenRule
+                    && $this->action[$idx] !== $this->defaultAction
+                    && $symbol !== $this->errorSymbol
+                ) {
+                    if (count($expected) === 4) {
+                        /* Too many expected tokens */
+                        return [];
+                    }
+
+                    $expected[] = $name;
+                }
+            }
+        }
+
+        return $expected;
+    }
+
+    /*
+     * Tracing functions used for debugging the parser.
+     */
+
+    /*
+    protected function traceNewState($state, $symbol) {
+        echo '% State ' . $state
+            . ', Lookahead ' . ($symbol == self::SYMBOL_NONE ? '--none--' : $this->symbolToName[$symbol]) . "\n";
+    }
+
+    protected function traceRead($symbol) {
+        echo '% Reading ' . $this->symbolToName[$symbol] . "\n";
+    }
+
+    protected function traceShift($symbol) {
+        echo '% Shift ' . $this->symbolToName[$symbol] . "\n";
+    }
+
+    protected function traceAccept() {
+        echo "% Accepted.\n";
+    }
+
+    protected function traceReduce($n) {
+        echo '% Reduce by (' . $n . ') ' . $this->productions[$n] . "\n";
+    }
+
+    protected function tracePop($state) {
+        echo '% Recovering, uncovered state ' . $state . "\n";
+    }
+
+    protected function traceDiscard($symbol) {
+        echo '% Discard ' . $this->symbolToName[$symbol] . "\n";
+    }
+    */
+
+    /*
+     * Helper functions invoked by semantic actions
+     */
+
+    /**
+     * Moves statements of semicolon-style namespaces into $ns->stmts and checks various error conditions.
+     *
+     * @param Node\Stmt[] $stmts
+     * @return Node\Stmt[]
+     */
+    protected function handleNamespaces(array $stmts) : array {
+        $hasErrored = false;
+        $style = $this->getNamespacingStyle($stmts);
+        if (null === $style) {
+            // not namespaced, nothing to do
+            return $stmts;
+        } elseif ('brace' === $style) {
+            // For braced namespaces we only have to check that there are no invalid statements between the namespaces
+            $afterFirstNamespace = false;
+            foreach ($stmts as $stmt) {
+                if ($stmt instanceof Node\Stmt\Namespace_) {
+                    $afterFirstNamespace = true;
+                } elseif (!$stmt instanceof Node\Stmt\HaltCompiler
+                        && !$stmt instanceof Node\Stmt\Nop
+                        && $afterFirstNamespace && !$hasErrored) {
+                    $this->emitError(new Error(
+                        'No code may exist outside of namespace {}', $stmt->getAttributes()));
+                    $hasErrored = true; // Avoid one error for every statement
+                }
+            }
+            return $stmts;
+        } else {
+            // For semicolon namespaces we have to move the statements after a namespace declaration into ->stmts
+            $resultStmts = [];
+            $targetStmts =& $resultStmts;
+            $lastNs = null;
+            foreach ($stmts as $stmt) {
+                if ($stmt instanceof Node\Stmt\Namespace_) {
+                    if ($lastNs !== null) {
+                        $this->fixupNamespaceAttributes($lastNs);
+                    }
+                    if ($stmt->stmts === null) {
+                        $stmt->stmts = [];
+                        $targetStmts =& $stmt->stmts;
+                        $resultStmts[] = $stmt;
+                    } else {
+                        // This handles the invalid case of mixed style namespaces
+                        $resultStmts[] = $stmt;
+                        $targetStmts =& $resultStmts;
+                    }
+                    $lastNs = $stmt;
+                } elseif ($stmt instanceof Node\Stmt\HaltCompiler) {
+                    // __halt_compiler() is not moved into the namespace
+                    $resultStmts[] = $stmt;
+                } else {
+                    $targetStmts[] = $stmt;
+                }
+            }
+            if ($lastNs !== null) {
+                $this->fixupNamespaceAttributes($lastNs);
+            }
+            return $resultStmts;
+        }
+    }
+
+    private function fixupNamespaceAttributes(Node\Stmt\Namespace_ $stmt) {
+        // We moved the statements into the namespace node, as such the end of the namespace node
+        // needs to be extended to the end of the statements.
+        if (empty($stmt->stmts)) {
+            return;
+        }
+
+        // We only move the builtin end attributes here. This is the best we can do with the
+        // knowledge we have.
+        $endAttributes = ['endLine', 'endFilePos', 'endTokenPos'];
+        $lastStmt = $stmt->stmts[count($stmt->stmts) - 1];
+        foreach ($endAttributes as $endAttribute) {
+            if ($lastStmt->hasAttribute($endAttribute)) {
+                $stmt->setAttribute($endAttribute, $lastStmt->getAttribute($endAttribute));
+            }
+        }
+    }
+
+    /**
+     * Determine namespacing style (semicolon or brace)
+     *
+     * @param Node[] $stmts Top-level statements.
+     *
+     * @return null|string One of "semicolon", "brace" or null (no namespaces)
+     */
+    private function getNamespacingStyle(array $stmts) {
+        $style = null;
+        $hasNotAllowedStmts = false;
+        foreach ($stmts as $i => $stmt) {
+            if ($stmt instanceof Node\Stmt\Namespace_) {
+                $currentStyle = null === $stmt->stmts ? 'semicolon' : 'brace';
+                if (null === $style) {
+                    $style = $currentStyle;
+                    if ($hasNotAllowedStmts) {
+                        $this->emitError(new Error(
+                            'Namespace declaration statement has to be the very first statement in the script',
+                            $stmt->getLine() // Avoid marking the entire namespace as an error
+                        ));
+                    }
+                } elseif ($style !== $currentStyle) {
+                    $this->emitError(new Error(
+                        'Cannot mix bracketed namespace declarations with unbracketed namespace declarations',
+                        $stmt->getLine() // Avoid marking the entire namespace as an error
+                    ));
+                    // Treat like semicolon style for namespace normalization
+                    return 'semicolon';
+                }
+                continue;
+            }
+
+            /* declare(), __halt_compiler() and nops can be used before a namespace declaration */
+            if ($stmt instanceof Node\Stmt\Declare_
+                || $stmt instanceof Node\Stmt\HaltCompiler
+                || $stmt instanceof Node\Stmt\Nop) {
+                continue;
+            }
+
+            /* There may be a hashbang line at the very start of the file */
+            if ($i === 0 && $stmt instanceof Node\Stmt\InlineHTML && preg_match('/\A#!.*\r?\n\z/', $stmt->value)) {
+                continue;
+            }
+
+            /* Everything else if forbidden before namespace declarations */
+            $hasNotAllowedStmts = true;
+        }
+        return $style;
+    }
+
+    /**
+     * Fix up parsing of static property calls in PHP 5.
+     *
+     * In PHP 5 A::$b[c][d] and A::$b[c][d]() have very different interpretation. The former is
+     * interpreted as (A::$b)[c][d], while the latter is the same as A::{$b[c][d]}(). We parse the
+     * latter as the former initially and this method fixes the AST into the correct form when we
+     * encounter the "()".
+     *
+     * @param  Node\Expr\StaticPropertyFetch|Node\Expr\ArrayDimFetch $prop
+     * @param  Node\Arg[] $args
+     * @param  array      $attributes
+     *
+     * @return Expr\StaticCall
+     */
+    protected function fixupPhp5StaticPropCall($prop, array $args, array $attributes) : Expr\StaticCall {
+        if ($prop instanceof Node\Expr\StaticPropertyFetch) {
+            $name = $prop->name instanceof VarLikeIdentifier
+                ? $prop->name->toString() : $prop->name;
+            $var = new Expr\Variable($name, $prop->name->getAttributes());
+            return new Expr\StaticCall($prop->class, $var, $args, $attributes);
+        } elseif ($prop instanceof Node\Expr\ArrayDimFetch) {
+            $tmp = $prop;
+            while ($tmp->var instanceof Node\Expr\ArrayDimFetch) {
+                $tmp = $tmp->var;
+            }
+
+            /** @var Expr\StaticPropertyFetch $staticProp */
+            $staticProp = $tmp->var;
+
+            // Set start attributes to attributes of innermost node
+            $tmp = $prop;
+            $this->fixupStartAttributes($tmp, $staticProp->name);
+            while ($tmp->var instanceof Node\Expr\ArrayDimFetch) {
+                $tmp = $tmp->var;
+                $this->fixupStartAttributes($tmp, $staticProp->name);
+            }
+
+            $name = $staticProp->name instanceof VarLikeIdentifier
+                ? $staticProp->name->toString() : $staticProp->name;
+            $tmp->var = new Expr\Variable($name, $staticProp->name->getAttributes());
+            return new Expr\StaticCall($staticProp->class, $prop, $args, $attributes);
+        } else {
+            throw new \Exception;
+        }
+    }
+
+    protected function fixupStartAttributes(Node $to, Node $from) {
+        $startAttributes = ['startLine', 'startFilePos', 'startTokenPos'];
+        foreach ($startAttributes as $startAttribute) {
+            if ($from->hasAttribute($startAttribute)) {
+                $to->setAttribute($startAttribute, $from->getAttribute($startAttribute));
+            }
+        }
+    }
+
+    protected function handleBuiltinTypes(Name $name) {
+        $builtinTypes = [
+            'bool'     => true,
+            'int'      => true,
+            'float'    => true,
+            'string'   => true,
+            'iterable' => true,
+            'void'     => true,
+            'object'   => true,
+            'null'     => true,
+            'false'    => true,
+            'mixed'    => true,
+        ];
+
+        if (!$name->isUnqualified()) {
+            return $name;
+        }
+
+        $lowerName = $name->toLowerString();
+        if (!isset($builtinTypes[$lowerName])) {
+            return $name;
+        }
+
+        return new Node\Identifier($lowerName, $name->getAttributes());
+    }
+
+    /**
+     * Get combined start and end attributes at a stack location
+     *
+     * @param int $pos Stack location
+     *
+     * @return array Combined start and end attributes
+     */
+    protected function getAttributesAt(int $pos) : array {
+        return $this->startAttributeStack[$pos] + $this->endAttributeStack[$pos];
+    }
+
+    protected function getFloatCastKind(string $cast): int
+    {
+        $cast = strtolower($cast);
+        if (strpos($cast, 'float') !== false) {
+            return Double::KIND_FLOAT;
+        }
+
+        if (strpos($cast, 'real') !== false) {
+            return Double::KIND_REAL;
+        }
+
+        return Double::KIND_DOUBLE;
+    }
+
+    protected function parseLNumber($str, $attributes, $allowInvalidOctal = false) {
+        try {
+            return LNumber::fromString($str, $attributes, $allowInvalidOctal);
+        } catch (Error $error) {
+            $this->emitError($error);
+            // Use dummy value
+            return new LNumber(0, $attributes);
+        }
+    }
+
+    /**
+     * Parse a T_NUM_STRING token into either an integer or string node.
+     *
+     * @param string $str        Number string
+     * @param array  $attributes Attributes
+     *
+     * @return LNumber|String_ Integer or string node.
+     */
+    protected function parseNumString(string $str, array $attributes) {
+        if (!preg_match('/^(?:0|-?[1-9][0-9]*)$/', $str)) {
+            return new String_($str, $attributes);
+        }
+
+        $num = +$str;
+        if (!is_int($num)) {
+            return new String_($str, $attributes);
+        }
+
+        return new LNumber($num, $attributes);
+    }
+
+    protected function stripIndentation(
+        string $string, int $indentLen, string $indentChar,
+        bool $newlineAtStart, bool $newlineAtEnd, array $attributes
+    ) {
+        if ($indentLen === 0) {
+            return $string;
+        }
+
+        $start = $newlineAtStart ? '(?:(?<=\n)|\A)' : '(?<=\n)';
+        $end = $newlineAtEnd ? '(?:(?=[\r\n])|\z)' : '(?=[\r\n])';
+        $regex = '/' . $start . '([ \t]*)(' . $end . ')?/';
+        return preg_replace_callback(
+            $regex,
+            function ($matches) use ($indentLen, $indentChar, $attributes) {
+                $prefix = substr($matches[1], 0, $indentLen);
+                if (false !== strpos($prefix, $indentChar === " " ? "\t" : " ")) {
+                    $this->emitError(new Error(
+                        'Invalid indentation - tabs and spaces cannot be mixed', $attributes
+                    ));
+                } elseif (strlen($prefix) < $indentLen && !isset($matches[2])) {
+                    $this->emitError(new Error(
+                        'Invalid body indentation level ' .
+                        '(expecting an indentation level of at least ' . $indentLen . ')',
+                        $attributes
+                    ));
+                }
+                return substr($matches[0], strlen($prefix));
+            },
+            $string
+        );
+    }
+
+    protected function parseDocString(
+        string $startToken, $contents, string $endToken,
+        array $attributes, array $endTokenAttributes, bool $parseUnicodeEscape
+    ) {
+        $kind = strpos($startToken, "'") === false
+            ? String_::KIND_HEREDOC : String_::KIND_NOWDOC;
+
+        $regex = '/\A[bB]?<<<[ \t]*[\'"]?([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)[\'"]?(?:\r\n|\n|\r)\z/';
+        $result = preg_match($regex, $startToken, $matches);
+        assert($result === 1);
+        $label = $matches[1];
+
+        $result = preg_match('/\A[ \t]*/', $endToken, $matches);
+        assert($result === 1);
+        $indentation = $matches[0];
+
+        $attributes['kind'] = $kind;
+        $attributes['docLabel'] = $label;
+        $attributes['docIndentation'] = $indentation;
+
+        $indentHasSpaces = false !== strpos($indentation, " ");
+        $indentHasTabs = false !== strpos($indentation, "\t");
+        if ($indentHasSpaces && $indentHasTabs) {
+            $this->emitError(new Error(
+                'Invalid indentation - tabs and spaces cannot be mixed',
+                $endTokenAttributes
+            ));
+
+            // Proceed processing as if this doc string is not indented
+            $indentation = '';
+        }
+
+        $indentLen = \strlen($indentation);
+        $indentChar = $indentHasSpaces ? " " : "\t";
+
+        if (\is_string($contents)) {
+            if ($contents === '') {
+                return new String_('', $attributes);
+            }
+
+            $contents = $this->stripIndentation(
+                $contents, $indentLen, $indentChar, true, true, $attributes
+            );
+            $contents = preg_replace('~(\r\n|\n|\r)\z~', '', $contents);
+
+            if ($kind === String_::KIND_HEREDOC) {
+                $contents = String_::parseEscapeSequences($contents, null, $parseUnicodeEscape);
+            }
+
+            return new String_($contents, $attributes);
+        } else {
+            assert(count($contents) > 0);
+            if (!$contents[0] instanceof Node\Scalar\EncapsedStringPart) {
+                // If there is no leading encapsed string part, pretend there is an empty one
+                $this->stripIndentation(
+                    '', $indentLen, $indentChar, true, false, $contents[0]->getAttributes()
+                );
+            }
+
+            $newContents = [];
+            foreach ($contents as $i => $part) {
+                if ($part instanceof Node\Scalar\EncapsedStringPart) {
+                    $isLast = $i === \count($contents) - 1;
+                    $part->value = $this->stripIndentation(
+                        $part->value, $indentLen, $indentChar,
+                        $i === 0, $isLast, $part->getAttributes()
+                    );
+                    $part->value = String_::parseEscapeSequences($part->value, null, $parseUnicodeEscape);
+                    if ($isLast) {
+                        $part->value = preg_replace('~(\r\n|\n|\r)\z~', '', $part->value);
+                    }
+                    if ('' === $part->value) {
+                        continue;
+                    }
+                }
+                $newContents[] = $part;
+            }
+            return new Encapsed($newContents, $attributes);
+        }
+    }
+
+    /**
+     * Create attributes for a zero-length common-capturing nop.
+     *
+     * @param Comment[] $comments
+     * @return array
+     */
+    protected function createCommentNopAttributes(array $comments) {
+        $comment = $comments[count($comments) - 1];
+        $commentEndLine = $comment->getEndLine();
+        $commentEndFilePos = $comment->getEndFilePos();
+        $commentEndTokenPos = $comment->getEndTokenPos();
+
+        $attributes = ['comments' => $comments];
+        if (-1 !== $commentEndLine) {
+            $attributes['startLine'] = $commentEndLine;
+            $attributes['endLine'] = $commentEndLine;
+        }
+        if (-1 !== $commentEndFilePos) {
+            $attributes['startFilePos'] = $commentEndFilePos + 1;
+            $attributes['endFilePos'] = $commentEndFilePos;
+        }
+        if (-1 !== $commentEndTokenPos) {
+            $attributes['startTokenPos'] = $commentEndTokenPos + 1;
+            $attributes['endTokenPos'] = $commentEndTokenPos;
+        }
+        return $attributes;
+    }
+
+    protected function checkModifier($a, $b, $modifierPos) {
+        // Jumping through some hoops here because verifyModifier() is also used elsewhere
+        try {
+            Class_::verifyModifier($a, $b);
+        } catch (Error $error) {
+            $error->setAttributes($this->getAttributesAt($modifierPos));
+            $this->emitError($error);
+        }
+    }
+
+    protected function checkParam(Param $node) {
+        if ($node->variadic && null !== $node->default) {
+            $this->emitError(new Error(
+                'Variadic parameter cannot have a default value',
+                $node->default->getAttributes()
+            ));
+        }
+    }
+
+    protected function checkTryCatch(TryCatch $node) {
+        if (empty($node->catches) && null === $node->finally) {
+            $this->emitError(new Error(
+                'Cannot use try without catch or finally', $node->getAttributes()
+            ));
+        }
+    }
+
+    protected function checkNamespace(Namespace_ $node) {
+        if (null !== $node->stmts) {
+            foreach ($node->stmts as $stmt) {
+                if ($stmt instanceof Namespace_) {
+                    $this->emitError(new Error(
+                        'Namespace declarations cannot be nested', $stmt->getAttributes()
+                    ));
+                }
+            }
+        }
+    }
+
+    protected function checkClass(Class_ $node, $namePos) {
+        if (null !== $node->name && $node->name->isSpecialClassName()) {
+            $this->emitError(new Error(
+                sprintf('Cannot use \'%s\' as class name as it is reserved', $node->name),
+                $this->getAttributesAt($namePos)
+            ));
+        }
+
+        if ($node->extends && $node->extends->isSpecialClassName()) {
+            $this->emitError(new Error(
+                sprintf('Cannot use \'%s\' as class name as it is reserved', $node->extends),
+                $node->extends->getAttributes()
+            ));
+        }
+
+        foreach ($node->implements as $interface) {
+            if ($interface->isSpecialClassName()) {
+                $this->emitError(new Error(
+                    sprintf('Cannot use \'%s\' as interface name as it is reserved', $interface),
+                    $interface->getAttributes()
+                ));
+            }
+        }
+    }
+
+    protected function checkInterface(Interface_ $node, $namePos) {
+        if (null !== $node->name && $node->name->isSpecialClassName()) {
+            $this->emitError(new Error(
+                sprintf('Cannot use \'%s\' as class name as it is reserved', $node->name),
+                $this->getAttributesAt($namePos)
+            ));
+        }
+
+        foreach ($node->extends as $interface) {
+            if ($interface->isSpecialClassName()) {
+                $this->emitError(new Error(
+                    sprintf('Cannot use \'%s\' as interface name as it is reserved', $interface),
+                    $interface->getAttributes()
+                ));
+            }
+        }
+    }
+
+    protected function checkClassMethod(ClassMethod $node, $modifierPos) {
+        if ($node->flags & Class_::MODIFIER_STATIC) {
+            switch ($node->name->toLowerString()) {
+                case '__construct':
+                    $this->emitError(new Error(
+                        sprintf('Constructor %s() cannot be static', $node->name),
+                        $this->getAttributesAt($modifierPos)));
+                    break;
+                case '__destruct':
+                    $this->emitError(new Error(
+                        sprintf('Destructor %s() cannot be static', $node->name),
+                        $this->getAttributesAt($modifierPos)));
+                    break;
+                case '__clone':
+                    $this->emitError(new Error(
+                        sprintf('Clone method %s() cannot be static', $node->name),
+                        $this->getAttributesAt($modifierPos)));
+                    break;
+            }
+        }
+    }
+
+    protected function checkClassConst(ClassConst $node, $modifierPos) {
+        if ($node->flags & Class_::MODIFIER_STATIC) {
+            $this->emitError(new Error(
+                "Cannot use 'static' as constant modifier",
+                $this->getAttributesAt($modifierPos)));
+        }
+        if ($node->flags & Class_::MODIFIER_ABSTRACT) {
+            $this->emitError(new Error(
+                "Cannot use 'abstract' as constant modifier",
+                $this->getAttributesAt($modifierPos)));
+        }
+        if ($node->flags & Class_::MODIFIER_FINAL) {
+            $this->emitError(new Error(
+                "Cannot use 'final' as constant modifier",
+                $this->getAttributesAt($modifierPos)));
+        }
+    }
+
+    protected function checkProperty(Property $node, $modifierPos) {
+        if ($node->flags & Class_::MODIFIER_ABSTRACT) {
+            $this->emitError(new Error('Properties cannot be declared abstract',
+                $this->getAttributesAt($modifierPos)));
+        }
+
+        if ($node->flags & Class_::MODIFIER_FINAL) {
+            $this->emitError(new Error('Properties cannot be declared final',
+                $this->getAttributesAt($modifierPos)));
+        }
+    }
+
+    protected function checkUseUse(UseUse $node, $namePos) {
+        if ($node->alias && $node->alias->isSpecialClassName()) {
+            $this->emitError(new Error(
+                sprintf(
+                    'Cannot use %s as %s because \'%2$s\' is a special class name',
+                    $node->name, $node->alias
+                ),
+                $this->getAttributesAt($namePos)
+            ));
+        }
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/ParserFactory.php b/vendor/nikic/php-parser/lib/PhpParser/ParserFactory.php
new file mode 100644
index 0000000000000000000000000000000000000000..f041e7ffe3adcc4181c6900b55061ed596f2786b
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/ParserFactory.php
@@ -0,0 +1,44 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser;
+
+class ParserFactory
+{
+    const PREFER_PHP7 = 1;
+    const PREFER_PHP5 = 2;
+    const ONLY_PHP7 = 3;
+    const ONLY_PHP5 = 4;
+
+    /**
+     * Creates a Parser instance, according to the provided kind.
+     *
+     * @param int        $kind  One of ::PREFER_PHP7, ::PREFER_PHP5, ::ONLY_PHP7 or ::ONLY_PHP5
+     * @param Lexer|null $lexer Lexer to use. Defaults to emulative lexer when not specified
+     * @param array      $parserOptions Parser options. See ParserAbstract::__construct() argument
+     *
+     * @return Parser The parser instance
+     */
+    public function create(int $kind, Lexer $lexer = null, array $parserOptions = []) : Parser {
+        if (null === $lexer) {
+            $lexer = new Lexer\Emulative();
+        }
+        switch ($kind) {
+            case self::PREFER_PHP7:
+                return new Parser\Multiple([
+                    new Parser\Php7($lexer, $parserOptions), new Parser\Php5($lexer, $parserOptions)
+                ]);
+            case self::PREFER_PHP5:
+                return new Parser\Multiple([
+                    new Parser\Php5($lexer, $parserOptions), new Parser\Php7($lexer, $parserOptions)
+                ]);
+            case self::ONLY_PHP7:
+                return new Parser\Php7($lexer, $parserOptions);
+            case self::ONLY_PHP5:
+                return new Parser\Php5($lexer, $parserOptions);
+            default:
+                throw new \LogicException(
+                    'Kind must be one of ::PREFER_PHP7, ::PREFER_PHP5, ::ONLY_PHP7 or ::ONLY_PHP5'
+                );
+        }
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/PrettyPrinter/Standard.php b/vendor/nikic/php-parser/lib/PhpParser/PrettyPrinter/Standard.php
new file mode 100644
index 0000000000000000000000000000000000000000..636129d553d983a21f27e8aeb9babffd089cb6d7
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/PrettyPrinter/Standard.php
@@ -0,0 +1,1069 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser\PrettyPrinter;
+
+use PhpParser\Node;
+use PhpParser\Node\Expr;
+use PhpParser\Node\Expr\AssignOp;
+use PhpParser\Node\Expr\BinaryOp;
+use PhpParser\Node\Expr\Cast;
+use PhpParser\Node\Name;
+use PhpParser\Node\Scalar;
+use PhpParser\Node\Scalar\MagicConst;
+use PhpParser\Node\Stmt;
+use PhpParser\PrettyPrinterAbstract;
+
+class Standard extends PrettyPrinterAbstract
+{
+    // Special nodes
+
+    protected function pParam(Node\Param $node) {
+        return $this->pAttrGroups($node->attrGroups, true)
+             . $this->pModifiers($node->flags)
+             . ($node->type ? $this->p($node->type) . ' ' : '')
+             . ($node->byRef ? '&' : '')
+             . ($node->variadic ? '...' : '')
+             . $this->p($node->var)
+             . ($node->default ? ' = ' . $this->p($node->default) : '');
+    }
+
+    protected function pArg(Node\Arg $node) {
+        return ($node->name ? $node->name->toString() . ': ' : '')
+             . ($node->byRef ? '&' : '') . ($node->unpack ? '...' : '')
+             . $this->p($node->value);
+    }
+
+    protected function pConst(Node\Const_ $node) {
+        return $node->name . ' = ' . $this->p($node->value);
+    }
+
+    protected function pNullableType(Node\NullableType $node) {
+        return '?' . $this->p($node->type);
+    }
+
+    protected function pUnionType(Node\UnionType $node) {
+        return $this->pImplode($node->types, '|');
+    }
+
+    protected function pIdentifier(Node\Identifier $node) {
+        return $node->name;
+    }
+
+    protected function pVarLikeIdentifier(Node\VarLikeIdentifier $node) {
+        return '$' . $node->name;
+    }
+
+    protected function pAttribute(Node\Attribute $node) {
+        return $this->p($node->name)
+             . ($node->args ? '(' . $this->pCommaSeparated($node->args) . ')' : '');
+    }
+
+    protected function pAttributeGroup(Node\AttributeGroup $node) {
+        return '#[' . $this->pCommaSeparated($node->attrs) . ']';
+    }
+
+    // Names
+
+    protected function pName(Name $node) {
+        return implode('\\', $node->parts);
+    }
+
+    protected function pName_FullyQualified(Name\FullyQualified $node) {
+        return '\\' . implode('\\', $node->parts);
+    }
+
+    protected function pName_Relative(Name\Relative $node) {
+        return 'namespace\\' . implode('\\', $node->parts);
+    }
+
+    // Magic Constants
+
+    protected function pScalar_MagicConst_Class(MagicConst\Class_ $node) {
+        return '__CLASS__';
+    }
+
+    protected function pScalar_MagicConst_Dir(MagicConst\Dir $node) {
+        return '__DIR__';
+    }
+
+    protected function pScalar_MagicConst_File(MagicConst\File $node) {
+        return '__FILE__';
+    }
+
+    protected function pScalar_MagicConst_Function(MagicConst\Function_ $node) {
+        return '__FUNCTION__';
+    }
+
+    protected function pScalar_MagicConst_Line(MagicConst\Line $node) {
+        return '__LINE__';
+    }
+
+    protected function pScalar_MagicConst_Method(MagicConst\Method $node) {
+        return '__METHOD__';
+    }
+
+    protected function pScalar_MagicConst_Namespace(MagicConst\Namespace_ $node) {
+        return '__NAMESPACE__';
+    }
+
+    protected function pScalar_MagicConst_Trait(MagicConst\Trait_ $node) {
+        return '__TRAIT__';
+    }
+
+    // Scalars
+
+    protected function pScalar_String(Scalar\String_ $node) {
+        $kind = $node->getAttribute('kind', Scalar\String_::KIND_SINGLE_QUOTED);
+        switch ($kind) {
+            case Scalar\String_::KIND_NOWDOC:
+                $label = $node->getAttribute('docLabel');
+                if ($label && !$this->containsEndLabel($node->value, $label)) {
+                    if ($node->value === '') {
+                        return "<<<'$label'\n$label" . $this->docStringEndToken;
+                    }
+
+                    return "<<<'$label'\n$node->value\n$label"
+                         . $this->docStringEndToken;
+                }
+                /* break missing intentionally */
+            case Scalar\String_::KIND_SINGLE_QUOTED:
+                return $this->pSingleQuotedString($node->value);
+            case Scalar\String_::KIND_HEREDOC:
+                $label = $node->getAttribute('docLabel');
+                if ($label && !$this->containsEndLabel($node->value, $label)) {
+                    if ($node->value === '') {
+                        return "<<<$label\n$label" . $this->docStringEndToken;
+                    }
+
+                    $escaped = $this->escapeString($node->value, null);
+                    return "<<<$label\n" . $escaped . "\n$label"
+                         . $this->docStringEndToken;
+                }
+            /* break missing intentionally */
+            case Scalar\String_::KIND_DOUBLE_QUOTED:
+                return '"' . $this->escapeString($node->value, '"') . '"';
+        }
+        throw new \Exception('Invalid string kind');
+    }
+
+    protected function pScalar_Encapsed(Scalar\Encapsed $node) {
+        if ($node->getAttribute('kind') === Scalar\String_::KIND_HEREDOC) {
+            $label = $node->getAttribute('docLabel');
+            if ($label && !$this->encapsedContainsEndLabel($node->parts, $label)) {
+                if (count($node->parts) === 1
+                    && $node->parts[0] instanceof Scalar\EncapsedStringPart
+                    && $node->parts[0]->value === ''
+                ) {
+                    return "<<<$label\n$label" . $this->docStringEndToken;
+                }
+
+                return "<<<$label\n" . $this->pEncapsList($node->parts, null) . "\n$label"
+                     . $this->docStringEndToken;
+            }
+        }
+        return '"' . $this->pEncapsList($node->parts, '"') . '"';
+    }
+
+    protected function pScalar_LNumber(Scalar\LNumber $node) {
+        if ($node->value === -\PHP_INT_MAX-1) {
+            // PHP_INT_MIN cannot be represented as a literal,
+            // because the sign is not part of the literal
+            return '(-' . \PHP_INT_MAX . '-1)';
+        }
+
+        $kind = $node->getAttribute('kind', Scalar\LNumber::KIND_DEC);
+        if (Scalar\LNumber::KIND_DEC === $kind) {
+            return (string) $node->value;
+        }
+
+        if ($node->value < 0) {
+            $sign = '-';
+            $str = (string) -$node->value;
+        } else {
+            $sign = '';
+            $str = (string) $node->value;
+        }
+        switch ($kind) {
+            case Scalar\LNumber::KIND_BIN:
+                return $sign . '0b' . base_convert($str, 10, 2);
+            case Scalar\LNumber::KIND_OCT:
+                return $sign . '0' . base_convert($str, 10, 8);
+            case Scalar\LNumber::KIND_HEX:
+                return $sign . '0x' . base_convert($str, 10, 16);
+        }
+        throw new \Exception('Invalid number kind');
+    }
+
+    protected function pScalar_DNumber(Scalar\DNumber $node) {
+        if (!is_finite($node->value)) {
+            if ($node->value === \INF) {
+                return '\INF';
+            } elseif ($node->value === -\INF) {
+                return '-\INF';
+            } else {
+                return '\NAN';
+            }
+        }
+
+        // Try to find a short full-precision representation
+        $stringValue = sprintf('%.16G', $node->value);
+        if ($node->value !== (double) $stringValue) {
+            $stringValue = sprintf('%.17G', $node->value);
+        }
+
+        // %G is locale dependent and there exists no locale-independent alternative. We don't want
+        // mess with switching locales here, so let's assume that a comma is the only non-standard
+        // decimal separator we may encounter...
+        $stringValue = str_replace(',', '.', $stringValue);
+
+        // ensure that number is really printed as float
+        return preg_match('/^-?[0-9]+$/', $stringValue) ? $stringValue . '.0' : $stringValue;
+    }
+
+    protected function pScalar_EncapsedStringPart(Scalar\EncapsedStringPart $node) {
+        throw new \LogicException('Cannot directly print EncapsedStringPart');
+    }
+
+    // Assignments
+
+    protected function pExpr_Assign(Expr\Assign $node) {
+        return $this->pInfixOp(Expr\Assign::class, $node->var, ' = ', $node->expr);
+    }
+
+    protected function pExpr_AssignRef(Expr\AssignRef $node) {
+        return $this->pInfixOp(Expr\AssignRef::class, $node->var, ' =& ', $node->expr);
+    }
+
+    protected function pExpr_AssignOp_Plus(AssignOp\Plus $node) {
+        return $this->pInfixOp(AssignOp\Plus::class, $node->var, ' += ', $node->expr);
+    }
+
+    protected function pExpr_AssignOp_Minus(AssignOp\Minus $node) {
+        return $this->pInfixOp(AssignOp\Minus::class, $node->var, ' -= ', $node->expr);
+    }
+
+    protected function pExpr_AssignOp_Mul(AssignOp\Mul $node) {
+        return $this->pInfixOp(AssignOp\Mul::class, $node->var, ' *= ', $node->expr);
+    }
+
+    protected function pExpr_AssignOp_Div(AssignOp\Div $node) {
+        return $this->pInfixOp(AssignOp\Div::class, $node->var, ' /= ', $node->expr);
+    }
+
+    protected function pExpr_AssignOp_Concat(AssignOp\Concat $node) {
+        return $this->pInfixOp(AssignOp\Concat::class, $node->var, ' .= ', $node->expr);
+    }
+
+    protected function pExpr_AssignOp_Mod(AssignOp\Mod $node) {
+        return $this->pInfixOp(AssignOp\Mod::class, $node->var, ' %= ', $node->expr);
+    }
+
+    protected function pExpr_AssignOp_BitwiseAnd(AssignOp\BitwiseAnd $node) {
+        return $this->pInfixOp(AssignOp\BitwiseAnd::class, $node->var, ' &= ', $node->expr);
+    }
+
+    protected function pExpr_AssignOp_BitwiseOr(AssignOp\BitwiseOr $node) {
+        return $this->pInfixOp(AssignOp\BitwiseOr::class, $node->var, ' |= ', $node->expr);
+    }
+
+    protected function pExpr_AssignOp_BitwiseXor(AssignOp\BitwiseXor $node) {
+        return $this->pInfixOp(AssignOp\BitwiseXor::class, $node->var, ' ^= ', $node->expr);
+    }
+
+    protected function pExpr_AssignOp_ShiftLeft(AssignOp\ShiftLeft $node) {
+        return $this->pInfixOp(AssignOp\ShiftLeft::class, $node->var, ' <<= ', $node->expr);
+    }
+
+    protected function pExpr_AssignOp_ShiftRight(AssignOp\ShiftRight $node) {
+        return $this->pInfixOp(AssignOp\ShiftRight::class, $node->var, ' >>= ', $node->expr);
+    }
+
+    protected function pExpr_AssignOp_Pow(AssignOp\Pow $node) {
+        return $this->pInfixOp(AssignOp\Pow::class, $node->var, ' **= ', $node->expr);
+    }
+
+    protected function pExpr_AssignOp_Coalesce(AssignOp\Coalesce $node) {
+        return $this->pInfixOp(AssignOp\Coalesce::class, $node->var, ' ??= ', $node->expr);
+    }
+
+    // Binary expressions
+
+    protected function pExpr_BinaryOp_Plus(BinaryOp\Plus $node) {
+        return $this->pInfixOp(BinaryOp\Plus::class, $node->left, ' + ', $node->right);
+    }
+
+    protected function pExpr_BinaryOp_Minus(BinaryOp\Minus $node) {
+        return $this->pInfixOp(BinaryOp\Minus::class, $node->left, ' - ', $node->right);
+    }
+
+    protected function pExpr_BinaryOp_Mul(BinaryOp\Mul $node) {
+        return $this->pInfixOp(BinaryOp\Mul::class, $node->left, ' * ', $node->right);
+    }
+
+    protected function pExpr_BinaryOp_Div(BinaryOp\Div $node) {
+        return $this->pInfixOp(BinaryOp\Div::class, $node->left, ' / ', $node->right);
+    }
+
+    protected function pExpr_BinaryOp_Concat(BinaryOp\Concat $node) {
+        return $this->pInfixOp(BinaryOp\Concat::class, $node->left, ' . ', $node->right);
+    }
+
+    protected function pExpr_BinaryOp_Mod(BinaryOp\Mod $node) {
+        return $this->pInfixOp(BinaryOp\Mod::class, $node->left, ' % ', $node->right);
+    }
+
+    protected function pExpr_BinaryOp_BooleanAnd(BinaryOp\BooleanAnd $node) {
+        return $this->pInfixOp(BinaryOp\BooleanAnd::class, $node->left, ' && ', $node->right);
+    }
+
+    protected function pExpr_BinaryOp_BooleanOr(BinaryOp\BooleanOr $node) {
+        return $this->pInfixOp(BinaryOp\BooleanOr::class, $node->left, ' || ', $node->right);
+    }
+
+    protected function pExpr_BinaryOp_BitwiseAnd(BinaryOp\BitwiseAnd $node) {
+        return $this->pInfixOp(BinaryOp\BitwiseAnd::class, $node->left, ' & ', $node->right);
+    }
+
+    protected function pExpr_BinaryOp_BitwiseOr(BinaryOp\BitwiseOr $node) {
+        return $this->pInfixOp(BinaryOp\BitwiseOr::class, $node->left, ' | ', $node->right);
+    }
+
+    protected function pExpr_BinaryOp_BitwiseXor(BinaryOp\BitwiseXor $node) {
+        return $this->pInfixOp(BinaryOp\BitwiseXor::class, $node->left, ' ^ ', $node->right);
+    }
+
+    protected function pExpr_BinaryOp_ShiftLeft(BinaryOp\ShiftLeft $node) {
+        return $this->pInfixOp(BinaryOp\ShiftLeft::class, $node->left, ' << ', $node->right);
+    }
+
+    protected function pExpr_BinaryOp_ShiftRight(BinaryOp\ShiftRight $node) {
+        return $this->pInfixOp(BinaryOp\ShiftRight::class, $node->left, ' >> ', $node->right);
+    }
+
+    protected function pExpr_BinaryOp_Pow(BinaryOp\Pow $node) {
+        return $this->pInfixOp(BinaryOp\Pow::class, $node->left, ' ** ', $node->right);
+    }
+
+    protected function pExpr_BinaryOp_LogicalAnd(BinaryOp\LogicalAnd $node) {
+        return $this->pInfixOp(BinaryOp\LogicalAnd::class, $node->left, ' and ', $node->right);
+    }
+
+    protected function pExpr_BinaryOp_LogicalOr(BinaryOp\LogicalOr $node) {
+        return $this->pInfixOp(BinaryOp\LogicalOr::class, $node->left, ' or ', $node->right);
+    }
+
+    protected function pExpr_BinaryOp_LogicalXor(BinaryOp\LogicalXor $node) {
+        return $this->pInfixOp(BinaryOp\LogicalXor::class, $node->left, ' xor ', $node->right);
+    }
+
+    protected function pExpr_BinaryOp_Equal(BinaryOp\Equal $node) {
+        return $this->pInfixOp(BinaryOp\Equal::class, $node->left, ' == ', $node->right);
+    }
+
+    protected function pExpr_BinaryOp_NotEqual(BinaryOp\NotEqual $node) {
+        return $this->pInfixOp(BinaryOp\NotEqual::class, $node->left, ' != ', $node->right);
+    }
+
+    protected function pExpr_BinaryOp_Identical(BinaryOp\Identical $node) {
+        return $this->pInfixOp(BinaryOp\Identical::class, $node->left, ' === ', $node->right);
+    }
+
+    protected function pExpr_BinaryOp_NotIdentical(BinaryOp\NotIdentical $node) {
+        return $this->pInfixOp(BinaryOp\NotIdentical::class, $node->left, ' !== ', $node->right);
+    }
+
+    protected function pExpr_BinaryOp_Spaceship(BinaryOp\Spaceship $node) {
+        return $this->pInfixOp(BinaryOp\Spaceship::class, $node->left, ' <=> ', $node->right);
+    }
+
+    protected function pExpr_BinaryOp_Greater(BinaryOp\Greater $node) {
+        return $this->pInfixOp(BinaryOp\Greater::class, $node->left, ' > ', $node->right);
+    }
+
+    protected function pExpr_BinaryOp_GreaterOrEqual(BinaryOp\GreaterOrEqual $node) {
+        return $this->pInfixOp(BinaryOp\GreaterOrEqual::class, $node->left, ' >= ', $node->right);
+    }
+
+    protected function pExpr_BinaryOp_Smaller(BinaryOp\Smaller $node) {
+        return $this->pInfixOp(BinaryOp\Smaller::class, $node->left, ' < ', $node->right);
+    }
+
+    protected function pExpr_BinaryOp_SmallerOrEqual(BinaryOp\SmallerOrEqual $node) {
+        return $this->pInfixOp(BinaryOp\SmallerOrEqual::class, $node->left, ' <= ', $node->right);
+    }
+
+    protected function pExpr_BinaryOp_Coalesce(BinaryOp\Coalesce $node) {
+        return $this->pInfixOp(BinaryOp\Coalesce::class, $node->left, ' ?? ', $node->right);
+    }
+
+    protected function pExpr_Instanceof(Expr\Instanceof_ $node) {
+        list($precedence, $associativity) = $this->precedenceMap[Expr\Instanceof_::class];
+        return $this->pPrec($node->expr, $precedence, $associativity, -1)
+             . ' instanceof '
+             . $this->pNewVariable($node->class);
+    }
+
+    // Unary expressions
+
+    protected function pExpr_BooleanNot(Expr\BooleanNot $node) {
+        return $this->pPrefixOp(Expr\BooleanNot::class, '!', $node->expr);
+    }
+
+    protected function pExpr_BitwiseNot(Expr\BitwiseNot $node) {
+        return $this->pPrefixOp(Expr\BitwiseNot::class, '~', $node->expr);
+    }
+
+    protected function pExpr_UnaryMinus(Expr\UnaryMinus $node) {
+        if ($node->expr instanceof Expr\UnaryMinus || $node->expr instanceof Expr\PreDec) {
+            // Enforce -(-$expr) instead of --$expr
+            return '-(' . $this->p($node->expr) . ')';
+        }
+        return $this->pPrefixOp(Expr\UnaryMinus::class, '-', $node->expr);
+    }
+
+    protected function pExpr_UnaryPlus(Expr\UnaryPlus $node) {
+        if ($node->expr instanceof Expr\UnaryPlus || $node->expr instanceof Expr\PreInc) {
+            // Enforce +(+$expr) instead of ++$expr
+            return '+(' . $this->p($node->expr) . ')';
+        }
+        return $this->pPrefixOp(Expr\UnaryPlus::class, '+', $node->expr);
+    }
+
+    protected function pExpr_PreInc(Expr\PreInc $node) {
+        return $this->pPrefixOp(Expr\PreInc::class, '++', $node->var);
+    }
+
+    protected function pExpr_PreDec(Expr\PreDec $node) {
+        return $this->pPrefixOp(Expr\PreDec::class, '--', $node->var);
+    }
+
+    protected function pExpr_PostInc(Expr\PostInc $node) {
+        return $this->pPostfixOp(Expr\PostInc::class, $node->var, '++');
+    }
+
+    protected function pExpr_PostDec(Expr\PostDec $node) {
+        return $this->pPostfixOp(Expr\PostDec::class, $node->var, '--');
+    }
+
+    protected function pExpr_ErrorSuppress(Expr\ErrorSuppress $node) {
+        return $this->pPrefixOp(Expr\ErrorSuppress::class, '@', $node->expr);
+    }
+
+    protected function pExpr_YieldFrom(Expr\YieldFrom $node) {
+        return $this->pPrefixOp(Expr\YieldFrom::class, 'yield from ', $node->expr);
+    }
+
+    protected function pExpr_Print(Expr\Print_ $node) {
+        return $this->pPrefixOp(Expr\Print_::class, 'print ', $node->expr);
+    }
+
+    // Casts
+
+    protected function pExpr_Cast_Int(Cast\Int_ $node) {
+        return $this->pPrefixOp(Cast\Int_::class, '(int) ', $node->expr);
+    }
+
+    protected function pExpr_Cast_Double(Cast\Double $node) {
+        $kind = $node->getAttribute('kind', Cast\Double::KIND_DOUBLE);
+        if ($kind === Cast\Double::KIND_DOUBLE) {
+            $cast = '(double)';
+        } elseif ($kind === Cast\Double::KIND_FLOAT) {
+            $cast = '(float)';
+        } elseif ($kind === Cast\Double::KIND_REAL) {
+            $cast = '(real)';
+        }
+        return $this->pPrefixOp(Cast\Double::class, $cast . ' ', $node->expr);
+    }
+
+    protected function pExpr_Cast_String(Cast\String_ $node) {
+        return $this->pPrefixOp(Cast\String_::class, '(string) ', $node->expr);
+    }
+
+    protected function pExpr_Cast_Array(Cast\Array_ $node) {
+        return $this->pPrefixOp(Cast\Array_::class, '(array) ', $node->expr);
+    }
+
+    protected function pExpr_Cast_Object(Cast\Object_ $node) {
+        return $this->pPrefixOp(Cast\Object_::class, '(object) ', $node->expr);
+    }
+
+    protected function pExpr_Cast_Bool(Cast\Bool_ $node) {
+        return $this->pPrefixOp(Cast\Bool_::class, '(bool) ', $node->expr);
+    }
+
+    protected function pExpr_Cast_Unset(Cast\Unset_ $node) {
+        return $this->pPrefixOp(Cast\Unset_::class, '(unset) ', $node->expr);
+    }
+
+    // Function calls and similar constructs
+
+    protected function pExpr_FuncCall(Expr\FuncCall $node) {
+        return $this->pCallLhs($node->name)
+             . '(' . $this->pMaybeMultiline($node->args) . ')';
+    }
+
+    protected function pExpr_MethodCall(Expr\MethodCall $node) {
+        return $this->pDereferenceLhs($node->var) . '->' . $this->pObjectProperty($node->name)
+             . '(' . $this->pMaybeMultiline($node->args) . ')';
+    }
+
+    protected function pExpr_NullsafeMethodCall(Expr\NullsafeMethodCall $node) {
+        return $this->pDereferenceLhs($node->var) . '?->' . $this->pObjectProperty($node->name)
+            . '(' . $this->pMaybeMultiline($node->args) . ')';
+    }
+
+    protected function pExpr_StaticCall(Expr\StaticCall $node) {
+        return $this->pDereferenceLhs($node->class) . '::'
+             . ($node->name instanceof Expr
+                ? ($node->name instanceof Expr\Variable
+                   ? $this->p($node->name)
+                   : '{' . $this->p($node->name) . '}')
+                : $node->name)
+             . '(' . $this->pMaybeMultiline($node->args) . ')';
+    }
+
+    protected function pExpr_Empty(Expr\Empty_ $node) {
+        return 'empty(' . $this->p($node->expr) . ')';
+    }
+
+    protected function pExpr_Isset(Expr\Isset_ $node) {
+        return 'isset(' . $this->pCommaSeparated($node->vars) . ')';
+    }
+
+    protected function pExpr_Eval(Expr\Eval_ $node) {
+        return 'eval(' . $this->p($node->expr) . ')';
+    }
+
+    protected function pExpr_Include(Expr\Include_ $node) {
+        static $map = [
+            Expr\Include_::TYPE_INCLUDE      => 'include',
+            Expr\Include_::TYPE_INCLUDE_ONCE => 'include_once',
+            Expr\Include_::TYPE_REQUIRE      => 'require',
+            Expr\Include_::TYPE_REQUIRE_ONCE => 'require_once',
+        ];
+
+        return $map[$node->type] . ' ' . $this->p($node->expr);
+    }
+
+    protected function pExpr_List(Expr\List_ $node) {
+        return 'list(' . $this->pCommaSeparated($node->items) . ')';
+    }
+
+    // Other
+
+    protected function pExpr_Error(Expr\Error $node) {
+        throw new \LogicException('Cannot pretty-print AST with Error nodes');
+    }
+
+    protected function pExpr_Variable(Expr\Variable $node) {
+        if ($node->name instanceof Expr) {
+            return '${' . $this->p($node->name) . '}';
+        } else {
+            return '$' . $node->name;
+        }
+    }
+
+    protected function pExpr_Array(Expr\Array_ $node) {
+        $syntax = $node->getAttribute('kind',
+            $this->options['shortArraySyntax'] ? Expr\Array_::KIND_SHORT : Expr\Array_::KIND_LONG);
+        if ($syntax === Expr\Array_::KIND_SHORT) {
+            return '[' . $this->pMaybeMultiline($node->items, true) . ']';
+        } else {
+            return 'array(' . $this->pMaybeMultiline($node->items, true) . ')';
+        }
+    }
+
+    protected function pExpr_ArrayItem(Expr\ArrayItem $node) {
+        return (null !== $node->key ? $this->p($node->key) . ' => ' : '')
+             . ($node->byRef ? '&' : '')
+             . ($node->unpack ? '...' : '')
+             . $this->p($node->value);
+    }
+
+    protected function pExpr_ArrayDimFetch(Expr\ArrayDimFetch $node) {
+        return $this->pDereferenceLhs($node->var)
+             . '[' . (null !== $node->dim ? $this->p($node->dim) : '') . ']';
+    }
+
+    protected function pExpr_ConstFetch(Expr\ConstFetch $node) {
+        return $this->p($node->name);
+    }
+
+    protected function pExpr_ClassConstFetch(Expr\ClassConstFetch $node) {
+        return $this->pDereferenceLhs($node->class) . '::' . $this->p($node->name);
+    }
+
+    protected function pExpr_PropertyFetch(Expr\PropertyFetch $node) {
+        return $this->pDereferenceLhs($node->var) . '->' . $this->pObjectProperty($node->name);
+    }
+
+    protected function pExpr_NullsafePropertyFetch(Expr\NullsafePropertyFetch $node) {
+        return $this->pDereferenceLhs($node->var) . '?->' . $this->pObjectProperty($node->name);
+    }
+
+    protected function pExpr_StaticPropertyFetch(Expr\StaticPropertyFetch $node) {
+        return $this->pDereferenceLhs($node->class) . '::$' . $this->pObjectProperty($node->name);
+    }
+
+    protected function pExpr_ShellExec(Expr\ShellExec $node) {
+        return '`' . $this->pEncapsList($node->parts, '`') . '`';
+    }
+
+    protected function pExpr_Closure(Expr\Closure $node) {
+        return $this->pAttrGroups($node->attrGroups, true)
+             . ($node->static ? 'static ' : '')
+             . 'function ' . ($node->byRef ? '&' : '')
+             . '(' . $this->pCommaSeparated($node->params) . ')'
+             . (!empty($node->uses) ? ' use(' . $this->pCommaSeparated($node->uses) . ')' : '')
+             . (null !== $node->returnType ? ' : ' . $this->p($node->returnType) : '')
+             . ' {' . $this->pStmts($node->stmts) . $this->nl . '}';
+    }
+
+    protected function pExpr_Match(Expr\Match_ $node) {
+        return 'match (' . $this->p($node->cond) . ') {'
+            . $this->pCommaSeparatedMultiline($node->arms, true)
+            . $this->nl
+            . '}';
+    }
+
+    protected function pMatchArm(Node\MatchArm $node) {
+        return ($node->conds ? $this->pCommaSeparated($node->conds) : 'default')
+            . ' => ' . $this->p($node->body);
+    }
+
+    protected function pExpr_ArrowFunction(Expr\ArrowFunction $node) {
+        return $this->pAttrGroups($node->attrGroups, true)
+            . ($node->static ? 'static ' : '')
+            . 'fn' . ($node->byRef ? '&' : '')
+            . '(' . $this->pCommaSeparated($node->params) . ')'
+            . (null !== $node->returnType ? ': ' . $this->p($node->returnType) : '')
+            . ' => '
+            . $this->p($node->expr);
+    }
+
+    protected function pExpr_ClosureUse(Expr\ClosureUse $node) {
+        return ($node->byRef ? '&' : '') . $this->p($node->var);
+    }
+
+    protected function pExpr_New(Expr\New_ $node) {
+        if ($node->class instanceof Stmt\Class_) {
+            $args = $node->args ? '(' . $this->pMaybeMultiline($node->args) . ')' : '';
+            return 'new ' . $this->pClassCommon($node->class, $args);
+        }
+        return 'new ' . $this->pNewVariable($node->class)
+            . '(' . $this->pMaybeMultiline($node->args) . ')';
+    }
+
+    protected function pExpr_Clone(Expr\Clone_ $node) {
+        return 'clone ' . $this->p($node->expr);
+    }
+
+    protected function pExpr_Ternary(Expr\Ternary $node) {
+        // a bit of cheating: we treat the ternary as a binary op where the ?...: part is the operator.
+        // this is okay because the part between ? and : never needs parentheses.
+        return $this->pInfixOp(Expr\Ternary::class,
+            $node->cond, ' ?' . (null !== $node->if ? ' ' . $this->p($node->if) . ' ' : '') . ': ', $node->else
+        );
+    }
+
+    protected function pExpr_Exit(Expr\Exit_ $node) {
+        $kind = $node->getAttribute('kind', Expr\Exit_::KIND_DIE);
+        return ($kind === Expr\Exit_::KIND_EXIT ? 'exit' : 'die')
+             . (null !== $node->expr ? '(' . $this->p($node->expr) . ')' : '');
+    }
+
+    protected function pExpr_Throw(Expr\Throw_ $node) {
+        return 'throw ' . $this->p($node->expr);
+    }
+
+    protected function pExpr_Yield(Expr\Yield_ $node) {
+        if ($node->value === null) {
+            return 'yield';
+        } else {
+            // this is a bit ugly, but currently there is no way to detect whether the parentheses are necessary
+            return '(yield '
+                 . ($node->key !== null ? $this->p($node->key) . ' => ' : '')
+                 . $this->p($node->value)
+                 . ')';
+        }
+    }
+
+    // Declarations
+
+    protected function pStmt_Namespace(Stmt\Namespace_ $node) {
+        if ($this->canUseSemicolonNamespaces) {
+            return 'namespace ' . $this->p($node->name) . ';'
+                 . $this->nl . $this->pStmts($node->stmts, false);
+        } else {
+            return 'namespace' . (null !== $node->name ? ' ' . $this->p($node->name) : '')
+                 . ' {' . $this->pStmts($node->stmts) . $this->nl . '}';
+        }
+    }
+
+    protected function pStmt_Use(Stmt\Use_ $node) {
+        return 'use ' . $this->pUseType($node->type)
+             . $this->pCommaSeparated($node->uses) . ';';
+    }
+
+    protected function pStmt_GroupUse(Stmt\GroupUse $node) {
+        return 'use ' . $this->pUseType($node->type) . $this->pName($node->prefix)
+             . '\{' . $this->pCommaSeparated($node->uses) . '};';
+    }
+
+    protected function pStmt_UseUse(Stmt\UseUse $node) {
+        return $this->pUseType($node->type) . $this->p($node->name)
+             . (null !== $node->alias ? ' as ' . $node->alias : '');
+    }
+
+    protected function pUseType($type) {
+        return $type === Stmt\Use_::TYPE_FUNCTION ? 'function '
+            : ($type === Stmt\Use_::TYPE_CONSTANT ? 'const ' : '');
+    }
+
+    protected function pStmt_Interface(Stmt\Interface_ $node) {
+        return $this->pAttrGroups($node->attrGroups)
+             . 'interface ' . $node->name
+             . (!empty($node->extends) ? ' extends ' . $this->pCommaSeparated($node->extends) : '')
+             . $this->nl . '{' . $this->pStmts($node->stmts) . $this->nl . '}';
+    }
+
+    protected function pStmt_Class(Stmt\Class_ $node) {
+        return $this->pClassCommon($node, ' ' . $node->name);
+    }
+
+    protected function pStmt_Trait(Stmt\Trait_ $node) {
+        return $this->pAttrGroups($node->attrGroups)
+             . 'trait ' . $node->name
+             . $this->nl . '{' . $this->pStmts($node->stmts) . $this->nl . '}';
+    }
+
+    protected function pStmt_TraitUse(Stmt\TraitUse $node) {
+        return 'use ' . $this->pCommaSeparated($node->traits)
+             . (empty($node->adaptations)
+                ? ';'
+                : ' {' . $this->pStmts($node->adaptations) . $this->nl . '}');
+    }
+
+    protected function pStmt_TraitUseAdaptation_Precedence(Stmt\TraitUseAdaptation\Precedence $node) {
+        return $this->p($node->trait) . '::' . $node->method
+             . ' insteadof ' . $this->pCommaSeparated($node->insteadof) . ';';
+    }
+
+    protected function pStmt_TraitUseAdaptation_Alias(Stmt\TraitUseAdaptation\Alias $node) {
+        return (null !== $node->trait ? $this->p($node->trait) . '::' : '')
+             . $node->method . ' as'
+             . (null !== $node->newModifier ? ' ' . rtrim($this->pModifiers($node->newModifier), ' ') : '')
+             . (null !== $node->newName     ? ' ' . $node->newName                        : '')
+             . ';';
+    }
+
+    protected function pStmt_Property(Stmt\Property $node) {
+        return $this->pAttrGroups($node->attrGroups)
+            . (0 === $node->flags ? 'var ' : $this->pModifiers($node->flags))
+            . ($node->type ? $this->p($node->type) . ' ' : '')
+            . $this->pCommaSeparated($node->props) . ';';
+    }
+
+    protected function pStmt_PropertyProperty(Stmt\PropertyProperty $node) {
+        return '$' . $node->name
+             . (null !== $node->default ? ' = ' . $this->p($node->default) : '');
+    }
+
+    protected function pStmt_ClassMethod(Stmt\ClassMethod $node) {
+        return $this->pAttrGroups($node->attrGroups)
+             . $this->pModifiers($node->flags)
+             . 'function ' . ($node->byRef ? '&' : '') . $node->name
+             . '(' . $this->pMaybeMultiline($node->params) . ')'
+             . (null !== $node->returnType ? ' : ' . $this->p($node->returnType) : '')
+             . (null !== $node->stmts
+                ? $this->nl . '{' . $this->pStmts($node->stmts) . $this->nl . '}'
+                : ';');
+    }
+
+    protected function pStmt_ClassConst(Stmt\ClassConst $node) {
+        return $this->pAttrGroups($node->attrGroups)
+             . $this->pModifiers($node->flags)
+             . 'const ' . $this->pCommaSeparated($node->consts) . ';';
+    }
+
+    protected function pStmt_Function(Stmt\Function_ $node) {
+        return $this->pAttrGroups($node->attrGroups)
+             . 'function ' . ($node->byRef ? '&' : '') . $node->name
+             . '(' . $this->pCommaSeparated($node->params) . ')'
+             . (null !== $node->returnType ? ' : ' . $this->p($node->returnType) : '')
+             . $this->nl . '{' . $this->pStmts($node->stmts) . $this->nl . '}';
+    }
+
+    protected function pStmt_Const(Stmt\Const_ $node) {
+        return 'const ' . $this->pCommaSeparated($node->consts) . ';';
+    }
+
+    protected function pStmt_Declare(Stmt\Declare_ $node) {
+        return 'declare (' . $this->pCommaSeparated($node->declares) . ')'
+             . (null !== $node->stmts ? ' {' . $this->pStmts($node->stmts) . $this->nl . '}' : ';');
+    }
+
+    protected function pStmt_DeclareDeclare(Stmt\DeclareDeclare $node) {
+        return $node->key . '=' . $this->p($node->value);
+    }
+
+    // Control flow
+
+    protected function pStmt_If(Stmt\If_ $node) {
+        return 'if (' . $this->p($node->cond) . ') {'
+             . $this->pStmts($node->stmts) . $this->nl . '}'
+             . ($node->elseifs ? ' ' . $this->pImplode($node->elseifs, ' ') : '')
+             . (null !== $node->else ? ' ' . $this->p($node->else) : '');
+    }
+
+    protected function pStmt_ElseIf(Stmt\ElseIf_ $node) {
+        return 'elseif (' . $this->p($node->cond) . ') {'
+             . $this->pStmts($node->stmts) . $this->nl . '}';
+    }
+
+    protected function pStmt_Else(Stmt\Else_ $node) {
+        return 'else {' . $this->pStmts($node->stmts) . $this->nl . '}';
+    }
+
+    protected function pStmt_For(Stmt\For_ $node) {
+        return 'for ('
+             . $this->pCommaSeparated($node->init) . ';' . (!empty($node->cond) ? ' ' : '')
+             . $this->pCommaSeparated($node->cond) . ';' . (!empty($node->loop) ? ' ' : '')
+             . $this->pCommaSeparated($node->loop)
+             . ') {' . $this->pStmts($node->stmts) . $this->nl . '}';
+    }
+
+    protected function pStmt_Foreach(Stmt\Foreach_ $node) {
+        return 'foreach (' . $this->p($node->expr) . ' as '
+             . (null !== $node->keyVar ? $this->p($node->keyVar) . ' => ' : '')
+             . ($node->byRef ? '&' : '') . $this->p($node->valueVar) . ') {'
+             . $this->pStmts($node->stmts) . $this->nl . '}';
+    }
+
+    protected function pStmt_While(Stmt\While_ $node) {
+        return 'while (' . $this->p($node->cond) . ') {'
+             . $this->pStmts($node->stmts) . $this->nl . '}';
+    }
+
+    protected function pStmt_Do(Stmt\Do_ $node) {
+        return 'do {' . $this->pStmts($node->stmts) . $this->nl
+             . '} while (' . $this->p($node->cond) . ');';
+    }
+
+    protected function pStmt_Switch(Stmt\Switch_ $node) {
+        return 'switch (' . $this->p($node->cond) . ') {'
+             . $this->pStmts($node->cases) . $this->nl . '}';
+    }
+
+    protected function pStmt_Case(Stmt\Case_ $node) {
+        return (null !== $node->cond ? 'case ' . $this->p($node->cond) : 'default') . ':'
+             . $this->pStmts($node->stmts);
+    }
+
+    protected function pStmt_TryCatch(Stmt\TryCatch $node) {
+        return 'try {' . $this->pStmts($node->stmts) . $this->nl . '}'
+             . ($node->catches ? ' ' . $this->pImplode($node->catches, ' ') : '')
+             . ($node->finally !== null ? ' ' . $this->p($node->finally) : '');
+    }
+
+    protected function pStmt_Catch(Stmt\Catch_ $node) {
+        return 'catch (' . $this->pImplode($node->types, '|')
+             . ($node->var !== null ? ' ' . $this->p($node->var) : '')
+             . ') {' . $this->pStmts($node->stmts) . $this->nl . '}';
+    }
+
+    protected function pStmt_Finally(Stmt\Finally_ $node) {
+        return 'finally {' . $this->pStmts($node->stmts) . $this->nl . '}';
+    }
+
+    protected function pStmt_Break(Stmt\Break_ $node) {
+        return 'break' . ($node->num !== null ? ' ' . $this->p($node->num) : '') . ';';
+    }
+
+    protected function pStmt_Continue(Stmt\Continue_ $node) {
+        return 'continue' . ($node->num !== null ? ' ' . $this->p($node->num) : '') . ';';
+    }
+
+    protected function pStmt_Return(Stmt\Return_ $node) {
+        return 'return' . (null !== $node->expr ? ' ' . $this->p($node->expr) : '') . ';';
+    }
+
+    protected function pStmt_Throw(Stmt\Throw_ $node) {
+        return 'throw ' . $this->p($node->expr) . ';';
+    }
+
+    protected function pStmt_Label(Stmt\Label $node) {
+        return $node->name . ':';
+    }
+
+    protected function pStmt_Goto(Stmt\Goto_ $node) {
+        return 'goto ' . $node->name . ';';
+    }
+
+    // Other
+
+    protected function pStmt_Expression(Stmt\Expression $node) {
+        return $this->p($node->expr) . ';';
+    }
+
+    protected function pStmt_Echo(Stmt\Echo_ $node) {
+        return 'echo ' . $this->pCommaSeparated($node->exprs) . ';';
+    }
+
+    protected function pStmt_Static(Stmt\Static_ $node) {
+        return 'static ' . $this->pCommaSeparated($node->vars) . ';';
+    }
+
+    protected function pStmt_Global(Stmt\Global_ $node) {
+        return 'global ' . $this->pCommaSeparated($node->vars) . ';';
+    }
+
+    protected function pStmt_StaticVar(Stmt\StaticVar $node) {
+        return $this->p($node->var)
+             . (null !== $node->default ? ' = ' . $this->p($node->default) : '');
+    }
+
+    protected function pStmt_Unset(Stmt\Unset_ $node) {
+        return 'unset(' . $this->pCommaSeparated($node->vars) . ');';
+    }
+
+    protected function pStmt_InlineHTML(Stmt\InlineHTML $node) {
+        $newline = $node->getAttribute('hasLeadingNewline', true) ? "\n" : '';
+        return '?>' . $newline . $node->value . '<?php ';
+    }
+
+    protected function pStmt_HaltCompiler(Stmt\HaltCompiler $node) {
+        return '__halt_compiler();' . $node->remaining;
+    }
+
+    protected function pStmt_Nop(Stmt\Nop $node) {
+        return '';
+    }
+
+    // Helpers
+
+    protected function pClassCommon(Stmt\Class_ $node, $afterClassToken) {
+        return $this->pAttrGroups($node->attrGroups, $node->name === null)
+            . $this->pModifiers($node->flags)
+            . 'class' . $afterClassToken
+            . (null !== $node->extends ? ' extends ' . $this->p($node->extends) : '')
+            . (!empty($node->implements) ? ' implements ' . $this->pCommaSeparated($node->implements) : '')
+            . $this->nl . '{' . $this->pStmts($node->stmts) . $this->nl . '}';
+    }
+
+    protected function pObjectProperty($node) {
+        if ($node instanceof Expr) {
+            return '{' . $this->p($node) . '}';
+        } else {
+            return $node;
+        }
+    }
+
+    protected function pEncapsList(array $encapsList, $quote) {
+        $return = '';
+        foreach ($encapsList as $element) {
+            if ($element instanceof Scalar\EncapsedStringPart) {
+                $return .= $this->escapeString($element->value, $quote);
+            } else {
+                $return .= '{' . $this->p($element) . '}';
+            }
+        }
+
+        return $return;
+    }
+
+    protected function pSingleQuotedString(string $string) {
+        return '\'' . addcslashes($string, '\'\\') . '\'';
+    }
+
+    protected function escapeString($string, $quote) {
+        if (null === $quote) {
+            // For doc strings, don't escape newlines
+            $escaped = addcslashes($string, "\t\f\v$\\");
+        } else {
+            $escaped = addcslashes($string, "\n\r\t\f\v$" . $quote . "\\");
+        }
+
+        // Escape other control characters
+        return preg_replace_callback('/([\0-\10\16-\37])(?=([0-7]?))/', function ($matches) {
+            $oct = decoct(ord($matches[1]));
+            if ($matches[2] !== '') {
+                // If there is a trailing digit, use the full three character form
+                return '\\' . str_pad($oct, 3, '0', \STR_PAD_LEFT);
+            }
+            return '\\' . $oct;
+        }, $escaped);
+    }
+
+    protected function containsEndLabel($string, $label, $atStart = true, $atEnd = true) {
+        $start = $atStart ? '(?:^|[\r\n])' : '[\r\n]';
+        $end = $atEnd ? '(?:$|[;\r\n])' : '[;\r\n]';
+        return false !== strpos($string, $label)
+            && preg_match('/' . $start . $label . $end . '/', $string);
+    }
+
+    protected function encapsedContainsEndLabel(array $parts, $label) {
+        foreach ($parts as $i => $part) {
+            $atStart = $i === 0;
+            $atEnd = $i === count($parts) - 1;
+            if ($part instanceof Scalar\EncapsedStringPart
+                && $this->containsEndLabel($part->value, $label, $atStart, $atEnd)
+            ) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    protected function pDereferenceLhs(Node $node) {
+        if (!$this->dereferenceLhsRequiresParens($node)) {
+            return $this->p($node);
+        } else  {
+            return '(' . $this->p($node) . ')';
+        }
+    }
+
+    protected function pCallLhs(Node $node) {
+        if (!$this->callLhsRequiresParens($node)) {
+            return $this->p($node);
+        } else  {
+            return '(' . $this->p($node) . ')';
+        }
+    }
+
+    protected function pNewVariable(Node $node) {
+        // TODO: This is not fully accurate.
+        return $this->pDereferenceLhs($node);
+    }
+
+    /**
+     * @param Node[] $nodes
+     * @return bool
+     */
+    protected function hasNodeWithComments(array $nodes) {
+        foreach ($nodes as $node) {
+            if ($node && $node->getComments()) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    protected function pMaybeMultiline(array $nodes, bool $trailingComma = false) {
+        if (!$this->hasNodeWithComments($nodes)) {
+            return $this->pCommaSeparated($nodes);
+        } else {
+            return $this->pCommaSeparatedMultiline($nodes, $trailingComma) . $this->nl;
+        }
+    }
+
+    protected function pAttrGroups(array $nodes, bool $inline = false): string {
+        $result = '';
+        $sep = $inline ? ' ' : $this->nl;
+        foreach ($nodes as $node) {
+            $result .= $this->p($node) . $sep;
+        }
+
+        return $result;
+    }
+}
diff --git a/vendor/nikic/php-parser/lib/PhpParser/PrettyPrinterAbstract.php b/vendor/nikic/php-parser/lib/PhpParser/PrettyPrinterAbstract.php
new file mode 100644
index 0000000000000000000000000000000000000000..804026eff62f826716a856b20416112d2336f870
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/PrettyPrinterAbstract.php
@@ -0,0 +1,1490 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser;
+
+use PhpParser\Internal\DiffElem;
+use PhpParser\Internal\PrintableNewAnonClassNode;
+use PhpParser\Internal\TokenStream;
+use PhpParser\Node\Expr;
+use PhpParser\Node\Expr\AssignOp;
+use PhpParser\Node\Expr\BinaryOp;
+use PhpParser\Node\Expr\Cast;
+use PhpParser\Node\Scalar;
+use PhpParser\Node\Stmt;
+
+abstract class PrettyPrinterAbstract
+{
+    const FIXUP_PREC_LEFT       = 0; // LHS operand affected by precedence
+    const FIXUP_PREC_RIGHT      = 1; // RHS operand affected by precedence
+    const FIXUP_CALL_LHS        = 2; // LHS of call
+    const FIXUP_DEREF_LHS       = 3; // LHS of dereferencing operation
+    const FIXUP_BRACED_NAME     = 4; // Name operand that may require bracing
+    const FIXUP_VAR_BRACED_NAME = 5; // Name operand that may require ${} bracing
+    const FIXUP_ENCAPSED        = 6; // Encapsed string part
+
+    protected $precedenceMap = [
+        // [precedence, associativity]
+        // where for precedence -1 is %left, 0 is %nonassoc and 1 is %right
+        BinaryOp\Pow::class            => [  0,  1],
+        Expr\BitwiseNot::class         => [ 10,  1],
+        Expr\PreInc::class             => [ 10,  1],
+        Expr\PreDec::class             => [ 10,  1],
+        Expr\PostInc::class            => [ 10, -1],
+        Expr\PostDec::class            => [ 10, -1],
+        Expr\UnaryPlus::class          => [ 10,  1],
+        Expr\UnaryMinus::class         => [ 10,  1],
+        Cast\Int_::class               => [ 10,  1],
+        Cast\Double::class             => [ 10,  1],
+        Cast\String_::class            => [ 10,  1],
+        Cast\Array_::class             => [ 10,  1],
+        Cast\Object_::class            => [ 10,  1],
+        Cast\Bool_::class              => [ 10,  1],
+        Cast\Unset_::class             => [ 10,  1],
+        Expr\ErrorSuppress::class      => [ 10,  1],
+        Expr\Instanceof_::class        => [ 20,  0],
+        Expr\BooleanNot::class         => [ 30,  1],
+        BinaryOp\Mul::class            => [ 40, -1],
+        BinaryOp\Div::class            => [ 40, -1],
+        BinaryOp\Mod::class            => [ 40, -1],
+        BinaryOp\Plus::class           => [ 50, -1],
+        BinaryOp\Minus::class          => [ 50, -1],
+        BinaryOp\Concat::class         => [ 50, -1],
+        BinaryOp\ShiftLeft::class      => [ 60, -1],
+        BinaryOp\ShiftRight::class     => [ 60, -1],
+        BinaryOp\Smaller::class        => [ 70,  0],
+        BinaryOp\SmallerOrEqual::class => [ 70,  0],
+        BinaryOp\Greater::class        => [ 70,  0],
+        BinaryOp\GreaterOrEqual::class => [ 70,  0],
+        BinaryOp\Equal::class          => [ 80,  0],
+        BinaryOp\NotEqual::class       => [ 80,  0],
+        BinaryOp\Identical::class      => [ 80,  0],
+        BinaryOp\NotIdentical::class   => [ 80,  0],
+        BinaryOp\Spaceship::class      => [ 80,  0],
+        BinaryOp\BitwiseAnd::class     => [ 90, -1],
+        BinaryOp\BitwiseXor::class     => [100, -1],
+        BinaryOp\BitwiseOr::class      => [110, -1],
+        BinaryOp\BooleanAnd::class     => [120, -1],
+        BinaryOp\BooleanOr::class      => [130, -1],
+        BinaryOp\Coalesce::class       => [140,  1],
+        Expr\Ternary::class            => [150,  0],
+        // parser uses %left for assignments, but they really behave as %right
+        Expr\Assign::class             => [160,  1],
+        Expr\AssignRef::class          => [160,  1],
+        AssignOp\Plus::class           => [160,  1],
+        AssignOp\Minus::class          => [160,  1],
+        AssignOp\Mul::class            => [160,  1],
+        AssignOp\Div::class            => [160,  1],
+        AssignOp\Concat::class         => [160,  1],
+        AssignOp\Mod::class            => [160,  1],
+        AssignOp\BitwiseAnd::class     => [160,  1],
+        AssignOp\BitwiseOr::class      => [160,  1],
+        AssignOp\BitwiseXor::class     => [160,  1],
+        AssignOp\ShiftLeft::class      => [160,  1],
+        AssignOp\ShiftRight::class     => [160,  1],
+        AssignOp\Pow::class            => [160,  1],
+        AssignOp\Coalesce::class       => [160,  1],
+        Expr\YieldFrom::class          => [165,  1],
+        Expr\Print_::class             => [168,  1],
+        BinaryOp\LogicalAnd::class     => [170, -1],
+        BinaryOp\LogicalXor::class     => [180, -1],
+        BinaryOp\LogicalOr::class      => [190, -1],
+        Expr\Include_::class           => [200, -1],
+    ];
+
+    /** @var int Current indentation level. */
+    protected $indentLevel;
+    /** @var string Newline including current indentation. */
+    protected $nl;
+    /** @var string Token placed at end of doc string to ensure it is followed by a newline. */
+    protected $docStringEndToken;
+    /** @var bool Whether semicolon namespaces can be used (i.e. no global namespace is used) */
+    protected $canUseSemicolonNamespaces;
+    /** @var array Pretty printer options */
+    protected $options;
+
+    /** @var TokenStream Original tokens for use in format-preserving pretty print */
+    protected $origTokens;
+    /** @var Internal\Differ Differ for node lists */
+    protected $nodeListDiffer;
+    /** @var bool[] Map determining whether a certain character is a label character */
+    protected $labelCharMap;
+    /**
+     * @var int[][] Map from token classes and subnode names to FIXUP_* constants. This is used
+     *              during format-preserving prints to place additional parens/braces if necessary.
+     */
+    protected $fixupMap;
+    /**
+     * @var int[][] Map from "{$node->getType()}->{$subNode}" to ['left' => $l, 'right' => $r],
+     *              where $l and $r specify the token type that needs to be stripped when removing
+     *              this node.
+     */
+    protected $removalMap;
+    /**
+     * @var mixed[] Map from "{$node->getType()}->{$subNode}" to [$find, $beforeToken, $extraLeft, $extraRight].
+     *              $find is an optional token after which the insertion occurs. $extraLeft/Right
+     *              are optionally added before/after the main insertions.
+     */
+    protected $insertionMap;
+    /**
+     * @var string[] Map From "{$node->getType()}->{$subNode}" to string that should be inserted
+     *               between elements of this list subnode.
+     */
+    protected $listInsertionMap;
+    protected $emptyListInsertionMap;
+    /** @var int[] Map from "{$node->getType()}->{$subNode}" to token before which the modifiers
+     *             should be reprinted. */
+    protected $modifierChangeMap;
+
+    /**
+     * Creates a pretty printer instance using the given options.
+     *
+     * Supported options:
+     *  * bool $shortArraySyntax = false: Whether to use [] instead of array() as the default array
+     *                                    syntax, if the node does not specify a format.
+     *
+     * @param array $options Dictionary of formatting options
+     */
+    public function __construct(array $options = []) {
+        $this->docStringEndToken = '_DOC_STRING_END_' . mt_rand();
+
+        $defaultOptions = ['shortArraySyntax' => false];
+        $this->options = $options + $defaultOptions;
+    }
+
+    /**
+     * Reset pretty printing state.
+     */
+    protected function resetState() {
+        $this->indentLevel = 0;
+        $this->nl = "\n";
+        $this->origTokens = null;
+    }
+
+    /**
+     * Set indentation level
+     *
+     * @param int $level Level in number of spaces
+     */
+    protected function setIndentLevel(int $level) {
+        $this->indentLevel = $level;
+        $this->nl = "\n" . \str_repeat(' ', $level);
+    }
+
+    /**
+     * Increase indentation level.
+     */
+    protected function indent() {
+        $this->indentLevel += 4;
+        $this->nl .= '    ';
+    }
+
+    /**
+     * Decrease indentation level.
+     */
+    protected function outdent() {
+        assert($this->indentLevel >= 4);
+        $this->indentLevel -= 4;
+        $this->nl = "\n" . str_repeat(' ', $this->indentLevel);
+    }
+
+    /**
+     * Pretty prints an array of statements.
+     *
+     * @param Node[] $stmts Array of statements
+     *
+     * @return string Pretty printed statements
+     */
+    public function prettyPrint(array $stmts) : string {
+        $this->resetState();
+        $this->preprocessNodes($stmts);
+
+        return ltrim($this->handleMagicTokens($this->pStmts($stmts, false)));
+    }
+
+    /**
+     * Pretty prints an expression.
+     *
+     * @param Expr $node Expression node
+     *
+     * @return string Pretty printed node
+     */
+    public function prettyPrintExpr(Expr $node) : string {
+        $this->resetState();
+        return $this->handleMagicTokens($this->p($node));
+    }
+
+    /**
+     * Pretty prints a file of statements (includes the opening <?php tag if it is required).
+     *
+     * @param Node[] $stmts Array of statements
+     *
+     * @return string Pretty printed statements
+     */
+    public function prettyPrintFile(array $stmts) : string {
+        if (!$stmts) {
+            return "<?php\n\n";
+        }
+
+        $p = "<?php\n\n" . $this->prettyPrint($stmts);
+
+        if ($stmts[0] instanceof Stmt\InlineHTML) {
+            $p = preg_replace('/^<\?php\s+\?>\n?/', '', $p);
+        }
+        if ($stmts[count($stmts) - 1] instanceof Stmt\InlineHTML) {
+            $p = preg_replace('/<\?php$/', '', rtrim($p));
+        }
+
+        return $p;
+    }
+
+    /**
+     * Preprocesses the top-level nodes to initialize pretty printer state.
+     *
+     * @param Node[] $nodes Array of nodes
+     */
+    protected function preprocessNodes(array $nodes) {
+        /* We can use semicolon-namespaces unless there is a global namespace declaration */
+        $this->canUseSemicolonNamespaces = true;
+        foreach ($nodes as $node) {
+            if ($node instanceof Stmt\Namespace_ && null === $node->name) {
+                $this->canUseSemicolonNamespaces = false;
+                break;
+            }
+        }
+    }
+
+    /**
+     * Handles (and removes) no-indent and doc-string-end tokens.
+     *
+     * @param string $str
+     * @return string
+     */
+    protected function handleMagicTokens(string $str) : string {
+        // Replace doc-string-end tokens with nothing or a newline
+        $str = str_replace($this->docStringEndToken . ";\n", ";\n", $str);
+        $str = str_replace($this->docStringEndToken, "\n", $str);
+
+        return $str;
+    }
+
+    /**
+     * Pretty prints an array of nodes (statements) and indents them optionally.
+     *
+     * @param Node[] $nodes  Array of nodes
+     * @param bool   $indent Whether to indent the printed nodes
+     *
+     * @return string Pretty printed statements
+     */
+    protected function pStmts(array $nodes, bool $indent = true) : string {
+        if ($indent) {
+            $this->indent();
+        }
+
+        $result = '';
+        foreach ($nodes as $node) {
+            $comments = $node->getComments();
+            if ($comments) {
+                $result .= $this->nl . $this->pComments($comments);
+                if ($node instanceof Stmt\Nop) {
+                    continue;
+                }
+            }
+
+            $result .= $this->nl . $this->p($node);
+        }
+
+        if ($indent) {
+            $this->outdent();
+        }
+
+        return $result;
+    }
+
+    /**
+     * Pretty-print an infix operation while taking precedence into account.
+     *
+     * @param string $class          Node class of operator
+     * @param Node   $leftNode       Left-hand side node
+     * @param string $operatorString String representation of the operator
+     * @param Node   $rightNode      Right-hand side node
+     *
+     * @return string Pretty printed infix operation
+     */
+    protected function pInfixOp(string $class, Node $leftNode, string $operatorString, Node $rightNode) : string {
+        list($precedence, $associativity) = $this->precedenceMap[$class];
+
+        return $this->pPrec($leftNode, $precedence, $associativity, -1)
+             . $operatorString
+             . $this->pPrec($rightNode, $precedence, $associativity, 1);
+    }
+
+    /**
+     * Pretty-print a prefix operation while taking precedence into account.
+     *
+     * @param string $class          Node class of operator
+     * @param string $operatorString String representation of the operator
+     * @param Node   $node           Node
+     *
+     * @return string Pretty printed prefix operation
+     */
+    protected function pPrefixOp(string $class, string $operatorString, Node $node) : string {
+        list($precedence, $associativity) = $this->precedenceMap[$class];
+        return $operatorString . $this->pPrec($node, $precedence, $associativity, 1);
+    }
+
+    /**
+     * Pretty-print a postfix operation while taking precedence into account.
+     *
+     * @param string $class          Node class of operator
+     * @param string $operatorString String representation of the operator
+     * @param Node   $node           Node
+     *
+     * @return string Pretty printed postfix operation
+     */
+    protected function pPostfixOp(string $class, Node $node, string $operatorString) : string {
+        list($precedence, $associativity) = $this->precedenceMap[$class];
+        return $this->pPrec($node, $precedence, $associativity, -1) . $operatorString;
+    }
+
+    /**
+     * Prints an expression node with the least amount of parentheses necessary to preserve the meaning.
+     *
+     * @param Node $node                Node to pretty print
+     * @param int  $parentPrecedence    Precedence of the parent operator
+     * @param int  $parentAssociativity Associativity of parent operator
+     *                                  (-1 is left, 0 is nonassoc, 1 is right)
+     * @param int  $childPosition       Position of the node relative to the operator
+     *                                  (-1 is left, 1 is right)
+     *
+     * @return string The pretty printed node
+     */
+    protected function pPrec(Node $node, int $parentPrecedence, int $parentAssociativity, int $childPosition) : string {
+        $class = \get_class($node);
+        if (isset($this->precedenceMap[$class])) {
+            $childPrecedence = $this->precedenceMap[$class][0];
+            if ($childPrecedence > $parentPrecedence
+                || ($parentPrecedence === $childPrecedence && $parentAssociativity !== $childPosition)
+            ) {
+                return '(' . $this->p($node) . ')';
+            }
+        }
+
+        return $this->p($node);
+    }
+
+    /**
+     * Pretty prints an array of nodes and implodes the printed values.
+     *
+     * @param Node[] $nodes Array of Nodes to be printed
+     * @param string $glue  Character to implode with
+     *
+     * @return string Imploded pretty printed nodes
+     */
+    protected function pImplode(array $nodes, string $glue = '') : string {
+        $pNodes = [];
+        foreach ($nodes as $node) {
+            if (null === $node) {
+                $pNodes[] = '';
+            } else {
+                $pNodes[] = $this->p($node);
+            }
+        }
+
+        return implode($glue, $pNodes);
+    }
+
+    /**
+     * Pretty prints an array of nodes and implodes the printed values with commas.
+     *
+     * @param Node[] $nodes Array of Nodes to be printed
+     *
+     * @return string Comma separated pretty printed nodes
+     */
+    protected function pCommaSeparated(array $nodes) : string {
+        return $this->pImplode($nodes, ', ');
+    }
+
+    /**
+     * Pretty prints a comma-separated list of nodes in multiline style, including comments.
+     *
+     * The result includes a leading newline and one level of indentation (same as pStmts).
+     *
+     * @param Node[] $nodes         Array of Nodes to be printed
+     * @param bool   $trailingComma Whether to use a trailing comma
+     *
+     * @return string Comma separated pretty printed nodes in multiline style
+     */
+    protected function pCommaSeparatedMultiline(array $nodes, bool $trailingComma) : string {
+        $this->indent();
+
+        $result = '';
+        $lastIdx = count($nodes) - 1;
+        foreach ($nodes as $idx => $node) {
+            if ($node !== null) {
+                $comments = $node->getComments();
+                if ($comments) {
+                    $result .= $this->nl . $this->pComments($comments);
+                }
+
+                $result .= $this->nl . $this->p($node);
+            } else {
+                $result .= $this->nl;
+            }
+            if ($trailingComma || $idx !== $lastIdx) {
+                $result .= ',';
+            }
+        }
+
+        $this->outdent();
+        return $result;
+    }
+
+    /**
+     * Prints reformatted text of the passed comments.
+     *
+     * @param Comment[] $comments List of comments
+     *
+     * @return string Reformatted text of comments
+     */
+    protected function pComments(array $comments) : string {
+        $formattedComments = [];
+
+        foreach ($comments as $comment) {
+            $formattedComments[] = str_replace("\n", $this->nl, $comment->getReformattedText());
+        }
+
+        return implode($this->nl, $formattedComments);
+    }
+
+    /**
+     * Perform a format-preserving pretty print of an AST.
+     *
+     * The format preservation is best effort. For some changes to the AST the formatting will not
+     * be preserved (at least not locally).
+     *
+     * In order to use this method a number of prerequisites must be satisfied:
+     *  * The startTokenPos and endTokenPos attributes in the lexer must be enabled.
+     *  * The CloningVisitor must be run on the AST prior to modification.
+     *  * The original tokens must be provided, using the getTokens() method on the lexer.
+     *
+     * @param Node[] $stmts      Modified AST with links to original AST
+     * @param Node[] $origStmts  Original AST with token offset information
+     * @param array  $origTokens Tokens of the original code
+     *
+     * @return string
+     */
+    public function printFormatPreserving(array $stmts, array $origStmts, array $origTokens) : string {
+        $this->initializeNodeListDiffer();
+        $this->initializeLabelCharMap();
+        $this->initializeFixupMap();
+        $this->initializeRemovalMap();
+        $this->initializeInsertionMap();
+        $this->initializeListInsertionMap();
+        $this->initializeEmptyListInsertionMap();
+        $this->initializeModifierChangeMap();
+
+        $this->resetState();
+        $this->origTokens = new TokenStream($origTokens);
+
+        $this->preprocessNodes($stmts);
+
+        $pos = 0;
+        $result = $this->pArray($stmts, $origStmts, $pos, 0, 'File', 'stmts', null);
+        if (null !== $result) {
+            $result .= $this->origTokens->getTokenCode($pos, count($origTokens), 0);
+        } else {
+            // Fallback
+            // TODO Add <?php properly
+            $result = "<?php\n" . $this->pStmts($stmts, false);
+        }
+
+        return ltrim($this->handleMagicTokens($result));
+    }
+
+    protected function pFallback(Node $node) {
+        return $this->{'p' . $node->getType()}($node);
+    }
+
+    /**
+     * Pretty prints a node.
+     *
+     * This method also handles formatting preservation for nodes.
+     *
+     * @param Node $node Node to be pretty printed
+     * @param bool $parentFormatPreserved Whether parent node has preserved formatting
+     *
+     * @return string Pretty printed node
+     */
+    protected function p(Node $node, $parentFormatPreserved = false) : string {
+        // No orig tokens means this is a normal pretty print without preservation of formatting
+        if (!$this->origTokens) {
+            return $this->{'p' . $node->getType()}($node);
+        }
+
+        /** @var Node $origNode */
+        $origNode = $node->getAttribute('origNode');
+        if (null === $origNode) {
+            return $this->pFallback($node);
+        }
+
+        $class = \get_class($node);
+        \assert($class === \get_class($origNode));
+
+        $startPos = $origNode->getStartTokenPos();
+        $endPos = $origNode->getEndTokenPos();
+        \assert($startPos >= 0 && $endPos >= 0);
+
+        $fallbackNode = $node;
+        if ($node instanceof Expr\New_ && $node->class instanceof Stmt\Class_) {
+            // Normalize node structure of anonymous classes
+            $node = PrintableNewAnonClassNode::fromNewNode($node);
+            $origNode = PrintableNewAnonClassNode::fromNewNode($origNode);
+        }
+
+        // InlineHTML node does not contain closing and opening PHP tags. If the parent formatting
+        // is not preserved, then we need to use the fallback code to make sure the tags are
+        // printed.
+        if ($node instanceof Stmt\InlineHTML && !$parentFormatPreserved) {
+            return $this->pFallback($fallbackNode);
+        }
+
+        $indentAdjustment = $this->indentLevel - $this->origTokens->getIndentationBefore($startPos);
+
+        $type = $node->getType();
+        $fixupInfo = $this->fixupMap[$class] ?? null;
+
+        $result = '';
+        $pos = $startPos;
+        foreach ($node->getSubNodeNames() as $subNodeName) {
+            $subNode = $node->$subNodeName;
+            $origSubNode = $origNode->$subNodeName;
+
+            if ((!$subNode instanceof Node && $subNode !== null)
+                || (!$origSubNode instanceof Node && $origSubNode !== null)
+            ) {
+                if ($subNode === $origSubNode) {
+                    // Unchanged, can reuse old code
+                    continue;
+                }
+
+                if (is_array($subNode) && is_array($origSubNode)) {
+                    // Array subnode changed, we might be able to reconstruct it
+                    $listResult = $this->pArray(
+                        $subNode, $origSubNode, $pos, $indentAdjustment, $type, $subNodeName,
+                        $fixupInfo[$subNodeName] ?? null
+                    );
+                    if (null === $listResult) {
+                        return $this->pFallback($fallbackNode);
+                    }
+
+                    $result .= $listResult;
+                    continue;
+                }
+
+                if (is_int($subNode) && is_int($origSubNode)) {
+                    // Check if this is a modifier change
+                    $key = $type . '->' . $subNodeName;
+                    if (!isset($this->modifierChangeMap[$key])) {
+                        return $this->pFallback($fallbackNode);
+                    }
+
+                    $findToken = $this->modifierChangeMap[$key];
+                    $result .= $this->pModifiers($subNode);
+                    $pos = $this->origTokens->findRight($pos, $findToken);
+                    continue;
+                }
+
+                // If a non-node, non-array subnode changed, we don't be able to do a partial
+                // reconstructions, as we don't have enough offset information. Pretty print the
+                // whole node instead.
+                return $this->pFallback($fallbackNode);
+            }
+
+            $extraLeft = '';
+            $extraRight = '';
+            if ($origSubNode !== null) {
+                $subStartPos = $origSubNode->getStartTokenPos();
+                $subEndPos = $origSubNode->getEndTokenPos();
+                \assert($subStartPos >= 0 && $subEndPos >= 0);
+            } else {
+                if ($subNode === null) {
+                    // Both null, nothing to do
+                    continue;
+                }
+
+                // A node has been inserted, check if we have insertion information for it
+                $key = $type . '->' . $subNodeName;
+                if (!isset($this->insertionMap[$key])) {
+                    return $this->pFallback($fallbackNode);
+                }
+
+                list($findToken, $beforeToken, $extraLeft, $extraRight) = $this->insertionMap[$key];
+                if (null !== $findToken) {
+                    $subStartPos = $this->origTokens->findRight($pos, $findToken)
+                        + (int) !$beforeToken;
+                } else {
+                    $subStartPos = $pos;
+                }
+
+                if (null === $extraLeft && null !== $extraRight) {
+                    // If inserting on the right only, skipping whitespace looks better
+                    $subStartPos = $this->origTokens->skipRightWhitespace($subStartPos);
+                }
+                $subEndPos = $subStartPos - 1;
+            }
+
+            if (null === $subNode) {
+                // A node has been removed, check if we have removal information for it
+                $key = $type . '->' . $subNodeName;
+                if (!isset($this->removalMap[$key])) {
+                    return $this->pFallback($fallbackNode);
+                }
+
+                // Adjust positions to account for additional tokens that must be skipped
+                $removalInfo = $this->removalMap[$key];
+                if (isset($removalInfo['left'])) {
+                    $subStartPos = $this->origTokens->skipLeft($subStartPos - 1, $removalInfo['left']) + 1;
+                }
+                if (isset($removalInfo['right'])) {
+                    $subEndPos = $this->origTokens->skipRight($subEndPos + 1, $removalInfo['right']) - 1;
+                }
+            }
+
+            $result .= $this->origTokens->getTokenCode($pos, $subStartPos, $indentAdjustment);
+
+            if (null !== $subNode) {
+                $result .= $extraLeft;
+
+                $origIndentLevel = $this->indentLevel;
+                $this->setIndentLevel($this->origTokens->getIndentationBefore($subStartPos) + $indentAdjustment);
+
+                // If it's the same node that was previously in this position, it certainly doesn't
+                // need fixup. It's important to check this here, because our fixup checks are more
+                // conservative than strictly necessary.
+                if (isset($fixupInfo[$subNodeName])
+                    && $subNode->getAttribute('origNode') !== $origSubNode
+                ) {
+                    $fixup = $fixupInfo[$subNodeName];
+                    $res = $this->pFixup($fixup, $subNode, $class, $subStartPos, $subEndPos);
+                } else {
+                    $res = $this->p($subNode, true);
+                }
+
+                $this->safeAppend($result, $res);
+                $this->setIndentLevel($origIndentLevel);
+
+                $result .= $extraRight;
+            }
+
+            $pos = $subEndPos + 1;
+        }
+
+        $result .= $this->origTokens->getTokenCode($pos, $endPos + 1, $indentAdjustment);
+        return $result;
+    }
+
+    /**
+     * Perform a format-preserving pretty print of an array.
+     *
+     * @param array       $nodes            New nodes
+     * @param array       $origNodes        Original nodes
+     * @param int         $pos              Current token position (updated by reference)
+     * @param int         $indentAdjustment Adjustment for indentation
+     * @param string      $parentNodeType   Type of the containing node.
+     * @param string      $subNodeName      Name of array subnode.
+     * @param null|int    $fixup            Fixup information for array item nodes
+     *
+     * @return null|string Result of pretty print or null if cannot preserve formatting
+     */
+    protected function pArray(
+        array $nodes, array $origNodes, int &$pos, int $indentAdjustment,
+        string $parentNodeType, string $subNodeName, $fixup
+    ) {
+        $diff = $this->nodeListDiffer->diffWithReplacements($origNodes, $nodes);
+
+        $mapKey = $parentNodeType . '->' . $subNodeName;
+        $insertStr = $this->listInsertionMap[$mapKey] ?? null;
+        $isStmtList = $subNodeName === 'stmts';
+
+        $beforeFirstKeepOrReplace = true;
+        $skipRemovedNode = false;
+        $delayedAdd = [];
+        $lastElemIndentLevel = $this->indentLevel;
+
+        $insertNewline = false;
+        if ($insertStr === "\n") {
+            $insertStr = '';
+            $insertNewline = true;
+        }
+
+        if ($isStmtList && \count($origNodes) === 1 && \count($nodes) !== 1) {
+            $startPos = $origNodes[0]->getStartTokenPos();
+            $endPos = $origNodes[0]->getEndTokenPos();
+            \assert($startPos >= 0 && $endPos >= 0);
+            if (!$this->origTokens->haveBraces($startPos, $endPos)) {
+                // This was a single statement without braces, but either additional statements
+                // have been added, or the single statement has been removed. This requires the
+                // addition of braces. For now fall back.
+                // TODO: Try to preserve formatting
+                return null;
+            }
+        }
+
+        $result = '';
+        foreach ($diff as $i => $diffElem) {
+            $diffType = $diffElem->type;
+            /** @var Node|null $arrItem */
+            $arrItem = $diffElem->new;
+            /** @var Node|null $origArrItem */
+            $origArrItem = $diffElem->old;
+
+            if ($diffType === DiffElem::TYPE_KEEP || $diffType === DiffElem::TYPE_REPLACE) {
+                $beforeFirstKeepOrReplace = false;
+
+                if ($origArrItem === null || $arrItem === null) {
+                    // We can only handle the case where both are null
+                    if ($origArrItem === $arrItem) {
+                        continue;
+                    }
+                    return null;
+                }
+
+                if (!$arrItem instanceof Node || !$origArrItem instanceof Node) {
+                    // We can only deal with nodes. This can occur for Names, which use string arrays.
+                    return null;
+                }
+
+                $itemStartPos = $origArrItem->getStartTokenPos();
+                $itemEndPos = $origArrItem->getEndTokenPos();
+                \assert($itemStartPos >= 0 && $itemEndPos >= 0 && $itemStartPos >= $pos);
+
+                $origIndentLevel = $this->indentLevel;
+                $lastElemIndentLevel = $this->origTokens->getIndentationBefore($itemStartPos) + $indentAdjustment;
+                $this->setIndentLevel($lastElemIndentLevel);
+
+                $comments = $arrItem->getComments();
+                $origComments = $origArrItem->getComments();
+                $commentStartPos = $origComments ? $origComments[0]->getStartTokenPos() : $itemStartPos;
+                \assert($commentStartPos >= 0);
+
+                if ($commentStartPos < $pos) {
+                    // Comments may be assigned to multiple nodes if they start at the same position.
+                    // Make sure we don't try to print them multiple times.
+                    $commentStartPos = $itemStartPos;
+                }
+
+                if ($skipRemovedNode) {
+                    if ($isStmtList && $this->origTokens->haveBracesInRange($pos, $itemStartPos)) {
+                        // We'd remove the brace of a code block.
+                        // TODO: Preserve formatting.
+                        $this->setIndentLevel($origIndentLevel);
+                        return null;
+                    }
+                } else {
+                    $result .= $this->origTokens->getTokenCode(
+                        $pos, $commentStartPos, $indentAdjustment);
+                }
+
+                if (!empty($delayedAdd)) {
+                    /** @var Node $delayedAddNode */
+                    foreach ($delayedAdd as $delayedAddNode) {
+                        if ($insertNewline) {
+                            $delayedAddComments = $delayedAddNode->getComments();
+                            if ($delayedAddComments) {
+                                $result .= $this->pComments($delayedAddComments) . $this->nl;
+                            }
+                        }
+
+                        $this->safeAppend($result, $this->p($delayedAddNode, true));
+
+                        if ($insertNewline) {
+                            $result .= $insertStr . $this->nl;
+                        } else {
+                            $result .= $insertStr;
+                        }
+                    }
+
+                    $delayedAdd = [];
+                }
+
+                if ($comments !== $origComments) {
+                    if ($comments) {
+                        $result .= $this->pComments($comments) . $this->nl;
+                    }
+                } else {
+                    $result .= $this->origTokens->getTokenCode(
+                        $commentStartPos, $itemStartPos, $indentAdjustment);
+                }
+
+                // If we had to remove anything, we have done so now.
+                $skipRemovedNode = false;
+            } elseif ($diffType === DiffElem::TYPE_ADD) {
+                if (null === $insertStr) {
+                    // We don't have insertion information for this list type
+                    return null;
+                }
+
+                if ($insertStr === ', ' && $this->isMultiline($origNodes)) {
+                    $insertStr = ',';
+                    $insertNewline = true;
+                }
+
+                if ($beforeFirstKeepOrReplace) {
+                    // Will be inserted at the next "replace" or "keep" element
+                    $delayedAdd[] = $arrItem;
+                    continue;
+                }
+
+                $itemStartPos = $pos;
+                $itemEndPos = $pos - 1;
+
+                $origIndentLevel = $this->indentLevel;
+                $this->setIndentLevel($lastElemIndentLevel);
+
+                if ($insertNewline) {
+                    $comments = $arrItem->getComments();
+                    if ($comments) {
+                        $result .= $this->nl . $this->pComments($comments);
+                    }
+                    $result .= $insertStr . $this->nl;
+                } else {
+                    $result .= $insertStr;
+                }
+            } elseif ($diffType === DiffElem::TYPE_REMOVE) {
+                if (!$origArrItem instanceof Node) {
+                    // We only support removal for nodes
+                    return null;
+                }
+
+                $itemStartPos = $origArrItem->getStartTokenPos();
+                $itemEndPos = $origArrItem->getEndTokenPos();
+                \assert($itemStartPos >= 0 && $itemEndPos >= 0);
+
+                // Consider comments part of the node.
+                $origComments = $origArrItem->getComments();
+                if ($origComments) {
+                    $itemStartPos = $origComments[0]->getStartTokenPos();
+                }
+
+                if ($i === 0) {
+                    // If we're removing from the start, keep the tokens before the node and drop those after it,
+                    // instead of the other way around.
+                    $result .= $this->origTokens->getTokenCode(
+                        $pos, $itemStartPos, $indentAdjustment);
+                    $skipRemovedNode = true;
+                } else {
+                    if ($isStmtList && $this->origTokens->haveBracesInRange($pos, $itemStartPos)) {
+                        // We'd remove the brace of a code block.
+                        // TODO: Preserve formatting.
+                        return null;
+                    }
+                }
+
+                $pos = $itemEndPos + 1;
+                continue;
+            } else {
+                throw new \Exception("Shouldn't happen");
+            }
+
+            if (null !== $fixup && $arrItem->getAttribute('origNode') !== $origArrItem) {
+                $res = $this->pFixup($fixup, $arrItem, null, $itemStartPos, $itemEndPos);
+            } else {
+                $res = $this->p($arrItem, true);
+            }
+            $this->safeAppend($result, $res);
+
+            $this->setIndentLevel($origIndentLevel);
+            $pos = $itemEndPos + 1;
+        }
+
+        if ($skipRemovedNode) {
+            // TODO: Support removing single node.
+            return null;
+        }
+
+        if (!empty($delayedAdd)) {
+            if (!isset($this->emptyListInsertionMap[$mapKey])) {
+                return null;
+            }
+
+            list($findToken, $extraLeft, $extraRight) = $this->emptyListInsertionMap[$mapKey];
+            if (null !== $findToken) {
+                $insertPos = $this->origTokens->findRight($pos, $findToken) + 1;
+                $result .= $this->origTokens->getTokenCode($pos, $insertPos, $indentAdjustment);
+                $pos = $insertPos;
+            }
+
+            $first = true;
+            $result .= $extraLeft;
+            foreach ($delayedAdd as $delayedAddNode) {
+                if (!$first) {
+                    $result .= $insertStr;
+                }
+                $result .= $this->p($delayedAddNode, true);
+                $first = false;
+            }
+            $result .= $extraRight;
+        }
+
+        return $result;
+    }
+
+    /**
+     * Print node with fixups.
+     *
+     * Fixups here refer to the addition of extra parentheses, braces or other characters, that
+     * are required to preserve program semantics in a certain context (e.g. to maintain precedence
+     * or because only certain expressions are allowed in certain places).
+     *
+     * @param int         $fixup       Fixup type
+     * @param Node        $subNode     Subnode to print
+     * @param string|null $parentClass Class of parent node
+     * @param int         $subStartPos Original start pos of subnode
+     * @param int         $subEndPos   Original end pos of subnode
+     *
+     * @return string Result of fixed-up print of subnode
+     */
+    protected function pFixup(int $fixup, Node $subNode, $parentClass, int $subStartPos, int $subEndPos) : string {
+        switch ($fixup) {
+            case self::FIXUP_PREC_LEFT:
+            case self::FIXUP_PREC_RIGHT:
+                if (!$this->origTokens->haveParens($subStartPos, $subEndPos)) {
+                    list($precedence, $associativity) = $this->precedenceMap[$parentClass];
+                    return $this->pPrec($subNode, $precedence, $associativity,
+                        $fixup === self::FIXUP_PREC_LEFT ? -1 : 1);
+                }
+                break;
+            case self::FIXUP_CALL_LHS:
+                if ($this->callLhsRequiresParens($subNode)
+                    && !$this->origTokens->haveParens($subStartPos, $subEndPos)
+                ) {
+                    return '(' . $this->p($subNode) . ')';
+                }
+                break;
+            case self::FIXUP_DEREF_LHS:
+                if ($this->dereferenceLhsRequiresParens($subNode)
+                    && !$this->origTokens->haveParens($subStartPos, $subEndPos)
+                ) {
+                    return '(' . $this->p($subNode) . ')';
+                }
+                break;
+            case self::FIXUP_BRACED_NAME:
+            case self::FIXUP_VAR_BRACED_NAME:
+                if ($subNode instanceof Expr
+                    && !$this->origTokens->haveBraces($subStartPos, $subEndPos)
+                ) {
+                    return ($fixup === self::FIXUP_VAR_BRACED_NAME ? '$' : '')
+                        . '{' . $this->p($subNode) . '}';
+                }
+                break;
+            case self::FIXUP_ENCAPSED:
+                if (!$subNode instanceof Scalar\EncapsedStringPart
+                    && !$this->origTokens->haveBraces($subStartPos, $subEndPos)
+                ) {
+                    return '{' . $this->p($subNode) . '}';
+                }
+                break;
+            default:
+                throw new \Exception('Cannot happen');
+        }
+
+        // Nothing special to do
+        return $this->p($subNode);
+    }
+
+    /**
+     * Appends to a string, ensuring whitespace between label characters.
+     *
+     * Example: "echo" and "$x" result in "echo$x", but "echo" and "x" result in "echo x".
+     * Without safeAppend the result would be "echox", which does not preserve semantics.
+     *
+     * @param string $str
+     * @param string $append
+     */
+    protected function safeAppend(string &$str, string $append) {
+        if ($str === "") {
+            $str = $append;
+            return;
+        }
+
+        if ($append === "") {
+            return;
+        }
+
+        if (!$this->labelCharMap[$append[0]]
+                || !$this->labelCharMap[$str[\strlen($str) - 1]]) {
+            $str .= $append;
+        } else {
+            $str .= " " . $append;
+        }
+    }
+
+    /**
+     * Determines whether the LHS of a call must be wrapped in parenthesis.
+     *
+     * @param Node $node LHS of a call
+     *
+     * @return bool Whether parentheses are required
+     */
+    protected function callLhsRequiresParens(Node $node) : bool {
+        return !($node instanceof Node\Name
+            || $node instanceof Expr\Variable
+            || $node instanceof Expr\ArrayDimFetch
+            || $node instanceof Expr\FuncCall
+            || $node instanceof Expr\MethodCall
+            || $node instanceof Expr\NullsafeMethodCall
+            || $node instanceof Expr\StaticCall
+            || $node instanceof Expr\Array_);
+    }
+
+    /**
+     * Determines whether the LHS of a dereferencing operation must be wrapped in parenthesis.
+     *
+     * @param Node $node LHS of dereferencing operation
+     *
+     * @return bool Whether parentheses are required
+     */
+    protected function dereferenceLhsRequiresParens(Node $node) : bool {
+        return !($node instanceof Expr\Variable
+            || $node instanceof Node\Name
+            || $node instanceof Expr\ArrayDimFetch
+            || $node instanceof Expr\PropertyFetch
+            || $node instanceof Expr\NullsafePropertyFetch
+            || $node instanceof Expr\StaticPropertyFetch
+            || $node instanceof Expr\FuncCall
+            || $node instanceof Expr\MethodCall
+            || $node instanceof Expr\NullsafeMethodCall
+            || $node instanceof Expr\StaticCall
+            || $node instanceof Expr\Array_
+            || $node instanceof Scalar\String_
+            || $node instanceof Expr\ConstFetch
+            || $node instanceof Expr\ClassConstFetch);
+    }
+
+    /**
+     * Print modifiers, including trailing whitespace.
+     *
+     * @param int $modifiers Modifier mask to print
+     *
+     * @return string Printed modifiers
+     */
+    protected function pModifiers(int $modifiers) {
+        return ($modifiers & Stmt\Class_::MODIFIER_PUBLIC    ? 'public '    : '')
+             . ($modifiers & Stmt\Class_::MODIFIER_PROTECTED ? 'protected ' : '')
+             . ($modifiers & Stmt\Class_::MODIFIER_PRIVATE   ? 'private '   : '')
+             . ($modifiers & Stmt\Class_::MODIFIER_STATIC    ? 'static '    : '')
+             . ($modifiers & Stmt\Class_::MODIFIER_ABSTRACT  ? 'abstract '  : '')
+             . ($modifiers & Stmt\Class_::MODIFIER_FINAL     ? 'final '     : '');
+    }
+
+    /**
+     * Determine whether a list of nodes uses multiline formatting.
+     *
+     * @param (Node|null)[] $nodes Node list
+     *
+     * @return bool Whether multiline formatting is used
+     */
+    protected function isMultiline(array $nodes) : bool {
+        if (\count($nodes) < 2) {
+            return false;
+        }
+
+        $pos = -1;
+        foreach ($nodes as $node) {
+            if (null === $node) {
+                continue;
+            }
+
+            $endPos = $node->getEndTokenPos() + 1;
+            if ($pos >= 0) {
+                $text = $this->origTokens->getTokenCode($pos, $endPos, 0);
+                if (false === strpos($text, "\n")) {
+                    // We require that a newline is present between *every* item. If the formatting
+                    // is inconsistent, with only some items having newlines, we don't consider it
+                    // as multiline
+                    return false;
+                }
+            }
+            $pos = $endPos;
+        }
+
+        return true;
+    }
+
+    /**
+     * Lazily initializes label char map.
+     *
+     * The label char map determines whether a certain character may occur in a label.
+     */
+    protected function initializeLabelCharMap() {
+        if ($this->labelCharMap) return;
+
+        $this->labelCharMap = [];
+        for ($i = 0; $i < 256; $i++) {
+            // Since PHP 7.1 The lower range is 0x80. However, we also want to support code for
+            // older versions.
+            $this->labelCharMap[chr($i)] = $i >= 0x7f || ctype_alnum($i);
+        }
+    }
+
+    /**
+     * Lazily initializes node list differ.
+     *
+     * The node list differ is used to determine differences between two array subnodes.
+     */
+    protected function initializeNodeListDiffer() {
+        if ($this->nodeListDiffer) return;
+
+        $this->nodeListDiffer = new Internal\Differ(function ($a, $b) {
+            if ($a instanceof Node && $b instanceof Node) {
+                return $a === $b->getAttribute('origNode');
+            }
+            // Can happen for array destructuring
+            return $a === null && $b === null;
+        });
+    }
+
+    /**
+     * Lazily initializes fixup map.
+     *
+     * The fixup map is used to determine whether a certain subnode of a certain node may require
+     * some kind of "fixup" operation, e.g. the addition of parenthesis or braces.
+     */
+    protected function initializeFixupMap() {
+        if ($this->fixupMap) return;
+
+        $this->fixupMap = [
+            Expr\PreInc::class => ['var' => self::FIXUP_PREC_RIGHT],
+            Expr\PreDec::class => ['var' => self::FIXUP_PREC_RIGHT],
+            Expr\PostInc::class => ['var' => self::FIXUP_PREC_LEFT],
+            Expr\PostDec::class => ['var' => self::FIXUP_PREC_LEFT],
+            Expr\Instanceof_::class => [
+                'expr' => self::FIXUP_PREC_LEFT,
+                'class' => self::FIXUP_PREC_RIGHT, // TODO: FIXUP_NEW_VARIABLE
+            ],
+            Expr\Ternary::class => [
+                'cond' => self::FIXUP_PREC_LEFT,
+                'else' => self::FIXUP_PREC_RIGHT,
+            ],
+
+            Expr\FuncCall::class => ['name' => self::FIXUP_CALL_LHS],
+            Expr\StaticCall::class => ['class' => self::FIXUP_DEREF_LHS],
+            Expr\ArrayDimFetch::class => ['var' => self::FIXUP_DEREF_LHS],
+            Expr\ClassConstFetch::class => ['var' => self::FIXUP_DEREF_LHS],
+            Expr\New_::class => ['class' => self::FIXUP_DEREF_LHS], // TODO: FIXUP_NEW_VARIABLE
+            Expr\MethodCall::class => [
+                'var' => self::FIXUP_DEREF_LHS,
+                'name' => self::FIXUP_BRACED_NAME,
+            ],
+            Expr\NullsafeMethodCall::class => [
+                'var' => self::FIXUP_DEREF_LHS,
+                'name' => self::FIXUP_BRACED_NAME,
+            ],
+            Expr\StaticPropertyFetch::class => [
+                'class' => self::FIXUP_DEREF_LHS,
+                'name' => self::FIXUP_VAR_BRACED_NAME,
+            ],
+            Expr\PropertyFetch::class => [
+                'var' => self::FIXUP_DEREF_LHS,
+                'name' => self::FIXUP_BRACED_NAME,
+            ],
+            Expr\NullsafePropertyFetch::class => [
+                'var' => self::FIXUP_DEREF_LHS,
+                'name' => self::FIXUP_BRACED_NAME,
+            ],
+            Scalar\Encapsed::class => [
+                'parts' => self::FIXUP_ENCAPSED,
+            ],
+        ];
+
+        $binaryOps = [
+            BinaryOp\Pow::class, BinaryOp\Mul::class, BinaryOp\Div::class, BinaryOp\Mod::class,
+            BinaryOp\Plus::class, BinaryOp\Minus::class, BinaryOp\Concat::class,
+            BinaryOp\ShiftLeft::class, BinaryOp\ShiftRight::class, BinaryOp\Smaller::class,
+            BinaryOp\SmallerOrEqual::class, BinaryOp\Greater::class, BinaryOp\GreaterOrEqual::class,
+            BinaryOp\Equal::class, BinaryOp\NotEqual::class, BinaryOp\Identical::class,
+            BinaryOp\NotIdentical::class, BinaryOp\Spaceship::class, BinaryOp\BitwiseAnd::class,
+            BinaryOp\BitwiseXor::class, BinaryOp\BitwiseOr::class, BinaryOp\BooleanAnd::class,
+            BinaryOp\BooleanOr::class, BinaryOp\Coalesce::class, BinaryOp\LogicalAnd::class,
+            BinaryOp\LogicalXor::class, BinaryOp\LogicalOr::class,
+        ];
+        foreach ($binaryOps as $binaryOp) {
+            $this->fixupMap[$binaryOp] = [
+                'left' => self::FIXUP_PREC_LEFT,
+                'right' => self::FIXUP_PREC_RIGHT
+            ];
+        }
+
+        $assignOps = [
+            Expr\Assign::class, Expr\AssignRef::class, AssignOp\Plus::class, AssignOp\Minus::class,
+            AssignOp\Mul::class, AssignOp\Div::class, AssignOp\Concat::class, AssignOp\Mod::class,
+            AssignOp\BitwiseAnd::class, AssignOp\BitwiseOr::class, AssignOp\BitwiseXor::class,
+            AssignOp\ShiftLeft::class, AssignOp\ShiftRight::class, AssignOp\Pow::class, AssignOp\Coalesce::class
+        ];
+        foreach ($assignOps as $assignOp) {
+            $this->fixupMap[$assignOp] = [
+                'var' => self::FIXUP_PREC_LEFT,
+                'expr' => self::FIXUP_PREC_RIGHT,
+            ];
+        }
+
+        $prefixOps = [
+            Expr\BitwiseNot::class, Expr\BooleanNot::class, Expr\UnaryPlus::class, Expr\UnaryMinus::class,
+            Cast\Int_::class, Cast\Double::class, Cast\String_::class, Cast\Array_::class,
+            Cast\Object_::class, Cast\Bool_::class, Cast\Unset_::class, Expr\ErrorSuppress::class,
+            Expr\YieldFrom::class, Expr\Print_::class, Expr\Include_::class,
+        ];
+        foreach ($prefixOps as $prefixOp) {
+            $this->fixupMap[$prefixOp] = ['expr' => self::FIXUP_PREC_RIGHT];
+        }
+    }
+
+    /**
+     * Lazily initializes the removal map.
+     *
+     * The removal map is used to determine which additional tokens should be returned when a
+     * certain node is replaced by null.
+     */
+    protected function initializeRemovalMap() {
+        if ($this->removalMap) return;
+
+        $stripBoth = ['left' => \T_WHITESPACE, 'right' => \T_WHITESPACE];
+        $stripLeft = ['left' => \T_WHITESPACE];
+        $stripRight = ['right' => \T_WHITESPACE];
+        $stripDoubleArrow = ['right' => \T_DOUBLE_ARROW];
+        $stripColon = ['left' => ':'];
+        $stripEquals = ['left' => '='];
+        $this->removalMap = [
+            'Expr_ArrayDimFetch->dim' => $stripBoth,
+            'Expr_ArrayItem->key' => $stripDoubleArrow,
+            'Expr_ArrowFunction->returnType' => $stripColon,
+            'Expr_Closure->returnType' => $stripColon,
+            'Expr_Exit->expr' => $stripBoth,
+            'Expr_Ternary->if' => $stripBoth,
+            'Expr_Yield->key' => $stripDoubleArrow,
+            'Expr_Yield->value' => $stripBoth,
+            'Param->type' => $stripRight,
+            'Param->default' => $stripEquals,
+            'Stmt_Break->num' => $stripBoth,
+            'Stmt_Catch->var' => $stripLeft,
+            'Stmt_ClassMethod->returnType' => $stripColon,
+            'Stmt_Class->extends' => ['left' => \T_EXTENDS],
+            'Expr_PrintableNewAnonClass->extends' => ['left' => \T_EXTENDS],
+            'Stmt_Continue->num' => $stripBoth,
+            'Stmt_Foreach->keyVar' => $stripDoubleArrow,
+            'Stmt_Function->returnType' => $stripColon,
+            'Stmt_If->else' => $stripLeft,
+            'Stmt_Namespace->name' => $stripLeft,
+            'Stmt_Property->type' => $stripRight,
+            'Stmt_PropertyProperty->default' => $stripEquals,
+            'Stmt_Return->expr' => $stripBoth,
+            'Stmt_StaticVar->default' => $stripEquals,
+            'Stmt_TraitUseAdaptation_Alias->newName' => $stripLeft,
+            'Stmt_TryCatch->finally' => $stripLeft,
+            // 'Stmt_Case->cond': Replace with "default"
+            // 'Stmt_Class->name': Unclear what to do
+            // 'Stmt_Declare->stmts': Not a plain node
+            // 'Stmt_TraitUseAdaptation_Alias->newModifier': Not a plain node
+        ];
+    }
+
+    protected function initializeInsertionMap() {
+        if ($this->insertionMap) return;
+
+        // TODO: "yield" where both key and value are inserted doesn't work
+        // [$find, $beforeToken, $extraLeft, $extraRight]
+        $this->insertionMap = [
+            'Expr_ArrayDimFetch->dim' => ['[', false, null, null],
+            'Expr_ArrayItem->key' => [null, false, null, ' => '],
+            'Expr_ArrowFunction->returnType' => [')', false, ' : ', null],
+            'Expr_Closure->returnType' => [')', false, ' : ', null],
+            'Expr_Ternary->if' => ['?', false, ' ', ' '],
+            'Expr_Yield->key' => [\T_YIELD, false, null, ' => '],
+            'Expr_Yield->value' => [\T_YIELD, false, ' ', null],
+            'Param->type' => [null, false, null, ' '],
+            'Param->default' => [null, false, ' = ', null],
+            'Stmt_Break->num' => [\T_BREAK, false, ' ', null],
+            'Stmt_Catch->var' => [null, false, ' ', null],
+            'Stmt_ClassMethod->returnType' => [')', false, ' : ', null],
+            'Stmt_Class->extends' => [null, false, ' extends ', null],
+            'Expr_PrintableNewAnonClass->extends' => [null, ' extends ', null],
+            'Stmt_Continue->num' => [\T_CONTINUE, false, ' ', null],
+            'Stmt_Foreach->keyVar' => [\T_AS, false, null, ' => '],
+            'Stmt_Function->returnType' => [')', false, ' : ', null],
+            'Stmt_If->else' => [null, false, ' ', null],
+            'Stmt_Namespace->name' => [\T_NAMESPACE, false, ' ', null],
+            'Stmt_Property->type' => [\T_VARIABLE, true, null, ' '],
+            'Stmt_PropertyProperty->default' => [null, false, ' = ', null],
+            'Stmt_Return->expr' => [\T_RETURN, false, ' ', null],
+            'Stmt_StaticVar->default' => [null, false, ' = ', null],
+            //'Stmt_TraitUseAdaptation_Alias->newName' => [T_AS, false, ' ', null], // TODO
+            'Stmt_TryCatch->finally' => [null, false, ' ', null],
+
+            // 'Expr_Exit->expr': Complicated due to optional ()
+            // 'Stmt_Case->cond': Conversion from default to case
+            // 'Stmt_Class->name': Unclear
+            // 'Stmt_Declare->stmts': Not a proper node
+            // 'Stmt_TraitUseAdaptation_Alias->newModifier': Not a proper node
+        ];
+    }
+
+    protected function initializeListInsertionMap() {
+        if ($this->listInsertionMap) return;
+
+        $this->listInsertionMap = [
+            // special
+            //'Expr_ShellExec->parts' => '', // TODO These need to be treated more carefully
+            //'Scalar_Encapsed->parts' => '',
+            'Stmt_Catch->types' => '|',
+            'UnionType->types' => '|',
+            'Stmt_If->elseifs' => ' ',
+            'Stmt_TryCatch->catches' => ' ',
+
+            // comma-separated lists
+            'Expr_Array->items' => ', ',
+            'Expr_ArrowFunction->params' => ', ',
+            'Expr_Closure->params' => ', ',
+            'Expr_Closure->uses' => ', ',
+            'Expr_FuncCall->args' => ', ',
+            'Expr_Isset->vars' => ', ',
+            'Expr_List->items' => ', ',
+            'Expr_MethodCall->args' => ', ',
+            'Expr_NullsafeMethodCall->args' => ', ',
+            'Expr_New->args' => ', ',
+            'Expr_PrintableNewAnonClass->args' => ', ',
+            'Expr_StaticCall->args' => ', ',
+            'Stmt_ClassConst->consts' => ', ',
+            'Stmt_ClassMethod->params' => ', ',
+            'Stmt_Class->implements' => ', ',
+            'Expr_PrintableNewAnonClass->implements' => ', ',
+            'Stmt_Const->consts' => ', ',
+            'Stmt_Declare->declares' => ', ',
+            'Stmt_Echo->exprs' => ', ',
+            'Stmt_For->init' => ', ',
+            'Stmt_For->cond' => ', ',
+            'Stmt_For->loop' => ', ',
+            'Stmt_Function->params' => ', ',
+            'Stmt_Global->vars' => ', ',
+            'Stmt_GroupUse->uses' => ', ',
+            'Stmt_Interface->extends' => ', ',
+            'Stmt_Match->arms' => ', ',
+            'Stmt_Property->props' => ', ',
+            'Stmt_StaticVar->vars' => ', ',
+            'Stmt_TraitUse->traits' => ', ',
+            'Stmt_TraitUseAdaptation_Precedence->insteadof' => ', ',
+            'Stmt_Unset->vars' => ', ',
+            'Stmt_Use->uses' => ', ',
+            'MatchArm->conds' => ', ',
+            'AttributeGroup->attrs' => ', ',
+
+            // statement lists
+            'Expr_Closure->stmts' => "\n",
+            'Stmt_Case->stmts' => "\n",
+            'Stmt_Catch->stmts' => "\n",
+            'Stmt_Class->stmts' => "\n",
+            'Expr_PrintableNewAnonClass->stmts' => "\n",
+            'Stmt_Interface->stmts' => "\n",
+            'Stmt_Trait->stmts' => "\n",
+            'Stmt_ClassMethod->stmts' => "\n",
+            'Stmt_Declare->stmts' => "\n",
+            'Stmt_Do->stmts' => "\n",
+            'Stmt_ElseIf->stmts' => "\n",
+            'Stmt_Else->stmts' => "\n",
+            'Stmt_Finally->stmts' => "\n",
+            'Stmt_Foreach->stmts' => "\n",
+            'Stmt_For->stmts' => "\n",
+            'Stmt_Function->stmts' => "\n",
+            'Stmt_If->stmts' => "\n",
+            'Stmt_Namespace->stmts' => "\n",
+            'Stmt_Class->attrGroups' => "\n",
+            'Stmt_Interface->attrGroups' => "\n",
+            'Stmt_Trait->attrGroups' => "\n",
+            'Stmt_Function->attrGroups' => "\n",
+            'Stmt_ClassMethod->attrGroups' => "\n",
+            'Stmt_ClassConst->attrGroups' => "\n",
+            'Stmt_Property->attrGroups' => "\n",
+            'Expr_PrintableNewAnonClass->attrGroups' => ' ',
+            'Expr_Closure->attrGroups' => ' ',
+            'Expr_ArrowFunction->attrGroups' => ' ',
+            'Param->attrGroups' => ' ',
+            'Stmt_Switch->cases' => "\n",
+            'Stmt_TraitUse->adaptations' => "\n",
+            'Stmt_TryCatch->stmts' => "\n",
+            'Stmt_While->stmts' => "\n",
+
+            // dummy for top-level context
+            'File->stmts' => "\n",
+        ];
+    }
+
+    protected function initializeEmptyListInsertionMap() {
+        if ($this->emptyListInsertionMap) return;
+
+        // TODO Insertion into empty statement lists.
+
+        // [$find, $extraLeft, $extraRight]
+        $this->emptyListInsertionMap = [
+            'Expr_ArrowFunction->params' => ['(', '', ''],
+            'Expr_Closure->uses' => [')', ' use(', ')'],
+            'Expr_Closure->params' => ['(', '', ''],
+            'Expr_FuncCall->args' => ['(', '', ''],
+            'Expr_MethodCall->args' => ['(', '', ''],
+            'Expr_NullsafeMethodCall->args' => ['(', '', ''],
+            'Expr_New->args' => ['(', '', ''],
+            'Expr_PrintableNewAnonClass->args' => ['(', '', ''],
+            'Expr_PrintableNewAnonClass->implements' => [null, ' implements ', ''],
+            'Expr_StaticCall->args' => ['(', '', ''],
+            'Stmt_Class->implements' => [null, ' implements ', ''],
+            'Stmt_ClassMethod->params' => ['(', '', ''],
+            'Stmt_Interface->extends' => [null, ' extends ', ''],
+            'Stmt_Function->params' => ['(', '', ''],
+
+            /* These cannot be empty to start with:
+             * Expr_Isset->vars
+             * Stmt_Catch->types
+             * Stmt_Const->consts
+             * Stmt_ClassConst->consts
+             * Stmt_Declare->declares
+             * Stmt_Echo->exprs
+             * Stmt_Global->vars
+             * Stmt_GroupUse->uses
+             * Stmt_Property->props
+             * Stmt_StaticVar->vars
+             * Stmt_TraitUse->traits
+             * Stmt_TraitUseAdaptation_Precedence->insteadof
+             * Stmt_Unset->vars
+             * Stmt_Use->uses
+             * UnionType->types
+             */
+
+            /* TODO
+             * Stmt_If->elseifs
+             * Stmt_TryCatch->catches
+             * Expr_Array->items
+             * Expr_List->items
+             * Stmt_For->init
+             * Stmt_For->cond
+             * Stmt_For->loop
+             */
+        ];
+    }
+
+    protected function initializeModifierChangeMap() {
+        if ($this->modifierChangeMap) return;
+
+        $this->modifierChangeMap = [
+            'Stmt_ClassConst->flags' => \T_CONST,
+            'Stmt_ClassMethod->flags' => \T_FUNCTION,
+            'Stmt_Class->flags' => \T_CLASS,
+            'Stmt_Property->flags' => \T_VARIABLE,
+            'Param->flags' => \T_VARIABLE,
+            //'Stmt_TraitUseAdaptation_Alias->newModifier' => 0, // TODO
+        ];
+
+        // List of integer subnodes that are not modifiers:
+        // Expr_Include->type
+        // Stmt_GroupUse->type
+        // Stmt_Use->type
+        // Stmt_UseUse->type
+    }
+}
diff --git a/vendor/paragonie/constant_time_encoding/.gitignore b/vendor/paragonie/constant_time_encoding/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..e0caea8fce96645564e333191283920f3faf135b
--- /dev/null
+++ b/vendor/paragonie/constant_time_encoding/.gitignore
@@ -0,0 +1,2 @@
+.idea/
+vendor/
\ No newline at end of file
diff --git a/vendor/paragonie/constant_time_encoding/.travis.yml b/vendor/paragonie/constant_time_encoding/.travis.yml
new file mode 100644
index 0000000000000000000000000000000000000000..b97432319b353612033c845ca0dd1032ecd179ff
--- /dev/null
+++ b/vendor/paragonie/constant_time_encoding/.travis.yml
@@ -0,0 +1,23 @@
+language: php
+sudo: false
+
+matrix:
+  fast_finish: true
+  include:
+    - php: "7.0"
+    - php: "7.1"
+    - php: "7.2"
+    - php: "7.3"
+    - php: "7.4snapshot"
+    - php: "nightly"
+  allow_failures:
+    - php: "nightly"
+    - php: "7.4snapshot"
+
+install:
+    - composer self-update
+    - composer update
+
+script:
+    - vendor/bin/phpunit
+    - vendor/bin/psalm
diff --git a/vendor/paragonie/constant_time_encoding/LICENSE.txt b/vendor/paragonie/constant_time_encoding/LICENSE.txt
new file mode 100644
index 0000000000000000000000000000000000000000..7cb6fd8610a1c93ba155dda5a92b94439baf57be
--- /dev/null
+++ b/vendor/paragonie/constant_time_encoding/LICENSE.txt
@@ -0,0 +1,48 @@
+The MIT License (MIT)
+
+Copyright (c) 2016 - 2018 Paragon Initiative Enterprises
+
+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.
+
+------------------------------------------------------------------------------
+This library was based on the work of Steve "Sc00bz" Thomas.
+------------------------------------------------------------------------------
+
+The MIT License (MIT)
+
+Copyright (c) 2014 Steve Thomas
+
+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/paragonie/constant_time_encoding/README.md b/vendor/paragonie/constant_time_encoding/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..d7db2a2d071f470c4e8f21fa460ec4520499a236
--- /dev/null
+++ b/vendor/paragonie/constant_time_encoding/README.md
@@ -0,0 +1,84 @@
+# Constant-Time Encoding
+
+[![Build Status](https://travis-ci.org/paragonie/constant_time_encoding.svg?branch=master)](https://travis-ci.org/paragonie/constant_time_encoding)
+[![Latest Stable Version](https://poser.pugx.org/paragonie/constant_time_encoding/v/stable)](https://packagist.org/packages/paragonie/constant_time_encoding)
+[![Latest Unstable Version](https://poser.pugx.org/paragonie/constant_time_encoding/v/unstable)](https://packagist.org/packages/paragonie/constant_time_encoding)
+[![License](https://poser.pugx.org/paragonie/constant_time_encoding/license)](https://packagist.org/packages/paragonie/constant_time_encoding)
+[![Downloads](https://img.shields.io/packagist/dt/paragonie/constant_time_encoding.svg)](https://packagist.org/packages/paragonie/constant_time_encoding)
+
+Based on the [constant-time base64 implementation made by Steve "Sc00bz" Thomas](https://github.com/Sc00bz/ConstTimeEncoding),
+this library aims to offer character encoding functions that do not leak
+information about what you are encoding/decoding via processor cache 
+misses. Further reading on [cache-timing attacks](http://blog.ircmaxell.com/2014/11/its-all-about-time.html).
+
+Our fork offers the following enchancements:
+
+* `mbstring.func_overload` resistance
+* Unit tests
+* Composer- and Packagist-ready
+* Base16 encoding
+* Base32 encoding
+* Uses `pack()` and `unpack()` instead of `chr()` and `ord()`
+
+## PHP Version Requirements
+
+Version 2 of this library should work on **PHP 7** or newer. For PHP 5
+support, see [the v1.x branch](https://github.com/paragonie/constant_time_encoding/tree/v1.x).
+
+If you are adding this as a dependency to a project intended to work on both PHP 5 and PHP 7, please set the required version to `^1|^2` instead of just `^1` or `^2`.
+
+## How to Install
+
+```sh
+composer require paragonie/constant_time_encoding
+```
+
+## How to Use
+
+```php
+use \ParagonIE\ConstantTime\Encoding;
+
+// possibly (if applicable): 
+// require 'vendor/autoload.php';
+
+$data = random_bytes(32);
+echo Encoding::base64Encode($data), "\n";
+echo Encoding::base32EncodeUpper($data), "\n";
+echo Encoding::base32Encode($data), "\n";
+echo Encoding::hexEncode($data), "\n";
+echo Encoding::hexEncodeUpper($data), "\n";
+```
+
+Example output:
+ 
+```
+1VilPkeVqirlPifk5scbzcTTbMT2clp+Zkyv9VFFasE=
+2VMKKPSHSWVCVZJ6E7SONRY3ZXCNG3GE6ZZFU7TGJSX7KUKFNLAQ====
+2vmkkpshswvcvzj6e7sonry3zxcng3ge6zzfu7tgjsx7kukfnlaq====
+d558a53e4795aa2ae53e27e4e6c71bcdc4d36cc4f6725a7e664caff551456ac1
+D558A53E4795AA2AE53E27E4E6C71BDCC4D36CC4F6725A7E664CAFF551456AC1
+```
+
+If you only need a particular variant, you can just reference the 
+required class like so:
+
+```php
+use \ParagonIE\ConstantTime\Base64;
+use \ParagonIE\ConstantTime\Base32;
+
+$data = random_bytes(32);
+echo Base64::encode($data), "\n";
+echo Base32::encode($data), "\n";
+```
+
+Example output:
+
+```
+1VilPkeVqirlPifk5scbzcTTbMT2clp+Zkyv9VFFasE=
+2vmkkpshswvcvzj6e7sonry3zxcng3ge6zzfu7tgjsx7kukfnlaq====
+```
+
+## Support Contracts
+
+If your company uses this library in their products or services, you may be
+interested in [purchasing a support contract from Paragon Initiative Enterprises](https://paragonie.com/enterprise).
diff --git a/vendor/paragonie/constant_time_encoding/composer.json b/vendor/paragonie/constant_time_encoding/composer.json
new file mode 100644
index 0000000000000000000000000000000000000000..ac78c0412c002961c9a6f87fe30e949974056807
--- /dev/null
+++ b/vendor/paragonie/constant_time_encoding/composer.json
@@ -0,0 +1,51 @@
+{
+  "name": "paragonie/constant_time_encoding",
+  "description": "Constant-time Implementations of RFC 4648 Encoding (Base-64, Base-32, Base-16)",
+  "keywords": [
+    "base64",
+    "encoding",
+    "rfc4648",
+    "base32",
+    "base16",
+    "hex",
+    "bin2hex",
+    "hex2bin",
+    "base64_encode",
+    "base64_decode",
+    "base32_encode",
+    "base32_decode"
+  ],
+  "license": "MIT",
+  "type": "library",
+  "authors": [
+      {
+        "name":     "Paragon Initiative Enterprises",
+        "email":    "security@paragonie.com",
+        "homepage": "https://paragonie.com",
+        "role":     "Maintainer"
+      },
+      {
+        "name":     "Steve 'Sc00bz' Thomas",
+        "email":    "steve@tobtu.com",
+        "homepage": "https://www.tobtu.com",
+        "role":     "Original Developer"
+      }
+  ],
+  "support": {
+    "issues":   "https://github.com/paragonie/constant_time_encoding/issues",
+    "email":    "info@paragonie.com",
+    "source":   "https://github.com/paragonie/constant_time_encoding"
+  },
+  "require": {
+    "php": "^7|^8"
+  },
+  "require-dev": {
+    "phpunit/phpunit": "^6|^7",
+    "vimeo/psalm": "^1|^2|^3"
+  },
+  "autoload": {
+    "psr-4": {
+      "ParagonIE\\ConstantTime\\": "src/"
+    }
+  }
+}
diff --git a/vendor/paragonie/constant_time_encoding/phpunit.xml.dist b/vendor/paragonie/constant_time_encoding/phpunit.xml.dist
new file mode 100644
index 0000000000000000000000000000000000000000..a45b69237c5fe0e48ab514aa7088907044a2d4b3
--- /dev/null
+++ b/vendor/paragonie/constant_time_encoding/phpunit.xml.dist
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<phpunit backupGlobals="true"
+         backupStaticAttributes="false"
+         bootstrap="vendor/autoload.php"
+         colors="true"
+         convertErrorsToExceptions="true"
+         convertNoticesToExceptions="true"
+         convertWarningsToExceptions="true"
+         processIsolation="false"
+         stopOnError="false"
+         stopOnFailure="false"
+>
+    <testsuites>
+        <testsuite name="Constant Time Encoding Test Suite">
+            <directory suffix="Test.php">./tests</directory>
+        </testsuite>
+    </testsuites>
+    <filter>
+        <whitelist processUncoveredFilesFromWhitelist="true">
+            <directory suffix=".php">./src</directory>
+        </whitelist>
+    </filter>
+</phpunit>
\ No newline at end of file
diff --git a/vendor/paragonie/constant_time_encoding/psalm.xml b/vendor/paragonie/constant_time_encoding/psalm.xml
new file mode 100644
index 0000000000000000000000000000000000000000..0a17264b0547ca22d98033927c4e67be0a8dbad8
--- /dev/null
+++ b/vendor/paragonie/constant_time_encoding/psalm.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0"?>
+<psalm
+    useDocblockTypes="true"
+    totallyTyped="true"
+>
+    <projectFiles>
+        <directory name="src" />
+    </projectFiles>
+</psalm>
diff --git a/vendor/paragonie/constant_time_encoding/src/Base32.php b/vendor/paragonie/constant_time_encoding/src/Base32.php
new file mode 100644
index 0000000000000000000000000000000000000000..18c0ac9062870954b34c786ca9b3c4273fb06a09
--- /dev/null
+++ b/vendor/paragonie/constant_time_encoding/src/Base32.php
@@ -0,0 +1,471 @@
+<?php
+declare(strict_types=1);
+namespace ParagonIE\ConstantTime;
+
+/**
+ *  Copyright (c) 2016 - 2018 Paragon Initiative Enterprises.
+ *  Copyright (c) 2014 Steve "Sc00bz" Thomas (steve at tobtu dot com)
+ *
+ *  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.
+ */
+
+/**
+ * Class Base32
+ * [A-Z][2-7]
+ *
+ * @package ParagonIE\ConstantTime
+ */
+abstract class Base32 implements EncoderInterface
+{
+    /**
+     * Decode a Base32-encoded string into raw binary
+     *
+     * @param string $src
+     * @return string
+     * @throws \TypeError
+     */
+    public static function decode(string $src, bool $strictPadding = false): string
+    {
+        return static::doDecode($src, false, $strictPadding);
+    }
+
+    /**
+     * Decode an uppercase Base32-encoded string into raw binary
+     *
+     * @param string $src
+     * @return string
+     * @throws \TypeError
+     */
+    public static function decodeUpper(string $src, bool $strictPadding = false): string
+    {
+        return static::doDecode($src, true, $strictPadding);
+    }
+
+    /**
+     * Encode into Base32 (RFC 4648)
+     *
+     * @param string $src
+     * @return string
+     * @throws \TypeError
+     */
+    public static function encode(string $src): string
+    {
+        return static::doEncode($src, false, true);
+    }
+    /**
+     * Encode into Base32 (RFC 4648)
+     *
+     * @param string $src
+     * @return string
+     * @throws \TypeError
+     */
+    public static function encodeUnpadded(string $src): string
+    {
+        return static::doEncode($src, false, false);
+    }
+
+    /**
+     * Encode into uppercase Base32 (RFC 4648)
+     *
+     * @param string $src
+     * @return string
+     * @throws \TypeError
+     */
+    public static function encodeUpper(string $src): string
+    {
+        return static::doEncode($src, true, true);
+    }
+
+    /**
+     * Encode into uppercase Base32 (RFC 4648)
+     *
+     * @param string $src
+     * @return string
+     * @throws \TypeError
+     */
+    public static function encodeUpperUnpadded(string $src): string
+    {
+        return static::doEncode($src, true, false);
+    }
+
+    /**
+     * Uses bitwise operators instead of table-lookups to turn 5-bit integers
+     * into 8-bit integers.
+     *
+     * @param int $src
+     * @return int
+     */
+    protected static function decode5Bits(int $src): int
+    {
+        $ret = -1;
+
+        // if ($src > 96 && $src < 123) $ret += $src - 97 + 1; // -64
+        $ret += (((0x60 - $src) & ($src - 0x7b)) >> 8) & ($src - 96);
+
+        // if ($src > 0x31 && $src < 0x38) $ret += $src - 24 + 1; // -23
+        $ret += (((0x31 - $src) & ($src - 0x38)) >> 8) & ($src - 23);
+
+        return $ret;
+    }
+
+    /**
+     * Uses bitwise operators instead of table-lookups to turn 5-bit integers
+     * into 8-bit integers.
+     *
+     * Uppercase variant.
+     *
+     * @param int $src
+     * @return int
+     */
+    protected static function decode5BitsUpper(int $src): int
+    {
+        $ret = -1;
+
+        // if ($src > 64 && $src < 91) $ret += $src - 65 + 1; // -64
+        $ret += (((0x40 - $src) & ($src - 0x5b)) >> 8) & ($src - 64);
+
+        // if ($src > 0x31 && $src < 0x38) $ret += $src - 24 + 1; // -23
+        $ret += (((0x31 - $src) & ($src - 0x38)) >> 8) & ($src - 23);
+
+        return $ret;
+    }
+
+    /**
+     * Uses bitwise operators instead of table-lookups to turn 8-bit integers
+     * into 5-bit integers.
+     *
+     * @param int $src
+     * @return string
+     */
+    protected static function encode5Bits(int $src): string
+    {
+        $diff = 0x61;
+
+        // if ($src > 25) $ret -= 72;
+        $diff -= ((25 - $src) >> 8) & 73;
+
+        return \pack('C', $src + $diff);
+    }
+
+    /**
+     * Uses bitwise operators instead of table-lookups to turn 8-bit integers
+     * into 5-bit integers.
+     *
+     * Uppercase variant.
+     *
+     * @param int $src
+     * @return string
+     */
+    protected static function encode5BitsUpper(int $src): string
+    {
+        $diff = 0x41;
+
+        // if ($src > 25) $ret -= 40;
+        $diff -= ((25 - $src) >> 8) & 41;
+
+        return \pack('C', $src + $diff);
+    }
+
+
+    /**
+     * Base32 decoding
+     *
+     * @param string $src
+     * @param bool $upper
+     * @param bool $strictPadding
+     * @return string
+     * @throws \TypeError
+     * @psalm-suppress RedundantCondition
+     */
+    protected static function doDecode(string $src, bool $upper = false, bool $strictPadding = false): string
+    {
+        // We do this to reduce code duplication:
+        $method = $upper
+            ? 'decode5BitsUpper'
+            : 'decode5Bits';
+
+        // Remove padding
+        $srcLen = Binary::safeStrlen($src);
+        if ($srcLen === 0) {
+            return '';
+        }
+        if ($strictPadding) {
+            if (($srcLen & 7) === 0) {
+                for ($j = 0; $j < 7; ++$j) {
+                    if ($src[$srcLen - 1] === '=') {
+                        $srcLen--;
+                    } else {
+                        break;
+                    }
+                }
+            }
+            if (($srcLen & 7) === 1) {
+                throw new \RangeException(
+                    'Incorrect padding'
+                );
+            }
+        } else {
+            $src = \rtrim($src, '=');
+            $srcLen = Binary::safeStrlen($src);
+        }
+
+        $err = 0;
+        $dest = '';
+        // Main loop (no padding):
+        for ($i = 0; $i + 8 <= $srcLen; $i += 8) {
+            /** @var array<int, int> $chunk */
+            $chunk = \unpack('C*', Binary::safeSubstr($src, $i, 8));
+            /** @var int $c0 */
+            $c0 = static::$method($chunk[1]);
+            /** @var int $c1 */
+            $c1 = static::$method($chunk[2]);
+            /** @var int $c2 */
+            $c2 = static::$method($chunk[3]);
+            /** @var int $c3 */
+            $c3 = static::$method($chunk[4]);
+            /** @var int $c4 */
+            $c4 = static::$method($chunk[5]);
+            /** @var int $c5 */
+            $c5 = static::$method($chunk[6]);
+            /** @var int $c6 */
+            $c6 = static::$method($chunk[7]);
+            /** @var int $c7 */
+            $c7 = static::$method($chunk[8]);
+
+            $dest .= \pack(
+                'CCCCC',
+                (($c0 << 3) | ($c1 >> 2)             ) & 0xff,
+                (($c1 << 6) | ($c2 << 1) | ($c3 >> 4)) & 0xff,
+                (($c3 << 4) | ($c4 >> 1)             ) & 0xff,
+                (($c4 << 7) | ($c5 << 2) | ($c6 >> 3)) & 0xff,
+                (($c6 << 5) | ($c7     )             ) & 0xff
+            );
+            $err |= ($c0 | $c1 | $c2 | $c3 | $c4 | $c5 | $c6 | $c7) >> 8;
+        }
+        // The last chunk, which may have padding:
+        if ($i < $srcLen) {
+            /** @var array<int, int> $chunk */
+            $chunk = \unpack('C*', Binary::safeSubstr($src, $i, $srcLen - $i));
+            /** @var int $c0 */
+            $c0 = static::$method($chunk[1]);
+
+            if ($i + 6 < $srcLen) {
+                /** @var int $c1 */
+                $c1 = static::$method($chunk[2]);
+                /** @var int $c2 */
+                $c2 = static::$method($chunk[3]);
+                /** @var int $c3 */
+                $c3 = static::$method($chunk[4]);
+                /** @var int $c4 */
+                $c4 = static::$method($chunk[5]);
+                /** @var int $c5 */
+                $c5 = static::$method($chunk[6]);
+                /** @var int $c6 */
+                $c6 = static::$method($chunk[7]);
+
+                $dest .= \pack(
+                    'CCCC',
+                    (($c0 << 3) | ($c1 >> 2)             ) & 0xff,
+                    (($c1 << 6) | ($c2 << 1) | ($c3 >> 4)) & 0xff,
+                    (($c3 << 4) | ($c4 >> 1)             ) & 0xff,
+                    (($c4 << 7) | ($c5 << 2) | ($c6 >> 3)) & 0xff
+                );
+                $err |= ($c0 | $c1 | $c2 | $c3 | $c4 | $c5 | $c6) >> 8;
+            } elseif ($i + 5 < $srcLen) {
+                /** @var int $c1 */
+                $c1 = static::$method($chunk[2]);
+                /** @var int $c2 */
+                $c2 = static::$method($chunk[3]);
+                /** @var int $c3 */
+                $c3 = static::$method($chunk[4]);
+                /** @var int $c4 */
+                $c4 = static::$method($chunk[5]);
+                /** @var int $c5 */
+                $c5 = static::$method($chunk[6]);
+
+                $dest .= \pack(
+                    'CCCC',
+                    (($c0 << 3) | ($c1 >> 2)             ) & 0xff,
+                    (($c1 << 6) | ($c2 << 1) | ($c3 >> 4)) & 0xff,
+                    (($c3 << 4) | ($c4 >> 1)             ) & 0xff,
+                    (($c4 << 7) | ($c5 << 2)             ) & 0xff
+                );
+                $err |= ($c0 | $c1 | $c2 | $c3 | $c4 | $c5) >> 8;
+            } elseif ($i + 4 < $srcLen) {
+                /** @var int $c1 */
+                $c1 = static::$method($chunk[2]);
+                /** @var int $c2 */
+                $c2 = static::$method($chunk[3]);
+                /** @var int $c3 */
+                $c3 = static::$method($chunk[4]);
+                /** @var int $c4 */
+                $c4 = static::$method($chunk[5]);
+
+                $dest .= \pack(
+                    'CCC',
+                    (($c0 << 3) | ($c1 >> 2)             ) & 0xff,
+                    (($c1 << 6) | ($c2 << 1) | ($c3 >> 4)) & 0xff,
+                    (($c3 << 4) | ($c4 >> 1)             ) & 0xff
+                );
+                $err |= ($c0 | $c1 | $c2 | $c3 | $c4) >> 8;
+            } elseif ($i + 3 < $srcLen) {
+                /** @var int $c1 */
+                $c1 = static::$method($chunk[2]);
+                /** @var int $c2 */
+                $c2 = static::$method($chunk[3]);
+                /** @var int $c3 */
+                $c3 = static::$method($chunk[4]);
+
+                $dest .= \pack(
+                    'CC',
+                    (($c0 << 3) | ($c1 >> 2)             ) & 0xff,
+                    (($c1 << 6) | ($c2 << 1) | ($c3 >> 4)) & 0xff
+                );
+                $err |= ($c0 | $c1 | $c2 | $c3) >> 8;
+            } elseif ($i + 2 < $srcLen) {
+                /** @var int $c1 */
+                $c1 = static::$method($chunk[2]);
+                /** @var int $c2 */
+                $c2 = static::$method($chunk[3]);
+
+                $dest .= \pack(
+                    'CC',
+                    (($c0 << 3) | ($c1 >> 2)             ) & 0xff,
+                    (($c1 << 6) | ($c2 << 1)             ) & 0xff
+                );
+                $err |= ($c0 | $c1 | $c2) >> 8;
+            } elseif ($i + 1 < $srcLen) {
+                /** @var int $c1 */
+                $c1 = static::$method($chunk[2]);
+
+                $dest .= \pack(
+                    'C',
+                    (($c0 << 3) | ($c1 >> 2)             ) & 0xff
+                );
+                $err |= ($c0 | $c1) >> 8;
+            } else {
+                $dest .= \pack(
+                    'C',
+                    (($c0 << 3)                          ) & 0xff
+                );
+                $err |= ($c0) >> 8;
+            }
+        }
+        /** @var bool $check */
+        $check = ($err === 0);
+        if (!$check) {
+            throw new \RangeException(
+                'Base32::doDecode() only expects characters in the correct base32 alphabet'
+            );
+        }
+        return $dest;
+    }
+
+    /**
+     * Base32 Encoding
+     *
+     * @param string $src
+     * @param bool $upper
+     * @param bool $pad
+     * @return string
+     * @throws \TypeError
+     */
+    protected static function doEncode(string $src, bool $upper = false, $pad = true): string
+    {
+        // We do this to reduce code duplication:
+        $method = $upper
+            ? 'encode5BitsUpper'
+            : 'encode5Bits';
+        
+        $dest = '';
+        $srcLen = Binary::safeStrlen($src);
+
+        // Main loop (no padding):
+        for ($i = 0; $i + 5 <= $srcLen; $i += 5) {
+            /** @var array<int, int> $chunk */
+            $chunk = \unpack('C*', Binary::safeSubstr($src, $i, 5));
+            $b0 = $chunk[1];
+            $b1 = $chunk[2];
+            $b2 = $chunk[3];
+            $b3 = $chunk[4];
+            $b4 = $chunk[5];
+            $dest .=
+                static::$method(              ($b0 >> 3)  & 31) .
+                static::$method((($b0 << 2) | ($b1 >> 6)) & 31) .
+                static::$method((($b1 >> 1)             ) & 31) .
+                static::$method((($b1 << 4) | ($b2 >> 4)) & 31) .
+                static::$method((($b2 << 1) | ($b3 >> 7)) & 31) .
+                static::$method((($b3 >> 2)             ) & 31) .
+                static::$method((($b3 << 3) | ($b4 >> 5)) & 31) .
+                static::$method(  $b4                     & 31);
+        }
+        // The last chunk, which may have padding:
+        if ($i < $srcLen) {
+            /** @var array<int, int> $chunk */
+            $chunk = \unpack('C*', Binary::safeSubstr($src, $i, $srcLen - $i));
+            $b0 = $chunk[1];
+            if ($i + 3 < $srcLen) {
+                $b1 = $chunk[2];
+                $b2 = $chunk[3];
+                $b3 = $chunk[4];
+                $dest .=
+                    static::$method(              ($b0 >> 3)  & 31) .
+                    static::$method((($b0 << 2) | ($b1 >> 6)) & 31) .
+                    static::$method((($b1 >> 1)             ) & 31) .
+                    static::$method((($b1 << 4) | ($b2 >> 4)) & 31) .
+                    static::$method((($b2 << 1) | ($b3 >> 7)) & 31) .
+                    static::$method((($b3 >> 2)             ) & 31) .
+                    static::$method((($b3 << 3)             ) & 31);
+                if ($pad) {
+                    $dest .= '=';
+                }
+            } elseif ($i + 2 < $srcLen) {
+                $b1 = $chunk[2];
+                $b2 = $chunk[3];
+                $dest .=
+                    static::$method(              ($b0 >> 3)  & 31) .
+                    static::$method((($b0 << 2) | ($b1 >> 6)) & 31) .
+                    static::$method((($b1 >> 1)             ) & 31) .
+                    static::$method((($b1 << 4) | ($b2 >> 4)) & 31) .
+                    static::$method((($b2 << 1)             ) & 31);
+                if ($pad) {
+                    $dest .= '===';
+                }
+            } elseif ($i + 1 < $srcLen) {
+                $b1 = $chunk[2];
+                $dest .=
+                    static::$method(              ($b0 >> 3)  & 31) .
+                    static::$method((($b0 << 2) | ($b1 >> 6)) & 31) .
+                    static::$method((($b1 >> 1)             ) & 31) .
+                    static::$method((($b1 << 4)             ) & 31);
+                if ($pad) {
+                    $dest .= '====';
+                }
+            } else {
+                $dest .=
+                    static::$method(              ($b0 >> 3)  & 31) .
+                    static::$method( ($b0 << 2)               & 31);
+                if ($pad) {
+                    $dest .= '======';
+                }
+            }
+        }
+        return $dest;
+    }
+}
diff --git a/vendor/paragonie/constant_time_encoding/src/Base32Hex.php b/vendor/paragonie/constant_time_encoding/src/Base32Hex.php
new file mode 100644
index 0000000000000000000000000000000000000000..68fdad52c8941e563ae489d4123bd4802151d325
--- /dev/null
+++ b/vendor/paragonie/constant_time_encoding/src/Base32Hex.php
@@ -0,0 +1,111 @@
+<?php
+declare(strict_types=1);
+namespace ParagonIE\ConstantTime;
+
+/**
+ *  Copyright (c) 2016 - 2018 Paragon Initiative Enterprises.
+ *  Copyright (c) 2014 Steve "Sc00bz" Thomas (steve at tobtu dot com)
+ *
+ *  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.
+ */
+
+/**
+ * Class Base32Hex
+ * [0-9][A-V]
+ *
+ * @package ParagonIE\ConstantTime
+ */
+abstract class Base32Hex extends Base32
+{
+    /**
+     * Uses bitwise operators instead of table-lookups to turn 5-bit integers
+     * into 8-bit integers.
+     *
+     * @param int $src
+     * @return int
+     */
+    protected static function decode5Bits(int $src): int
+    {
+        $ret = -1;
+
+        // if ($src > 0x30 && $src < 0x3a) ret += $src - 0x2e + 1; // -47
+        $ret += (((0x2f - $src) & ($src - 0x3a)) >> 8) & ($src - 47);
+
+        // if ($src > 0x60 && $src < 0x77) ret += $src - 0x61 + 10 + 1; // -86
+        $ret += (((0x60 - $src) & ($src - 0x77)) >> 8) & ($src - 86);
+
+        return $ret;
+    }
+
+    /**
+     * Uses bitwise operators instead of table-lookups to turn 5-bit integers
+     * into 8-bit integers.
+     *
+     * @param int $src
+     * @return int
+     */
+    protected static function decode5BitsUpper(int $src): int
+    {
+        $ret = -1;
+
+        // if ($src > 0x30 && $src < 0x3a) ret += $src - 0x2e + 1; // -47
+        $ret += (((0x2f - $src) & ($src - 0x3a)) >> 8) & ($src - 47);
+
+        // if ($src > 0x40 && $src < 0x57) ret += $src - 0x41 + 10 + 1; // -54
+        $ret += (((0x40 - $src) & ($src - 0x57)) >> 8) & ($src - 54);
+
+        return $ret;
+    }
+
+    /**
+     * Uses bitwise operators instead of table-lookups to turn 8-bit integers
+     * into 5-bit integers.
+     *
+     * @param int $src
+     * @return string
+     */
+    protected static function encode5Bits(int $src): string
+    {
+        $src += 0x30;
+
+        // if ($src > 0x39) $src += 0x61 - 0x3a; // 39
+        $src += ((0x39 - $src) >> 8) & 39;
+
+        return \pack('C', $src);
+    }
+
+    /**
+     * Uses bitwise operators instead of table-lookups to turn 8-bit integers
+     * into 5-bit integers.
+     *
+     * Uppercase variant.
+     *
+     * @param int $src
+     * @return string
+     */
+    protected static function encode5BitsUpper(int $src): string
+    {
+        $src += 0x30;
+
+        // if ($src > 0x39) $src += 0x41 - 0x3a; // 7
+        $src += ((0x39 - $src) >> 8) & 7;
+
+        return \pack('C', $src);
+    }
+}
\ No newline at end of file
diff --git a/vendor/paragonie/constant_time_encoding/src/Base64.php b/vendor/paragonie/constant_time_encoding/src/Base64.php
new file mode 100644
index 0000000000000000000000000000000000000000..b806909f208e294ffdec867445cc9dc8e7acdc83
--- /dev/null
+++ b/vendor/paragonie/constant_time_encoding/src/Base64.php
@@ -0,0 +1,271 @@
+<?php
+declare(strict_types=1);
+namespace ParagonIE\ConstantTime;
+
+/**
+ *  Copyright (c) 2016 - 2018 Paragon Initiative Enterprises.
+ *  Copyright (c) 2014 Steve "Sc00bz" Thomas (steve at tobtu dot com)
+ *
+ *  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.
+ */
+
+/**
+ * Class Base64
+ * [A-Z][a-z][0-9]+/
+ *
+ * @package ParagonIE\ConstantTime
+ */
+abstract class Base64 implements EncoderInterface
+{
+    /**
+     * Encode into Base64
+     *
+     * Base64 character set "[A-Z][a-z][0-9]+/"
+     *
+     * @param string $src
+     * @return string
+     * @throws \TypeError
+     */
+    public static function encode(string $src): string
+    {
+        return static::doEncode($src, true);
+    }
+
+    /**
+     * Encode into Base64, no = padding
+     *
+     * Base64 character set "[A-Z][a-z][0-9]+/"
+     *
+     * @param string $src
+     * @return string
+     * @throws \TypeError
+     */
+    public static function encodeUnpadded(string $src): string
+    {
+        return static::doEncode($src, false);
+    }
+
+    /**
+     * @param string $src
+     * @param bool $pad   Include = padding?
+     * @return string
+     * @throws \TypeError
+     */
+    protected static function doEncode(string $src, bool $pad = true): string
+    {
+        $dest = '';
+        $srcLen = Binary::safeStrlen($src);
+        // Main loop (no padding):
+        for ($i = 0; $i + 3 <= $srcLen; $i += 3) {
+            /** @var array<int, int> $chunk */
+            $chunk = \unpack('C*', Binary::safeSubstr($src, $i, 3));
+            $b0 = $chunk[1];
+            $b1 = $chunk[2];
+            $b2 = $chunk[3];
+
+            $dest .=
+                static::encode6Bits(               $b0 >> 2       ) .
+                static::encode6Bits((($b0 << 4) | ($b1 >> 4)) & 63) .
+                static::encode6Bits((($b1 << 2) | ($b2 >> 6)) & 63) .
+                static::encode6Bits(  $b2                     & 63);
+        }
+        // The last chunk, which may have padding:
+        if ($i < $srcLen) {
+            /** @var array<int, int> $chunk */
+            $chunk = \unpack('C*', Binary::safeSubstr($src, $i, $srcLen - $i));
+            $b0 = $chunk[1];
+            if ($i + 1 < $srcLen) {
+                $b1 = $chunk[2];
+                $dest .=
+                    static::encode6Bits($b0 >> 2) .
+                    static::encode6Bits((($b0 << 4) | ($b1 >> 4)) & 63) .
+                    static::encode6Bits(($b1 << 2) & 63);
+                if ($pad) {
+                    $dest .= '=';
+                }
+            } else {
+                $dest .=
+                    static::encode6Bits( $b0 >> 2) .
+                    static::encode6Bits(($b0 << 4) & 63);
+                if ($pad) {
+                    $dest .= '==';
+                }
+            }
+        }
+        return $dest;
+    }
+
+    /**
+     * decode from base64 into binary
+     *
+     * Base64 character set "./[A-Z][a-z][0-9]"
+     *
+     * @param string $src
+     * @param bool $strictPadding
+     * @return string
+     * @throws \RangeException
+     * @throws \TypeError
+     * @psalm-suppress RedundantCondition
+     */
+    public static function decode(string $src, bool $strictPadding = false): string
+    {
+        // Remove padding
+        $srcLen = Binary::safeStrlen($src);
+        if ($srcLen === 0) {
+            return '';
+        }
+
+        if ($strictPadding) {
+            if (($srcLen & 3) === 0) {
+                if ($src[$srcLen - 1] === '=') {
+                    $srcLen--;
+                    if ($src[$srcLen - 1] === '=') {
+                        $srcLen--;
+                    }
+                }
+            }
+            if (($srcLen & 3) === 1) {
+                throw new \RangeException(
+                    'Incorrect padding'
+                );
+            }
+            if ($src[$srcLen - 1] === '=') {
+                throw new \RangeException(
+                    'Incorrect padding'
+                );
+            }
+        } else {
+            $src = \rtrim($src, '=');
+            $srcLen = Binary::safeStrlen($src);
+        }
+
+        $err = 0;
+        $dest = '';
+        // Main loop (no padding):
+        for ($i = 0; $i + 4 <= $srcLen; $i += 4) {
+            /** @var array<int, int> $chunk */
+            $chunk = \unpack('C*', Binary::safeSubstr($src, $i, 4));
+            $c0 = static::decode6Bits($chunk[1]);
+            $c1 = static::decode6Bits($chunk[2]);
+            $c2 = static::decode6Bits($chunk[3]);
+            $c3 = static::decode6Bits($chunk[4]);
+
+            $dest .= \pack(
+                'CCC',
+                ((($c0 << 2) | ($c1 >> 4)) & 0xff),
+                ((($c1 << 4) | ($c2 >> 2)) & 0xff),
+                ((($c2 << 6) |  $c3      ) & 0xff)
+            );
+            $err |= ($c0 | $c1 | $c2 | $c3) >> 8;
+        }
+        // The last chunk, which may have padding:
+        if ($i < $srcLen) {
+            /** @var array<int, int> $chunk */
+            $chunk = \unpack('C*', Binary::safeSubstr($src, $i, $srcLen - $i));
+            $c0 = static::decode6Bits($chunk[1]);
+
+            if ($i + 2 < $srcLen) {
+                $c1 = static::decode6Bits($chunk[2]);
+                $c2 = static::decode6Bits($chunk[3]);
+                $dest .= \pack(
+                    'CC',
+                    ((($c0 << 2) | ($c1 >> 4)) & 0xff),
+                    ((($c1 << 4) | ($c2 >> 2)) & 0xff)
+                );
+                $err |= ($c0 | $c1 | $c2) >> 8;
+            } elseif ($i + 1 < $srcLen) {
+                $c1 = static::decode6Bits($chunk[2]);
+                $dest .= \pack(
+                    'C',
+                    ((($c0 << 2) | ($c1 >> 4)) & 0xff)
+                );
+                $err |= ($c0 | $c1) >> 8;
+            } elseif ($i < $srcLen && $strictPadding) {
+                $err |= 1;
+            }
+        }
+        /** @var bool $check */
+        $check = ($err === 0);
+        if (!$check) {
+            throw new \RangeException(
+                'Base64::decode() only expects characters in the correct base64 alphabet'
+            );
+        }
+        return $dest;
+    }
+
+    /**
+     * Uses bitwise operators instead of table-lookups to turn 6-bit integers
+     * into 8-bit integers.
+     *
+     * Base64 character set:
+     * [A-Z]      [a-z]      [0-9]      +     /
+     * 0x41-0x5a, 0x61-0x7a, 0x30-0x39, 0x2b, 0x2f
+     *
+     * @param int $src
+     * @return int
+     */
+    protected static function decode6Bits(int $src): int
+    {
+        $ret = -1;
+
+        // if ($src > 0x40 && $src < 0x5b) $ret += $src - 0x41 + 1; // -64
+        $ret += (((0x40 - $src) & ($src - 0x5b)) >> 8) & ($src - 64);
+
+        // if ($src > 0x60 && $src < 0x7b) $ret += $src - 0x61 + 26 + 1; // -70
+        $ret += (((0x60 - $src) & ($src - 0x7b)) >> 8) & ($src - 70);
+
+        // if ($src > 0x2f && $src < 0x3a) $ret += $src - 0x30 + 52 + 1; // 5
+        $ret += (((0x2f - $src) & ($src - 0x3a)) >> 8) & ($src + 5);
+
+        // if ($src == 0x2b) $ret += 62 + 1;
+        $ret += (((0x2a - $src) & ($src - 0x2c)) >> 8) & 63;
+
+        // if ($src == 0x2f) ret += 63 + 1;
+        $ret += (((0x2e - $src) & ($src - 0x30)) >> 8) & 64;
+
+        return $ret;
+    }
+
+    /**
+     * Uses bitwise operators instead of table-lookups to turn 8-bit integers
+     * into 6-bit integers.
+     *
+     * @param int $src
+     * @return string
+     */
+    protected static function encode6Bits(int $src): string
+    {
+        $diff = 0x41;
+
+        // if ($src > 25) $diff += 0x61 - 0x41 - 26; // 6
+        $diff += ((25 - $src) >> 8) & 6;
+
+        // if ($src > 51) $diff += 0x30 - 0x61 - 26; // -75
+        $diff -= ((51 - $src) >> 8) & 75;
+
+        // if ($src > 61) $diff += 0x2b - 0x30 - 10; // -15
+        $diff -= ((61 - $src) >> 8) & 15;
+
+        // if ($src > 62) $diff += 0x2f - 0x2b - 1; // 3
+        $diff += ((62 - $src) >> 8) & 3;
+
+        return \pack('C', $src + $diff);
+    }
+}
diff --git a/vendor/paragonie/constant_time_encoding/src/Base64DotSlash.php b/vendor/paragonie/constant_time_encoding/src/Base64DotSlash.php
new file mode 100644
index 0000000000000000000000000000000000000000..8ad2e2bf155c773207a818acf4c01892bdaac3e1
--- /dev/null
+++ b/vendor/paragonie/constant_time_encoding/src/Base64DotSlash.php
@@ -0,0 +1,88 @@
+<?php
+declare(strict_types=1);
+namespace ParagonIE\ConstantTime;
+
+/**
+ *  Copyright (c) 2016 - 2018 Paragon Initiative Enterprises.
+ *  Copyright (c) 2014 Steve "Sc00bz" Thomas (steve at tobtu dot com)
+ *
+ *  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.
+ */
+
+/**
+ * Class Base64DotSlash
+ * ./[A-Z][a-z][0-9]
+ *
+ * @package ParagonIE\ConstantTime
+ */
+abstract class Base64DotSlash extends Base64
+{
+    /**
+     * Uses bitwise operators instead of table-lookups to turn 6-bit integers
+     * into 8-bit integers.
+     *
+     * Base64 character set:
+     * ./         [A-Z]      [a-z]     [0-9]
+     * 0x2e-0x2f, 0x41-0x5a, 0x61-0x7a, 0x30-0x39
+     *
+     * @param int $src
+     * @return int
+     */
+    protected static function decode6Bits(int $src): int
+    {
+        $ret = -1;
+
+        // if ($src > 0x2d && $src < 0x30) ret += $src - 0x2e + 1; // -45
+        $ret += (((0x2d - $src) & ($src - 0x30)) >> 8) & ($src - 45);
+
+        // if ($src > 0x40 && $src < 0x5b) ret += $src - 0x41 + 2 + 1; // -62
+        $ret += (((0x40 - $src) & ($src - 0x5b)) >> 8) & ($src - 62);
+
+        // if ($src > 0x60 && $src < 0x7b) ret += $src - 0x61 + 28 + 1; // -68
+        $ret += (((0x60 - $src) & ($src - 0x7b)) >> 8) & ($src - 68);
+
+        // if ($src > 0x2f && $src < 0x3a) ret += $src - 0x30 + 54 + 1; // 7
+        $ret += (((0x2f - $src) & ($src - 0x3a)) >> 8) & ($src + 7);
+
+        return $ret;
+    }
+
+    /**
+     * Uses bitwise operators instead of table-lookups to turn 8-bit integers
+     * into 6-bit integers.
+     *
+     * @param int $src
+     * @return string
+     */
+    protected static function encode6Bits(int $src): string
+    {
+        $src += 0x2e;
+
+        // if ($src > 0x2f) $src += 0x41 - 0x30; // 17
+        $src += ((0x2f - $src) >> 8) & 17;
+
+        // if ($src > 0x5a) $src += 0x61 - 0x5b; // 6
+        $src += ((0x5a - $src) >> 8) & 6;
+
+        // if ($src > 0x7a) $src += 0x30 - 0x7b; // -75
+        $src -= ((0x7a - $src) >> 8) & 75;
+
+        return \pack('C', $src);
+    }
+}
diff --git a/vendor/paragonie/constant_time_encoding/src/Base64DotSlashOrdered.php b/vendor/paragonie/constant_time_encoding/src/Base64DotSlashOrdered.php
new file mode 100644
index 0000000000000000000000000000000000000000..dd1459e8508ff864cfa4191ccbc9ee2de6c42e11
--- /dev/null
+++ b/vendor/paragonie/constant_time_encoding/src/Base64DotSlashOrdered.php
@@ -0,0 +1,82 @@
+<?php
+declare(strict_types=1);
+namespace ParagonIE\ConstantTime;
+
+/**
+ *  Copyright (c) 2016 - 2018 Paragon Initiative Enterprises.
+ *  Copyright (c) 2014 Steve "Sc00bz" Thomas (steve at tobtu dot com)
+ *
+ *  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.
+ */
+
+/**
+ * Class Base64DotSlashOrdered
+ * ./[0-9][A-Z][a-z]
+ *
+ * @package ParagonIE\ConstantTime
+ */
+abstract class Base64DotSlashOrdered extends Base64
+{
+    /**
+     * Uses bitwise operators instead of table-lookups to turn 6-bit integers
+     * into 8-bit integers.
+     *
+     * Base64 character set:
+     * [.-9]      [A-Z]      [a-z]
+     * 0x2e-0x39, 0x41-0x5a, 0x61-0x7a
+     *
+     * @param int $src
+     * @return int
+     */
+    protected static function decode6Bits(int $src): int
+    {
+        $ret = -1;
+
+        // if ($src > 0x2d && $src < 0x3a) ret += $src - 0x2e + 1; // -45
+        $ret += (((0x2d - $src) & ($src - 0x3a)) >> 8) & ($src - 45);
+
+        // if ($src > 0x40 && $src < 0x5b) ret += $src - 0x41 + 12 + 1; // -52
+        $ret += (((0x40 - $src) & ($src - 0x5b)) >> 8) & ($src - 52);
+
+        // if ($src > 0x60 && $src < 0x7b) ret += $src - 0x61 + 38 + 1; // -58
+        $ret += (((0x60 - $src) & ($src - 0x7b)) >> 8) & ($src - 58);
+
+        return $ret;
+    }
+
+    /**
+     * Uses bitwise operators instead of table-lookups to turn 8-bit integers
+     * into 6-bit integers.
+     *
+     * @param int $src
+     * @return string
+     */
+    protected static function encode6Bits(int $src): string
+    {
+        $src += 0x2e;
+
+        // if ($src > 0x39) $src += 0x41 - 0x3a; // 7
+        $src += ((0x39 - $src) >> 8) & 7;
+
+        // if ($src > 0x5a) $src += 0x61 - 0x5b; // 6
+        $src += ((0x5a - $src) >> 8) & 6;
+
+        return \pack('C', $src);
+    }
+}
diff --git a/vendor/paragonie/constant_time_encoding/src/Base64UrlSafe.php b/vendor/paragonie/constant_time_encoding/src/Base64UrlSafe.php
new file mode 100644
index 0000000000000000000000000000000000000000..1a4107527a794458655113dd7c0dd780071584a6
--- /dev/null
+++ b/vendor/paragonie/constant_time_encoding/src/Base64UrlSafe.php
@@ -0,0 +1,95 @@
+<?php
+declare(strict_types=1);
+namespace ParagonIE\ConstantTime;
+
+/**
+ *  Copyright (c) 2016 - 2018 Paragon Initiative Enterprises.
+ *  Copyright (c) 2014 Steve "Sc00bz" Thomas (steve at tobtu dot com)
+ *
+ *  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.
+ */
+
+/**
+ * Class Base64UrlSafe
+ * [A-Z][a-z][0-9]\-_
+ *
+ * @package ParagonIE\ConstantTime
+ */
+abstract class Base64UrlSafe extends Base64
+{
+
+    /**
+     * Uses bitwise operators instead of table-lookups to turn 6-bit integers
+     * into 8-bit integers.
+     *
+     * Base64 character set:
+     * [A-Z]      [a-z]      [0-9]      -     _
+     * 0x41-0x5a, 0x61-0x7a, 0x30-0x39, 0x2d, 0x5f
+     *
+     * @param int $src
+     * @return int
+     */
+    protected static function decode6Bits(int $src): int
+    {
+        $ret = -1;
+
+        // if ($src > 0x40 && $src < 0x5b) $ret += $src - 0x41 + 1; // -64
+        $ret += (((0x40 - $src) & ($src - 0x5b)) >> 8) & ($src - 64);
+
+        // if ($src > 0x60 && $src < 0x7b) $ret += $src - 0x61 + 26 + 1; // -70
+        $ret += (((0x60 - $src) & ($src - 0x7b)) >> 8) & ($src - 70);
+
+        // if ($src > 0x2f && $src < 0x3a) $ret += $src - 0x30 + 52 + 1; // 5
+        $ret += (((0x2f - $src) & ($src - 0x3a)) >> 8) & ($src + 5);
+
+        // if ($src == 0x2c) $ret += 62 + 1;
+        $ret += (((0x2c - $src) & ($src - 0x2e)) >> 8) & 63;
+
+        // if ($src == 0x5f) ret += 63 + 1;
+        $ret += (((0x5e - $src) & ($src - 0x60)) >> 8) & 64;
+
+        return $ret;
+    }
+
+    /**
+     * Uses bitwise operators instead of table-lookups to turn 8-bit integers
+     * into 6-bit integers.
+     *
+     * @param int $src
+     * @return string
+     */
+    protected static function encode6Bits(int $src): string
+    {
+        $diff = 0x41;
+
+        // if ($src > 25) $diff += 0x61 - 0x41 - 26; // 6
+        $diff += ((25 - $src) >> 8) & 6;
+
+        // if ($src > 51) $diff += 0x30 - 0x61 - 26; // -75
+        $diff -= ((51 - $src) >> 8) & 75;
+
+        // if ($src > 61) $diff += 0x2d - 0x30 - 10; // -13
+        $diff -= ((61 - $src) >> 8) & 13;
+
+        // if ($src > 62) $diff += 0x5f - 0x2b - 1; // 3
+        $diff += ((62 - $src) >> 8) & 49;
+
+        return \pack('C', $src + $diff);
+    }
+}
diff --git a/vendor/paragonie/constant_time_encoding/src/Binary.php b/vendor/paragonie/constant_time_encoding/src/Binary.php
new file mode 100644
index 0000000000000000000000000000000000000000..38c3ec89a813942be26a25f286d2f79c6ee6f729
--- /dev/null
+++ b/vendor/paragonie/constant_time_encoding/src/Binary.php
@@ -0,0 +1,85 @@
+<?php
+declare(strict_types=1);
+namespace ParagonIE\ConstantTime;
+
+/**
+ *  Copyright (c) 2016 - 2018 Paragon Initiative Enterprises.
+ *  Copyright (c) 2014 Steve "Sc00bz" Thomas (steve at tobtu dot com)
+ *
+ *  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.
+ */
+
+/**
+ * Class Binary
+ *
+ * Binary string operators that don't choke on
+ * mbstring.func_overload
+ *
+ * @package ParagonIE\ConstantTime
+ */
+abstract class Binary
+{
+    /**
+     * Safe string length
+     *
+     * @ref mbstring.func_overload
+     *
+     * @param string $str
+     * @return int
+     */
+    public static function safeStrlen(string $str): int
+    {
+        if (\function_exists('mb_strlen')) {
+            return (int) \mb_strlen($str, '8bit');
+        } else {
+            return (int) \strlen($str);
+        }
+    }
+
+    /**
+     * Safe substring
+     *
+     * @ref mbstring.func_overload
+     *
+     * @staticvar boolean $exists
+     * @param string $str
+     * @param int $start
+     * @param int $length
+     * @return string
+     * @throws \TypeError
+     */
+    public static function safeSubstr(
+        string $str,
+        int $start = 0,
+        $length = null
+    ): string {
+        if ($length === 0) {
+            return '';
+        }
+        if (\function_exists('mb_substr')) {
+            return \mb_substr($str, $start, $length, '8bit');
+        }
+        // Unlike mb_substr(), substr() doesn't accept NULL for length
+        if ($length !== null) {
+            return \substr($str, $start, $length);
+        } else {
+            return \substr($str, $start);
+        }
+    }
+}
diff --git a/vendor/paragonie/constant_time_encoding/src/EncoderInterface.php b/vendor/paragonie/constant_time_encoding/src/EncoderInterface.php
new file mode 100644
index 0000000000000000000000000000000000000000..7aeee55a8604d5c9f1def288ce0ff6db3006ea61
--- /dev/null
+++ b/vendor/paragonie/constant_time_encoding/src/EncoderInterface.php
@@ -0,0 +1,52 @@
+<?php
+declare(strict_types=1);
+namespace ParagonIE\ConstantTime;
+
+/**
+ *  Copyright (c) 2016 - 2018 Paragon Initiative Enterprises.
+ *  Copyright (c) 2014 Steve "Sc00bz" Thomas (steve at tobtu dot com)
+ *
+ *  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.
+ */
+
+/**
+ * Interface EncoderInterface
+ * @package ParagonIE\ConstantTime
+ */
+interface EncoderInterface
+{
+    /**
+     * Convert a binary string into a hexadecimal string without cache-timing
+     * leaks
+     *
+     * @param string $binString (raw binary)
+     * @return string
+     */
+    public static function encode(string $binString): string;
+
+    /**
+     * Convert a binary string into a hexadecimal string without cache-timing
+     * leaks
+     *
+     * @param string $encodedString
+     * @param bool $strictPadding Error on invalid padding
+     * @return string (raw binary)
+     */
+    public static function decode(string $encodedString, bool $strictPadding = false): string;
+}
diff --git a/vendor/paragonie/constant_time_encoding/src/Encoding.php b/vendor/paragonie/constant_time_encoding/src/Encoding.php
new file mode 100644
index 0000000000000000000000000000000000000000..896a6684179e61c9c846a67264ca94d0ba30ad30
--- /dev/null
+++ b/vendor/paragonie/constant_time_encoding/src/Encoding.php
@@ -0,0 +1,260 @@
+<?php
+declare(strict_types=1);
+namespace ParagonIE\ConstantTime;
+
+/**
+ *  Copyright (c) 2016 - 2018 Paragon Initiative Enterprises.
+ *  Copyright (c) 2014 Steve "Sc00bz" Thomas (steve at tobtu dot com)
+ *
+ *  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.
+ */
+
+/**
+ * Class Encoding
+ * @package ParagonIE\ConstantTime
+ */
+abstract class Encoding
+{
+    /**
+     * RFC 4648 Base32 encoding
+     *
+     * @param string $str
+     * @return string
+     * @throws \TypeError
+     */
+    public static function base32Encode(string $str): string
+    {
+        return Base32::encode($str);
+    }
+
+    /**
+     * RFC 4648 Base32 encoding
+     *
+     * @param string $str
+     * @return string
+     * @throws \TypeError
+     */
+    public static function base32EncodeUpper(string $str): string
+    {
+        return Base32::encodeUpper($str);
+    }
+
+    /**
+     * RFC 4648 Base32 decoding
+     *
+     * @param string $str
+     * @return string
+     * @throws \TypeError
+     */
+    public static function base32Decode(string $str): string
+    {
+        return Base32::decode($str);
+    }
+
+    /**
+     * RFC 4648 Base32 decoding
+     *
+     * @param string $str
+     * @return string
+     * @throws \TypeError
+     */
+    public static function base32DecodeUpper(string $str): string
+    {
+        return Base32::decodeUpper($str);
+    }
+
+    /**
+     * RFC 4648 Base32 encoding
+     *
+     * @param string $str
+     * @return string
+     * @throws \TypeError
+     */
+    public static function base32HexEncode(string $str): string
+    {
+        return Base32Hex::encode($str);
+    }
+
+    /**
+     * RFC 4648 Base32Hex encoding
+     *
+     * @param string $str
+     * @return string
+     * @throws \TypeError
+     */
+    public static function base32HexEncodeUpper(string $str): string
+    {
+        return Base32Hex::encodeUpper($str);
+    }
+
+    /**
+     * RFC 4648 Base32Hex decoding
+     *
+     * @param string $str
+     * @return string
+     * @throws \TypeError
+     */
+    public static function base32HexDecode(string $str): string
+    {
+        return Base32Hex::decode($str);
+    }
+
+    /**
+     * RFC 4648 Base32Hex decoding
+     *
+     * @param string $str
+     * @return string
+     * @throws \TypeError
+     */
+    public static function base32HexDecodeUpper(string $str): string
+    {
+        return Base32Hex::decodeUpper($str);
+    }
+
+    /**
+     * RFC 4648 Base64 encoding
+     *
+     * @param string $str
+     * @return string
+     * @throws \TypeError
+     */
+    public static function base64Encode(string $str): string
+    {
+        return Base64::encode($str);
+    }
+
+    /**
+     * RFC 4648 Base64 decoding
+     *
+     * @param string $str
+     * @return string
+     * @throws \TypeError
+     */
+    public static function base64Decode(string $str): string
+    {
+        return Base64::decode($str);
+    }
+
+    /**
+     * Encode into Base64
+     *
+     * Base64 character set "./[A-Z][a-z][0-9]"
+     * @param string $str
+     * @return string
+     * @throws \TypeError
+     */
+    public static function base64EncodeDotSlash(string $str): string
+    {
+        return Base64DotSlash::encode($str);
+    }
+
+    /**
+     * Decode from base64 to raw binary
+     *
+     * Base64 character set "./[A-Z][a-z][0-9]"
+     *
+     * @param string $str
+     * @return string
+     * @throws \RangeException
+     * @throws \TypeError
+     */
+    public static function base64DecodeDotSlash(string $str): string
+    {
+        return Base64DotSlash::decode($str);
+    }
+
+    /**
+     * Encode into Base64
+     *
+     * Base64 character set "[.-9][A-Z][a-z]" or "./[0-9][A-Z][a-z]"
+     * @param string $str
+     * @return string
+     * @throws \TypeError
+     */
+    public static function base64EncodeDotSlashOrdered(string $str): string
+    {
+        return Base64DotSlashOrdered::encode($str);
+    }
+
+    /**
+     * Decode from base64 to raw binary
+     *
+     * Base64 character set "[.-9][A-Z][a-z]" or "./[0-9][A-Z][a-z]"
+     *
+     * @param string $str
+     * @return string
+     * @throws \RangeException
+     * @throws \TypeError
+     */
+    public static function base64DecodeDotSlashOrdered(string $str): string
+    {
+        return Base64DotSlashOrdered::decode($str);
+    }
+
+    /**
+     * Convert a binary string into a hexadecimal string without cache-timing
+     * leaks
+     *
+     * @param string $bin_string (raw binary)
+     * @return string
+     * @throws \TypeError
+     */
+    public static function hexEncode(string $bin_string): string
+    {
+        return Hex::encode($bin_string);
+    }
+
+    /**
+     * Convert a hexadecimal string into a binary string without cache-timing
+     * leaks
+     *
+     * @param string $hex_string
+     * @return string (raw binary)
+     * @throws \RangeException
+     */
+    public static function hexDecode(string $hex_string): string
+    {
+        return Hex::decode($hex_string);
+    }
+
+    /**
+     * Convert a binary string into a hexadecimal string without cache-timing
+     * leaks
+     *
+     * @param string $bin_string (raw binary)
+     * @return string
+     * @throws \TypeError
+     */
+    public static function hexEncodeUpper(string $bin_string): string
+    {
+        return Hex::encodeUpper($bin_string);
+    }
+
+    /**
+     * Convert a binary string into a hexadecimal string without cache-timing
+     * leaks
+     *
+     * @param string $bin_string (raw binary)
+     * @return string
+     */
+    public static function hexDecodeUpper(string $bin_string): string
+    {
+        return Hex::decode($bin_string);
+    }
+}
diff --git a/vendor/paragonie/constant_time_encoding/src/Hex.php b/vendor/paragonie/constant_time_encoding/src/Hex.php
new file mode 100644
index 0000000000000000000000000000000000000000..c3413ec15e475bfe9643a1bfb750cd29b104b149
--- /dev/null
+++ b/vendor/paragonie/constant_time_encoding/src/Hex.php
@@ -0,0 +1,159 @@
+<?php
+declare(strict_types=1);
+namespace ParagonIE\ConstantTime;
+
+/**
+ *  Copyright (c) 2016 - 2018 Paragon Initiative Enterprises.
+ *  Copyright (c) 2014 Steve "Sc00bz" Thomas (steve at tobtu dot com)
+ *
+ *  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.
+ */
+
+/**
+ * Class Hex
+ * @package ParagonIE\ConstantTime
+ */
+abstract class Hex implements EncoderInterface
+{
+    /**
+     * Convert a binary string into a hexadecimal string without cache-timing
+     * leaks
+     *
+     * @param string $binString (raw binary)
+     * @return string
+     * @throws \TypeError
+     */
+    public static function encode(string $binString): string
+    {
+        /** @var string $hex */
+        $hex = '';
+        $len = Binary::safeStrlen($binString);
+        for ($i = 0; $i < $len; ++$i) {
+            /** @var array<int, int> $chunk */
+            $chunk = \unpack('C', Binary::safeSubstr($binString, $i, 1));
+            /** @var int $c */
+            $c = $chunk[1] & 0xf;
+            /** @var int $b */
+            $b = $chunk[1] >> 4;
+
+            $hex .= pack(
+                'CC',
+                (87 + $b + ((($b - 10) >> 8) & ~38)),
+                (87 + $c + ((($c - 10) >> 8) & ~38))
+            );
+        }
+        return $hex;
+    }
+
+    /**
+     * Convert a binary string into a hexadecimal string without cache-timing
+     * leaks, returning uppercase letters (as per RFC 4648)
+     *
+     * @param string $binString (raw binary)
+     * @return string
+     * @throws \TypeError
+     */
+    public static function encodeUpper(string $binString): string
+    {
+        /** @var string $hex */
+        $hex = '';
+        /** @var int $len */
+        $len = Binary::safeStrlen($binString);
+
+        for ($i = 0; $i < $len; ++$i) {
+            /** @var array<int, int> $chunk */
+            $chunk = \unpack('C', Binary::safeSubstr($binString, $i, 2));
+            /** @var int $c */
+            $c = $chunk[1] & 0xf;
+            /** @var int $b */
+            $b = $chunk[1] >> 4;
+
+            $hex .= pack(
+                'CC',
+                (55 + $b + ((($b - 10) >> 8) & ~6)),
+                (55 + $c + ((($c - 10) >> 8) & ~6))
+            );
+        }
+        return $hex;
+    }
+
+    /**
+     * Convert a hexadecimal string into a binary string without cache-timing
+     * leaks
+     *
+     * @param string $hexString
+     * @param bool $strictPadding
+     * @return string (raw binary)
+     * @throws \RangeException
+     */
+    public static function decode(string $hexString, bool $strictPadding = false): string
+    {
+        /** @var int $hex_pos */
+        $hex_pos = 0;
+        /** @var string $bin */
+        $bin = '';
+        /** @var int $c_acc */
+        $c_acc = 0;
+        /** @var int $hex_len */
+        $hex_len = Binary::safeStrlen($hexString);
+        /** @var int $state */
+        $state = 0;
+        if (($hex_len & 1) !== 0) {
+            if ($strictPadding) {
+                throw new \RangeException(
+                    'Expected an even number of hexadecimal characters'
+                );
+            } else {
+                $hexString = '0' . $hexString;
+                ++$hex_len;
+            }
+        }
+
+        /** @var array<int, int> $chunk */
+        $chunk = \unpack('C*', $hexString);
+        while ($hex_pos < $hex_len) {
+            ++$hex_pos;
+            /** @var int $c */
+            $c = $chunk[$hex_pos];
+            /** @var int $c_num */
+            $c_num = $c ^ 48;
+            /** @var int $c_num0 */
+            $c_num0 = ($c_num - 10) >> 8;
+            /** @var int $c_alpha */
+            $c_alpha = ($c & ~32) - 55;
+            /** @var int $c_alpha0 */
+            $c_alpha0 = (($c_alpha - 10) ^ ($c_alpha - 16)) >> 8;
+
+            if (($c_num0 | $c_alpha0) === 0) {
+                throw new \RangeException(
+                    'hexEncode() only expects hexadecimal characters'
+                );
+            }
+            /** @var int $c_val */
+            $c_val = ($c_num0 & $c_num) | ($c_alpha & $c_alpha0);
+            if ($state === 0) {
+                $c_acc = $c_val * 16;
+            } else {
+                $bin .= \pack('C', $c_acc | $c_val);
+            }
+            $state ^= 1;
+        }
+        return $bin;
+    }
+}
diff --git a/vendor/paragonie/constant_time_encoding/src/RFC4648.php b/vendor/paragonie/constant_time_encoding/src/RFC4648.php
new file mode 100644
index 0000000000000000000000000000000000000000..492cad00ef4776bfbcd097eb53c00c0697c945a6
--- /dev/null
+++ b/vendor/paragonie/constant_time_encoding/src/RFC4648.php
@@ -0,0 +1,175 @@
+<?php
+declare(strict_types=1);
+namespace ParagonIE\ConstantTime;
+
+/**
+ *  Copyright (c) 2016 - 2018 Paragon Initiative Enterprises.
+ *  Copyright (c) 2014 Steve "Sc00bz" Thomas (steve at tobtu dot com)
+ *
+ *  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.
+ */
+
+/**
+ * Class RFC4648
+ *
+ * This class conforms strictly to the RFC
+ *
+ * @package ParagonIE\ConstantTime
+ */
+abstract class RFC4648
+{
+    /**
+     * RFC 4648 Base64 encoding
+     *
+     * "foo" -> "Zm9v"
+     *
+     * @param string $str
+     * @return string
+     * @throws \TypeError
+     */
+    public static function base64Encode(string $str): string
+    {
+        return Base64::encode($str);
+    }
+
+    /**
+     * RFC 4648 Base64 decoding
+     *
+     * "Zm9v" -> "foo"
+     *
+     * @param string $str
+     * @return string
+     * @throws \TypeError
+     */
+    public static function base64Decode(string $str): string
+    {
+        return Base64::decode($str, true);
+    }
+
+    /**
+     * RFC 4648 Base64 (URL Safe) encoding
+     *
+     * "foo" -> "Zm9v"
+     *
+     * @param string $str
+     * @return string
+     * @throws \TypeError
+     */
+    public static function base64UrlSafeEncode(string $str): string
+    {
+        return Base64UrlSafe::encode($str);
+    }
+
+    /**
+     * RFC 4648 Base64 (URL Safe) decoding
+     *
+     * "Zm9v" -> "foo"
+     *
+     * @param string $str
+     * @return string
+     * @throws \TypeError
+     */
+    public static function base64UrlSafeDecode(string $str): string
+    {
+        return Base64UrlSafe::decode($str, true);
+    }
+
+    /**
+     * RFC 4648 Base32 encoding
+     *
+     * "foo" -> "MZXW6==="
+     *
+     * @param string $str
+     * @return string
+     * @throws \TypeError
+     */
+    public static function base32Encode(string $str): string
+    {
+        return Base32::encodeUpper($str);
+    }
+
+    /**
+     * RFC 4648 Base32 encoding
+     *
+     * "MZXW6===" -> "foo"
+     *
+     * @param string $str
+     * @return string
+     * @throws \TypeError
+     */
+    public static function base32Decode(string $str): string
+    {
+        return Base32::decodeUpper($str, true);
+    }
+
+    /**
+     * RFC 4648 Base32-Hex encoding
+     *
+     * "foo" -> "CPNMU==="
+     *
+     * @param string $str
+     * @return string
+     * @throws \TypeError
+     */
+    public static function base32HexEncode(string $str): string
+    {
+        return Base32::encodeUpper($str);
+    }
+
+    /**
+     * RFC 4648 Base32-Hex decoding
+     *
+     * "CPNMU===" -> "foo"
+     *
+     * @param string $str
+     * @return string
+     * @throws \TypeError
+     */
+    public static function base32HexDecode(string $str): string
+    {
+        return Base32::decodeUpper($str, true);
+    }
+
+    /**
+     * RFC 4648 Base16 decoding
+     *
+     * "foo" -> "666F6F"
+     *
+     * @param string $str
+     * @return string
+     * @throws \TypeError
+     */
+    public static function base16Encode(string $str): string
+    {
+        return Hex::encodeUpper($str);
+    }
+
+    /**
+     * RFC 4648 Base16 decoding
+     *
+     * "666F6F" -> "foo"
+     *
+     * @param string $str
+     * @return string
+     */
+    public static function base16Decode(string $str): string
+    {
+        return Hex::decode($str, true);
+    }
+}
\ No newline at end of file
diff --git a/vendor/paragonie/constant_time_encoding/tests/Base32HexTest.php b/vendor/paragonie/constant_time_encoding/tests/Base32HexTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..ed19f336f706dd372b7965d5a093e387ae3f59ca
--- /dev/null
+++ b/vendor/paragonie/constant_time_encoding/tests/Base32HexTest.php
@@ -0,0 +1,49 @@
+<?php
+use \ParagonIE\ConstantTime\Base32Hex;
+
+class Base32HexTest extends PHPUnit\Framework\TestCase
+{
+    /**
+     * @covers Base32Hex::encode()
+     * @covers Base32Hex::decode()
+     * @covers Base32Hex::encodeUpper()
+     * @covers Base32Hex::decodeUpper()
+     */
+    public function testRandom()
+    {
+        for ($i = 1; $i < 32; ++$i) {
+            for ($j = 0; $j < 50; ++$j) {
+                $random = \random_bytes($i);
+
+                $enc = Base32Hex::encode($random);
+                $this->assertSame(
+                    $random,
+                    Base32Hex::decode($enc)
+                );
+                $unpadded = \rtrim($enc, '=');
+                $this->assertSame(
+                    $unpadded,
+                    Base32Hex::encodeUnpadded($random)
+                );
+                $this->assertSame(
+                    $random,
+                    Base32Hex::decode($unpadded)
+                );
+
+                $enc = Base32Hex::encodeUpper($random);
+                $this->assertSame(
+                    $random,
+                    Base32Hex::decodeUpper($enc)
+                );                $unpadded = \rtrim($enc, '=');
+                $this->assertSame(
+                    $unpadded,
+                    Base32Hex::encodeUpperUnpadded($random)
+                );
+                $this->assertSame(
+                    $random,
+                    Base32Hex::decodeUpper($unpadded)
+                );
+            }
+        }
+    }
+}
diff --git a/vendor/paragonie/constant_time_encoding/tests/Base32Test.php b/vendor/paragonie/constant_time_encoding/tests/Base32Test.php
new file mode 100644
index 0000000000000000000000000000000000000000..65e8e7c56b16e1134de1a74de02d5a8967f07fa8
--- /dev/null
+++ b/vendor/paragonie/constant_time_encoding/tests/Base32Test.php
@@ -0,0 +1,50 @@
+<?php
+use \ParagonIE\ConstantTime\Base32;
+
+class Base32Test extends PHPUnit\Framework\TestCase
+{
+    /**
+     * @covers Base32::encode()
+     * @covers Base32::decode()
+     * @covers Base32::encodeUpper()
+     * @covers Base32::decodeUpper()
+     */
+    public function testRandom()
+    {
+        for ($i = 1; $i < 32; ++$i) {
+            for ($j = 0; $j < 50; ++$j) {
+                $random = \random_bytes($i);
+
+                $enc = Base32::encode($random);
+                $this->assertSame(
+                    $random,
+                    Base32::decode($enc)
+                );
+                $unpadded = \rtrim($enc, '=');
+                $this->assertSame(
+                    $unpadded,
+                    Base32::encodeUnpadded($random)
+                );
+                $this->assertSame(
+                    $random,
+                    Base32::decode($unpadded)
+                );
+
+                $enc = Base32::encodeUpper($random);
+                $this->assertSame(
+                    $random,
+                    Base32::decodeUpper($enc)
+                );
+                $unpadded = \rtrim($enc, '=');
+                $this->assertSame(
+                    $unpadded,
+                    Base32::encodeUpperUnpadded($random)
+                );
+                $this->assertSame(
+                    $random,
+                    Base32::decodeUpper($unpadded)
+                );
+            }
+        }
+    }
+}
diff --git a/vendor/paragonie/constant_time_encoding/tests/Base64DotSlashOrderedTest.php b/vendor/paragonie/constant_time_encoding/tests/Base64DotSlashOrderedTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..f7dc828b1cb68e148ca1b8925627a2aeae8eb3c0
--- /dev/null
+++ b/vendor/paragonie/constant_time_encoding/tests/Base64DotSlashOrderedTest.php
@@ -0,0 +1,34 @@
+<?php
+use \ParagonIE\ConstantTime\Base64DotSlashOrdered;
+
+class Base64DotSlashOrderedTest extends PHPUnit\Framework\TestCase
+{
+    /**
+     * @covers Base64DotSlashOrdered::encode()
+     * @covers Base64DotSlashOrdered::decode()
+     */
+    public function testRandom()
+    {
+        for ($i = 1; $i < 32; ++$i) {
+            for ($j = 0; $j < 50; ++$j) {
+                $random = \random_bytes($i);
+
+                $enc = Base64DotSlashOrdered::encode($random);
+                $this->assertSame(
+                    $random,
+                    Base64DotSlashOrdered::decode($enc)
+                );
+
+                $unpadded = \rtrim($enc, '=');
+                $this->assertSame(
+                    $random,
+                    Base64DotSlashOrdered::decode($unpadded)
+                );
+                $this->assertSame(
+                    $random,
+                    Base64DotSlashOrdered::decode($unpadded)
+                );
+            }
+        }
+    }
+}
diff --git a/vendor/paragonie/constant_time_encoding/tests/Base64DotSlashTest.php b/vendor/paragonie/constant_time_encoding/tests/Base64DotSlashTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..257a3d5495375a8db4e2870150ad37bc059733c7
--- /dev/null
+++ b/vendor/paragonie/constant_time_encoding/tests/Base64DotSlashTest.php
@@ -0,0 +1,34 @@
+<?php
+use \ParagonIE\ConstantTime\Base64DotSlash;
+
+class Base64DotSlashTest extends PHPUnit\Framework\TestCase
+{
+    /**
+     * @covers Base64DotSlash::encode()
+     * @covers Base64DotSlash::decode()
+     */
+    public function testRandom()
+    {
+        for ($i = 1; $i < 32; ++$i) {
+            for ($j = 0; $j < 50; ++$j) {
+                $random = \random_bytes($i);
+
+                $enc = Base64DotSlash::encode($random);
+                $this->assertSame(
+                    $random,
+                    Base64DotSlash::decode($enc)
+                );
+
+                $unpadded = \rtrim($enc, '=');
+                $this->assertSame(
+                    $random,
+                    Base64DotSlash::decode($unpadded)
+                );
+                $this->assertSame(
+                    $random,
+                    Base64DotSlash::decode($unpadded)
+                );
+            }
+        }
+    }
+}
diff --git a/vendor/paragonie/constant_time_encoding/tests/Base64Test.php b/vendor/paragonie/constant_time_encoding/tests/Base64Test.php
new file mode 100644
index 0000000000000000000000000000000000000000..16ab47da0e1643de2d264200838591064574786b
--- /dev/null
+++ b/vendor/paragonie/constant_time_encoding/tests/Base64Test.php
@@ -0,0 +1,79 @@
+<?php
+use \ParagonIE\ConstantTime\Base64;
+
+class Base64Test extends PHPUnit\Framework\TestCase
+{
+    /**
+     * @covers Base64::encode()
+     * @covers Base64::decode()
+     */
+    public function testRandom()
+    {
+        for ($i = 1; $i < 32; ++$i) {
+            for ($j = 0; $j < 50; ++$j) {
+                $random = \random_bytes($i);
+
+                $enc = Base64::encode($random);
+                $this->assertSame(
+                    $random,
+                    Base64::decode($enc)
+                );
+                $this->assertSame(
+                    \base64_encode($random),
+                    $enc
+                );
+
+                $unpadded = \rtrim($enc, '=');
+                $this->assertSame(
+                    $random,
+                    Base64::decode($unpadded)
+                );
+                $this->assertSame(
+                    $random,
+                    Base64::decode($unpadded)
+                );
+            }
+        }
+        $str = 'MIIFzzCCBLegAwIBAgIDAfdlMA0GCSqGSIb3DQEBBQUAMHMxCzAJBgNVBAYTAlBM' .
+            'MSgwJgYDVQQKDB9LcmFqb3dhIEl6YmEgUm96bGljemVuaW93YSBTLkEuMSQwIgYDVQQ' .
+            'DDBtDT1BFIFNaQUZJUiAtIEt3YWxpZmlrb3dhbnkxFDASBgNVBAUTC05yIHdwaXN1Oi' .
+            'A2MB4XDTExMTEwOTA2MDAwMFoXDTEzMTEwOTA2MDAwMFowgdkxCzAJBgNVBAYTAlBMM' .
+            'RwwGgYDVQQKDBNVcnrEhWQgTWlhc3RhIEdkeW5pMRswGQYDVQQFExJQRVNFTDogNjEw' .
+            'NjA2MDMxMTgxGTAXBgNVBAMMEEplcnp5IFByemV3b3Jza2kxTzBNBgNVBBAwRgwiQWw' .
+            'uIE1hcnN6YcWCa2EgUGnFgnN1ZHNraWVnbyA1Mi81NAwNODEtMzgyIEdkeW5pYQwGUG' .
+            '9sc2thDAlwb21vcnNraWUxDjAMBgNVBCoMBUplcnp5MRMwEQYDVQQEDApQcnpld29yc' .
+            '2tpMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCMm5vjGqHPthJCMqKpqssSISRo' .
+            's0PYDTcEQzyyurfX67EJWKtZj6HNwuDMEGJ02iBNZfjUl7r8dIi28bSKhNlsfycXZKY' .
+            'RcIjp0+r5RqtR2auo9GQ6veKb61DEAGIqaR+uLLcJVTHCu0w9oXLGbRlGth5eNoj03C' .
+            'xXVAH2IfhbNwIDAQABo4IChzCCAoMwDAYDVR0TAQH/BAIwADCCAUgGA1UdIAEB/wSCA' .
+            'TwwggE4MIIBNAYJKoRoAYb3IwEBMIIBJTCB3QYIKwYBBQUHAgIwgdAMgc1EZWtsYXJh' .
+            'Y2phIHRhIGplc3Qgb8Wbd2lhZGN6ZW5pZW0gd3lkYXdjeSwgxbxlIHRlbiBjZXJ0eWZ' .
+            'pa2F0IHpvc3RhxYIgd3lkYW55IGpha28gY2VydHlmaWthdCBrd2FsaWZpa293YW55IH' .
+            'pnb2RuaWUgeiB3eW1hZ2FuaWFtaSB1c3Rhd3kgbyBwb2RwaXNpZSBlbGVrdHJvbmlje' .
+            'm55bSBvcmF6IHRvd2FyenlzesSFY3ltaSBqZWogcm96cG9yesSFZHplbmlhbWkuMEMG' .
+            'CCsGAQUFBwIBFjdodHRwOi8vd3d3Lmtpci5jb20ucGwvY2VydHlmaWthY2phX2tsdWN' .
+            '6eS9wb2xpdHlrYS5odG1sMAkGA1UdCQQCMAAwIQYDVR0RBBowGIEWai5wcnpld29yc2' .
+            'tpQGdkeW5pYS5wbDAOBgNVHQ8BAf8EBAMCBkAwgZ4GA1UdIwSBljCBk4AU3TGldJXip' .
+            'N4oGS3ZYmnBDMFs8gKhd6R1MHMxCzAJBgNVBAYTAlBMMSgwJgYDVQQKDB9LcmFqb3dh' .
+            'IEl6YmEgUm96bGljemVuaW93YSBTLkEuMSQwIgYDVQQDDBtDT1BFIFNaQUZJUiAtIEt' .
+            '3YWxpZmlrb3dhbnkxFDASBgNVBAUTC05yIHdwaXN1OiA2ggJb9jBIBgNVHR8EQTA/MD' .
+            '2gO6A5hjdodHRwOi8vd3d3Lmtpci5jb20ucGwvY2VydHlmaWthY2phX2tsdWN6eS9DU' .
+            'kxfT1pLMzIuY3JsMA0GCSqGSIb3DQEBBQUAA4IBAQBYPIqnAreyeql7/opJjcar/qWZ' .
+            'y9ruhB2q0lZFsJOhwgMnbQXzp/4vv93YJqcHGAXdHP6EO8FQX47mjo2ZKQmi+cIHJHL' .
+            'ONdX/3Im+M17V0iNAh7Z1lOSfTRT+iiwe/F8phcEaD5q2RmvYusR7zXZq/cLL0If0hX' .
+            'oPZ/EHQxjN8pxzxiUx6bJAgturnIMEfRNesxwghdr1dkUjOhGLf3kHVzgM6j3VAM7oF' .
+            'mMUb5y5s96Bzl10DodWitjOEH0vvnIcsppSxH1C1dCAi0o9f/1y2XuLNhBNHMAyTqpY' .
+            'PX8Yvav1c+Z50OMaSXHAnTa20zv8UtiHbaAhwlifCelUMj93S';
+        
+        try {
+            Base64::decode($str, true);
+            $this->fail('Strict padding not enforced');
+        } catch (\Exception $ex) {
+
+            $this->assertSame(
+                Base64::decode($str),
+                \base64_decode($str)
+            );
+        }
+    }
+}
diff --git a/vendor/paragonie/constant_time_encoding/tests/Base64UrlSafeTest.php b/vendor/paragonie/constant_time_encoding/tests/Base64UrlSafeTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..136ed611ce8bdde78a9cd420bc5000031706a4fd
--- /dev/null
+++ b/vendor/paragonie/constant_time_encoding/tests/Base64UrlSafeTest.php
@@ -0,0 +1,58 @@
+<?php
+
+use ParagonIE\ConstantTime\Base64UrlSafe;
+use ParagonIE\ConstantTime\Binary;
+
+/**
+ * Class Base64UrlSafeTest
+ */
+class Base64UrlSafeTest extends PHPUnit\Framework\TestCase
+{
+    /**
+     * @covers Base64UrlSafe::encode()
+     * @covers Base64UrlSafe::decode()
+     *
+     * @throws Exception
+     * @throws TypeError
+     */
+    public function testRandom()
+    {
+        for ($i = 1; $i < 32; ++$i) {
+            for ($j = 0; $j < 50; ++$j) {
+                $random = \random_bytes($i);
+
+                $enc = Base64UrlSafe::encode($random);
+                $this->assertSame(
+                    $random,
+                    Base64UrlSafe::decode($enc)
+                );
+                $this->assertSame(
+                    \strtr(\base64_encode($random), '+/', '-_'),
+                    $enc
+                );
+
+                $unpadded = \rtrim($enc, '=');
+                $this->assertSame(
+                    $unpadded,
+                    Base64UrlSafe::encodeUnpadded($random)
+                );
+                $this->assertSame(
+                    $random,
+                    Base64UrlSafe::decode($unpadded)
+                );
+            }
+        }
+
+        $random = \random_bytes(1 << 20);
+        $enc = Base64UrlSafe::encode($random);
+        $this->assertTrue(Binary::safeStrlen($enc) > 65536);
+        $this->assertSame(
+            $random,
+            Base64UrlSafe::decode($enc)
+        );
+        $this->assertSame(
+            \strtr(\base64_encode($random), '+/', '-_'),
+            $enc
+        );
+    }
+}
diff --git a/vendor/paragonie/constant_time_encoding/tests/EncodingTest.php b/vendor/paragonie/constant_time_encoding/tests/EncodingTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..6f774d8c04b75e0b5eacf32ac42e17cc08e2fd8b
--- /dev/null
+++ b/vendor/paragonie/constant_time_encoding/tests/EncodingTest.php
@@ -0,0 +1,307 @@
+<?php
+use \ParagonIE\ConstantTime\Base32;
+use \ParagonIE\ConstantTime\Base32Hex;
+use \ParagonIE\ConstantTime\Base64;
+use \ParagonIE\ConstantTime\Base64DotSlash;
+use \ParagonIE\ConstantTime\Base64DotSlashOrdered;
+use \ParagonIE\ConstantTime\Base64UrlSafe;
+use \ParagonIE\ConstantTime\Encoding;
+use \ParagonIE\ConstantTime\Hex;
+
+class EncodingTest extends PHPUnit\Framework\TestCase
+{
+    public function testBase32Encode()
+    {
+        $this->assertSame(
+            Encoding::base32Encode("\x00"),
+            'aa======'
+        );
+        $this->assertSame(
+            Encoding::base32Encode("\x00\x00"),
+            'aaaa===='
+        );
+        $this->assertSame(
+            Encoding::base32Encode("\x00\x00\x00"),
+            'aaaaa==='
+        );
+        $this->assertSame(
+            Encoding::base32Encode("\x00\x00\x00\x00"),
+            'aaaaaaa='
+        );
+        $this->assertSame(
+            Encoding::base32Encode("\x00\x00\x00\x00\x00"),
+            'aaaaaaaa'
+        );
+        $this->assertSame(
+            Encoding::base32Encode("\x00\x00\x0F\xFF\xFF"),
+            'aaaa7777'
+        );
+        $this->assertSame(
+            Encoding::base32Encode("\xFF\xFF\xF0\x00\x00"),
+            '7777aaaa'
+        );
+
+        $this->assertSame(
+            Encoding::base32Encode("\xce\x73\x9c\xe7\x39"),
+            'zzzzzzzz'
+        );
+        $this->assertSame(
+            Encoding::base32Encode("\xd6\xb5\xad\x6b\x5a"),
+            '22222222'
+        );
+        $this->assertSame(
+            Base32::encodeUpper("\x00"),
+            'AA======'
+        );
+        $this->assertSame(
+            Base32::encodeUpper("\x00\x00"),
+            'AAAA===='
+        );
+        $this->assertSame(
+            Base32::encodeUpper("\x00\x00\x00"),
+            'AAAAA==='
+        );
+        $this->assertSame(
+            Base32::encodeUpper("\x00\x00\x00\x00"),
+            'AAAAAAA='
+        );
+        $this->assertSame(
+            Base32::encodeUpper("\x00\x00\x00\x00\x00"),
+            'AAAAAAAA'
+        );
+        $this->assertSame(
+            Base32::encodeUpper("\x00\x00\x0F\xFF\xFF"),
+            'AAAA7777'
+        );
+        $this->assertSame(
+            Base32::encodeUpper("\xFF\xFF\xF0\x00\x00"),
+            '7777AAAA'
+        );
+
+        $this->assertSame(
+            Base32::encodeUpper("\xce\x73\x9c\xe7\x39"),
+            'ZZZZZZZZ'
+        );
+        $this->assertSame(
+            Base32::encodeUpper("\xd6\xb5\xad\x6b\x5a"),
+            '22222222'
+        );
+    }
+
+    public function testBase32Hex()
+    {
+        $this->assertSame(
+            Base32Hex::encode("\x00"),
+            '00======'
+        );
+        $this->assertSame(
+            Base32Hex::encode("\x00\x00"),
+            '0000===='
+        );
+        $this->assertSame(
+            Base32Hex::encode("\x00\x00\x00"),
+            '00000==='
+        );
+        $this->assertSame(
+            Base32Hex::encode("\x00\x00\x00\x00"),
+            '0000000='
+        );
+        $this->assertSame(
+            Base32Hex::encode("\x00\x00\x00\x00\x00"),
+            '00000000'
+        );
+        $this->assertSame(
+            Base32Hex::encode("\x00\x00\x0F\xFF\xFF"),
+            '0000vvvv'
+        );
+        $this->assertSame(
+            Base32Hex::encode("\xFF\xFF\xF0\x00\x00"),
+            'vvvv0000'
+        );
+
+
+    }
+
+    /**
+     * Based on test vectors from RFC 4648
+     */
+    public function testBase32Decode()
+    {
+        $this->assertSame(
+            "\x00\x00\x00\x00\x00\x00",
+            Encoding::base32Decode('aaaaaaaaaa======')
+        );
+        $this->assertSame(
+            "\x00\x00\x00\x00\x00\x00\x00",
+            Encoding::base32Decode('aaaaaaaaaaaa====')
+        );
+        $this->assertSame(
+            "\x00\x00\x00\x00\x00\x00\x00\x00",
+            Encoding::base32Decode('aaaaaaaaaaaaa===')
+        );
+        $this->assertSame(
+            "\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+            Encoding::base32Decode('aaaaaaaaaaaaaaa=')
+        );
+        $this->assertSame(
+            "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+            Encoding::base32Decode('aaaaaaaaaaaaaaaa')
+        );
+        $this->assertSame(
+            "\x00",
+            Encoding::base32Decode('aa======')
+        );
+        $this->assertSame(
+            "\x00\x00",
+            Encoding::base32Decode('aaaa====')
+        );
+        $this->assertSame(
+            "\x00\x00\x00",
+            Encoding::base32Decode('aaaaa===')
+        );
+        $this->assertSame(
+            "\x00\x00\x00\x00",
+            Encoding::base32Decode('aaaaaaa=')
+        );
+        $this->assertSame(
+            "\x00\x00\x00\x00\x00",
+            Encoding::base32Decode('aaaaaaaa')
+        );
+        $this->assertSame(
+            "\x00\x00\x0F\xFF\xFF",
+            Encoding::base32Decode('aaaa7777')
+        );
+        $this->assertSame(
+            "\xFF\xFF\xF0\x00\x00",
+            Encoding::base32Decode('7777aaaa')
+        );
+        $this->assertSame(
+            "\xce\x73\x9c\xe7\x39",
+            Encoding::base32Decode('zzzzzzzz')
+        );
+        $this->assertSame(
+            "\xd6\xb5\xad\x6b\x5a",
+            Encoding::base32Decode('22222222')
+        );
+        $this->assertSame(
+            'foobar',
+            Encoding::base32Decode('mzxw6ytboi======')
+        );
+
+        $rand = random_bytes(9);
+        $enc = Encoding::base32Encode($rand);
+
+        $this->assertSame(
+            Encoding::base32Encode($rand),
+            Encoding::base32Encode(Encoding::base32Decode($enc))
+        );
+        $this->assertSame(
+            $rand,
+            Encoding::base32Decode($enc)
+        );
+    }
+
+    /**
+     * @covers Encoding::hexDecode()
+     * @covers Encoding::hexEncode()
+     * @covers Encoding::base32Decode()
+     * @covers Encoding::base32Encode()
+     * @covers Encoding::base64Decode()
+     * @covers Encoding::base64Encode()
+     * @covers Encoding::base64DotSlashDecode()
+     * @covers Encoding::base64DotSlashEncode()
+     * @covers Encoding::base64DotSlashOrderedDecode()
+     * @covers Encoding::base64DotSlashOrderedEncode()
+     */
+    public function testBasicEncoding()
+    {
+        // Re-run the test at least 3 times for each length
+        for ($j = 0; $j < 3; ++$j) {
+            for ($i = 1; $i < 84; ++$i) {
+                $rand = random_bytes($i);
+                $enc = Encoding::hexEncode($rand);
+                $this->assertSame(
+                    \bin2hex($rand),
+                    $enc,
+                    "Hex Encoding - Length: " . $i
+                );
+                $this->assertSame(
+                    $rand,
+                    Encoding::hexDecode($enc),
+                    "Hex Encoding - Length: " . $i
+                );
+
+                // Uppercase variant:
+                $enc = Hex::encodeUpper($rand);
+                $this->assertSame(
+                    \strtoupper(\bin2hex($rand)),
+                    $enc,
+                    "Hex Encoding - Length: " . $i
+                );
+                $this->assertSame(
+                    $rand,
+                    Hex::decode($enc),
+                    "HexUpper Encoding - Length: " . $i
+                );
+
+                $enc = Encoding::base32Encode($rand);
+                $this->assertSame(
+                    $rand,
+                    Encoding::base32Decode($enc),
+                    "Base32 Encoding - Length: " . $i
+                );
+
+                $enc = Encoding::base32EncodeUpper($rand);
+                $this->assertSame(
+                    $rand,
+                    Encoding::base32DecodeUpper($enc),
+                    "Base32Upper Encoding - Length: " . $i
+                );
+
+                $enc = Encoding::base32HexEncode($rand);
+                $this->assertSame(
+                    bin2hex($rand),
+                    bin2hex(Encoding::base32HexDecode($enc)),
+                    "Base32Hex Encoding - Length: " . $i
+                );
+
+                $enc = Encoding::base32HexEncodeUpper($rand);
+                $this->assertSame(
+                    bin2hex($rand),
+                    bin2hex(Encoding::base32HexDecodeUpper($enc)),
+                    "Base32HexUpper Encoding - Length: " . $i
+                );
+
+                $enc = Encoding::base64Encode($rand);
+                $this->assertSame(
+                    $rand,
+                    Encoding::base64Decode($enc),
+                    "Base64 Encoding - Length: " . $i
+                );
+
+                $enc = Encoding::base64EncodeDotSlash($rand);
+                $this->assertSame(
+                    $rand,
+                    Encoding::base64DecodeDotSlash($enc),
+                    "Base64 DotSlash Encoding - Length: " . $i
+                );
+                $enc = Encoding::base64EncodeDotSlashOrdered($rand);
+                $this->assertSame(
+                    $rand,
+                    Encoding::base64DecodeDotSlashOrdered($enc),
+                    "Base64 Ordered DotSlash Encoding - Length: " . $i
+                );
+
+                $enc = Base64UrlSafe::encode($rand);
+                $this->assertSame(
+                    \strtr(\base64_encode($rand), '+/', '-_'),
+                    $enc
+                );
+                $this->assertSame(
+                    $rand,
+                    Base64UrlSafe::decode($enc)
+                );
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/vendor/paragonie/constant_time_encoding/tests/HexTest.php b/vendor/paragonie/constant_time_encoding/tests/HexTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..5c31f6d15c03b12219391ad35a24c28ae73d41b9
--- /dev/null
+++ b/vendor/paragonie/constant_time_encoding/tests/HexTest.php
@@ -0,0 +1,39 @@
+<?php
+use \ParagonIE\ConstantTime\Hex;
+
+class HexTest extends PHPUnit\Framework\TestCase
+{
+    /**
+     * @covers Hex::encode()
+     * @covers Hex::decode()
+     * @covers Hex::encodeUpper()
+     */
+    public function testRandom()
+    {
+        for ($i = 1; $i < 32; ++$i) {
+            for ($j = 0; $j < 50; ++$j) {
+                $random = \random_bytes($i);
+
+                $enc = Hex::encode($random);
+                $this->assertSame(
+                    $random,
+                    Hex::decode($enc)
+                );
+                $this->assertSame(
+                    \bin2hex($random),
+                    $enc
+                );
+
+                $enc = Hex::encodeUpper($random);
+                $this->assertSame(
+                    $random,
+                    Hex::decode($enc)
+                );
+                $this->assertSame(
+                    \strtoupper(\bin2hex($random)),
+                    $enc
+                );
+            }
+        }
+    }
+}
diff --git a/vendor/paragonie/constant_time_encoding/tests/RFC4648Test.php b/vendor/paragonie/constant_time_encoding/tests/RFC4648Test.php
new file mode 100644
index 0000000000000000000000000000000000000000..a6653de885dfc69f1c66357a3a66be70c9fac797
--- /dev/null
+++ b/vendor/paragonie/constant_time_encoding/tests/RFC4648Test.php
@@ -0,0 +1,84 @@
+<?php
+use \ParagonIE\ConstantTime\Base32;
+use \ParagonIE\ConstantTime\Base32Hex;
+use \ParagonIE\ConstantTime\Base64;
+use \ParagonIE\ConstantTime\Base64DotSlash;
+use \ParagonIE\ConstantTime\Base64DotSlashOrdered;
+use \ParagonIE\ConstantTime\Encoding;
+use \ParagonIE\ConstantTime\Hex;
+
+/**
+ * Class RFC4648Test
+ *
+ * @ref https://tools.ietf.org/html/rfc4648#section-10
+ */
+class RFC4648Test extends PHPUnit\Framework\TestCase
+{
+    public function testVectorBase64()
+    {
+        $this->assertSame(Base64::encode(''), '');
+        $this->assertSame(Base64::encode('f'), 'Zg==');
+        $this->assertSame(Base64::encode('fo'), 'Zm8=');
+        $this->assertSame(Base64::encode('foo'), 'Zm9v');
+        $this->assertSame(Base64::encode('foob'), 'Zm9vYg==');
+        $this->assertSame(Base64::encode('fooba'), 'Zm9vYmE=');
+        $this->assertSame(Base64::encode('foobar'), 'Zm9vYmFy');
+    }
+
+    public function testVectorBase32()
+    {
+        $this->assertSame(Base32::encode(''), '');
+        $this->assertSame(Base32::encode('f'), 'my======');
+        $this->assertSame(Base32::encode('fo'), 'mzxq====');
+        $this->assertSame(Base32::encode('foo'), 'mzxw6===');
+        $this->assertSame(Base32::encode('foob'), 'mzxw6yq=');
+        $this->assertSame(Base32::encode('fooba'), 'mzxw6ytb');
+        $this->assertSame(Base32::encode('foobar'), 'mzxw6ytboi======');
+
+        $this->assertSame(Base32::encodeUpper(''), '');
+        $this->assertSame(Base32::encodeUpper('f'), 'MY======');
+        $this->assertSame(Base32::encodeUpper('fo'), 'MZXQ====');
+        $this->assertSame(Base32::encodeUpper('foo'), 'MZXW6===');
+        $this->assertSame(Base32::encodeUpper('foob'), 'MZXW6YQ=');
+        $this->assertSame(Base32::encodeUpper('fooba'), 'MZXW6YTB');
+        $this->assertSame(Base32::encodeUpper('foobar'), 'MZXW6YTBOI======');
+    }
+
+    public function testVectorBase32Hex()
+    {
+        $this->assertSame(Base32Hex::encode(''), '');
+        $this->assertSame(Base32Hex::encode('f'), 'co======');
+        $this->assertSame(Base32Hex::encode('fo'), 'cpng====');
+        $this->assertSame(Base32Hex::encode('foo'), 'cpnmu===');
+        $this->assertSame(Base32Hex::encode('foob'), 'cpnmuog=');
+        $this->assertSame(Base32Hex::encode('fooba'), 'cpnmuoj1');
+        $this->assertSame(Base32Hex::encode('foobar'), 'cpnmuoj1e8======');
+
+        $this->assertSame(Base32Hex::encodeUpper(''), '');
+        $this->assertSame(Base32Hex::encodeUpper('f'), 'CO======');
+        $this->assertSame(Base32Hex::encodeUpper('fo'), 'CPNG====');
+        $this->assertSame(Base32Hex::encodeUpper('foo'), 'CPNMU===');
+        $this->assertSame(Base32Hex::encodeUpper('foob'), 'CPNMUOG=');
+        $this->assertSame(Base32Hex::encodeUpper('fooba'), 'CPNMUOJ1');
+        $this->assertSame(Base32Hex::encodeUpper('foobar'), 'CPNMUOJ1E8======');
+    }
+
+    public function testVectorBase16()
+    {
+        $this->assertSame(Hex::encode(''), '');
+        $this->assertSame(Hex::encode('f'), '66');
+        $this->assertSame(Hex::encode('fo'), '666f');
+        $this->assertSame(Hex::encode('foo'), '666f6f');
+        $this->assertSame(Hex::encode('foob'), '666f6f62');
+        $this->assertSame(Hex::encode('fooba'), '666f6f6261');
+        $this->assertSame(Hex::encode('foobar'), '666f6f626172');
+
+        $this->assertSame(Hex::encodeUpper(''), '');
+        $this->assertSame(Hex::encodeUpper('f'), '66');
+        $this->assertSame(Hex::encodeUpper('fo'), '666F');
+        $this->assertSame(Hex::encodeUpper('foo'), '666F6F');
+        $this->assertSame(Hex::encodeUpper('foob'), '666F6F62');
+        $this->assertSame(Hex::encodeUpper('fooba'), '666F6F6261');
+        $this->assertSame(Hex::encodeUpper('foobar'), '666F6F626172');
+    }
+}
diff --git a/vendor/paragonie/random_compat/LICENSE b/vendor/paragonie/random_compat/LICENSE
new file mode 100644
index 0000000000000000000000000000000000000000..45c7017dfb33dd003ee038cc9232d2430ffbf9a2
--- /dev/null
+++ b/vendor/paragonie/random_compat/LICENSE
@@ -0,0 +1,22 @@
+The MIT License (MIT)
+
+Copyright (c) 2015 Paragon Initiative Enterprises
+
+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/paragonie/random_compat/build-phar.sh b/vendor/paragonie/random_compat/build-phar.sh
new file mode 100755
index 0000000000000000000000000000000000000000..b4a5ba31cc7bbd042027b4c111e224c4c99f4fc5
--- /dev/null
+++ b/vendor/paragonie/random_compat/build-phar.sh
@@ -0,0 +1,5 @@
+#!/usr/bin/env bash
+
+basedir=$( dirname $( readlink -f ${BASH_SOURCE[0]} ) )
+
+php -dphar.readonly=0 "$basedir/other/build_phar.php" $*
\ No newline at end of file
diff --git a/vendor/paragonie/random_compat/composer.json b/vendor/paragonie/random_compat/composer.json
new file mode 100644
index 0000000000000000000000000000000000000000..1fa8de9f1bc98e22e9fd47d12ae4c9582bdf87ba
--- /dev/null
+++ b/vendor/paragonie/random_compat/composer.json
@@ -0,0 +1,34 @@
+{
+  "name":         "paragonie/random_compat",
+  "description":  "PHP 5.x polyfill for random_bytes() and random_int() from PHP 7",
+  "keywords": [
+    "csprng",
+    "random",
+    "polyfill",
+    "pseudorandom"
+  ],
+  "license":      "MIT",
+  "type":         "library",
+  "authors": [
+    {
+      "name":     "Paragon Initiative Enterprises",
+      "email":    "security@paragonie.com",
+      "homepage": "https://paragonie.com"
+    }
+  ],
+  "support": {
+    "issues":     "https://github.com/paragonie/random_compat/issues",
+    "email":      "info@paragonie.com",
+    "source":     "https://github.com/paragonie/random_compat"
+  },
+  "require": {
+    "php": "^7"
+  },
+  "require-dev": {
+    "vimeo/psalm": "^1",
+    "phpunit/phpunit": "4.*|5.*"
+  },
+  "suggest": {
+    "ext-libsodium": "Provides a modern crypto API that can be used to generate random bytes."
+  }
+}
diff --git a/vendor/paragonie/random_compat/lib/random.php b/vendor/paragonie/random_compat/lib/random.php
new file mode 100644
index 0000000000000000000000000000000000000000..c7731a56ff02161ee3d3c7d68fc466364490c2b2
--- /dev/null
+++ b/vendor/paragonie/random_compat/lib/random.php
@@ -0,0 +1,32 @@
+<?php
+/**
+ * Random_* Compatibility Library
+ * for using the new PHP 7 random_* API in PHP 5 projects
+ *
+ * @version 2.99.99
+ * @released 2018-06-06
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2015 - 2018 Paragon Initiative Enterprises
+ *
+ * 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.
+ */
+
+// NOP
diff --git a/vendor/paragonie/random_compat/other/build_phar.php b/vendor/paragonie/random_compat/other/build_phar.php
new file mode 100644
index 0000000000000000000000000000000000000000..70ef4b2ed838a6bf32d64e3da4c26f9d367e6ab5
--- /dev/null
+++ b/vendor/paragonie/random_compat/other/build_phar.php
@@ -0,0 +1,57 @@
+<?php
+$dist = dirname(__DIR__).'/dist';
+if (!is_dir($dist)) {
+    mkdir($dist, 0755);
+}
+if (file_exists($dist.'/random_compat.phar')) {
+    unlink($dist.'/random_compat.phar');
+}
+$phar = new Phar(
+    $dist.'/random_compat.phar',
+    FilesystemIterator::CURRENT_AS_FILEINFO | \FilesystemIterator::KEY_AS_FILENAME,
+    'random_compat.phar'
+);
+rename(
+    dirname(__DIR__).'/lib/random.php', 
+    dirname(__DIR__).'/lib/index.php'
+);
+$phar->buildFromDirectory(dirname(__DIR__).'/lib');
+rename(
+    dirname(__DIR__).'/lib/index.php', 
+    dirname(__DIR__).'/lib/random.php'
+);
+
+/**
+ * If we pass an (optional) path to a private key as a second argument, we will
+ * sign the Phar with OpenSSL.
+ * 
+ * If you leave this out, it will produce an unsigned .phar!
+ */
+if ($argc > 1) {
+    if (!@is_readable($argv[1])) {
+        echo 'Could not read the private key file:', $argv[1], "\n";
+        exit(255);
+    }
+    $pkeyFile = file_get_contents($argv[1]);
+    
+    $private = openssl_get_privatekey($pkeyFile);
+    if ($private !== false) {
+        $pkey = '';
+        openssl_pkey_export($private, $pkey);
+        $phar->setSignatureAlgorithm(Phar::OPENSSL, $pkey);
+        
+        /**
+         * Save the corresponding public key to the file
+         */
+        if (!@is_readable($dist.'/random_compat.phar.pubkey')) {
+            $details = openssl_pkey_get_details($private);
+            file_put_contents(
+                $dist.'/random_compat.phar.pubkey',
+                $details['key']
+            );
+        }
+    } else {
+        echo 'An error occurred reading the private key from OpenSSL.', "\n";
+        exit(255);
+    }
+}
diff --git a/vendor/paragonie/random_compat/psalm-autoload.php b/vendor/paragonie/random_compat/psalm-autoload.php
new file mode 100644
index 0000000000000000000000000000000000000000..d71d1b818c311072207e3ee4abff9f82a10d2fa9
--- /dev/null
+++ b/vendor/paragonie/random_compat/psalm-autoload.php
@@ -0,0 +1,9 @@
+<?php
+
+require_once 'lib/byte_safe_strings.php';
+require_once 'lib/cast_to_int.php';
+require_once 'lib/error_polyfill.php';
+require_once 'other/ide_stubs/libsodium.php';
+require_once 'lib/random.php';
+
+$int = random_int(0, 65536);
diff --git a/vendor/paragonie/random_compat/psalm.xml b/vendor/paragonie/random_compat/psalm.xml
new file mode 100644
index 0000000000000000000000000000000000000000..596d99dd6b7751496681dda7e8361296ad3628d3
--- /dev/null
+++ b/vendor/paragonie/random_compat/psalm.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0"?>
+<psalm
+    autoloader="psalm-autoload.php"
+    stopOnFirstError="false"
+    useDocblockTypes="true"
+>
+    <projectFiles>
+        <directory name="lib" />
+    </projectFiles>
+    <issueHandlers>
+        <RedundantConditionGivenDocblockType errorLevel="info" />
+        <UnresolvableInclude errorLevel="info" />
+        <DuplicateClass errorLevel="info" />
+        <InvalidOperand errorLevel="info" />
+        <UndefinedConstant errorLevel="info" />
+        <MissingReturnType errorLevel="info" />
+        <InvalidReturnType errorLevel="info" />
+    </issueHandlers>
+</psalm>
diff --git a/vendor/phar-io/manifest/CHANGELOG.md b/vendor/phar-io/manifest/CHANGELOG.md
new file mode 100644
index 0000000000000000000000000000000000000000..b777a36e51e7152cf64de782bba4cc855e8dddd7
--- /dev/null
+++ b/vendor/phar-io/manifest/CHANGELOG.md
@@ -0,0 +1,25 @@
+# Changelog
+
+All notable changes to phar-io/manifest are documented in this file using the [Keep a CHANGELOG](http://keepachangelog.com/) principles.
+
+## [2.0.1] - 27.06.2020
+
+This release now supports the use of PHP 7.2+ and ^8.0
+
+## [2.0.0] - 10.05.2020
+
+This release now requires PHP 7.2+
+
+### Changed
+
+- Upgraded to phar-io/version 3.0
+    - Version strings `v1.2.3` will now be converted to valid semantic version strings `1.2.3`
+    - Abreviated strings like `1.0` will get expaneded to `1.0.0`  
+
+### Unreleased
+
+[Unreleased]: https://github.com/phar-io/version/compare/2.0.0...HEAD
+[2.0.0]: https://github.com/phar-io/version/compare/1.0.1...2.0.0
+[1.0.3]: https://github.com/phar-io/version/compare/1.0.2...1.0.3
+[1.0.2]: https://github.com/phar-io/version/compare/1.0.1...1.0.2
+[1.0.1]: https://github.com/phar-io/version/compare/1.0.0...1.0.1
diff --git a/vendor/phar-io/manifest/LICENSE b/vendor/phar-io/manifest/LICENSE
new file mode 100644
index 0000000000000000000000000000000000000000..64690cf2bf2cab92e769e3272d4ad765b8fff248
--- /dev/null
+++ b/vendor/phar-io/manifest/LICENSE
@@ -0,0 +1,31 @@
+Phar.io - Manifest
+
+Copyright (c) 2016-2019 Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>, and contributors
+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 Arne Blankerts nor the names of 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 HOLDER 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/phar-io/manifest/README.md b/vendor/phar-io/manifest/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..e6d0b055d1540e960a72098e54db25e885566f37
--- /dev/null
+++ b/vendor/phar-io/manifest/README.md
@@ -0,0 +1,30 @@
+# Manifest
+
+Component for reading [phar.io](https://phar.io/) manifest information from a [PHP Archive (PHAR)](http://php.net/phar).
+
+[![Build Status](https://travis-ci.org/phar-io/manifest.svg?branch=master)](https://travis-ci.org/phar-io/manifest)
+[![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/phar-io/manifest/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/phar-io/manifest/?branch=master)
+[![SensioLabsInsight](https://insight.sensiolabs.com/projects/d8cc6035-69ad-477d-bd1a-ccc605480fd7/mini.png)](https://insight.sensiolabs.com/projects/d8cc6035-69ad-477d-bd1a-ccc605480fd7)
+
+## Installation
+
+You can add this library as a local, per-project dependency to your project using [Composer](https://getcomposer.org/):
+
+    composer require phar-io/manifest
+
+If you only need this library during development, for instance to run your project's test suite, then you should add it as a development-time dependency:
+
+    composer require --dev phar-io/manifest
+
+## Usage
+
+```php
+use PharIo\Manifest\ManifestLoader;
+use PharIo\Manifest\ManifestSerializer;
+
+$manifest = ManifestLoader::fromFile('manifest.xml');
+
+var_dump($manifest);
+
+echo (new ManifestSerializer)->serializeToString($manifest);
+```
diff --git a/vendor/phar-io/manifest/composer.json b/vendor/phar-io/manifest/composer.json
new file mode 100644
index 0000000000000000000000000000000000000000..a2521193a986d65e3f4a54a8ae512f8050c4d71e
--- /dev/null
+++ b/vendor/phar-io/manifest/composer.json
@@ -0,0 +1,42 @@
+{
+  "name": "phar-io/manifest",
+  "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)",
+  "license": "BSD-3-Clause",
+  "authors": [
+    {
+      "name": "Arne Blankerts",
+      "email": "arne@blankerts.de",
+      "role": "Developer"
+    },
+    {
+      "name": "Sebastian Heuer",
+      "email": "sebastian@phpeople.de",
+      "role": "Developer"
+    },
+    {
+      "name": "Sebastian Bergmann",
+      "email": "sebastian@phpunit.de",
+      "role": "Developer"
+    }
+  ],
+  "support": {
+    "issues": "https://github.com/phar-io/manifest/issues"
+  },
+  "require": {
+    "php": "^7.2 || ^8.0",
+    "ext-dom": "*",
+    "ext-phar": "*",
+    "ext-xmlwriter": "*",
+    "phar-io/version": "^3.0.1"
+  },
+  "autoload": {
+    "classmap": [
+      "src/"
+    ]
+  },
+  "extra": {
+    "branch-alias": {
+        "dev-master": "2.0.x-dev"
+    }
+  }
+}
diff --git a/vendor/phar-io/manifest/src/ManifestDocumentMapper.php b/vendor/phar-io/manifest/src/ManifestDocumentMapper.php
new file mode 100644
index 0000000000000000000000000000000000000000..8e539d5f1d66e37cc5ca53fb601fe44837821c77
--- /dev/null
+++ b/vendor/phar-io/manifest/src/ManifestDocumentMapper.php
@@ -0,0 +1,150 @@
+<?php declare(strict_types = 1);
+/*
+ * This file is part of PharIo\Manifest.
+ *
+ * (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PharIo\Manifest;
+
+use PharIo\Version\Exception as VersionException;
+use PharIo\Version\Version;
+use PharIo\Version\VersionConstraintParser;
+
+class ManifestDocumentMapper {
+    public function map(ManifestDocument $document): Manifest {
+        try {
+            $contains          = $document->getContainsElement();
+            $type              = $this->mapType($contains);
+            $copyright         = $this->mapCopyright($document->getCopyrightElement());
+            $requirements      = $this->mapRequirements($document->getRequiresElement());
+            $bundledComponents = $this->mapBundledComponents($document);
+
+            return new Manifest(
+                new ApplicationName($contains->getName()),
+                new Version($contains->getVersion()),
+                $type,
+                $copyright,
+                $requirements,
+                $bundledComponents
+            );
+        } catch (VersionException $e) {
+            throw new ManifestDocumentMapperException($e->getMessage(), (int)$e->getCode(), $e);
+        } catch (Exception $e) {
+            throw new ManifestDocumentMapperException($e->getMessage(), (int)$e->getCode(), $e);
+        }
+    }
+
+    private function mapType(ContainsElement $contains): Type {
+        switch ($contains->getType()) {
+            case 'application':
+                return Type::application();
+            case 'library':
+                return Type::library();
+            case 'extension':
+                return $this->mapExtension($contains->getExtensionElement());
+        }
+
+        throw new ManifestDocumentMapperException(
+            \sprintf('Unsupported type %s', $contains->getType())
+        );
+    }
+
+    private function mapCopyright(CopyrightElement $copyright): CopyrightInformation {
+        $authors = new AuthorCollection();
+
+        foreach ($copyright->getAuthorElements() as $authorElement) {
+            $authors->add(
+                new Author(
+                    $authorElement->getName(),
+                    new Email($authorElement->getEmail())
+                )
+            );
+        }
+
+        $licenseElement = $copyright->getLicenseElement();
+        $license        = new License(
+            $licenseElement->getType(),
+            new Url($licenseElement->getUrl())
+        );
+
+        return new CopyrightInformation(
+            $authors,
+            $license
+        );
+    }
+
+    private function mapRequirements(RequiresElement $requires): RequirementCollection {
+        $collection = new RequirementCollection();
+        $phpElement = $requires->getPHPElement();
+        $parser     = new VersionConstraintParser;
+
+        try {
+            $versionConstraint = $parser->parse($phpElement->getVersion());
+        } catch (VersionException $e) {
+            throw new ManifestDocumentMapperException(
+                \sprintf('Unsupported version constraint - %s', $e->getMessage()),
+                (int)$e->getCode(),
+                $e
+            );
+        }
+
+        $collection->add(
+            new PhpVersionRequirement(
+                $versionConstraint
+            )
+        );
+
+        if (!$phpElement->hasExtElements()) {
+            return $collection;
+        }
+
+        foreach ($phpElement->getExtElements() as $extElement) {
+            $collection->add(
+                new PhpExtensionRequirement($extElement->getName())
+            );
+        }
+
+        return $collection;
+    }
+
+    private function mapBundledComponents(ManifestDocument $document): BundledComponentCollection {
+        $collection = new BundledComponentCollection();
+
+        if (!$document->hasBundlesElement()) {
+            return $collection;
+        }
+
+        foreach ($document->getBundlesElement()->getComponentElements() as $componentElement) {
+            $collection->add(
+                new BundledComponent(
+                    $componentElement->getName(),
+                    new Version(
+                        $componentElement->getVersion()
+                    )
+                )
+            );
+        }
+
+        return $collection;
+    }
+
+    private function mapExtension(ExtensionElement $extension): Extension {
+        try {
+            $versionConstraint = (new VersionConstraintParser)->parse($extension->getCompatible());
+
+            return Type::extension(
+                new ApplicationName($extension->getFor()),
+                $versionConstraint
+            );
+        } catch (VersionException $e) {
+            throw new ManifestDocumentMapperException(
+                \sprintf('Unsupported version constraint - %s', $e->getMessage()),
+                (int)$e->getCode(),
+                $e
+            );
+        }
+    }
+}
diff --git a/vendor/phar-io/manifest/src/ManifestLoader.php b/vendor/phar-io/manifest/src/ManifestLoader.php
new file mode 100644
index 0000000000000000000000000000000000000000..ae884e49a026d671245a8a0a1ade41a704868053
--- /dev/null
+++ b/vendor/phar-io/manifest/src/ManifestLoader.php
@@ -0,0 +1,44 @@
+<?php declare(strict_types = 1);
+/*
+ * This file is part of PharIo\Manifest.
+ *
+ * (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PharIo\Manifest;
+
+class ManifestLoader {
+    public static function fromFile(string $filename): Manifest {
+        try {
+            return (new ManifestDocumentMapper())->map(
+                ManifestDocument::fromFile($filename)
+            );
+        } catch (Exception $e) {
+            throw new ManifestLoaderException(
+                \sprintf('Loading %s failed.', $filename),
+                (int)$e->getCode(),
+                $e
+            );
+        }
+    }
+
+    public static function fromPhar(string $filename): Manifest {
+        return self::fromFile('phar://' . $filename . '/manifest.xml');
+    }
+
+    public static function fromString(string $manifest): Manifest {
+        try {
+            return (new ManifestDocumentMapper())->map(
+                ManifestDocument::fromString($manifest)
+            );
+        } catch (Exception $e) {
+            throw new ManifestLoaderException(
+                'Processing string failed',
+                (int)$e->getCode(),
+                $e
+            );
+        }
+    }
+}
diff --git a/vendor/phar-io/manifest/src/ManifestSerializer.php b/vendor/phar-io/manifest/src/ManifestSerializer.php
new file mode 100644
index 0000000000000000000000000000000000000000..e236b5984cc5f33e0bfb82d5aa9d1165b530582f
--- /dev/null
+++ b/vendor/phar-io/manifest/src/ManifestSerializer.php
@@ -0,0 +1,168 @@
+<?php declare(strict_types = 1);
+/*
+ * This file is part of PharIo\Manifest.
+ *
+ * (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PharIo\Manifest;
+
+use PharIo\Version\AnyVersionConstraint;
+use PharIo\Version\Version;
+use PharIo\Version\VersionConstraint;
+use XMLWriter;
+
+/** @psalm-suppress MissingConstructor */
+class ManifestSerializer {
+    /** @var XMLWriter */
+    private $xmlWriter;
+
+    public function serializeToFile(Manifest $manifest, string $filename): void {
+        \file_put_contents(
+            $filename,
+            $this->serializeToString($manifest)
+        );
+    }
+
+    public function serializeToString(Manifest $manifest): string {
+        $this->startDocument();
+
+        $this->addContains($manifest->getName(), $manifest->getVersion(), $manifest->getType());
+        $this->addCopyright($manifest->getCopyrightInformation());
+        $this->addRequirements($manifest->getRequirements());
+        $this->addBundles($manifest->getBundledComponents());
+
+        return $this->finishDocument();
+    }
+
+    private function startDocument(): void {
+        $xmlWriter = new XMLWriter();
+        $xmlWriter->openMemory();
+        $xmlWriter->setIndent(true);
+        $xmlWriter->setIndentString(\str_repeat(' ', 4));
+        $xmlWriter->startDocument('1.0', 'UTF-8');
+        $xmlWriter->startElement('phar');
+        $xmlWriter->writeAttribute('xmlns', 'https://phar.io/xml/manifest/1.0');
+
+        $this->xmlWriter = $xmlWriter;
+    }
+
+    private function finishDocument(): string {
+        $this->xmlWriter->endElement();
+        $this->xmlWriter->endDocument();
+
+        return $this->xmlWriter->outputMemory();
+    }
+
+    private function addContains(ApplicationName $name, Version $version, Type $type): void {
+        $this->xmlWriter->startElement('contains');
+        $this->xmlWriter->writeAttribute('name', $name->asString());
+        $this->xmlWriter->writeAttribute('version', $version->getVersionString());
+
+        switch (true) {
+            case $type->isApplication(): {
+                $this->xmlWriter->writeAttribute('type', 'application');
+
+                break;
+            }
+
+            case $type->isLibrary(): {
+                $this->xmlWriter->writeAttribute('type', 'library');
+
+                break;
+            }
+
+            case $type->isExtension(): {
+                $this->xmlWriter->writeAttribute('type', 'extension');
+                /* @var $type Extension */
+                $this->addExtension(
+                    $type->getApplicationName(),
+                    $type->getVersionConstraint()
+                );
+
+                break;
+            }
+
+            default: {
+                $this->xmlWriter->writeAttribute('type', 'custom');
+            }
+        }
+
+        $this->xmlWriter->endElement();
+    }
+
+    private function addCopyright(CopyrightInformation $copyrightInformation): void {
+        $this->xmlWriter->startElement('copyright');
+
+        foreach ($copyrightInformation->getAuthors() as $author) {
+            $this->xmlWriter->startElement('author');
+            $this->xmlWriter->writeAttribute('name', $author->getName());
+            $this->xmlWriter->writeAttribute('email', $author->getEmail()->asString());
+            $this->xmlWriter->endElement();
+        }
+
+        $license = $copyrightInformation->getLicense();
+
+        $this->xmlWriter->startElement('license');
+        $this->xmlWriter->writeAttribute('type', $license->getName());
+        $this->xmlWriter->writeAttribute('url', $license->getUrl()->asString());
+        $this->xmlWriter->endElement();
+
+        $this->xmlWriter->endElement();
+    }
+
+    private function addRequirements(RequirementCollection $requirementCollection): void {
+        $phpRequirement = new AnyVersionConstraint();
+        $extensions     = [];
+
+        foreach ($requirementCollection as $requirement) {
+            if ($requirement instanceof PhpVersionRequirement) {
+                $phpRequirement = $requirement->getVersionConstraint();
+
+                continue;
+            }
+
+            if ($requirement instanceof PhpExtensionRequirement) {
+                $extensions[] = $requirement->asString();
+            }
+        }
+
+        $this->xmlWriter->startElement('requires');
+        $this->xmlWriter->startElement('php');
+        $this->xmlWriter->writeAttribute('version', $phpRequirement->asString());
+
+        foreach ($extensions as $extension) {
+            $this->xmlWriter->startElement('ext');
+            $this->xmlWriter->writeAttribute('name', $extension);
+            $this->xmlWriter->endElement();
+        }
+
+        $this->xmlWriter->endElement();
+        $this->xmlWriter->endElement();
+    }
+
+    private function addBundles(BundledComponentCollection $bundledComponentCollection): void {
+        if (\count($bundledComponentCollection) === 0) {
+            return;
+        }
+        $this->xmlWriter->startElement('bundles');
+
+        foreach ($bundledComponentCollection as $bundledComponent) {
+            $this->xmlWriter->startElement('component');
+            $this->xmlWriter->writeAttribute('name', $bundledComponent->getName());
+            $this->xmlWriter->writeAttribute('version', $bundledComponent->getVersion()->getVersionString());
+            $this->xmlWriter->endElement();
+        }
+
+        $this->xmlWriter->endElement();
+    }
+
+    private function addExtension(ApplicationName $applicationName, VersionConstraint $versionConstraint): void {
+        $this->xmlWriter->startElement('extension');
+        $this->xmlWriter->writeAttribute('for', $applicationName->asString());
+        $this->xmlWriter->writeAttribute('compatible', $versionConstraint->asString());
+        $this->xmlWriter->endElement();
+    }
+}
diff --git a/vendor/phar-io/manifest/src/exceptions/ElementCollectionException.php b/vendor/phar-io/manifest/src/exceptions/ElementCollectionException.php
new file mode 100644
index 0000000000000000000000000000000000000000..766fc0e6a1ed08ff374336ad21c9cf5d71b1b88b
--- /dev/null
+++ b/vendor/phar-io/manifest/src/exceptions/ElementCollectionException.php
@@ -0,0 +1,13 @@
+<?php declare(strict_types = 1);
+/*
+ * This file is part of PharIo\Manifest.
+ *
+ * (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PharIo\Manifest;
+
+class ElementCollectionException extends \InvalidArgumentException implements Exception {
+}
diff --git a/vendor/phar-io/manifest/src/exceptions/Exception.php b/vendor/phar-io/manifest/src/exceptions/Exception.php
new file mode 100644
index 0000000000000000000000000000000000000000..e7f122097751ed2b12a412e0871218b933e134c5
--- /dev/null
+++ b/vendor/phar-io/manifest/src/exceptions/Exception.php
@@ -0,0 +1,13 @@
+<?php declare(strict_types = 1);
+/*
+ * This file is part of PharIo\Manifest.
+ *
+ * (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PharIo\Manifest;
+
+interface Exception extends \Throwable {
+}
diff --git a/vendor/phar-io/manifest/src/exceptions/InvalidApplicationNameException.php b/vendor/phar-io/manifest/src/exceptions/InvalidApplicationNameException.php
new file mode 100644
index 0000000000000000000000000000000000000000..952901eb526ebf0ad2f878a60468277d56b7a925
--- /dev/null
+++ b/vendor/phar-io/manifest/src/exceptions/InvalidApplicationNameException.php
@@ -0,0 +1,14 @@
+<?php declare(strict_types = 1);
+/*
+ * This file is part of PharIo\Manifest.
+ *
+ * (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PharIo\Manifest;
+
+class InvalidApplicationNameException extends \InvalidArgumentException implements Exception {
+    public const InvalidFormat = 2;
+}
diff --git a/vendor/phar-io/manifest/src/exceptions/InvalidEmailException.php b/vendor/phar-io/manifest/src/exceptions/InvalidEmailException.php
new file mode 100644
index 0000000000000000000000000000000000000000..3cbe08223c95713613a99d2ecf41257cb3ab7c34
--- /dev/null
+++ b/vendor/phar-io/manifest/src/exceptions/InvalidEmailException.php
@@ -0,0 +1,13 @@
+<?php declare(strict_types = 1);
+/*
+ * This file is part of PharIo\Manifest.
+ *
+ * (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PharIo\Manifest;
+
+class InvalidEmailException extends \InvalidArgumentException implements Exception {
+}
diff --git a/vendor/phar-io/manifest/src/exceptions/InvalidUrlException.php b/vendor/phar-io/manifest/src/exceptions/InvalidUrlException.php
new file mode 100644
index 0000000000000000000000000000000000000000..8f77e2946e70160a18f47a1dfbaf0ffbcda71a4e
--- /dev/null
+++ b/vendor/phar-io/manifest/src/exceptions/InvalidUrlException.php
@@ -0,0 +1,13 @@
+<?php declare(strict_types = 1);
+/*
+ * This file is part of PharIo\Manifest.
+ *
+ * (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PharIo\Manifest;
+
+class InvalidUrlException extends \InvalidArgumentException implements Exception {
+}
diff --git a/vendor/phar-io/manifest/src/exceptions/ManifestDocumentException.php b/vendor/phar-io/manifest/src/exceptions/ManifestDocumentException.php
new file mode 100644
index 0000000000000000000000000000000000000000..cf1c314c6f8263fc201e1c5934d8ed46681110ea
--- /dev/null
+++ b/vendor/phar-io/manifest/src/exceptions/ManifestDocumentException.php
@@ -0,0 +1,5 @@
+<?php declare(strict_types = 1);
+namespace PharIo\Manifest;
+
+class ManifestDocumentException extends \RuntimeException implements Exception {
+}
diff --git a/vendor/phar-io/manifest/src/exceptions/ManifestDocumentLoadingException.php b/vendor/phar-io/manifest/src/exceptions/ManifestDocumentLoadingException.php
new file mode 100644
index 0000000000000000000000000000000000000000..4676e35465b2406d3e0a5db2a5d67d7dc64294d6
--- /dev/null
+++ b/vendor/phar-io/manifest/src/exceptions/ManifestDocumentLoadingException.php
@@ -0,0 +1,45 @@
+<?php declare(strict_types = 1);
+/*
+ * This file is part of PharIo\Manifest.
+ *
+ * (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PharIo\Manifest;
+
+use LibXMLError;
+
+class ManifestDocumentLoadingException extends \Exception implements Exception {
+    /** @var LibXMLError[] */
+    private $libxmlErrors;
+
+    /**
+     * ManifestDocumentLoadingException constructor.
+     *
+     * @param LibXMLError[] $libxmlErrors
+     */
+    public function __construct(array $libxmlErrors) {
+        $this->libxmlErrors = $libxmlErrors;
+        $first              = $this->libxmlErrors[0];
+
+        parent::__construct(
+            \sprintf(
+                '%s (Line: %d / Column: %d / File: %s)',
+                $first->message,
+                $first->line,
+                $first->column,
+                $first->file
+            ),
+            $first->code
+        );
+    }
+
+    /**
+     * @return LibXMLError[]
+     */
+    public function getLibxmlErrors(): array {
+        return $this->libxmlErrors;
+    }
+}
diff --git a/vendor/phar-io/manifest/src/exceptions/ManifestDocumentMapperException.php b/vendor/phar-io/manifest/src/exceptions/ManifestDocumentMapperException.php
new file mode 100644
index 0000000000000000000000000000000000000000..43373bd346666296ce96319973421c1c3f59e56d
--- /dev/null
+++ b/vendor/phar-io/manifest/src/exceptions/ManifestDocumentMapperException.php
@@ -0,0 +1,5 @@
+<?php declare(strict_types = 1);
+namespace PharIo\Manifest;
+
+class ManifestDocumentMapperException extends \RuntimeException implements Exception {
+}
diff --git a/vendor/phar-io/manifest/src/exceptions/ManifestElementException.php b/vendor/phar-io/manifest/src/exceptions/ManifestElementException.php
new file mode 100644
index 0000000000000000000000000000000000000000..a4e772369d7790062fdf281fc61cb8c7514b5705
--- /dev/null
+++ b/vendor/phar-io/manifest/src/exceptions/ManifestElementException.php
@@ -0,0 +1,5 @@
+<?php declare(strict_types = 1);
+namespace PharIo\Manifest;
+
+class ManifestElementException extends \RuntimeException implements Exception {
+}
diff --git a/vendor/phar-io/manifest/src/exceptions/ManifestLoaderException.php b/vendor/phar-io/manifest/src/exceptions/ManifestLoaderException.php
new file mode 100644
index 0000000000000000000000000000000000000000..df0971edc75130a32452cef0127d7241ec1a0578
--- /dev/null
+++ b/vendor/phar-io/manifest/src/exceptions/ManifestLoaderException.php
@@ -0,0 +1,5 @@
+<?php declare(strict_types = 1);
+namespace PharIo\Manifest;
+
+class ManifestLoaderException extends \Exception implements Exception {
+}
diff --git a/vendor/phar-io/manifest/src/values/Application.php b/vendor/phar-io/manifest/src/values/Application.php
new file mode 100644
index 0000000000000000000000000000000000000000..5420bcb8f2aa343ec3831eb8f8559dbe48a9bf98
--- /dev/null
+++ b/vendor/phar-io/manifest/src/values/Application.php
@@ -0,0 +1,16 @@
+<?php declare(strict_types = 1);
+/*
+ * This file is part of PharIo\Manifest.
+ *
+ * (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PharIo\Manifest;
+
+class Application extends Type {
+    public function isApplication(): bool {
+        return true;
+    }
+}
diff --git a/vendor/phar-io/manifest/src/values/ApplicationName.php b/vendor/phar-io/manifest/src/values/ApplicationName.php
new file mode 100644
index 0000000000000000000000000000000000000000..d71744ab6dd36ca31efc2b40dd9d298de5266937
--- /dev/null
+++ b/vendor/phar-io/manifest/src/values/ApplicationName.php
@@ -0,0 +1,37 @@
+<?php declare(strict_types = 1);
+/*
+ * This file is part of PharIo\Manifest.
+ *
+ * (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PharIo\Manifest;
+
+class ApplicationName {
+    /** @var string */
+    private $name;
+
+    public function __construct(string $name) {
+        $this->ensureValidFormat($name);
+        $this->name = $name;
+    }
+
+    public function asString(): string {
+        return $this->name;
+    }
+
+    public function isEqual(ApplicationName $name): bool {
+        return $this->name === $name->name;
+    }
+
+    private function ensureValidFormat(string $name): void {
+        if (!\preg_match('#\w/\w#', $name)) {
+            throw new InvalidApplicationNameException(
+                \sprintf('Format of name "%s" is not valid - expected: vendor/packagename', $name),
+                InvalidApplicationNameException::InvalidFormat
+            );
+        }
+    }
+}
diff --git a/vendor/phar-io/manifest/src/values/Author.php b/vendor/phar-io/manifest/src/values/Author.php
new file mode 100644
index 0000000000000000000000000000000000000000..82b666e7d6da4689b41246c8bfe3f829e34ea695
--- /dev/null
+++ b/vendor/phar-io/manifest/src/values/Author.php
@@ -0,0 +1,39 @@
+<?php declare(strict_types = 1);
+/*
+ * This file is part of PharIo\Manifest.
+ *
+ * (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PharIo\Manifest;
+
+class Author {
+    /** @var string */
+    private $name;
+
+    /** @var Email */
+    private $email;
+
+    public function __construct(string $name, Email $email) {
+        $this->name  = $name;
+        $this->email = $email;
+    }
+
+    public function asString(): string {
+        return \sprintf(
+            '%s <%s>',
+            $this->name,
+            $this->email->asString()
+        );
+    }
+
+    public function getName(): string {
+        return $this->name;
+    }
+
+    public function getEmail(): Email {
+        return $this->email;
+    }
+}
diff --git a/vendor/phar-io/manifest/src/values/AuthorCollection.php b/vendor/phar-io/manifest/src/values/AuthorCollection.php
new file mode 100644
index 0000000000000000000000000000000000000000..27e50ad845caa11174ed354481c0f76ea77de009
--- /dev/null
+++ b/vendor/phar-io/manifest/src/values/AuthorCollection.php
@@ -0,0 +1,34 @@
+<?php declare(strict_types = 1);
+/*
+ * This file is part of PharIo\Manifest.
+ *
+ * (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PharIo\Manifest;
+
+class AuthorCollection implements \Countable, \IteratorAggregate {
+    /** @var Author[] */
+    private $authors = [];
+
+    public function add(Author $author): void {
+        $this->authors[] = $author;
+    }
+
+    /**
+     * @return Author[]
+     */
+    public function getAuthors(): array {
+        return $this->authors;
+    }
+
+    public function count(): int {
+        return \count($this->authors);
+    }
+
+    public function getIterator(): AuthorCollectionIterator {
+        return new AuthorCollectionIterator($this);
+    }
+}
diff --git a/vendor/phar-io/manifest/src/values/AuthorCollectionIterator.php b/vendor/phar-io/manifest/src/values/AuthorCollectionIterator.php
new file mode 100644
index 0000000000000000000000000000000000000000..4ff3c39431669c46aeb9146c6f5560bcb28fbd1b
--- /dev/null
+++ b/vendor/phar-io/manifest/src/values/AuthorCollectionIterator.php
@@ -0,0 +1,42 @@
+<?php declare(strict_types = 1);
+/*
+ * This file is part of PharIo\Manifest.
+ *
+ * (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PharIo\Manifest;
+
+class AuthorCollectionIterator implements \Iterator {
+    /** @var Author[] */
+    private $authors;
+
+    /** @var int */
+    private $position = 0;
+
+    public function __construct(AuthorCollection $authors) {
+        $this->authors = $authors->getAuthors();
+    }
+
+    public function rewind(): void {
+        $this->position = 0;
+    }
+
+    public function valid(): bool {
+        return $this->position < \count($this->authors);
+    }
+
+    public function key(): int {
+        return $this->position;
+    }
+
+    public function current(): Author {
+        return $this->authors[$this->position];
+    }
+
+    public function next(): void {
+        $this->position++;
+    }
+}
diff --git a/vendor/phar-io/manifest/src/values/BundledComponent.php b/vendor/phar-io/manifest/src/values/BundledComponent.php
new file mode 100644
index 0000000000000000000000000000000000000000..ea77b4402c672f6a1fe2fd1d714c8aed0c813906
--- /dev/null
+++ b/vendor/phar-io/manifest/src/values/BundledComponent.php
@@ -0,0 +1,33 @@
+<?php declare(strict_types = 1);
+/*
+ * This file is part of PharIo\Manifest.
+ *
+ * (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PharIo\Manifest;
+
+use PharIo\Version\Version;
+
+class BundledComponent {
+    /** @var string */
+    private $name;
+
+    /** @var Version */
+    private $version;
+
+    public function __construct(string $name, Version $version) {
+        $this->name    = $name;
+        $this->version = $version;
+    }
+
+    public function getName(): string {
+        return $this->name;
+    }
+
+    public function getVersion(): Version {
+        return $this->version;
+    }
+}
diff --git a/vendor/phar-io/manifest/src/values/BundledComponentCollection.php b/vendor/phar-io/manifest/src/values/BundledComponentCollection.php
new file mode 100644
index 0000000000000000000000000000000000000000..b628eaa35853dd77bf766af72c27efca65143ef7
--- /dev/null
+++ b/vendor/phar-io/manifest/src/values/BundledComponentCollection.php
@@ -0,0 +1,34 @@
+<?php declare(strict_types = 1);
+/*
+ * This file is part of PharIo\Manifest.
+ *
+ * (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PharIo\Manifest;
+
+class BundledComponentCollection implements \Countable, \IteratorAggregate {
+    /** @var BundledComponent[] */
+    private $bundledComponents = [];
+
+    public function add(BundledComponent $bundledComponent): void {
+        $this->bundledComponents[] = $bundledComponent;
+    }
+
+    /**
+     * @return BundledComponent[]
+     */
+    public function getBundledComponents(): array {
+        return $this->bundledComponents;
+    }
+
+    public function count(): int {
+        return \count($this->bundledComponents);
+    }
+
+    public function getIterator(): BundledComponentCollectionIterator {
+        return new BundledComponentCollectionIterator($this);
+    }
+}
diff --git a/vendor/phar-io/manifest/src/values/BundledComponentCollectionIterator.php b/vendor/phar-io/manifest/src/values/BundledComponentCollectionIterator.php
new file mode 100644
index 0000000000000000000000000000000000000000..462db45a1f8fcc7be26fe6bbcd63fd7e0baeb5bf
--- /dev/null
+++ b/vendor/phar-io/manifest/src/values/BundledComponentCollectionIterator.php
@@ -0,0 +1,42 @@
+<?php declare(strict_types = 1);
+/*
+ * This file is part of PharIo\Manifest.
+ *
+ * (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PharIo\Manifest;
+
+class BundledComponentCollectionIterator implements \Iterator {
+    /** @var BundledComponent[] */
+    private $bundledComponents;
+
+    /** @var int */
+    private $position = 0;
+
+    public function __construct(BundledComponentCollection $bundledComponents) {
+        $this->bundledComponents = $bundledComponents->getBundledComponents();
+    }
+
+    public function rewind(): void {
+        $this->position = 0;
+    }
+
+    public function valid(): bool {
+        return $this->position < \count($this->bundledComponents);
+    }
+
+    public function key(): int {
+        return $this->position;
+    }
+
+    public function current(): BundledComponent {
+        return $this->bundledComponents[$this->position];
+    }
+
+    public function next(): void {
+        $this->position++;
+    }
+}
diff --git a/vendor/phar-io/manifest/src/values/CopyrightInformation.php b/vendor/phar-io/manifest/src/values/CopyrightInformation.php
new file mode 100644
index 0000000000000000000000000000000000000000..d26f947212d43e09b46b6844193c13459a5640a4
--- /dev/null
+++ b/vendor/phar-io/manifest/src/values/CopyrightInformation.php
@@ -0,0 +1,31 @@
+<?php declare(strict_types = 1);
+/*
+ * This file is part of PharIo\Manifest.
+ *
+ * (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PharIo\Manifest;
+
+class CopyrightInformation {
+    /** @var AuthorCollection */
+    private $authors;
+
+    /** @var License */
+    private $license;
+
+    public function __construct(AuthorCollection $authors, License $license) {
+        $this->authors = $authors;
+        $this->license = $license;
+    }
+
+    public function getAuthors(): AuthorCollection {
+        return $this->authors;
+    }
+
+    public function getLicense(): License {
+        return $this->license;
+    }
+}
diff --git a/vendor/phar-io/manifest/src/values/Email.php b/vendor/phar-io/manifest/src/values/Email.php
new file mode 100644
index 0000000000000000000000000000000000000000..588348d8900b6c6f11601d5cef0a304005056462
--- /dev/null
+++ b/vendor/phar-io/manifest/src/values/Email.php
@@ -0,0 +1,31 @@
+<?php declare(strict_types = 1);
+/*
+ * This file is part of PharIo\Manifest.
+ *
+ * (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PharIo\Manifest;
+
+class Email {
+    /** @var string */
+    private $email;
+
+    public function __construct(string $email) {
+        $this->ensureEmailIsValid($email);
+
+        $this->email = $email;
+    }
+
+    public function asString(): string {
+        return $this->email;
+    }
+
+    private function ensureEmailIsValid(string $url): void {
+        if (\filter_var($url, \FILTER_VALIDATE_EMAIL) === false) {
+            throw new InvalidEmailException;
+        }
+    }
+}
diff --git a/vendor/phar-io/manifest/src/values/Extension.php b/vendor/phar-io/manifest/src/values/Extension.php
new file mode 100644
index 0000000000000000000000000000000000000000..4c5726f8a93322f7927204a6cf16445ed7b26a3d
--- /dev/null
+++ b/vendor/phar-io/manifest/src/values/Extension.php
@@ -0,0 +1,46 @@
+<?php declare(strict_types = 1);
+/*
+ * This file is part of PharIo\Manifest.
+ *
+ * (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PharIo\Manifest;
+
+use PharIo\Version\Version;
+use PharIo\Version\VersionConstraint;
+
+class Extension extends Type {
+    /** @var ApplicationName */
+    private $application;
+
+    /** @var VersionConstraint */
+    private $versionConstraint;
+
+    public function __construct(ApplicationName $application, VersionConstraint $versionConstraint) {
+        $this->application       = $application;
+        $this->versionConstraint = $versionConstraint;
+    }
+
+    public function getApplicationName(): ApplicationName {
+        return $this->application;
+    }
+
+    public function getVersionConstraint(): VersionConstraint {
+        return $this->versionConstraint;
+    }
+
+    public function isExtension(): bool {
+        return true;
+    }
+
+    public function isExtensionFor(ApplicationName $name): bool {
+        return $this->application->isEqual($name);
+    }
+
+    public function isCompatibleWith(ApplicationName $name, Version $version): bool {
+        return $this->isExtensionFor($name) && $this->versionConstraint->complies($version);
+    }
+}
diff --git a/vendor/phar-io/manifest/src/values/Library.php b/vendor/phar-io/manifest/src/values/Library.php
new file mode 100644
index 0000000000000000000000000000000000000000..21849e137c434611cbc56309239ef2ab5b6eee4b
--- /dev/null
+++ b/vendor/phar-io/manifest/src/values/Library.php
@@ -0,0 +1,16 @@
+<?php declare(strict_types = 1);
+/*
+ * This file is part of PharIo\Manifest.
+ *
+ * (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PharIo\Manifest;
+
+class Library extends Type {
+    public function isLibrary(): bool {
+        return true;
+    }
+}
diff --git a/vendor/phar-io/manifest/src/values/License.php b/vendor/phar-io/manifest/src/values/License.php
new file mode 100644
index 0000000000000000000000000000000000000000..39542fe871d3b45162e3b7928147487434cc7f71
--- /dev/null
+++ b/vendor/phar-io/manifest/src/values/License.php
@@ -0,0 +1,31 @@
+<?php declare(strict_types = 1);
+/*
+ * This file is part of PharIo\Manifest.
+ *
+ * (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PharIo\Manifest;
+
+class License {
+    /** @var string */
+    private $name;
+
+    /** @var Url */
+    private $url;
+
+    public function __construct(string $name, Url $url) {
+        $this->name = $name;
+        $this->url  = $url;
+    }
+
+    public function getName(): string {
+        return $this->name;
+    }
+
+    public function getUrl(): Url {
+        return $this->url;
+    }
+}
diff --git a/vendor/phar-io/manifest/src/values/Manifest.php b/vendor/phar-io/manifest/src/values/Manifest.php
new file mode 100644
index 0000000000000000000000000000000000000000..0140b842b038224e5247e48036e3459034131a56
--- /dev/null
+++ b/vendor/phar-io/manifest/src/values/Manifest.php
@@ -0,0 +1,92 @@
+<?php declare(strict_types = 1);
+/*
+ * This file is part of PharIo\Manifest.
+ *
+ * (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PharIo\Manifest;
+
+use PharIo\Version\Version;
+
+class Manifest {
+    /** @var ApplicationName */
+    private $name;
+
+    /** @var Version */
+    private $version;
+
+    /** @var Type */
+    private $type;
+
+    /** @var CopyrightInformation */
+    private $copyrightInformation;
+
+    /** @var RequirementCollection */
+    private $requirements;
+
+    /** @var BundledComponentCollection */
+    private $bundledComponents;
+
+    public function __construct(ApplicationName $name, Version $version, Type $type, CopyrightInformation $copyrightInformation, RequirementCollection $requirements, BundledComponentCollection $bundledComponents) {
+        $this->name                 = $name;
+        $this->version              = $version;
+        $this->type                 = $type;
+        $this->copyrightInformation = $copyrightInformation;
+        $this->requirements         = $requirements;
+        $this->bundledComponents    = $bundledComponents;
+    }
+
+    public function getName(): ApplicationName {
+        return $this->name;
+    }
+
+    public function getVersion(): Version {
+        return $this->version;
+    }
+
+    public function getType(): Type {
+        return $this->type;
+    }
+
+    public function getCopyrightInformation(): CopyrightInformation {
+        return $this->copyrightInformation;
+    }
+
+    public function getRequirements(): RequirementCollection {
+        return $this->requirements;
+    }
+
+    public function getBundledComponents(): BundledComponentCollection {
+        return $this->bundledComponents;
+    }
+
+    public function isApplication(): bool {
+        return $this->type->isApplication();
+    }
+
+    public function isLibrary(): bool {
+        return $this->type->isLibrary();
+    }
+
+    public function isExtension(): bool {
+        return $this->type->isExtension();
+    }
+
+    public function isExtensionFor(ApplicationName $application, Version $version = null): bool {
+        if (!$this->isExtension()) {
+            return false;
+        }
+
+        /** @var Extension $type */
+        $type = $this->type;
+
+        if ($version !== null) {
+            return $type->isCompatibleWith($application, $version);
+        }
+
+        return $type->isExtensionFor($application);
+    }
+}
diff --git a/vendor/phar-io/manifest/src/values/PhpExtensionRequirement.php b/vendor/phar-io/manifest/src/values/PhpExtensionRequirement.php
new file mode 100644
index 0000000000000000000000000000000000000000..088f38584c332efef695a4d17eae73813f0e3e33
--- /dev/null
+++ b/vendor/phar-io/manifest/src/values/PhpExtensionRequirement.php
@@ -0,0 +1,23 @@
+<?php declare(strict_types = 1);
+/*
+ * This file is part of PharIo\Manifest.
+ *
+ * (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PharIo\Manifest;
+
+class PhpExtensionRequirement implements Requirement {
+    /** @var string */
+    private $extension;
+
+    public function __construct(string $extension) {
+        $this->extension = $extension;
+    }
+
+    public function asString(): string {
+        return $this->extension;
+    }
+}
diff --git a/vendor/phar-io/manifest/src/values/PhpVersionRequirement.php b/vendor/phar-io/manifest/src/values/PhpVersionRequirement.php
new file mode 100644
index 0000000000000000000000000000000000000000..f8d6f6d1315e247aecf921ccf162199cd9bfe2c8
--- /dev/null
+++ b/vendor/phar-io/manifest/src/values/PhpVersionRequirement.php
@@ -0,0 +1,25 @@
+<?php declare(strict_types = 1);
+/*
+ * This file is part of PharIo\Manifest.
+ *
+ * (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PharIo\Manifest;
+
+use PharIo\Version\VersionConstraint;
+
+class PhpVersionRequirement implements Requirement {
+    /** @var VersionConstraint */
+    private $versionConstraint;
+
+    public function __construct(VersionConstraint $versionConstraint) {
+        $this->versionConstraint = $versionConstraint;
+    }
+
+    public function getVersionConstraint(): VersionConstraint {
+        return $this->versionConstraint;
+    }
+}
diff --git a/vendor/phar-io/manifest/src/values/Requirement.php b/vendor/phar-io/manifest/src/values/Requirement.php
new file mode 100644
index 0000000000000000000000000000000000000000..8b845d6a0b24c63f6e17d4129781e459ada5ae58
--- /dev/null
+++ b/vendor/phar-io/manifest/src/values/Requirement.php
@@ -0,0 +1,13 @@
+<?php declare(strict_types = 1);
+/*
+ * This file is part of PharIo\Manifest.
+ *
+ * (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PharIo\Manifest;
+
+interface Requirement {
+}
diff --git a/vendor/phar-io/manifest/src/values/RequirementCollection.php b/vendor/phar-io/manifest/src/values/RequirementCollection.php
new file mode 100644
index 0000000000000000000000000000000000000000..b82cd955e3f22b215c3b2a0c4a46e585b54fca89
--- /dev/null
+++ b/vendor/phar-io/manifest/src/values/RequirementCollection.php
@@ -0,0 +1,34 @@
+<?php declare(strict_types = 1);
+/*
+ * This file is part of PharIo\Manifest.
+ *
+ * (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PharIo\Manifest;
+
+class RequirementCollection implements \Countable, \IteratorAggregate {
+    /** @var Requirement[] */
+    private $requirements = [];
+
+    public function add(Requirement $requirement): void {
+        $this->requirements[] = $requirement;
+    }
+
+    /**
+     * @return Requirement[]
+     */
+    public function getRequirements(): array {
+        return $this->requirements;
+    }
+
+    public function count(): int {
+        return \count($this->requirements);
+    }
+
+    public function getIterator(): RequirementCollectionIterator {
+        return new RequirementCollectionIterator($this);
+    }
+}
diff --git a/vendor/phar-io/manifest/src/values/RequirementCollectionIterator.php b/vendor/phar-io/manifest/src/values/RequirementCollectionIterator.php
new file mode 100644
index 0000000000000000000000000000000000000000..5614eaf7fcfa7b79d4371b5c8b199425a412d415
--- /dev/null
+++ b/vendor/phar-io/manifest/src/values/RequirementCollectionIterator.php
@@ -0,0 +1,42 @@
+<?php declare(strict_types = 1);
+/*
+ * This file is part of PharIo\Manifest.
+ *
+ * (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PharIo\Manifest;
+
+class RequirementCollectionIterator implements \Iterator {
+    /** @var Requirement[] */
+    private $requirements;
+
+    /** @var int */
+    private $position = 0;
+
+    public function __construct(RequirementCollection $requirements) {
+        $this->requirements = $requirements->getRequirements();
+    }
+
+    public function rewind(): void {
+        $this->position = 0;
+    }
+
+    public function valid(): bool {
+        return $this->position < \count($this->requirements);
+    }
+
+    public function key(): int {
+        return $this->position;
+    }
+
+    public function current(): Requirement {
+        return $this->requirements[$this->position];
+    }
+
+    public function next(): void {
+        $this->position++;
+    }
+}
diff --git a/vendor/phar-io/manifest/src/values/Type.php b/vendor/phar-io/manifest/src/values/Type.php
new file mode 100644
index 0000000000000000000000000000000000000000..23b289805ed78762d1a432702293031fd53435db
--- /dev/null
+++ b/vendor/phar-io/manifest/src/values/Type.php
@@ -0,0 +1,41 @@
+<?php declare(strict_types = 1);
+/*
+ * This file is part of PharIo\Manifest.
+ *
+ * (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PharIo\Manifest;
+
+use PharIo\Version\VersionConstraint;
+
+abstract class Type {
+    public static function application(): Application {
+        return new Application;
+    }
+
+    public static function library(): Library {
+        return new Library;
+    }
+
+    public static function extension(ApplicationName $application, VersionConstraint $versionConstraint): Extension {
+        return new Extension($application, $versionConstraint);
+    }
+
+    /** @psalm-assert-if-true Application $this */
+    public function isApplication(): bool {
+        return false;
+    }
+
+    /** @psalm-assert-if-true Library $this */
+    public function isLibrary(): bool {
+        return false;
+    }
+
+    /** @psalm-assert-if-true Extension $this */
+    public function isExtension(): bool {
+        return false;
+    }
+}
diff --git a/vendor/phar-io/manifest/src/values/Url.php b/vendor/phar-io/manifest/src/values/Url.php
new file mode 100644
index 0000000000000000000000000000000000000000..639525333ce2ebc0fadc771b748d7e33dcaa3b81
--- /dev/null
+++ b/vendor/phar-io/manifest/src/values/Url.php
@@ -0,0 +1,36 @@
+<?php declare(strict_types = 1);
+/*
+ * This file is part of PharIo\Manifest.
+ *
+ * (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PharIo\Manifest;
+
+class Url {
+    /** @var string */
+    private $url;
+
+    public function __construct(string $url) {
+        $this->ensureUrlIsValid($url);
+
+        $this->url = $url;
+    }
+
+    public function asString(): string {
+        return $this->url;
+    }
+
+    /**
+     * @param string $url
+     *
+     * @throws InvalidUrlException
+     */
+    private function ensureUrlIsValid($url): void {
+        if (\filter_var($url, \FILTER_VALIDATE_URL) === false) {
+            throw new InvalidUrlException;
+        }
+    }
+}
diff --git a/vendor/phar-io/manifest/src/xml/AuthorElement.php b/vendor/phar-io/manifest/src/xml/AuthorElement.php
new file mode 100644
index 0000000000000000000000000000000000000000..c454b271ac41014cdea4087b7dd3a7231b2aebc6
--- /dev/null
+++ b/vendor/phar-io/manifest/src/xml/AuthorElement.php
@@ -0,0 +1,20 @@
+<?php declare(strict_types = 1);
+/*
+ * This file is part of PharIo\Manifest.
+ *
+ * (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PharIo\Manifest;
+
+class AuthorElement extends ManifestElement {
+    public function getName(): string {
+        return $this->getAttributeValue('name');
+    }
+
+    public function getEmail(): string {
+        return $this->getAttributeValue('email');
+    }
+}
diff --git a/vendor/phar-io/manifest/src/xml/AuthorElementCollection.php b/vendor/phar-io/manifest/src/xml/AuthorElementCollection.php
new file mode 100644
index 0000000000000000000000000000000000000000..a54147eb467513a0e744702a92c99a1ee51444c1
--- /dev/null
+++ b/vendor/phar-io/manifest/src/xml/AuthorElementCollection.php
@@ -0,0 +1,18 @@
+<?php declare(strict_types = 1);
+/*
+ * This file is part of PharIo\Manifest.
+ *
+ * (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PharIo\Manifest;
+
+class AuthorElementCollection extends ElementCollection {
+    public function current(): AuthorElement {
+        return new AuthorElement(
+            $this->getCurrentElement()
+        );
+    }
+}
diff --git a/vendor/phar-io/manifest/src/xml/BundlesElement.php b/vendor/phar-io/manifest/src/xml/BundlesElement.php
new file mode 100644
index 0000000000000000000000000000000000000000..eb2105acd7bfb4b8b4092c365afefa5d0933ebde
--- /dev/null
+++ b/vendor/phar-io/manifest/src/xml/BundlesElement.php
@@ -0,0 +1,18 @@
+<?php declare(strict_types = 1);
+/*
+ * This file is part of PharIo\Manifest.
+ *
+ * (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PharIo\Manifest;
+
+class BundlesElement extends ManifestElement {
+    public function getComponentElements(): ComponentElementCollection {
+        return new ComponentElementCollection(
+            $this->getChildrenByName('component')
+        );
+    }
+}
diff --git a/vendor/phar-io/manifest/src/xml/ComponentElement.php b/vendor/phar-io/manifest/src/xml/ComponentElement.php
new file mode 100644
index 0000000000000000000000000000000000000000..7f6a5ec9a4e284fef6f3e8142572d6ae90d6316a
--- /dev/null
+++ b/vendor/phar-io/manifest/src/xml/ComponentElement.php
@@ -0,0 +1,20 @@
+<?php declare(strict_types = 1);
+/*
+ * This file is part of PharIo\Manifest.
+ *
+ * (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PharIo\Manifest;
+
+class ComponentElement extends ManifestElement {
+    public function getName(): string {
+        return $this->getAttributeValue('name');
+    }
+
+    public function getVersion(): string {
+        return $this->getAttributeValue('version');
+    }
+}
diff --git a/vendor/phar-io/manifest/src/xml/ComponentElementCollection.php b/vendor/phar-io/manifest/src/xml/ComponentElementCollection.php
new file mode 100644
index 0000000000000000000000000000000000000000..23bcbd2f1af46234acb7828cfa6d5622ed3efc24
--- /dev/null
+++ b/vendor/phar-io/manifest/src/xml/ComponentElementCollection.php
@@ -0,0 +1,18 @@
+<?php declare(strict_types = 1);
+/*
+ * This file is part of PharIo\Manifest.
+ *
+ * (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PharIo\Manifest;
+
+class ComponentElementCollection extends ElementCollection {
+    public function current(): ComponentElement {
+        return new ComponentElement(
+            $this->getCurrentElement()
+        );
+    }
+}
diff --git a/vendor/phar-io/manifest/src/xml/ContainsElement.php b/vendor/phar-io/manifest/src/xml/ContainsElement.php
new file mode 100644
index 0000000000000000000000000000000000000000..ebef49d9b18be2a505449a8d8acab6d1fe44ee15
--- /dev/null
+++ b/vendor/phar-io/manifest/src/xml/ContainsElement.php
@@ -0,0 +1,30 @@
+<?php declare(strict_types = 1);
+/*
+ * This file is part of PharIo\Manifest.
+ *
+ * (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PharIo\Manifest;
+
+class ContainsElement extends ManifestElement {
+    public function getName(): string {
+        return $this->getAttributeValue('name');
+    }
+
+    public function getVersion(): string {
+        return $this->getAttributeValue('version');
+    }
+
+    public function getType(): string {
+        return $this->getAttributeValue('type');
+    }
+
+    public function getExtensionElement(): ExtensionElement {
+        return new ExtensionElement(
+            $this->getChildByName('extension')
+        );
+    }
+}
diff --git a/vendor/phar-io/manifest/src/xml/CopyrightElement.php b/vendor/phar-io/manifest/src/xml/CopyrightElement.php
new file mode 100644
index 0000000000000000000000000000000000000000..3debe7dcdebffd5abf8afc26b02812755acfc802
--- /dev/null
+++ b/vendor/phar-io/manifest/src/xml/CopyrightElement.php
@@ -0,0 +1,24 @@
+<?php declare(strict_types = 1);
+/*
+ * This file is part of PharIo\Manifest.
+ *
+ * (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PharIo\Manifest;
+
+class CopyrightElement extends ManifestElement {
+    public function getAuthorElements(): AuthorElementCollection {
+        return new AuthorElementCollection(
+            $this->getChildrenByName('author')
+        );
+    }
+
+    public function getLicenseElement(): LicenseElement {
+        return new LicenseElement(
+            $this->getChildByName('license')
+        );
+    }
+}
diff --git a/vendor/phar-io/manifest/src/xml/ElementCollection.php b/vendor/phar-io/manifest/src/xml/ElementCollection.php
new file mode 100644
index 0000000000000000000000000000000000000000..1d13a91605cafe10eaa0cdeffadfb8ad2b230192
--- /dev/null
+++ b/vendor/phar-io/manifest/src/xml/ElementCollection.php
@@ -0,0 +1,60 @@
+<?php declare(strict_types = 1);
+/*
+ * This file is part of PharIo\Manifest.
+ *
+ * (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PharIo\Manifest;
+
+use DOMElement;
+use DOMNodeList;
+
+abstract class ElementCollection implements \Iterator {
+    /** @var DOMElement[] */
+    private $nodes = [];
+
+    /** @var int */
+    private $position;
+
+    public function __construct(DOMNodeList $nodeList) {
+        $this->position = 0;
+        $this->importNodes($nodeList);
+    }
+
+    abstract public function current();
+
+    public function next(): void {
+        $this->position++;
+    }
+
+    public function key() {
+        return $this->position;
+    }
+
+    public function valid() {
+        return $this->position < \count($this->nodes);
+    }
+
+    public function rewind(): void {
+        $this->position = 0;
+    }
+
+    protected function getCurrentElement(): DOMElement {
+        return $this->nodes[$this->position];
+    }
+
+    private function importNodes(DOMNodeList $nodeList): void {
+        foreach ($nodeList as $node) {
+            if (!$node instanceof DOMElement) {
+                throw new ElementCollectionException(
+                    \sprintf('\DOMElement expected, got \%s', \get_class($node))
+                );
+            }
+
+            $this->nodes[] = $node;
+        }
+    }
+}
diff --git a/vendor/phar-io/manifest/src/xml/ExtElement.php b/vendor/phar-io/manifest/src/xml/ExtElement.php
new file mode 100644
index 0000000000000000000000000000000000000000..257853c43f281142ecceb8eb5802c6719442f191
--- /dev/null
+++ b/vendor/phar-io/manifest/src/xml/ExtElement.php
@@ -0,0 +1,16 @@
+<?php declare(strict_types = 1);
+/*
+ * This file is part of PharIo\Manifest.
+ *
+ * (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PharIo\Manifest;
+
+class ExtElement extends ManifestElement {
+    public function getName(): string {
+        return $this->getAttributeValue('name');
+    }
+}
diff --git a/vendor/phar-io/manifest/src/xml/ExtElementCollection.php b/vendor/phar-io/manifest/src/xml/ExtElementCollection.php
new file mode 100644
index 0000000000000000000000000000000000000000..059773490a3a5db7fd7da874de2813431f84513d
--- /dev/null
+++ b/vendor/phar-io/manifest/src/xml/ExtElementCollection.php
@@ -0,0 +1,18 @@
+<?php declare(strict_types = 1);
+/*
+ * This file is part of PharIo\Manifest.
+ *
+ * (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PharIo\Manifest;
+
+class ExtElementCollection extends ElementCollection {
+    public function current(): ExtElement {
+        return new ExtElement(
+            $this->getCurrentElement()
+        );
+    }
+}
diff --git a/vendor/phar-io/manifest/src/xml/ExtensionElement.php b/vendor/phar-io/manifest/src/xml/ExtensionElement.php
new file mode 100644
index 0000000000000000000000000000000000000000..db067f9963960409d0731e07b54c3f0e58ea21d6
--- /dev/null
+++ b/vendor/phar-io/manifest/src/xml/ExtensionElement.php
@@ -0,0 +1,20 @@
+<?php declare(strict_types = 1);
+/*
+ * This file is part of PharIo\Manifest.
+ *
+ * (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PharIo\Manifest;
+
+class ExtensionElement extends ManifestElement {
+    public function getFor(): string {
+        return $this->getAttributeValue('for');
+    }
+
+    public function getCompatible(): string {
+        return $this->getAttributeValue('compatible');
+    }
+}
diff --git a/vendor/phar-io/manifest/src/xml/LicenseElement.php b/vendor/phar-io/manifest/src/xml/LicenseElement.php
new file mode 100644
index 0000000000000000000000000000000000000000..658c3d1c25540c08b50ba1cd000429e9707aad82
--- /dev/null
+++ b/vendor/phar-io/manifest/src/xml/LicenseElement.php
@@ -0,0 +1,20 @@
+<?php declare(strict_types = 1);
+/*
+ * This file is part of PharIo\Manifest.
+ *
+ * (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PharIo\Manifest;
+
+class LicenseElement extends ManifestElement {
+    public function getType(): string {
+        return $this->getAttributeValue('type');
+    }
+
+    public function getUrl(): string {
+        return $this->getAttributeValue('url');
+    }
+}
diff --git a/vendor/phar-io/manifest/src/xml/ManifestDocument.php b/vendor/phar-io/manifest/src/xml/ManifestDocument.php
new file mode 100644
index 0000000000000000000000000000000000000000..f88b282936c6e0687c437f0e0d55174d92290019
--- /dev/null
+++ b/vendor/phar-io/manifest/src/xml/ManifestDocument.php
@@ -0,0 +1,103 @@
+<?php declare(strict_types = 1);
+/*
+ * This file is part of PharIo\Manifest.
+ *
+ * (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PharIo\Manifest;
+
+use DOMDocument;
+use DOMElement;
+
+class ManifestDocument {
+    public const XMLNS = 'https://phar.io/xml/manifest/1.0';
+
+    /** @var DOMDocument */
+    private $dom;
+
+    public static function fromFile(string $filename): ManifestDocument {
+        if (!\file_exists($filename)) {
+            throw new ManifestDocumentException(
+                \sprintf('File "%s" not found', $filename)
+            );
+        }
+
+        return self::fromString(
+            \file_get_contents($filename)
+        );
+    }
+
+    public static function fromString(string $xmlString): ManifestDocument {
+        $prev = \libxml_use_internal_errors(true);
+        \libxml_clear_errors();
+
+        $dom = new DOMDocument();
+        $dom->loadXML($xmlString);
+
+        $errors = \libxml_get_errors();
+        \libxml_use_internal_errors($prev);
+
+        if (\count($errors) !== 0) {
+            throw new ManifestDocumentLoadingException($errors);
+        }
+
+        return new self($dom);
+    }
+
+    private function __construct(DOMDocument $dom) {
+        $this->ensureCorrectDocumentType($dom);
+
+        $this->dom = $dom;
+    }
+
+    public function getContainsElement(): ContainsElement {
+        return new ContainsElement(
+            $this->fetchElementByName('contains')
+        );
+    }
+
+    public function getCopyrightElement(): CopyrightElement {
+        return new CopyrightElement(
+            $this->fetchElementByName('copyright')
+        );
+    }
+
+    public function getRequiresElement(): RequiresElement {
+        return new RequiresElement(
+            $this->fetchElementByName('requires')
+        );
+    }
+
+    public function hasBundlesElement(): bool {
+        return $this->dom->getElementsByTagNameNS(self::XMLNS, 'bundles')->length === 1;
+    }
+
+    public function getBundlesElement(): BundlesElement {
+        return new BundlesElement(
+            $this->fetchElementByName('bundles')
+        );
+    }
+
+    private function ensureCorrectDocumentType(DOMDocument $dom): void {
+        $root = $dom->documentElement;
+
+        if ($root->localName !== 'phar' || $root->namespaceURI !== self::XMLNS) {
+            throw new ManifestDocumentException('Not a phar.io manifest document');
+        }
+    }
+
+    private function fetchElementByName(string $elementName): DOMElement {
+        $element = $this->dom->getElementsByTagNameNS(self::XMLNS, $elementName)->item(0);
+
+        if (!$element instanceof DOMElement) {
+            throw new ManifestDocumentException(
+                \sprintf('Element %s missing', $elementName)
+            );
+        }
+
+        return $element;
+    }
+}
diff --git a/vendor/phar-io/manifest/src/xml/ManifestElement.php b/vendor/phar-io/manifest/src/xml/ManifestElement.php
new file mode 100644
index 0000000000000000000000000000000000000000..1f57f547d53d1e336cfebbb5cfd09e9eef4d87a4
--- /dev/null
+++ b/vendor/phar-io/manifest/src/xml/ManifestElement.php
@@ -0,0 +1,66 @@
+<?php declare(strict_types = 1);
+/*
+ * This file is part of PharIo\Manifest.
+ *
+ * (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PharIo\Manifest;
+
+use DOMElement;
+use DOMNodeList;
+
+class ManifestElement {
+    public const XMLNS = 'https://phar.io/xml/manifest/1.0';
+
+    /** @var DOMElement */
+    private $element;
+
+    public function __construct(DOMElement $element) {
+        $this->element = $element;
+    }
+
+    protected function getAttributeValue(string $name): string {
+        if (!$this->element->hasAttribute($name)) {
+            throw new ManifestElementException(
+                \sprintf(
+                    'Attribute %s not set on element %s',
+                    $name,
+                    $this->element->localName
+                )
+            );
+        }
+
+        return $this->element->getAttribute($name);
+    }
+
+    protected function getChildByName(string $elementName): DOMElement {
+        $element = $this->element->getElementsByTagNameNS(self::XMLNS, $elementName)->item(0);
+
+        if (!$element instanceof DOMElement) {
+            throw new ManifestElementException(
+                \sprintf('Element %s missing', $elementName)
+            );
+        }
+
+        return $element;
+    }
+
+    protected function getChildrenByName(string $elementName): DOMNodeList {
+        $elementList = $this->element->getElementsByTagNameNS(self::XMLNS, $elementName);
+
+        if ($elementList->length === 0) {
+            throw new ManifestElementException(
+                \sprintf('Element(s) %s missing', $elementName)
+            );
+        }
+
+        return $elementList;
+    }
+
+    protected function hasChild(string $elementName): bool {
+        return $this->element->getElementsByTagNameNS(self::XMLNS, $elementName)->length !== 0;
+    }
+}
diff --git a/vendor/phar-io/manifest/src/xml/PhpElement.php b/vendor/phar-io/manifest/src/xml/PhpElement.php
new file mode 100644
index 0000000000000000000000000000000000000000..c5c906c968dd3eb5d06a88e2447678b8dc5251a9
--- /dev/null
+++ b/vendor/phar-io/manifest/src/xml/PhpElement.php
@@ -0,0 +1,26 @@
+<?php declare(strict_types = 1);
+/*
+ * This file is part of PharIo\Manifest.
+ *
+ * (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PharIo\Manifest;
+
+class PhpElement extends ManifestElement {
+    public function getVersion(): string {
+        return $this->getAttributeValue('version');
+    }
+
+    public function hasExtElements(): bool {
+        return $this->hasChild('ext');
+    }
+
+    public function getExtElements(): ExtElementCollection {
+        return new ExtElementCollection(
+            $this->getChildrenByName('ext')
+        );
+    }
+}
diff --git a/vendor/phar-io/manifest/src/xml/RequiresElement.php b/vendor/phar-io/manifest/src/xml/RequiresElement.php
new file mode 100644
index 0000000000000000000000000000000000000000..b7cd41ef7f5de7cdcce05687b798aef9c056e1a1
--- /dev/null
+++ b/vendor/phar-io/manifest/src/xml/RequiresElement.php
@@ -0,0 +1,18 @@
+<?php declare(strict_types = 1);
+/*
+ * This file is part of PharIo\Manifest.
+ *
+ * (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PharIo\Manifest;
+
+class RequiresElement extends ManifestElement {
+    public function getPHPElement(): PhpElement {
+        return new PhpElement(
+            $this->getChildByName('php')
+        );
+    }
+}
diff --git a/vendor/phar-io/version/CHANGELOG.md b/vendor/phar-io/version/CHANGELOG.md
new file mode 100644
index 0000000000000000000000000000000000000000..dc8e3574530d6cb4cfaec3f3ebc0664ebfa87902
--- /dev/null
+++ b/vendor/phar-io/version/CHANGELOG.md
@@ -0,0 +1,121 @@
+# Changelog
+
+All notable changes to phar-io/version are documented in this file using the [Keep a CHANGELOG](http://keepachangelog.com/) principles.
+
+## [3.1.0] - 2021-02-23
+
+>### Changed
+
+- Internal Refactoring
+- More scalar types
+
+### Added
+
+- [#24](https://github.com/phar-io/version/issues/24): `Version::getOriginalString()` added (Thanks @addshore)
+- Version constraints using the caret operator (`^`) now honor pre-1.0 releases, e.g. `^0.3` translates to `0.3.*`)
+- Various integration tests for version constraint processing
+
+### Fixed
+
+- [#23](https://github.com/phar-io/version/pull/23): Tilde operator without patch level
+
+
+
+## [3.0.4] - 14.12.2020
+
+### Fixed 
+
+- [#22](https://github.com/phar-io/version/pull/22): make dev suffix rank works for uppercase too
+
+## [3.0.3] - 30.11.2020
+
+### Added
+
+- Comparator method `Version::equals()` added
+
+
+## [3.0.2] - 27.06.2020
+
+This release now supports PHP 7.2+ and PHP ^8.0. No other changes included.
+
+
+## [3.0.1] - 09.05.2020
+
+__Potential BC Break Notice:__
+`Version::getVersionString()` no longer returns `v` prefixes in case the "input"
+string contained one. These are not part of the semver specs
+(see https://semver.org/#is-v123-a-semantic-version) and get stripped out.
+As of Version 3.1.0 `Version::getOriginalString()` can be used to still
+retrieve it as given.
+
+### Changed
+
+- Internal Refactoring
+- More scalar types
+
+### Fixed
+
+- Fixed Constraint processing Regression for ^1.2  and ~1.2
+
+
+## [3.0.0] - 05.05.2020
+
+### Changed
+
+- Require PHP 7.2+
+- All code now uses strict mode
+- Scalar types have been added as needed
+
+### Added
+
+- The technically invalid format using 'v' prefix ("v1.2.3") is now properly supported 
+
+
+## [2.0.1] - 08.07.2018
+
+### Fixed
+
+- Versions without a pre-release suffix are now always considered greater 
+than versions with a pre-release suffix. Example: `3.0.0 > 3.0.0-alpha.1`  
+
+
+## [2.0.0] - 23.06.2018
+
+Changes to public API:
+
+- `PreReleaseSuffix::construct()`: optional parameter `$number` removed
+- `PreReleaseSuffix::isGreaterThan()`: introduced
+- `Version::hasPreReleaseSuffix()`: introduced
+
+### Added
+
+- [#11](https://github.com/phar-io/version/issues/11): Added support for pre-release version suffixes. Supported values are:
+  - `dev`
+  - `beta` (also abbreviated form `b`)
+  - `rc`
+  - `alpha` (also abbreviated form `a`)
+  - `patch` (also abbreviated form `p`)
+
+  All values can be followed by a number, e.g. `beta3`. 
+
+  When comparing versions, the pre-release suffix is taken into account. Example:
+`1.5.0 > 1.5.0-beta1 > 1.5.0-alpha3 > 1.5.0-alpha2 > 1.5.0-dev11`
+
+### Changed
+
+- reorganized the source directories
+
+### Fixed
+
+- [#10](https://github.com/phar-io/version/issues/10): Version numbers containing 
+a numeric suffix as seen in Debian packages are now supported.  
+
+
+[3.1.0]: https://github.com/phar-io/version/compare/3.0.4...3.1.0
+[3.0.4]: https://github.com/phar-io/version/compare/3.0.3...3.0.4
+[3.0.3]: https://github.com/phar-io/version/compare/3.0.2...3.0.3
+[3.0.2]: https://github.com/phar-io/version/compare/3.0.1...3.0.2
+[3.0.1]: https://github.com/phar-io/version/compare/3.0.0...3.0.1
+[3.0.0]: https://github.com/phar-io/version/compare/2.0.1...3.0.0
+[2.0.1]: https://github.com/phar-io/version/compare/2.0.0...2.0.1
+[2.0.0]: https://github.com/phar-io/version/compare/1.0.1...2.0.0
diff --git a/vendor/phar-io/version/LICENSE b/vendor/phar-io/version/LICENSE
new file mode 100644
index 0000000000000000000000000000000000000000..359dbc50f2448da1eb3b139cb76fc3c3044f9172
--- /dev/null
+++ b/vendor/phar-io/version/LICENSE
@@ -0,0 +1,31 @@
+phar-io/version
+
+Copyright (c) 2016-2017 Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de> and contributors
+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 Arne Blankerts nor the names of 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 HOLDER 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/phar-io/version/README.md b/vendor/phar-io/version/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..76e6e9857929a354ecb6e85c50106134ef7925b7
--- /dev/null
+++ b/vendor/phar-io/version/README.md
@@ -0,0 +1,61 @@
+# Version
+
+Library for handling version information and constraints
+
+[![Build Status](https://travis-ci.org/phar-io/version.svg?branch=master)](https://travis-ci.org/phar-io/version)
+
+## Installation
+
+You can add this library as a local, per-project dependency to your project using [Composer](https://getcomposer.org/):
+
+    composer require phar-io/version
+
+If you only need this library during development, for instance to run your project's test suite, then you should add it as a development-time dependency:
+
+    composer require --dev phar-io/version
+
+## Version constraints
+
+A Version constraint describes a range of versions or a discrete version number. The format of version numbers follows the schema of [semantic versioning](http://semver.org): `<major>.<minor>.<patch>`. A constraint might contain an operator that describes the range.
+
+Beside the typical mathematical operators like `<=`, `>=`, there are two special operators:
+
+*Caret operator*: `^1.0`
+can be written as `>=1.0.0 <2.0.0` and read as »every Version within major version `1`«.
+
+*Tilde operator*: `~1.0.0`
+can be written as `>=1.0.0 <1.1.0` and read as »every version within minor version `1.1`. The behavior of tilde operator depends on whether a patch level version is provided or not. If no patch level is provided, tilde operator behaves like the caret operator: `~1.0` is identical to `^1.0`.
+
+## Usage examples
+
+Parsing version constraints and check discrete versions for compliance:
+
+```php
+
+use PharIo\Version\Version;
+use PharIo\Version\VersionConstraintParser;
+
+$parser = new VersionConstraintParser();
+$caret_constraint = $parser->parse( '^7.0' );
+
+$caret_constraint->complies( new Version( '7.0.17' ) ); // true
+$caret_constraint->complies( new Version( '7.1.0' ) ); // true
+$caret_constraint->complies( new Version( '6.4.34' ) ); // false
+
+$tilde_constraint = $parser->parse( '~1.1.0' );
+
+$tilde_constraint->complies( new Version( '1.1.4' ) ); // true
+$tilde_constraint->complies( new Version( '1.2.0' ) ); // false
+```
+
+As of version 2.0.0, pre-release labels are supported and taken into account when comparing versions:
+
+```php
+
+$leftVersion = new PharIo\Version\Version('3.0.0-alpha.1');
+$rightVersion = new PharIo\Version\Version('3.0.0-alpha.2');
+
+$leftVersion->isGreaterThan($rightVersion); // false
+$rightVersion->isGreaterThan($leftVersion); // true
+
+``` 
diff --git a/vendor/phar-io/version/composer.json b/vendor/phar-io/version/composer.json
new file mode 100644
index 0000000000000000000000000000000000000000..22687dcd3b32f2d0ded63dc779b507d64780bf46
--- /dev/null
+++ b/vendor/phar-io/version/composer.json
@@ -0,0 +1,34 @@
+{
+  "name": "phar-io/version",
+  "description": "Library for handling version information and constraints",
+  "license": "BSD-3-Clause",
+  "authors": [
+    {
+      "name": "Arne Blankerts",
+      "email": "arne@blankerts.de",
+      "role": "Developer"
+    },
+    {
+      "name": "Sebastian Heuer",
+      "email": "sebastian@phpeople.de",
+      "role": "Developer"
+    },
+    {
+      "name": "Sebastian Bergmann",
+      "email": "sebastian@phpunit.de",
+      "role": "Developer"
+    }
+  ],
+  "support": {
+    "issues": "https://github.com/phar-io/version/issues"
+  },
+  "require": {
+    "php": "^7.2 || ^8.0"
+  },
+  "autoload": {
+    "classmap": [
+      "src/"
+    ]
+  }
+}
+
diff --git a/vendor/phar-io/version/src/PreReleaseSuffix.php b/vendor/phar-io/version/src/PreReleaseSuffix.php
new file mode 100644
index 0000000000000000000000000000000000000000..50aa525cbd47ec04e435a441c04a42149e2a9fb2
--- /dev/null
+++ b/vendor/phar-io/version/src/PreReleaseSuffix.php
@@ -0,0 +1,85 @@
+<?php declare(strict_types = 1);
+namespace PharIo\Version;
+
+class PreReleaseSuffix {
+    private const valueScoreMap = [
+        'dev'   => 0,
+        'a'     => 1,
+        'alpha' => 1,
+        'b'     => 2,
+        'beta'  => 2,
+        'rc'    => 3,
+        'p'     => 4,
+        'patch' => 4,
+    ];
+
+    /** @var string */
+    private $value;
+
+    /** @var int */
+    private $valueScore;
+
+    /** @var int */
+    private $number = 0;
+
+    /** @var string */
+    private $full;
+
+    /**
+     * @throws InvalidPreReleaseSuffixException
+     */
+    public function __construct(string $value) {
+        $this->parseValue($value);
+    }
+
+    public function asString(): string {
+        return $this->full;
+    }
+
+    public function getValue(): string {
+        return $this->value;
+    }
+
+    public function getNumber(): ?int {
+        return $this->number;
+    }
+
+    public function isGreaterThan(PreReleaseSuffix $suffix): bool {
+        if ($this->valueScore > $suffix->valueScore) {
+            return true;
+        }
+
+        if ($this->valueScore < $suffix->valueScore) {
+            return false;
+        }
+
+        return $this->getNumber() > $suffix->getNumber();
+    }
+
+    private function mapValueToScore(string $value): int {
+        $value = \strtolower($value);
+
+        if (\array_key_exists($value, self::valueScoreMap)) {
+            return self::valueScoreMap[$value];
+        }
+
+        return 0;
+    }
+
+    private function parseValue(string $value): void {
+        $regex = '/-?((dev|beta|b|rc|alpha|a|patch|p)\.?(\d*)).*$/i';
+
+        if (\preg_match($regex, $value, $matches) !== 1) {
+            throw new InvalidPreReleaseSuffixException(\sprintf('Invalid label %s', $value));
+        }
+
+        $this->full  = $matches[1];
+        $this->value = $matches[2];
+
+        if ($matches[3] !== '') {
+            $this->number = (int)$matches[3];
+        }
+
+        $this->valueScore = $this->mapValueToScore($matches[2]);
+    }
+}
diff --git a/vendor/phar-io/version/src/Version.php b/vendor/phar-io/version/src/Version.php
new file mode 100644
index 0000000000000000000000000000000000000000..b72ef5edbbd4733271de9c26ccd129b9a9d31200
--- /dev/null
+++ b/vendor/phar-io/version/src/Version.php
@@ -0,0 +1,162 @@
+<?php declare(strict_types = 1);
+/*
+ * This file is part of PharIo\Version.
+ *
+ * (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PharIo\Version;
+
+class Version {
+    /** @var string */
+    private $originalVersionString;
+
+    /** @var VersionNumber */
+    private $major;
+
+    /** @var VersionNumber */
+    private $minor;
+
+    /** @var VersionNumber */
+    private $patch;
+
+    /** @var null|PreReleaseSuffix */
+    private $preReleaseSuffix;
+
+    public function __construct(string $versionString) {
+        $this->ensureVersionStringIsValid($versionString);
+        $this->originalVersionString = $versionString;
+    }
+
+    public function getPreReleaseSuffix(): PreReleaseSuffix {
+        if ($this->preReleaseSuffix === null) {
+            throw new NoPreReleaseSuffixException('No pre-release suffix set');
+        }
+
+        return $this->preReleaseSuffix;
+    }
+
+    public function getOriginalString(): string {
+        return $this->originalVersionString;
+    }
+
+    public function getVersionString(): string {
+        $str = \sprintf(
+            '%d.%d.%d',
+            $this->getMajor()->getValue() ?? 0,
+            $this->getMinor()->getValue() ?? 0,
+            $this->getPatch()->getValue() ?? 0
+        );
+
+        if (!$this->hasPreReleaseSuffix()) {
+            return $str;
+        }
+
+        return $str . '-' . $this->getPreReleaseSuffix()->asString();
+    }
+
+    public function hasPreReleaseSuffix(): bool {
+        return $this->preReleaseSuffix !== null;
+    }
+
+    public function equals(Version $other): bool {
+        return $this->getVersionString() === $other->getVersionString();
+    }
+
+    public function isGreaterThan(Version $version): bool {
+        if ($version->getMajor()->getValue() > $this->getMajor()->getValue()) {
+            return false;
+        }
+
+        if ($version->getMajor()->getValue() < $this->getMajor()->getValue()) {
+            return true;
+        }
+
+        if ($version->getMinor()->getValue() > $this->getMinor()->getValue()) {
+            return false;
+        }
+
+        if ($version->getMinor()->getValue() < $this->getMinor()->getValue()) {
+            return true;
+        }
+
+        if ($version->getPatch()->getValue() > $this->getPatch()->getValue()) {
+            return false;
+        }
+
+        if ($version->getPatch()->getValue() < $this->getPatch()->getValue()) {
+            return true;
+        }
+
+        if (!$version->hasPreReleaseSuffix() && !$this->hasPreReleaseSuffix()) {
+            return false;
+        }
+
+        if ($version->hasPreReleaseSuffix() && !$this->hasPreReleaseSuffix()) {
+            return true;
+        }
+
+        if (!$version->hasPreReleaseSuffix() && $this->hasPreReleaseSuffix()) {
+            return false;
+        }
+
+        return $this->getPreReleaseSuffix()->isGreaterThan($version->getPreReleaseSuffix());
+    }
+
+    public function getMajor(): VersionNumber {
+        return $this->major;
+    }
+
+    public function getMinor(): VersionNumber {
+        return $this->minor;
+    }
+
+    public function getPatch(): VersionNumber {
+        return $this->patch;
+    }
+
+    /**
+     * @param string[] $matches
+     *
+     * @throws InvalidPreReleaseSuffixException
+     */
+    private function parseVersion(array $matches): void {
+        $this->major = new VersionNumber((int)$matches['Major']);
+        $this->minor = new VersionNumber((int)$matches['Minor']);
+        $this->patch = isset($matches['Patch']) ? new VersionNumber((int)$matches['Patch']) : new VersionNumber(0);
+
+        if (isset($matches['PreReleaseSuffix'])) {
+            $this->preReleaseSuffix = new PreReleaseSuffix($matches['PreReleaseSuffix']);
+        }
+    }
+
+    /**
+     * @param string $version
+     *
+     * @throws InvalidVersionException
+     */
+    private function ensureVersionStringIsValid($version): void {
+        $regex = '/^v?
+            (?<Major>(0|(?:[1-9]\d*)))
+            \\.
+            (?<Minor>(0|(?:[1-9]\d*)))
+            (\\.
+                (?<Patch>(0|(?:[1-9]\d*)))
+            )?
+            (?:
+                -
+                (?<PreReleaseSuffix>(?:(dev|beta|b|rc|alpha|a|patch|p)\.?\d*))
+            )?       
+        $/xi';
+
+        if (\preg_match($regex, $version, $matches) !== 1) {
+            throw new InvalidVersionException(
+                \sprintf("Version string '%s' does not follow SemVer semantics", $version)
+            );
+        }
+
+        $this->parseVersion($matches);
+    }
+}
diff --git a/vendor/phar-io/version/src/VersionConstraintParser.php b/vendor/phar-io/version/src/VersionConstraintParser.php
new file mode 100644
index 0000000000000000000000000000000000000000..644a86f0bb2360b130b4ab79450c403d5bcb0244
--- /dev/null
+++ b/vendor/phar-io/version/src/VersionConstraintParser.php
@@ -0,0 +1,115 @@
+<?php declare(strict_types = 1);
+/*
+ * This file is part of PharIo\Version.
+ *
+ * (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PharIo\Version;
+
+class VersionConstraintParser {
+    /**
+     * @throws UnsupportedVersionConstraintException
+     */
+    public function parse(string $value): VersionConstraint {
+        if (\strpos($value, '||') !== false) {
+            return $this->handleOrGroup($value);
+        }
+
+        if (!\preg_match('/^[\^~*]?v?[\d.*]+(?:-.*)?$/i', $value)) {
+            throw new UnsupportedVersionConstraintException(
+                \sprintf('Version constraint %s is not supported.', $value)
+            );
+        }
+
+        switch ($value[0]) {
+            case '~':
+                return $this->handleTildeOperator($value);
+            case '^':
+                return $this->handleCaretOperator($value);
+        }
+
+        $constraint = new VersionConstraintValue($value);
+
+        if ($constraint->getMajor()->isAny()) {
+            return new AnyVersionConstraint();
+        }
+
+        if ($constraint->getMinor()->isAny()) {
+            return new SpecificMajorVersionConstraint(
+                $constraint->getVersionString(),
+                $constraint->getMajor()->getValue() ?? 0
+            );
+        }
+
+        if ($constraint->getPatch()->isAny()) {
+            return new SpecificMajorAndMinorVersionConstraint(
+                $constraint->getVersionString(),
+                $constraint->getMajor()->getValue() ?? 0,
+                $constraint->getMinor()->getValue() ?? 0
+            );
+        }
+
+        return new ExactVersionConstraint($constraint->getVersionString());
+    }
+
+    private function handleOrGroup(string $value): OrVersionConstraintGroup {
+        $constraints = [];
+
+        foreach (\explode('||', $value) as $groupSegment) {
+            $constraints[] = $this->parse(\trim($groupSegment));
+        }
+
+        return new OrVersionConstraintGroup($value, $constraints);
+    }
+
+    private function handleTildeOperator(string $value): AndVersionConstraintGroup {
+        $constraintValue = new VersionConstraintValue(\substr($value, 1));
+
+        if ($constraintValue->getPatch()->isAny()) {
+            return $this->handleCaretOperator($value);
+        }
+
+        $constraints = [
+            new GreaterThanOrEqualToVersionConstraint(
+                $value,
+                new Version(\substr($value, 1))
+            ),
+            new SpecificMajorAndMinorVersionConstraint(
+                $value,
+                $constraintValue->getMajor()->getValue() ?? 0,
+                $constraintValue->getMinor()->getValue() ?? 0
+            )
+        ];
+
+        return new AndVersionConstraintGroup($value, $constraints);
+    }
+
+    private function handleCaretOperator(string $value): AndVersionConstraintGroup {
+        $constraintValue = new VersionConstraintValue(\substr($value, 1));
+
+        $constraints = [
+            new GreaterThanOrEqualToVersionConstraint($value, new Version(\substr($value, 1)))
+        ];
+
+        if ($constraintValue->getMajor()->getValue() === 0) {
+            $constraints[] = new SpecificMajorAndMinorVersionConstraint(
+                $value,
+                $constraintValue->getMajor()->getValue() ?? 0,
+                $constraintValue->getMinor()->getValue() ?? 0
+            );
+        } else {
+            $constraints[] = new SpecificMajorVersionConstraint(
+                $value,
+                $constraintValue->getMajor()->getValue() ?? 0
+            );
+        }
+
+        return new AndVersionConstraintGroup(
+            $value,
+            $constraints
+        );
+    }
+}
diff --git a/vendor/phar-io/version/src/VersionConstraintValue.php b/vendor/phar-io/version/src/VersionConstraintValue.php
new file mode 100644
index 0000000000000000000000000000000000000000..0762e7c0e8ebc929574de29c3bbdac61566cd4b5
--- /dev/null
+++ b/vendor/phar-io/version/src/VersionConstraintValue.php
@@ -0,0 +1,88 @@
+<?php declare(strict_types = 1);
+namespace PharIo\Version;
+
+class VersionConstraintValue {
+    /** @var VersionNumber */
+    private $major;
+
+    /** @var VersionNumber */
+    private $minor;
+
+    /** @var VersionNumber */
+    private $patch;
+
+    /** @var string */
+    private $label = '';
+
+    /** @var string */
+    private $buildMetaData = '';
+
+    /** @var string */
+    private $versionString = '';
+
+    public function __construct(string $versionString) {
+        $this->versionString = $versionString;
+
+        $this->parseVersion($versionString);
+    }
+
+    public function getLabel(): string {
+        return $this->label;
+    }
+
+    public function getBuildMetaData(): string {
+        return $this->buildMetaData;
+    }
+
+    public function getVersionString(): string {
+        return $this->versionString;
+    }
+
+    public function getMajor(): VersionNumber {
+        return $this->major;
+    }
+
+    public function getMinor(): VersionNumber {
+        return $this->minor;
+    }
+
+    public function getPatch(): VersionNumber {
+        return $this->patch;
+    }
+
+    private function parseVersion(string $versionString): void {
+        $this->extractBuildMetaData($versionString);
+        $this->extractLabel($versionString);
+        $this->stripPotentialVPrefix($versionString);
+
+        $versionSegments = \explode('.', $versionString);
+        $this->major     = new VersionNumber(\is_numeric($versionSegments[0]) ? (int)$versionSegments[0] : null);
+
+        $minorValue = isset($versionSegments[1]) && \is_numeric($versionSegments[1]) ? (int)$versionSegments[1] : null;
+        $patchValue = isset($versionSegments[2]) && \is_numeric($versionSegments[2]) ? (int)$versionSegments[2] : null;
+
+        $this->minor = new VersionNumber($minorValue);
+        $this->patch = new VersionNumber($patchValue);
+    }
+
+    private function extractBuildMetaData(string &$versionString): void {
+        if (\preg_match('/\+(.*)/', $versionString, $matches) === 1) {
+            $this->buildMetaData = $matches[1];
+            $versionString       = \str_replace($matches[0], '', $versionString);
+        }
+    }
+
+    private function extractLabel(string &$versionString): void {
+        if (\preg_match('/-(.*)/', $versionString, $matches) === 1) {
+            $this->label   = $matches[1];
+            $versionString = \str_replace($matches[0], '', $versionString);
+        }
+    }
+
+    private function stripPotentialVPrefix(string &$versionString): void {
+        if ($versionString[0] !== 'v') {
+            return;
+        }
+        $versionString = \substr($versionString, 1);
+    }
+}
diff --git a/vendor/phar-io/version/src/VersionNumber.php b/vendor/phar-io/version/src/VersionNumber.php
new file mode 100644
index 0000000000000000000000000000000000000000..4833a9b0f5d3cc5bfcc8235f36b4b07b35b1d8ae
--- /dev/null
+++ b/vendor/phar-io/version/src/VersionNumber.php
@@ -0,0 +1,28 @@
+<?php declare(strict_types = 1);
+/*
+ * This file is part of PharIo\Version.
+ *
+ * (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PharIo\Version;
+
+class VersionNumber {
+
+    /** @var ?int */
+    private $value;
+
+    public function __construct(?int $value) {
+        $this->value = $value;
+    }
+
+    public function isAny(): bool {
+        return $this->value === null;
+    }
+
+    public function getValue(): ?int {
+        return $this->value;
+    }
+}
diff --git a/vendor/phar-io/version/src/constraints/AbstractVersionConstraint.php b/vendor/phar-io/version/src/constraints/AbstractVersionConstraint.php
new file mode 100644
index 0000000000000000000000000000000000000000..66201a140fd93906a888a8dfc1802383c75e276b
--- /dev/null
+++ b/vendor/phar-io/version/src/constraints/AbstractVersionConstraint.php
@@ -0,0 +1,23 @@
+<?php declare(strict_types = 1);
+/*
+ * This file is part of PharIo\Version.
+ *
+ * (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PharIo\Version;
+
+abstract class AbstractVersionConstraint implements VersionConstraint {
+    /** @var string */
+    private $originalValue;
+
+    public function __construct(string $originalValue) {
+        $this->originalValue = $originalValue;
+    }
+
+    public function asString(): string {
+        return $this->originalValue;
+    }
+}
diff --git a/vendor/phar-io/version/src/constraints/AndVersionConstraintGroup.php b/vendor/phar-io/version/src/constraints/AndVersionConstraintGroup.php
new file mode 100644
index 0000000000000000000000000000000000000000..5096f2fbbc17298bf1b2ca9d3ab9b4321eee65be
--- /dev/null
+++ b/vendor/phar-io/version/src/constraints/AndVersionConstraintGroup.php
@@ -0,0 +1,34 @@
+<?php declare(strict_types = 1);
+/*
+ * This file is part of PharIo\Version.
+ *
+ * (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PharIo\Version;
+
+class AndVersionConstraintGroup extends AbstractVersionConstraint {
+    /** @var VersionConstraint[] */
+    private $constraints = [];
+
+    /**
+     * @param VersionConstraint[] $constraints
+     */
+    public function __construct(string $originalValue, array $constraints) {
+        parent::__construct($originalValue);
+
+        $this->constraints = $constraints;
+    }
+
+    public function complies(Version $version): bool {
+        foreach ($this->constraints as $constraint) {
+            if (!$constraint->complies($version)) {
+                return false;
+            }
+        }
+
+        return true;
+    }
+}
diff --git a/vendor/phar-io/version/src/constraints/AnyVersionConstraint.php b/vendor/phar-io/version/src/constraints/AnyVersionConstraint.php
new file mode 100644
index 0000000000000000000000000000000000000000..1499f071f07e1d5290d4ccec71b312316892f56c
--- /dev/null
+++ b/vendor/phar-io/version/src/constraints/AnyVersionConstraint.php
@@ -0,0 +1,20 @@
+<?php declare(strict_types = 1);
+/*
+ * This file is part of PharIo\Version.
+ *
+ * (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PharIo\Version;
+
+class AnyVersionConstraint implements VersionConstraint {
+    public function complies(Version $version): bool {
+        return true;
+    }
+
+    public function asString(): string {
+        return '*';
+    }
+}
diff --git a/vendor/phar-io/version/src/constraints/ExactVersionConstraint.php b/vendor/phar-io/version/src/constraints/ExactVersionConstraint.php
new file mode 100644
index 0000000000000000000000000000000000000000..2dd75f985711d1b21b11cc05eca7ede4753ccbad
--- /dev/null
+++ b/vendor/phar-io/version/src/constraints/ExactVersionConstraint.php
@@ -0,0 +1,16 @@
+<?php declare(strict_types = 1);
+/*
+ * This file is part of PharIo\Version.
+ *
+ * (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PharIo\Version;
+
+class ExactVersionConstraint extends AbstractVersionConstraint {
+    public function complies(Version $version): bool {
+        return $this->asString() === $version->getVersionString();
+    }
+}
diff --git a/vendor/phar-io/version/src/constraints/GreaterThanOrEqualToVersionConstraint.php b/vendor/phar-io/version/src/constraints/GreaterThanOrEqualToVersionConstraint.php
new file mode 100644
index 0000000000000000000000000000000000000000..ec3717231085900fd02c50ce0a536588b1b42a40
--- /dev/null
+++ b/vendor/phar-io/version/src/constraints/GreaterThanOrEqualToVersionConstraint.php
@@ -0,0 +1,26 @@
+<?php declare(strict_types = 1);
+/*
+ * This file is part of PharIo\Version.
+ *
+ * (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PharIo\Version;
+
+class GreaterThanOrEqualToVersionConstraint extends AbstractVersionConstraint {
+    /** @var Version */
+    private $minimalVersion;
+
+    public function __construct(string $originalValue, Version $minimalVersion) {
+        parent::__construct($originalValue);
+
+        $this->minimalVersion = $minimalVersion;
+    }
+
+    public function complies(Version $version): bool {
+        return $version->getVersionString() === $this->minimalVersion->getVersionString()
+            || $version->isGreaterThan($this->minimalVersion);
+    }
+}
diff --git a/vendor/phar-io/version/src/constraints/OrVersionConstraintGroup.php b/vendor/phar-io/version/src/constraints/OrVersionConstraintGroup.php
new file mode 100644
index 0000000000000000000000000000000000000000..59fd382f841a7a23de9bfb137fa1c7ce93bb63fc
--- /dev/null
+++ b/vendor/phar-io/version/src/constraints/OrVersionConstraintGroup.php
@@ -0,0 +1,35 @@
+<?php declare(strict_types = 1);
+/*
+ * This file is part of PharIo\Version.
+ *
+ * (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PharIo\Version;
+
+class OrVersionConstraintGroup extends AbstractVersionConstraint {
+    /** @var VersionConstraint[] */
+    private $constraints = [];
+
+    /**
+     * @param string              $originalValue
+     * @param VersionConstraint[] $constraints
+     */
+    public function __construct($originalValue, array $constraints) {
+        parent::__construct($originalValue);
+
+        $this->constraints = $constraints;
+    }
+
+    public function complies(Version $version): bool {
+        foreach ($this->constraints as $constraint) {
+            if ($constraint->complies($version)) {
+                return true;
+            }
+        }
+
+        return false;
+    }
+}
diff --git a/vendor/phar-io/version/src/constraints/SpecificMajorAndMinorVersionConstraint.php b/vendor/phar-io/version/src/constraints/SpecificMajorAndMinorVersionConstraint.php
new file mode 100644
index 0000000000000000000000000000000000000000..302aa311cdaac9bfb7c4e6a75e0178fbf9d6bc51
--- /dev/null
+++ b/vendor/phar-io/version/src/constraints/SpecificMajorAndMinorVersionConstraint.php
@@ -0,0 +1,33 @@
+<?php declare(strict_types = 1);
+/*
+ * This file is part of PharIo\Version.
+ *
+ * (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PharIo\Version;
+
+class SpecificMajorAndMinorVersionConstraint extends AbstractVersionConstraint {
+    /** @var int */
+    private $major;
+
+    /** @var int */
+    private $minor;
+
+    public function __construct(string $originalValue, int $major, int $minor) {
+        parent::__construct($originalValue);
+
+        $this->major = $major;
+        $this->minor = $minor;
+    }
+
+    public function complies(Version $version): bool {
+        if ($version->getMajor()->getValue() !== $this->major) {
+            return false;
+        }
+
+        return $version->getMinor()->getValue() === $this->minor;
+    }
+}
diff --git a/vendor/phar-io/version/src/constraints/SpecificMajorVersionConstraint.php b/vendor/phar-io/version/src/constraints/SpecificMajorVersionConstraint.php
new file mode 100644
index 0000000000000000000000000000000000000000..968b809c12954dbc1de9346aea304918feb185d6
--- /dev/null
+++ b/vendor/phar-io/version/src/constraints/SpecificMajorVersionConstraint.php
@@ -0,0 +1,25 @@
+<?php declare(strict_types = 1);
+/*
+ * This file is part of PharIo\Version.
+ *
+ * (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PharIo\Version;
+
+class SpecificMajorVersionConstraint extends AbstractVersionConstraint {
+    /** @var int */
+    private $major;
+
+    public function __construct(string $originalValue, int $major) {
+        parent::__construct($originalValue);
+
+        $this->major = $major;
+    }
+
+    public function complies(Version $version): bool {
+        return $version->getMajor()->getValue() === $this->major;
+    }
+}
diff --git a/vendor/phar-io/version/src/constraints/VersionConstraint.php b/vendor/phar-io/version/src/constraints/VersionConstraint.php
new file mode 100644
index 0000000000000000000000000000000000000000..e94f9e00edc362b7e51231041e6174302e6dceb9
--- /dev/null
+++ b/vendor/phar-io/version/src/constraints/VersionConstraint.php
@@ -0,0 +1,16 @@
+<?php declare(strict_types = 1);
+/*
+ * This file is part of PharIo\Version.
+ *
+ * (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PharIo\Version;
+
+interface VersionConstraint {
+    public function complies(Version $version): bool;
+
+    public function asString(): string;
+}
diff --git a/vendor/phar-io/version/src/exceptions/Exception.php b/vendor/phar-io/version/src/exceptions/Exception.php
new file mode 100644
index 0000000000000000000000000000000000000000..3ea458f3d098a0203b19783150e141e6c804b154
--- /dev/null
+++ b/vendor/phar-io/version/src/exceptions/Exception.php
@@ -0,0 +1,15 @@
+<?php declare(strict_types = 1);
+/*
+ * This file is part of PharIo\Version.
+ *
+ * (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PharIo\Version;
+
+use Throwable;
+
+interface Exception extends Throwable {
+}
diff --git a/vendor/phar-io/version/src/exceptions/InvalidPreReleaseSuffixException.php b/vendor/phar-io/version/src/exceptions/InvalidPreReleaseSuffixException.php
new file mode 100644
index 0000000000000000000000000000000000000000..bc0b0c3e4d93fa2245b0840c6d07d87c5b1c4afa
--- /dev/null
+++ b/vendor/phar-io/version/src/exceptions/InvalidPreReleaseSuffixException.php
@@ -0,0 +1,5 @@
+<?php declare(strict_types = 1);
+namespace PharIo\Version;
+
+class InvalidPreReleaseSuffixException extends \Exception implements Exception {
+}
diff --git a/vendor/phar-io/version/src/exceptions/InvalidVersionException.php b/vendor/phar-io/version/src/exceptions/InvalidVersionException.php
new file mode 100644
index 0000000000000000000000000000000000000000..e9e93108c0db8381cbe49025975384da0f668157
--- /dev/null
+++ b/vendor/phar-io/version/src/exceptions/InvalidVersionException.php
@@ -0,0 +1,5 @@
+<?php declare(strict_types = 1);
+namespace PharIo\Version;
+
+class InvalidVersionException extends \InvalidArgumentException implements Exception {
+}
diff --git a/vendor/phar-io/version/src/exceptions/NoPreReleaseSuffixException.php b/vendor/phar-io/version/src/exceptions/NoPreReleaseSuffixException.php
new file mode 100644
index 0000000000000000000000000000000000000000..aa0b20f7a59af1315bab90b03a682b693c21ec8d
--- /dev/null
+++ b/vendor/phar-io/version/src/exceptions/NoPreReleaseSuffixException.php
@@ -0,0 +1,5 @@
+<?php declare(strict_types = 1);
+namespace PharIo\Version;
+
+class NoPreReleaseSuffixException extends \Exception implements Exception {
+}
diff --git a/vendor/phar-io/version/src/exceptions/UnsupportedVersionConstraintException.php b/vendor/phar-io/version/src/exceptions/UnsupportedVersionConstraintException.php
new file mode 100644
index 0000000000000000000000000000000000000000..6d98e82506e7ec4a82266125655806e805e30708
--- /dev/null
+++ b/vendor/phar-io/version/src/exceptions/UnsupportedVersionConstraintException.php
@@ -0,0 +1,13 @@
+<?php declare(strict_types = 1);
+/*
+ * This file is part of PharIo\Version.
+ *
+ * (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PharIo\Version;
+
+final class UnsupportedVersionConstraintException extends \RuntimeException implements Exception {
+}
diff --git a/vendor/phpdocumentor/reflection-common/.github/dependabot.yml b/vendor/phpdocumentor/reflection-common/.github/dependabot.yml
new file mode 100644
index 0000000000000000000000000000000000000000..c630ffa6b3f0586c39cd467330f7578bfbba94ef
--- /dev/null
+++ b/vendor/phpdocumentor/reflection-common/.github/dependabot.yml
@@ -0,0 +1,7 @@
+version: 2
+updates:
+- package-ecosystem: composer
+  directory: "/"
+  schedule:
+    interval: daily
+  open-pull-requests-limit: 10
diff --git a/vendor/phpdocumentor/reflection-common/.github/workflows/push.yml b/vendor/phpdocumentor/reflection-common/.github/workflows/push.yml
new file mode 100644
index 0000000000000000000000000000000000000000..484410e9ac21815947bd23631a336927efd14746
--- /dev/null
+++ b/vendor/phpdocumentor/reflection-common/.github/workflows/push.yml
@@ -0,0 +1,223 @@
+on:
+  push:
+    branches:
+      - 2.x
+  pull_request:
+name: Qa workflow
+jobs:
+  setup:
+    runs-on: ubuntu-latest
+    steps:
+      - uses: actions/checkout@v2
+
+      - name: Restore/cache vendor folder
+        uses: actions/cache@v1
+        with:
+          path: vendor
+          key: all-build-${{ hashFiles('**/composer.lock') }}
+          restore-keys: |
+            all-build-${{ hashFiles('**/composer.lock') }}
+            all-build-
+
+      - name: Restore/cache tools folder
+        uses: actions/cache@v1
+        with:
+          path: tools
+          key: all-tools-${{ github.sha }}
+          restore-keys: |
+            all-tools-${{ github.sha }}-
+            all-tools-
+
+      - name: composer
+        uses: docker://composer
+        env:
+          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+        with:
+          args: install --no-interaction --prefer-dist --optimize-autoloader
+
+      - name: Install phive
+        run: make install-phive
+
+      - name: Install PHAR dependencies
+        run: tools/phive.phar --no-progress install --copy --trust-gpg-keys 4AA394086372C20A,8A03EA3B385DBAA1 --force-accept-unsigned
+
+  phpunit-with-coverage:
+    runs-on: ubuntu-latest
+    name: Unit tests
+    needs: setup
+    steps:
+      - uses: actions/checkout@v2
+
+      - name: Setup PHP
+        uses: shivammathur/setup-php@v2
+        with:
+          php-version: 7.2
+          ini-values: memory_limit=2G, display_errors=On, error_reporting=-1
+          coverage: pcov
+
+      - name: Restore/cache tools folder
+        uses: actions/cache@v1
+        with:
+          path: tools
+          key: all-tools-${{ github.sha }}
+          restore-keys: |
+            all-tools-${{ github.sha }}-
+            all-tools-
+
+      - name: Get composer cache directory
+        id: composer-cache
+        run: echo "::set-output name=dir::$(composer config cache-files-dir)"
+
+      - name: Cache composer dependencies
+        uses: actions/cache@v1
+        with:
+          path: ${{ steps.composer-cache.outputs.dir }}
+          key: ubuntu-latest-composer-${{ hashFiles('**/composer.lock') }}
+          restore-keys: ubuntu-latest-composer-
+
+      - name: Install Composer dependencies
+        run: |
+          composer install --no-progress --no-suggest --prefer-dist --optimize-autoloader
+
+      - name: Run PHPUnit
+        run: php tools/phpunit
+
+  phpunit:
+    runs-on: ${{ matrix.operating-system }}
+    strategy:
+      matrix:
+        operating-system:
+          - ubuntu-latest
+          - windows-latest
+          - macOS-latest
+        php-versions: ['7.2', '7.3', '7.4', '8.0']
+    name: Unit tests for PHP version ${{ matrix.php-versions }} on ${{ matrix.operating-system }}
+    needs:
+      - setup
+      - phpunit-with-coverage
+    steps:
+      - uses: actions/checkout@v2
+
+      - name: Restore/cache tools folder
+        uses: actions/cache@v1
+        with:
+          path: tools
+          key: all-tools-${{ github.sha }}
+          restore-keys: |
+            all-tools-${{ github.sha }}-
+            all-tools-
+
+      - name: Setup PHP
+        uses: shivammathur/setup-php@v2
+        with:
+          php-version: ${{ matrix.php-versions }}
+          ini-values: memory_limit=2G, display_errors=On, error_reporting=-1
+          coverage: none
+
+      - name: Get composer cache directory
+        id: composer-cache
+        run: echo "::set-output name=dir::$(composer config cache-files-dir)"
+
+      - name: Cache composer dependencies
+        uses: actions/cache@v1
+        with:
+          path: ${{ steps.composer-cache.outputs.dir }}
+          key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }}
+          restore-keys: ${{ runner.os }}-composer-
+
+      - name: Install Composer dependencies
+        run: |
+          composer install --no-progress --no-suggest --prefer-dist --optimize-autoloader
+
+      - name: Run PHPUnit
+        continue-on-error: true
+        run: php tools/phpunit
+
+  codestyle:
+    runs-on: ubuntu-latest
+    needs: [setup, phpunit]
+    steps:
+      - uses: actions/checkout@v2
+      - name: Restore/cache vendor folder
+        uses: actions/cache@v1
+        with:
+          path: vendor
+          key: all-build-${{ hashFiles('**/composer.lock') }}
+          restore-keys: |
+            all-build-${{ hashFiles('**/composer.lock') }}
+            all-build-
+      - name: Code style check
+        uses: phpDocumentor/coding-standard@latest
+        with:
+          args: -s
+
+  phpstan:
+    runs-on: ubuntu-latest
+    needs: [setup, phpunit]
+    steps:
+      - uses: actions/checkout@v2
+      - name: Restore/cache vendor folder
+        uses: actions/cache@v1
+        with:
+          path: vendor
+          key: all-build-${{ hashFiles('**/composer.lock') }}
+          restore-keys: |
+            all-build-${{ hashFiles('**/composer.lock') }}
+            all-build-
+      - name: PHPStan
+        uses: phpDocumentor/phpstan-ga@latest
+        env:
+          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+        with:
+          args: analyse src --configuration phpstan.neon
+
+  psalm:
+    runs-on: ubuntu-latest
+    needs: [setup, phpunit]
+    steps:
+      - uses: actions/checkout@v2
+
+      - name: Setup PHP
+        uses: shivammathur/setup-php@v2
+        with:
+          php-version: 7.2
+          ini-values: memory_limit=2G, display_errors=On, error_reporting=-1
+          tools: psalm
+          coverage: none
+
+      - name: Get composer cache directory
+        id: composer-cache
+        run: echo "::set-output name=dir::$(composer config cache-files-dir)"
+
+      - name: Cache composer dependencies
+        uses: actions/cache@v1
+        with:
+          path: ${{ steps.composer-cache.outputs.dir }}
+          key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }}
+          restore-keys: ${{ runner.os }}-composer-
+
+      - name: Install Composer dependencies
+        run: |
+          composer install --no-progress --no-suggest --prefer-dist --optimize-autoloader
+
+      - name: Psalm
+        run: psalm --output-format=github
+
+  bc_check:
+    name: BC Check
+    runs-on: ubuntu-latest
+    needs: [setup, phpunit]
+    steps:
+      - uses: actions/checkout@v2
+      - name: fetch tags
+        run: git fetch --depth=1 origin +refs/tags/*:refs/tags/*
+      - name: Restore/cache vendor folder
+        uses: actions/cache@v1
+        with:
+          path: vendor
+          key: all-build-${{ hashFiles('**/composer.lock') }}
+          restore-keys: |
+            all-build-${{ hashFiles('**/composer.lock') }}
+            all-build-
+      - name: Roave BC Check
+        uses: docker://nyholm/roave-bc-check-ga
diff --git a/vendor/phpdocumentor/reflection-common/LICENSE b/vendor/phpdocumentor/reflection-common/LICENSE
new file mode 100644
index 0000000000000000000000000000000000000000..ed6926c1ee795441d5e57d3985e644e5f6028d89
--- /dev/null
+++ b/vendor/phpdocumentor/reflection-common/LICENSE
@@ -0,0 +1,22 @@
+The MIT License (MIT)
+
+Copyright (c) 2015 phpDocumentor
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+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/phpdocumentor/reflection-common/README.md b/vendor/phpdocumentor/reflection-common/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..70f830dc71dff125335730d2c85163f14b6f2278
--- /dev/null
+++ b/vendor/phpdocumentor/reflection-common/README.md
@@ -0,0 +1,11 @@
+[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
+![Qa workflow](https://github.com/phpDocumentor/ReflectionCommon/workflows/Qa%20workflow/badge.svg)
+[![Coveralls Coverage](https://img.shields.io/coveralls/github/phpDocumentor/ReflectionCommon.svg)](https://coveralls.io/github/phpDocumentor/ReflectionCommon?branch=master)
+[![Scrutinizer Code Coverage](https://img.shields.io/scrutinizer/coverage/g/phpDocumentor/ReflectionCommon.svg)](https://scrutinizer-ci.com/g/phpDocumentor/ReflectionCommon/?branch=master)
+[![Scrutinizer Code Quality](https://img.shields.io/scrutinizer/g/phpDocumentor/ReflectionCommon.svg)](https://scrutinizer-ci.com/g/phpDocumentor/ReflectionCommon/?branch=master)
+[![Stable Version](https://img.shields.io/packagist/v/phpDocumentor/Reflection-Common.svg)](https://packagist.org/packages/phpDocumentor/Reflection-Common)
+[![Unstable Version](https://img.shields.io/packagist/vpre/phpDocumentor/Reflection-Common.svg)](https://packagist.org/packages/phpDocumentor/Reflection-Common)
+
+
+ReflectionCommon
+================
diff --git a/vendor/phpdocumentor/reflection-common/composer.json b/vendor/phpdocumentor/reflection-common/composer.json
new file mode 100644
index 0000000000000000000000000000000000000000..4d128b49a9e26af95feb9fe3d229582c270fa61d
--- /dev/null
+++ b/vendor/phpdocumentor/reflection-common/composer.json
@@ -0,0 +1,28 @@
+{
+    "name": "phpdocumentor/reflection-common",
+    "keywords": ["phpdoc", "phpDocumentor", "reflection", "static analysis", "FQSEN"],
+    "homepage": "http://www.phpdoc.org",
+    "description": "Common reflection classes used by phpdocumentor to reflect the code structure",
+    "license": "MIT",
+    "authors": [
+        {
+            "name": "Jaap van Otterdijk",
+            "email": "opensource@ijaap.nl"
+        }
+    ],
+    "require": {
+        "php": "^7.2 || ^8.0"
+    },
+    "autoload" : {
+      "psr-4" : {
+        "phpDocumentor\\Reflection\\": "src/"
+      }
+    },
+    "require-dev": {
+    },
+    "extra": {
+        "branch-alias": {
+            "dev-2.x": "2.x-dev"
+        }
+    }
+}
diff --git a/vendor/phpdocumentor/reflection-common/src/Element.php b/vendor/phpdocumentor/reflection-common/src/Element.php
new file mode 100644
index 0000000000000000000000000000000000000000..8923e4fb01d315aeb336fe32f3d08bba9644d36e
--- /dev/null
+++ b/vendor/phpdocumentor/reflection-common/src/Element.php
@@ -0,0 +1,30 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * phpDocumentor
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ *
+ * @link      http://phpdoc.org
+ */
+
+namespace phpDocumentor\Reflection;
+
+/**
+ * Interface for Api Elements
+ */
+interface Element
+{
+    /**
+     * Returns the Fqsen of the element.
+     */
+    public function getFqsen() : Fqsen;
+
+    /**
+     * Returns the name of the element.
+     */
+    public function getName() : string;
+}
diff --git a/vendor/phpdocumentor/reflection-common/src/File.php b/vendor/phpdocumentor/reflection-common/src/File.php
new file mode 100644
index 0000000000000000000000000000000000000000..239c137e74a158abb133c4cc916ab38b0ff001ec
--- /dev/null
+++ b/vendor/phpdocumentor/reflection-common/src/File.php
@@ -0,0 +1,35 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * This file is part of phpDocumentor.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ *
+ * @link      http://phpdoc.org
+ */
+
+namespace phpDocumentor\Reflection;
+
+/**
+ * Interface for files processed by the ProjectFactory
+ */
+interface File
+{
+    /**
+     * Returns the content of the file as a string.
+     */
+    public function getContents() : string;
+
+    /**
+     * Returns md5 hash of the file.
+     */
+    public function md5() : string;
+
+    /**
+     * Returns an relative path to the file.
+     */
+    public function path() : string;
+}
diff --git a/vendor/phpdocumentor/reflection-common/src/Fqsen.php b/vendor/phpdocumentor/reflection-common/src/Fqsen.php
new file mode 100644
index 0000000000000000000000000000000000000000..8fc5d34411cae4e6d9c53c914aa65431b29ac498
--- /dev/null
+++ b/vendor/phpdocumentor/reflection-common/src/Fqsen.php
@@ -0,0 +1,89 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * phpDocumentor
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ *
+ * @link      http://phpdoc.org
+ */
+
+namespace phpDocumentor\Reflection;
+
+use InvalidArgumentException;
+use function assert;
+use function end;
+use function explode;
+use function is_string;
+use function preg_match;
+use function sprintf;
+use function trim;
+
+/**
+ * Value Object for Fqsen.
+ *
+ * @link https://github.com/phpDocumentor/fig-standards/blob/master/proposed/phpdoc-meta.md
+ *
+ * @psalm-immutable
+ */
+final class Fqsen
+{
+    /** @var string full quallified class name */
+    private $fqsen;
+
+    /** @var string name of the element without path. */
+    private $name;
+
+    /**
+     * Initializes the object.
+     *
+     * @throws InvalidArgumentException when $fqsen is not matching the format.
+     */
+    public function __construct(string $fqsen)
+    {
+        $matches = [];
+
+        $result = preg_match(
+            //phpcs:ignore Generic.Files.LineLength.TooLong
+            '/^\\\\([a-zA-Z_\\x7f-\\xff][a-zA-Z0-9_\\x7f-\\xff\\\\]*)?(?:[:]{2}\\$?([a-zA-Z_\\x7f-\\xff][a-zA-Z0-9_\\x7f-\\xff]*))?(?:\\(\\))?$/',
+            $fqsen,
+            $matches
+        );
+
+        if ($result === 0) {
+            throw new InvalidArgumentException(
+                sprintf('"%s" is not a valid Fqsen.', $fqsen)
+            );
+        }
+
+        $this->fqsen = $fqsen;
+
+        if (isset($matches[2])) {
+            $this->name = $matches[2];
+        } else {
+            $matches = explode('\\', $fqsen);
+            $name = end($matches);
+            assert(is_string($name));
+            $this->name = trim($name, '()');
+        }
+    }
+
+    /**
+     * converts this class to string.
+     */
+    public function __toString() : string
+    {
+        return $this->fqsen;
+    }
+
+    /**
+     * Returns the name of the element without path.
+     */
+    public function getName() : string
+    {
+        return $this->name;
+    }
+}
diff --git a/vendor/phpdocumentor/reflection-common/src/Location.php b/vendor/phpdocumentor/reflection-common/src/Location.php
new file mode 100644
index 0000000000000000000000000000000000000000..177deede693c3108a467ba18b98daaf348ef82e7
--- /dev/null
+++ b/vendor/phpdocumentor/reflection-common/src/Location.php
@@ -0,0 +1,53 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * This file is part of phpDocumentor.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ *
+ * @link      http://phpdoc.org
+ */
+
+namespace phpDocumentor\Reflection;
+
+/**
+ * The location where an element occurs within a file.
+ *
+ * @psalm-immutable
+ */
+final class Location
+{
+    /** @var int */
+    private $lineNumber = 0;
+
+    /** @var int */
+    private $columnNumber = 0;
+
+    /**
+     * Initializes the location for an element using its line number in the file and optionally the column number.
+     */
+    public function __construct(int $lineNumber, int $columnNumber = 0)
+    {
+        $this->lineNumber = $lineNumber;
+        $this->columnNumber = $columnNumber;
+    }
+
+    /**
+     * Returns the line number that is covered by this location.
+     */
+    public function getLineNumber() : int
+    {
+        return $this->lineNumber;
+    }
+
+    /**
+     * Returns the column number (character position on a line) for this location object.
+     */
+    public function getColumnNumber() : int
+    {
+        return $this->columnNumber;
+    }
+}
diff --git a/vendor/phpdocumentor/reflection-common/src/Project.php b/vendor/phpdocumentor/reflection-common/src/Project.php
new file mode 100644
index 0000000000000000000000000000000000000000..57839fd1467adc5e0c2818d8257c65926b7f4e31
--- /dev/null
+++ b/vendor/phpdocumentor/reflection-common/src/Project.php
@@ -0,0 +1,25 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * phpDocumentor
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ *
+ * @link      http://phpdoc.org
+ */
+
+namespace phpDocumentor\Reflection;
+
+/**
+ * Interface for project. Since the definition of a project can be different per factory this interface will be small.
+ */
+interface Project
+{
+    /**
+     * Returns the name of the project.
+     */
+    public function getName() : string;
+}
diff --git a/vendor/phpdocumentor/reflection-common/src/ProjectFactory.php b/vendor/phpdocumentor/reflection-common/src/ProjectFactory.php
new file mode 100644
index 0000000000000000000000000000000000000000..8bdc60678d38b7b495c46c47931677522c8d0bd5
--- /dev/null
+++ b/vendor/phpdocumentor/reflection-common/src/ProjectFactory.php
@@ -0,0 +1,28 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * phpDocumentor
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ *
+ * @link      http://phpdoc.org
+ */
+
+namespace phpDocumentor\Reflection;
+
+/**
+ * Interface for project factories. A project factory shall convert a set of files
+ * into an object implementing the Project interface.
+ */
+interface ProjectFactory
+{
+    /**
+     * Creates a project from the set of files.
+     *
+     * @param File[] $files
+     */
+    public function create(string $name, array $files) : Project;
+}
diff --git a/vendor/phpdocumentor/reflection-docblock/LICENSE b/vendor/phpdocumentor/reflection-docblock/LICENSE
new file mode 100644
index 0000000000000000000000000000000000000000..792e4040f26f0347b3beb069d6ea070e6ae14a69
--- /dev/null
+++ b/vendor/phpdocumentor/reflection-docblock/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2010 Mike van Riel
+
+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/phpdocumentor/reflection-docblock/README.md b/vendor/phpdocumentor/reflection-docblock/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..51f10883b731b6e0aa93e3479b304359fa756306
--- /dev/null
+++ b/vendor/phpdocumentor/reflection-docblock/README.md
@@ -0,0 +1,75 @@
+[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
+![Qa workflow](https://github.com/phpDocumentor/ReflectionDocBlock/workflows/Qa%20workflow/badge.svg)
+[![Coveralls Coverage](https://img.shields.io/coveralls/github/phpDocumentor/ReflectionDocBlock.svg)](https://coveralls.io/github/phpDocumentor/ReflectionDocBlock?branch=master)
+[![Scrutinizer Code Coverage](https://img.shields.io/scrutinizer/coverage/g/phpDocumentor/ReflectionDocBlock.svg)](https://scrutinizer-ci.com/g/phpDocumentor/ReflectionDocBlock/?branch=master)
+[![Scrutinizer Code Quality](https://img.shields.io/scrutinizer/g/phpDocumentor/ReflectionDocBlock.svg)](https://scrutinizer-ci.com/g/phpDocumentor/ReflectionDocBlock/?branch=master)
+[![Stable Version](https://img.shields.io/packagist/v/phpdocumentor/reflection-docblock.svg)](https://packagist.org/packages/phpdocumentor/reflection-docblock)
+[![Unstable Version](https://img.shields.io/packagist/vpre/phpdocumentor/reflection-docblock.svg)](https://packagist.org/packages/phpdocumentor/reflection-docblock)
+
+ReflectionDocBlock 
+==================
+
+Introduction
+------------
+
+The ReflectionDocBlock component of phpDocumentor provides a DocBlock parser
+that is 100% compatible with the [PHPDoc standard](http://phpdoc.org/docs/latest).
+
+With this component, a library can provide support for annotations via DocBlocks
+or otherwise retrieve information that is embedded in a DocBlock.
+
+Installation
+------------
+
+```bash
+composer require phpdocumentor/reflection-docblock
+```
+
+Usage
+-----
+
+In order to parse the DocBlock one needs a DocBlockFactory that can be
+instantiated using its `createInstance` factory method like this:
+
+```php
+$factory  = \phpDocumentor\Reflection\DocBlockFactory::createInstance();
+```
+
+Then we can use the `create` method of the factory to interpret the DocBlock.
+Please note that it is also possible to provide a class that has the
+`getDocComment()` method, such as an object of type `ReflectionClass`, the
+create method will read that if it exists.
+
+```php
+$docComment = <<<DOCCOMMENT
+/**
+ * This is an example of a summary.
+ *
+ * This is a Description. A Summary and Description are separated by either
+ * two subsequent newlines (thus a whiteline in between as can be seen in this
+ * example), or when the Summary ends with a dot (`.`) and some form of
+ * whitespace.
+ */
+DOCCOMMENT;
+
+$docblock = $factory->create($docComment);
+```
+
+The `create` method will yield an object of type `\phpDocumentor\Reflection\DocBlock`
+whose methods can be queried:
+
+```php
+// Contains the summary for this DocBlock
+$summary = $docblock->getSummary();
+
+// Contains \phpDocumentor\Reflection\DocBlock\Description object
+$description = $docblock->getDescription();
+
+// You can either cast it to string
+$description = (string) $docblock->getDescription();
+
+// Or use the render method to get a string representation of the Description.
+$description = $docblock->getDescription()->render();
+```
+
+> For more examples it would be best to review the scripts in the [`/examples` folder](/examples).
diff --git a/vendor/phpdocumentor/reflection-docblock/composer.json b/vendor/phpdocumentor/reflection-docblock/composer.json
new file mode 100644
index 0000000000000000000000000000000000000000..7038f48a660936d36b7548c81f4fef74534e4499
--- /dev/null
+++ b/vendor/phpdocumentor/reflection-docblock/composer.json
@@ -0,0 +1,41 @@
+{
+    "name": "phpdocumentor/reflection-docblock",
+    "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.",
+    "type": "library",
+    "license": "MIT",
+    "authors": [
+        {
+            "name": "Mike van Riel",
+            "email": "me@mikevanriel.com"
+        },
+        {
+            "name": "Jaap van Otterdijk",
+            "email": "account@ijaap.nl"
+        }
+    ],
+    "require": {
+        "php": "^7.2 || ^8.0",
+        "phpdocumentor/type-resolver": "^1.3",
+        "webmozart/assert": "^1.9.1",
+        "phpdocumentor/reflection-common": "^2.2",
+        "ext-filter": "*"
+    },
+    "require-dev": {
+        "mockery/mockery": "~1.3.2"
+    },
+    "autoload": {
+        "psr-4": {
+            "phpDocumentor\\Reflection\\": "src"
+        }
+    },
+    "autoload-dev": {
+        "psr-4": {
+            "phpDocumentor\\Reflection\\": "tests/unit"
+        }
+    },
+    "extra": {
+        "branch-alias": {
+            "dev-master": "5.x-dev"
+        }
+    }
+}
diff --git a/vendor/phpdocumentor/reflection-docblock/src/DocBlock.php b/vendor/phpdocumentor/reflection-docblock/src/DocBlock.php
new file mode 100644
index 0000000000000000000000000000000000000000..f3403d6e8cafbf4b1400733ed03cf7685af1f9ae
--- /dev/null
+++ b/vendor/phpdocumentor/reflection-docblock/src/DocBlock.php
@@ -0,0 +1,204 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * This file is part of phpDocumentor.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ *
+ * @link      http://phpdoc.org
+ */
+
+namespace phpDocumentor\Reflection;
+
+use phpDocumentor\Reflection\DocBlock\Tag;
+use Webmozart\Assert\Assert;
+
+final class DocBlock
+{
+    /** @var string The opening line for this docblock. */
+    private $summary;
+
+    /** @var DocBlock\Description The actual description for this docblock. */
+    private $description;
+
+    /** @var Tag[] An array containing all the tags in this docblock; except inline. */
+    private $tags = [];
+
+    /** @var Types\Context|null Information about the context of this DocBlock. */
+    private $context;
+
+    /** @var Location|null Information about the location of this DocBlock. */
+    private $location;
+
+    /** @var bool Is this DocBlock (the start of) a template? */
+    private $isTemplateStart;
+
+    /** @var bool Does this DocBlock signify the end of a DocBlock template? */
+    private $isTemplateEnd;
+
+    /**
+     * @param DocBlock\Tag[] $tags
+     * @param Types\Context  $context  The context in which the DocBlock occurs.
+     * @param Location       $location The location within the file that this DocBlock occurs in.
+     */
+    public function __construct(
+        string $summary = '',
+        ?DocBlock\Description $description = null,
+        array $tags = [],
+        ?Types\Context $context = null,
+        ?Location $location = null,
+        bool $isTemplateStart = false,
+        bool $isTemplateEnd = false
+    ) {
+        Assert::allIsInstanceOf($tags, Tag::class);
+
+        $this->summary     = $summary;
+        $this->description = $description ?: new DocBlock\Description('');
+        foreach ($tags as $tag) {
+            $this->addTag($tag);
+        }
+
+        $this->context  = $context;
+        $this->location = $location;
+
+        $this->isTemplateEnd   = $isTemplateEnd;
+        $this->isTemplateStart = $isTemplateStart;
+    }
+
+    public function getSummary() : string
+    {
+        return $this->summary;
+    }
+
+    public function getDescription() : DocBlock\Description
+    {
+        return $this->description;
+    }
+
+    /**
+     * Returns the current context.
+     */
+    public function getContext() : ?Types\Context
+    {
+        return $this->context;
+    }
+
+    /**
+     * Returns the current location.
+     */
+    public function getLocation() : ?Location
+    {
+        return $this->location;
+    }
+
+    /**
+     * Returns whether this DocBlock is the start of a Template section.
+     *
+     * A Docblock may serve as template for a series of subsequent DocBlocks. This is indicated by a special marker
+     * (`#@+`) that is appended directly after the opening `/**` of a DocBlock.
+     *
+     * An example of such an opening is:
+     *
+     * ```
+     * /**#@+
+     *  * My DocBlock
+     *  * /
+     * ```
+     *
+     * The description and tags (not the summary!) are copied onto all subsequent DocBlocks and also applied to all
+     * elements that follow until another DocBlock is found that contains the closing marker (`#@-`).
+     *
+     * @see self::isTemplateEnd() for the check whether a closing marker was provided.
+     */
+    public function isTemplateStart() : bool
+    {
+        return $this->isTemplateStart;
+    }
+
+    /**
+     * Returns whether this DocBlock is the end of a Template section.
+     *
+     * @see self::isTemplateStart() for a more complete description of the Docblock Template functionality.
+     */
+    public function isTemplateEnd() : bool
+    {
+        return $this->isTemplateEnd;
+    }
+
+    /**
+     * Returns the tags for this DocBlock.
+     *
+     * @return Tag[]
+     */
+    public function getTags() : array
+    {
+        return $this->tags;
+    }
+
+    /**
+     * Returns an array of tags matching the given name. If no tags are found
+     * an empty array is returned.
+     *
+     * @param string $name String to search by.
+     *
+     * @return Tag[]
+     */
+    public function getTagsByName(string $name) : array
+    {
+        $result = [];
+
+        foreach ($this->getTags() as $tag) {
+            if ($tag->getName() !== $name) {
+                continue;
+            }
+
+            $result[] = $tag;
+        }
+
+        return $result;
+    }
+
+    /**
+     * Checks if a tag of a certain type is present in this DocBlock.
+     *
+     * @param string $name Tag name to check for.
+     */
+    public function hasTag(string $name) : bool
+    {
+        foreach ($this->getTags() as $tag) {
+            if ($tag->getName() === $name) {
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+    /**
+     * Remove a tag from this DocBlock.
+     *
+     * @param Tag $tagToRemove The tag to remove.
+     */
+    public function removeTag(Tag $tagToRemove) : void
+    {
+        foreach ($this->tags as $key => $tag) {
+            if ($tag === $tagToRemove) {
+                unset($this->tags[$key]);
+                break;
+            }
+        }
+    }
+
+    /**
+     * Adds a tag to this DocBlock.
+     *
+     * @param Tag $tag The tag to add.
+     */
+    private function addTag(Tag $tag) : void
+    {
+        $this->tags[] = $tag;
+    }
+}
diff --git a/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Description.php b/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Description.php
new file mode 100644
index 0000000000000000000000000000000000000000..7b11b808e788b5da3d154729d528221c8a112286
--- /dev/null
+++ b/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Description.php
@@ -0,0 +1,114 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * This file is part of phpDocumentor.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ *
+ * @link      http://phpdoc.org
+ */
+
+namespace phpDocumentor\Reflection\DocBlock;
+
+use phpDocumentor\Reflection\DocBlock\Tags\Formatter;
+use phpDocumentor\Reflection\DocBlock\Tags\Formatter\PassthroughFormatter;
+use function vsprintf;
+
+/**
+ * Object representing to description for a DocBlock.
+ *
+ * A Description object can consist of plain text but can also include tags. A Description Formatter can then combine
+ * a body template with sprintf-style placeholders together with formatted tags in order to reconstitute a complete
+ * description text using the format that you would prefer.
+ *
+ * Because parsing a Description text can be a verbose process this is handled by the {@see DescriptionFactory}. It is
+ * thus recommended to use that to create a Description object, like this:
+ *
+ *     $description = $descriptionFactory->create('This is a {@see Description}', $context);
+ *
+ * The description factory will interpret the given body and create a body template and list of tags from them, and pass
+ * that onto the constructor if this class.
+ *
+ * > The $context variable is a class of type {@see \phpDocumentor\Reflection\Types\Context} and contains the namespace
+ * > and the namespace aliases that apply to this DocBlock. These are used by the Factory to resolve and expand partial
+ * > type names and FQSENs.
+ *
+ * If you do not want to use the DescriptionFactory you can pass a body template and tag listing like this:
+ *
+ *     $description = new Description(
+ *         'This is a %1$s',
+ *         [ new See(new Fqsen('\phpDocumentor\Reflection\DocBlock\Description')) ]
+ *     );
+ *
+ * It is generally recommended to use the Factory as that will also apply escaping rules, while the Description object
+ * is mainly responsible for rendering.
+ *
+ * @see DescriptionFactory to create a new Description.
+ * @see Description\Formatter for the formatting of the body and tags.
+ */
+class Description
+{
+    /** @var string */
+    private $bodyTemplate;
+
+    /** @var Tag[] */
+    private $tags;
+
+    /**
+     * Initializes a Description with its body (template) and a listing of the tags used in the body template.
+     *
+     * @param Tag[] $tags
+     */
+    public function __construct(string $bodyTemplate, array $tags = [])
+    {
+        $this->bodyTemplate = $bodyTemplate;
+        $this->tags         = $tags;
+    }
+
+    /**
+     * Returns the body template.
+     */
+    public function getBodyTemplate() : string
+    {
+        return $this->bodyTemplate;
+    }
+
+    /**
+     * Returns the tags for this DocBlock.
+     *
+     * @return Tag[]
+     */
+    public function getTags() : array
+    {
+        return $this->tags;
+    }
+
+    /**
+     * Renders this description as a string where the provided formatter will format the tags in the expected string
+     * format.
+     */
+    public function render(?Formatter $formatter = null) : string
+    {
+        if ($formatter === null) {
+            $formatter = new PassthroughFormatter();
+        }
+
+        $tags = [];
+        foreach ($this->tags as $tag) {
+            $tags[] = '{' . $formatter->format($tag) . '}';
+        }
+
+        return vsprintf($this->bodyTemplate, $tags);
+    }
+
+    /**
+     * Returns a plain string representation of this description.
+     */
+    public function __toString() : string
+    {
+        return $this->render();
+    }
+}
diff --git a/vendor/phpdocumentor/reflection-docblock/src/DocBlock/DescriptionFactory.php b/vendor/phpdocumentor/reflection-docblock/src/DocBlock/DescriptionFactory.php
new file mode 100644
index 0000000000000000000000000000000000000000..c27d2a0121abc058a779d49df5e59cb533015133
--- /dev/null
+++ b/vendor/phpdocumentor/reflection-docblock/src/DocBlock/DescriptionFactory.php
@@ -0,0 +1,177 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * This file is part of phpDocumentor.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ *
+ * @link      http://phpdoc.org
+ */
+
+namespace phpDocumentor\Reflection\DocBlock;
+
+use phpDocumentor\Reflection\Types\Context as TypeContext;
+use phpDocumentor\Reflection\Utils;
+use function count;
+use function explode;
+use function implode;
+use function ltrim;
+use function min;
+use function str_replace;
+use function strlen;
+use function strpos;
+use function substr;
+use function trim;
+use const PREG_SPLIT_DELIM_CAPTURE;
+
+/**
+ * Creates a new Description object given a body of text.
+ *
+ * Descriptions in phpDocumentor are somewhat complex entities as they can contain one or more tags inside their
+ * body that can be replaced with a readable output. The replacing is done by passing a Formatter object to the
+ * Description object's `render` method.
+ *
+ * In addition to the above does a Description support two types of escape sequences:
+ *
+ * 1. `{@}` to escape the `@` character to prevent it from being interpreted as part of a tag, i.e. `{{@}link}`
+ * 2. `{}` to escape the `}` character, this can be used if you want to use the `}` character in the description
+ *    of an inline tag.
+ *
+ * If a body consists of multiple lines then this factory will also remove any superfluous whitespace at the beginning
+ * of each line while maintaining any indentation that is used. This will prevent formatting parsers from tripping
+ * over unexpected spaces as can be observed with tag descriptions.
+ */
+class DescriptionFactory
+{
+    /** @var TagFactory */
+    private $tagFactory;
+
+    /**
+     * Initializes this factory with the means to construct (inline) tags.
+     */
+    public function __construct(TagFactory $tagFactory)
+    {
+        $this->tagFactory = $tagFactory;
+    }
+
+    /**
+     * Returns the parsed text of this description.
+     */
+    public function create(string $contents, ?TypeContext $context = null) : Description
+    {
+        $tokens   = $this->lex($contents);
+        $count    = count($tokens);
+        $tagCount = 0;
+        $tags     = [];
+
+        for ($i = 1; $i < $count; $i += 2) {
+            $tags[]     = $this->tagFactory->create($tokens[$i], $context);
+            $tokens[$i] = '%' . ++$tagCount . '$s';
+        }
+
+        //In order to allow "literal" inline tags, the otherwise invalid
+        //sequence "{@}" is changed to "@", and "{}" is changed to "}".
+        //"%" is escaped to "%%" because of vsprintf.
+        //See unit tests for examples.
+        for ($i = 0; $i < $count; $i += 2) {
+            $tokens[$i] = str_replace(['{@}', '{}', '%'], ['@', '}', '%%'], $tokens[$i]);
+        }
+
+        return new Description(implode('', $tokens), $tags);
+    }
+
+    /**
+     * Strips the contents from superfluous whitespace and splits the description into a series of tokens.
+     *
+     * @return string[] A series of tokens of which the description text is composed.
+     */
+    private function lex(string $contents) : array
+    {
+        $contents = $this->removeSuperfluousStartingWhitespace($contents);
+
+        // performance optimalization; if there is no inline tag, don't bother splitting it up.
+        if (strpos($contents, '{@') === false) {
+            return [$contents];
+        }
+
+        return Utils::pregSplit(
+            '/\{
+                # "{@}" is not a valid inline tag. This ensures that we do not treat it as one, but treat it literally.
+                (?!@\})
+                # We want to capture the whole tag line, but without the inline tag delimiters.
+                (\@
+                    # Match everything up to the next delimiter.
+                    [^{}]*
+                    # Nested inline tag content should not be captured, or it will appear in the result separately.
+                    (?:
+                        # Match nested inline tags.
+                        (?:
+                            # Because we did not catch the tag delimiters earlier, we must be explicit with them here.
+                            # Notice that this also matches "{}", as a way to later introduce it as an escape sequence.
+                            \{(?1)?\}
+                            |
+                            # Make sure we match hanging "{".
+                            \{
+                        )
+                        # Match content after the nested inline tag.
+                        [^{}]*
+                    )* # If there are more inline tags, match them as well. We use "*" since there may not be any
+                       # nested inline tags.
+                )
+            \}/Sux',
+            $contents,
+            0,
+            PREG_SPLIT_DELIM_CAPTURE
+        );
+    }
+
+    /**
+     * Removes the superfluous from a multi-line description.
+     *
+     * When a description has more than one line then it can happen that the second and subsequent lines have an
+     * additional indentation. This is commonly in use with tags like this:
+     *
+     *     {@}since 1.1.0 This is an example
+     *         description where we have an
+     *         indentation in the second and
+     *         subsequent lines.
+     *
+     * If we do not normalize the indentation then we have superfluous whitespace on the second and subsequent
+     * lines and this may cause rendering issues when, for example, using a Markdown converter.
+     */
+    private function removeSuperfluousStartingWhitespace(string $contents) : string
+    {
+        $lines = explode("\n", $contents);
+
+        // if there is only one line then we don't have lines with superfluous whitespace and
+        // can use the contents as-is
+        if (count($lines) <= 1) {
+            return $contents;
+        }
+
+        // determine how many whitespace characters need to be stripped
+        $startingSpaceCount = 9999999;
+        for ($i = 1, $iMax = count($lines); $i < $iMax; ++$i) {
+            // lines with a no length do not count as they are not indented at all
+            if (trim($lines[$i]) === '') {
+                continue;
+            }
+
+            // determine the number of prefixing spaces by checking the difference in line length before and after
+            // an ltrim
+            $startingSpaceCount = min($startingSpaceCount, strlen($lines[$i]) - strlen(ltrim($lines[$i])));
+        }
+
+        // strip the number of spaces from each line
+        if ($startingSpaceCount > 0) {
+            for ($i = 1, $iMax = count($lines); $i < $iMax; ++$i) {
+                $lines[$i] = substr($lines[$i], $startingSpaceCount);
+            }
+        }
+
+        return implode("\n", $lines);
+    }
+}
diff --git a/vendor/phpdocumentor/reflection-docblock/src/DocBlock/ExampleFinder.php b/vendor/phpdocumentor/reflection-docblock/src/DocBlock/ExampleFinder.php
new file mode 100644
index 0000000000000000000000000000000000000000..7249efb0499f20bc4aac47009674f374f0365e47
--- /dev/null
+++ b/vendor/phpdocumentor/reflection-docblock/src/DocBlock/ExampleFinder.php
@@ -0,0 +1,157 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * This file is part of phpDocumentor.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ *
+ * @link      http://phpdoc.org
+ */
+
+namespace phpDocumentor\Reflection\DocBlock;
+
+use phpDocumentor\Reflection\DocBlock\Tags\Example;
+use function array_slice;
+use function file;
+use function getcwd;
+use function implode;
+use function is_readable;
+use function rtrim;
+use function sprintf;
+use function trim;
+use const DIRECTORY_SEPARATOR;
+
+/**
+ * Class used to find an example file's location based on a given ExampleDescriptor.
+ */
+class ExampleFinder
+{
+    /** @var string */
+    private $sourceDirectory = '';
+
+    /** @var string[] */
+    private $exampleDirectories = [];
+
+    /**
+     * Attempts to find the example contents for the given descriptor.
+     */
+    public function find(Example $example) : string
+    {
+        $filename = $example->getFilePath();
+
+        $file = $this->getExampleFileContents($filename);
+        if (!$file) {
+            return sprintf('** File not found : %s **', $filename);
+        }
+
+        return implode('', array_slice($file, $example->getStartingLine() - 1, $example->getLineCount()));
+    }
+
+    /**
+     * Registers the project's root directory where an 'examples' folder can be expected.
+     */
+    public function setSourceDirectory(string $directory = '') : void
+    {
+        $this->sourceDirectory = $directory;
+    }
+
+    /**
+     * Returns the project's root directory where an 'examples' folder can be expected.
+     */
+    public function getSourceDirectory() : string
+    {
+        return $this->sourceDirectory;
+    }
+
+    /**
+     * Registers a series of directories that may contain examples.
+     *
+     * @param string[] $directories
+     */
+    public function setExampleDirectories(array $directories) : void
+    {
+        $this->exampleDirectories = $directories;
+    }
+
+    /**
+     * Returns a series of directories that may contain examples.
+     *
+     * @return string[]
+     */
+    public function getExampleDirectories() : array
+    {
+        return $this->exampleDirectories;
+    }
+
+    /**
+     * Attempts to find the requested example file and returns its contents or null if no file was found.
+     *
+     * This method will try several methods in search of the given example file, the first one it encounters is
+     * returned:
+     *
+     * 1. Iterates through all examples folders for the given filename
+     * 2. Checks the source folder for the given filename
+     * 3. Checks the 'examples' folder in the current working directory for examples
+     * 4. Checks the path relative to the current working directory for the given filename
+     *
+     * @return string[] all lines of the example file
+     */
+    private function getExampleFileContents(string $filename) : ?array
+    {
+        $normalizedPath = null;
+
+        foreach ($this->exampleDirectories as $directory) {
+            $exampleFileFromConfig = $this->constructExamplePath($directory, $filename);
+            if (is_readable($exampleFileFromConfig)) {
+                $normalizedPath = $exampleFileFromConfig;
+                break;
+            }
+        }
+
+        if (!$normalizedPath) {
+            if (is_readable($this->getExamplePathFromSource($filename))) {
+                $normalizedPath = $this->getExamplePathFromSource($filename);
+            } elseif (is_readable($this->getExamplePathFromExampleDirectory($filename))) {
+                $normalizedPath = $this->getExamplePathFromExampleDirectory($filename);
+            } elseif (is_readable($filename)) {
+                $normalizedPath = $filename;
+            }
+        }
+
+        $lines = $normalizedPath && is_readable($normalizedPath) ? file($normalizedPath) : false;
+
+        return $lines !== false ? $lines : null;
+    }
+
+    /**
+     * Get example filepath based on the example directory inside your project.
+     */
+    private function getExamplePathFromExampleDirectory(string $file) : string
+    {
+        return getcwd() . DIRECTORY_SEPARATOR . 'examples' . DIRECTORY_SEPARATOR . $file;
+    }
+
+    /**
+     * Returns a path to the example file in the given directory..
+     */
+    private function constructExamplePath(string $directory, string $file) : string
+    {
+        return rtrim($directory, '\\/') . DIRECTORY_SEPARATOR . $file;
+    }
+
+    /**
+     * Get example filepath based on sourcecode.
+     */
+    private function getExamplePathFromSource(string $file) : string
+    {
+        return sprintf(
+            '%s%s%s',
+            trim($this->getSourceDirectory(), '\\/'),
+            DIRECTORY_SEPARATOR,
+            trim($file, '"')
+        );
+    }
+}
diff --git a/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Serializer.php b/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Serializer.php
new file mode 100644
index 0000000000000000000000000000000000000000..531970b92f08731b4340a277a7d72d9aa6895be8
--- /dev/null
+++ b/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Serializer.php
@@ -0,0 +1,151 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * This file is part of phpDocumentor.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ *
+ * @link http://phpdoc.org
+ */
+
+namespace phpDocumentor\Reflection\DocBlock;
+
+use phpDocumentor\Reflection\DocBlock;
+use phpDocumentor\Reflection\DocBlock\Tags\Formatter;
+use phpDocumentor\Reflection\DocBlock\Tags\Formatter\PassthroughFormatter;
+use function sprintf;
+use function str_repeat;
+use function str_replace;
+use function strlen;
+use function wordwrap;
+
+/**
+ * Converts a DocBlock back from an object to a complete DocComment including Asterisks.
+ */
+class Serializer
+{
+    /** @var string The string to indent the comment with. */
+    protected $indentString = ' ';
+
+    /** @var int The number of times the indent string is repeated. */
+    protected $indent = 0;
+
+    /** @var bool Whether to indent the first line with the given indent amount and string. */
+    protected $isFirstLineIndented = true;
+
+    /** @var int|null The max length of a line. */
+    protected $lineLength;
+
+    /** @var Formatter A custom tag formatter. */
+    protected $tagFormatter;
+
+    /**
+     * Create a Serializer instance.
+     *
+     * @param int       $indent          The number of times the indent string is repeated.
+     * @param string    $indentString    The string to indent the comment with.
+     * @param bool      $indentFirstLine Whether to indent the first line.
+     * @param int|null  $lineLength      The max length of a line or NULL to disable line wrapping.
+     * @param Formatter $tagFormatter    A custom tag formatter, defaults to PassthroughFormatter.
+     */
+    public function __construct(
+        int $indent = 0,
+        string $indentString = ' ',
+        bool $indentFirstLine = true,
+        ?int $lineLength = null,
+        ?Formatter $tagFormatter = null
+    ) {
+        $this->indent              = $indent;
+        $this->indentString        = $indentString;
+        $this->isFirstLineIndented = $indentFirstLine;
+        $this->lineLength          = $lineLength;
+        $this->tagFormatter        = $tagFormatter ?: new PassthroughFormatter();
+    }
+
+    /**
+     * Generate a DocBlock comment.
+     *
+     * @param DocBlock $docblock The DocBlock to serialize.
+     *
+     * @return string The serialized doc block.
+     */
+    public function getDocComment(DocBlock $docblock) : string
+    {
+        $indent      = str_repeat($this->indentString, $this->indent);
+        $firstIndent = $this->isFirstLineIndented ? $indent : '';
+        // 3 === strlen(' * ')
+        $wrapLength = $this->lineLength ? $this->lineLength - strlen($indent) - 3 : null;
+
+        $text = $this->removeTrailingSpaces(
+            $indent,
+            $this->addAsterisksForEachLine(
+                $indent,
+                $this->getSummaryAndDescriptionTextBlock($docblock, $wrapLength)
+            )
+        );
+
+        $comment = $firstIndent . "/**\n";
+        if ($text) {
+            $comment .= $indent . ' * ' . $text . "\n";
+            $comment .= $indent . " *\n";
+        }
+
+        $comment = $this->addTagBlock($docblock, $wrapLength, $indent, $comment);
+
+        return $comment . $indent . ' */';
+    }
+
+    private function removeTrailingSpaces(string $indent, string $text) : string
+    {
+        return str_replace(
+            sprintf("\n%s * \n", $indent),
+            sprintf("\n%s *\n", $indent),
+            $text
+        );
+    }
+
+    private function addAsterisksForEachLine(string $indent, string $text) : string
+    {
+        return str_replace(
+            "\n",
+            sprintf("\n%s * ", $indent),
+            $text
+        );
+    }
+
+    private function getSummaryAndDescriptionTextBlock(DocBlock $docblock, ?int $wrapLength) : string
+    {
+        $text = $docblock->getSummary() . ((string) $docblock->getDescription() ? "\n\n" . $docblock->getDescription()
+                : '');
+        if ($wrapLength !== null) {
+            $text = wordwrap($text, $wrapLength);
+
+            return $text;
+        }
+
+        return $text;
+    }
+
+    private function addTagBlock(DocBlock $docblock, ?int $wrapLength, string $indent, string $comment) : string
+    {
+        foreach ($docblock->getTags() as $tag) {
+            $tagText = $this->tagFormatter->format($tag);
+            if ($wrapLength !== null) {
+                $tagText = wordwrap($tagText, $wrapLength);
+            }
+
+            $tagText = str_replace(
+                "\n",
+                sprintf("\n%s * ", $indent),
+                $tagText
+            );
+
+            $comment .= sprintf("%s * %s\n", $indent, $tagText);
+        }
+
+        return $comment;
+    }
+}
diff --git a/vendor/phpdocumentor/reflection-docblock/src/DocBlock/StandardTagFactory.php b/vendor/phpdocumentor/reflection-docblock/src/DocBlock/StandardTagFactory.php
new file mode 100644
index 0000000000000000000000000000000000000000..e64b587ef406ef22fcb913f0d40defb8d25df38c
--- /dev/null
+++ b/vendor/phpdocumentor/reflection-docblock/src/DocBlock/StandardTagFactory.php
@@ -0,0 +1,347 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * This file is part of phpDocumentor.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ *
+ * @link http://phpdoc.org
+ */
+
+namespace phpDocumentor\Reflection\DocBlock;
+
+use InvalidArgumentException;
+use phpDocumentor\Reflection\DocBlock\Tags\Author;
+use phpDocumentor\Reflection\DocBlock\Tags\Covers;
+use phpDocumentor\Reflection\DocBlock\Tags\Deprecated;
+use phpDocumentor\Reflection\DocBlock\Tags\Generic;
+use phpDocumentor\Reflection\DocBlock\Tags\InvalidTag;
+use phpDocumentor\Reflection\DocBlock\Tags\Link as LinkTag;
+use phpDocumentor\Reflection\DocBlock\Tags\Method;
+use phpDocumentor\Reflection\DocBlock\Tags\Param;
+use phpDocumentor\Reflection\DocBlock\Tags\Property;
+use phpDocumentor\Reflection\DocBlock\Tags\PropertyRead;
+use phpDocumentor\Reflection\DocBlock\Tags\PropertyWrite;
+use phpDocumentor\Reflection\DocBlock\Tags\Return_;
+use phpDocumentor\Reflection\DocBlock\Tags\See as SeeTag;
+use phpDocumentor\Reflection\DocBlock\Tags\Since;
+use phpDocumentor\Reflection\DocBlock\Tags\Source;
+use phpDocumentor\Reflection\DocBlock\Tags\Throws;
+use phpDocumentor\Reflection\DocBlock\Tags\Uses;
+use phpDocumentor\Reflection\DocBlock\Tags\Var_;
+use phpDocumentor\Reflection\DocBlock\Tags\Version;
+use phpDocumentor\Reflection\FqsenResolver;
+use phpDocumentor\Reflection\Types\Context as TypeContext;
+use ReflectionMethod;
+use ReflectionNamedType;
+use ReflectionParameter;
+use Webmozart\Assert\Assert;
+use function array_merge;
+use function array_slice;
+use function call_user_func_array;
+use function count;
+use function get_class;
+use function preg_match;
+use function strpos;
+use function trim;
+
+/**
+ * Creates a Tag object given the contents of a tag.
+ *
+ * This Factory is capable of determining the appropriate class for a tag and instantiate it using its `create`
+ * factory method. The `create` factory method of a Tag can have a variable number of arguments; this way you can
+ * pass the dependencies that you need to construct a tag object.
+ *
+ * > Important: each parameter in addition to the body variable for the `create` method must default to null, otherwise
+ * > it violates the constraint with the interface; it is recommended to use the {@see Assert::notNull()} method to
+ * > verify that a dependency is actually passed.
+ *
+ * This Factory also features a Service Locator component that is used to pass the right dependencies to the
+ * `create` method of a tag; each dependency should be registered as a service or as a parameter.
+ *
+ * When you want to use a Tag of your own with custom handling you need to call the `registerTagHandler` method, pass
+ * the name of the tag and a Fully Qualified Class Name pointing to a class that implements the Tag interface.
+ */
+final class StandardTagFactory implements TagFactory
+{
+    /** PCRE regular expression matching a tag name. */
+    public const REGEX_TAGNAME = '[\w\-\_\\\\:]+';
+
+    /**
+     * @var array<class-string<Tag>> An array with a tag as a key, and an
+     *                               FQCN to a class that handles it as an array value.
+     */
+    private $tagHandlerMappings = [
+        'author' => Author::class,
+        'covers' => Covers::class,
+        'deprecated' => Deprecated::class,
+        // 'example'        => '\phpDocumentor\Reflection\DocBlock\Tags\Example',
+        'link' => LinkTag::class,
+        'method' => Method::class,
+        'param' => Param::class,
+        'property-read' => PropertyRead::class,
+        'property' => Property::class,
+        'property-write' => PropertyWrite::class,
+        'return' => Return_::class,
+        'see' => SeeTag::class,
+        'since' => Since::class,
+        'source' => Source::class,
+        'throw' => Throws::class,
+        'throws' => Throws::class,
+        'uses' => Uses::class,
+        'var' => Var_::class,
+        'version' => Version::class,
+    ];
+
+    /**
+     * @var array<class-string<Tag>> An array with a anotation s a key, and an
+     *      FQCN to a class that handles it as an array value.
+     */
+    private $annotationMappings = [];
+
+    /**
+     * @var ReflectionParameter[][] a lazy-loading cache containing parameters
+     *      for each tagHandler that has been used.
+     */
+    private $tagHandlerParameterCache = [];
+
+    /** @var FqsenResolver */
+    private $fqsenResolver;
+
+    /**
+     * @var mixed[] an array representing a simple Service Locator where we can store parameters and
+     *     services that can be inserted into the Factory Methods of Tag Handlers.
+     */
+    private $serviceLocator = [];
+
+    /**
+     * Initialize this tag factory with the means to resolve an FQSEN and optionally a list of tag handlers.
+     *
+     * If no tag handlers are provided than the default list in the {@see self::$tagHandlerMappings} property
+     * is used.
+     *
+     * @see self::registerTagHandler() to add a new tag handler to the existing default list.
+     *
+     * @param array<class-string<Tag>> $tagHandlers
+     */
+    public function __construct(FqsenResolver $fqsenResolver, ?array $tagHandlers = null)
+    {
+        $this->fqsenResolver = $fqsenResolver;
+        if ($tagHandlers !== null) {
+            $this->tagHandlerMappings = $tagHandlers;
+        }
+
+        $this->addService($fqsenResolver, FqsenResolver::class);
+    }
+
+    public function create(string $tagLine, ?TypeContext $context = null) : Tag
+    {
+        if (!$context) {
+            $context = new TypeContext('');
+        }
+
+        [$tagName, $tagBody] = $this->extractTagParts($tagLine);
+
+        return $this->createTag(trim($tagBody), $tagName, $context);
+    }
+
+    /**
+     * @param mixed $value
+     */
+    public function addParameter(string $name, $value) : void
+    {
+        $this->serviceLocator[$name] = $value;
+    }
+
+    public function addService(object $service, ?string $alias = null) : void
+    {
+        $this->serviceLocator[$alias ?: get_class($service)] = $service;
+    }
+
+    public function registerTagHandler(string $tagName, string $handler) : void
+    {
+        Assert::stringNotEmpty($tagName);
+        Assert::classExists($handler);
+        Assert::implementsInterface($handler, Tag::class);
+
+        if (strpos($tagName, '\\') && $tagName[0] !== '\\') {
+            throw new InvalidArgumentException(
+                'A namespaced tag must have a leading backslash as it must be fully qualified'
+            );
+        }
+
+        $this->tagHandlerMappings[$tagName] = $handler;
+    }
+
+    /**
+     * Extracts all components for a tag.
+     *
+     * @return string[]
+     */
+    private function extractTagParts(string $tagLine) : array
+    {
+        $matches = [];
+        if (!preg_match('/^@(' . self::REGEX_TAGNAME . ')((?:[\s\(\{])\s*([^\s].*)|$)/us', $tagLine, $matches)) {
+            throw new InvalidArgumentException(
+                'The tag "' . $tagLine . '" does not seem to be wellformed, please check it for errors'
+            );
+        }
+
+        if (count($matches) < 3) {
+            $matches[] = '';
+        }
+
+        return array_slice($matches, 1);
+    }
+
+    /**
+     * Creates a new tag object with the given name and body or returns null if the tag name was recognized but the
+     * body was invalid.
+     */
+    private function createTag(string $body, string $name, TypeContext $context) : Tag
+    {
+        $handlerClassName = $this->findHandlerClassName($name, $context);
+        $arguments        = $this->getArgumentsForParametersFromWiring(
+            $this->fetchParametersForHandlerFactoryMethod($handlerClassName),
+            $this->getServiceLocatorWithDynamicParameters($context, $name, $body)
+        );
+
+        try {
+            $callable = [$handlerClassName, 'create'];
+            Assert::isCallable($callable);
+            /** @phpstan-var callable(string): ?Tag $callable */
+            $tag = call_user_func_array($callable, $arguments);
+
+            return $tag ?? InvalidTag::create($body, $name);
+        } catch (InvalidArgumentException $e) {
+            return InvalidTag::create($body, $name)->withError($e);
+        }
+    }
+
+    /**
+     * Determines the Fully Qualified Class Name of the Factory or Tag (containing a Factory Method `create`).
+     *
+     * @return class-string<Tag>
+     */
+    private function findHandlerClassName(string $tagName, TypeContext $context) : string
+    {
+        $handlerClassName = Generic::class;
+        if (isset($this->tagHandlerMappings[$tagName])) {
+            $handlerClassName = $this->tagHandlerMappings[$tagName];
+        } elseif ($this->isAnnotation($tagName)) {
+            // TODO: Annotation support is planned for a later stage and as such is disabled for now
+            $tagName = (string) $this->fqsenResolver->resolve($tagName, $context);
+            if (isset($this->annotationMappings[$tagName])) {
+                $handlerClassName = $this->annotationMappings[$tagName];
+            }
+        }
+
+        return $handlerClassName;
+    }
+
+    /**
+     * Retrieves the arguments that need to be passed to the Factory Method with the given Parameters.
+     *
+     * @param ReflectionParameter[] $parameters
+     * @param mixed[]               $locator
+     *
+     * @return mixed[] A series of values that can be passed to the Factory Method of the tag whose parameters
+     *     is provided with this method.
+     */
+    private function getArgumentsForParametersFromWiring(array $parameters, array $locator) : array
+    {
+        $arguments = [];
+        foreach ($parameters as $parameter) {
+            $type     = $parameter->getType();
+            $typeHint = null;
+            if ($type instanceof ReflectionNamedType) {
+                $typeHint = $type->getName();
+                if ($typeHint === 'self') {
+                    $declaringClass = $parameter->getDeclaringClass();
+                    if ($declaringClass !== null) {
+                        $typeHint = $declaringClass->getName();
+                    }
+                }
+            }
+
+            if (isset($locator[$typeHint])) {
+                $arguments[] = $locator[$typeHint];
+                continue;
+            }
+
+            $parameterName = $parameter->getName();
+            if (isset($locator[$parameterName])) {
+                $arguments[] = $locator[$parameterName];
+                continue;
+            }
+
+            $arguments[] = null;
+        }
+
+        return $arguments;
+    }
+
+    /**
+     * Retrieves a series of ReflectionParameter objects for the static 'create' method of the given
+     * tag handler class name.
+     *
+     * @param class-string $handlerClassName
+     *
+     * @return ReflectionParameter[]
+     */
+    private function fetchParametersForHandlerFactoryMethod(string $handlerClassName) : array
+    {
+        if (!isset($this->tagHandlerParameterCache[$handlerClassName])) {
+            $methodReflection                                  = new ReflectionMethod($handlerClassName, 'create');
+            $this->tagHandlerParameterCache[$handlerClassName] = $methodReflection->getParameters();
+        }
+
+        return $this->tagHandlerParameterCache[$handlerClassName];
+    }
+
+    /**
+     * Returns a copy of this class' Service Locator with added dynamic parameters,
+     * such as the tag's name, body and Context.
+     *
+     * @param TypeContext $context The Context (namespace and aliasses) that may be
+     *  passed and is used to resolve FQSENs.
+     * @param string      $tagName The name of the tag that may be
+     *  passed onto the factory method of the Tag class.
+     * @param string      $tagBody The body of the tag that may be
+     *  passed onto the factory method of the Tag class.
+     *
+     * @return mixed[]
+     */
+    private function getServiceLocatorWithDynamicParameters(
+        TypeContext $context,
+        string $tagName,
+        string $tagBody
+    ) : array {
+        return array_merge(
+            $this->serviceLocator,
+            [
+                'name' => $tagName,
+                'body' => $tagBody,
+                TypeContext::class => $context,
+            ]
+        );
+    }
+
+    /**
+     * Returns whether the given tag belongs to an annotation.
+     *
+     * @todo this method should be populated once we implement Annotation notation support.
+     */
+    private function isAnnotation(string $tagContent) : bool
+    {
+        // 1. Contains a namespace separator
+        // 2. Contains parenthesis
+        // 3. Is present in a list of known annotations (make the algorithm smart by first checking is the last part
+        //    of the annotation class name matches the found tag name
+
+        return false;
+    }
+}
diff --git a/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tag.php b/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tag.php
new file mode 100644
index 0000000000000000000000000000000000000000..f55de91695be84ce53d93b912477fd6d75aa2d2d
--- /dev/null
+++ b/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tag.php
@@ -0,0 +1,32 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * This file is part of phpDocumentor.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ *
+ * @link      http://phpdoc.org
+ */
+
+namespace phpDocumentor\Reflection\DocBlock;
+
+use phpDocumentor\Reflection\DocBlock\Tags\Formatter;
+
+interface Tag
+{
+    public function getName() : string;
+
+    /**
+     * @return Tag|mixed Class that implements Tag
+     *
+     * @phpstan-return ?Tag
+     */
+    public static function create(string $body);
+
+    public function render(?Formatter $formatter = null) : string;
+
+    public function __toString() : string;
+}
diff --git a/vendor/phpdocumentor/reflection-docblock/src/DocBlock/TagFactory.php b/vendor/phpdocumentor/reflection-docblock/src/DocBlock/TagFactory.php
new file mode 100644
index 0000000000000000000000000000000000000000..0d318d1bebd55b39b5967bcaa5c8dd8039c68cd4
--- /dev/null
+++ b/vendor/phpdocumentor/reflection-docblock/src/DocBlock/TagFactory.php
@@ -0,0 +1,84 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * This file is part of phpDocumentor.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ *
+ * @link http://phpdoc.org
+ */
+
+namespace phpDocumentor\Reflection\DocBlock;
+
+use InvalidArgumentException;
+use phpDocumentor\Reflection\Types\Context as TypeContext;
+
+interface TagFactory
+{
+    /**
+     * Adds a parameter to the service locator that can be injected in a tag's factory method.
+     *
+     * When calling a tag's "create" method we always check the signature for dependencies to inject. One way is to
+     * typehint a parameter in the signature so that we can use that interface or class name to inject a dependency
+     * (see {@see addService()} for more information on that).
+     *
+     * Another way is to check the name of the argument against the names in the Service Locator. With this method
+     * you can add a variable that will be inserted when a tag's create method is not typehinted and has a matching
+     * name.
+     *
+     * Be aware that there are two reserved names:
+     *
+     * - name, representing the name of the tag.
+     * - body, representing the complete body of the tag.
+     *
+     * These parameters are injected at the last moment and will override any existing parameter with those names.
+     *
+     * @param mixed $value
+     */
+    public function addParameter(string $name, $value) : void;
+
+    /**
+     * Factory method responsible for instantiating the correct sub type.
+     *
+     * @param string $tagLine The text for this tag, including description.
+     *
+     * @return Tag A new tag object.
+     *
+     * @throws InvalidArgumentException If an invalid tag line was presented.
+     */
+    public function create(string $tagLine, ?TypeContext $context = null) : Tag;
+
+    /**
+     * Registers a service with the Service Locator using the FQCN of the class or the alias, if provided.
+     *
+     * When calling a tag's "create" method we always check the signature for dependencies to inject. If a parameter
+     * has a typehint then the ServiceLocator is queried to see if a Service is registered for that typehint.
+     *
+     * Because interfaces are regularly used as type-hints this method provides an alias parameter; if the FQCN of the
+     * interface is passed as alias then every time that interface is requested the provided service will be returned.
+     */
+    public function addService(object $service) : void;
+
+    /**
+     * Registers a handler for tags.
+     *
+     * If you want to use your own tags then you can use this method to instruct the TagFactory
+     * to register the name of a tag with the FQCN of a 'Tag Handler'. The Tag handler should implement
+     * the {@see Tag} interface (and thus the create method).
+     *
+     * @param string                    $tagName Name of tag to register a handler for. When registering a namespaced
+     *                                   tag, the full name, along with a prefixing slash MUST be provided.
+     * @param class-string<Tag>         $handler FQCN of handler.
+     *
+     * @throws InvalidArgumentException If the tag name is not a string.
+     * @throws InvalidArgumentException If the tag name is namespaced (contains backslashes) but
+     *                                   does not start with a backslash.
+     * @throws InvalidArgumentException If the handler is not a string.
+     * @throws InvalidArgumentException If the handler is not an existing class.
+     * @throws InvalidArgumentException If the handler does not implement the {@see Tag} interface.
+     */
+    public function registerTagHandler(string $tagName, string $handler) : void;
+}
diff --git a/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Author.php b/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Author.php
new file mode 100644
index 0000000000000000000000000000000000000000..d1207571dafbc1e5ad3b77cd74bdd67e65eddd24
--- /dev/null
+++ b/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Author.php
@@ -0,0 +1,100 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * This file is part of phpDocumentor.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ *
+ * @link http://phpdoc.org
+ */
+
+namespace phpDocumentor\Reflection\DocBlock\Tags;
+
+use InvalidArgumentException;
+use function filter_var;
+use function preg_match;
+use function trim;
+use const FILTER_VALIDATE_EMAIL;
+
+/**
+ * Reflection class for an {@}author tag in a Docblock.
+ */
+final class Author extends BaseTag implements Factory\StaticMethod
+{
+    /** @var string register that this is the author tag. */
+    protected $name = 'author';
+
+    /** @var string The name of the author */
+    private $authorName;
+
+    /** @var string The email of the author */
+    private $authorEmail;
+
+    /**
+     * Initializes this tag with the author name and e-mail.
+     */
+    public function __construct(string $authorName, string $authorEmail)
+    {
+        if ($authorEmail && !filter_var($authorEmail, FILTER_VALIDATE_EMAIL)) {
+            throw new InvalidArgumentException('The author tag does not have a valid e-mail address');
+        }
+
+        $this->authorName  = $authorName;
+        $this->authorEmail = $authorEmail;
+    }
+
+    /**
+     * Gets the author's name.
+     *
+     * @return string The author's name.
+     */
+    public function getAuthorName() : string
+    {
+        return $this->authorName;
+    }
+
+    /**
+     * Returns the author's email.
+     *
+     * @return string The author's email.
+     */
+    public function getEmail() : string
+    {
+        return $this->authorEmail;
+    }
+
+    /**
+     * Returns this tag in string form.
+     */
+    public function __toString() : string
+    {
+        if ($this->authorEmail) {
+            $authorEmail = '<' . $this->authorEmail . '>';
+        } else {
+            $authorEmail = '';
+        }
+
+        $authorName = (string) $this->authorName;
+
+        return $authorName . ($authorEmail !== '' ? ($authorName !== '' ? ' ' : '') . $authorEmail : '');
+    }
+
+    /**
+     * Attempts to create a new Author object based on †he tag body.
+     */
+    public static function create(string $body) : ?self
+    {
+        $splitTagContent = preg_match('/^([^\<]*)(?:\<([^\>]*)\>)?$/u', $body, $matches);
+        if (!$splitTagContent) {
+            return null;
+        }
+
+        $authorName = trim($matches[1]);
+        $email      = isset($matches[2]) ? trim($matches[2]) : '';
+
+        return new static($authorName, $email);
+    }
+}
diff --git a/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/BaseTag.php b/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/BaseTag.php
new file mode 100644
index 0000000000000000000000000000000000000000..fbcd4022fcb23181684ff3aa70fd3e4bdfb40bd4
--- /dev/null
+++ b/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/BaseTag.php
@@ -0,0 +1,53 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * This file is part of phpDocumentor.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ *
+ * @link http://phpdoc.org
+ */
+
+namespace phpDocumentor\Reflection\DocBlock\Tags;
+
+use phpDocumentor\Reflection\DocBlock;
+use phpDocumentor\Reflection\DocBlock\Description;
+
+/**
+ * Parses a tag definition for a DocBlock.
+ */
+abstract class BaseTag implements DocBlock\Tag
+{
+    /** @var string Name of the tag */
+    protected $name = '';
+
+    /** @var Description|null Description of the tag. */
+    protected $description;
+
+    /**
+     * Gets the name of this tag.
+     *
+     * @return string The name of this tag.
+     */
+    public function getName() : string
+    {
+        return $this->name;
+    }
+
+    public function getDescription() : ?Description
+    {
+        return $this->description;
+    }
+
+    public function render(?Formatter $formatter = null) : string
+    {
+        if ($formatter === null) {
+            $formatter = new Formatter\PassthroughFormatter();
+        }
+
+        return $formatter->format($this);
+    }
+}
diff --git a/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Covers.php b/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Covers.php
new file mode 100644
index 0000000000000000000000000000000000000000..9e52e5e4ca0107c0d5afac75ccb4d7950589be58
--- /dev/null
+++ b/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Covers.php
@@ -0,0 +1,100 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * This file is part of phpDocumentor.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ *
+ * @link http://phpdoc.org
+ */
+
+namespace phpDocumentor\Reflection\DocBlock\Tags;
+
+use phpDocumentor\Reflection\DocBlock\Description;
+use phpDocumentor\Reflection\DocBlock\DescriptionFactory;
+use phpDocumentor\Reflection\Fqsen;
+use phpDocumentor\Reflection\FqsenResolver;
+use phpDocumentor\Reflection\Types\Context as TypeContext;
+use phpDocumentor\Reflection\Utils;
+use Webmozart\Assert\Assert;
+use function array_key_exists;
+use function explode;
+
+/**
+ * Reflection class for a @covers tag in a Docblock.
+ */
+final class Covers extends BaseTag implements Factory\StaticMethod
+{
+    /** @var string */
+    protected $name = 'covers';
+
+    /** @var Fqsen */
+    private $refers;
+
+    /**
+     * Initializes this tag.
+     */
+    public function __construct(Fqsen $refers, ?Description $description = null)
+    {
+        $this->refers      = $refers;
+        $this->description = $description;
+    }
+
+    public static function create(
+        string $body,
+        ?DescriptionFactory $descriptionFactory = null,
+        ?FqsenResolver $resolver = null,
+        ?TypeContext $context = null
+    ) : self {
+        Assert::stringNotEmpty($body);
+        Assert::notNull($descriptionFactory);
+        Assert::notNull($resolver);
+
+        $parts = Utils::pregSplit('/\s+/Su', $body, 2);
+
+        return new static(
+            self::resolveFqsen($parts[0], $resolver, $context),
+            $descriptionFactory->create($parts[1] ?? '', $context)
+        );
+    }
+
+    private static function resolveFqsen(string $parts, ?FqsenResolver $fqsenResolver, ?TypeContext $context) : Fqsen
+    {
+        Assert::notNull($fqsenResolver);
+        $fqsenParts = explode('::', $parts);
+        $resolved = $fqsenResolver->resolve($fqsenParts[0], $context);
+
+        if (!array_key_exists(1, $fqsenParts)) {
+            return $resolved;
+        }
+
+        return new Fqsen($resolved . '::' . $fqsenParts[1]);
+    }
+
+    /**
+     * Returns the structural element this tag refers to.
+     */
+    public function getReference() : Fqsen
+    {
+        return $this->refers;
+    }
+
+    /**
+     * Returns a string representation of this tag.
+     */
+    public function __toString() : string
+    {
+        if ($this->description) {
+            $description = $this->description->render();
+        } else {
+            $description = '';
+        }
+
+        $refers = (string) $this->refers;
+
+        return $refers . ($description !== '' ? ($refers !== '' ? ' ' : '') . $description : '');
+    }
+}
diff --git a/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Deprecated.php b/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Deprecated.php
new file mode 100644
index 0000000000000000000000000000000000000000..68e8f03639e402efc90211ece5dd4821e23d8ef7
--- /dev/null
+++ b/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Deprecated.php
@@ -0,0 +1,108 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * This file is part of phpDocumentor.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ *
+ * @link      http://phpdoc.org
+ */
+
+namespace phpDocumentor\Reflection\DocBlock\Tags;
+
+use phpDocumentor\Reflection\DocBlock\Description;
+use phpDocumentor\Reflection\DocBlock\DescriptionFactory;
+use phpDocumentor\Reflection\Types\Context as TypeContext;
+use Webmozart\Assert\Assert;
+use function preg_match;
+
+/**
+ * Reflection class for a {@}deprecated tag in a Docblock.
+ */
+final class Deprecated extends BaseTag implements Factory\StaticMethod
+{
+    /** @var string */
+    protected $name = 'deprecated';
+
+    /**
+     * PCRE regular expression matching a version vector.
+     * Assumes the "x" modifier.
+     */
+    public const REGEX_VECTOR = '(?:
+        # Normal release vectors.
+        \d\S*
+        |
+        # VCS version vectors. Per PHPCS, they are expected to
+        # follow the form of the VCS name, followed by ":", followed
+        # by the version vector itself.
+        # By convention, popular VCSes like CVS, SVN and GIT use "$"
+        # around the actual version vector.
+        [^\s\:]+\:\s*\$[^\$]+\$
+    )';
+
+    /** @var string|null The version vector. */
+    private $version;
+
+    public function __construct(?string $version = null, ?Description $description = null)
+    {
+        Assert::nullOrNotEmpty($version);
+
+        $this->version     = $version;
+        $this->description = $description;
+    }
+
+    /**
+     * @return static
+     */
+    public static function create(
+        ?string $body,
+        ?DescriptionFactory $descriptionFactory = null,
+        ?TypeContext $context = null
+    ) : self {
+        if (empty($body)) {
+            return new static();
+        }
+
+        $matches = [];
+        if (!preg_match('/^(' . self::REGEX_VECTOR . ')\s*(.+)?$/sux', $body, $matches)) {
+            return new static(
+                null,
+                $descriptionFactory !== null ? $descriptionFactory->create($body, $context) : null
+            );
+        }
+
+        Assert::notNull($descriptionFactory);
+
+        return new static(
+            $matches[1],
+            $descriptionFactory->create($matches[2] ?? '', $context)
+        );
+    }
+
+    /**
+     * Gets the version section of the tag.
+     */
+    public function getVersion() : ?string
+    {
+        return $this->version;
+    }
+
+    /**
+     * Returns a string representation for this tag.
+     */
+    public function __toString() : string
+    {
+        if ($this->description) {
+            $description = $this->description->render();
+        } else {
+            $description = '';
+        }
+
+        $version = (string) $this->version;
+
+        return $version . ($description !== '' ? ($version !== '' ? ' ' : '') . $description : '');
+    }
+}
diff --git a/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Example.php b/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Example.php
new file mode 100644
index 0000000000000000000000000000000000000000..3face1efa620753b0b02213c136654bd78b43f61
--- /dev/null
+++ b/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Example.php
@@ -0,0 +1,199 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * This file is part of phpDocumentor.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ *
+ * @link      http://phpdoc.org
+ */
+
+namespace phpDocumentor\Reflection\DocBlock\Tags;
+
+use phpDocumentor\Reflection\DocBlock\Tag;
+use Webmozart\Assert\Assert;
+use function array_key_exists;
+use function preg_match;
+use function rawurlencode;
+use function str_replace;
+use function strpos;
+use function trim;
+
+/**
+ * Reflection class for a {@}example tag in a Docblock.
+ */
+final class Example implements Tag, Factory\StaticMethod
+{
+    /** @var string Path to a file to use as an example. May also be an absolute URI. */
+    private $filePath;
+
+    /**
+     * @var bool Whether the file path component represents an URI. This determines how the file portion
+     *     appears at {@link getContent()}.
+     */
+    private $isURI;
+
+    /** @var int */
+    private $startingLine;
+
+    /** @var int */
+    private $lineCount;
+
+    /** @var string|null */
+    private $content;
+
+    public function __construct(
+        string $filePath,
+        bool $isURI,
+        int $startingLine,
+        int $lineCount,
+        ?string $content
+    ) {
+        Assert::stringNotEmpty($filePath);
+        Assert::greaterThanEq($startingLine, 1);
+        Assert::greaterThanEq($lineCount, 0);
+
+        $this->filePath     = $filePath;
+        $this->startingLine = $startingLine;
+        $this->lineCount    = $lineCount;
+        if ($content !== null) {
+            $this->content = trim($content);
+        }
+
+        $this->isURI = $isURI;
+    }
+
+    public function getContent() : string
+    {
+        if ($this->content === null || $this->content === '') {
+            $filePath = $this->filePath;
+            if ($this->isURI) {
+                $filePath = $this->isUriRelative($this->filePath)
+                    ? str_replace('%2F', '/', rawurlencode($this->filePath))
+                    : $this->filePath;
+            }
+
+            return trim($filePath);
+        }
+
+        return $this->content;
+    }
+
+    public function getDescription() : ?string
+    {
+        return $this->content;
+    }
+
+    public static function create(string $body) : ?Tag
+    {
+        // File component: File path in quotes or File URI / Source information
+        if (!preg_match('/^\s*(?:(\"[^\"]+\")|(\S+))(?:\s+(.*))?$/sux', $body, $matches)) {
+            return null;
+        }
+
+        $filePath = null;
+        $fileUri  = null;
+        if ($matches[1] !== '') {
+            $filePath = $matches[1];
+        } else {
+            $fileUri = $matches[2];
+        }
+
+        $startingLine = 1;
+        $lineCount    = 0;
+        $description  = null;
+
+        if (array_key_exists(3, $matches)) {
+            $description = $matches[3];
+
+            // Starting line / Number of lines / Description
+            if (preg_match('/^([1-9]\d*)(?:\s+((?1))\s*)?(.*)$/sux', $matches[3], $contentMatches)) {
+                $startingLine = (int) $contentMatches[1];
+                if (isset($contentMatches[2])) {
+                    $lineCount = (int) $contentMatches[2];
+                }
+
+                if (array_key_exists(3, $contentMatches)) {
+                    $description = $contentMatches[3];
+                }
+            }
+        }
+
+        return new static(
+            $filePath ?? ($fileUri ?? ''),
+            $fileUri !== null,
+            $startingLine,
+            $lineCount,
+            $description
+        );
+    }
+
+    /**
+     * Returns the file path.
+     *
+     * @return string Path to a file to use as an example.
+     *     May also be an absolute URI.
+     */
+    public function getFilePath() : string
+    {
+        return trim($this->filePath, '"');
+    }
+
+    /**
+     * Returns a string representation for this tag.
+     */
+    public function __toString() : string
+    {
+        $filePath = (string) $this->filePath;
+        $isDefaultLine = $this->startingLine === 1 && $this->lineCount === 0;
+        $startingLine = !$isDefaultLine ? (string) $this->startingLine : '';
+        $lineCount = !$isDefaultLine ? (string) $this->lineCount : '';
+        $content = (string) $this->content;
+
+        return $filePath
+            . ($startingLine !== ''
+                ? ($filePath !== '' ? ' ' : '') . $startingLine
+                : '')
+            . ($lineCount !== ''
+                ? ($filePath !== '' || $startingLine !== '' ? ' ' : '') . $lineCount
+                : '')
+            . ($content !== ''
+                ? ($filePath !== '' || $startingLine !== '' || $lineCount !== '' ? ' ' : '') . $content
+                : '');
+    }
+
+    /**
+     * Returns true if the provided URI is relative or contains a complete scheme (and thus is absolute).
+     */
+    private function isUriRelative(string $uri) : bool
+    {
+        return strpos($uri, ':') === false;
+    }
+
+    public function getStartingLine() : int
+    {
+        return $this->startingLine;
+    }
+
+    public function getLineCount() : int
+    {
+        return $this->lineCount;
+    }
+
+    public function getName() : string
+    {
+        return 'example';
+    }
+
+    public function render(?Formatter $formatter = null) : string
+    {
+        if ($formatter === null) {
+            $formatter = new Formatter\PassthroughFormatter();
+        }
+
+        return $formatter->format($this);
+    }
+}
diff --git a/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/StaticMethod.php b/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/StaticMethod.php
new file mode 100644
index 0000000000000000000000000000000000000000..f6f0bb5a4b1cd16cdd526e6d4799fe296460a428
--- /dev/null
+++ b/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/StaticMethod.php
@@ -0,0 +1,25 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * This file is part of phpDocumentor.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ *
+ * @link      http://phpdoc.org
+ */
+
+namespace phpDocumentor\Reflection\DocBlock\Tags\Factory;
+
+/**
+ * @deprecated This contract is totally covered by Tag contract. Every class using StaticMethod also use Tag
+ */
+interface StaticMethod
+{
+    /**
+     * @return mixed
+     */
+    public static function create(string $body);
+}
diff --git a/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Formatter.php b/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Formatter.php
new file mode 100644
index 0000000000000000000000000000000000000000..92fb9e6c4118020bd43817f65af6d9204b8c3ad0
--- /dev/null
+++ b/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Formatter.php
@@ -0,0 +1,24 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * This file is part of phpDocumentor.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ *
+ * @link      http://phpdoc.org
+ */
+
+namespace phpDocumentor\Reflection\DocBlock\Tags;
+
+use phpDocumentor\Reflection\DocBlock\Tag;
+
+interface Formatter
+{
+    /**
+     * Formats a tag into a string representation according to a specific format, such as Markdown.
+     */
+    public function format(Tag $tag) : string;
+}
diff --git a/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Formatter/AlignFormatter.php b/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Formatter/AlignFormatter.php
new file mode 100644
index 0000000000000000000000000000000000000000..b1a406c0f095902fbd7ac37b45961f59f10d54d2
--- /dev/null
+++ b/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Formatter/AlignFormatter.php
@@ -0,0 +1,49 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * This file is part of phpDocumentor.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ *
+ * @link      http://phpdoc.org
+ */
+
+namespace phpDocumentor\Reflection\DocBlock\Tags\Formatter;
+
+use phpDocumentor\Reflection\DocBlock\Tag;
+use phpDocumentor\Reflection\DocBlock\Tags\Formatter;
+use function max;
+use function str_repeat;
+use function strlen;
+
+class AlignFormatter implements Formatter
+{
+    /** @var int The maximum tag name length. */
+    protected $maxLen = 0;
+
+    /**
+     * @param Tag[] $tags All tags that should later be aligned with the formatter.
+     */
+    public function __construct(array $tags)
+    {
+        foreach ($tags as $tag) {
+            $this->maxLen = max($this->maxLen, strlen($tag->getName()));
+        }
+    }
+
+    /**
+     * Formats the given tag to return a simple plain text version.
+     */
+    public function format(Tag $tag) : string
+    {
+        return '@' . $tag->getName() .
+            str_repeat(
+                ' ',
+                $this->maxLen - strlen($tag->getName()) + 1
+            ) .
+            $tag;
+    }
+}
diff --git a/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Formatter/PassthroughFormatter.php b/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Formatter/PassthroughFormatter.php
new file mode 100644
index 0000000000000000000000000000000000000000..f26d22fb685a7035f6c820a90c6b628f5b95cb48
--- /dev/null
+++ b/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Formatter/PassthroughFormatter.php
@@ -0,0 +1,29 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * This file is part of phpDocumentor.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ *
+ * @link      http://phpdoc.org
+ */
+
+namespace phpDocumentor\Reflection\DocBlock\Tags\Formatter;
+
+use phpDocumentor\Reflection\DocBlock\Tag;
+use phpDocumentor\Reflection\DocBlock\Tags\Formatter;
+use function trim;
+
+class PassthroughFormatter implements Formatter
+{
+    /**
+     * Formats the given tag to return a simple plain text version.
+     */
+    public function format(Tag $tag) : string
+    {
+        return trim('@' . $tag->getName() . ' ' . $tag);
+    }
+}
diff --git a/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Generic.php b/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Generic.php
new file mode 100644
index 0000000000000000000000000000000000000000..a7b423f5f7250b0084f3378701ef19aacb517b0b
--- /dev/null
+++ b/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Generic.php
@@ -0,0 +1,88 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * This file is part of phpDocumentor.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ *
+ * @link      http://phpdoc.org
+ */
+
+namespace phpDocumentor\Reflection\DocBlock\Tags;
+
+use InvalidArgumentException;
+use phpDocumentor\Reflection\DocBlock\Description;
+use phpDocumentor\Reflection\DocBlock\DescriptionFactory;
+use phpDocumentor\Reflection\DocBlock\StandardTagFactory;
+use phpDocumentor\Reflection\Types\Context as TypeContext;
+use Webmozart\Assert\Assert;
+use function preg_match;
+
+/**
+ * Parses a tag definition for a DocBlock.
+ */
+final class Generic extends BaseTag implements Factory\StaticMethod
+{
+    /**
+     * Parses a tag and populates the member variables.
+     *
+     * @param string      $name        Name of the tag.
+     * @param Description $description The contents of the given tag.
+     */
+    public function __construct(string $name, ?Description $description = null)
+    {
+        $this->validateTagName($name);
+
+        $this->name        = $name;
+        $this->description = $description;
+    }
+
+    /**
+     * Creates a new tag that represents any unknown tag type.
+     *
+     * @return static
+     */
+    public static function create(
+        string $body,
+        string $name = '',
+        ?DescriptionFactory $descriptionFactory = null,
+        ?TypeContext $context = null
+    ) : self {
+        Assert::stringNotEmpty($name);
+        Assert::notNull($descriptionFactory);
+
+        $description = $body !== '' ? $descriptionFactory->create($body, $context) : null;
+
+        return new static($name, $description);
+    }
+
+    /**
+     * Returns the tag as a serialized string
+     */
+    public function __toString() : string
+    {
+        if ($this->description) {
+            $description = $this->description->render();
+        } else {
+            $description = '';
+        }
+
+        return $description;
+    }
+
+    /**
+     * Validates if the tag name matches the expected format, otherwise throws an exception.
+     */
+    private function validateTagName(string $name) : void
+    {
+        if (!preg_match('/^' . StandardTagFactory::REGEX_TAGNAME . '$/u', $name)) {
+            throw new InvalidArgumentException(
+                'The tag name "' . $name . '" is not wellformed. Tags may only consist of letters, underscores, '
+                . 'hyphens and backslashes.'
+            );
+        }
+    }
+}
diff --git a/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/InvalidTag.php b/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/InvalidTag.php
new file mode 100644
index 0000000000000000000000000000000000000000..e3deb5a8d01e90784836bb5fe512bb7936fb6673
--- /dev/null
+++ b/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/InvalidTag.php
@@ -0,0 +1,144 @@
+<?php
+
+declare(strict_types=1);
+
+namespace phpDocumentor\Reflection\DocBlock\Tags;
+
+use Closure;
+use Exception;
+use phpDocumentor\Reflection\DocBlock\Tag;
+use ReflectionClass;
+use ReflectionException;
+use ReflectionFunction;
+use Throwable;
+use function array_map;
+use function get_class;
+use function get_resource_type;
+use function is_array;
+use function is_object;
+use function is_resource;
+use function sprintf;
+
+/**
+ * This class represents an exception during the tag creation
+ *
+ * Since the internals of the library are relaying on the correct syntax of a docblock
+ * we cannot simply throw exceptions at all time because the exceptions will break the creation of a
+ * docklock. Just silently ignore the exceptions is not an option because the user as an issue to fix.
+ *
+ * This tag holds that error information until a using application is able to display it. The object wil just behave
+ * like any normal tag. So the normal application flow will not break.
+ */
+final class InvalidTag implements Tag
+{
+    /** @var string */
+    private $name;
+
+    /** @var string */
+    private $body;
+
+    /** @var Throwable|null */
+    private $throwable;
+
+    private function __construct(string $name, string $body)
+    {
+        $this->name = $name;
+        $this->body = $body;
+    }
+
+    public function getException() : ?Throwable
+    {
+        return $this->throwable;
+    }
+
+    public function getName() : string
+    {
+        return $this->name;
+    }
+
+    public static function create(string $body, string $name = '') : self
+    {
+        return new self($name, $body);
+    }
+
+    public function withError(Throwable $exception) : self
+    {
+        $this->flattenExceptionBacktrace($exception);
+        $tag            = new self($this->name, $this->body);
+        $tag->throwable = $exception;
+
+        return $tag;
+    }
+
+    /**
+     * Removes all complex types from backtrace
+     *
+     * Not all objects are serializable. So we need to remove them from the
+     * stored exception to be sure that we do not break existing library usage.
+     */
+    private function flattenExceptionBacktrace(Throwable $exception) : void
+    {
+        $traceProperty = (new ReflectionClass(Exception::class))->getProperty('trace');
+        $traceProperty->setAccessible(true);
+
+        do {
+            $trace = $exception->getTrace();
+            if (isset($trace[0]['args'])) {
+                $trace = array_map(
+                    function (array $call) : array {
+                        $call['args'] = array_map([$this, 'flattenArguments'], $call['args']);
+
+                        return $call;
+                    },
+                    $trace
+                );
+            }
+
+            $traceProperty->setValue($exception, $trace);
+            $exception = $exception->getPrevious();
+        } while ($exception !== null);
+
+        $traceProperty->setAccessible(false);
+    }
+
+    /**
+     * @param mixed $value
+     *
+     * @return mixed
+     *
+     * @throws ReflectionException
+     */
+    private function flattenArguments($value)
+    {
+        if ($value instanceof Closure) {
+            $closureReflection = new ReflectionFunction($value);
+            $value             = sprintf(
+                '(Closure at %s:%s)',
+                $closureReflection->getFileName(),
+                $closureReflection->getStartLine()
+            );
+        } elseif (is_object($value)) {
+            $value = sprintf('object(%s)', get_class($value));
+        } elseif (is_resource($value)) {
+            $value = sprintf('resource(%s)', get_resource_type($value));
+        } elseif (is_array($value)) {
+            $value = array_map([$this, 'flattenArguments'], $value);
+        }
+
+        return $value;
+    }
+
+    public function render(?Formatter $formatter = null) : string
+    {
+        if ($formatter === null) {
+            $formatter = new Formatter\PassthroughFormatter();
+        }
+
+        return $formatter->format($this);
+    }
+
+    public function __toString() : string
+    {
+        return $this->body;
+    }
+}
diff --git a/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Link.php b/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Link.php
new file mode 100644
index 0000000000000000000000000000000000000000..226bbe0f9eb4591f883b60874c4dd2ad7a57328f
--- /dev/null
+++ b/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Link.php
@@ -0,0 +1,78 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * This file is part of phpDocumentor.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ *
+ * @link http://phpdoc.org
+ */
+
+namespace phpDocumentor\Reflection\DocBlock\Tags;
+
+use phpDocumentor\Reflection\DocBlock\Description;
+use phpDocumentor\Reflection\DocBlock\DescriptionFactory;
+use phpDocumentor\Reflection\Types\Context as TypeContext;
+use phpDocumentor\Reflection\Utils;
+use Webmozart\Assert\Assert;
+
+/**
+ * Reflection class for a {@}link tag in a Docblock.
+ */
+final class Link extends BaseTag implements Factory\StaticMethod
+{
+    /** @var string */
+    protected $name = 'link';
+
+    /** @var string */
+    private $link;
+
+    /**
+     * Initializes a link to a URL.
+     */
+    public function __construct(string $link, ?Description $description = null)
+    {
+        $this->link        = $link;
+        $this->description = $description;
+    }
+
+    public static function create(
+        string $body,
+        ?DescriptionFactory $descriptionFactory = null,
+        ?TypeContext $context = null
+    ) : self {
+        Assert::notNull($descriptionFactory);
+
+        $parts = Utils::pregSplit('/\s+/Su', $body, 2);
+        $description = isset($parts[1]) ? $descriptionFactory->create($parts[1], $context) : null;
+
+        return new static($parts[0], $description);
+    }
+
+    /**
+     * Gets the link
+     */
+    public function getLink() : string
+    {
+        return $this->link;
+    }
+
+    /**
+     * Returns a string representation for this tag.
+     */
+    public function __toString() : string
+    {
+        if ($this->description) {
+            $description = $this->description->render();
+        } else {
+            $description = '';
+        }
+
+        $link = (string) $this->link;
+
+        return $link . ($description !== '' ? ($link !== '' ? ' ' : '') . $description : '');
+    }
+}
diff --git a/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Method.php b/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Method.php
new file mode 100644
index 0000000000000000000000000000000000000000..08c0407ea93a557de04da73b83bc7e7949dd8b64
--- /dev/null
+++ b/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Method.php
@@ -0,0 +1,279 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * This file is part of phpDocumentor.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ *
+ * @link http://phpdoc.org
+ */
+
+namespace phpDocumentor\Reflection\DocBlock\Tags;
+
+use InvalidArgumentException;
+use phpDocumentor\Reflection\DocBlock\Description;
+use phpDocumentor\Reflection\DocBlock\DescriptionFactory;
+use phpDocumentor\Reflection\Type;
+use phpDocumentor\Reflection\TypeResolver;
+use phpDocumentor\Reflection\Types\Context as TypeContext;
+use phpDocumentor\Reflection\Types\Mixed_;
+use phpDocumentor\Reflection\Types\Void_;
+use Webmozart\Assert\Assert;
+use function array_keys;
+use function explode;
+use function implode;
+use function is_string;
+use function preg_match;
+use function sort;
+use function strpos;
+use function substr;
+use function trim;
+use function var_export;
+
+/**
+ * Reflection class for an {@}method in a Docblock.
+ */
+final class Method extends BaseTag implements Factory\StaticMethod
+{
+    /** @var string */
+    protected $name = 'method';
+
+    /** @var string */
+    private $methodName;
+
+    /**
+     * @phpstan-var array<int, array{name: string, type: Type}>
+     * @var array<int, array<string, Type|string>>
+     */
+    private $arguments;
+
+    /** @var bool */
+    private $isStatic;
+
+    /** @var Type */
+    private $returnType;
+
+    /**
+     * @param array<int, array<string, Type|string>> $arguments
+     *
+     * @phpstan-param array<int, array{name: string, type: Type}|string> $arguments
+     */
+    public function __construct(
+        string $methodName,
+        array $arguments = [],
+        ?Type $returnType = null,
+        bool $static = false,
+        ?Description $description = null
+    ) {
+        Assert::stringNotEmpty($methodName);
+
+        if ($returnType === null) {
+            $returnType = new Void_();
+        }
+
+        $this->methodName  = $methodName;
+        $this->arguments   = $this->filterArguments($arguments);
+        $this->returnType  = $returnType;
+        $this->isStatic    = $static;
+        $this->description = $description;
+    }
+
+    public static function create(
+        string $body,
+        ?TypeResolver $typeResolver = null,
+        ?DescriptionFactory $descriptionFactory = null,
+        ?TypeContext $context = null
+    ) : ?self {
+        Assert::stringNotEmpty($body);
+        Assert::notNull($typeResolver);
+        Assert::notNull($descriptionFactory);
+
+        // 1. none or more whitespace
+        // 2. optionally the keyword "static" followed by whitespace
+        // 3. optionally a word with underscores followed by whitespace : as
+        //    type for the return value
+        // 4. then optionally a word with underscores followed by () and
+        //    whitespace : as method name as used by phpDocumentor
+        // 5. then a word with underscores, followed by ( and any character
+        //    until a ) and whitespace : as method name with signature
+        // 6. any remaining text : as description
+        if (!preg_match(
+            '/^
+                # Static keyword
+                # Declares a static method ONLY if type is also present
+                (?:
+                    (static)
+                    \s+
+                )?
+                # Return type
+                (?:
+                    (
+                        (?:[\w\|_\\\\]*\$this[\w\|_\\\\]*)
+                        |
+                        (?:
+                            (?:[\w\|_\\\\]+)
+                            # array notation
+                            (?:\[\])*
+                        )*+
+                    )
+                    \s+
+                )?
+                # Method name
+                ([\w_]+)
+                # Arguments
+                (?:
+                    \(([^\)]*)\)
+                )?
+                \s*
+                # Description
+                (.*)
+            $/sux',
+            $body,
+            $matches
+        )) {
+            return null;
+        }
+
+        [, $static, $returnType, $methodName, $argumentLines, $description] = $matches;
+
+        $static = $static === 'static';
+
+        if ($returnType === '') {
+            $returnType = 'void';
+        }
+
+        $returnType  = $typeResolver->resolve($returnType, $context);
+        $description = $descriptionFactory->create($description, $context);
+
+        /** @phpstan-var array<int, array{name: string, type: Type}> $arguments */
+        $arguments = [];
+        if ($argumentLines !== '') {
+            $argumentsExploded = explode(',', $argumentLines);
+            foreach ($argumentsExploded as $argument) {
+                $argument = explode(' ', self::stripRestArg(trim($argument)), 2);
+                if (strpos($argument[0], '$') === 0) {
+                    $argumentName = substr($argument[0], 1);
+                    $argumentType = new Mixed_();
+                } else {
+                    $argumentType = $typeResolver->resolve($argument[0], $context);
+                    $argumentName = '';
+                    if (isset($argument[1])) {
+                        $argument[1]  = self::stripRestArg($argument[1]);
+                        $argumentName = substr($argument[1], 1);
+                    }
+                }
+
+                $arguments[] = ['name' => $argumentName, 'type' => $argumentType];
+            }
+        }
+
+        return new static($methodName, $arguments, $returnType, $static, $description);
+    }
+
+    /**
+     * Retrieves the method name.
+     */
+    public function getMethodName() : string
+    {
+        return $this->methodName;
+    }
+
+    /**
+     * @return array<int, array<string, Type|string>>
+     *
+     * @phpstan-return array<int, array{name: string, type: Type}>
+     */
+    public function getArguments() : array
+    {
+        return $this->arguments;
+    }
+
+    /**
+     * Checks whether the method tag describes a static method or not.
+     *
+     * @return bool TRUE if the method declaration is for a static method, FALSE otherwise.
+     */
+    public function isStatic() : bool
+    {
+        return $this->isStatic;
+    }
+
+    public function getReturnType() : Type
+    {
+        return $this->returnType;
+    }
+
+    public function __toString() : string
+    {
+        $arguments = [];
+        foreach ($this->arguments as $argument) {
+            $arguments[] = $argument['type'] . ' $' . $argument['name'];
+        }
+
+        $argumentStr = '(' . implode(', ', $arguments) . ')';
+
+        if ($this->description) {
+            $description = $this->description->render();
+        } else {
+            $description = '';
+        }
+
+        $static = $this->isStatic ? 'static' : '';
+
+        $returnType = (string) $this->returnType;
+
+        $methodName = (string) $this->methodName;
+
+        return $static
+            . ($returnType !== '' ? ($static !== '' ? ' ' : '') . $returnType : '')
+            . ($methodName !== '' ? ($static !== '' || $returnType !== '' ? ' ' : '') . $methodName : '')
+            . $argumentStr
+            . ($description !== '' ? ' ' . $description : '');
+    }
+
+    /**
+     * @param mixed[][]|string[] $arguments
+     *
+     * @return mixed[][]
+     *
+     * @phpstan-param array<int, array{name: string, type: Type}|string> $arguments
+     * @phpstan-return array<int, array{name: string, type: Type}>
+     */
+    private function filterArguments(array $arguments = []) : array
+    {
+        $result = [];
+        foreach ($arguments as $argument) {
+            if (is_string($argument)) {
+                $argument = ['name' => $argument];
+            }
+
+            if (!isset($argument['type'])) {
+                $argument['type'] = new Mixed_();
+            }
+
+            $keys = array_keys($argument);
+            sort($keys);
+            if ($keys !== ['name', 'type']) {
+                throw new InvalidArgumentException(
+                    'Arguments can only have the "name" and "type" fields, found: ' . var_export($keys, true)
+                );
+            }
+
+            $result[] = $argument;
+        }
+
+        return $result;
+    }
+
+    private static function stripRestArg(string $argument) : string
+    {
+        if (strpos($argument, '...') === 0) {
+            $argument = trim(substr($argument, 3));
+        }
+
+        return $argument;
+    }
+}
diff --git a/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Param.php b/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Param.php
new file mode 100644
index 0000000000000000000000000000000000000000..83419e9c5dcdbe14abb0380bb8607a3978301d8c
--- /dev/null
+++ b/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Param.php
@@ -0,0 +1,172 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * This file is part of phpDocumentor.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ *
+ * @link      http://phpdoc.org
+ */
+
+namespace phpDocumentor\Reflection\DocBlock\Tags;
+
+use phpDocumentor\Reflection\DocBlock\Description;
+use phpDocumentor\Reflection\DocBlock\DescriptionFactory;
+use phpDocumentor\Reflection\Type;
+use phpDocumentor\Reflection\TypeResolver;
+use phpDocumentor\Reflection\Types\Context as TypeContext;
+use phpDocumentor\Reflection\Utils;
+use Webmozart\Assert\Assert;
+use function array_shift;
+use function array_unshift;
+use function implode;
+use function strpos;
+use function substr;
+use const PREG_SPLIT_DELIM_CAPTURE;
+
+/**
+ * Reflection class for the {@}param tag in a Docblock.
+ */
+final class Param extends TagWithType implements Factory\StaticMethod
+{
+    /** @var string|null */
+    private $variableName;
+
+    /** @var bool determines whether this is a variadic argument */
+    private $isVariadic;
+
+    /** @var bool determines whether this is passed by reference */
+    private $isReference;
+
+    public function __construct(
+        ?string $variableName,
+        ?Type $type = null,
+        bool $isVariadic = false,
+        ?Description $description = null,
+        bool $isReference = false
+    ) {
+        $this->name         = 'param';
+        $this->variableName = $variableName;
+        $this->type         = $type;
+        $this->isVariadic   = $isVariadic;
+        $this->description  = $description;
+        $this->isReference  = $isReference;
+    }
+
+    public static function create(
+        string $body,
+        ?TypeResolver $typeResolver = null,
+        ?DescriptionFactory $descriptionFactory = null,
+        ?TypeContext $context = null
+    ) : self {
+        Assert::stringNotEmpty($body);
+        Assert::notNull($typeResolver);
+        Assert::notNull($descriptionFactory);
+
+        [$firstPart, $body] = self::extractTypeFromBody($body);
+
+        $type         = null;
+        $parts        = Utils::pregSplit('/(\s+)/Su', $body, 2, PREG_SPLIT_DELIM_CAPTURE);
+        $variableName = '';
+        $isVariadic   = false;
+        $isReference   = false;
+
+        // if the first item that is encountered is not a variable; it is a type
+        if ($firstPart && !self::strStartsWithVariable($firstPart)) {
+            $type = $typeResolver->resolve($firstPart, $context);
+        } else {
+            // first part is not a type; we should prepend it to the parts array for further processing
+            array_unshift($parts, $firstPart);
+        }
+
+        // if the next item starts with a $ or ...$ or &$ or &...$ it must be the variable name
+        if (isset($parts[0]) && self::strStartsWithVariable($parts[0])) {
+            $variableName = array_shift($parts);
+            if ($type) {
+                array_shift($parts);
+            }
+
+            Assert::notNull($variableName);
+
+            if (strpos($variableName, '$') === 0) {
+                $variableName = substr($variableName, 1);
+            } elseif (strpos($variableName, '&$') === 0) {
+                $isReference = true;
+                $variableName = substr($variableName, 2);
+            } elseif (strpos($variableName, '...$') === 0) {
+                $isVariadic = true;
+                $variableName = substr($variableName, 4);
+            } elseif (strpos($variableName, '&...$') === 0) {
+                $isVariadic   = true;
+                $isReference  = true;
+                $variableName = substr($variableName, 5);
+            }
+        }
+
+        $description = $descriptionFactory->create(implode('', $parts), $context);
+
+        return new static($variableName, $type, $isVariadic, $description, $isReference);
+    }
+
+    /**
+     * Returns the variable's name.
+     */
+    public function getVariableName() : ?string
+    {
+        return $this->variableName;
+    }
+
+    /**
+     * Returns whether this tag is variadic.
+     */
+    public function isVariadic() : bool
+    {
+        return $this->isVariadic;
+    }
+
+    /**
+     * Returns whether this tag is passed by reference.
+     */
+    public function isReference() : bool
+    {
+        return $this->isReference;
+    }
+
+    /**
+     * Returns a string representation for this tag.
+     */
+    public function __toString() : string
+    {
+        if ($this->description) {
+            $description = $this->description->render();
+        } else {
+            $description = '';
+        }
+
+        $variableName = '';
+        if ($this->variableName) {
+            $variableName .= ($this->isReference ? '&' : '') . ($this->isVariadic ? '...' : '');
+            $variableName .= '$' . $this->variableName;
+        }
+
+        $type = (string) $this->type;
+
+        return $type
+            . ($variableName !== '' ? ($type !== '' ? ' ' : '') . $variableName : '')
+            . ($description !== '' ? ($type !== '' || $variableName !== '' ? ' ' : '') . $description : '');
+    }
+
+    private static function strStartsWithVariable(string $str) : bool
+    {
+        return strpos($str, '$') === 0
+               ||
+               strpos($str, '...$') === 0
+               ||
+               strpos($str, '&$') === 0
+               ||
+               strpos($str, '&...$') === 0;
+    }
+}
diff --git a/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Property.php b/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Property.php
new file mode 100644
index 0000000000000000000000000000000000000000..03897578b982a849988ebe431ddc933f052e6502
--- /dev/null
+++ b/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Property.php
@@ -0,0 +1,119 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * This file is part of phpDocumentor.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ *
+ * @link      http://phpdoc.org
+ */
+
+namespace phpDocumentor\Reflection\DocBlock\Tags;
+
+use phpDocumentor\Reflection\DocBlock\Description;
+use phpDocumentor\Reflection\DocBlock\DescriptionFactory;
+use phpDocumentor\Reflection\Type;
+use phpDocumentor\Reflection\TypeResolver;
+use phpDocumentor\Reflection\Types\Context as TypeContext;
+use phpDocumentor\Reflection\Utils;
+use Webmozart\Assert\Assert;
+use function array_shift;
+use function array_unshift;
+use function implode;
+use function strpos;
+use function substr;
+use const PREG_SPLIT_DELIM_CAPTURE;
+
+/**
+ * Reflection class for a {@}property tag in a Docblock.
+ */
+final class Property extends TagWithType implements Factory\StaticMethod
+{
+    /** @var string|null */
+    protected $variableName;
+
+    public function __construct(?string $variableName, ?Type $type = null, ?Description $description = null)
+    {
+        Assert::string($variableName);
+
+        $this->name         = 'property';
+        $this->variableName = $variableName;
+        $this->type         = $type;
+        $this->description  = $description;
+    }
+
+    public static function create(
+        string $body,
+        ?TypeResolver $typeResolver = null,
+        ?DescriptionFactory $descriptionFactory = null,
+        ?TypeContext $context = null
+    ) : self {
+        Assert::stringNotEmpty($body);
+        Assert::notNull($typeResolver);
+        Assert::notNull($descriptionFactory);
+
+        [$firstPart, $body] = self::extractTypeFromBody($body);
+        $type               = null;
+        $parts              = Utils::pregSplit('/(\s+)/Su', $body, 2, PREG_SPLIT_DELIM_CAPTURE);
+        $variableName = '';
+
+        // if the first item that is encountered is not a variable; it is a type
+        if ($firstPart && $firstPart[0] !== '$') {
+            $type = $typeResolver->resolve($firstPart, $context);
+        } else {
+            // first part is not a type; we should prepend it to the parts array for further processing
+            array_unshift($parts, $firstPart);
+        }
+
+        // if the next item starts with a $ it must be the variable name
+        if (isset($parts[0]) && strpos($parts[0], '$') === 0) {
+            $variableName = array_shift($parts);
+            if ($type) {
+                array_shift($parts);
+            }
+
+            Assert::notNull($variableName);
+
+            $variableName = substr($variableName, 1);
+        }
+
+        $description = $descriptionFactory->create(implode('', $parts), $context);
+
+        return new static($variableName, $type, $description);
+    }
+
+    /**
+     * Returns the variable's name.
+     */
+    public function getVariableName() : ?string
+    {
+        return $this->variableName;
+    }
+
+    /**
+     * Returns a string representation for this tag.
+     */
+    public function __toString() : string
+    {
+        if ($this->description) {
+            $description = $this->description->render();
+        } else {
+            $description = '';
+        }
+
+        if ($this->variableName) {
+            $variableName = '$' . $this->variableName;
+        } else {
+            $variableName = '';
+        }
+
+        $type = (string) $this->type;
+
+        return $type
+            . ($variableName !== '' ? ($type !== '' ? ' ' : '') . $variableName : '')
+            . ($description !== '' ? ($type !== '' || $variableName !== '' ? ' ' : '') . $description : '');
+    }
+}
diff --git a/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/PropertyRead.php b/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/PropertyRead.php
new file mode 100644
index 0000000000000000000000000000000000000000..7ff55d50b53d1ddb45a7eef83feec621bd9868ce
--- /dev/null
+++ b/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/PropertyRead.php
@@ -0,0 +1,119 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * This file is part of phpDocumentor.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ *
+ * @link      http://phpdoc.org
+ */
+
+namespace phpDocumentor\Reflection\DocBlock\Tags;
+
+use phpDocumentor\Reflection\DocBlock\Description;
+use phpDocumentor\Reflection\DocBlock\DescriptionFactory;
+use phpDocumentor\Reflection\Type;
+use phpDocumentor\Reflection\TypeResolver;
+use phpDocumentor\Reflection\Types\Context as TypeContext;
+use phpDocumentor\Reflection\Utils;
+use Webmozart\Assert\Assert;
+use function array_shift;
+use function array_unshift;
+use function implode;
+use function strpos;
+use function substr;
+use const PREG_SPLIT_DELIM_CAPTURE;
+
+/**
+ * Reflection class for a {@}property-read tag in a Docblock.
+ */
+final class PropertyRead extends TagWithType implements Factory\StaticMethod
+{
+    /** @var string|null */
+    protected $variableName;
+
+    public function __construct(?string $variableName, ?Type $type = null, ?Description $description = null)
+    {
+        Assert::string($variableName);
+
+        $this->name         = 'property-read';
+        $this->variableName = $variableName;
+        $this->type         = $type;
+        $this->description  = $description;
+    }
+
+    public static function create(
+        string $body,
+        ?TypeResolver $typeResolver = null,
+        ?DescriptionFactory $descriptionFactory = null,
+        ?TypeContext $context = null
+    ) : self {
+        Assert::stringNotEmpty($body);
+        Assert::notNull($typeResolver);
+        Assert::notNull($descriptionFactory);
+
+        [$firstPart, $body] = self::extractTypeFromBody($body);
+        $type               = null;
+        $parts              = Utils::pregSplit('/(\s+)/Su', $body, 2, PREG_SPLIT_DELIM_CAPTURE);
+        $variableName = '';
+
+        // if the first item that is encountered is not a variable; it is a type
+        if ($firstPart && $firstPart[0] !== '$') {
+            $type = $typeResolver->resolve($firstPart, $context);
+        } else {
+            // first part is not a type; we should prepend it to the parts array for further processing
+            array_unshift($parts, $firstPart);
+        }
+
+        // if the next item starts with a $ it must be the variable name
+        if (isset($parts[0]) && strpos($parts[0], '$') === 0) {
+            $variableName = array_shift($parts);
+            if ($type) {
+                array_shift($parts);
+            }
+
+            Assert::notNull($variableName);
+
+            $variableName = substr($variableName, 1);
+        }
+
+        $description = $descriptionFactory->create(implode('', $parts), $context);
+
+        return new static($variableName, $type, $description);
+    }
+
+    /**
+     * Returns the variable's name.
+     */
+    public function getVariableName() : ?string
+    {
+        return $this->variableName;
+    }
+
+    /**
+     * Returns a string representation for this tag.
+     */
+    public function __toString() : string
+    {
+        if ($this->description) {
+            $description = $this->description->render();
+        } else {
+            $description = '';
+        }
+
+        if ($this->variableName) {
+            $variableName = '$' . $this->variableName;
+        } else {
+            $variableName = '';
+        }
+
+        $type = (string) $this->type;
+
+        return $type
+            . ($variableName !== '' ? ($type !== '' ? ' ' : '') . $variableName : '')
+            . ($description !== '' ? ($type !== '' || $variableName !== '' ? ' ' : '') . $description : '');
+    }
+}
diff --git a/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/PropertyWrite.php b/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/PropertyWrite.php
new file mode 100644
index 0000000000000000000000000000000000000000..cc1e4b6108338fd7660e2ba4f4452baac87f0db1
--- /dev/null
+++ b/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/PropertyWrite.php
@@ -0,0 +1,119 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * This file is part of phpDocumentor.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ *
+ * @link      http://phpdoc.org
+ */
+
+namespace phpDocumentor\Reflection\DocBlock\Tags;
+
+use phpDocumentor\Reflection\DocBlock\Description;
+use phpDocumentor\Reflection\DocBlock\DescriptionFactory;
+use phpDocumentor\Reflection\Type;
+use phpDocumentor\Reflection\TypeResolver;
+use phpDocumentor\Reflection\Types\Context as TypeContext;
+use phpDocumentor\Reflection\Utils;
+use Webmozart\Assert\Assert;
+use function array_shift;
+use function array_unshift;
+use function implode;
+use function strpos;
+use function substr;
+use const PREG_SPLIT_DELIM_CAPTURE;
+
+/**
+ * Reflection class for a {@}property-write tag in a Docblock.
+ */
+final class PropertyWrite extends TagWithType implements Factory\StaticMethod
+{
+    /** @var string */
+    protected $variableName;
+
+    public function __construct(?string $variableName, ?Type $type = null, ?Description $description = null)
+    {
+        Assert::string($variableName);
+
+        $this->name         = 'property-write';
+        $this->variableName = $variableName;
+        $this->type         = $type;
+        $this->description  = $description;
+    }
+
+    public static function create(
+        string $body,
+        ?TypeResolver $typeResolver = null,
+        ?DescriptionFactory $descriptionFactory = null,
+        ?TypeContext $context = null
+    ) : self {
+        Assert::stringNotEmpty($body);
+        Assert::notNull($typeResolver);
+        Assert::notNull($descriptionFactory);
+
+        [$firstPart, $body] = self::extractTypeFromBody($body);
+        $type               = null;
+        $parts              = Utils::pregSplit('/(\s+)/Su', $body, 2, PREG_SPLIT_DELIM_CAPTURE);
+        $variableName = '';
+
+        // if the first item that is encountered is not a variable; it is a type
+        if ($firstPart && $firstPart[0] !== '$') {
+            $type = $typeResolver->resolve($firstPart, $context);
+        } else {
+            // first part is not a type; we should prepend it to the parts array for further processing
+            array_unshift($parts, $firstPart);
+        }
+
+        // if the next item starts with a $ it must be the variable name
+        if (isset($parts[0]) && strpos($parts[0], '$') === 0) {
+            $variableName = array_shift($parts);
+            if ($type) {
+                array_shift($parts);
+            }
+
+            Assert::notNull($variableName);
+
+            $variableName = substr($variableName, 1);
+        }
+
+        $description = $descriptionFactory->create(implode('', $parts), $context);
+
+        return new static($variableName, $type, $description);
+    }
+
+    /**
+     * Returns the variable's name.
+     */
+    public function getVariableName() : ?string
+    {
+        return $this->variableName;
+    }
+
+    /**
+     * Returns a string representation for this tag.
+     */
+    public function __toString() : string
+    {
+        if ($this->description) {
+            $description = $this->description->render();
+        } else {
+            $description = '';
+        }
+
+        if ($this->variableName) {
+            $variableName = '$' . $this->variableName;
+        } else {
+            $variableName = '';
+        }
+
+        $type = (string) $this->type;
+
+        return $type
+            . ($variableName !== '' ? ($type !== '' ? ' ' : '') . $variableName : '')
+            . ($description !== '' ? ($type !== '' || $variableName !== '' ? ' ' : '') . $description : '');
+    }
+}
diff --git a/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Reference/Fqsen.php b/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Reference/Fqsen.php
new file mode 100644
index 0000000000000000000000000000000000000000..cede74c17401ab8c5e17848dd42b1ba4f3ec7002
--- /dev/null
+++ b/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Reference/Fqsen.php
@@ -0,0 +1,38 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * This file is part of phpDocumentor.
+ *
+ *  For the full copyright and license information, please view the LICENSE
+ *  file that was distributed with this source code.
+ *
+ * @link http://phpdoc.org
+ */
+
+namespace phpDocumentor\Reflection\DocBlock\Tags\Reference;
+
+use phpDocumentor\Reflection\Fqsen as RealFqsen;
+
+/**
+ * Fqsen reference used by {@see \phpDocumentor\Reflection\DocBlock\Tags\See}
+ */
+final class Fqsen implements Reference
+{
+    /** @var RealFqsen */
+    private $fqsen;
+
+    public function __construct(RealFqsen $fqsen)
+    {
+        $this->fqsen = $fqsen;
+    }
+
+    /**
+     * @return string string representation of the referenced fqsen
+     */
+    public function __toString() : string
+    {
+        return (string) $this->fqsen;
+    }
+}
diff --git a/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Reference/Reference.php b/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Reference/Reference.php
new file mode 100644
index 0000000000000000000000000000000000000000..5eedcbc366c567a3b17c66c7d2b73c43ea2b727e
--- /dev/null
+++ b/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Reference/Reference.php
@@ -0,0 +1,22 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * This file is part of phpDocumentor.
+ *
+ *  For the full copyright and license information, please view the LICENSE
+ *  file that was distributed with this source code.
+ *
+ * @link http://phpdoc.org
+ */
+
+namespace phpDocumentor\Reflection\DocBlock\Tags\Reference;
+
+/**
+ * Interface for references in {@see \phpDocumentor\Reflection\DocBlock\Tags\See}
+ */
+interface Reference
+{
+    public function __toString() : string;
+}
diff --git a/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Reference/Url.php b/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Reference/Url.php
new file mode 100644
index 0000000000000000000000000000000000000000..1b2374b9c0116603992087442673fe252b0f9a4b
--- /dev/null
+++ b/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Reference/Url.php
@@ -0,0 +1,36 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * This file is part of phpDocumentor.
+ *
+ *  For the full copyright and license information, please view the LICENSE
+ *  file that was distributed with this source code.
+ *
+ * @link http://phpdoc.org
+ */
+
+namespace phpDocumentor\Reflection\DocBlock\Tags\Reference;
+
+use Webmozart\Assert\Assert;
+
+/**
+ * Url reference used by {@see \phpDocumentor\Reflection\DocBlock\Tags\See}
+ */
+final class Url implements Reference
+{
+    /** @var string */
+    private $uri;
+
+    public function __construct(string $uri)
+    {
+        Assert::stringNotEmpty($uri);
+        $this->uri = $uri;
+    }
+
+    public function __toString() : string
+    {
+        return $this->uri;
+    }
+}
diff --git a/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Return_.php b/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Return_.php
new file mode 100644
index 0000000000000000000000000000000000000000..546a0eaa5a97a1f1eaea144d47758da20609494b
--- /dev/null
+++ b/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Return_.php
@@ -0,0 +1,64 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * This file is part of phpDocumentor.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ *
+ * @link      http://phpdoc.org
+ */
+
+namespace phpDocumentor\Reflection\DocBlock\Tags;
+
+use phpDocumentor\Reflection\DocBlock\Description;
+use phpDocumentor\Reflection\DocBlock\DescriptionFactory;
+use phpDocumentor\Reflection\Type;
+use phpDocumentor\Reflection\TypeResolver;
+use phpDocumentor\Reflection\Types\Context as TypeContext;
+use Webmozart\Assert\Assert;
+
+/**
+ * Reflection class for a {@}return tag in a Docblock.
+ */
+final class Return_ extends TagWithType implements Factory\StaticMethod
+{
+    public function __construct(Type $type, ?Description $description = null)
+    {
+        $this->name        = 'return';
+        $this->type        = $type;
+        $this->description = $description;
+    }
+
+    public static function create(
+        string $body,
+        ?TypeResolver $typeResolver = null,
+        ?DescriptionFactory $descriptionFactory = null,
+        ?TypeContext $context = null
+    ) : self {
+        Assert::notNull($typeResolver);
+        Assert::notNull($descriptionFactory);
+
+        [$type, $description] = self::extractTypeFromBody($body);
+
+        $type        = $typeResolver->resolve($type, $context);
+        $description = $descriptionFactory->create($description, $context);
+
+        return new static($type, $description);
+    }
+
+    public function __toString() : string
+    {
+        if ($this->description) {
+            $description = $this->description->render();
+        } else {
+            $description = '';
+        }
+
+        $type = $this->type ? '' . $this->type : 'mixed';
+
+        return $type . ($description !== '' ? ($type !== '' ? ' ' : '') . $description : '');
+    }
+}
diff --git a/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/See.php b/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/See.php
new file mode 100644
index 0000000000000000000000000000000000000000..73311df78ac20082099aa77e2d81aa45d619979d
--- /dev/null
+++ b/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/See.php
@@ -0,0 +1,105 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * This file is part of phpDocumentor.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ *
+ * @link http://phpdoc.org
+ */
+
+namespace phpDocumentor\Reflection\DocBlock\Tags;
+
+use phpDocumentor\Reflection\DocBlock\Description;
+use phpDocumentor\Reflection\DocBlock\DescriptionFactory;
+use phpDocumentor\Reflection\DocBlock\Tags\Reference\Fqsen as FqsenRef;
+use phpDocumentor\Reflection\DocBlock\Tags\Reference\Reference;
+use phpDocumentor\Reflection\DocBlock\Tags\Reference\Url;
+use phpDocumentor\Reflection\Fqsen;
+use phpDocumentor\Reflection\FqsenResolver;
+use phpDocumentor\Reflection\Types\Context as TypeContext;
+use phpDocumentor\Reflection\Utils;
+use Webmozart\Assert\Assert;
+use function array_key_exists;
+use function explode;
+use function preg_match;
+
+/**
+ * Reflection class for an {@}see tag in a Docblock.
+ */
+final class See extends BaseTag implements Factory\StaticMethod
+{
+    /** @var string */
+    protected $name = 'see';
+
+    /** @var Reference */
+    protected $refers;
+
+    /**
+     * Initializes this tag.
+     */
+    public function __construct(Reference $refers, ?Description $description = null)
+    {
+        $this->refers      = $refers;
+        $this->description = $description;
+    }
+
+    public static function create(
+        string $body,
+        ?FqsenResolver $typeResolver = null,
+        ?DescriptionFactory $descriptionFactory = null,
+        ?TypeContext $context = null
+    ) : self {
+        Assert::notNull($descriptionFactory);
+
+        $parts = Utils::pregSplit('/\s+/Su', $body, 2);
+        $description = isset($parts[1]) ? $descriptionFactory->create($parts[1], $context) : null;
+
+        // https://tools.ietf.org/html/rfc2396#section-3
+        if (preg_match('/\w:\/\/\w/i', $parts[0])) {
+            return new static(new Url($parts[0]), $description);
+        }
+
+        return new static(new FqsenRef(self::resolveFqsen($parts[0], $typeResolver, $context)), $description);
+    }
+
+    private static function resolveFqsen(string $parts, ?FqsenResolver $fqsenResolver, ?TypeContext $context) : Fqsen
+    {
+        Assert::notNull($fqsenResolver);
+        $fqsenParts = explode('::', $parts);
+        $resolved = $fqsenResolver->resolve($fqsenParts[0], $context);
+
+        if (!array_key_exists(1, $fqsenParts)) {
+            return $resolved;
+        }
+
+        return new Fqsen($resolved . '::' . $fqsenParts[1]);
+    }
+
+    /**
+     * Returns the ref of this tag.
+     */
+    public function getReference() : Reference
+    {
+        return $this->refers;
+    }
+
+    /**
+     * Returns a string representation of this tag.
+     */
+    public function __toString() : string
+    {
+        if ($this->description) {
+            $description = $this->description->render();
+        } else {
+            $description = '';
+        }
+
+        $refers = (string) $this->refers;
+
+        return $refers . ($description !== '' ? ($refers !== '' ? ' ' : '') . $description : '');
+    }
+}
diff --git a/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Since.php b/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Since.php
new file mode 100644
index 0000000000000000000000000000000000000000..32de527b0e27559c501989b938cc34bbc13405ff
--- /dev/null
+++ b/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Since.php
@@ -0,0 +1,102 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * This file is part of phpDocumentor.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ *
+ * @link      http://phpdoc.org
+ */
+
+namespace phpDocumentor\Reflection\DocBlock\Tags;
+
+use phpDocumentor\Reflection\DocBlock\Description;
+use phpDocumentor\Reflection\DocBlock\DescriptionFactory;
+use phpDocumentor\Reflection\Types\Context as TypeContext;
+use Webmozart\Assert\Assert;
+use function preg_match;
+
+/**
+ * Reflection class for a {@}since tag in a Docblock.
+ */
+final class Since extends BaseTag implements Factory\StaticMethod
+{
+    /** @var string */
+    protected $name = 'since';
+
+    /**
+     * PCRE regular expression matching a version vector.
+     * Assumes the "x" modifier.
+     */
+    public const REGEX_VECTOR = '(?:
+        # Normal release vectors.
+        \d\S*
+        |
+        # VCS version vectors. Per PHPCS, they are expected to
+        # follow the form of the VCS name, followed by ":", followed
+        # by the version vector itself.
+        # By convention, popular VCSes like CVS, SVN and GIT use "$"
+        # around the actual version vector.
+        [^\s\:]+\:\s*\$[^\$]+\$
+    )';
+
+    /** @var string|null The version vector. */
+    private $version;
+
+    public function __construct(?string $version = null, ?Description $description = null)
+    {
+        Assert::nullOrNotEmpty($version);
+
+        $this->version     = $version;
+        $this->description = $description;
+    }
+
+    public static function create(
+        ?string $body,
+        ?DescriptionFactory $descriptionFactory = null,
+        ?TypeContext $context = null
+    ) : ?self {
+        if (empty($body)) {
+            return new static();
+        }
+
+        $matches = [];
+        if (!preg_match('/^(' . self::REGEX_VECTOR . ')\s*(.+)?$/sux', $body, $matches)) {
+            return null;
+        }
+
+        Assert::notNull($descriptionFactory);
+
+        return new static(
+            $matches[1],
+            $descriptionFactory->create($matches[2] ?? '', $context)
+        );
+    }
+
+    /**
+     * Gets the version section of the tag.
+     */
+    public function getVersion() : ?string
+    {
+        return $this->version;
+    }
+
+    /**
+     * Returns a string representation for this tag.
+     */
+    public function __toString() : string
+    {
+        if ($this->description) {
+            $description = $this->description->render();
+        } else {
+            $description = '';
+        }
+
+        $version = (string) $this->version;
+
+        return $version . ($description !== '' ? ($version !== '' ? ' ' : '') . $description : '');
+    }
+}
diff --git a/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Source.php b/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Source.php
new file mode 100644
index 0000000000000000000000000000000000000000..f0c3101411deabe285f9d1395ac7acb047cc5c69
--- /dev/null
+++ b/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Source.php
@@ -0,0 +1,117 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * This file is part of phpDocumentor.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ *
+ * @link      http://phpdoc.org
+ */
+
+namespace phpDocumentor\Reflection\DocBlock\Tags;
+
+use phpDocumentor\Reflection\DocBlock\Description;
+use phpDocumentor\Reflection\DocBlock\DescriptionFactory;
+use phpDocumentor\Reflection\Types\Context as TypeContext;
+use Webmozart\Assert\Assert;
+use function preg_match;
+
+/**
+ * Reflection class for a {@}source tag in a Docblock.
+ */
+final class Source extends BaseTag implements Factory\StaticMethod
+{
+    /** @var string */
+    protected $name = 'source';
+
+    /** @var int The starting line, relative to the structural element's location. */
+    private $startingLine;
+
+    /** @var int|null The number of lines, relative to the starting line. NULL means "to the end". */
+    private $lineCount;
+
+    /**
+     * @param int|string      $startingLine should be a to int convertible value
+     * @param int|string|null $lineCount    should be a to int convertible value
+     */
+    public function __construct($startingLine, $lineCount = null, ?Description $description = null)
+    {
+        Assert::integerish($startingLine);
+        Assert::nullOrIntegerish($lineCount);
+
+        $this->startingLine = (int) $startingLine;
+        $this->lineCount    = $lineCount !== null ? (int) $lineCount : null;
+        $this->description  = $description;
+    }
+
+    public static function create(
+        string $body,
+        ?DescriptionFactory $descriptionFactory = null,
+        ?TypeContext $context = null
+    ) : self {
+        Assert::stringNotEmpty($body);
+        Assert::notNull($descriptionFactory);
+
+        $startingLine = 1;
+        $lineCount    = null;
+        $description  = null;
+
+        // Starting line / Number of lines / Description
+        if (preg_match('/^([1-9]\d*)\s*(?:((?1))\s+)?(.*)$/sux', $body, $matches)) {
+            $startingLine = (int) $matches[1];
+            if (isset($matches[2]) && $matches[2] !== '') {
+                $lineCount = (int) $matches[2];
+            }
+
+            $description = $matches[3];
+        }
+
+        return new static($startingLine, $lineCount, $descriptionFactory->create($description??'', $context));
+    }
+
+    /**
+     * Gets the starting line.
+     *
+     * @return int The starting line, relative to the structural element's
+     *     location.
+     */
+    public function getStartingLine() : int
+    {
+        return $this->startingLine;
+    }
+
+    /**
+     * Returns the number of lines.
+     *
+     * @return int|null The number of lines, relative to the starting line. NULL
+     *     means "to the end".
+     */
+    public function getLineCount() : ?int
+    {
+        return $this->lineCount;
+    }
+
+    public function __toString() : string
+    {
+        if ($this->description) {
+            $description = $this->description->render();
+        } else {
+            $description = '';
+        }
+
+        $startingLine = (string) $this->startingLine;
+
+        $lineCount = $this->lineCount !== null ? '' . $this->lineCount : '';
+
+        return $startingLine
+            . ($lineCount !== ''
+                ? ($startingLine || $startingLine === '0' ? ' ' : '') . $lineCount
+                : '')
+            . ($description !== ''
+                ? ($startingLine || $startingLine === '0' || $lineCount !== '' ? ' ' : '') . $description
+                : '');
+    }
+}
diff --git a/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/TagWithType.php b/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/TagWithType.php
new file mode 100644
index 0000000000000000000000000000000000000000..0083d34b287747299959c1d5297d0b4154734135
--- /dev/null
+++ b/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/TagWithType.php
@@ -0,0 +1,65 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * This file is part of phpDocumentor.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ *
+ * @link      http://phpdoc.org
+ */
+
+namespace phpDocumentor\Reflection\DocBlock\Tags;
+
+use phpDocumentor\Reflection\Type;
+use function in_array;
+use function strlen;
+use function substr;
+use function trim;
+
+abstract class TagWithType extends BaseTag
+{
+    /** @var ?Type */
+    protected $type;
+
+    /**
+     * Returns the type section of the variable.
+     */
+    public function getType() : ?Type
+    {
+        return $this->type;
+    }
+
+    /**
+     * @return string[]
+     */
+    protected static function extractTypeFromBody(string $body) : array
+    {
+        $type         = '';
+        $nestingLevel = 0;
+        for ($i = 0, $iMax = strlen($body); $i < $iMax; $i++) {
+            $character = $body[$i];
+
+            if ($nestingLevel === 0 && trim($character) === '') {
+                break;
+            }
+
+            $type .= $character;
+            if (in_array($character, ['<', '(', '[', '{'])) {
+                $nestingLevel++;
+                continue;
+            }
+
+            if (in_array($character, ['>', ')', ']', '}'])) {
+                $nestingLevel--;
+                continue;
+            }
+        }
+
+        $description = trim(substr($body, strlen($type)));
+
+        return [$type, $description];
+    }
+}
diff --git a/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Throws.php b/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Throws.php
new file mode 100644
index 0000000000000000000000000000000000000000..d4dc9472c3caf32c9396f33ba03ebb0b8d71681e
--- /dev/null
+++ b/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Throws.php
@@ -0,0 +1,64 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * This file is part of phpDocumentor.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ *
+ * @link      http://phpdoc.org
+ */
+
+namespace phpDocumentor\Reflection\DocBlock\Tags;
+
+use phpDocumentor\Reflection\DocBlock\Description;
+use phpDocumentor\Reflection\DocBlock\DescriptionFactory;
+use phpDocumentor\Reflection\Type;
+use phpDocumentor\Reflection\TypeResolver;
+use phpDocumentor\Reflection\Types\Context as TypeContext;
+use Webmozart\Assert\Assert;
+
+/**
+ * Reflection class for a {@}throws tag in a Docblock.
+ */
+final class Throws extends TagWithType implements Factory\StaticMethod
+{
+    public function __construct(Type $type, ?Description $description = null)
+    {
+        $this->name        = 'throws';
+        $this->type        = $type;
+        $this->description = $description;
+    }
+
+    public static function create(
+        string $body,
+        ?TypeResolver $typeResolver = null,
+        ?DescriptionFactory $descriptionFactory = null,
+        ?TypeContext $context = null
+    ) : self {
+        Assert::notNull($typeResolver);
+        Assert::notNull($descriptionFactory);
+
+        [$type, $description] = self::extractTypeFromBody($body);
+
+        $type        = $typeResolver->resolve($type, $context);
+        $description = $descriptionFactory->create($description, $context);
+
+        return new static($type, $description);
+    }
+
+    public function __toString() : string
+    {
+        if ($this->description) {
+            $description = $this->description->render();
+        } else {
+            $description = '';
+        }
+
+        $type = (string) $this->type;
+
+        return $type . ($description !== '' ? ($type !== '' ? ' ' : '') . $description : '');
+    }
+}
diff --git a/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Uses.php b/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Uses.php
new file mode 100644
index 0000000000000000000000000000000000000000..4d52afccd0067dbcd4e962c3a501e2100b7f909b
--- /dev/null
+++ b/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Uses.php
@@ -0,0 +1,99 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * This file is part of phpDocumentor.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ *
+ * @link http://phpdoc.org
+ */
+
+namespace phpDocumentor\Reflection\DocBlock\Tags;
+
+use phpDocumentor\Reflection\DocBlock\Description;
+use phpDocumentor\Reflection\DocBlock\DescriptionFactory;
+use phpDocumentor\Reflection\Fqsen;
+use phpDocumentor\Reflection\FqsenResolver;
+use phpDocumentor\Reflection\Types\Context as TypeContext;
+use phpDocumentor\Reflection\Utils;
+use Webmozart\Assert\Assert;
+use function array_key_exists;
+use function explode;
+
+/**
+ * Reflection class for a {@}uses tag in a Docblock.
+ */
+final class Uses extends BaseTag implements Factory\StaticMethod
+{
+    /** @var string */
+    protected $name = 'uses';
+
+    /** @var Fqsen */
+    protected $refers;
+
+    /**
+     * Initializes this tag.
+     */
+    public function __construct(Fqsen $refers, ?Description $description = null)
+    {
+        $this->refers      = $refers;
+        $this->description = $description;
+    }
+
+    public static function create(
+        string $body,
+        ?FqsenResolver $resolver = null,
+        ?DescriptionFactory $descriptionFactory = null,
+        ?TypeContext $context = null
+    ) : self {
+        Assert::notNull($resolver);
+        Assert::notNull($descriptionFactory);
+
+        $parts = Utils::pregSplit('/\s+/Su', $body, 2);
+
+        return new static(
+            self::resolveFqsen($parts[0], $resolver, $context),
+            $descriptionFactory->create($parts[1] ?? '', $context)
+        );
+    }
+
+    private static function resolveFqsen(string $parts, ?FqsenResolver $fqsenResolver, ?TypeContext $context) : Fqsen
+    {
+        Assert::notNull($fqsenResolver);
+        $fqsenParts = explode('::', $parts);
+        $resolved = $fqsenResolver->resolve($fqsenParts[0], $context);
+
+        if (!array_key_exists(1, $fqsenParts)) {
+            return $resolved;
+        }
+
+        return new Fqsen($resolved . '::' . $fqsenParts[1]);
+    }
+
+    /**
+     * Returns the structural element this tag refers to.
+     */
+    public function getReference() : Fqsen
+    {
+        return $this->refers;
+    }
+
+    /**
+     * Returns a string representation of this tag.
+     */
+    public function __toString() : string
+    {
+        if ($this->description) {
+            $description = $this->description->render();
+        } else {
+            $description = '';
+        }
+
+        $refers = (string) $this->refers;
+
+        return $refers . ($description !== '' ? ($refers !== '' ? ' ' : '') . $description : '');
+    }
+}
diff --git a/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Var_.php b/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Var_.php
new file mode 100644
index 0000000000000000000000000000000000000000..762c262f9efb73013e9708495e94aba808f9cf22
--- /dev/null
+++ b/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Var_.php
@@ -0,0 +1,120 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * This file is part of phpDocumentor.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ *
+ * @link      http://phpdoc.org
+ */
+
+namespace phpDocumentor\Reflection\DocBlock\Tags;
+
+use phpDocumentor\Reflection\DocBlock\Description;
+use phpDocumentor\Reflection\DocBlock\DescriptionFactory;
+use phpDocumentor\Reflection\Type;
+use phpDocumentor\Reflection\TypeResolver;
+use phpDocumentor\Reflection\Types\Context as TypeContext;
+use phpDocumentor\Reflection\Utils;
+use Webmozart\Assert\Assert;
+use function array_shift;
+use function array_unshift;
+use function implode;
+use function strpos;
+use function substr;
+use const PREG_SPLIT_DELIM_CAPTURE;
+
+/**
+ * Reflection class for a {@}var tag in a Docblock.
+ */
+final class Var_ extends TagWithType implements Factory\StaticMethod
+{
+    /** @var string|null */
+    protected $variableName = '';
+
+    public function __construct(?string $variableName, ?Type $type = null, ?Description $description = null)
+    {
+        Assert::string($variableName);
+
+        $this->name         = 'var';
+        $this->variableName = $variableName;
+        $this->type         = $type;
+        $this->description  = $description;
+    }
+
+    public static function create(
+        string $body,
+        ?TypeResolver $typeResolver = null,
+        ?DescriptionFactory $descriptionFactory = null,
+        ?TypeContext $context = null
+    ) : self {
+        Assert::stringNotEmpty($body);
+        Assert::notNull($typeResolver);
+        Assert::notNull($descriptionFactory);
+
+        [$firstPart, $body] = self::extractTypeFromBody($body);
+
+        $parts = Utils::pregSplit('/(\s+)/Su', $body, 2, PREG_SPLIT_DELIM_CAPTURE);
+        $type         = null;
+        $variableName = '';
+
+        // if the first item that is encountered is not a variable; it is a type
+        if ($firstPart && $firstPart[0] !== '$') {
+            $type = $typeResolver->resolve($firstPart, $context);
+        } else {
+            // first part is not a type; we should prepend it to the parts array for further processing
+            array_unshift($parts, $firstPart);
+        }
+
+        // if the next item starts with a $ it must be the variable name
+        if (isset($parts[0]) && strpos($parts[0], '$') === 0) {
+            $variableName = array_shift($parts);
+            if ($type) {
+                array_shift($parts);
+            }
+
+            Assert::notNull($variableName);
+
+            $variableName = substr($variableName, 1);
+        }
+
+        $description = $descriptionFactory->create(implode('', $parts), $context);
+
+        return new static($variableName, $type, $description);
+    }
+
+    /**
+     * Returns the variable's name.
+     */
+    public function getVariableName() : ?string
+    {
+        return $this->variableName;
+    }
+
+    /**
+     * Returns a string representation for this tag.
+     */
+    public function __toString() : string
+    {
+        if ($this->description) {
+            $description = $this->description->render();
+        } else {
+            $description = '';
+        }
+
+        if ($this->variableName) {
+            $variableName = '$' . $this->variableName;
+        } else {
+            $variableName = '';
+        }
+
+        $type = (string) $this->type;
+
+        return $type
+            . ($variableName !== '' ? ($type !== '' ? ' ' : '') . $variableName : '')
+            . ($description !== '' ? ($type !== '' || $variableName !== '' ? ' ' : '') . $description : '');
+    }
+}
diff --git a/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Version.php b/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Version.php
new file mode 100644
index 0000000000000000000000000000000000000000..460c86d72e5aa37f0a4f1e760f554ca39e4893ae
--- /dev/null
+++ b/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Version.php
@@ -0,0 +1,105 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * This file is part of phpDocumentor.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ *
+ * @link http://phpdoc.org
+ */
+
+namespace phpDocumentor\Reflection\DocBlock\Tags;
+
+use phpDocumentor\Reflection\DocBlock\Description;
+use phpDocumentor\Reflection\DocBlock\DescriptionFactory;
+use phpDocumentor\Reflection\Types\Context as TypeContext;
+use Webmozart\Assert\Assert;
+use function preg_match;
+
+/**
+ * Reflection class for a {@}version tag in a Docblock.
+ */
+final class Version extends BaseTag implements Factory\StaticMethod
+{
+    /** @var string */
+    protected $name = 'version';
+
+    /**
+     * PCRE regular expression matching a version vector.
+     * Assumes the "x" modifier.
+     */
+    public const REGEX_VECTOR = '(?:
+        # Normal release vectors.
+        \d\S*
+        |
+        # VCS version vectors. Per PHPCS, they are expected to
+        # follow the form of the VCS name, followed by ":", followed
+        # by the version vector itself.
+        # By convention, popular VCSes like CVS, SVN and GIT use "$"
+        # around the actual version vector.
+        [^\s\:]+\:\s*\$[^\$]+\$
+    )';
+
+    /** @var string|null The version vector. */
+    private $version;
+
+    public function __construct(?string $version = null, ?Description $description = null)
+    {
+        Assert::nullOrStringNotEmpty($version);
+
+        $this->version     = $version;
+        $this->description = $description;
+    }
+
+    public static function create(
+        ?string $body,
+        ?DescriptionFactory $descriptionFactory = null,
+        ?TypeContext $context = null
+    ) : ?self {
+        if (empty($body)) {
+            return new static();
+        }
+
+        $matches = [];
+        if (!preg_match('/^(' . self::REGEX_VECTOR . ')\s*(.+)?$/sux', $body, $matches)) {
+            return null;
+        }
+
+        $description = null;
+        if ($descriptionFactory !== null) {
+            $description = $descriptionFactory->create($matches[2] ?? '', $context);
+        }
+
+        return new static(
+            $matches[1],
+            $description
+        );
+    }
+
+    /**
+     * Gets the version section of the tag.
+     */
+    public function getVersion() : ?string
+    {
+        return $this->version;
+    }
+
+    /**
+     * Returns a string representation for this tag.
+     */
+    public function __toString() : string
+    {
+        if ($this->description) {
+            $description = $this->description->render();
+        } else {
+            $description = '';
+        }
+
+        $version = (string) $this->version;
+
+        return $version . ($description !== '' ? ($version !== '' ? ' ' : '') . $description : '');
+    }
+}
diff --git a/vendor/phpdocumentor/reflection-docblock/src/DocBlockFactory.php b/vendor/phpdocumentor/reflection-docblock/src/DocBlockFactory.php
new file mode 100644
index 0000000000000000000000000000000000000000..cf04e5a552f12f3c8f3965fa352d595c60cd2ad4
--- /dev/null
+++ b/vendor/phpdocumentor/reflection-docblock/src/DocBlockFactory.php
@@ -0,0 +1,286 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * This file is part of phpDocumentor.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ *
+ * @link      http://phpdoc.org
+ */
+
+namespace phpDocumentor\Reflection;
+
+use InvalidArgumentException;
+use LogicException;
+use phpDocumentor\Reflection\DocBlock\DescriptionFactory;
+use phpDocumentor\Reflection\DocBlock\StandardTagFactory;
+use phpDocumentor\Reflection\DocBlock\Tag;
+use phpDocumentor\Reflection\DocBlock\TagFactory;
+use Webmozart\Assert\Assert;
+use function array_shift;
+use function count;
+use function explode;
+use function is_object;
+use function method_exists;
+use function preg_match;
+use function preg_replace;
+use function str_replace;
+use function strpos;
+use function substr;
+use function trim;
+
+final class DocBlockFactory implements DocBlockFactoryInterface
+{
+    /** @var DocBlock\DescriptionFactory */
+    private $descriptionFactory;
+
+    /** @var DocBlock\TagFactory */
+    private $tagFactory;
+
+    /**
+     * Initializes this factory with the required subcontractors.
+     */
+    public function __construct(DescriptionFactory $descriptionFactory, TagFactory $tagFactory)
+    {
+        $this->descriptionFactory = $descriptionFactory;
+        $this->tagFactory         = $tagFactory;
+    }
+
+    /**
+     * Factory method for easy instantiation.
+     *
+     * @param array<string, class-string<Tag>> $additionalTags
+     */
+    public static function createInstance(array $additionalTags = []) : self
+    {
+        $fqsenResolver      = new FqsenResolver();
+        $tagFactory         = new StandardTagFactory($fqsenResolver);
+        $descriptionFactory = new DescriptionFactory($tagFactory);
+
+        $tagFactory->addService($descriptionFactory);
+        $tagFactory->addService(new TypeResolver($fqsenResolver));
+
+        $docBlockFactory = new self($descriptionFactory, $tagFactory);
+        foreach ($additionalTags as $tagName => $tagHandler) {
+            $docBlockFactory->registerTagHandler($tagName, $tagHandler);
+        }
+
+        return $docBlockFactory;
+    }
+
+    /**
+     * @param object|string $docblock A string containing the DocBlock to parse or an object supporting the
+     *                                getDocComment method (such as a ReflectionClass object).
+     */
+    public function create($docblock, ?Types\Context $context = null, ?Location $location = null) : DocBlock
+    {
+        if (is_object($docblock)) {
+            if (!method_exists($docblock, 'getDocComment')) {
+                $exceptionMessage = 'Invalid object passed; the given object must support the getDocComment method';
+
+                throw new InvalidArgumentException($exceptionMessage);
+            }
+
+            $docblock = $docblock->getDocComment();
+            Assert::string($docblock);
+        }
+
+        Assert::stringNotEmpty($docblock);
+
+        if ($context === null) {
+            $context = new Types\Context('');
+        }
+
+        $parts = $this->splitDocBlock($this->stripDocComment($docblock));
+
+        [$templateMarker, $summary, $description, $tags] = $parts;
+
+        return new DocBlock(
+            $summary,
+            $description ? $this->descriptionFactory->create($description, $context) : null,
+            $this->parseTagBlock($tags, $context),
+            $context,
+            $location,
+            $templateMarker === '#@+',
+            $templateMarker === '#@-'
+        );
+    }
+
+    /**
+     * @param class-string<Tag> $handler
+     */
+    public function registerTagHandler(string $tagName, string $handler) : void
+    {
+        $this->tagFactory->registerTagHandler($tagName, $handler);
+    }
+
+    /**
+     * Strips the asterisks from the DocBlock comment.
+     *
+     * @param string $comment String containing the comment text.
+     */
+    private function stripDocComment(string $comment) : string
+    {
+        $comment = preg_replace('#[ \t]*(?:\/\*\*|\*\/|\*)?[ \t]?(.*)?#u', '$1', $comment);
+        Assert::string($comment);
+        $comment = trim($comment);
+
+        // reg ex above is not able to remove */ from a single line docblock
+        if (substr($comment, -2) === '*/') {
+            $comment = trim(substr($comment, 0, -2));
+        }
+
+        return str_replace(["\r\n", "\r"], "\n", $comment);
+    }
+
+    // phpcs:disable
+    /**
+     * Splits the DocBlock into a template marker, summary, description and block of tags.
+     *
+     * @param string $comment Comment to split into the sub-parts.
+     *
+     * @return string[] containing the template marker (if any), summary, description and a string containing the tags.
+     *
+     * @author Mike van Riel <me@mikevanriel.com> for extending the regex with template marker support.
+     *
+     * @author Richard van Velzen (@_richardJ) Special thanks to Richard for the regex responsible for the split.
+     */
+    private function splitDocBlock(string $comment) : array
+    {
+        // phpcs:enable
+        // Performance improvement cheat: if the first character is an @ then only tags are in this DocBlock. This
+        // method does not split tags so we return this verbatim as the fourth result (tags). This saves us the
+        // performance impact of running a regular expression
+        if (strpos($comment, '@') === 0) {
+            return ['', '', '', $comment];
+        }
+
+        // clears all extra horizontal whitespace from the line endings to prevent parsing issues
+        $comment = preg_replace('/\h*$/Sum', '', $comment);
+        Assert::string($comment);
+        /*
+         * Splits the docblock into a template marker, summary, description and tags section.
+         *
+         * - The template marker is empty, #@+ or #@- if the DocBlock starts with either of those (a newline may
+         *   occur after it and will be stripped).
+         * - The short description is started from the first character until a dot is encountered followed by a
+         *   newline OR two consecutive newlines (horizontal whitespace is taken into account to consider spacing
+         *   errors). This is optional.
+         * - The long description, any character until a new line is encountered followed by an @ and word
+         *   characters (a tag). This is optional.
+         * - Tags; the remaining characters
+         *
+         * Big thanks to RichardJ for contributing this Regular Expression
+         */
+        preg_match(
+            '/
+            \A
+            # 1. Extract the template marker
+            (?:(\#\@\+|\#\@\-)\n?)?
+
+            # 2. Extract the summary
+            (?:
+              (?! @\pL ) # The summary may not start with an @
+              (
+                [^\n.]+
+                (?:
+                  (?! \. \n | \n{2} )     # End summary upon a dot followed by newline or two newlines
+                  [\n.]* (?! [ \t]* @\pL ) # End summary when an @ is found as first character on a new line
+                  [^\n.]+                 # Include anything else
+                )*
+                \.?
+              )?
+            )
+
+            # 3. Extract the description
+            (?:
+              \s*        # Some form of whitespace _must_ precede a description because a summary must be there
+              (?! @\pL ) # The description may not start with an @
+              (
+                [^\n]+
+                (?: \n+
+                  (?! [ \t]* @\pL ) # End description when an @ is found as first character on a new line
+                  [^\n]+            # Include anything else
+                )*
+              )
+            )?
+
+            # 4. Extract the tags (anything that follows)
+            (\s+ [\s\S]*)? # everything that follows
+            /ux',
+            $comment,
+            $matches
+        );
+        array_shift($matches);
+
+        while (count($matches) < 4) {
+            $matches[] = '';
+        }
+
+        return $matches;
+    }
+
+    /**
+     * Creates the tag objects.
+     *
+     * @param string        $tags    Tag block to parse.
+     * @param Types\Context $context Context of the parsed Tag
+     *
+     * @return DocBlock\Tag[]
+     */
+    private function parseTagBlock(string $tags, Types\Context $context) : array
+    {
+        $tags = $this->filterTagBlock($tags);
+        if ($tags === null) {
+            return [];
+        }
+
+        $result = [];
+        $lines  = $this->splitTagBlockIntoTagLines($tags);
+        foreach ($lines as $key => $tagLine) {
+            $result[$key] = $this->tagFactory->create(trim($tagLine), $context);
+        }
+
+        return $result;
+    }
+
+    /**
+     * @return string[]
+     */
+    private function splitTagBlockIntoTagLines(string $tags) : array
+    {
+        $result = [];
+        foreach (explode("\n", $tags) as $tagLine) {
+            if ($tagLine !== '' && strpos($tagLine, '@') === 0) {
+                $result[] = $tagLine;
+            } else {
+                $result[count($result) - 1] .= "\n" . $tagLine;
+            }
+        }
+
+        return $result;
+    }
+
+    private function filterTagBlock(string $tags) : ?string
+    {
+        $tags = trim($tags);
+        if (!$tags) {
+            return null;
+        }
+
+        if ($tags[0] !== '@') {
+            // @codeCoverageIgnoreStart
+            // Can't simulate this; this only happens if there is an error with the parsing of the DocBlock that
+            // we didn't foresee.
+
+            throw new LogicException('A tag block started with text instead of an at-sign(@): ' . $tags);
+
+            // @codeCoverageIgnoreEnd
+        }
+
+        return $tags;
+    }
+}
diff --git a/vendor/phpdocumentor/reflection-docblock/src/DocBlockFactoryInterface.php b/vendor/phpdocumentor/reflection-docblock/src/DocBlockFactoryInterface.php
new file mode 100644
index 0000000000000000000000000000000000000000..ef039a4d83c8808f6f5661c9db6623c32dc9b11b
--- /dev/null
+++ b/vendor/phpdocumentor/reflection-docblock/src/DocBlockFactoryInterface.php
@@ -0,0 +1,23 @@
+<?php
+
+declare(strict_types=1);
+
+namespace phpDocumentor\Reflection;
+
+use phpDocumentor\Reflection\DocBlock\Tag;
+
+// phpcs:ignore SlevomatCodingStandard.Classes.SuperfluousInterfaceNaming.SuperfluousSuffix
+interface DocBlockFactoryInterface
+{
+    /**
+     * Factory method for easy instantiation.
+     *
+     * @param array<string, class-string<Tag>> $additionalTags
+     */
+    public static function createInstance(array $additionalTags = []) : DocBlockFactory;
+
+    /**
+     * @param string|object $docblock
+     */
+    public function create($docblock, ?Types\Context $context = null, ?Location $location = null) : DocBlock;
+}
diff --git a/vendor/phpdocumentor/reflection-docblock/src/Exception/PcreException.php b/vendor/phpdocumentor/reflection-docblock/src/Exception/PcreException.php
new file mode 100644
index 0000000000000000000000000000000000000000..77aa40e13502ee09679bb0105b7b355d44095cbe
--- /dev/null
+++ b/vendor/phpdocumentor/reflection-docblock/src/Exception/PcreException.php
@@ -0,0 +1,38 @@
+<?php
+
+declare(strict_types=1);
+
+namespace phpDocumentor\Reflection\Exception;
+
+use InvalidArgumentException;
+use const PREG_BACKTRACK_LIMIT_ERROR;
+use const PREG_BAD_UTF8_ERROR;
+use const PREG_BAD_UTF8_OFFSET_ERROR;
+use const PREG_INTERNAL_ERROR;
+use const PREG_JIT_STACKLIMIT_ERROR;
+use const PREG_NO_ERROR;
+use const PREG_RECURSION_LIMIT_ERROR;
+
+final class PcreException extends InvalidArgumentException
+{
+    public static function createFromPhpError(int $errorCode) : self
+    {
+        switch ($errorCode) {
+            case PREG_BACKTRACK_LIMIT_ERROR:
+                return new self('Backtrack limit error');
+            case PREG_RECURSION_LIMIT_ERROR:
+                return new self('Recursion limit error');
+            case PREG_BAD_UTF8_ERROR:
+                return new self('Bad UTF8 error');
+            case PREG_BAD_UTF8_OFFSET_ERROR:
+                return new self('Bad UTF8 offset error');
+            case PREG_JIT_STACKLIMIT_ERROR:
+                return new self('Jit stacklimit error');
+            case PREG_NO_ERROR:
+            case PREG_INTERNAL_ERROR:
+            default:
+        }
+
+        return new self('Unknown Pcre error');
+    }
+}
diff --git a/vendor/phpdocumentor/reflection-docblock/src/Utils.php b/vendor/phpdocumentor/reflection-docblock/src/Utils.php
new file mode 100644
index 0000000000000000000000000000000000000000..d9b790b8f875a0f006406229a3fc553a1ecd6c36
--- /dev/null
+++ b/vendor/phpdocumentor/reflection-docblock/src/Utils.php
@@ -0,0 +1,57 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * This file is part of phpDocumentor.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ *
+ * @link      http://phpdoc.org
+ */
+
+namespace phpDocumentor\Reflection;
+
+use phpDocumentor\Reflection\Exception\PcreException;
+use function preg_last_error;
+use function preg_split as php_preg_split;
+
+abstract class Utils
+{
+    /**
+     * Wrapper function for phps preg_split
+     *
+     * This function is inspired by {@link https://github.com/thecodingmachine/safe/blob/master/generated/pcre.php}. But
+     * since this library is all about performance we decided to strip everything we don't need. Reducing the amount
+     * of files that have to be loaded, ect.
+     *
+     * @param string $pattern The pattern to search for, as a string.
+     * @param string $subject The input string.
+     * @param int|null $limit If specified, then only substrings up to limit are returned with the
+     *      rest of the string being placed in the last substring. A limit of -1 or 0 means "no limit".
+     * @param int $flags flags can be any combination of the following flags (combined with the | bitwise operator):
+     * *PREG_SPLIT_NO_EMPTY*
+     *      If this flag is set, only non-empty pieces will be returned by preg_split().
+     * *PREG_SPLIT_DELIM_CAPTURE*
+     *      If this flag is set, parenthesized expression in the delimiter pattern will be captured
+     *      and returned as well.
+     * *PREG_SPLIT_OFFSET_CAPTURE*
+     *      If this flag is set, for every occurring match the appendant string offset will also be returned.
+     *      Note that this changes the return value in an array where every element is an array consisting of the
+     *      matched string at offset 0 and its string offset into subject at offset 1.
+     *
+     * @return string[] Returns an array containing substrings of subject split along boundaries matched by pattern
+     *
+     * @throws PcreException
+     */
+    public static function pregSplit(string $pattern, string $subject, ?int $limit = -1, int $flags = 0) : array
+    {
+        $parts = php_preg_split($pattern, $subject, $limit, $flags);
+        if ($parts === false) {
+            throw PcreException::createFromPhpError(preg_last_error());
+        }
+
+        return $parts;
+    }
+}
diff --git a/vendor/phpdocumentor/type-resolver/LICENSE b/vendor/phpdocumentor/type-resolver/LICENSE
new file mode 100644
index 0000000000000000000000000000000000000000..792e4040f26f0347b3beb069d6ea070e6ae14a69
--- /dev/null
+++ b/vendor/phpdocumentor/type-resolver/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2010 Mike van Riel
+
+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/phpdocumentor/type-resolver/README.md b/vendor/phpdocumentor/type-resolver/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..f30d3a24e705fb4bea1a02e312a073b300537458
--- /dev/null
+++ b/vendor/phpdocumentor/type-resolver/README.md
@@ -0,0 +1,177 @@
+[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
+![](https://github.com/phpdocumentor/typeresolver/workflows/Qa%20workflow/badge.svg?branch=1.x)
+[![Coveralls Coverage](https://img.shields.io/coveralls/github/phpDocumentor/TypeResolver.svg)](https://coveralls.io/github/phpDocumentor/TypeResolver?branch=1.x)
+[![Scrutinizer Code Coverage](https://img.shields.io/scrutinizer/coverage/g/phpDocumentor/TypeResolver.svg)](https://scrutinizer-ci.com/g/phpDocumentor/TypeResolver/?branch=1.x)
+[![Scrutinizer Code Quality](https://img.shields.io/scrutinizer/g/phpDocumentor/TypeResolver.svg)](https://scrutinizer-ci.com/g/phpDocumentor/TypeResolver/?branch=1.x)
+![Packagist Version](https://img.shields.io/packagist/v/phpdocumentor/type-resolver?label=Packagist%20stable)
+![Packagist Version](https://img.shields.io/packagist/vpre/phpdocumentor/type-resolver?label=Packagist%20unstable)
+
+TypeResolver and FqsenResolver
+==============================
+
+The specification on types in DocBlocks (PSR-5) describes various keywords and special constructs
+but also how to statically resolve the partial name of a Class into a Fully Qualified Class Name (FQCN).
+
+PSR-5 also introduces an additional way to describe deeper elements than Classes, Interfaces and Traits 
+called the Fully Qualified Structural Element Name (FQSEN). Using this it is possible to refer to methods,
+properties and class constants but also functions and global constants.
+
+This package provides two Resolvers that are capable of 
+
+1. Returning a series of Value Object for given expression while resolving any partial class names, and 
+2. Returning an FQSEN object after resolving any partial Structural Element Names into Fully Qualified Structural 
+   Element names.
+
+## Installing
+
+The easiest way to install this library is with [Composer](https://getcomposer.org) using the following command:
+
+    $ composer require phpdocumentor/type-resolver
+
+## Examples
+
+Ready to dive in and don't want to read through all that text below? Just consult the [examples](examples) folder and check which type of action that your want to accomplish.
+
+## On Types and Element Names
+
+This component can be used in one of two ways
+ 
+1. To resolve a Type or
+2. To resolve a Fully Qualified Structural Element Name
+ 
+The big difference between these two is in the number of things it can resolve. 
+
+The TypeResolver can resolve:
+
+- a php primitive or pseudo-primitive such as a string or void (`@var string` or `@return void`).
+- a composite such as an array of string (`@var string[]`).
+- a compound such as a string or integer (`@var string|integer`).
+- an array expression (`@var (string|TypeResolver)[]`)
+- an object or interface such as the TypeResolver class (`@var TypeResolver` 
+  or `@var \phpDocumentor\Reflection\TypeResolver`)
+
+  > please note that if you want to pass partial class names that additional steps are necessary, see the 
+  > chapter `Resolving partial classes and FQSENs` for more information.
+
+Where the FqsenResolver can resolve:
+
+- Constant expressions (i.e. `@see \MyNamespace\MY_CONSTANT`)
+- Function expressions (i.e. `@see \MyNamespace\myFunction()`)
+- Class expressions (i.e. `@see \MyNamespace\MyClass`)
+- Interface expressions (i.e. `@see \MyNamespace\MyInterface`)
+- Trait expressions (i.e. `@see \MyNamespace\MyTrait`)
+- Class constant expressions (i.e. `@see \MyNamespace\MyClass::MY_CONSTANT`)
+- Property expressions (i.e. `@see \MyNamespace\MyClass::$myProperty`)
+- Method expressions (i.e. `@see \MyNamespace\MyClass::myMethod()`)
+
+## Resolving a type
+
+In order to resolve a type you will have to instantiate the class `\phpDocumentor\Reflection\TypeResolver` and call its `resolve` method like this:
+
+```php
+$typeResolver = new \phpDocumentor\Reflection\TypeResolver();
+$type = $typeResolver->resolve('string|integer');
+```
+
+In this example you will receive a Value Object of class `\phpDocumentor\Reflection\Types\Compound` that has two 
+elements, one of type `\phpDocumentor\Reflection\Types\String_` and one of type 
+`\phpDocumentor\Reflection\Types\Integer`.
+
+The real power of this resolver is in its capability to expand partial class names into fully qualified class names; but in order to do that we need an additional `\phpDocumentor\Reflection\Types\Context` class that will inform the resolver in which namespace the given expression occurs and which namespace aliases (or imports) apply.
+
+### Resolving nullable types
+
+Php 7.1 introduced nullable types e.g. `?string`. Type resolver will resolve the original type without the nullable notation `?`
+just like it would do without the `?`. After that the type is wrapped in a `\phpDocumentor\Reflection\Types\Nullable` object.
+The `Nullable` type has a method to fetch the actual type. 
+
+## Resolving an FQSEN
+
+A Fully Qualified Structural Element Name is a reference to another element in your code bases and can be resolved using the `\phpDocumentor\Reflection\FqsenResolver` class' `resolve` method, like this:
+
+```php
+$fqsenResolver = new \phpDocumentor\Reflection\FqsenResolver();
+$fqsen = $fqsenResolver->resolve('\phpDocumentor\Reflection\FqsenResolver::resolve()');
+```
+
+In this example we resolve a Fully Qualified Structural Element Name (meaning that it includes the full namespace, class name and element name) and receive a Value Object of type `\phpDocumentor\Reflection\Fqsen`.
+
+The real power of this resolver is in its capability to expand partial element names into Fully Qualified Structural Element Names; but in order to do that we need an additional `\phpDocumentor\Reflection\Types\Context` class that will inform the resolver in which namespace the given expression occurs and which namespace aliases (or imports) apply.
+
+## Resolving partial Classes and Structural Element Names
+
+Perhaps the best feature of this library is that it knows how to resolve partial class names into fully qualified class names.
+
+For example, you have this file:
+
+```php
+namespace My\Example;
+
+use phpDocumentor\Reflection\Types;
+
+class Classy
+{
+    /**
+     * @var Types\Context
+     * @see Classy::otherFunction()
+     */
+    public function __construct($context) {}
+    
+    public function otherFunction(){}
+}
+```
+
+Suppose that you would want to resolve (and expand) the type in the `@var` tag and the element name in the `@see` tag.
+
+For the resolvers to know how to expand partial names you have to provide a bit of _Context_ for them by instantiating a new class named `\phpDocumentor\Reflection\Types\Context` with the name of the namespace and the aliases that are in play.
+
+### Creating a Context
+
+You can do this by manually creating a Context like this:
+
+```php
+$context = new \phpDocumentor\Reflection\Types\Context(
+    '\My\Example', 
+    [ 'Types' => '\phpDocumentor\Reflection\Types']
+);
+```
+
+Or by using the `\phpDocumentor\Reflection\Types\ContextFactory` to instantiate a new context based on a Reflector object or by providing the namespace that you'd like to extract and the source code of the file in which the given type expression occurs.
+
+```php
+$contextFactory = new \phpDocumentor\Reflection\Types\ContextFactory();
+$context = $contextFactory->createFromReflector(new ReflectionMethod('\My\Example\Classy', '__construct'));
+```
+
+or
+
+```php
+$contextFactory = new \phpDocumentor\Reflection\Types\ContextFactory();
+$context = $contextFactory->createForNamespace('\My\Example', file_get_contents('My/Example/Classy.php'));
+```
+
+### Using the Context
+
+After you have obtained a Context it is just a matter of passing it along with the `resolve` method of either Resolver class as second argument and the Resolvers will take this into account when resolving partial names.
+
+To obtain the resolved class name for the `@var` tag in the example above you can do:
+
+```php
+$typeResolver = new \phpDocumentor\Reflection\TypeResolver();
+$type = $typeResolver->resolve('Types\Context', $context);
+```
+
+When you do this you will receive an object of class `\phpDocumentor\Reflection\Types\Object_` for which you can call the `getFqsen` method to receive a Value Object that represents the complete FQSEN. So that would be `phpDocumentor\Reflection\Types\Context`.
+
+> Why is the FQSEN wrapped in another object `Object_`?
+> 
+> The resolve method of the TypeResolver only returns object with the interface `Type` and the FQSEN is a common type that does not represent a Type. Also: in some cases a type can represent an "Untyped Object", meaning that it is an object (signified by the `object` keyword) but does not refer to a specific element using an FQSEN.
+
+Another example is on how to resolve the FQSEN of a method as can be seen with the `@see` tag in the example above. To resolve that you can do the following:
+
+```php
+$fqsenResolver = new \phpDocumentor\Reflection\FqsenResolver();
+$type = $fqsenResolver->resolve('Classy::otherFunction()', $context);
+```
+
+Because Classy is a Class in the current namespace its FQSEN will have the `My\Example` namespace and by calling the `resolve` method of the FQSEN Resolver you will receive an `Fqsen` object that refers to `\My\Example\Classy::otherFunction()`.
diff --git a/vendor/phpdocumentor/type-resolver/composer.json b/vendor/phpdocumentor/type-resolver/composer.json
new file mode 100644
index 0000000000000000000000000000000000000000..242ecbe39a4f3478adb2e1f9ae509bfadd7045b5
--- /dev/null
+++ b/vendor/phpdocumentor/type-resolver/composer.json
@@ -0,0 +1,34 @@
+{
+    "name": "phpdocumentor/type-resolver",
+    "description": "A PSR-5 based resolver of Class names, Types and Structural Element Names",
+    "type": "library",
+    "license": "MIT",
+    "authors": [
+        {
+          "name": "Mike van Riel",
+          "email": "me@mikevanriel.com"
+        }
+    ],
+    "require": {
+        "php": "^7.2 || ^8.0",
+        "phpdocumentor/reflection-common": "^2.0"
+    },
+    "require-dev": {
+        "ext-tokenizer": "*"
+    },
+    "autoload": {
+        "psr-4": {
+            "phpDocumentor\\Reflection\\": "src"
+        }
+    },
+    "autoload-dev": {
+        "psr-4": {
+            "phpDocumentor\\Reflection\\": ["tests/unit", "tests/benchmark"]
+        }
+    },
+    "extra": {
+        "branch-alias": {
+            "dev-1.x": "1.x-dev"
+        }
+    }
+}
diff --git a/vendor/phpdocumentor/type-resolver/phpbench.json b/vendor/phpdocumentor/type-resolver/phpbench.json
new file mode 100644
index 0000000000000000000000000000000000000000..ced1ebab47037ac2e82996d39e1eef831781852f
--- /dev/null
+++ b/vendor/phpdocumentor/type-resolver/phpbench.json
@@ -0,0 +1,10 @@
+{
+  "bootstrap": "vendor/autoload.php",
+  "path": "tests/benchmark",
+  "extensions": [
+    "Jaapio\\Blackfire\\Extension"
+  ],
+  "blackfire" : {
+    "env": "c12030d0-c177-47e2-b466-4994c40dc993"
+  }
+}
diff --git a/vendor/phpdocumentor/type-resolver/src/FqsenResolver.php b/vendor/phpdocumentor/type-resolver/src/FqsenResolver.php
new file mode 100644
index 0000000000000000000000000000000000000000..6447a0159d7102f4ca9ce089ddcc9ac8c6925b64
--- /dev/null
+++ b/vendor/phpdocumentor/type-resolver/src/FqsenResolver.php
@@ -0,0 +1,79 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * This file is part of phpDocumentor.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ *
+ * @link      http://phpdoc.org
+ */
+
+namespace phpDocumentor\Reflection;
+
+use InvalidArgumentException;
+use phpDocumentor\Reflection\Types\Context;
+use function explode;
+use function implode;
+use function strpos;
+
+/**
+ * Resolver for Fqsen using Context information
+ *
+ * @psalm-immutable
+ */
+class FqsenResolver
+{
+    /** @var string Definition of the NAMESPACE operator in PHP */
+    private const OPERATOR_NAMESPACE = '\\';
+
+    public function resolve(string $fqsen, ?Context $context = null) : Fqsen
+    {
+        if ($context === null) {
+            $context = new Context('');
+        }
+
+        if ($this->isFqsen($fqsen)) {
+            return new Fqsen($fqsen);
+        }
+
+        return $this->resolvePartialStructuralElementName($fqsen, $context);
+    }
+
+    /**
+     * Tests whether the given type is a Fully Qualified Structural Element Name.
+     */
+    private function isFqsen(string $type) : bool
+    {
+        return strpos($type, self::OPERATOR_NAMESPACE) === 0;
+    }
+
+    /**
+     * Resolves a partial Structural Element Name (i.e. `Reflection\DocBlock`) to its FQSEN representation
+     * (i.e. `\phpDocumentor\Reflection\DocBlock`) based on the Namespace and aliases mentioned in the Context.
+     *
+     * @throws InvalidArgumentException When type is not a valid FQSEN.
+     */
+    private function resolvePartialStructuralElementName(string $type, Context $context) : Fqsen
+    {
+        $typeParts = explode(self::OPERATOR_NAMESPACE, $type, 2);
+
+        $namespaceAliases = $context->getNamespaceAliases();
+
+        // if the first segment is not an alias; prepend namespace name and return
+        if (!isset($namespaceAliases[$typeParts[0]])) {
+            $namespace = $context->getNamespace();
+            if ($namespace !== '') {
+                $namespace .= self::OPERATOR_NAMESPACE;
+            }
+
+            return new Fqsen(self::OPERATOR_NAMESPACE . $namespace . $type);
+        }
+
+        $typeParts[0] = $namespaceAliases[$typeParts[0]];
+
+        return new Fqsen(self::OPERATOR_NAMESPACE . implode(self::OPERATOR_NAMESPACE, $typeParts));
+    }
+}
diff --git a/vendor/phpdocumentor/type-resolver/src/PseudoType.php b/vendor/phpdocumentor/type-resolver/src/PseudoType.php
new file mode 100644
index 0000000000000000000000000000000000000000..f94cff5b35778c0a4c8c15c793b8dde7502cc24d
--- /dev/null
+++ b/vendor/phpdocumentor/type-resolver/src/PseudoType.php
@@ -0,0 +1,19 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * This file is part of phpDocumentor.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ *
+ * @link      http://phpdoc.org
+ */
+
+namespace phpDocumentor\Reflection;
+
+interface PseudoType extends Type
+{
+    public function underlyingType() : Type;
+}
diff --git a/vendor/phpdocumentor/type-resolver/src/PseudoTypes/False_.php b/vendor/phpdocumentor/type-resolver/src/PseudoTypes/False_.php
new file mode 100644
index 0000000000000000000000000000000000000000..fea5baaf1ecd808f1e294161fdaefe6460c640d7
--- /dev/null
+++ b/vendor/phpdocumentor/type-resolver/src/PseudoTypes/False_.php
@@ -0,0 +1,39 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * This file is part of phpDocumentor.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ *
+ * @link https://phpdoc.org
+ */
+
+namespace phpDocumentor\Reflection\PseudoTypes;
+
+use phpDocumentor\Reflection\PseudoType;
+use phpDocumentor\Reflection\Type;
+use phpDocumentor\Reflection\Types\Boolean;
+use function class_alias;
+
+/**
+ * Value Object representing the PseudoType 'False', which is a Boolean type.
+ *
+ * @psalm-immutable
+ */
+final class False_ extends Boolean implements PseudoType
+{
+    public function underlyingType() : Type
+    {
+        return new Boolean();
+    }
+
+    public function __toString() : string
+    {
+        return 'false';
+    }
+}
+
+class_alias('\phpDocumentor\Reflection\PseudoTypes\False_', 'phpDocumentor\Reflection\Types\False_', false);
diff --git a/vendor/phpdocumentor/type-resolver/src/PseudoTypes/True_.php b/vendor/phpdocumentor/type-resolver/src/PseudoTypes/True_.php
new file mode 100644
index 0000000000000000000000000000000000000000..766c26c4b8dae2b7c0dcfa819eb44b99edc372f6
--- /dev/null
+++ b/vendor/phpdocumentor/type-resolver/src/PseudoTypes/True_.php
@@ -0,0 +1,39 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * This file is part of phpDocumentor.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ *
+ * @link https://phpdoc.org
+ */
+
+namespace phpDocumentor\Reflection\PseudoTypes;
+
+use phpDocumentor\Reflection\PseudoType;
+use phpDocumentor\Reflection\Type;
+use phpDocumentor\Reflection\Types\Boolean;
+use function class_alias;
+
+/**
+ * Value Object representing the PseudoType 'False', which is a Boolean type.
+ *
+ * @psalm-immutable
+ */
+final class True_ extends Boolean implements PseudoType
+{
+    public function underlyingType() : Type
+    {
+        return new Boolean();
+    }
+
+    public function __toString() : string
+    {
+        return 'true';
+    }
+}
+
+class_alias('\phpDocumentor\Reflection\PseudoTypes\True_', 'phpDocumentor\Reflection\Types\True_', false);
diff --git a/vendor/phpdocumentor/type-resolver/src/Type.php b/vendor/phpdocumentor/type-resolver/src/Type.php
new file mode 100644
index 0000000000000000000000000000000000000000..d2b86df00141345215a795a9dad30d549adc5274
--- /dev/null
+++ b/vendor/phpdocumentor/type-resolver/src/Type.php
@@ -0,0 +1,25 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * This file is part of phpDocumentor.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ *
+ * @link      http://phpdoc.org
+ */
+
+namespace phpDocumentor\Reflection;
+
+/**
+ * @psalm-immutable
+ */
+interface Type
+{
+    /**
+     * Returns a rendered output of the Type as it would be used in a DocBlock.
+     */
+    public function __toString() : string;
+}
diff --git a/vendor/phpdocumentor/type-resolver/src/TypeResolver.php b/vendor/phpdocumentor/type-resolver/src/TypeResolver.php
new file mode 100644
index 0000000000000000000000000000000000000000..07e1b8331da088f3249c36487101df95bc4802a2
--- /dev/null
+++ b/vendor/phpdocumentor/type-resolver/src/TypeResolver.php
@@ -0,0 +1,543 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * This file is part of phpDocumentor.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ *
+ * @link      http://phpdoc.org
+ */
+
+namespace phpDocumentor\Reflection;
+
+use ArrayIterator;
+use InvalidArgumentException;
+use phpDocumentor\Reflection\Types\Array_;
+use phpDocumentor\Reflection\Types\ClassString;
+use phpDocumentor\Reflection\Types\Collection;
+use phpDocumentor\Reflection\Types\Compound;
+use phpDocumentor\Reflection\Types\Context;
+use phpDocumentor\Reflection\Types\Expression;
+use phpDocumentor\Reflection\Types\Integer;
+use phpDocumentor\Reflection\Types\Intersection;
+use phpDocumentor\Reflection\Types\Iterable_;
+use phpDocumentor\Reflection\Types\Nullable;
+use phpDocumentor\Reflection\Types\Object_;
+use phpDocumentor\Reflection\Types\String_;
+use RuntimeException;
+use function array_key_exists;
+use function array_pop;
+use function array_values;
+use function class_exists;
+use function class_implements;
+use function count;
+use function end;
+use function in_array;
+use function key;
+use function preg_split;
+use function strpos;
+use function strtolower;
+use function trim;
+use const PREG_SPLIT_DELIM_CAPTURE;
+use const PREG_SPLIT_NO_EMPTY;
+
+final class TypeResolver
+{
+    /** @var string Definition of the ARRAY operator for types */
+    private const OPERATOR_ARRAY = '[]';
+
+    /** @var string Definition of the NAMESPACE operator in PHP */
+    private const OPERATOR_NAMESPACE = '\\';
+
+    /** @var int the iterator parser is inside a compound context */
+    private const PARSER_IN_COMPOUND = 0;
+
+    /** @var int the iterator parser is inside a nullable expression context */
+    private const PARSER_IN_NULLABLE = 1;
+
+    /** @var int the iterator parser is inside an array expression context */
+    private const PARSER_IN_ARRAY_EXPRESSION = 2;
+
+    /** @var int the iterator parser is inside a collection expression context */
+    private const PARSER_IN_COLLECTION_EXPRESSION = 3;
+
+    /**
+     * @var array<string, string> List of recognized keywords and unto which Value Object they map
+     * @psalm-var array<string, class-string<Type>>
+     */
+    private $keywords = [
+        'string' => Types\String_::class,
+        'class-string' => Types\ClassString::class,
+        'int' => Types\Integer::class,
+        'integer' => Types\Integer::class,
+        'bool' => Types\Boolean::class,
+        'boolean' => Types\Boolean::class,
+        'real' => Types\Float_::class,
+        'float' => Types\Float_::class,
+        'double' => Types\Float_::class,
+        'object' => Object_::class,
+        'mixed' => Types\Mixed_::class,
+        'array' => Array_::class,
+        'resource' => Types\Resource_::class,
+        'void' => Types\Void_::class,
+        'null' => Types\Null_::class,
+        'scalar' => Types\Scalar::class,
+        'callback' => Types\Callable_::class,
+        'callable' => Types\Callable_::class,
+        'false' => PseudoTypes\False_::class,
+        'true' => PseudoTypes\True_::class,
+        'self' => Types\Self_::class,
+        '$this' => Types\This::class,
+        'static' => Types\Static_::class,
+        'parent' => Types\Parent_::class,
+        'iterable' => Iterable_::class,
+    ];
+
+    /**
+     * @var FqsenResolver
+     * @psalm-readonly
+     */
+    private $fqsenResolver;
+
+    /**
+     * Initializes this TypeResolver with the means to create and resolve Fqsen objects.
+     */
+    public function __construct(?FqsenResolver $fqsenResolver = null)
+    {
+        $this->fqsenResolver = $fqsenResolver ?: new FqsenResolver();
+    }
+
+    /**
+     * Analyzes the given type and returns the FQCN variant.
+     *
+     * When a type is provided this method checks whether it is not a keyword or
+     * Fully Qualified Class Name. If so it will use the given namespace and
+     * aliases to expand the type to a FQCN representation.
+     *
+     * This method only works as expected if the namespace and aliases are set;
+     * no dynamic reflection is being performed here.
+     *
+     * @uses Context::getNamespaceAliases() to check whether the first part of the relative type name should not be
+     * replaced with another namespace.
+     * @uses Context::getNamespace()        to determine with what to prefix the type name.
+     *
+     * @param string $type The relative or absolute type.
+     */
+    public function resolve(string $type, ?Context $context = null) : Type
+    {
+        $type = trim($type);
+        if (!$type) {
+            throw new InvalidArgumentException('Attempted to resolve "' . $type . '" but it appears to be empty');
+        }
+
+        if ($context === null) {
+            $context = new Context('');
+        }
+
+        // split the type string into tokens `|`, `?`, `<`, `>`, `,`, `(`, `)`, `[]`, '<', '>' and type names
+        $tokens = preg_split(
+            '/(\\||\\?|<|>|&|, ?|\\(|\\)|\\[\\]+)/',
+            $type,
+            -1,
+            PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE
+        );
+
+        if ($tokens === false) {
+            throw new InvalidArgumentException('Unable to split the type string "' . $type . '" into tokens');
+        }
+
+        /** @var ArrayIterator<int, string|null> $tokenIterator */
+        $tokenIterator = new ArrayIterator($tokens);
+
+        return $this->parseTypes($tokenIterator, $context, self::PARSER_IN_COMPOUND);
+    }
+
+    /**
+     * Analyse each tokens and creates types
+     *
+     * @param ArrayIterator<int, string|null> $tokens        the iterator on tokens
+     * @param int                        $parserContext on of self::PARSER_* constants, indicating
+     * the context where we are in the parsing
+     */
+    private function parseTypes(ArrayIterator $tokens, Context $context, int $parserContext) : Type
+    {
+        $types = [];
+        $token = '';
+        $compoundToken = '|';
+        while ($tokens->valid()) {
+            $token = $tokens->current();
+            if ($token === null) {
+                throw new RuntimeException(
+                    'Unexpected nullable character'
+                );
+            }
+
+            if ($token === '|' || $token === '&') {
+                if (count($types) === 0) {
+                    throw new RuntimeException(
+                        'A type is missing before a type separator'
+                    );
+                }
+
+                if (!in_array($parserContext, [
+                    self::PARSER_IN_COMPOUND,
+                    self::PARSER_IN_ARRAY_EXPRESSION,
+                    self::PARSER_IN_COLLECTION_EXPRESSION,
+                ], true)
+                ) {
+                    throw new RuntimeException(
+                        'Unexpected type separator'
+                    );
+                }
+
+                $compoundToken = $token;
+                $tokens->next();
+            } elseif ($token === '?') {
+                if (!in_array($parserContext, [
+                    self::PARSER_IN_COMPOUND,
+                    self::PARSER_IN_ARRAY_EXPRESSION,
+                    self::PARSER_IN_COLLECTION_EXPRESSION,
+                ], true)
+                ) {
+                    throw new RuntimeException(
+                        'Unexpected nullable character'
+                    );
+                }
+
+                $tokens->next();
+                $type    = $this->parseTypes($tokens, $context, self::PARSER_IN_NULLABLE);
+                $types[] = new Nullable($type);
+            } elseif ($token === '(') {
+                $tokens->next();
+                $type = $this->parseTypes($tokens, $context, self::PARSER_IN_ARRAY_EXPRESSION);
+
+                $token = $tokens->current();
+                if ($token === null) { // Someone did not properly close their array expression ..
+                    break;
+                }
+
+                $tokens->next();
+
+                $resolvedType = new Expression($type);
+
+                $types[] = $resolvedType;
+            } elseif ($parserContext === self::PARSER_IN_ARRAY_EXPRESSION && $token[0] === ')') {
+                break;
+            } elseif ($token === '<') {
+                if (count($types) === 0) {
+                    throw new RuntimeException(
+                        'Unexpected collection operator "<", class name is missing'
+                    );
+                }
+
+                $classType = array_pop($types);
+                if ($classType !== null) {
+                    if ((string) $classType === 'class-string') {
+                        $types[] = $this->resolveClassString($tokens, $context);
+                    } else {
+                        $types[] = $this->resolveCollection($tokens, $classType, $context);
+                    }
+                }
+
+                $tokens->next();
+            } elseif ($parserContext === self::PARSER_IN_COLLECTION_EXPRESSION
+                && ($token === '>' || trim($token) === ',')
+            ) {
+                break;
+            } elseif ($token === self::OPERATOR_ARRAY) {
+                end($types);
+                $last = key($types);
+                $lastItem = $types[$last];
+                if ($lastItem instanceof Expression) {
+                    $lastItem = $lastItem->getValueType();
+                }
+
+                $types[$last] = new Array_($lastItem);
+
+                $tokens->next();
+            } else {
+                $type = $this->resolveSingleType($token, $context);
+                $tokens->next();
+                if ($parserContext === self::PARSER_IN_NULLABLE) {
+                    return $type;
+                }
+
+                $types[] = $type;
+            }
+        }
+
+        if ($token === '|' || $token === '&') {
+            throw new RuntimeException(
+                'A type is missing after a type separator'
+            );
+        }
+
+        if (count($types) === 0) {
+            if ($parserContext === self::PARSER_IN_NULLABLE) {
+                throw new RuntimeException(
+                    'A type is missing after a nullable character'
+                );
+            }
+
+            if ($parserContext === self::PARSER_IN_ARRAY_EXPRESSION) {
+                throw new RuntimeException(
+                    'A type is missing in an array expression'
+                );
+            }
+
+            if ($parserContext === self::PARSER_IN_COLLECTION_EXPRESSION) {
+                throw new RuntimeException(
+                    'A type is missing in a collection expression'
+                );
+            }
+        } elseif (count($types) === 1) {
+            return $types[0];
+        }
+
+        if ($compoundToken === '|') {
+            return new Compound(array_values($types));
+        }
+
+        return new Intersection(array_values($types));
+    }
+
+    /**
+     * resolve the given type into a type object
+     *
+     * @param string $type the type string, representing a single type
+     *
+     * @return Type|Array_|Object_
+     *
+     * @psalm-mutation-free
+     */
+    private function resolveSingleType(string $type, Context $context) : object
+    {
+        switch (true) {
+            case $this->isKeyword($type):
+                return $this->resolveKeyword($type);
+            case $this->isFqsen($type):
+                return $this->resolveTypedObject($type);
+            case $this->isPartialStructuralElementName($type):
+                return $this->resolveTypedObject($type, $context);
+
+            // @codeCoverageIgnoreStart
+            default:
+                // I haven't got the foggiest how the logic would come here but added this as a defense.
+                throw new RuntimeException(
+                    'Unable to resolve type "' . $type . '", there is no known method to resolve it'
+                );
+        }
+
+        // @codeCoverageIgnoreEnd
+    }
+
+    /**
+     * Adds a keyword to the list of Keywords and associates it with a specific Value Object.
+     *
+     * @psalm-param class-string<Type> $typeClassName
+     */
+    public function addKeyword(string $keyword, string $typeClassName) : void
+    {
+        if (!class_exists($typeClassName)) {
+            throw new InvalidArgumentException(
+                'The Value Object that needs to be created with a keyword "' . $keyword . '" must be an existing class'
+                . ' but we could not find the class ' . $typeClassName
+            );
+        }
+
+        if (!in_array(Type::class, class_implements($typeClassName), true)) {
+            throw new InvalidArgumentException(
+                'The class "' . $typeClassName . '" must implement the interface "phpDocumentor\Reflection\Type"'
+            );
+        }
+
+        $this->keywords[$keyword] = $typeClassName;
+    }
+
+    /**
+     * Detects whether the given type represents a PHPDoc keyword.
+     *
+     * @param string $type A relative or absolute type as defined in the phpDocumentor documentation.
+     *
+     * @psalm-mutation-free
+     */
+    private function isKeyword(string $type) : bool
+    {
+        return array_key_exists(strtolower($type), $this->keywords);
+    }
+
+    /**
+     * Detects whether the given type represents a relative structural element name.
+     *
+     * @param string $type A relative or absolute type as defined in the phpDocumentor documentation.
+     *
+     * @psalm-mutation-free
+     */
+    private function isPartialStructuralElementName(string $type) : bool
+    {
+        return ($type[0] !== self::OPERATOR_NAMESPACE) && !$this->isKeyword($type);
+    }
+
+    /**
+     * Tests whether the given type is a Fully Qualified Structural Element Name.
+     *
+     * @psalm-mutation-free
+     */
+    private function isFqsen(string $type) : bool
+    {
+        return strpos($type, self::OPERATOR_NAMESPACE) === 0;
+    }
+
+    /**
+     * Resolves the given keyword (such as `string`) into a Type object representing that keyword.
+     *
+     * @psalm-mutation-free
+     */
+    private function resolveKeyword(string $type) : Type
+    {
+        $className = $this->keywords[strtolower($type)];
+
+        return new $className();
+    }
+
+    /**
+     * Resolves the given FQSEN string into an FQSEN object.
+     *
+     * @psalm-mutation-free
+     */
+    private function resolveTypedObject(string $type, ?Context $context = null) : Object_
+    {
+        return new Object_($this->fqsenResolver->resolve($type, $context));
+    }
+
+    /**
+     * Resolves class string
+     *
+     * @param ArrayIterator<int, (string|null)> $tokens
+     */
+    private function resolveClassString(ArrayIterator $tokens, Context $context) : Type
+    {
+        $tokens->next();
+
+        $classType = $this->parseTypes($tokens, $context, self::PARSER_IN_COLLECTION_EXPRESSION);
+
+        if (!$classType instanceof Object_ || $classType->getFqsen() === null) {
+            throw new RuntimeException(
+                $classType . ' is not a class string'
+            );
+        }
+
+        $token = $tokens->current();
+        if ($token !== '>') {
+            if (empty($token)) {
+                throw new RuntimeException(
+                    'class-string: ">" is missing'
+                );
+            }
+
+            throw new RuntimeException(
+                'Unexpected character "' . $token . '", ">" is missing'
+            );
+        }
+
+        return new ClassString($classType->getFqsen());
+    }
+
+    /**
+     * Resolves the collection values and keys
+     *
+     * @param ArrayIterator<int, (string|null)> $tokens
+     *
+     * @return Array_|Iterable_|Collection
+     */
+    private function resolveCollection(ArrayIterator $tokens, Type $classType, Context $context) : Type
+    {
+        $isArray    = ((string) $classType === 'array');
+        $isIterable = ((string) $classType === 'iterable');
+
+        // allow only "array", "iterable" or class name before "<"
+        if (!$isArray && !$isIterable
+            && (!$classType instanceof Object_ || $classType->getFqsen() === null)) {
+            throw new RuntimeException(
+                $classType . ' is not a collection'
+            );
+        }
+
+        $tokens->next();
+
+        $valueType = $this->parseTypes($tokens, $context, self::PARSER_IN_COLLECTION_EXPRESSION);
+        $keyType   = null;
+
+        $token = $tokens->current();
+        if ($token !== null && trim($token) === ',') {
+            // if we have a comma, then we just parsed the key type, not the value type
+            $keyType = $valueType;
+            if ($isArray) {
+                // check the key type for an "array" collection. We allow only
+                // strings or integers.
+                if (!$keyType instanceof String_ &&
+                    !$keyType instanceof Integer &&
+                    !$keyType instanceof Compound
+                ) {
+                    throw new RuntimeException(
+                        'An array can have only integers or strings as keys'
+                    );
+                }
+
+                if ($keyType instanceof Compound) {
+                    foreach ($keyType->getIterator() as $item) {
+                        if (!$item instanceof String_ &&
+                            !$item instanceof Integer
+                        ) {
+                            throw new RuntimeException(
+                                'An array can have only integers or strings as keys'
+                            );
+                        }
+                    }
+                }
+            }
+
+            $tokens->next();
+            // now let's parse the value type
+            $valueType = $this->parseTypes($tokens, $context, self::PARSER_IN_COLLECTION_EXPRESSION);
+        }
+
+        $token = $tokens->current();
+        if ($token !== '>') {
+            if (empty($token)) {
+                throw new RuntimeException(
+                    'Collection: ">" is missing'
+                );
+            }
+
+            throw new RuntimeException(
+                'Unexpected character "' . $token . '", ">" is missing'
+            );
+        }
+
+        if ($isArray) {
+            return new Array_($valueType, $keyType);
+        }
+
+        if ($isIterable) {
+            return new Iterable_($valueType, $keyType);
+        }
+
+        if ($classType instanceof Object_) {
+            return $this->makeCollectionFromObject($classType, $valueType, $keyType);
+        }
+
+        throw new RuntimeException('Invalid $classType provided');
+    }
+
+    /**
+     * @psalm-pure
+     */
+    private function makeCollectionFromObject(Object_ $object, Type $valueType, ?Type $keyType = null) : Collection
+    {
+        return new Collection($object->getFqsen(), $valueType, $keyType);
+    }
+}
diff --git a/vendor/phpdocumentor/type-resolver/src/Types/AbstractList.php b/vendor/phpdocumentor/type-resolver/src/Types/AbstractList.php
new file mode 100644
index 0000000000000000000000000000000000000000..bbea4f1414711b5a51ceaa51ea625651ab4e94af
--- /dev/null
+++ b/vendor/phpdocumentor/type-resolver/src/Types/AbstractList.php
@@ -0,0 +1,83 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * This file is part of phpDocumentor.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ *
+ * @link      http://phpdoc.org
+ */
+
+namespace phpDocumentor\Reflection\Types;
+
+use phpDocumentor\Reflection\Type;
+
+/**
+ * Represents a list of values. This is an abstract class for Array_ and Collection.
+ *
+ * @psalm-immutable
+ */
+abstract class AbstractList implements Type
+{
+    /** @var Type */
+    protected $valueType;
+
+    /** @var Type|null */
+    protected $keyType;
+
+    /** @var Type */
+    protected $defaultKeyType;
+
+    /**
+     * Initializes this representation of an array with the given Type.
+     */
+    public function __construct(?Type $valueType = null, ?Type $keyType = null)
+    {
+        if ($valueType === null) {
+            $valueType = new Mixed_();
+        }
+
+        $this->valueType      = $valueType;
+        $this->defaultKeyType = new Compound([new String_(), new Integer()]);
+        $this->keyType        = $keyType;
+    }
+
+    /**
+     * Returns the type for the keys of this array.
+     */
+    public function getKeyType() : Type
+    {
+        return $this->keyType ?? $this->defaultKeyType;
+    }
+
+    /**
+     * Returns the value for the keys of this array.
+     */
+    public function getValueType() : Type
+    {
+        return $this->valueType;
+    }
+
+    /**
+     * Returns a rendered output of the Type as it would be used in a DocBlock.
+     */
+    public function __toString() : string
+    {
+        if ($this->keyType) {
+            return 'array<' . $this->keyType . ',' . $this->valueType . '>';
+        }
+
+        if ($this->valueType instanceof Mixed_) {
+            return 'array';
+        }
+
+        if ($this->valueType instanceof Compound) {
+            return '(' . $this->valueType . ')[]';
+        }
+
+        return $this->valueType . '[]';
+    }
+}
diff --git a/vendor/phpdocumentor/type-resolver/src/Types/AggregatedType.php b/vendor/phpdocumentor/type-resolver/src/Types/AggregatedType.php
new file mode 100644
index 0000000000000000000000000000000000000000..95222958310c1f4e5ae3a0644971efa23c942460
--- /dev/null
+++ b/vendor/phpdocumentor/type-resolver/src/Types/AggregatedType.php
@@ -0,0 +1,124 @@
+<?php
+/**
+ * This file is part of phpDocumentor.
+ *
+ *  For the full copyright and license information, please view the LICENSE
+ *  file that was distributed with this source code.
+ *
+ * @link      http://phpdoc.org
+ */
+
+declare(strict_types=1);
+
+namespace phpDocumentor\Reflection\Types;
+
+use ArrayIterator;
+use IteratorAggregate;
+use phpDocumentor\Reflection\Type;
+use function array_key_exists;
+use function implode;
+
+/**
+ * Base class for aggregated types like Compound and Intersection
+ *
+ * A Aggregated Type is not so much a special keyword or object reference but is a series of Types that are separated
+ * using separator.
+ *
+ * @psalm-immutable
+ * @template-implements IteratorAggregate<int, Type>
+ */
+abstract class AggregatedType implements Type, IteratorAggregate
+{
+    /**
+     * @psalm-allow-private-mutation
+     * @var array<int, Type>
+     */
+    private $types = [];
+
+    /** @var string */
+    private $token;
+
+    /**
+     * @param array<Type> $types
+     */
+    public function __construct(array $types, string $token)
+    {
+        foreach ($types as $type) {
+            $this->add($type);
+        }
+
+        $this->token = $token;
+    }
+
+    /**
+     * Returns the type at the given index.
+     */
+    public function get(int $index) : ?Type
+    {
+        if (!$this->has($index)) {
+            return null;
+        }
+
+        return $this->types[$index];
+    }
+
+    /**
+     * Tests if this compound type has a type with the given index.
+     */
+    public function has(int $index) : bool
+    {
+        return array_key_exists($index, $this->types);
+    }
+
+    /**
+     * Tests if this compound type contains the given type.
+     */
+    public function contains(Type $type) : bool
+    {
+        foreach ($this->types as $typePart) {
+            // if the type is duplicate; do not add it
+            if ((string) $typePart === (string) $type) {
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+    /**
+     * Returns a rendered output of the Type as it would be used in a DocBlock.
+     */
+    public function __toString() : string
+    {
+        return implode($this->token, $this->types);
+    }
+
+    /**
+     * @return ArrayIterator<int, Type>
+     */
+    public function getIterator() : ArrayIterator
+    {
+        return new ArrayIterator($this->types);
+    }
+
+    /**
+     * @psalm-suppress ImpureMethodCall
+     */
+    private function add(Type $type) : void
+    {
+        if ($type instanceof self) {
+            foreach ($type->getIterator() as $subType) {
+                $this->add($subType);
+            }
+
+            return;
+        }
+
+        // if the type is duplicate; do not add it
+        if ($this->contains($type)) {
+            return;
+        }
+
+        $this->types[] = $type;
+    }
+}
diff --git a/vendor/phpdocumentor/type-resolver/src/Types/Array_.php b/vendor/phpdocumentor/type-resolver/src/Types/Array_.php
new file mode 100644
index 0000000000000000000000000000000000000000..7f880e2db2732ab41c70ee078268025541802fae
--- /dev/null
+++ b/vendor/phpdocumentor/type-resolver/src/Types/Array_.php
@@ -0,0 +1,29 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * This file is part of phpDocumentor.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ *
+ * @link      http://phpdoc.org
+ */
+
+namespace phpDocumentor\Reflection\Types;
+
+/**
+ * Represents an array type as described in the PSR-5, the PHPDoc Standard.
+ *
+ * An array can be represented in two forms:
+ *
+ * 1. Untyped (`array`), where the key and value type is unknown and hence classified as 'Mixed_'.
+ * 2. Types (`string[]`), where the value type is provided by preceding an opening and closing square bracket with a
+ *    type name.
+ *
+ * @psalm-immutable
+ */
+final class Array_ extends AbstractList
+{
+}
diff --git a/vendor/phpdocumentor/type-resolver/src/Types/Boolean.php b/vendor/phpdocumentor/type-resolver/src/Types/Boolean.php
new file mode 100644
index 0000000000000000000000000000000000000000..9163b51b680457e7aa1caa27e72128da4bd4d764
--- /dev/null
+++ b/vendor/phpdocumentor/type-resolver/src/Types/Boolean.php
@@ -0,0 +1,32 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * This file is part of phpDocumentor.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ *
+ * @link      http://phpdoc.org
+ */
+
+namespace phpDocumentor\Reflection\Types;
+
+use phpDocumentor\Reflection\Type;
+
+/**
+ * Value Object representing a Boolean type.
+ *
+ * @psalm-immutable
+ */
+class Boolean implements Type
+{
+    /**
+     * Returns a rendered output of the Type as it would be used in a DocBlock.
+     */
+    public function __toString() : string
+    {
+        return 'bool';
+    }
+}
diff --git a/vendor/phpdocumentor/type-resolver/src/Types/Callable_.php b/vendor/phpdocumentor/type-resolver/src/Types/Callable_.php
new file mode 100644
index 0000000000000000000000000000000000000000..1522325e313ae6167b0c1042e38ce7f354189723
--- /dev/null
+++ b/vendor/phpdocumentor/type-resolver/src/Types/Callable_.php
@@ -0,0 +1,32 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * This file is part of phpDocumentor.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ *
+ * @link      http://phpdoc.org
+ */
+
+namespace phpDocumentor\Reflection\Types;
+
+use phpDocumentor\Reflection\Type;
+
+/**
+ * Value Object representing a Callable type.
+ *
+ * @psalm-immutable
+ */
+final class Callable_ implements Type
+{
+    /**
+     * Returns a rendered output of the Type as it would be used in a DocBlock.
+     */
+    public function __toString() : string
+    {
+        return 'callable';
+    }
+}
diff --git a/vendor/phpdocumentor/type-resolver/src/Types/ClassString.php b/vendor/phpdocumentor/type-resolver/src/Types/ClassString.php
new file mode 100644
index 0000000000000000000000000000000000000000..f847f17273e16b166767c9c60af29896c4d6a96d
--- /dev/null
+++ b/vendor/phpdocumentor/type-resolver/src/Types/ClassString.php
@@ -0,0 +1,56 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * This file is part of phpDocumentor.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ *
+ * @link      http://phpdoc.org
+ */
+
+namespace phpDocumentor\Reflection\Types;
+
+use phpDocumentor\Reflection\Fqsen;
+use phpDocumentor\Reflection\Type;
+
+/**
+ * Value Object representing the type 'string'.
+ *
+ * @psalm-immutable
+ */
+final class ClassString implements Type
+{
+    /** @var Fqsen|null */
+    private $fqsen;
+
+    /**
+     * Initializes this representation of a class string with the given Fqsen.
+     */
+    public function __construct(?Fqsen $fqsen = null)
+    {
+        $this->fqsen = $fqsen;
+    }
+
+    /**
+     * Returns the FQSEN associated with this object.
+     */
+    public function getFqsen() : ?Fqsen
+    {
+        return $this->fqsen;
+    }
+
+    /**
+     * Returns a rendered output of the Type as it would be used in a DocBlock.
+     */
+    public function __toString() : string
+    {
+        if ($this->fqsen === null) {
+            return 'class-string';
+        }
+
+        return 'class-string<' . (string) $this->fqsen . '>';
+    }
+}
diff --git a/vendor/phpdocumentor/type-resolver/src/Types/Collection.php b/vendor/phpdocumentor/type-resolver/src/Types/Collection.php
new file mode 100644
index 0000000000000000000000000000000000000000..84b4463a6e26bc682bbb91f9845830c72d554edf
--- /dev/null
+++ b/vendor/phpdocumentor/type-resolver/src/Types/Collection.php
@@ -0,0 +1,68 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * This file is part of phpDocumentor.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ *
+ * @link      http://phpdoc.org
+ */
+
+namespace phpDocumentor\Reflection\Types;
+
+use phpDocumentor\Reflection\Fqsen;
+use phpDocumentor\Reflection\Type;
+
+/**
+ * Represents a collection type as described in the PSR-5, the PHPDoc Standard.
+ *
+ * A collection can be represented in two forms:
+ *
+ * 1. `ACollectionObject<aValueType>`
+ * 2. `ACollectionObject<aValueType,aKeyType>`
+ *
+ * - ACollectionObject can be 'array' or an object that can act as an array
+ * - aValueType and aKeyType can be any type expression
+ *
+ * @psalm-immutable
+ */
+final class Collection extends AbstractList
+{
+    /** @var Fqsen|null */
+    private $fqsen;
+
+    /**
+     * Initializes this representation of an array with the given Type or Fqsen.
+     */
+    public function __construct(?Fqsen $fqsen, Type $valueType, ?Type $keyType = null)
+    {
+        parent::__construct($valueType, $keyType);
+
+        $this->fqsen = $fqsen;
+    }
+
+    /**
+     * Returns the FQSEN associated with this object.
+     */
+    public function getFqsen() : ?Fqsen
+    {
+        return $this->fqsen;
+    }
+
+    /**
+     * Returns a rendered output of the Type as it would be used in a DocBlock.
+     */
+    public function __toString() : string
+    {
+        $objectType = (string) ($this->fqsen ?? 'object');
+
+        if ($this->keyType === null) {
+            return $objectType . '<' . $this->valueType . '>';
+        }
+
+        return $objectType . '<' . $this->keyType . ',' . $this->valueType . '>';
+    }
+}
diff --git a/vendor/phpdocumentor/type-resolver/src/Types/Compound.php b/vendor/phpdocumentor/type-resolver/src/Types/Compound.php
new file mode 100644
index 0000000000000000000000000000000000000000..ad426cc2c03e43a05b4c50509920e219bc1d09a7
--- /dev/null
+++ b/vendor/phpdocumentor/type-resolver/src/Types/Compound.php
@@ -0,0 +1,38 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * This file is part of phpDocumentor.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ *
+ * @link      http://phpdoc.org
+ */
+
+namespace phpDocumentor\Reflection\Types;
+
+use phpDocumentor\Reflection\Type;
+
+/**
+ * Value Object representing a Compound Type.
+ *
+ * A Compound Type is not so much a special keyword or object reference but is a series of Types that are separated
+ * using an OR operator (`|`). This combination of types signifies that whatever is associated with this compound type
+ * may contain a value with any of the given types.
+ *
+ * @psalm-immutable
+ */
+final class Compound extends AggregatedType
+{
+    /**
+     * Initializes a compound type (i.e. `string|int`) and tests if the provided types all implement the Type interface.
+     *
+     * @param array<Type> $types
+     */
+    public function __construct(array $types)
+    {
+        parent::__construct($types, '|');
+    }
+}
diff --git a/vendor/phpdocumentor/type-resolver/src/Types/Context.php b/vendor/phpdocumentor/type-resolver/src/Types/Context.php
new file mode 100644
index 0000000000000000000000000000000000000000..c134d7cfd206b42ee4166c7d6bb7ecc059eebfa5
--- /dev/null
+++ b/vendor/phpdocumentor/type-resolver/src/Types/Context.php
@@ -0,0 +1,97 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * This file is part of phpDocumentor.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ *
+ * @link      http://phpdoc.org
+ */
+
+namespace phpDocumentor\Reflection\Types;
+
+use function strlen;
+use function substr;
+use function trim;
+
+/**
+ * Provides information about the Context in which the DocBlock occurs that receives this context.
+ *
+ * A DocBlock does not know of its own accord in which namespace it occurs and which namespace aliases are applicable
+ * for the block of code in which it is in. This information is however necessary to resolve Class names in tags since
+ * you can provide a short form or make use of namespace aliases.
+ *
+ * The phpDocumentor Reflection component knows how to create this class but if you use the DocBlock parser from your
+ * own application it is possible to generate a Context class using the ContextFactory; this will analyze the file in
+ * which an associated class resides for its namespace and imports.
+ *
+ * @see ContextFactory::createFromClassReflector()
+ * @see ContextFactory::createForNamespace()
+ *
+ * @psalm-immutable
+ */
+final class Context
+{
+    /** @var string The current namespace. */
+    private $namespace;
+
+    /**
+     * @var string[] List of namespace aliases => Fully Qualified Namespace.
+     * @psalm-var array<string, string>
+     */
+    private $namespaceAliases;
+
+    /**
+     * Initializes the new context and normalizes all passed namespaces to be in Qualified Namespace Name (QNN)
+     * format (without a preceding `\`).
+     *
+     * @param string   $namespace        The namespace where this DocBlock resides in.
+     * @param string[] $namespaceAliases List of namespace aliases => Fully Qualified Namespace.
+     *
+     * @psalm-param array<string, string> $namespaceAliases
+     */
+    public function __construct(string $namespace, array $namespaceAliases = [])
+    {
+        $this->namespace = $namespace !== 'global' && $namespace !== 'default'
+            ? trim($namespace, '\\')
+            : '';
+
+        foreach ($namespaceAliases as $alias => $fqnn) {
+            if ($fqnn[0] === '\\') {
+                $fqnn = substr($fqnn, 1);
+            }
+
+            if ($fqnn[strlen($fqnn) - 1] === '\\') {
+                $fqnn = substr($fqnn, 0, -1);
+            }
+
+            $namespaceAliases[$alias] = $fqnn;
+        }
+
+        $this->namespaceAliases = $namespaceAliases;
+    }
+
+    /**
+     * Returns the Qualified Namespace Name (thus without `\` in front) where the associated element is in.
+     */
+    public function getNamespace() : string
+    {
+        return $this->namespace;
+    }
+
+    /**
+     * Returns a list of Qualified Namespace Names (thus without `\` in front) that are imported, the keys represent
+     * the alias for the imported Namespace.
+     *
+     * @return string[]
+     *
+     * @psalm-return array<string, string>
+     */
+    public function getNamespaceAliases() : array
+    {
+        return $this->namespaceAliases;
+    }
+}
diff --git a/vendor/phpdocumentor/type-resolver/src/Types/ContextFactory.php b/vendor/phpdocumentor/type-resolver/src/Types/ContextFactory.php
new file mode 100644
index 0000000000000000000000000000000000000000..5d09d565ec73748d768c260a46cbd37b5b7bbb27
--- /dev/null
+++ b/vendor/phpdocumentor/type-resolver/src/Types/ContextFactory.php
@@ -0,0 +1,423 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * This file is part of phpDocumentor.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ *
+ * @link      http://phpdoc.org
+ */
+
+namespace phpDocumentor\Reflection\Types;
+
+use ArrayIterator;
+use InvalidArgumentException;
+use ReflectionClass;
+use ReflectionClassConstant;
+use ReflectionMethod;
+use ReflectionParameter;
+use ReflectionProperty;
+use Reflector;
+use RuntimeException;
+use UnexpectedValueException;
+use function define;
+use function defined;
+use function file_exists;
+use function file_get_contents;
+use function get_class;
+use function in_array;
+use function is_string;
+use function strrpos;
+use function substr;
+use function token_get_all;
+use function trim;
+use const T_AS;
+use const T_CLASS;
+use const T_CURLY_OPEN;
+use const T_DOLLAR_OPEN_CURLY_BRACES;
+use const T_NAMESPACE;
+use const T_NS_SEPARATOR;
+use const T_STRING;
+use const T_USE;
+
+if (!defined('T_NAME_QUALIFIED')) {
+    define('T_NAME_QUALIFIED', 'T_NAME_QUALIFIED');
+}
+
+if (!defined('T_NAME_FULLY_QUALIFIED')) {
+    define('T_NAME_FULLY_QUALIFIED', 'T_NAME_FULLY_QUALIFIED');
+}
+
+/**
+ * Convenience class to create a Context for DocBlocks when not using the Reflection Component of phpDocumentor.
+ *
+ * For a DocBlock to be able to resolve types that use partial namespace names or rely on namespace imports we need to
+ * provide a bit of context so that the DocBlock can read that and based on it decide how to resolve the types to
+ * Fully Qualified names.
+ *
+ * @see Context for more information.
+ */
+final class ContextFactory
+{
+    /** The literal used at the end of a use statement. */
+    private const T_LITERAL_END_OF_USE = ';';
+
+    /** The literal used between sets of use statements */
+    private const T_LITERAL_USE_SEPARATOR = ',';
+
+    /**
+     * Build a Context given a Class Reflection.
+     *
+     * @see Context for more information on Contexts.
+     */
+    public function createFromReflector(Reflector $reflector) : Context
+    {
+        if ($reflector instanceof ReflectionClass) {
+            //phpcs:ignore SlevomatCodingStandard.Commenting.InlineDocCommentDeclaration.MissingVariable
+            /** @var ReflectionClass<object> $reflector */
+
+            return $this->createFromReflectionClass($reflector);
+        }
+
+        if ($reflector instanceof ReflectionParameter) {
+            return $this->createFromReflectionParameter($reflector);
+        }
+
+        if ($reflector instanceof ReflectionMethod) {
+            return $this->createFromReflectionMethod($reflector);
+        }
+
+        if ($reflector instanceof ReflectionProperty) {
+            return $this->createFromReflectionProperty($reflector);
+        }
+
+        if ($reflector instanceof ReflectionClassConstant) {
+            return $this->createFromReflectionClassConstant($reflector);
+        }
+
+        throw new UnexpectedValueException('Unhandled \Reflector instance given:  ' . get_class($reflector));
+    }
+
+    private function createFromReflectionParameter(ReflectionParameter $parameter) : Context
+    {
+        $class = $parameter->getDeclaringClass();
+        if (!$class) {
+            throw new InvalidArgumentException('Unable to get class of ' . $parameter->getName());
+        }
+
+        //phpcs:ignore SlevomatCodingStandard.Commenting.InlineDocCommentDeclaration.MissingVariable
+        /** @var ReflectionClass<object> $class */
+
+        return $this->createFromReflectionClass($class);
+    }
+
+    private function createFromReflectionMethod(ReflectionMethod $method) : Context
+    {
+        //phpcs:ignore SlevomatCodingStandard.Commenting.InlineDocCommentDeclaration.MissingVariable
+        /** @var ReflectionClass<object> $class */
+        $class = $method->getDeclaringClass();
+
+        return $this->createFromReflectionClass($class);
+    }
+
+    private function createFromReflectionProperty(ReflectionProperty $property) : Context
+    {
+        //phpcs:ignore SlevomatCodingStandard.Commenting.InlineDocCommentDeclaration.MissingVariable
+        /** @var ReflectionClass<object> $class */
+        $class = $property->getDeclaringClass();
+
+        return $this->createFromReflectionClass($class);
+    }
+
+    private function createFromReflectionClassConstant(ReflectionClassConstant $constant) : Context
+    {
+        //phpcs:ignore SlevomatCodingStandard.Commenting.InlineDocCommentDeclaration.MissingVariable
+        /** @var ReflectionClass<object> $class */
+        $class = $constant->getDeclaringClass();
+
+        return $this->createFromReflectionClass($class);
+    }
+
+    /**
+     * @param ReflectionClass<object> $class
+     */
+    private function createFromReflectionClass(ReflectionClass $class) : Context
+    {
+        $fileName  = $class->getFileName();
+        $namespace = $class->getNamespaceName();
+
+        if (is_string($fileName) && file_exists($fileName)) {
+            $contents = file_get_contents($fileName);
+            if ($contents === false) {
+                throw new RuntimeException('Unable to read file "' . $fileName . '"');
+            }
+
+            return $this->createForNamespace($namespace, $contents);
+        }
+
+        return new Context($namespace, []);
+    }
+
+    /**
+     * Build a Context for a namespace in the provided file contents.
+     *
+     * @see Context for more information on Contexts.
+     *
+     * @param string $namespace    It does not matter if a `\` precedes the namespace name,
+     * this method first normalizes.
+     * @param string $fileContents The file's contents to retrieve the aliases from with the given namespace.
+     */
+    public function createForNamespace(string $namespace, string $fileContents) : Context
+    {
+        $namespace        = trim($namespace, '\\');
+        $useStatements    = [];
+        $currentNamespace = '';
+        $tokens           = new ArrayIterator(token_get_all($fileContents));
+
+        while ($tokens->valid()) {
+            $currentToken = $tokens->current();
+            switch ($currentToken[0]) {
+                case T_NAMESPACE:
+                    $currentNamespace = $this->parseNamespace($tokens);
+                    break;
+                case T_CLASS:
+                    // Fast-forward the iterator through the class so that any
+                    // T_USE tokens found within are skipped - these are not
+                    // valid namespace use statements so should be ignored.
+                    $braceLevel      = 0;
+                    $firstBraceFound = false;
+                    while ($tokens->valid() && ($braceLevel > 0 || !$firstBraceFound)) {
+                        $currentToken = $tokens->current();
+                        if ($currentToken === '{'
+                            || in_array($currentToken[0], [T_CURLY_OPEN, T_DOLLAR_OPEN_CURLY_BRACES], true)) {
+                            if (!$firstBraceFound) {
+                                $firstBraceFound = true;
+                            }
+
+                            ++$braceLevel;
+                        }
+
+                        if ($currentToken === '}') {
+                            --$braceLevel;
+                        }
+
+                        $tokens->next();
+                    }
+
+                    break;
+                case T_USE:
+                    if ($currentNamespace === $namespace) {
+                        $useStatements += $this->parseUseStatement($tokens);
+                    }
+
+                    break;
+            }
+
+            $tokens->next();
+        }
+
+        return new Context($namespace, $useStatements);
+    }
+
+    /**
+     * Deduce the name from tokens when we are at the T_NAMESPACE token.
+     *
+     * @param ArrayIterator<int, string|array{0:int,1:string,2:int}> $tokens
+     */
+    private function parseNamespace(ArrayIterator $tokens) : string
+    {
+        // skip to the first string or namespace separator
+        $this->skipToNextStringOrNamespaceSeparator($tokens);
+
+        $name = '';
+        $acceptedTokens = [T_STRING, T_NS_SEPARATOR, T_NAME_QUALIFIED];
+        while ($tokens->valid() && in_array($tokens->current()[0], $acceptedTokens, true)) {
+            $name .= $tokens->current()[1];
+            $tokens->next();
+        }
+
+        return $name;
+    }
+
+    /**
+     * Deduce the names of all imports when we are at the T_USE token.
+     *
+     * @param ArrayIterator<int, string|array{0:int,1:string,2:int}> $tokens
+     *
+     * @return string[]
+     *
+     * @psalm-return array<string, string>
+     */
+    private function parseUseStatement(ArrayIterator $tokens) : array
+    {
+        $uses = [];
+
+        while ($tokens->valid()) {
+            $this->skipToNextStringOrNamespaceSeparator($tokens);
+
+            $uses += $this->extractUseStatements($tokens);
+            $currentToken = $tokens->current();
+            if ($currentToken[0] === self::T_LITERAL_END_OF_USE) {
+                return $uses;
+            }
+        }
+
+        return $uses;
+    }
+
+    /**
+     * Fast-forwards the iterator as longs as we don't encounter a T_STRING or T_NS_SEPARATOR token.
+     *
+     * @param ArrayIterator<int, string|array{0:int,1:string,2:int}> $tokens
+     */
+    private function skipToNextStringOrNamespaceSeparator(ArrayIterator $tokens) : void
+    {
+        while ($tokens->valid()) {
+            $currentToken = $tokens->current();
+            if (in_array($currentToken[0], [T_STRING, T_NS_SEPARATOR], true)) {
+                break;
+            }
+
+            if ($currentToken[0] === T_NAME_QUALIFIED) {
+                break;
+            }
+
+            if (defined('T_NAME_FULLY_QUALIFIED') && $currentToken[0] === T_NAME_FULLY_QUALIFIED) {
+                break;
+            }
+
+            $tokens->next();
+        }
+    }
+
+    /**
+     * Deduce the namespace name and alias of an import when we are at the T_USE token or have not reached the end of
+     * a USE statement yet. This will return a key/value array of the alias => namespace.
+     *
+     * @param ArrayIterator<int, string|array{0:int,1:string,2:int}> $tokens
+     *
+     * @return string[]
+     *
+     * @psalm-suppress TypeDoesNotContainType
+     *
+     * @psalm-return array<string, string>
+     */
+    private function extractUseStatements(ArrayIterator $tokens) : array
+    {
+        $extractedUseStatements = [];
+        $groupedNs              = '';
+        $currentNs              = '';
+        $currentAlias           = '';
+        $state                  = 'start';
+
+        while ($tokens->valid()) {
+            $currentToken = $tokens->current();
+            $tokenId      = is_string($currentToken) ? $currentToken : $currentToken[0];
+            $tokenValue   = is_string($currentToken) ? null : $currentToken[1];
+            switch ($state) {
+                case 'start':
+                    switch ($tokenId) {
+                        case T_STRING:
+                        case T_NS_SEPARATOR:
+                            $currentNs   .= (string) $tokenValue;
+                            $currentAlias =  $tokenValue;
+                            break;
+                        case T_NAME_QUALIFIED:
+                        case T_NAME_FULLY_QUALIFIED:
+                            $currentNs   .= (string) $tokenValue;
+                            $currentAlias = substr(
+                                (string) $tokenValue,
+                                (int) (strrpos((string) $tokenValue, '\\')) + 1
+                            );
+                            break;
+                        case T_CURLY_OPEN:
+                        case '{':
+                            $state     = 'grouped';
+                            $groupedNs = $currentNs;
+                            break;
+                        case T_AS:
+                            $state = 'start-alias';
+                            break;
+                        case self::T_LITERAL_USE_SEPARATOR:
+                        case self::T_LITERAL_END_OF_USE:
+                            $state = 'end';
+                            break;
+                        default:
+                            break;
+                    }
+
+                    break;
+                case 'start-alias':
+                    switch ($tokenId) {
+                        case T_STRING:
+                            $currentAlias = $tokenValue;
+                            break;
+                        case self::T_LITERAL_USE_SEPARATOR:
+                        case self::T_LITERAL_END_OF_USE:
+                            $state = 'end';
+                            break;
+                        default:
+                            break;
+                    }
+
+                    break;
+                case 'grouped':
+                    switch ($tokenId) {
+                        case T_STRING:
+                        case T_NS_SEPARATOR:
+                            $currentNs   .= (string) $tokenValue;
+                            $currentAlias = $tokenValue;
+                            break;
+                        case T_AS:
+                            $state = 'grouped-alias';
+                            break;
+                        case self::T_LITERAL_USE_SEPARATOR:
+                            $state                                          = 'grouped';
+                            $extractedUseStatements[(string) $currentAlias] = $currentNs;
+                            $currentNs                                      = $groupedNs;
+                            $currentAlias                                   = '';
+                            break;
+                        case self::T_LITERAL_END_OF_USE:
+                            $state = 'end';
+                            break;
+                        default:
+                            break;
+                    }
+
+                    break;
+                case 'grouped-alias':
+                    switch ($tokenId) {
+                        case T_STRING:
+                            $currentAlias = $tokenValue;
+                            break;
+                        case self::T_LITERAL_USE_SEPARATOR:
+                            $state                                          = 'grouped';
+                            $extractedUseStatements[(string) $currentAlias] = $currentNs;
+                            $currentNs                                      = $groupedNs;
+                            $currentAlias                                   = '';
+                            break;
+                        case self::T_LITERAL_END_OF_USE:
+                            $state = 'end';
+                            break;
+                        default:
+                            break;
+                    }
+            }
+
+            if ($state === 'end') {
+                break;
+            }
+
+            $tokens->next();
+        }
+
+        if ($groupedNs !== $currentNs) {
+            $extractedUseStatements[(string) $currentAlias] = $currentNs;
+        }
+
+        return $extractedUseStatements;
+    }
+}
diff --git a/vendor/phpdocumentor/type-resolver/src/Types/Expression.php b/vendor/phpdocumentor/type-resolver/src/Types/Expression.php
new file mode 100644
index 0000000000000000000000000000000000000000..4a8ae1fcf783ef5589509259167552d6db631486
--- /dev/null
+++ b/vendor/phpdocumentor/type-resolver/src/Types/Expression.php
@@ -0,0 +1,51 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * This file is part of phpDocumentor.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ *
+ * @link      http://phpdoc.org
+ */
+
+namespace phpDocumentor\Reflection\Types;
+
+use phpDocumentor\Reflection\Type;
+
+/**
+ * Represents an expression type as described in the PSR-5, the PHPDoc Standard.
+ *
+ * @psalm-immutable
+ */
+final class Expression implements Type
+{
+    /** @var Type */
+    protected $valueType;
+
+    /**
+     * Initializes this representation of an array with the given Type.
+     */
+    public function __construct(Type $valueType)
+    {
+        $this->valueType = $valueType;
+    }
+
+    /**
+     * Returns the value for the keys of this array.
+     */
+    public function getValueType() : Type
+    {
+        return $this->valueType;
+    }
+
+    /**
+     * Returns a rendered output of the Type as it would be used in a DocBlock.
+     */
+    public function __toString() : string
+    {
+        return '(' . $this->valueType . ')';
+    }
+}
diff --git a/vendor/phpdocumentor/type-resolver/src/Types/Float_.php b/vendor/phpdocumentor/type-resolver/src/Types/Float_.php
new file mode 100644
index 0000000000000000000000000000000000000000..e70ce7dd5d3ed446464e2f45e045fa569e05ddb2
--- /dev/null
+++ b/vendor/phpdocumentor/type-resolver/src/Types/Float_.php
@@ -0,0 +1,32 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * This file is part of phpDocumentor.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ *
+ * @link      http://phpdoc.org
+ */
+
+namespace phpDocumentor\Reflection\Types;
+
+use phpDocumentor\Reflection\Type;
+
+/**
+ * Value Object representing a Float.
+ *
+ * @psalm-immutable
+ */
+final class Float_ implements Type
+{
+    /**
+     * Returns a rendered output of the Type as it would be used in a DocBlock.
+     */
+    public function __toString() : string
+    {
+        return 'float';
+    }
+}
diff --git a/vendor/phpdocumentor/type-resolver/src/Types/Integer.php b/vendor/phpdocumentor/type-resolver/src/Types/Integer.php
new file mode 100644
index 0000000000000000000000000000000000000000..2cfd7e9e757c6287346fae407f4d99a220cd5d41
--- /dev/null
+++ b/vendor/phpdocumentor/type-resolver/src/Types/Integer.php
@@ -0,0 +1,32 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * This file is part of phpDocumentor.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ *
+ * @link      http://phpdoc.org
+ */
+
+namespace phpDocumentor\Reflection\Types;
+
+use phpDocumentor\Reflection\Type;
+
+/**
+ * Value object representing Integer type
+ *
+ * @psalm-immutable
+ */
+final class Integer implements Type
+{
+    /**
+     * Returns a rendered output of the Type as it would be used in a DocBlock.
+     */
+    public function __toString() : string
+    {
+        return 'int';
+    }
+}
diff --git a/vendor/phpdocumentor/type-resolver/src/Types/Intersection.php b/vendor/phpdocumentor/type-resolver/src/Types/Intersection.php
new file mode 100644
index 0000000000000000000000000000000000000000..ced37b6262b6f5d15803ed7529e2760529bf8933
--- /dev/null
+++ b/vendor/phpdocumentor/type-resolver/src/Types/Intersection.php
@@ -0,0 +1,37 @@
+<?php
+/**
+ * This file is part of phpDocumentor.
+ *
+ *  For the full copyright and license information, please view the LICENSE
+ *  file that was distributed with this source code.
+ *
+ *  @link      http://phpdoc.org
+ */
+
+declare(strict_types=1);
+
+namespace phpDocumentor\Reflection\Types;
+
+use phpDocumentor\Reflection\Type;
+
+/**
+ * Value Object representing a Compound Type.
+ *
+ * A Intersection Type is not so much a special keyword or object reference but is a series of Types that are separated
+ * using an AND operator (`&`). This combination of types signifies that whatever is associated with this Intersection
+ * type may contain a value with any of the given types.
+ *
+ * @psalm-immutable
+ */
+final class Intersection extends AggregatedType
+{
+    /**
+     * Initializes a intersection type (i.e. `\A&\B`) and tests if the provided types all implement the Type interface.
+     *
+     * @param array<Type> $types
+     */
+    public function __construct(array $types)
+    {
+        parent::__construct($types, '&');
+    }
+}
diff --git a/vendor/phpdocumentor/type-resolver/src/Types/Iterable_.php b/vendor/phpdocumentor/type-resolver/src/Types/Iterable_.php
new file mode 100644
index 0000000000000000000000000000000000000000..a03a7cd3f0195372319fbf273aef6b5d3637346e
--- /dev/null
+++ b/vendor/phpdocumentor/type-resolver/src/Types/Iterable_.php
@@ -0,0 +1,38 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * This file is part of phpDocumentor.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ *
+ * @link      http://phpdoc.org
+ */
+
+namespace phpDocumentor\Reflection\Types;
+
+/**
+ * Value Object representing iterable type
+ *
+ * @psalm-immutable
+ */
+final class Iterable_ extends AbstractList
+{
+    /**
+     * Returns a rendered output of the Type as it would be used in a DocBlock.
+     */
+    public function __toString() : string
+    {
+        if ($this->keyType) {
+            return 'iterable<' . $this->keyType . ',' . $this->valueType . '>';
+        }
+
+        if ($this->valueType instanceof Mixed_) {
+            return 'iterable';
+        }
+
+        return 'iterable<' . $this->valueType . '>';
+    }
+}
diff --git a/vendor/phpdocumentor/type-resolver/src/Types/Mixed_.php b/vendor/phpdocumentor/type-resolver/src/Types/Mixed_.php
new file mode 100644
index 0000000000000000000000000000000000000000..2fedff4009b559e8d61b759ac93c62ab0e2be424
--- /dev/null
+++ b/vendor/phpdocumentor/type-resolver/src/Types/Mixed_.php
@@ -0,0 +1,32 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * This file is part of phpDocumentor.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ *
+ * @link      http://phpdoc.org
+ */
+
+namespace phpDocumentor\Reflection\Types;
+
+use phpDocumentor\Reflection\Type;
+
+/**
+ * Value Object representing an unknown, or mixed, type.
+ *
+ * @psalm-immutable
+ */
+final class Mixed_ implements Type
+{
+    /**
+     * Returns a rendered output of the Type as it would be used in a DocBlock.
+     */
+    public function __toString() : string
+    {
+        return 'mixed';
+    }
+}
diff --git a/vendor/phpdocumentor/type-resolver/src/Types/Null_.php b/vendor/phpdocumentor/type-resolver/src/Types/Null_.php
new file mode 100644
index 0000000000000000000000000000000000000000..f5994d9ad6c85f32fd42f02bacde222401aa28b2
--- /dev/null
+++ b/vendor/phpdocumentor/type-resolver/src/Types/Null_.php
@@ -0,0 +1,32 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * This file is part of phpDocumentor.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ *
+ * @link      http://phpdoc.org
+ */
+
+namespace phpDocumentor\Reflection\Types;
+
+use phpDocumentor\Reflection\Type;
+
+/**
+ * Value Object representing a null value or type.
+ *
+ * @psalm-immutable
+ */
+final class Null_ implements Type
+{
+    /**
+     * Returns a rendered output of the Type as it would be used in a DocBlock.
+     */
+    public function __toString() : string
+    {
+        return 'null';
+    }
+}
diff --git a/vendor/phpdocumentor/type-resolver/src/Types/Nullable.php b/vendor/phpdocumentor/type-resolver/src/Types/Nullable.php
new file mode 100644
index 0000000000000000000000000000000000000000..80aaf4ecc6df9d4f9a63c985f4cdcde492cdceb8
--- /dev/null
+++ b/vendor/phpdocumentor/type-resolver/src/Types/Nullable.php
@@ -0,0 +1,51 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * This file is part of phpDocumentor.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ *
+ * @link      http://phpdoc.org
+ */
+
+namespace phpDocumentor\Reflection\Types;
+
+use phpDocumentor\Reflection\Type;
+
+/**
+ * Value Object representing a nullable type. The real type is wrapped.
+ *
+ * @psalm-immutable
+ */
+final class Nullable implements Type
+{
+    /** @var Type The actual type that is wrapped */
+    private $realType;
+
+    /**
+     * Initialises this nullable type using the real type embedded
+     */
+    public function __construct(Type $realType)
+    {
+        $this->realType = $realType;
+    }
+
+    /**
+     * Provide access to the actual type directly, if needed.
+     */
+    public function getActualType() : Type
+    {
+        return $this->realType;
+    }
+
+    /**
+     * Returns a rendered output of the Type as it would be used in a DocBlock.
+     */
+    public function __toString() : string
+    {
+        return '?' . $this->realType->__toString();
+    }
+}
diff --git a/vendor/phpdocumentor/type-resolver/src/Types/Object_.php b/vendor/phpdocumentor/type-resolver/src/Types/Object_.php
new file mode 100644
index 0000000000000000000000000000000000000000..4cfe2a0c32273651e62050c407a9078deb15607c
--- /dev/null
+++ b/vendor/phpdocumentor/type-resolver/src/Types/Object_.php
@@ -0,0 +1,68 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * This file is part of phpDocumentor.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ *
+ * @link      http://phpdoc.org
+ */
+
+namespace phpDocumentor\Reflection\Types;
+
+use InvalidArgumentException;
+use phpDocumentor\Reflection\Fqsen;
+use phpDocumentor\Reflection\Type;
+use function strpos;
+
+/**
+ * Value Object representing an object.
+ *
+ * An object can be either typed or untyped. When an object is typed it means that it has an identifier, the FQSEN,
+ * pointing to an element in PHP. Object types that are untyped do not refer to a specific class but represent objects
+ * in general.
+ *
+ * @psalm-immutable
+ */
+final class Object_ implements Type
+{
+    /** @var Fqsen|null */
+    private $fqsen;
+
+    /**
+     * Initializes this object with an optional FQSEN, if not provided this object is considered 'untyped'.
+     *
+     * @throws InvalidArgumentException When provided $fqsen is not a valid type.
+     */
+    public function __construct(?Fqsen $fqsen = null)
+    {
+        if (strpos((string) $fqsen, '::') !== false || strpos((string) $fqsen, '()') !== false) {
+            throw new InvalidArgumentException(
+                'Object types can only refer to a class, interface or trait but a method, function, constant or '
+                . 'property was received: ' . (string) $fqsen
+            );
+        }
+
+        $this->fqsen = $fqsen;
+    }
+
+    /**
+     * Returns the FQSEN associated with this object.
+     */
+    public function getFqsen() : ?Fqsen
+    {
+        return $this->fqsen;
+    }
+
+    public function __toString() : string
+    {
+        if ($this->fqsen) {
+            return (string) $this->fqsen;
+        }
+
+        return 'object';
+    }
+}
diff --git a/vendor/phpdocumentor/type-resolver/src/Types/Parent_.php b/vendor/phpdocumentor/type-resolver/src/Types/Parent_.php
new file mode 100644
index 0000000000000000000000000000000000000000..08900abce9950a3dbcbeeee79c3e70c1ec537e65
--- /dev/null
+++ b/vendor/phpdocumentor/type-resolver/src/Types/Parent_.php
@@ -0,0 +1,34 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * This file is part of phpDocumentor.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ *
+ * @link      http://phpdoc.org
+ */
+
+namespace phpDocumentor\Reflection\Types;
+
+use phpDocumentor\Reflection\Type;
+
+/**
+ * Value Object representing the 'parent' type.
+ *
+ * Parent, as a Type, represents the parent class of class in which the associated element was defined.
+ *
+ * @psalm-immutable
+ */
+final class Parent_ implements Type
+{
+    /**
+     * Returns a rendered output of the Type as it would be used in a DocBlock.
+     */
+    public function __toString() : string
+    {
+        return 'parent';
+    }
+}
diff --git a/vendor/phpdocumentor/type-resolver/src/Types/Resource_.php b/vendor/phpdocumentor/type-resolver/src/Types/Resource_.php
new file mode 100644
index 0000000000000000000000000000000000000000..2d4a794c2b9221b36115d25719b2d10ad5416fd6
--- /dev/null
+++ b/vendor/phpdocumentor/type-resolver/src/Types/Resource_.php
@@ -0,0 +1,32 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * This file is part of phpDocumentor.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ *
+ * @link      http://phpdoc.org
+ */
+
+namespace phpDocumentor\Reflection\Types;
+
+use phpDocumentor\Reflection\Type;
+
+/**
+ * Value Object representing the 'resource' Type.
+ *
+ * @psalm-immutable
+ */
+final class Resource_ implements Type
+{
+    /**
+     * Returns a rendered output of the Type as it would be used in a DocBlock.
+     */
+    public function __toString() : string
+    {
+        return 'resource';
+    }
+}
diff --git a/vendor/phpdocumentor/type-resolver/src/Types/Scalar.php b/vendor/phpdocumentor/type-resolver/src/Types/Scalar.php
new file mode 100644
index 0000000000000000000000000000000000000000..00ac369144d7ce3091f177e8bf2b6857b364d88d
--- /dev/null
+++ b/vendor/phpdocumentor/type-resolver/src/Types/Scalar.php
@@ -0,0 +1,32 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * This file is part of phpDocumentor.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ *
+ * @link      http://phpdoc.org
+ */
+
+namespace phpDocumentor\Reflection\Types;
+
+use phpDocumentor\Reflection\Type;
+
+/**
+ * Value Object representing the 'scalar' pseudo-type, which is either a string, integer, float or boolean.
+ *
+ * @psalm-immutable
+ */
+final class Scalar implements Type
+{
+    /**
+     * Returns a rendered output of the Type as it would be used in a DocBlock.
+     */
+    public function __toString() : string
+    {
+        return 'scalar';
+    }
+}
diff --git a/vendor/phpdocumentor/type-resolver/src/Types/Self_.php b/vendor/phpdocumentor/type-resolver/src/Types/Self_.php
new file mode 100644
index 0000000000000000000000000000000000000000..7fa13fa5e98ff024fa1b428124e4e9b84207ad06
--- /dev/null
+++ b/vendor/phpdocumentor/type-resolver/src/Types/Self_.php
@@ -0,0 +1,34 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * This file is part of phpDocumentor.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ *
+ * @link      http://phpdoc.org
+ */
+
+namespace phpDocumentor\Reflection\Types;
+
+use phpDocumentor\Reflection\Type;
+
+/**
+ * Value Object representing the 'self' type.
+ *
+ * Self, as a Type, represents the class in which the associated element was defined.
+ *
+ * @psalm-immutable
+ */
+final class Self_ implements Type
+{
+    /**
+     * Returns a rendered output of the Type as it would be used in a DocBlock.
+     */
+    public function __toString() : string
+    {
+        return 'self';
+    }
+}
diff --git a/vendor/phpdocumentor/type-resolver/src/Types/Static_.php b/vendor/phpdocumentor/type-resolver/src/Types/Static_.php
new file mode 100644
index 0000000000000000000000000000000000000000..568400ce5806fbaec64deefcd24551badcb32245
--- /dev/null
+++ b/vendor/phpdocumentor/type-resolver/src/Types/Static_.php
@@ -0,0 +1,39 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * This file is part of phpDocumentor.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ *
+ * @link      http://phpdoc.org
+ */
+
+namespace phpDocumentor\Reflection\Types;
+
+use phpDocumentor\Reflection\Type;
+
+/**
+ * Value Object representing the 'static' type.
+ *
+ * Self, as a Type, represents the class in which the associated element was called. This differs from self as self does
+ * not take inheritance into account but static means that the return type is always that of the class of the called
+ * element.
+ *
+ * See the documentation on late static binding in the PHP Documentation for more information on the difference between
+ * static and self.
+ *
+ * @psalm-immutable
+ */
+final class Static_ implements Type
+{
+    /**
+     * Returns a rendered output of the Type as it would be used in a DocBlock.
+     */
+    public function __toString() : string
+    {
+        return 'static';
+    }
+}
diff --git a/vendor/phpdocumentor/type-resolver/src/Types/String_.php b/vendor/phpdocumentor/type-resolver/src/Types/String_.php
new file mode 100644
index 0000000000000000000000000000000000000000..6b92e413d446391ed536ecd3ca7e684241641352
--- /dev/null
+++ b/vendor/phpdocumentor/type-resolver/src/Types/String_.php
@@ -0,0 +1,32 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * This file is part of phpDocumentor.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ *
+ * @link      http://phpdoc.org
+ */
+
+namespace phpDocumentor\Reflection\Types;
+
+use phpDocumentor\Reflection\Type;
+
+/**
+ * Value Object representing the type 'string'.
+ *
+ * @psalm-immutable
+ */
+final class String_ implements Type
+{
+    /**
+     * Returns a rendered output of the Type as it would be used in a DocBlock.
+     */
+    public function __toString() : string
+    {
+        return 'string';
+    }
+}
diff --git a/vendor/phpdocumentor/type-resolver/src/Types/This.php b/vendor/phpdocumentor/type-resolver/src/Types/This.php
new file mode 100644
index 0000000000000000000000000000000000000000..58cb3af05781a72cac472254087534c73ee036a8
--- /dev/null
+++ b/vendor/phpdocumentor/type-resolver/src/Types/This.php
@@ -0,0 +1,35 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * This file is part of phpDocumentor.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ *
+ * @link      http://phpdoc.org
+ */
+
+namespace phpDocumentor\Reflection\Types;
+
+use phpDocumentor\Reflection\Type;
+
+/**
+ * Value Object representing the '$this' pseudo-type.
+ *
+ * $this, as a Type, represents the instance of the class associated with the element as it was called. $this is
+ * commonly used when documenting fluent interfaces since it represents that the same object is returned.
+ *
+ * @psalm-immutable
+ */
+final class This implements Type
+{
+    /**
+     * Returns a rendered output of the Type as it would be used in a DocBlock.
+     */
+    public function __toString() : string
+    {
+        return '$this';
+    }
+}
diff --git a/vendor/phpdocumentor/type-resolver/src/Types/Void_.php b/vendor/phpdocumentor/type-resolver/src/Types/Void_.php
new file mode 100644
index 0000000000000000000000000000000000000000..5cabad50521281a775e9f42d5458d85d1b5d8072
--- /dev/null
+++ b/vendor/phpdocumentor/type-resolver/src/Types/Void_.php
@@ -0,0 +1,35 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * This file is part of phpDocumentor.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ *
+ * @link      http://phpdoc.org
+ */
+
+namespace phpDocumentor\Reflection\Types;
+
+use phpDocumentor\Reflection\Type;
+
+/**
+ * Value Object representing the pseudo-type 'void'.
+ *
+ * Void is generally only used when working with return types as it signifies that the method intentionally does not
+ * return any value.
+ *
+ * @psalm-immutable
+ */
+final class Void_ implements Type
+{
+    /**
+     * Returns a rendered output of the Type as it would be used in a DocBlock.
+     */
+    public function __toString() : string
+    {
+        return 'void';
+    }
+}
diff --git a/vendor/phpmailer/phpmailer/README.md b/vendor/phpmailer/phpmailer/README.md
index 6270646395507ebbca63c7709848b9548ca4f28a..c287e307a6c844969d17c3ba1d8dae731086c598 100644
--- a/vendor/phpmailer/phpmailer/README.md
+++ b/vendor/phpmailer/phpmailer/README.md
@@ -6,7 +6,7 @@ Build status: [![Build Status](https://travis-ci.org/PHPMailer/PHPMailer.svg)](h
 [![Scrutinizer Quality Score](https://scrutinizer-ci.com/g/PHPMailer/PHPMailer/badges/quality-score.png?s=3758e21d279becdf847a557a56a3ed16dfec9d5d)](https://scrutinizer-ci.com/g/PHPMailer/PHPMailer/)
 [![Code Coverage](https://scrutinizer-ci.com/g/PHPMailer/PHPMailer/badges/coverage.png?s=3fe6ca5fe8cd2cdf96285756e42932f7ca256962)](https://scrutinizer-ci.com/g/PHPMailer/PHPMailer/)
 
-[![Latest Stable Version](https://poser.pugx.org/phpmailer/phpmailer/v/stable.svg)](https://packagist.org/packages/phpmailer/phpmailer) [![Total Downloads](https://poser.pugx.org/phpmailer/phpmailer/downloads)](https://packagist.org/packages/phpmailer/phpmailer) [![Latest Unstable Version](https://poser.pugx.org/phpmailer/phpmailer/v/unstable.svg)](https://packagist.org/packages/phpmailer/phpmailer) [![License](https://poser.pugx.org/phpmailer/phpmailer/license.svg)](https://packagist.org/packages/phpmailer/phpmailer)
+[![Latest Stable Version](https://poser.pugx.org/phpmailer/phpmailer/v/stable.svg)](https://packagist.org/packages/phpmailer/phpmailer) [![Total Downloads](https://poser.pugx.org/phpmailer/phpmailer/downloads)](https://packagist.org/packages/phpmailer/phpmailer) [![Latest Unstable Version](https://poser.pugx.org/phpmailer/phpmailer/v/unstable.svg)](https://packagist.org/packages/phpmailer/phpmailer) [![License](https://poser.pugx.org/phpmailer/phpmailer/license.svg)](https://packagist.org/packages/phpmailer/phpmailer) [![API Docs](https://github.com/phpmailer/phpmailer/workflows/Docs/badge.svg)](http://phpmailer.github.io/PHPMailer/)
 
 ## Class Features
 - Probably the world's most popular code for sending email from PHP!
@@ -16,7 +16,7 @@ Build status: [![Build Status](https://travis-ci.org/PHPMailer/PHPMailer.svg)](h
 - Multipart/alternative emails for mail clients that do not read HTML email
 - Add attachments, including inline
 - Support for UTF-8 content and 8bit, base64, binary, and quoted-printable encodings
-- SMTP authentication with LOGIN, PLAIN, CRAM-MD5 and XOAUTH2 mechanisms over SSL and SMTP+STARTTLS transports
+- SMTP authentication with LOGIN, PLAIN, CRAM-MD5, and XOAUTH2 mechanisms over SSL and SMTP+STARTTLS transports
 - Validates email addresses automatically
 - Protect against header injection attacks
 - Error messages in over 50 languages!
@@ -26,12 +26,12 @@ Build status: [![Build Status](https://travis-ci.org/PHPMailer/PHPMailer.svg)](h
 - Much more!
 
 ## Why you might need it
-Many PHP developers utilize email in their code. The only PHP function that supports this is the `mail()` function. However, it does not provide any assistance for making use of popular features such as HTML-based emails and attachments.
+Many PHP developers need to send email from their code. The only PHP function that supports this is [`mail()`](https://www.php.net/manual/en/function.mail.php). However, it does not provide any assistance for making use of popular features such as encryption, authentication, HTML messages, and attachments.
 
-Formatting email correctly is surprisingly difficult. There are myriad overlapping RFCs, requiring tight adherence to horribly complicated formatting and encoding rules - the vast majority of code that you'll find online that uses the `mail()` function directly is just plain wrong!
-*Please* don't be tempted to do it yourself - if you don't use PHPMailer, there are many other excellent libraries that you should look at before rolling your own - try [SwiftMailer](https://swiftmailer.symfony.com/), [Zend/Mail](https://zendframework.github.io/zend-mail/), [eZcomponents](https://github.com/zetacomponents/Mail) etc.
+Formatting email correctly is surprisingly difficult. There are myriad overlapping RFCs, requiring tight adherence to horribly complicated formatting and encoding rules – the vast majority of code that you'll find online that uses the `mail()` function directly is just plain wrong!
+*Please* don't be tempted to do it yourself – if you don't use PHPMailer, there are many other excellent libraries that you should look at before rolling your own. Try [SwiftMailer](https://swiftmailer.symfony.com/), [Zend/Mail](https://zendframework.github.io/zend-mail/), [ZetaComponents](https://github.com/zetacomponents/Mail) etc.
 
-The PHP `mail()` function usually sends via a local mail server, typically fronted by a `sendmail` binary on Linux, BSD and OS X platforms, however, Windows usually doesn't include a local mail server; PHPMailer's integrated SMTP implementation allows email sending on Windows platforms without a local mail server.
+The PHP `mail()` function usually sends via a local mail server, typically fronted by a `sendmail` binary on Linux, BSD, and macOS platforms, however, Windows usually doesn't include a local mail server; PHPMailer's integrated SMTP implementation allows email sending on Windows platforms without a local mail server.
 
 ## License
 This software is distributed under the [LGPL 2.1](http://www.gnu.org/licenses/lgpl-2.1.html) license, along with the [GPL Cooperation Commitment](https://gplcc.github.io/gplcc/). Please read LICENSE for information on the software availability and distribution.
@@ -40,7 +40,7 @@ This software is distributed under the [LGPL 2.1](http://www.gnu.org/licenses/lg
 PHPMailer is available on [Packagist](https://packagist.org/packages/phpmailer/phpmailer) (using semantic versioning), and installation via [Composer](https://getcomposer.org) is the recommended way to install PHPMailer. Just add this line to your `composer.json` file:
 
 ```json
-"phpmailer/phpmailer": "~6.0"
+"phpmailer/phpmailer": "~6.1"
 ```
 
 or run
@@ -70,15 +70,13 @@ If you're not using the `SMTP` class explicitly (you're probably not), you don't
 If you don't speak git or just want a tarball, click the 'zip' button on the right of the project page in GitHub, though note that docs and examples are not included in the tarball.
 
 ## Legacy versions
-PHPMailer 5.2 (which is compatible with PHP 5.0 - 7.0) is no longer being supported for feature updates, and will only be receiving security updates from now on. You will find the latest version of 5.2 in the [5.2-stable branch](https://github.com/PHPMailer/PHPMailer/tree/5.2-stable), and future versions of 5.2 will be tagged with 5.2.x version numbers, so existing Composer configs should remain working. If you're using PHP 5.5 or later, we recommend you make the necessary changes to switch to the 6.0 release.
+PHPMailer 5.2 (which is compatible with PHP 5.0 - 7.0) is no longer being supported, even for security updates. You will find the latest version of 5.2 in the [5.2-stable branch](https://github.com/PHPMailer/PHPMailer/tree/5.2-stable). If you're using PHP 5.5 or later (which you should be), switch to the 6.x releases.
 
-The 5.2 branch will not receive security updates after December 31st 2018.
-
-## Upgrading from 5.2
+### Upgrading from 5.2
 The biggest changes are that source files are now in the `src/` folder, and PHPMailer now declares the namespace `PHPMailer\PHPMailer`. This has several important effects – [read the upgrade guide](https://github.com/PHPMailer/PHPMailer/tree/master/UPGRADING.md) for more details.
 
 ### Minimal installation
-While installing the entire package manually or with Composer is simple, convenient and reliable, you may want to include only vital files in your project. At the very least you will need [src/PHPMailer.php](https://github.com/PHPMailer/PHPMailer/tree/master/src/PHPMailer.php). If you're using SMTP, you'll need [src/SMTP.php](https://github.com/PHPMailer/PHPMailer/tree/master/src/SMTP.php), and if you're using POP-before SMTP, you'll need [src/POP3.php](https://github.com/PHPMailer/PHPMailer/tree/master/src/POP3.php). You can skip the [language](https://github.com/PHPMailer/PHPMailer/tree/master/language/) folder if you're not showing errors to users and can make do with English-only errors. If you're using XOAUTH2 you will need [src/OAuth.php](https://github.com/PHPMailer/PHPMailer/tree/master/src/OAuth.php) as well as the Composer dependencies for the services you wish to authenticate with. Really, it's much easier to use Composer!
+While installing the entire package manually or with Composer is simple, convenient, and reliable, you may want to include only vital files in your project. At the very least you will need [src/PHPMailer.php](https://github.com/PHPMailer/PHPMailer/tree/master/src/PHPMailer.php). If you're using SMTP, you'll need [src/SMTP.php](https://github.com/PHPMailer/PHPMailer/tree/master/src/SMTP.php), and if you're using POP-before SMTP, you'll need [src/POP3.php](https://github.com/PHPMailer/PHPMailer/tree/master/src/POP3.php). You can skip the [language](https://github.com/PHPMailer/PHPMailer/tree/master/language/) folder if you're not showing errors to users and can make do with English-only errors. If you're using XOAUTH2 you will need [src/OAuth.php](https://github.com/PHPMailer/PHPMailer/tree/master/src/OAuth.php) as well as the Composer dependencies for the services you wish to authenticate with. Really, it's much easier to use Composer!
 
 ## A Simple Example
 
@@ -87,22 +85,25 @@ While installing the entire package manually or with Composer is simple, conveni
 // Import PHPMailer classes into the global namespace
 // These must be at the top of your script, not inside a function
 use PHPMailer\PHPMailer\PHPMailer;
+use PHPMailer\PHPMailer\SMTP;
 use PHPMailer\PHPMailer\Exception;
 
-//Load Composer's autoloader
+// Load Composer's autoloader
 require 'vendor/autoload.php';
 
-$mail = new PHPMailer(true);                              // Passing `true` enables exceptions
+// Instantiation and passing `true` enables exceptions
+$mail = new PHPMailer(true);
+
 try {
     //Server settings
-    $mail->SMTPDebug = 2;                                 // Enable verbose debug output
-    $mail->isSMTP();                                      // Set mailer to use SMTP
-    $mail->Host = 'smtp1.example.com;smtp2.example.com';  // Specify main and backup SMTP servers
-    $mail->SMTPAuth = true;                               // Enable SMTP authentication
-    $mail->Username = 'user@example.com';                 // SMTP username
-    $mail->Password = 'secret';                           // SMTP password
-    $mail->SMTPSecure = 'tls';                            // Enable TLS encryption, `ssl` also accepted
-    $mail->Port = 587;                                    // TCP port to connect to
+    $mail->SMTPDebug = SMTP::DEBUG_SERVER;                      // Enable verbose debug output
+    $mail->isSMTP();                                            // Send using SMTP
+    $mail->Host       = 'smtp1.example.com';                    // Set the SMTP server to send through
+    $mail->SMTPAuth   = true;                                   // Enable SMTP authentication
+    $mail->Username   = 'user@example.com';                     // SMTP username
+    $mail->Password   = 'secret';                               // SMTP password
+    $mail->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS;         // Enable TLS encryption; `PHPMailer::ENCRYPTION_SMTPS` encouraged
+    $mail->Port       = 587;                                    // TCP port to connect to, use 465 for `PHPMailer::ENCRYPTION_SMTPS` above
 
     //Recipients
     $mail->setFrom('from@example.com', 'Mailer');
@@ -112,11 +113,11 @@ try {
     $mail->addCC('cc@example.com');
     $mail->addBCC('bcc@example.com');
 
-    //Attachments
+    // Attachments
     $mail->addAttachment('/var/tmp/file.tar.gz');         // Add attachments
     $mail->addAttachment('/tmp/image.jpg', 'new.jpg');    // Optional name
 
-    //Content
+    // Content
     $mail->isHTML(true);                                  // Set email format to HTML
     $mail->Subject = 'Here is the subject';
     $mail->Body    = 'This is the HTML message body <b>in bold!</b>';
@@ -125,16 +126,18 @@ try {
     $mail->send();
     echo 'Message has been sent';
 } catch (Exception $e) {
-    echo 'Message could not be sent. Mailer Error: ', $mail->ErrorInfo;
+    echo "Message could not be sent. Mailer Error: {$mail->ErrorInfo}";
 }
 ```
 
 You'll find plenty more to play with in the [examples](https://github.com/PHPMailer/PHPMailer/tree/master/examples) folder.
 
+If you are re-using the instance (e.g. when sending to a mailing list), you may need to clear the recipient list to avoid sending duplicate messages. See [the mailing list example](https://github.com/PHPMailer/PHPMailer/blob/master/examples/mailing_list.phps) for further guidance.
+
 That's it. You should now be ready to use PHPMailer!
 
 ## Localization
-PHPMailer defaults to English, but in the [language](https://github.com/PHPMailer/PHPMailer/tree/master/language/) folder you'll find numerous (48 at the time of writing!) translations for PHPMailer error messages that you may encounter. Their filenames contain [ISO 639-1](http://en.wikipedia.org/wiki/ISO_639-1) language code for the translations, for example `fr` for French. To specify a language, you need to tell PHPMailer which one to use, like this:
+PHPMailer defaults to English, but in the [language](https://github.com/PHPMailer/PHPMailer/tree/master/language/) folder you'll find many translations for PHPMailer error messages that you may encounter. Their filenames contain [ISO 639-1](http://en.wikipedia.org/wiki/ISO_639-1) language code for the translations, for example `fr` for French. To specify a language, you need to tell PHPMailer which one to use, like this:
 
 ```php
 // To load the French version
@@ -152,7 +155,7 @@ Note that in order to reduce PHPMailer's deployed code footprint, the examples a
 
 Complete generated API documentation is [available online](http://phpmailer.github.io/PHPMailer/).
 
-You can generate complete API-level documentation by running `phpdoc` in the top-level folder, and documentation will appear in the `docs` folder, though you'll need to have [PHPDocumentor](http://www.phpdoc.org) installed. You may find [the unit tests](https://github.com/PHPMailer/PHPMailer/tree/master/test/phpmailerTest.php) a good source of how to do various operations such as encryption.
+You can generate complete API-level documentation by running `phpdoc` in the top-level folder, and documentation will appear in the `docs` folder, though you'll need to have [PHPDocumentor](http://www.phpdoc.org) installed. You may find [the unit tests](https://github.com/PHPMailer/PHPMailer/blob/master/test/PHPMailerTest.php) a good source of how to do various operations such as encryption.
 
 If the documentation doesn't cover what you need, search the [many questions on Stack Overflow](http://stackoverflow.com/questions/tagged/phpmailer), and before you ask a question about "SMTP Error: Could not connect to SMTP host.", [read the troubleshooting guide](https://github.com/PHPMailer/PHPMailer/wiki/Troubleshooting).
 
diff --git a/vendor/phpmailer/phpmailer/SECURITY.md b/vendor/phpmailer/phpmailer/SECURITY.md
index 5e917cd04a51585413aa23436fae8b0a9ca03714..fc3e61c2012b08c8802c26a8c64bb5adddfcd3c8 100644
--- a/vendor/phpmailer/phpmailer/SECURITY.md
+++ b/vendor/phpmailer/phpmailer/SECURITY.md
@@ -2,6 +2,8 @@
 
 Please disclose any vulnerabilities found responsibly - report any security problems found to the maintainers privately.
 
+PHPMailer versions 6.1.5 and earlier contain an output escaping bug that occurs in `Content-Type` and `Content-Disposition` when filenames passed into `addAttachment` and other methods that accept attachment names contain double quote characters, in contravention of RFC822 3.4.1. No specific vulnerability has been found relating to this, but it could allow file attachments to bypass attachment filters that are based on matching filename extensions. Recorded as [CVE-2020-13625](https://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2020-13625). Reported by Elar Lang of Clarified Security.
+
 PHPMailer versions prior to 6.0.6 and 5.2.27 are vulnerable to an object injection attack by passing `phar://` paths into `addAttachment()` and other functions that may receive unfiltered local paths, possibly leading to RCE. Recorded as [CVE-2018-19296](https://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2018-19296). See [this article](https://knasmueller.net/5-answers-about-php-phar-exploitation) for more info on this type of vulnerability. Mitigated by blocking the use of paths containing URL-protocol style prefixes such as `phar://`. Reported by Sehun Oh of cyberone.kr.
 
 PHPMailer versions prior to 5.2.24 (released July 26th 2017) have an XSS vulnerability in one of the code examples, [CVE-2017-11503](https://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2017-11503). The `code_generator.phps` example did not filter user input prior to output. This file is distributed with a `.phps` extension, so it it not normally executable unless it is explicitly renamed, and the file is not included when PHPMailer is loaded through composer, so it is safe by default. There was also an undisclosed potential XSS vulnerability in the default exception handler (unused by default). Patches for both issues kindly provided by Patrick Monnerat of the Fedora Project.
diff --git a/vendor/phpmailer/phpmailer/VERSION b/vendor/phpmailer/phpmailer/VERSION
index 41bd15e2ea953cf4d02de3592b651ad60114a2c6..cb6b1ffdc80dfcc784bb041b676ea36af33880ef 100644
--- a/vendor/phpmailer/phpmailer/VERSION
+++ b/vendor/phpmailer/phpmailer/VERSION
@@ -1 +1 @@
-6.0.7
\ No newline at end of file
+6.1.7
\ No newline at end of file
diff --git a/vendor/phpmailer/phpmailer/composer.json b/vendor/phpmailer/phpmailer/composer.json
index ee4e890d20c5f108db0e5acdc8739a47c7bcd13b..90d2576f5648ab4987a0ebbe177b19017e4d9565 100644
--- a/vendor/phpmailer/phpmailer/composer.json
+++ b/vendor/phpmailer/phpmailer/composer.json
@@ -19,6 +19,12 @@
             "name": "Brent R. Matzelle"
         }
     ],
+    "funding": [
+        {
+            "url": "https://github.com/synchro",
+            "type": "github"
+        }
+    ],
     "require": {
         "php": ">=5.5.0",
         "ext-ctype": "*",
@@ -26,12 +32,8 @@
     },
     "require-dev": {
         "friendsofphp/php-cs-fixer": "^2.2",
-        "phpdocumentor/phpdocumentor": "2.*",
         "phpunit/phpunit": "^4.8 || ^5.7",
-        "zendframework/zend-serializer": "2.7.*",
-        "doctrine/annotations": "1.2.*",
-        "zendframework/zend-eventmanager": "3.0.*",
-        "zendframework/zend-i18n": "2.7.3"
+        "doctrine/annotations": "^1.2"
     },
     "suggest": {
         "psr/log": "For optional PSR-3 debug logging",
@@ -51,5 +53,5 @@
             "PHPMailer\\Test\\": "test/"
         }
     },
-    "license": "LGPL-2.1"
+    "license": "LGPL-2.1-only"
 }
diff --git a/vendor/phpmailer/phpmailer/language/phpmailer.lang-af.php b/vendor/phpmailer/phpmailer/language/phpmailer.lang-af.php
new file mode 100644
index 0000000000000000000000000000000000000000..3c42d78e15a2e641c78df947abfd246ae28ad7ad
--- /dev/null
+++ b/vendor/phpmailer/phpmailer/language/phpmailer.lang-af.php
@@ -0,0 +1,25 @@
+<?php
+/**
+ * Afrikaans PHPMailer language file: refer to English translation for definitive list
+ * @package PHPMailer
+ */
+
+$PHPMAILER_LANG['authenticate']         = 'SMTP-fout: kon nie geverifieer word nie.';
+$PHPMAILER_LANG['connect_host']         = 'SMTP-fout: kon nie aan SMTP-verbind nie.';
+$PHPMAILER_LANG['data_not_accepted']    = 'SMTP-fout: data nie aanvaar nie.';
+$PHPMAILER_LANG['empty_message']        = 'Boodskapliggaam leeg.';
+$PHPMAILER_LANG['encoding']             = 'Onbekende kodering: ';
+$PHPMAILER_LANG['execute']              = 'Kon nie uitvoer nie: ';
+$PHPMAILER_LANG['file_access']          = 'Kon nie lêer oopmaak nie: ';
+$PHPMAILER_LANG['file_open']            = 'Lêerfout: Kon nie lêer oopmaak nie: ';
+$PHPMAILER_LANG['from_failed']          = 'Die volgende Van adres misluk: ';
+$PHPMAILER_LANG['instantiate']          = 'Kon nie posfunksie instansieer nie.';
+$PHPMAILER_LANG['invalid_address']      = 'Ongeldige adres: ';
+$PHPMAILER_LANG['mailer_not_supported'] = ' mailer word nie ondersteun nie.';
+$PHPMAILER_LANG['provide_address']      = 'U moet ten minste een ontvanger e-pos adres verskaf.';
+$PHPMAILER_LANG['recipients_failed']    = 'SMTP-fout: Die volgende ontvangers het misluk: ';
+$PHPMAILER_LANG['signing']              = 'Ondertekening Fout: ';
+$PHPMAILER_LANG['smtp_connect_failed']  = 'SMTP-verbinding () misluk.';
+$PHPMAILER_LANG['smtp_error']           = 'SMTP-bediener fout: ';
+$PHPMAILER_LANG['variable_set']         = 'Kan nie veranderlike instel of herstel nie: ';
+$PHPMAILER_LANG['extension_missing']    = 'Uitbreiding ontbreek: ';
diff --git a/vendor/phpmailer/phpmailer/language/phpmailer.lang-da.php b/vendor/phpmailer/phpmailer/language/phpmailer.lang-da.php
index e725f4b477c86455458a2f75d68e3fc776045503..5febb516e08bd9f1ea2f35e9ff0ce782e0818204 100644
--- a/vendor/phpmailer/phpmailer/language/phpmailer.lang-da.php
+++ b/vendor/phpmailer/phpmailer/language/phpmailer.lang-da.php
@@ -2,25 +2,27 @@
 /**
  * Danish PHPMailer language file: refer to English translation for definitive list
  * @package PHPMailer
- * @author Mikael Stokkebro <info@stokkebro.dk>
+ * @author John Sebastian <jms@iwb.dk>
+ * Rewrite and extension of the work by Mikael Stokkebro <info@stokkebro.dk> 
+ *  
  */
 
-$PHPMAILER_LANG['authenticate']         = 'SMTP fejl: Kunne ikke logge på.';
-$PHPMAILER_LANG['connect_host']         = 'SMTP fejl: Kunne ikke tilslutte SMTP serveren.';
-$PHPMAILER_LANG['data_not_accepted']    = 'SMTP fejl: Data kunne ikke accepteres.';
-//$PHPMAILER_LANG['empty_message']        = 'Message body empty';
+$PHPMAILER_LANG['authenticate']         = 'SMTP fejl: Login mislykkedes.';
+$PHPMAILER_LANG['connect_host']         = 'SMTP fejl: Forbindelse til SMTP serveren kunne ikke oprettes.';
+$PHPMAILER_LANG['data_not_accepted']    = 'SMTP fejl: Data blev ikke accepteret.';
+$PHPMAILER_LANG['empty_message']        = 'Meddelelsen er uden indhold';
 $PHPMAILER_LANG['encoding']             = 'Ukendt encode-format: ';
-$PHPMAILER_LANG['execute']              = 'Kunne ikke køre: ';
-$PHPMAILER_LANG['file_access']          = 'Ingen adgang til fil: ';
+$PHPMAILER_LANG['execute']              = 'Kunne ikke afvikle: ';
+$PHPMAILER_LANG['file_access']          = 'Kunne ikke tilgå filen: ';
 $PHPMAILER_LANG['file_open']            = 'Fil fejl: Kunne ikke åbne filen: ';
 $PHPMAILER_LANG['from_failed']          = 'Følgende afsenderadresse er forkert: ';
-$PHPMAILER_LANG['instantiate']          = 'Kunne ikke initialisere email funktionen.';
-//$PHPMAILER_LANG['invalid_address']        = 'Invalid address: ';
+$PHPMAILER_LANG['instantiate']          = 'Email funktionen kunne ikke initialiseres.';
+$PHPMAILER_LANG['invalid_address']      = 'Udgyldig adresse: ';
 $PHPMAILER_LANG['mailer_not_supported'] = ' mailer understøttes ikke.';
-$PHPMAILER_LANG['provide_address']      = 'Du skal indtaste mindst en modtagers emailadresse.';
+$PHPMAILER_LANG['provide_address']      = 'Indtast mindst en modtagers email adresse.';
 $PHPMAILER_LANG['recipients_failed']    = 'SMTP fejl: Følgende modtagere er forkerte: ';
-//$PHPMAILER_LANG['signing']              = 'Signing Error: ';
-//$PHPMAILER_LANG['smtp_connect_failed']  = 'SMTP Connect() failed.';
-//$PHPMAILER_LANG['smtp_error']           = 'SMTP server error: ';
-//$PHPMAILER_LANG['variable_set']         = 'Cannot set or reset variable: ';
-//$PHPMAILER_LANG['extension_missing']    = 'Extension missing: ';
+$PHPMAILER_LANG['signing']              = 'Signeringsfejl: ';
+$PHPMAILER_LANG['smtp_connect_failed']  = 'SMTP Connect() fejlede.';
+$PHPMAILER_LANG['smtp_error']           = 'SMTP server fejl: ';
+$PHPMAILER_LANG['variable_set']         = 'Kunne ikke definere eller nulstille variablen: ';
+$PHPMAILER_LANG['extension_missing']    = 'Udvidelse mangler: ';
diff --git a/vendor/phpmailer/phpmailer/language/phpmailer.lang-fa.php b/vendor/phpmailer/phpmailer/language/phpmailer.lang-fa.php
index ad0745c581c411b453a9ab29a266f3c647dab636..8aa0ad2218962766e912e1f03a7d32485fc63133 100644
--- a/vendor/phpmailer/phpmailer/language/phpmailer.lang-fa.php
+++ b/vendor/phpmailer/phpmailer/language/phpmailer.lang-fa.php
@@ -24,4 +24,4 @@ $PHPMAILER_LANG['signing']              = 'خطا در امضا: ';
 $PHPMAILER_LANG['smtp_connect_failed']  = 'خطا در اتصال به SMTP.';
 $PHPMAILER_LANG['smtp_error']           = 'خطا در SMTP Server: ';
 $PHPMAILER_LANG['variable_set']         = 'امکان ارسال یا ارسال مجدد متغیر‌ها وجود ندارد: ';
-//$PHPMAILER_LANG['extension_missing']    = 'Extension missing: ';
+$PHPMAILER_LANG['extension_missing']    = 'افزونه موجود نیست: ';
diff --git a/vendor/phpmailer/phpmailer/language/phpmailer.lang-am.php b/vendor/phpmailer/phpmailer/language/phpmailer.lang-hy.php
similarity index 100%
rename from vendor/phpmailer/phpmailer/language/phpmailer.lang-am.php
rename to vendor/phpmailer/phpmailer/language/phpmailer.lang-hy.php
diff --git a/vendor/phpmailer/phpmailer/language/phpmailer.lang-nl.php b/vendor/phpmailer/phpmailer/language/phpmailer.lang-nl.php
index 2fb01b2d8f9a025dca2b7cb8c3603a87814753f7..f4d0e7cd3bdd424ccfee7060831dd9a37a9a13b1 100644
--- a/vendor/phpmailer/phpmailer/language/phpmailer.lang-nl.php
+++ b/vendor/phpmailer/phpmailer/language/phpmailer.lang-nl.php
@@ -16,6 +16,8 @@ $PHPMAILER_LANG['file_open']            = 'Bestandsfout: kon bestand niet openen
 $PHPMAILER_LANG['from_failed']          = 'Het volgende afzendersadres is mislukt: ';
 $PHPMAILER_LANG['instantiate']          = 'Kon mailfunctie niet initialiseren.';
 $PHPMAILER_LANG['invalid_address']      = 'Ongeldig adres: ';
+$PHPMAILER_LANG['invalid_hostentry']    = 'Ongeldige hostentry: ';
+$PHPMAILER_LANG['invalid_host']         = 'Ongeldige host: ';
 $PHPMAILER_LANG['mailer_not_supported'] = ' mailer wordt niet ondersteund.';
 $PHPMAILER_LANG['provide_address']      = 'Er moet minstens één ontvanger worden opgegeven.';
 $PHPMAILER_LANG['recipients_failed']    = 'SMTP-fout: de volgende ontvangers zijn mislukt: ';
diff --git a/vendor/phpmailer/phpmailer/language/phpmailer.lang-pt_br.php b/vendor/phpmailer/phpmailer/language/phpmailer.lang-pt_br.php
index 4ec10f777ee37f4e2d012684236be8f9822b35a2..62d692d426c9f5f5e177853679f0e7b73515ec0a 100644
--- a/vendor/phpmailer/phpmailer/language/phpmailer.lang-pt_br.php
+++ b/vendor/phpmailer/phpmailer/language/phpmailer.lang-pt_br.php
@@ -26,4 +26,4 @@ $PHPMAILER_LANG['signing']              = 'Erro de Assinatura: ';
 $PHPMAILER_LANG['smtp_connect_failed']  = 'SMTP Connect() falhou.';
 $PHPMAILER_LANG['smtp_error']           = 'Erro de servidor SMTP: ';
 $PHPMAILER_LANG['variable_set']         = 'Não foi possível definir ou redefinir a variável: ';
-$PHPMAILER_LANG['extension_missing']    = 'Extensão ausente: ';
+$PHPMAILER_LANG['extension_missing']    = 'Extensão não existe: ';
diff --git a/vendor/phpmailer/phpmailer/language/phpmailer.lang-ru.php b/vendor/phpmailer/phpmailer/language/phpmailer.lang-ru.php
index 4066f6b451c86a82813106a0fb806ff0d1be3119..720e9a116d8a3754674f48fead1bd623c880810b 100644
--- a/vendor/phpmailer/phpmailer/language/phpmailer.lang-ru.php
+++ b/vendor/phpmailer/phpmailer/language/phpmailer.lang-ru.php
@@ -7,21 +7,21 @@
  */
 
 $PHPMAILER_LANG['authenticate']         = 'Ошибка SMTP: ошибка авторизации.';
-$PHPMAILER_LANG['connect_host']         = 'Ошибка SMTP: не удается подключиться к серверу SMTP.';
+$PHPMAILER_LANG['connect_host']         = 'Ошибка SMTP: не удается подключиться к SMTP-серверу.';
 $PHPMAILER_LANG['data_not_accepted']    = 'Ошибка SMTP: данные не приняты.';
-$PHPMAILER_LANG['encoding']             = 'Неизвестный вид кодировки: ';
+$PHPMAILER_LANG['encoding']             = 'Неизвестная кодировка: ';
 $PHPMAILER_LANG['execute']              = 'Невозможно выполнить команду: ';
 $PHPMAILER_LANG['file_access']          = 'Нет доступа к файлу: ';
-$PHPMAILER_LANG['file_open']            = 'Файловая ошибка: не удается открыть файл: ';
+$PHPMAILER_LANG['file_open']            = 'Файловая ошибка: не удаётся открыть файл: ';
 $PHPMAILER_LANG['from_failed']          = 'Неверный адрес отправителя: ';
-$PHPMAILER_LANG['instantiate']          = 'Невозможно запустить функцию mail.';
-$PHPMAILER_LANG['provide_address']      = 'Пожалуйста, введите хотя бы один адрес e-mail получателя.';
+$PHPMAILER_LANG['instantiate']          = 'Невозможно запустить функцию mail().';
+$PHPMAILER_LANG['provide_address']      = 'Пожалуйста, введите хотя бы один email-адрес получателя.';
 $PHPMAILER_LANG['mailer_not_supported'] = ' — почтовый сервер не поддерживается.';
-$PHPMAILER_LANG['recipients_failed']    = 'Ошибка SMTP: отправка по следующим адресам получателей не удалась: ';
+$PHPMAILER_LANG['recipients_failed']    = 'Ошибка SMTP: не удалась отправка таким адресатам: ';
 $PHPMAILER_LANG['empty_message']        = 'Пустое сообщение';
-$PHPMAILER_LANG['invalid_address']      = 'Не отослано, неправильный формат email адреса: ';
+$PHPMAILER_LANG['invalid_address']      = 'Не отправлено из-за неправильного формата email-адреса: ';
 $PHPMAILER_LANG['signing']              = 'Ошибка подписи: ';
 $PHPMAILER_LANG['smtp_connect_failed']  = 'Ошибка соединения с SMTP-сервером';
 $PHPMAILER_LANG['smtp_error']           = 'Ошибка SMTP-сервера: ';
-$PHPMAILER_LANG['variable_set']         = 'Невозможно установить или переустановить переменную: ';
+$PHPMAILER_LANG['variable_set']         = 'Невозможно установить или сбросить переменную: ';
 $PHPMAILER_LANG['extension_missing']    = 'Расширение отсутствует: ';
diff --git a/vendor/phpmailer/phpmailer/language/phpmailer.lang-sv.php b/vendor/phpmailer/phpmailer/language/phpmailer.lang-sv.php
index 4408e63eb0e6622b2f22abe20068c3870fa7dbbc..c78237e7c4cf9413084a714576801c281949a616 100644
--- a/vendor/phpmailer/phpmailer/language/phpmailer.lang-sv.php
+++ b/vendor/phpmailer/phpmailer/language/phpmailer.lang-sv.php
@@ -19,8 +19,8 @@ $PHPMAILER_LANG['invalid_address']      = 'Felaktig adress: ';
 $PHPMAILER_LANG['provide_address']      = 'Du måste ange minst en mottagares e-postadress.';
 $PHPMAILER_LANG['mailer_not_supported'] = ' mailer stöds inte.';
 $PHPMAILER_LANG['recipients_failed']    = 'SMTP fel: Följande mottagare är felaktig: ';
-$PHPMAILER_LANG['signing']              = 'Signerings fel: ';
+$PHPMAILER_LANG['signing']              = 'Signeringsfel: ';
 $PHPMAILER_LANG['smtp_connect_failed']  = 'SMTP Connect() misslyckades.';
-$PHPMAILER_LANG['smtp_error']           = 'SMTP server fel: ';
+$PHPMAILER_LANG['smtp_error']           = 'SMTP serverfel: ';
 $PHPMAILER_LANG['variable_set']         = 'Kunde inte definiera eller återställa variabel: ';
 $PHPMAILER_LANG['extension_missing']    = 'Tillägg ej tillgängligt: ';
diff --git a/vendor/phpmailer/phpmailer/language/phpmailer.lang-uk.php b/vendor/phpmailer/phpmailer/language/phpmailer.lang-uk.php
index a0a160660a72c2c3116cc829840838d9aa65f893..fcd77ade9c291bdd3763c283616068e4704640fe 100644
--- a/vendor/phpmailer/phpmailer/language/phpmailer.lang-uk.php
+++ b/vendor/phpmailer/phpmailer/language/phpmailer.lang-uk.php
@@ -7,21 +7,21 @@
  */
 
 $PHPMAILER_LANG['authenticate']         = 'Помилка SMTP: помилка авторизації.';
-$PHPMAILER_LANG['connect_host']         = 'Помилка SMTP: не вдається під\'єднатися до серверу SMTP.';
-$PHPMAILER_LANG['data_not_accepted']    = 'Помилка SMTP: дані не прийняті.';
-$PHPMAILER_LANG['encoding']             = 'Невідомий тип кодування: ';
+$PHPMAILER_LANG['connect_host']         = 'Помилка SMTP: не вдається під\'єднатися до SMTP-серверу.';
+$PHPMAILER_LANG['data_not_accepted']    = 'Помилка SMTP: дані не прийнято.';
+$PHPMAILER_LANG['encoding']             = 'Невідоме кодування: ';
 $PHPMAILER_LANG['execute']              = 'Неможливо виконати команду: ';
 $PHPMAILER_LANG['file_access']          = 'Немає доступу до файлу: ';
 $PHPMAILER_LANG['file_open']            = 'Помилка файлової системи: не вдається відкрити файл: ';
 $PHPMAILER_LANG['from_failed']          = 'Невірна адреса відправника: ';
-$PHPMAILER_LANG['instantiate']          = 'Неможливо запустити функцію mail.';
-$PHPMAILER_LANG['provide_address']      = 'Будь-ласка, введіть хоча б одну адресу e-mail отримувача.';
+$PHPMAILER_LANG['instantiate']          = 'Неможливо запустити функцію mail().';
+$PHPMAILER_LANG['provide_address']      = 'Будь-ласка, введіть хоча б одну email-адресу отримувача.';
 $PHPMAILER_LANG['mailer_not_supported'] = ' - поштовий сервер не підтримується.';
-$PHPMAILER_LANG['recipients_failed']    = 'Помилка SMTP: відправлення наступним отримувачам не вдалося: ';
-$PHPMAILER_LANG['empty_message']        = 'Пусте тіло повідомлення';
-$PHPMAILER_LANG['invalid_address']      = 'Не відправлено, невірний формат адреси e-mail: ';
+$PHPMAILER_LANG['recipients_failed']    = 'Помилка SMTP: не вдалося відправлення для таких отримувачів: ';
+$PHPMAILER_LANG['empty_message']        = 'Пусте повідомлення';
+$PHPMAILER_LANG['invalid_address']      = 'Не відправлено через невірний формат email-адреси: ';
 $PHPMAILER_LANG['signing']              = 'Помилка підпису: ';
-$PHPMAILER_LANG['smtp_connect_failed']  = 'Помилка з\'єднання із SMTP-сервером';
+$PHPMAILER_LANG['smtp_connect_failed']  = 'Помилка з\'єднання з SMTP-сервером';
 $PHPMAILER_LANG['smtp_error']           = 'Помилка SMTP-сервера: ';
-$PHPMAILER_LANG['variable_set']         = 'Неможливо встановити або перевстановити змінну: ';
-$PHPMAILER_LANG['extension_missing']    = 'Не знайдено розширення: ';
+$PHPMAILER_LANG['variable_set']         = 'Неможливо встановити або скинути змінну: ';
+$PHPMAILER_LANG['extension_missing']    = 'Розширення відсутнє: ';
diff --git a/vendor/phpmailer/phpmailer/src/Exception.php b/vendor/phpmailer/phpmailer/src/Exception.php
index 9a05dec3ca869c06256c9bc66f2c82ac48b272aa..b1e552f50b7c917eac1ed00ff511e15b6bd318e6 100644
--- a/vendor/phpmailer/phpmailer/src/Exception.php
+++ b/vendor/phpmailer/phpmailer/src/Exception.php
@@ -23,7 +23,7 @@ namespace PHPMailer\PHPMailer;
 /**
  * PHPMailer exception handler.
  *
- * @author  Marcus Bointon <phpmailer@synchromedia.co.uk>
+ * @author Marcus Bointon <phpmailer@synchromedia.co.uk>
  */
 class Exception extends \Exception
 {
diff --git a/vendor/phpmailer/phpmailer/src/OAuth.php b/vendor/phpmailer/phpmailer/src/OAuth.php
index 0bce7e3468c69c458b110178c0988490d747176d..0271963cee681ea93210d9e1d36000fdd5c52fcf 100644
--- a/vendor/phpmailer/phpmailer/src/OAuth.php
+++ b/vendor/phpmailer/phpmailer/src/OAuth.php
@@ -123,7 +123,7 @@ class OAuth
     public function getOauth64()
     {
         // Get a new token if it's not available or has expired
-        if (null === $this->oauthToken or $this->oauthToken->hasExpired()) {
+        if (null === $this->oauthToken || $this->oauthToken->hasExpired()) {
             $this->oauthToken = $this->getToken();
         }
 
diff --git a/vendor/phpmailer/phpmailer/src/PHPMailer.php b/vendor/phpmailer/phpmailer/src/PHPMailer.php
index 52104924d4cfd5f2c3c7902b16ee6098eeb0fd4e..2d4156f4e85cf36f9de18dc79b9c8ad4a200c0ff 100644
--- a/vendor/phpmailer/phpmailer/src/PHPMailer.php
+++ b/vendor/phpmailer/phpmailer/src/PHPMailer.php
@@ -3,13 +3,13 @@
  * PHPMailer - PHP email creation and transport class.
  * PHP Version 5.5.
  *
- * @see       https://github.com/PHPMailer/PHPMailer/ The PHPMailer GitHub project
+ * @see https://github.com/PHPMailer/PHPMailer/ The PHPMailer GitHub project
  *
  * @author    Marcus Bointon (Synchro/coolbru) <phpmailer@synchromedia.co.uk>
  * @author    Jim Jagielski (jimjag) <jimjag@gmail.com>
  * @author    Andy Prevost (codeworxtech) <codeworxtech@users.sourceforge.net>
  * @author    Brent R. Matzelle (original founder)
- * @copyright 2012 - 2017 Marcus Bointon
+ * @copyright 2012 - 2019 Marcus Bointon
  * @copyright 2010 - 2012 Jim Jagielski
  * @copyright 2004 - 2009 Andy Prevost
  * @license   http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
@@ -23,13 +23,14 @@ namespace PHPMailer\PHPMailer;
 /**
  * PHPMailer - PHP email creation and transport class.
  *
- * @author  Marcus Bointon (Synchro/coolbru) <phpmailer@synchromedia.co.uk>
- * @author  Jim Jagielski (jimjag) <jimjag@gmail.com>
- * @author  Andy Prevost (codeworxtech) <codeworxtech@users.sourceforge.net>
- * @author  Brent R. Matzelle (original founder)
+ * @author Marcus Bointon (Synchro/coolbru) <phpmailer@synchromedia.co.uk>
+ * @author Jim Jagielski (jimjag) <jimjag@gmail.com>
+ * @author Andy Prevost (codeworxtech) <codeworxtech@users.sourceforge.net>
+ * @author Brent R. Matzelle (original founder)
  */
 class PHPMailer
 {
+    const CHARSET_ASCII = 'us-ascii';
     const CHARSET_ISO88591 = 'iso-8859-1';
     const CHARSET_UTF8 = 'utf-8';
 
@@ -46,12 +47,24 @@ class PHPMailer
     const ENCODING_BINARY = 'binary';
     const ENCODING_QUOTED_PRINTABLE = 'quoted-printable';
 
+    const ENCRYPTION_STARTTLS = 'tls';
+    const ENCRYPTION_SMTPS = 'ssl';
+
+    const ICAL_METHOD_REQUEST = 'REQUEST';
+    const ICAL_METHOD_PUBLISH = 'PUBLISH';
+    const ICAL_METHOD_REPLY = 'REPLY';
+    const ICAL_METHOD_ADD = 'ADD';
+    const ICAL_METHOD_CANCEL = 'CANCEL';
+    const ICAL_METHOD_REFRESH = 'REFRESH';
+    const ICAL_METHOD_COUNTER = 'COUNTER';
+    const ICAL_METHOD_DECLINECOUNTER = 'DECLINECOUNTER';
+
     /**
      * Email priority.
      * Options: null (default), 1 = High, 3 = Normal, 5 = low.
      * When null, the header is not set at all.
      *
-     * @var int
+     * @var int|null
      */
     public $Priority;
 
@@ -145,6 +158,22 @@ class PHPMailer
      */
     public $Ical = '';
 
+    /**
+     * Value-array of "method" in Contenttype header "text/calendar"
+     *
+     * @var string[]
+     */
+    protected static $IcalMethods = [
+        self::ICAL_METHOD_REQUEST,
+        self::ICAL_METHOD_PUBLISH,
+        self::ICAL_METHOD_REPLY,
+        self::ICAL_METHOD_ADD,
+        self::ICAL_METHOD_CANCEL,
+        self::ICAL_METHOD_REFRESH,
+        self::ICAL_METHOD_COUNTER,
+        self::ICAL_METHOD_DECLINECOUNTER,
+    ];
+
     /**
      * The complete compiled MIME message body.
      *
@@ -212,6 +241,8 @@ class PHPMailer
      * $_SERVER['SERVER_NAME'], gethostname(), php_uname('n'), or the value
      * 'localhost.localdomain'.
      *
+     * @see PHPMailer::$Helo
+     *
      * @var string
      */
     public $Hostname = '';
@@ -258,7 +289,7 @@ class PHPMailer
     public $Port = 25;
 
     /**
-     * The SMTP HELO of the message.
+     * The SMTP HELO/EHLO name used for the SMTP connection.
      * Default is $Hostname. If $Hostname is empty, PHPMailer attempts to find
      * one with the same method described above for $Hostname.
      *
@@ -270,7 +301,7 @@ class PHPMailer
 
     /**
      * What kind of encryption to use on the SMTP connection.
-     * Options: '', 'ssl' or 'tls'.
+     * Options: '', static::ENCRYPTION_STARTTLS, or static::ENCRYPTION_SMTPS.
      *
      * @var string
      */
@@ -340,15 +371,28 @@ class PHPMailer
      */
     public $Timeout = 300;
 
+    /**
+     * Comma separated list of DSN notifications
+     * 'NEVER' under no circumstances a DSN must be returned to the sender.
+     *         If you use NEVER all other notifications will be ignored.
+     * 'SUCCESS' will notify you when your mail has arrived at its destination.
+     * 'FAILURE' will arrive if an error occurred during delivery.
+     * 'DELAY'   will notify you if there is an unusual delay in delivery, but the actual
+     *           delivery's outcome (success or failure) is not yet decided.
+     *
+     * @see https://tools.ietf.org/html/rfc3461 See section 4.1 for more information about NOTIFY
+     */
+    public $dsn = '';
+
     /**
      * SMTP class debug output mode.
      * Debug output level.
      * Options:
-     * * `0` No output
-     * * `1` Commands
-     * * `2` Data and commands
-     * * `3` As 2 plus connection status
-     * * `4` Low-level data output.
+     * * SMTP::DEBUG_OFF: No output
+     * * SMTP::DEBUG_CLIENT: Client messages
+     * * SMTP::DEBUG_SERVER: Client and server messages
+     * * SMTP::DEBUG_CONNECTION: As SERVER plus connection status
+     * * SMTP::DEBUG_LOWLEVEL: Noisy, low-level data output, rarely needed
      *
      * @see SMTP::$do_debug
      *
@@ -397,6 +441,8 @@ class PHPMailer
      * Only supported in `mail` and `sendmail` transports, not in SMTP.
      *
      * @var bool
+     *
+     * @deprecated 6.0.0 PHPMailer isn't a mailing list manager!
      */
     public $SingleTo = false;
 
@@ -514,9 +560,9 @@ class PHPMailer
 
     /**
      * What to put in the X-Mailer header.
-     * Options: An empty string for PHPMailer default, whitespace for none, or a string to use.
+     * Options: An empty string for PHPMailer default, whitespace/null for none, or a string to use.
      *
-     * @var string
+     * @var string|null
      */
     public $XMailer = '';
 
@@ -701,7 +747,7 @@ class PHPMailer
      *
      * @var string
      */
-    const VERSION = '6.0.7';
+    const VERSION = '6.1.7';
 
     /**
      * Error severity: message only, continue processing.
@@ -725,11 +771,32 @@ class PHPMailer
     const STOP_CRITICAL = 2;
 
     /**
-     * SMTP RFC standard line ending.
+     * The SMTP standard CRLF line break.
+     * If you want to change line break format, change static::$LE, not this.
+     */
+    const CRLF = "\r\n";
+
+    /**
+     * "Folding White Space" a white space string used for line folding.
+     */
+    const FWS = ' ';
+
+    /**
+     * SMTP RFC standard line ending; Carriage Return, Line Feed.
      *
      * @var string
      */
-    protected static $LE = "\r\n";
+    protected static $LE = self::CRLF;
+
+    /**
+     * The maximum line length supported by mail().
+     *
+     * Background: mail() will sometimes corrupt messages
+     * with headers headers longer than 65 chars, see #818.
+     *
+     * @var int
+     */
+    const MAIL_MAX_LINE_LENGTH = 63;
 
     /**
      * The maximum line length allowed by RFC 2822 section 2.1.1.
@@ -794,7 +861,7 @@ class PHPMailer
             $subject = $this->encodeHeader($this->secureHeader($subject));
         }
         //Calling mail() with null params breaks
-        if (!$this->UseSendmailOptions or null === $params) {
+        if (!$this->UseSendmailOptions || null === $params) {
             $result = @mail($to, $subject, $body, $header);
         } else {
             $result = @mail($to, $subject, $body, $header, $params);
@@ -824,7 +891,7 @@ class PHPMailer
             return;
         }
         //Avoid clash with built-in function names
-        if (!in_array($this->Debugoutput, ['error_log', 'html', 'echo']) and is_callable($this->Debugoutput)) {
+        if (is_callable($this->Debugoutput) && !in_array($this->Debugoutput, ['error_log', 'html', 'echo'])) {
             call_user_func($this->Debugoutput, $str, $this->SMTPDebug);
 
             return;
@@ -845,12 +912,12 @@ class PHPMailer
             case 'echo':
             default:
                 //Normalize line breaks
-                $str = preg_replace('/\r\n|\r/ms', "\n", $str);
+                $str = preg_replace('/\r\n|\r/m', "\n", $str);
                 echo gmdate('Y-m-d H:i:s'),
                 "\t",
                     //Trim trailing space
                 trim(
-                //Indent for readability, except for trailing break
+                    //Indent for readability, except for trailing break
                     str_replace(
                         "\n",
                         "\n                   \t                  ",
@@ -927,6 +994,8 @@ class PHPMailer
      * @param string $address The email address to send to
      * @param string $name
      *
+     * @throws Exception
+     *
      * @return bool true on success, false if address already used or invalid in some way
      */
     public function addAddress($address, $name = '')
@@ -940,6 +1009,8 @@ class PHPMailer
      * @param string $address The email address to send to
      * @param string $name
      *
+     * @throws Exception
+     *
      * @return bool true on success, false if address already used or invalid in some way
      */
     public function addCC($address, $name = '')
@@ -953,6 +1024,8 @@ class PHPMailer
      * @param string $address The email address to send to
      * @param string $name
      *
+     * @throws Exception
+     *
      * @return bool true on success, false if address already used or invalid in some way
      */
     public function addBCC($address, $name = '')
@@ -966,6 +1039,8 @@ class PHPMailer
      * @param string $address The email address to reply to
      * @param string $name
      *
+     * @throws Exception
+     *
      * @return bool true on success, false if address already used or invalid in some way
      */
     public function addReplyTo($address, $name = '')
@@ -994,10 +1069,12 @@ class PHPMailer
         $pos = strrpos($address, '@');
         if (false === $pos) {
             // At-sign is missing.
-            $error_message = sprintf('%s (%s): %s',
+            $error_message = sprintf(
+                '%s (%s): %s',
                 $this->lang('invalid_address'),
                 $kind,
-                $address);
+                $address
+            );
             $this->setError($error_message);
             $this->edebug($error_message);
             if ($this->exceptions) {
@@ -1008,19 +1085,17 @@ class PHPMailer
         }
         $params = [$kind, $address, $name];
         // Enqueue addresses with IDN until we know the PHPMailer::$CharSet.
-        if ($this->has8bitChars(substr($address, ++$pos)) and static::idnSupported()) {
-            if ('Reply-To' != $kind) {
+        if (static::idnSupported() && $this->has8bitChars(substr($address, ++$pos))) {
+            if ('Reply-To' !== $kind) {
                 if (!array_key_exists($address, $this->RecipientsQueue)) {
                     $this->RecipientsQueue[$address] = $params;
 
                     return true;
                 }
-            } else {
-                if (!array_key_exists($address, $this->ReplyToQueue)) {
-                    $this->ReplyToQueue[$address] = $params;
+            } elseif (!array_key_exists($address, $this->ReplyToQueue)) {
+                $this->ReplyToQueue[$address] = $params;
 
-                    return true;
-                }
+                return true;
             }
 
             return false;
@@ -1045,9 +1120,11 @@ class PHPMailer
     protected function addAnAddress($kind, $address, $name = '')
     {
         if (!in_array($kind, ['to', 'cc', 'bcc', 'Reply-To'])) {
-            $error_message = sprintf('%s: %s',
+            $error_message = sprintf(
+                '%s: %s',
                 $this->lang('Invalid recipient kind'),
-                $kind);
+                $kind
+            );
             $this->setError($error_message);
             $this->edebug($error_message);
             if ($this->exceptions) {
@@ -1057,10 +1134,12 @@ class PHPMailer
             return false;
         }
         if (!static::validateAddress($address)) {
-            $error_message = sprintf('%s (%s): %s',
+            $error_message = sprintf(
+                '%s (%s): %s',
                 $this->lang('invalid_address'),
                 $kind,
-                $address);
+                $address
+            );
             $this->setError($error_message);
             $this->edebug($error_message);
             if ($this->exceptions) {
@@ -1069,19 +1148,17 @@ class PHPMailer
 
             return false;
         }
-        if ('Reply-To' != $kind) {
+        if ('Reply-To' !== $kind) {
             if (!array_key_exists(strtolower($address), $this->all_recipients)) {
                 $this->{$kind}[] = [$address, $name];
                 $this->all_recipients[strtolower($address)] = true;
 
                 return true;
             }
-        } else {
-            if (!array_key_exists(strtolower($address), $this->ReplyTo)) {
-                $this->ReplyTo[strtolower($address)] = [$address, $name];
+        } elseif (!array_key_exists(strtolower($address), $this->ReplyTo)) {
+            $this->ReplyTo[strtolower($address)] = [$address, $name];
 
-                return true;
-            }
+            return true;
         }
 
         return false;
@@ -1093,7 +1170,7 @@ class PHPMailer
      * Uses the imap_rfc822_parse_adrlist function if the IMAP extension is available.
      * Note that quotes in the name part are removed.
      *
-     * @see    http://www.andrew.cmu.edu/user/agreen1/testing/mrbs/web/Mail/RFC822.php A more careful implementation
+     * @see http://www.andrew.cmu.edu/user/agreen1/testing/mrbs/web/Mail/RFC822.php A more careful implementation
      *
      * @param string $addrstr The address list string
      * @param bool   $useimap Whether to use the IMAP extension to parse the list
@@ -1103,17 +1180,17 @@ class PHPMailer
     public static function parseAddresses($addrstr, $useimap = true)
     {
         $addresses = [];
-        if ($useimap and function_exists('imap_rfc822_parse_adrlist')) {
+        if ($useimap && function_exists('imap_rfc822_parse_adrlist')) {
             //Use this built-in parser if it's available
             $list = imap_rfc822_parse_adrlist($addrstr, '');
             foreach ($list as $address) {
-                if ('.SYNTAX-ERROR.' != $address->host) {
-                    if (static::validateAddress($address->mailbox . '@' . $address->host)) {
-                        $addresses[] = [
-                            'name' => (property_exists($address, 'personal') ? $address->personal : ''),
-                            'address' => $address->mailbox . '@' . $address->host,
-                        ];
-                    }
+                if (('.SYNTAX-ERROR.' !== $address->host) && static::validateAddress(
+                    $address->mailbox . '@' . $address->host
+                )) {
+                    $addresses[] = [
+                        'name' => (property_exists($address, 'personal') ? $address->personal : ''),
+                        'address' => $address->mailbox . '@' . $address->host,
+                    ];
                 }
             }
         } else {
@@ -1163,12 +1240,15 @@ class PHPMailer
         $name = trim(preg_replace('/[\r\n]+/', '', $name)); //Strip breaks and trim
         // Don't validate now addresses with IDN. Will be done in send().
         $pos = strrpos($address, '@');
-        if (false === $pos or
-            (!$this->has8bitChars(substr($address, ++$pos)) or !static::idnSupported()) and
-            !static::validateAddress($address)) {
-            $error_message = sprintf('%s (From): %s',
+        if ((false === $pos)
+            || ((!$this->has8bitChars(substr($address, ++$pos)) || !static::idnSupported())
+            && !static::validateAddress($address))
+        ) {
+            $error_message = sprintf(
+                '%s (From): %s',
                 $this->lang('invalid_address'),
-                $address);
+                $address
+            );
             $this->setError($error_message);
             $this->edebug($error_message);
             if ($this->exceptions) {
@@ -1179,10 +1259,8 @@ class PHPMailer
         }
         $this->From = $address;
         $this->FromName = $name;
-        if ($auto) {
-            if (empty($this->Sender)) {
-                $this->Sender = $address;
-            }
+        if ($auto && empty($this->Sender)) {
+            $this->Sender = $address;
         }
 
         return true;
@@ -1234,7 +1312,7 @@ class PHPMailer
             return call_user_func($patternselect, $address);
         }
         //Reject line breaks in addresses; it's valid RFC5322, but not RFC5321
-        if (strpos($address, "\n") !== false or strpos($address, "\r") !== false) {
+        if (strpos($address, "\n") !== false || strpos($address, "\r") !== false) {
             return false;
         }
         switch ($patternselect) {
@@ -1281,7 +1359,7 @@ class PHPMailer
                 );
             case 'php':
             default:
-                return (bool) filter_var($address, FILTER_VALIDATE_EMAIL);
+                return filter_var($address, FILTER_VALIDATE_EMAIL) !== false;
         }
     }
 
@@ -1293,7 +1371,7 @@ class PHPMailer
      */
     public static function idnSupported()
     {
-        return function_exists('idn_to_ascii') and function_exists('mb_convert_encoding');
+        return function_exists('idn_to_ascii') && function_exists('mb_convert_encoding');
     }
 
     /**
@@ -1304,7 +1382,7 @@ class PHPMailer
      * - Conversion to punycode is impossible (e.g. required PHP functions are not available)
      *   or fails for any reason (e.g. domain contains characters not allowed in an IDN).
      *
-     * @see    PHPMailer::$CharSet
+     * @see PHPMailer::$CharSet
      *
      * @param string $address The email address to convert
      *
@@ -1314,17 +1392,23 @@ class PHPMailer
     {
         // Verify we have required functions, CharSet, and at-sign.
         $pos = strrpos($address, '@');
-        if (static::idnSupported() and
-            !empty($this->CharSet) and
-            false !== $pos
+        if (!empty($this->CharSet) &&
+            false !== $pos &&
+            static::idnSupported()
         ) {
             $domain = substr($address, ++$pos);
             // Verify CharSet string is a valid one, and domain properly encoded in this CharSet.
-            if ($this->has8bitChars($domain) and @mb_check_encoding($domain, $this->CharSet)) {
+            if ($this->has8bitChars($domain) && @mb_check_encoding($domain, $this->CharSet)) {
                 $domain = mb_convert_encoding($domain, 'UTF-8', $this->CharSet);
                 //Ignore IDE complaints about this line - method signature changed in PHP 5.4
                 $errorcode = 0;
-                $punycode = idn_to_ascii($domain, $errorcode, INTL_IDNA_VARIANT_UTS46);
+                if (defined('INTL_IDNA_VARIANT_UTS46')) {
+                    $punycode = idn_to_ascii($domain, $errorcode, INTL_IDNA_VARIANT_UTS46);
+                } elseif (defined('INTL_IDNA_VARIANT_2003')) {
+                    $punycode = idn_to_ascii($domain, $errorcode, INTL_IDNA_VARIANT_2003);
+                } else {
+                    $punycode = idn_to_ascii($domain, $errorcode);
+                }
                 if (false !== $punycode) {
                     return substr($address, 0, $pos) . $punycode;
                 }
@@ -1370,24 +1454,22 @@ class PHPMailer
      */
     public function preSend()
     {
-        if ('smtp' == $this->Mailer or
-            ('mail' == $this->Mailer and stripos(PHP_OS, 'WIN') === 0)
+        if ('smtp' === $this->Mailer
+            || ('mail' === $this->Mailer && stripos(PHP_OS, 'WIN') === 0)
         ) {
             //SMTP mandates RFC-compliant line endings
             //and it's also used with mail() on Windows
-            static::setLE("\r\n");
+            static::setLE(self::CRLF);
         } else {
             //Maintain backward compatibility with legacy Linux command line mailers
             static::setLE(PHP_EOL);
         }
         //Check for buggy PHP versions that add a header with an incorrect line break
-        if (ini_get('mail.add_x_header') == 1
-            and 'mail' == $this->Mailer
-            and stripos(PHP_OS, 'WIN') === 0
-            and ((version_compare(PHP_VERSION, '7.0.0', '>=')
-                    and version_compare(PHP_VERSION, '7.0.17', '<'))
-                or (version_compare(PHP_VERSION, '7.1.0', '>=')
-                    and version_compare(PHP_VERSION, '7.1.3', '<')))
+        if ('mail' === $this->Mailer
+            && ((PHP_VERSION_ID >= 70000 && PHP_VERSION_ID < 70017)
+                || (PHP_VERSION_ID >= 70100 && PHP_VERSION_ID < 70103))
+            && ini_get('mail.add_x_header') === '1'
+            && stripos(PHP_OS, 'WIN') === 0
         ) {
             trigger_error(
                 'Your version of PHP is affected by a bug that may result in corrupted messages.' .
@@ -1418,10 +1500,12 @@ class PHPMailer
                 }
                 $this->$address_kind = $this->punyencodeAddress($this->$address_kind);
                 if (!static::validateAddress($this->$address_kind)) {
-                    $error_message = sprintf('%s (%s): %s',
+                    $error_message = sprintf(
+                        '%s (%s): %s',
                         $this->lang('invalid_address'),
                         $address_kind,
-                        $this->$address_kind);
+                        $this->$address_kind
+                    );
                     $this->setError($error_message);
                     $this->edebug($error_message);
                     if ($this->exceptions) {
@@ -1439,7 +1523,7 @@ class PHPMailer
 
             $this->setMessageType();
             // Refuse to send an empty message unless we are specifically allowing it
-            if (!$this->AllowEmpty and empty($this->Body)) {
+            if (!$this->AllowEmpty && empty($this->Body)) {
                 throw new Exception($this->lang('empty_message'), self::STOP_CRITICAL);
             }
 
@@ -1455,7 +1539,7 @@ class PHPMailer
 
             // To capture the complete message when using mail(), create
             // an extra header list which createHeader() doesn't fold in
-            if ('mail' == $this->Mailer) {
+            if ('mail' === $this->Mailer) {
                 if (count($this->to) > 0) {
                     $this->mailHeader .= $this->addrAppend('To', $this->to);
                 } else {
@@ -1469,11 +1553,11 @@ class PHPMailer
 
             // Sign with DKIM if enabled
             if (!empty($this->DKIM_domain)
-                and !empty($this->DKIM_selector)
-                and (!empty($this->DKIM_private_string)
-                    or (!empty($this->DKIM_private)
-                        and static::isPermittedPath($this->DKIM_private)
-                        and file_exists($this->DKIM_private)
+                && !empty($this->DKIM_selector)
+                && (!empty($this->DKIM_private_string)
+                    || (!empty($this->DKIM_private)
+                        && static::isPermittedPath($this->DKIM_private)
+                        && file_exists($this->DKIM_private)
                     )
                 )
             ) {
@@ -1482,7 +1566,7 @@ class PHPMailer
                     $this->encodeHeader($this->secureHeader($this->Subject)),
                     $this->MIMEBody
                 );
-                $this->MIMEHeader = rtrim($this->MIMEHeader, "\r\n ") . static::$LE .
+                $this->MIMEHeader = static::stripTrailingWSP($this->MIMEHeader) . static::$LE .
                     static::normalizeBreaks($header_dkim) . static::$LE;
             }
 
@@ -1538,7 +1622,7 @@ class PHPMailer
     /**
      * Send mail using the $Sendmail program.
      *
-     * @see    PHPMailer::$Sendmail
+     * @see PHPMailer::$Sendmail
      *
      * @param string $header The message headers
      * @param string $body   The message body
@@ -1549,19 +1633,19 @@ class PHPMailer
      */
     protected function sendmailSend($header, $body)
     {
+        $header = static::stripTrailingWSP($header) . static::$LE . static::$LE;
+
         // CVE-2016-10033, CVE-2016-10045: Don't pass -f if characters will be escaped.
-        if (!empty($this->Sender) and self::isShellSafe($this->Sender)) {
-            if ('qmail' == $this->Mailer) {
+        if (!empty($this->Sender) && self::isShellSafe($this->Sender)) {
+            if ('qmail' === $this->Mailer) {
                 $sendmailFmt = '%s -f%s';
             } else {
                 $sendmailFmt = '%s -oi -f%s -t';
             }
+        } elseif ('qmail' === $this->Mailer) {
+            $sendmailFmt = '%s';
         } else {
-            if ('qmail' == $this->Mailer) {
-                $sendmailFmt = '%s';
-            } else {
-                $sendmailFmt = '%s -oi -t';
-            }
+            $sendmailFmt = '%s -oi -t';
         }
 
         $sendmail = sprintf($sendmailFmt, escapeshellcmd($this->Sendmail), $this->Sender);
@@ -1577,7 +1661,7 @@ class PHPMailer
                 fwrite($mail, $body);
                 $result = pclose($mail);
                 $this->doCallback(
-                    ($result == 0),
+                    ($result === 0),
                     [$toAddr],
                     $this->cc,
                     $this->bcc,
@@ -1599,7 +1683,7 @@ class PHPMailer
             fwrite($mail, $body);
             $result = pclose($mail);
             $this->doCallback(
-                ($result == 0),
+                ($result === 0),
                 $this->to,
                 $this->cc,
                 $this->bcc,
@@ -1630,7 +1714,7 @@ class PHPMailer
     {
         // Future-proof
         if (escapeshellcmd($string) !== $string
-            or !in_array(escapeshellarg($string), ["'$string'", "\"$string\""])
+            || !in_array(escapeshellarg($string), ["'$string'", "\"$string\""])
         ) {
             return false;
         }
@@ -1668,7 +1752,7 @@ class PHPMailer
     /**
      * Send mail using the PHP mail() function.
      *
-     * @see    http://www.php.net/manual/en/book.mail.php
+     * @see http://www.php.net/manual/en/book.mail.php
      *
      * @param string $header The message headers
      * @param string $body   The message body
@@ -1679,6 +1763,8 @@ class PHPMailer
      */
     protected function mailSend($header, $body)
     {
+        $header = static::stripTrailingWSP($header) . static::$LE . static::$LE;
+
         $toArr = [];
         foreach ($this->to as $toaddr) {
             $toArr[] = $this->addrFormat($toaddr);
@@ -1687,24 +1773,22 @@ class PHPMailer
 
         $params = null;
         //This sets the SMTP envelope sender which gets turned into a return-path header by the receiver
-        if (!empty($this->Sender) and static::validateAddress($this->Sender)) {
-            //A space after `-f` is optional, but there is a long history of its presence
-            //causing problems, so we don't use one
-            //Exim docs: http://www.exim.org/exim-html-current/doc/html/spec_html/ch-the_exim_command_line.html
-            //Sendmail docs: http://www.sendmail.org/~ca/email/man/sendmail.html
-            //Qmail docs: http://www.qmail.org/man/man8/qmail-inject.html
-            //Example problem: https://www.drupal.org/node/1057954
-            // CVE-2016-10033, CVE-2016-10045: Don't pass -f if characters will be escaped.
-            if (self::isShellSafe($this->Sender)) {
-                $params = sprintf('-f%s', $this->Sender);
-            }
+        //A space after `-f` is optional, but there is a long history of its presence
+        //causing problems, so we don't use one
+        //Exim docs: http://www.exim.org/exim-html-current/doc/html/spec_html/ch-the_exim_command_line.html
+        //Sendmail docs: http://www.sendmail.org/~ca/email/man/sendmail.html
+        //Qmail docs: http://www.qmail.org/man/man8/qmail-inject.html
+        //Example problem: https://www.drupal.org/node/1057954
+        // CVE-2016-10033, CVE-2016-10045: Don't pass -f if characters will be escaped.
+        if (!empty($this->Sender) && static::validateAddress($this->Sender) && self::isShellSafe($this->Sender)) {
+            $params = sprintf('-f%s', $this->Sender);
         }
-        if (!empty($this->Sender) and static::validateAddress($this->Sender)) {
+        if (!empty($this->Sender) && static::validateAddress($this->Sender)) {
             $old_from = ini_get('sendmail_from');
             ini_set('sendmail_from', $this->Sender);
         }
         $result = false;
-        if ($this->SingleTo and count($toArr) > 1) {
+        if ($this->SingleTo && count($toArr) > 1) {
             foreach ($toArr as $toAddr) {
                 $result = $this->mailPassthru($toAddr, $this->Subject, $body, $header, $params);
                 $this->doCallback($result, [$toAddr], $this->cc, $this->bcc, $this->Subject, $body, $this->From, []);
@@ -1742,8 +1826,6 @@ class PHPMailer
     /**
      * Provide an instance to use for SMTP operations.
      *
-     * @param SMTP $smtp
-     *
      * @return SMTP
      */
     public function setSMTPInstance(SMTP $smtp)
@@ -1770,12 +1852,13 @@ class PHPMailer
      */
     protected function smtpSend($header, $body)
     {
+        $header = static::stripTrailingWSP($header) . static::$LE . static::$LE;
         $bad_rcpt = [];
         if (!$this->smtpConnect($this->SMTPOptions)) {
             throw new Exception($this->lang('smtp_connect_failed'), self::STOP_CRITICAL);
         }
         //Sender already validated in preSend()
-        if ('' == $this->Sender) {
+        if ('' === $this->Sender) {
             $smtp_from = $this->From;
         } else {
             $smtp_from = $this->Sender;
@@ -1789,7 +1872,7 @@ class PHPMailer
         // Attempt to send to all recipients
         foreach ([$this->to, $this->cc, $this->bcc] as $togroup) {
             foreach ($togroup as $to) {
-                if (!$this->smtp->recipient($to[0])) {
+                if (!$this->smtp->recipient($to[0], $this->dsn)) {
                     $error = $this->smtp->getError();
                     $bad_rcpt[] = ['to' => $to[0], 'error' => $error['detail']];
                     $isSent = false;
@@ -1802,7 +1885,7 @@ class PHPMailer
         }
 
         // Only send the DATA command if we have viable recipients
-        if ((count($this->all_recipients) > count($bad_rcpt)) and !$this->smtp->data($header . $body)) {
+        if ((count($this->all_recipients) > count($bad_rcpt)) && !$this->smtp->data($header . $body)) {
             throw new Exception($this->lang('data_not_accepted'), self::STOP_CRITICAL);
         }
 
@@ -1834,10 +1917,7 @@ class PHPMailer
             foreach ($bad_rcpt as $bad) {
                 $errstr .= $bad['to'] . ': ' . $bad['error'];
             }
-            throw new Exception(
-                $this->lang('recipients_failed') . $errstr,
-                self::STOP_CONTINUE
-            );
+            throw new Exception($this->lang('recipients_failed') . $errstr, self::STOP_CONTINUE);
         }
 
         return true;
@@ -1881,50 +1961,49 @@ class PHPMailer
         foreach ($hosts as $hostentry) {
             $hostinfo = [];
             if (!preg_match(
-                '/^((ssl|tls):\/\/)*([a-zA-Z0-9\.-]*|\[[a-fA-F0-9:]+\]):?([0-9]*)$/',
+                '/^(?:(ssl|tls):\/\/)?(.+?)(?::(\d+))?$/',
                 trim($hostentry),
                 $hostinfo
             )) {
-                static::edebug($this->lang('connect_host') . ' ' . $hostentry);
+                $this->edebug($this->lang('invalid_hostentry') . ' ' . trim($hostentry));
                 // Not a valid host entry
                 continue;
             }
-            // $hostinfo[2]: optional ssl or tls prefix
-            // $hostinfo[3]: the hostname
-            // $hostinfo[4]: optional port number
+            // $hostinfo[1]: optional ssl or tls prefix
+            // $hostinfo[2]: the hostname
+            // $hostinfo[3]: optional port number
             // The host string prefix can temporarily override the current setting for SMTPSecure
             // If it's not specified, the default value is used
 
             //Check the host name is a valid name or IP address before trying to use it
-            if (!static::isValidHost($hostinfo[3])) {
-                static::edebug($this->lang('connect_host') . ' ' . $hostentry);
+            if (!static::isValidHost($hostinfo[2])) {
+                $this->edebug($this->lang('invalid_host') . ' ' . $hostinfo[2]);
                 continue;
             }
             $prefix = '';
             $secure = $this->SMTPSecure;
-            $tls = ('tls' == $this->SMTPSecure);
-            if ('ssl' == $hostinfo[2] or ('' == $hostinfo[2] and 'ssl' == $this->SMTPSecure)) {
+            $tls = (static::ENCRYPTION_STARTTLS === $this->SMTPSecure);
+            if ('ssl' === $hostinfo[1] || ('' === $hostinfo[1] && static::ENCRYPTION_SMTPS === $this->SMTPSecure)) {
                 $prefix = 'ssl://';
                 $tls = false; // Can't have SSL and TLS at the same time
-                $secure = 'ssl';
-            } elseif ('tls' == $hostinfo[2]) {
+                $secure = static::ENCRYPTION_SMTPS;
+            } elseif ('tls' === $hostinfo[1]) {
                 $tls = true;
                 // tls doesn't use a prefix
-                $secure = 'tls';
+                $secure = static::ENCRYPTION_STARTTLS;
             }
             //Do we need the OpenSSL extension?
             $sslext = defined('OPENSSL_ALGO_SHA256');
-            if ('tls' === $secure or 'ssl' === $secure) {
+            if (static::ENCRYPTION_STARTTLS === $secure || static::ENCRYPTION_SMTPS === $secure) {
                 //Check for an OpenSSL constant rather than using extension_loaded, which is sometimes disabled
                 if (!$sslext) {
                     throw new Exception($this->lang('extension_missing') . 'openssl', self::STOP_CRITICAL);
                 }
             }
-            $host = $hostinfo[3];
+            $host = $hostinfo[2];
             $port = $this->Port;
-            $tport = (int) $hostinfo[4];
-            if ($tport > 0 and $tport < 65536) {
-                $port = $tport;
+            if (array_key_exists(3, $hostinfo) && is_numeric($hostinfo[3]) && $hostinfo[3] > 0 && $hostinfo[3] < 65536) {
+                $port = (int) $hostinfo[3];
             }
             if ($this->smtp->connect($prefix . $host, $port, $this->Timeout, $options)) {
                 try {
@@ -1939,7 +2018,7 @@ class PHPMailer
                     // * we have openssl extension
                     // * we are not already using SSL
                     // * the server offers STARTTLS
-                    if ($this->SMTPAutoTLS and $sslext and 'ssl' != $secure and $this->smtp->getServerExt('STARTTLS')) {
+                    if ($this->SMTPAutoTLS && $sslext && 'ssl' !== $secure && $this->smtp->getServerExt('STARTTLS')) {
                         $tls = true;
                     }
                     if ($tls) {
@@ -1949,16 +2028,13 @@ class PHPMailer
                         // We must resend EHLO after TLS negotiation
                         $this->smtp->hello($hello);
                     }
-                    if ($this->SMTPAuth) {
-                        if (!$this->smtp->authenticate(
-                            $this->Username,
-                            $this->Password,
-                            $this->AuthType,
-                            $this->oauth
-                        )
-                        ) {
-                            throw new Exception($this->lang('authenticate'));
-                        }
+                    if ($this->SMTPAuth && !$this->smtp->authenticate(
+                        $this->Username,
+                        $this->Password,
+                        $this->AuthType,
+                        $this->oauth
+                    )) {
+                        throw new Exception($this->lang('authenticate'));
                     }
 
                     return true;
@@ -1973,7 +2049,7 @@ class PHPMailer
         // If we get here, all connection attempts have failed, so close connection hard
         $this->smtp->close();
         // As we've caught all exceptions, just report whatever the last one was
-        if ($this->exceptions and null !== $lastexception) {
+        if ($this->exceptions && null !== $lastexception) {
             throw $lastexception;
         }
 
@@ -1985,11 +2061,9 @@ class PHPMailer
      */
     public function smtpClose()
     {
-        if (null !== $this->smtp) {
-            if ($this->smtp->connected()) {
-                $this->smtp->quit();
-                $this->smtp->close();
-            }
+        if ((null !== $this->smtp) && $this->smtp->connected()) {
+            $this->smtp->quit();
+            $this->smtp->close();
         }
     }
 
@@ -2014,6 +2088,7 @@ class PHPMailer
             'se' => 'sv',
             'rs' => 'sr',
             'tg' => 'tl',
+            'am' => 'hy',
         ];
 
         if (isset($renamed_langcodes[$langcode])) {
@@ -2033,6 +2108,8 @@ class PHPMailer
             'from_failed' => 'The following From address failed: ',
             'instantiate' => 'Could not instantiate mail function.',
             'invalid_address' => 'Invalid address: ',
+            'invalid_hostentry' => 'Invalid hostentry: ',
+            'invalid_host' => 'Invalid host: ',
             'mailer_not_supported' => ' mailer is not supported.',
             'provide_address' => 'You must provide at least one recipient email address.',
             'recipients_failed' => 'SMTP Error: The following recipients failed: ',
@@ -2053,7 +2130,7 @@ class PHPMailer
         $foundlang = true;
         $lang_file = $lang_path . 'phpmailer.lang-' . $langcode . '.php';
         // There is no English translation file
-        if ('en' != $langcode) {
+        if ('en' !== $langcode) {
             // Make sure language file path is readable
             if (!static::isPermittedPath($lang_file) || !file_exists($lang_file)) {
                 $foundlang = false;
@@ -2113,9 +2190,8 @@ class PHPMailer
             return $this->secureHeader($addr[0]);
         }
 
-        return $this->encodeHeader($this->secureHeader($addr[1]), 'phrase') . ' <' . $this->secureHeader(
-                $addr[0]
-            ) . '>';
+        return $this->encodeHeader($this->secureHeader($addr[1]), 'phrase') .
+            ' <' . $this->secureHeader($addr[0]) . '>';
     }
 
     /**
@@ -2145,7 +2221,7 @@ class PHPMailer
 
         $message = static::normalizeBreaks($message);
         //Remove a trailing line break
-        if (substr($message, -$lelen) == static::$LE) {
+        if (substr($message, -$lelen) === static::$LE) {
             $message = substr($message, 0, -$lelen);
         }
 
@@ -2158,16 +2234,16 @@ class PHPMailer
             $buf = '';
             $firstword = true;
             foreach ($words as $word) {
-                if ($qp_mode and (strlen($word) > $length)) {
+                if ($qp_mode && (strlen($word) > $length)) {
                     $space_left = $length - strlen($buf) - $crlflen;
                     if (!$firstword) {
                         if ($space_left > 20) {
                             $len = $space_left;
                             if ($is_utf8) {
                                 $len = $this->utf8CharBoundary($word, $len);
-                            } elseif ('=' == substr($word, $len - 1, 1)) {
+                            } elseif ('=' === substr($word, $len - 1, 1)) {
                                 --$len;
-                            } elseif ('=' == substr($word, $len - 2, 1)) {
+                            } elseif ('=' === substr($word, $len - 2, 1)) {
                                 $len -= 2;
                             }
                             $part = substr($word, 0, $len);
@@ -2179,22 +2255,22 @@ class PHPMailer
                         }
                         $buf = '';
                     }
-                    while (strlen($word) > 0) {
+                    while ($word !== '') {
                         if ($length <= 0) {
                             break;
                         }
                         $len = $length;
                         if ($is_utf8) {
                             $len = $this->utf8CharBoundary($word, $len);
-                        } elseif ('=' == substr($word, $len - 1, 1)) {
+                        } elseif ('=' === substr($word, $len - 1, 1)) {
                             --$len;
-                        } elseif ('=' == substr($word, $len - 2, 1)) {
+                        } elseif ('=' === substr($word, $len - 2, 1)) {
                             $len -= 2;
                         }
                         $part = substr($word, 0, $len);
-                        $word = substr($word, $len);
+                        $word = (string) substr($word, $len);
 
-                        if (strlen($word) > 0) {
+                        if ($word !== '') {
                             $message .= $part . sprintf('=%s', static::$LE);
                         } else {
                             $buf = $part;
@@ -2207,7 +2283,7 @@ class PHPMailer
                     }
                     $buf .= $word;
 
-                    if (strlen($buf) > $length and '' != $buf_o) {
+                    if ('' !== $buf_o && strlen($buf) > $length) {
                         $message .= $buf_o . $soft_break;
                         $buf = $word;
                     }
@@ -2302,23 +2378,21 @@ class PHPMailer
     {
         $result = '';
 
-        $result .= $this->headerLine('Date', '' == $this->MessageDate ? self::rfcDate() : $this->MessageDate);
+        $result .= $this->headerLine('Date', '' === $this->MessageDate ? self::rfcDate() : $this->MessageDate);
 
         // To be created automatically by mail()
         if ($this->SingleTo) {
-            if ('mail' != $this->Mailer) {
+            if ('mail' !== $this->Mailer) {
                 foreach ($this->to as $toaddr) {
                     $this->SingleToArray[] = $this->addrFormat($toaddr);
                 }
             }
-        } else {
-            if (count($this->to) > 0) {
-                if ('mail' != $this->Mailer) {
-                    $result .= $this->addrAppend('To', $this->to);
-                }
-            } elseif (count($this->cc) == 0) {
-                $result .= $this->headerLine('To', 'undisclosed-recipients:;');
+        } elseif (count($this->to) > 0) {
+            if ('mail' !== $this->Mailer) {
+                $result .= $this->addrAppend('To', $this->to);
             }
+        } elseif (count($this->cc) === 0) {
+            $result .= $this->headerLine('To', 'undisclosed-recipients:;');
         }
 
         $result .= $this->addrAppend('From', [[trim($this->From), $this->FromName]]);
@@ -2330,9 +2404,9 @@ class PHPMailer
 
         // sendmail and mail() extract Bcc from the header before sending
         if ((
-                'sendmail' == $this->Mailer or 'qmail' == $this->Mailer or 'mail' == $this->Mailer
+                'sendmail' === $this->Mailer || 'qmail' === $this->Mailer || 'mail' === $this->Mailer
             )
-            and count($this->bcc) > 0
+            && count($this->bcc) > 0
         ) {
             $result .= $this->addrAppend('Bcc', $this->bcc);
         }
@@ -2342,13 +2416,13 @@ class PHPMailer
         }
 
         // mail() sets the subject itself
-        if ('mail' != $this->Mailer) {
+        if ('mail' !== $this->Mailer) {
             $result .= $this->headerLine('Subject', $this->encodeHeader($this->secureHeader($this->Subject)));
         }
 
         // Only allow a custom message ID if it conforms to RFC 5322 section 3.6.4
         // https://tools.ietf.org/html/rfc5322#section-3.6.4
-        if ('' != $this->MessageID and preg_match('/^<.*@.*>$/', $this->MessageID)) {
+        if ('' !== $this->MessageID && preg_match('/^<.*@.*>$/', $this->MessageID)) {
             $this->lastMessageID = $this->MessageID;
         } else {
             $this->lastMessageID = sprintf('<%s@%s>', $this->uniqueid, $this->serverHostname());
@@ -2357,7 +2431,7 @@ class PHPMailer
         if (null !== $this->Priority) {
             $result .= $this->headerLine('X-Priority', $this->Priority);
         }
-        if ('' == $this->XMailer) {
+        if ('' === $this->XMailer) {
             $result .= $this->headerLine(
                 'X-Mailer',
                 'PHPMailer ' . self::VERSION . ' (https://github.com/PHPMailer/PHPMailer)'
@@ -2369,7 +2443,7 @@ class PHPMailer
             }
         }
 
-        if ('' != $this->ConfirmReadingTo) {
+        if ('' !== $this->ConfirmReadingTo) {
             $result .= $this->headerLine('Disposition-Notification-To', '<' . $this->ConfirmReadingTo . '>');
         }
 
@@ -2400,19 +2474,19 @@ class PHPMailer
         switch ($this->message_type) {
             case 'inline':
                 $result .= $this->headerLine('Content-Type', static::CONTENT_TYPE_MULTIPART_RELATED . ';');
-                $result .= $this->textLine("\tboundary=\"" . $this->boundary[1] . '"');
+                $result .= $this->textLine(' boundary="' . $this->boundary[1] . '"');
                 break;
             case 'attach':
             case 'inline_attach':
             case 'alt_attach':
             case 'alt_inline_attach':
                 $result .= $this->headerLine('Content-Type', static::CONTENT_TYPE_MULTIPART_MIXED . ';');
-                $result .= $this->textLine("\tboundary=\"" . $this->boundary[1] . '"');
+                $result .= $this->textLine(' boundary="' . $this->boundary[1] . '"');
                 break;
             case 'alt':
             case 'alt_inline':
                 $result .= $this->headerLine('Content-Type', static::CONTENT_TYPE_MULTIPART_ALTERNATIVE . ';');
-                $result .= $this->textLine("\tboundary=\"" . $this->boundary[1] . '"');
+                $result .= $this->textLine(' boundary="' . $this->boundary[1] . '"');
                 break;
             default:
                 // Catches case 'plain': and case '':
@@ -2421,10 +2495,10 @@ class PHPMailer
                 break;
         }
         // RFC1341 part 5 says 7bit is assumed if not specified
-        if (static::ENCODING_7BIT != $this->Encoding) {
+        if (static::ENCODING_7BIT !== $this->Encoding) {
             // RFC 2045 section 6.4 says multipart MIME parts may only use 7bit, 8bit or binary CTE
             if ($ismultipart) {
-                if (static::ENCODING_8BIT == $this->Encoding) {
+                if (static::ENCODING_8BIT === $this->Encoding) {
                     $result .= $this->headerLine('Content-Transfer-Encoding', static::ENCODING_8BIT);
                 }
                 // The only remaining alternatives are quoted-printable and base64, which are both 7bit compatible
@@ -2433,8 +2507,8 @@ class PHPMailer
             }
         }
 
-        if ('mail' != $this->Mailer) {
-            $result .= static::$LE;
+        if ('mail' !== $this->Mailer) {
+//            $result .= static::$LE;
         }
 
         return $result;
@@ -2451,7 +2525,8 @@ class PHPMailer
      */
     public function getSentMIMEMessage()
     {
-        return rtrim($this->MIMEHeader . $this->mailHeader, "\n\r") . static::$LE . static::$LE . $this->MIMEBody;
+        return static::stripTrailingWSP($this->MIMEHeader . $this->mailHeader) .
+            static::$LE . static::$LE . $this->MIMEBody;
     }
 
     /**
@@ -2462,11 +2537,19 @@ class PHPMailer
     protected function generateId()
     {
         $len = 32; //32 bytes = 256 bits
+        $bytes = '';
         if (function_exists('random_bytes')) {
-            $bytes = random_bytes($len);
+            try {
+                $bytes = random_bytes($len);
+            } catch (\Exception $e) {
+                //Do nothing
+            }
         } elseif (function_exists('openssl_random_pseudo_bytes')) {
+            /** @noinspection CryptographicallySecureRandomnessInspection */
             $bytes = openssl_random_pseudo_bytes($len);
-        } else {
+        }
+        if ($bytes === '') {
+            //We failed to produce a proper random string, so make do.
             //Use a hash to force the length to the same as the other methods
             $bytes = hash('sha256', uniqid((string) mt_rand(), true), true);
         }
@@ -2501,32 +2584,32 @@ class PHPMailer
         $bodyEncoding = $this->Encoding;
         $bodyCharSet = $this->CharSet;
         //Can we do a 7-bit downgrade?
-        if (static::ENCODING_8BIT == $bodyEncoding and !$this->has8bitChars($this->Body)) {
+        if (static::ENCODING_8BIT === $bodyEncoding && !$this->has8bitChars($this->Body)) {
             $bodyEncoding = static::ENCODING_7BIT;
             //All ISO 8859, Windows codepage and UTF-8 charsets are ascii compatible up to 7-bit
-            $bodyCharSet = 'us-ascii';
+            $bodyCharSet = static::CHARSET_ASCII;
         }
         //If lines are too long, and we're not already using an encoding that will shorten them,
         //change to quoted-printable transfer encoding for the body part only
-        if (static::ENCODING_BASE64 != $this->Encoding and static::hasLineLongerThanMax($this->Body)) {
+        if (static::ENCODING_BASE64 !== $this->Encoding && static::hasLineLongerThanMax($this->Body)) {
             $bodyEncoding = static::ENCODING_QUOTED_PRINTABLE;
         }
 
         $altBodyEncoding = $this->Encoding;
         $altBodyCharSet = $this->CharSet;
         //Can we do a 7-bit downgrade?
-        if (static::ENCODING_8BIT == $altBodyEncoding and !$this->has8bitChars($this->AltBody)) {
+        if (static::ENCODING_8BIT === $altBodyEncoding && !$this->has8bitChars($this->AltBody)) {
             $altBodyEncoding = static::ENCODING_7BIT;
             //All ISO 8859, Windows codepage and UTF-8 charsets are ascii compatible up to 7-bit
-            $altBodyCharSet = 'us-ascii';
+            $altBodyCharSet = static::CHARSET_ASCII;
         }
         //If lines are too long, and we're not already using an encoding that will shorten them,
         //change to quoted-printable transfer encoding for the alt body part only
-        if (static::ENCODING_BASE64 != $altBodyEncoding and static::hasLineLongerThanMax($this->AltBody)) {
+        if (static::ENCODING_BASE64 !== $altBodyEncoding && static::hasLineLongerThanMax($this->AltBody)) {
             $altBodyEncoding = static::ENCODING_QUOTED_PRINTABLE;
         }
         //Use this as a preamble in all multipart message types
-        $mimepre = 'This is a multi-part message in MIME format.' . static::$LE;
+        $mimepre = 'This is a multi-part message in MIME format.' . static::$LE . static::$LE;
         switch ($this->message_type) {
             case 'inline':
                 $body .= $mimepre;
@@ -2546,7 +2629,8 @@ class PHPMailer
                 $body .= $mimepre;
                 $body .= $this->textLine('--' . $this->boundary[1]);
                 $body .= $this->headerLine('Content-Type', static::CONTENT_TYPE_MULTIPART_RELATED . ';');
-                $body .= $this->textLine("\tboundary=\"" . $this->boundary[2] . '"');
+                $body .= $this->textLine(' boundary="' . $this->boundary[2] . '";');
+                $body .= $this->textLine(' type="' . static::CONTENT_TYPE_TEXT_HTML . '"');
                 $body .= static::$LE;
                 $body .= $this->getBoundary($this->boundary[2], $bodyCharSet, '', $bodyEncoding);
                 $body .= $this->encodeString($this->Body, $bodyEncoding);
@@ -2557,14 +2641,36 @@ class PHPMailer
                 break;
             case 'alt':
                 $body .= $mimepre;
-                $body .= $this->getBoundary($this->boundary[1], $altBodyCharSet, static::CONTENT_TYPE_PLAINTEXT, $altBodyEncoding);
+                $body .= $this->getBoundary(
+                    $this->boundary[1],
+                    $altBodyCharSet,
+                    static::CONTENT_TYPE_PLAINTEXT,
+                    $altBodyEncoding
+                );
                 $body .= $this->encodeString($this->AltBody, $altBodyEncoding);
                 $body .= static::$LE;
-                $body .= $this->getBoundary($this->boundary[1], $bodyCharSet, static::CONTENT_TYPE_TEXT_HTML, $bodyEncoding);
+                $body .= $this->getBoundary(
+                    $this->boundary[1],
+                    $bodyCharSet,
+                    static::CONTENT_TYPE_TEXT_HTML,
+                    $bodyEncoding
+                );
                 $body .= $this->encodeString($this->Body, $bodyEncoding);
                 $body .= static::$LE;
                 if (!empty($this->Ical)) {
-                    $body .= $this->getBoundary($this->boundary[1], '', static::CONTENT_TYPE_TEXT_CALENDAR . '; method=REQUEST', '');
+                    $method = static::ICAL_METHOD_REQUEST;
+                    foreach (static::$IcalMethods as $imethod) {
+                        if (stripos($this->Ical, 'METHOD:' . $imethod) !== false) {
+                            $method = $imethod;
+                            break;
+                        }
+                    }
+                    $body .= $this->getBoundary(
+                        $this->boundary[1],
+                        '',
+                        static::CONTENT_TYPE_TEXT_CALENDAR . '; method=' . $method,
+                        ''
+                    );
                     $body .= $this->encodeString($this->Ical, $this->Encoding);
                     $body .= static::$LE;
                 }
@@ -2572,14 +2678,25 @@ class PHPMailer
                 break;
             case 'alt_inline':
                 $body .= $mimepre;
-                $body .= $this->getBoundary($this->boundary[1], $altBodyCharSet, static::CONTENT_TYPE_PLAINTEXT, $altBodyEncoding);
+                $body .= $this->getBoundary(
+                    $this->boundary[1],
+                    $altBodyCharSet,
+                    static::CONTENT_TYPE_PLAINTEXT,
+                    $altBodyEncoding
+                );
                 $body .= $this->encodeString($this->AltBody, $altBodyEncoding);
                 $body .= static::$LE;
                 $body .= $this->textLine('--' . $this->boundary[1]);
                 $body .= $this->headerLine('Content-Type', static::CONTENT_TYPE_MULTIPART_RELATED . ';');
-                $body .= $this->textLine("\tboundary=\"" . $this->boundary[2] . '"');
+                $body .= $this->textLine(' boundary="' . $this->boundary[2] . '";');
+                $body .= $this->textLine(' type="' . static::CONTENT_TYPE_TEXT_HTML . '"');
                 $body .= static::$LE;
-                $body .= $this->getBoundary($this->boundary[2], $bodyCharSet, static::CONTENT_TYPE_TEXT_HTML, $bodyEncoding);
+                $body .= $this->getBoundary(
+                    $this->boundary[2],
+                    $bodyCharSet,
+                    static::CONTENT_TYPE_TEXT_HTML,
+                    $bodyEncoding
+                );
                 $body .= $this->encodeString($this->Body, $bodyEncoding);
                 $body .= static::$LE;
                 $body .= $this->attachAll('inline', $this->boundary[2]);
@@ -2590,16 +2707,38 @@ class PHPMailer
                 $body .= $mimepre;
                 $body .= $this->textLine('--' . $this->boundary[1]);
                 $body .= $this->headerLine('Content-Type', static::CONTENT_TYPE_MULTIPART_ALTERNATIVE . ';');
-                $body .= $this->textLine("\tboundary=\"" . $this->boundary[2] . '"');
+                $body .= $this->textLine(' boundary="' . $this->boundary[2] . '"');
                 $body .= static::$LE;
-                $body .= $this->getBoundary($this->boundary[2], $altBodyCharSet, static::CONTENT_TYPE_PLAINTEXT, $altBodyEncoding);
+                $body .= $this->getBoundary(
+                    $this->boundary[2],
+                    $altBodyCharSet,
+                    static::CONTENT_TYPE_PLAINTEXT,
+                    $altBodyEncoding
+                );
                 $body .= $this->encodeString($this->AltBody, $altBodyEncoding);
                 $body .= static::$LE;
-                $body .= $this->getBoundary($this->boundary[2], $bodyCharSet, static::CONTENT_TYPE_TEXT_HTML, $bodyEncoding);
+                $body .= $this->getBoundary(
+                    $this->boundary[2],
+                    $bodyCharSet,
+                    static::CONTENT_TYPE_TEXT_HTML,
+                    $bodyEncoding
+                );
                 $body .= $this->encodeString($this->Body, $bodyEncoding);
                 $body .= static::$LE;
                 if (!empty($this->Ical)) {
-                    $body .= $this->getBoundary($this->boundary[2], '', static::CONTENT_TYPE_TEXT_CALENDAR . '; method=REQUEST', '');
+                    $method = static::ICAL_METHOD_REQUEST;
+                    foreach (static::$IcalMethods as $imethod) {
+                        if (stripos($this->Ical, 'METHOD:' . $imethod) !== false) {
+                            $method = $imethod;
+                            break;
+                        }
+                    }
+                    $body .= $this->getBoundary(
+                        $this->boundary[2],
+                        '',
+                        static::CONTENT_TYPE_TEXT_CALENDAR . '; method=' . $method,
+                        ''
+                    );
                     $body .= $this->encodeString($this->Ical, $this->Encoding);
                 }
                 $body .= $this->endBoundary($this->boundary[2]);
@@ -2610,16 +2749,27 @@ class PHPMailer
                 $body .= $mimepre;
                 $body .= $this->textLine('--' . $this->boundary[1]);
                 $body .= $this->headerLine('Content-Type', static::CONTENT_TYPE_MULTIPART_ALTERNATIVE . ';');
-                $body .= $this->textLine("\tboundary=\"" . $this->boundary[2] . '"');
+                $body .= $this->textLine(' boundary="' . $this->boundary[2] . '"');
                 $body .= static::$LE;
-                $body .= $this->getBoundary($this->boundary[2], $altBodyCharSet, static::CONTENT_TYPE_PLAINTEXT, $altBodyEncoding);
+                $body .= $this->getBoundary(
+                    $this->boundary[2],
+                    $altBodyCharSet,
+                    static::CONTENT_TYPE_PLAINTEXT,
+                    $altBodyEncoding
+                );
                 $body .= $this->encodeString($this->AltBody, $altBodyEncoding);
                 $body .= static::$LE;
                 $body .= $this->textLine('--' . $this->boundary[2]);
                 $body .= $this->headerLine('Content-Type', static::CONTENT_TYPE_MULTIPART_RELATED . ';');
-                $body .= $this->textLine("\tboundary=\"" . $this->boundary[3] . '"');
+                $body .= $this->textLine(' boundary="' . $this->boundary[3] . '";');
+                $body .= $this->textLine(' type="' . static::CONTENT_TYPE_TEXT_HTML . '"');
                 $body .= static::$LE;
-                $body .= $this->getBoundary($this->boundary[3], $bodyCharSet, static::CONTENT_TYPE_TEXT_HTML, $bodyEncoding);
+                $body .= $this->getBoundary(
+                    $this->boundary[3],
+                    $bodyCharSet,
+                    static::CONTENT_TYPE_TEXT_HTML,
+                    $bodyEncoding
+                );
                 $body .= $this->encodeString($this->Body, $bodyEncoding);
                 $body .= static::$LE;
                 $body .= $this->attachAll('inline', $this->boundary[3]);
@@ -2646,12 +2796,11 @@ class PHPMailer
                 if (!defined('PKCS7_TEXT')) {
                     throw new Exception($this->lang('extension_missing') . 'openssl');
                 }
-                // @TODO would be nice to use php://temp streams here
-                $file = tempnam(sys_get_temp_dir(), 'mail');
-                if (false === file_put_contents($file, $body)) {
-                    throw new Exception($this->lang('signing') . ' Could not write temp file');
-                }
-                $signed = tempnam(sys_get_temp_dir(), 'signed');
+
+                $file = tempnam(sys_get_temp_dir(), 'srcsign');
+                $signed = tempnam(sys_get_temp_dir(), 'mailsign');
+                file_put_contents($file, $body);
+
                 //Workaround for PHP bug https://bugs.php.net/bug.php?id=69197
                 if (empty($this->sign_extracerts_file)) {
                     $sign = @openssl_pkcs7_sign(
@@ -2672,6 +2821,7 @@ class PHPMailer
                         $this->sign_extracerts_file
                     );
                 }
+
                 @unlink($file);
                 if ($sign) {
                     $body = file_get_contents($signed);
@@ -2708,20 +2858,20 @@ class PHPMailer
     protected function getBoundary($boundary, $charSet, $contentType, $encoding)
     {
         $result = '';
-        if ('' == $charSet) {
+        if ('' === $charSet) {
             $charSet = $this->CharSet;
         }
-        if ('' == $contentType) {
+        if ('' === $contentType) {
             $contentType = $this->ContentType;
         }
-        if ('' == $encoding) {
+        if ('' === $encoding) {
             $encoding = $this->Encoding;
         }
         $result .= $this->textLine('--' . $boundary);
         $result .= sprintf('Content-Type: %s; charset=%s', $contentType, $charSet);
         $result .= static::$LE;
         // RFC1341 part 5 says 7bit is assumed if not specified
-        if (static::ENCODING_7BIT != $encoding) {
+        if (static::ENCODING_7BIT !== $encoding) {
             $result .= $this->headerLine('Content-Transfer-Encoding', $encoding);
         }
         $result .= static::$LE;
@@ -2758,7 +2908,7 @@ class PHPMailer
             $type[] = 'attach';
         }
         $this->message_type = implode('_', $type);
-        if ('' == $this->message_type) {
+        if ('' === $this->message_type) {
             //The 'plain' message_type refers to the message having a single body element, not that it is plain-text
             $this->message_type = 'plain';
         }
@@ -2806,22 +2956,30 @@ class PHPMailer
      *
      * @return bool
      */
-    public function addAttachment($path, $name = '', $encoding = self::ENCODING_BASE64, $type = '', $disposition = 'attachment')
-    {
+    public function addAttachment(
+        $path,
+        $name = '',
+        $encoding = self::ENCODING_BASE64,
+        $type = '',
+        $disposition = 'attachment'
+    ) {
         try {
-            if (!static::isPermittedPath($path) || !@is_file($path)) {
+            if (!static::isPermittedPath($path) || !@is_file($path) || !is_readable($path)) {
                 throw new Exception($this->lang('file_access') . $path, self::STOP_CONTINUE);
             }
 
             // If a MIME type is not specified, try to work it out from the file name
-            if ('' == $type) {
+            if ('' === $type) {
                 $type = static::filenameToType($path);
             }
 
-            $filename = basename($path);
-            if ('' == $name) {
+            $filename = (string) static::mb_pathinfo($path, PATHINFO_BASENAME);
+            if ('' === $name) {
                 $name = $filename;
             }
+            if (!$this->validateEncoding($encoding)) {
+                throw new Exception($this->lang('encoding') . $encoding);
+            }
 
             $this->attachment[] = [
                 0 => $path,
@@ -2863,6 +3021,8 @@ class PHPMailer
      * @param string $disposition_type
      * @param string $boundary
      *
+     * @throws Exception
+     *
      * @return string
      */
     protected function attachAll($disposition_type, $boundary)
@@ -2875,7 +3035,7 @@ class PHPMailer
         // Add all attachments
         foreach ($this->attachment as $attachment) {
             // Check if it is a valid disposition_filter
-            if ($attachment[6] == $disposition_type) {
+            if ($attachment[6] === $disposition_type) {
                 // Check for string attachment
                 $string = '';
                 $path = '';
@@ -2887,7 +3047,7 @@ class PHPMailer
                 }
 
                 $inclhash = hash('sha256', serialize($attachment));
-                if (in_array($inclhash, $incl)) {
+                if (in_array($inclhash, $incl, true)) {
                     continue;
                 }
                 $incl[] = $inclhash;
@@ -2896,7 +3056,7 @@ class PHPMailer
                 $type = $attachment[4];
                 $disposition = $attachment[6];
                 $cid = $attachment[7];
-                if ('inline' == $disposition and array_key_exists($cid, $cidUniq)) {
+                if ('inline' === $disposition && array_key_exists($cid, $cidUniq)) {
                     continue;
                 }
                 $cidUniq[$cid] = true;
@@ -2905,9 +3065,9 @@ class PHPMailer
                 //Only include a filename property if we have one
                 if (!empty($name)) {
                     $mime[] = sprintf(
-                        'Content-Type: %s; name="%s"%s',
+                        'Content-Type: %s; name=%s%s',
                         $type,
-                        $this->encodeHeader($this->secureHeader($name)),
+                        static::quotedString($this->encodeHeader($this->secureHeader($name))),
                         static::$LE
                     );
                 } else {
@@ -2918,42 +3078,31 @@ class PHPMailer
                     );
                 }
                 // RFC1341 part 5 says 7bit is assumed if not specified
-                if (static::ENCODING_7BIT != $encoding) {
+                if (static::ENCODING_7BIT !== $encoding) {
                     $mime[] = sprintf('Content-Transfer-Encoding: %s%s', $encoding, static::$LE);
                 }
 
-                if (!empty($cid)) {
-                    $mime[] = sprintf('Content-ID: <%s>%s', $cid, static::$LE);
+                //Only set Content-IDs on inline attachments
+                if ((string) $cid !== '' && $disposition === 'inline') {
+                    $mime[] = 'Content-ID: <' . $this->encodeHeader($this->secureHeader($cid)) . '>' . static::$LE;
                 }
 
-                // If a filename contains any of these chars, it should be quoted,
-                // but not otherwise: RFC2183 & RFC2045 5.1
-                // Fixes a warning in IETF's msglint MIME checker
-                // Allow for bypassing the Content-Disposition header totally
-                if (!(empty($disposition))) {
+                // Allow for bypassing the Content-Disposition header
+                if (!empty($disposition)) {
                     $encoded_name = $this->encodeHeader($this->secureHeader($name));
-                    if (preg_match('/[ \(\)<>@,;:\\"\/\[\]\?=]/', $encoded_name)) {
+                    if (!empty($encoded_name)) {
                         $mime[] = sprintf(
-                            'Content-Disposition: %s; filename="%s"%s',
+                            'Content-Disposition: %s; filename=%s%s',
                             $disposition,
-                            $encoded_name,
+                            static::quotedString($encoded_name),
                             static::$LE . static::$LE
                         );
                     } else {
-                        if (!empty($encoded_name)) {
-                            $mime[] = sprintf(
-                                'Content-Disposition: %s; filename=%s%s',
-                                $disposition,
-                                $encoded_name,
-                                static::$LE . static::$LE
-                            );
-                        } else {
-                            $mime[] = sprintf(
-                                'Content-Disposition: %s%s',
-                                $disposition,
-                                static::$LE . static::$LE
-                            );
-                        }
+                        $mime[] = sprintf(
+                            'Content-Disposition: %s%s',
+                            $disposition,
+                            static::$LE . static::$LE
+                        );
                     }
                 } else {
                     $mime[] = static::$LE;
@@ -2984,14 +3133,12 @@ class PHPMailer
      * @param string $path     The full path to the file
      * @param string $encoding The encoding to use; one of 'base64', '7bit', '8bit', 'binary', 'quoted-printable'
      *
-     * @throws Exception
-     *
      * @return string
      */
     protected function encodeFile($path, $encoding = self::ENCODING_BASE64)
     {
         try {
-            if (!static::isPermittedPath($path) || !file_exists($path)) {
+            if (!static::isPermittedPath($path) || !file_exists($path) || !is_readable($path)) {
                 throw new Exception($this->lang('file_open') . $path, self::STOP_CONTINUE);
             }
             $file_buffer = file_get_contents($path);
@@ -3003,6 +3150,10 @@ class PHPMailer
             return $file_buffer;
         } catch (Exception $exc) {
             $this->setError($exc->getMessage());
+            $this->edebug($exc->getMessage());
+            if ($this->exceptions) {
+                throw $exc;
+            }
 
             return '';
         }
@@ -3015,6 +3166,8 @@ class PHPMailer
      * @param string $str      The text to encode
      * @param string $encoding The encoding to use; one of 'base64', '7bit', '8bit', 'binary', 'quoted-printable'
      *
+     * @throws Exception
+     *
      * @return string
      */
     public function encodeString($str, $encoding = self::ENCODING_BASE64)
@@ -3032,7 +3185,7 @@ class PHPMailer
             case static::ENCODING_8BIT:
                 $encoded = static::normalizeBreaks($str);
                 // Make sure it ends with a line break
-                if (substr($encoded, -(strlen(static::$LE))) != static::$LE) {
+                if (substr($encoded, -(strlen(static::$LE))) !== static::$LE) {
                     $encoded .= static::$LE;
                 }
                 break;
@@ -3044,6 +3197,9 @@ class PHPMailer
                 break;
             default:
                 $this->setError($this->lang('encoding') . $encoding);
+                if ($this->exceptions) {
+                    throw new Exception($this->lang('encoding') . $encoding);
+                }
                 break;
         }
 
@@ -3068,7 +3224,7 @@ class PHPMailer
                 if (!preg_match('/[\200-\377]/', $str)) {
                     // Can't use addslashes as we don't know the value of magic_quotes_sybase
                     $encoded = addcslashes($str, "\0..\37\177\\\"");
-                    if (($str == $encoded) and !preg_match('/[^A-Za-z0-9!#$%&\'*+\/=?^_`{|}~ -]/', $str)) {
+                    if (($str === $encoded) && !preg_match('/[^A-Za-z0-9!#$%&\'*+\/=?^_`{|}~ -]/', $str)) {
                         return $encoded;
                     }
 
@@ -3086,51 +3242,57 @@ class PHPMailer
                 break;
         }
 
-        //RFCs specify a maximum line length of 78 chars, however mail() will sometimes
-        //corrupt messages with headers longer than 65 chars. See #818
-        $lengthsub = 'mail' == $this->Mailer ? 13 : 0;
-        $maxlen = static::STD_LINE_LENGTH - $lengthsub;
-        // Try to select the encoding which should produce the shortest output
+        if ($this->has8bitChars($str)) {
+            $charset = $this->CharSet;
+        } else {
+            $charset = static::CHARSET_ASCII;
+        }
+
+        // Q/B encoding adds 8 chars and the charset ("` =?<charset>?[QB]?<content>?=`").
+        $overhead = 8 + strlen($charset);
+
+        if ('mail' === $this->Mailer) {
+            $maxlen = static::MAIL_MAX_LINE_LENGTH - $overhead;
+        } else {
+            $maxlen = static::MAX_LINE_LENGTH - $overhead;
+        }
+
+        // Select the encoding that produces the shortest output and/or prevents corruption.
         if ($matchcount > strlen($str) / 3) {
-            // More than a third of the content will need encoding, so B encoding will be most efficient
+            // More than 1/3 of the content needs encoding, use B-encode.
             $encoding = 'B';
-            //This calculation is:
-            // max line length
-            // - shorten to avoid mail() corruption
-            // - Q/B encoding char overhead ("` =?<charset>?[QB]?<content>?=`")
-            // - charset name length
-            $maxlen = static::STD_LINE_LENGTH - $lengthsub - 8 - strlen($this->CharSet);
-            if ($this->hasMultiBytes($str)) {
-                // Use a custom function which correctly encodes and wraps long
-                // multibyte strings without breaking lines within a character
-                $encoded = $this->base64EncodeWrapMB($str, "\n");
-            } else {
-                $encoded = base64_encode($str);
-                $maxlen -= $maxlen % 4;
-                $encoded = trim(chunk_split($encoded, $maxlen, "\n"));
-            }
-            $encoded = preg_replace('/^(.*)$/m', ' =?' . $this->CharSet . "?$encoding?\\1?=", $encoded);
         } elseif ($matchcount > 0) {
-            //1 or more chars need encoding, use Q-encode
+            // Less than 1/3 of the content needs encoding, use Q-encode.
             $encoding = 'Q';
-            //Recalc max line length for Q encoding - see comments on B encode
-            $maxlen = static::STD_LINE_LENGTH - $lengthsub - 8 - strlen($this->CharSet);
-            $encoded = $this->encodeQ($str, $position);
-            $encoded = $this->wrapText($encoded, $maxlen, true);
-            $encoded = str_replace('=' . static::$LE, "\n", trim($encoded));
-            $encoded = preg_replace('/^(.*)$/m', ' =?' . $this->CharSet . "?$encoding?\\1?=", $encoded);
         } elseif (strlen($str) > $maxlen) {
-            //No chars need encoding, but line is too long, so fold it
-            $encoded = trim($this->wrapText($str, $maxlen, false));
-            if ($str == $encoded) {
-                //Wrapping nicely didn't work, wrap hard instead
-                $encoded = trim(chunk_split($str, static::STD_LINE_LENGTH, static::$LE));
-            }
-            $encoded = str_replace(static::$LE, "\n", trim($encoded));
-            $encoded = preg_replace('/^(.*)$/m', ' \\1', $encoded);
+            // No encoding needed, but value exceeds max line length, use Q-encode to prevent corruption.
+            $encoding = 'Q';
         } else {
-            //No reformatting needed
-            return $str;
+            // No reformatting needed
+            $encoding = false;
+        }
+
+        switch ($encoding) {
+            case 'B':
+                if ($this->hasMultiBytes($str)) {
+                    // Use a custom function which correctly encodes and wraps long
+                    // multibyte strings without breaking lines within a character
+                    $encoded = $this->base64EncodeWrapMB($str, "\n");
+                } else {
+                    $encoded = base64_encode($str);
+                    $maxlen -= $maxlen % 4;
+                    $encoded = trim(chunk_split($encoded, $maxlen, "\n"));
+                }
+                $encoded = preg_replace('/^(.*)$/m', ' =?' . $charset . "?$encoding?\\1?=", $encoded);
+                break;
+            case 'Q':
+                $encoded = $this->encodeQ($str, $position);
+                $encoded = $this->wrapText($encoded, $maxlen, true);
+                $encoded = str_replace('=' . static::$LE, "\n", trim($encoded));
+                $encoded = preg_replace('/^(.*)$/m', ' =?' . $charset . "?$encoding?\\1?=", $encoded);
+                break;
+            default:
+                return $str;
         }
 
         return trim(static::normalizeBreaks($encoded));
@@ -3194,6 +3356,7 @@ class PHPMailer
         // Base64 has a 4:3 ratio
         $avgLength = floor($length * $ratio * .75);
 
+        $offset = 0;
         for ($i = 0; $i < $mb_length; $i += $offset) {
             $lookBack = 0;
             do {
@@ -3254,7 +3417,6 @@ class PHPMailer
             default:
                 // RFC 2047 section 5.1
                 // Replace every high ascii, control, =, ? and _ characters
-                /** @noinspection SuspiciousAssignmentsInspection */
                 $pattern = '\000-\011\013\014\016-\037\075\077\137\177-\377' . $pattern;
                 break;
         }
@@ -3262,7 +3424,7 @@ class PHPMailer
         if (preg_match_all("/[{$pattern}]/", $encoded, $matches)) {
             // If the string contains an '=', make sure it's the first thing we replace
             // so as to avoid double-encoding
-            $eqkey = array_search('=', $matches[0]);
+            $eqkey = array_search('=', $matches[0], true);
             if (false !== $eqkey) {
                 unset($matches[0][$eqkey]);
                 array_unshift($matches[0], '=');
@@ -3286,6 +3448,10 @@ class PHPMailer
      * @param string $encoding    File encoding (see $Encoding)
      * @param string $type        File extension (MIME) type
      * @param string $disposition Disposition to use
+     *
+     * @throws Exception
+     *
+     * @return bool True on successfully adding an attachment
      */
     public function addStringAttachment(
         $string,
@@ -3294,21 +3460,38 @@ class PHPMailer
         $type = '',
         $disposition = 'attachment'
     ) {
-        // If a MIME type is not specified, try to work it out from the file name
-        if ('' == $type) {
-            $type = static::filenameToType($filename);
-        }
-        // Append to $attachment array
-        $this->attachment[] = [
-            0 => $string,
-            1 => $filename,
-            2 => basename($filename),
-            3 => $encoding,
-            4 => $type,
-            5 => true, // isStringAttachment
-            6 => $disposition,
-            7 => 0,
-        ];
+        try {
+            // If a MIME type is not specified, try to work it out from the file name
+            if ('' === $type) {
+                $type = static::filenameToType($filename);
+            }
+
+            if (!$this->validateEncoding($encoding)) {
+                throw new Exception($this->lang('encoding') . $encoding);
+            }
+
+            // Append to $attachment array
+            $this->attachment[] = [
+                0 => $string,
+                1 => $filename,
+                2 => static::mb_pathinfo($filename, PATHINFO_BASENAME),
+                3 => $encoding,
+                4 => $type,
+                5 => true, // isStringAttachment
+                6 => $disposition,
+                7 => 0,
+            ];
+        } catch (Exception $exc) {
+            $this->setError($exc->getMessage());
+            $this->edebug($exc->getMessage());
+            if ($this->exceptions) {
+                throw $exc;
+            }
+
+            return false;
+        }
+
+        return true;
     }
 
     /**
@@ -3328,37 +3511,57 @@ class PHPMailer
      * @param string $type        File MIME type
      * @param string $disposition Disposition to use
      *
+     * @throws Exception
+     *
      * @return bool True on successfully adding an attachment
      */
-    public function addEmbeddedImage($path, $cid, $name = '', $encoding = self::ENCODING_BASE64, $type = '', $disposition = 'inline')
-    {
-        if (!static::isPermittedPath($path) || !@is_file($path)) {
-            $this->setError($this->lang('file_access') . $path);
+    public function addEmbeddedImage(
+        $path,
+        $cid,
+        $name = '',
+        $encoding = self::ENCODING_BASE64,
+        $type = '',
+        $disposition = 'inline'
+    ) {
+        try {
+            if (!static::isPermittedPath($path) || !@is_file($path) || !is_readable($path)) {
+                throw new Exception($this->lang('file_access') . $path, self::STOP_CONTINUE);
+            }
 
-            return false;
-        }
+            // If a MIME type is not specified, try to work it out from the file name
+            if ('' === $type) {
+                $type = static::filenameToType($path);
+            }
 
-        // If a MIME type is not specified, try to work it out from the file name
-        if ('' == $type) {
-            $type = static::filenameToType($path);
-        }
+            if (!$this->validateEncoding($encoding)) {
+                throw new Exception($this->lang('encoding') . $encoding);
+            }
 
-        $filename = basename($path);
-        if ('' == $name) {
-            $name = $filename;
-        }
+            $filename = (string) static::mb_pathinfo($path, PATHINFO_BASENAME);
+            if ('' === $name) {
+                $name = $filename;
+            }
 
-        // Append to $attachment array
-        $this->attachment[] = [
-            0 => $path,
-            1 => $filename,
-            2 => $name,
-            3 => $encoding,
-            4 => $type,
-            5 => false, // isStringAttachment
-            6 => $disposition,
-            7 => $cid,
-        ];
+            // Append to $attachment array
+            $this->attachment[] = [
+                0 => $path,
+                1 => $filename,
+                2 => $name,
+                3 => $encoding,
+                4 => $type,
+                5 => false, // isStringAttachment
+                6 => $disposition,
+                7 => $cid,
+            ];
+        } catch (Exception $exc) {
+            $this->setError($exc->getMessage());
+            $this->edebug($exc->getMessage());
+            if ($this->exceptions) {
+                throw $exc;
+            }
+
+            return false;
+        }
 
         return true;
     }
@@ -3378,6 +3581,8 @@ class PHPMailer
      * @param string $type        MIME type - will be used in preference to any automatically derived type
      * @param string $disposition Disposition to use
      *
+     * @throws Exception
+     *
      * @return bool True on successfully adding an attachment
      */
     public function addStringEmbeddedImage(
@@ -3388,26 +3593,62 @@ class PHPMailer
         $type = '',
         $disposition = 'inline'
     ) {
-        // If a MIME type is not specified, try to work it out from the name
-        if ('' == $type and !empty($name)) {
-            $type = static::filenameToType($name);
-        }
-
-        // Append to $attachment array
-        $this->attachment[] = [
-            0 => $string,
-            1 => $name,
-            2 => $name,
-            3 => $encoding,
-            4 => $type,
-            5 => true, // isStringAttachment
-            6 => $disposition,
-            7 => $cid,
-        ];
+        try {
+            // If a MIME type is not specified, try to work it out from the name
+            if ('' === $type && !empty($name)) {
+                $type = static::filenameToType($name);
+            }
+
+            if (!$this->validateEncoding($encoding)) {
+                throw new Exception($this->lang('encoding') . $encoding);
+            }
+
+            // Append to $attachment array
+            $this->attachment[] = [
+                0 => $string,
+                1 => $name,
+                2 => $name,
+                3 => $encoding,
+                4 => $type,
+                5 => true, // isStringAttachment
+                6 => $disposition,
+                7 => $cid,
+            ];
+        } catch (Exception $exc) {
+            $this->setError($exc->getMessage());
+            $this->edebug($exc->getMessage());
+            if ($this->exceptions) {
+                throw $exc;
+            }
+
+            return false;
+        }
 
         return true;
     }
 
+    /**
+     * Validate encodings.
+     *
+     * @param string $encoding
+     *
+     * @return bool
+     */
+    protected function validateEncoding($encoding)
+    {
+        return in_array(
+            $encoding,
+            [
+                self::ENCODING_7BIT,
+                self::ENCODING_QUOTED_PRINTABLE,
+                self::ENCODING_BASE64,
+                self::ENCODING_8BIT,
+                self::ENCODING_BINARY,
+            ],
+            true
+        );
+    }
+
     /**
      * Check if an embedded attachment is present with this cid.
      *
@@ -3418,7 +3659,7 @@ class PHPMailer
     protected function cidExists($cid)
     {
         foreach ($this->attachment as $attachment) {
-            if ('inline' == $attachment[6] and $cid == $attachment[7]) {
+            if ('inline' === $attachment[6] && $cid === $attachment[7]) {
                 return true;
             }
         }
@@ -3434,7 +3675,7 @@ class PHPMailer
     public function inlineImageExists()
     {
         foreach ($this->attachment as $attachment) {
-            if ('inline' == $attachment[6]) {
+            if ('inline' === $attachment[6]) {
                 return true;
             }
         }
@@ -3450,7 +3691,7 @@ class PHPMailer
     public function attachmentExists()
     {
         foreach ($this->attachment as $attachment) {
-            if ('attachment' == $attachment[6]) {
+            if ('attachment' === $attachment[6]) {
                 return true;
             }
         }
@@ -3477,8 +3718,8 @@ class PHPMailer
     {
         $this->RecipientsQueue = array_filter(
             $this->RecipientsQueue,
-            function ($params) use ($kind) {
-                return $params[0] != $kind;
+            static function ($params) use ($kind) {
+                return $params[0] !== $kind;
             }
         );
     }
@@ -3564,7 +3805,7 @@ class PHPMailer
     protected function setError($msg)
     {
         ++$this->error_count;
-        if ('smtp' == $this->Mailer and null !== $this->smtp) {
+        if ('smtp' === $this->Mailer && null !== $this->smtp) {
             $lasterror = $this->smtp->getError();
             if (!empty($lasterror['error'])) {
                 $msg .= $this->lang('smtp_error') . $lasterror['error'];
@@ -3607,9 +3848,9 @@ class PHPMailer
         $result = '';
         if (!empty($this->Hostname)) {
             $result = $this->Hostname;
-        } elseif (isset($_SERVER) and array_key_exists('SERVER_NAME', $_SERVER)) {
+        } elseif (isset($_SERVER) && array_key_exists('SERVER_NAME', $_SERVER)) {
             $result = $_SERVER['SERVER_NAME'];
-        } elseif (function_exists('gethostname') and gethostname() !== false) {
+        } elseif (function_exists('gethostname') && gethostname() !== false) {
             $result = gethostname();
         } elseif (php_uname('n') !== false) {
             $result = php_uname('n');
@@ -3633,22 +3874,23 @@ class PHPMailer
     {
         //Simple syntax limits
         if (empty($host)
-            or !is_string($host)
-            or strlen($host) > 256
+            || !is_string($host)
+            || strlen($host) > 256
+            || !preg_match('/^([a-zA-Z\d.-]*|\[[a-fA-F\d:]+])$/', $host)
         ) {
             return false;
         }
         //Looks like a bracketed IPv6 address
-        if (trim($host, '[]') != $host) {
-            return (bool) filter_var(trim($host, '[]'), FILTER_VALIDATE_IP, FILTER_FLAG_IPV6);
+        if (strlen($host) > 2 && substr($host, 0, 1) === '[' && substr($host, -1, 1) === ']') {
+            return filter_var(substr($host, 1, -1), FILTER_VALIDATE_IP, FILTER_FLAG_IPV6) !== false;
         }
         //If removing all the dots results in a numeric string, it must be an IPv4 address.
         //Need to check this first because otherwise things like `999.0.0.0` are considered valid host names
         if (is_numeric(str_replace('.', '', $host))) {
             //Is it a valid IPv4 address?
-            return (bool) filter_var($host, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4);
+            return filter_var($host, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4) !== false;
         }
-        if (filter_var('http://' . $host, FILTER_VALIDATE_URL)) {
+        if (filter_var('http://' . $host, FILTER_VALIDATE_URL) !== false) {
             //Is it a syntactically valid hostname?
             return true;
         }
@@ -3666,11 +3908,11 @@ class PHPMailer
     protected function lang($key)
     {
         if (count($this->language) < 1) {
-            $this->setLanguage('en'); // set the default language
+            $this->setLanguage(); // set the default language
         }
 
         if (array_key_exists($key, $this->language)) {
-            if ('smtp_connect_failed' == $key) {
+            if ('smtp_connect_failed' === $key) {
                 //Include a link to troubleshooting docs on SMTP connection failure
                 //this is by far the biggest cause of support questions
                 //but it's usually not PHPMailer's fault.
@@ -3701,15 +3943,28 @@ class PHPMailer
      *
      * @param string      $name  Custom header name
      * @param string|null $value Header value
+     *
+     * @throws Exception
      */
     public function addCustomHeader($name, $value = null)
     {
-        if (null === $value) {
+        if (null === $value && strpos($name, ':') !== false) {
             // Value passed in as name:value
-            $this->CustomHeader[] = explode(':', $name, 2);
-        } else {
-            $this->CustomHeader[] = [$name, $value];
+            list($name, $value) = explode(':', $name, 2);
         }
+        $name = trim($name);
+        $value = trim($value);
+        //Ensure name is not empty, and that neither name nor value contain line breaks
+        if (empty($name) || strpbrk($name . $value, "\r\n") !== false) {
+            if ($this->exceptions) {
+                throw new Exception('Invalid header name or value');
+            }
+
+            return false;
+        }
+        $this->CustomHeader[] = [$name, $value];
+
+        return true;
     }
 
     /**
@@ -3736,36 +3991,46 @@ class PHPMailer
      * @param string        $message  HTML message string
      * @param string        $basedir  Absolute path to a base directory to prepend to relative paths to images
      * @param bool|callable $advanced Whether to use the internal HTML to text converter
-     *                                or your own custom converter @see PHPMailer::html2text()
+     *                                or your own custom converter
+     * @return string The transformed message body
+     *
+     * @throws Exception
      *
-     * @return string $message The transformed message Body
+     * @see PHPMailer::html2text()
      */
     public function msgHTML($message, $basedir = '', $advanced = false)
     {
-        preg_match_all('/(src|background)=["\'](.*)["\']/Ui', $message, $images);
+        preg_match_all('/(?<!-)(src|background)=["\'](.*)["\']/Ui', $message, $images);
         if (array_key_exists(2, $images)) {
-            if (strlen($basedir) > 1 && '/' != substr($basedir, -1)) {
+            if (strlen($basedir) > 1 && '/' !== substr($basedir, -1)) {
                 // Ensure $basedir has a trailing /
                 $basedir .= '/';
             }
             foreach ($images[2] as $imgindex => $url) {
                 // Convert data URIs into embedded images
                 //e.g. "data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=="
+                $match = [];
                 if (preg_match('#^data:(image/(?:jpe?g|gif|png));?(base64)?,(.+)#', $url, $match)) {
-                    if (count($match) == 4 and static::ENCODING_BASE64 == $match[2]) {
+                    if (count($match) === 4 && static::ENCODING_BASE64 === $match[2]) {
                         $data = base64_decode($match[3]);
-                    } elseif ('' == $match[2]) {
+                    } elseif ('' === $match[2]) {
                         $data = rawurldecode($match[3]);
                     } else {
                         //Not recognised so leave it alone
                         continue;
                     }
-                    //Hash the decoded data, not the URL so that the same data-URI image used in multiple places
+                    //Hash the decoded data, not the URL, so that the same data-URI image used in multiple places
                     //will only be embedded once, even if it used a different encoding
-                    $cid = hash('sha256', $data) . '@phpmailer.0'; // RFC2392 S 2
+                    $cid = substr(hash('sha256', $data), 0, 32) . '@phpmailer.0'; // RFC2392 S 2
 
                     if (!$this->cidExists($cid)) {
-                        $this->addStringEmbeddedImage($data, $cid, 'embed' . $imgindex, static::ENCODING_BASE64, $match[1]);
+                        $this->addStringEmbeddedImage(
+                            $data,
+                            $cid,
+                            'embed' . $imgindex,
+                            static::ENCODING_BASE64,
+                            $match[1]
+                        );
                     }
                     $message = str_replace(
                         $images[0][$imgindex],
@@ -3777,22 +4042,23 @@ class PHPMailer
                 if (// Only process relative URLs if a basedir is provided (i.e. no absolute local paths)
                     !empty($basedir)
                     // Ignore URLs containing parent dir traversal (..)
-                    and (strpos($url, '..') === false)
+                    && (strpos($url, '..') === false)
                     // Do not change urls that are already inline images
-                    and 0 !== strpos($url, 'cid:')
+                    && 0 !== strpos($url, 'cid:')
                     // Do not change absolute URLs, including anonymous protocol
-                    and !preg_match('#^[a-z][a-z0-9+.-]*:?//#i', $url)
+                    && !preg_match('#^[a-z][a-z0-9+.-]*:?//#i', $url)
                 ) {
-                    $filename = basename($url);
+                    $filename = static::mb_pathinfo($url, PATHINFO_BASENAME);
                     $directory = dirname($url);
-                    if ('.' == $directory) {
+                    if ('.' === $directory) {
                         $directory = '';
                     }
-                    $cid = hash('sha256', $url) . '@phpmailer.0'; // RFC2392 S 2
-                    if (strlen($basedir) > 1 and '/' != substr($basedir, -1)) {
+                    // RFC2392 S 2
+                    $cid = substr(hash('sha256', $url), 0, 32) . '@phpmailer.0';
+                    if (strlen($basedir) > 1 && '/' !== substr($basedir, -1)) {
                         $basedir .= '/';
                     }
-                    if (strlen($directory) > 1 and '/' != substr($directory, -1)) {
+                    if (strlen($directory) > 1 && '/' !== substr($directory, -1)) {
                         $directory .= '/';
                     }
                     if ($this->addEmbeddedImage(
@@ -3812,7 +4078,7 @@ class PHPMailer
                 }
             }
         }
-        $this->isHTML(true);
+        $this->isHTML();
         // Convert all message body line breaks to LE, makes quoted-printable encoding work much better
         $this->Body = static::normalizeBreaks($message);
         $this->AltBody = static::normalizeBreaks($this->html2text($message, $advanced));
@@ -4014,7 +4280,7 @@ class PHPMailer
      * Multi-byte-safe pathinfo replacement.
      * Drop-in replacement for pathinfo(), but multibyte- and cross-platform-safe.
      *
-     * @see    http://www.php.net/manual/en/function.pathinfo.php#107461
+     * @see http://www.php.net/manual/en/function.pathinfo.php#107461
      *
      * @param string     $path    A filename or path, does not need to exist as a file
      * @param int|string $options Either a PATHINFO_* constant,
@@ -4026,7 +4292,7 @@ class PHPMailer
     {
         $ret = ['dirname' => '', 'basename' => '', 'extension' => '', 'filename' => ''];
         $pathinfo = [];
-        if (preg_match('#^(.*?)[\\\\/]*(([^/\\\\]*?)(\.([^\.\\\\/]+?)|))[\\\\/\.]*$#im', $path, $pathinfo)) {
+        if (preg_match('#^(.*?)[\\\\/]*(([^/\\\\]*?)(\.([^.\\\\/]+?)|))[\\\\/.]*$#m', $path, $pathinfo)) {
             if (array_key_exists(1, $pathinfo)) {
                 $ret['dirname'] = $pathinfo[1];
             }
@@ -4063,9 +4329,9 @@ class PHPMailer
      * You should avoid this function - it's more verbose, less efficient, more error-prone and
      * harder to debug than setting properties directly.
      * Usage Example:
-     * `$mail->set('SMTPSecure', 'tls');`
+     * `$mail->set('SMTPSecure', static::ENCRYPTION_STARTTLS);`
      *   is the same as:
-     * `$mail->SMTPSecure = 'tls';`.
+     * `$mail->SMTPSecure = static::ENCRYPTION_STARTTLS;`.
      *
      * @param string $name  The property name to set
      * @param mixed  $value The value to set the property to
@@ -4112,7 +4378,7 @@ class PHPMailer
             $breaktype = static::$LE;
         }
         // Normalise to \n
-        $text = str_replace(["\r\n", "\r"], "\n", $text);
+        $text = str_replace([self::CRLF, "\r"], "\n", $text);
         // Now convert LE as needed
         if ("\n" !== $breaktype) {
             $text = str_replace("\n", $breaktype, $text);
@@ -4121,6 +4387,18 @@ class PHPMailer
         return $text;
     }
 
+    /**
+     * Remove trailing breaks from a string.
+     *
+     * @param string $text
+     *
+     * @return string The text to remove breaks from
+     */
+    public static function stripTrailingWSP($text)
+    {
+        return rtrim($text, " \r\n\t");
+    }
+
     /**
      * Return the current line break format string.
      *
@@ -4170,7 +4448,7 @@ class PHPMailer
         $len = strlen($txt);
         for ($i = 0; $i < $len; ++$i) {
             $ord = ord($txt[$i]);
-            if (((0x21 <= $ord) and ($ord <= 0x3A)) or $ord == 0x3C or ((0x3E <= $ord) and ($ord <= 0x7E))) {
+            if (((0x21 <= $ord) && ($ord <= 0x3A)) || $ord === 0x3C || ((0x3E <= $ord) && ($ord <= 0x7E))) {
                 $line .= $txt[$i];
             } else {
                 $line .= '=' . sprintf('%02X', $ord);
@@ -4201,7 +4479,7 @@ class PHPMailer
         $privKeyStr = !empty($this->DKIM_private_string) ?
             $this->DKIM_private_string :
             file_get_contents($this->DKIM_private);
-        if ('' != $this->DKIM_passphrase) {
+        if ('' !== $this->DKIM_passphrase) {
             $privKey = openssl_pkey_get_private($privKeyStr, $this->DKIM_passphrase);
         } else {
             $privKey = openssl_pkey_get_private($privKeyStr);
@@ -4221,7 +4499,7 @@ class PHPMailer
      * Uses the 'relaxed' algorithm from RFC6376 section 3.4.2.
      * Canonicalized headers should *always* use CRLF, regardless of mailer setting.
      *
-     * @see    https://tools.ietf.org/html/rfc6376#section-3.4.2
+     * @see https://tools.ietf.org/html/rfc6376#section-3.4.2
      *
      * @param string $signHeader Header
      *
@@ -4229,13 +4507,15 @@ class PHPMailer
      */
     public function DKIM_HeaderC($signHeader)
     {
-        //Unfold all header continuation lines
-        //Also collapses folded whitespace.
+        //Normalize breaks to CRLF (regardless of the mailer)
+        $signHeader = static::normalizeBreaks($signHeader, self::CRLF);
+        //Unfold header lines
         //Note PCRE \s is too broad a definition of whitespace; RFC5322 defines it as `[ \t]`
         //@see https://tools.ietf.org/html/rfc5322#section-2.2
         //That means this may break if you do something daft like put vertical tabs in your headers.
         $signHeader = preg_replace('/\r\n[ \t]+/', ' ', $signHeader);
-        $lines = explode("\r\n", $signHeader);
+        //Break headers out into an array
+        $lines = explode(self::CRLF, $signHeader);
         foreach ($lines as $key => $line) {
             //If the header is missing a :, skip it as it's invalid
             //This is likely to happen because the explode() above will also split
@@ -4246,16 +4526,16 @@ class PHPMailer
             list($heading, $value) = explode(':', $line, 2);
             //Lower-case header name
             $heading = strtolower($heading);
-            //Collapse white space within the value
-            $value = preg_replace('/[ \t]{2,}/', ' ', $value);
+            //Collapse white space within the value, also convert WSP to space
+            $value = preg_replace('/[ \t]+/', ' ', $value);
             //RFC6376 is slightly unclear here - it says to delete space at the *end* of each value
             //But then says to delete space before and after the colon.
             //Net result is the same as trimming both ends of the value.
-            //by elimination, the same applies to the field name
+            //By elimination, the same applies to the field name
             $lines[$key] = trim($heading, " \t") . ':' . trim($value, " \t");
         }
 
-        return implode("\r\n", $lines);
+        return implode(self::CRLF, $lines);
     }
 
     /**
@@ -4263,7 +4543,7 @@ class PHPMailer
      * Uses the 'simple' algorithm from RFC6376 section 3.4.3.
      * Canonicalized bodies should *always* use CRLF, regardless of mailer setting.
      *
-     * @see    https://tools.ietf.org/html/rfc6376#section-3.4.3
+     * @see https://tools.ietf.org/html/rfc6376#section-3.4.3
      *
      * @param string $body Message Body
      *
@@ -4272,13 +4552,13 @@ class PHPMailer
     public function DKIM_BodyC($body)
     {
         if (empty($body)) {
-            return "\r\n";
+            return self::CRLF;
         }
         // Normalize line endings to CRLF
-        $body = static::normalizeBreaks($body, "\r\n");
+        $body = static::normalizeBreaks($body, self::CRLF);
 
         //Reduce multiple trailing line breaks to a single one
-        return rtrim($body, "\r\n") . "\r\n";
+        return static::stripTrailingWSP($body) . self::CRLF;
     }
 
     /**
@@ -4288,109 +4568,143 @@ class PHPMailer
      * @param string $subject      Subject
      * @param string $body         Body
      *
+     * @throws Exception
+     *
      * @return string
      */
     public function DKIM_Add($headers_line, $subject, $body)
     {
         $DKIMsignatureType = 'rsa-sha256'; // Signature & hash algorithms
-        $DKIMcanonicalization = 'relaxed/simple'; // Canonicalization of header/body
+        $DKIMcanonicalization = 'relaxed/simple'; // Canonicalization methods of header & body
         $DKIMquery = 'dns/txt'; // Query method
-        $DKIMtime = time(); // Signature Timestamp = seconds since 00:00:00 - Jan 1, 1970 (UTC time zone)
-        $subject_header = "Subject: $subject";
-        $headers = explode(static::$LE, $headers_line);
-        $from_header = '';
-        $to_header = '';
-        $date_header = '';
-        $current = '';
-        $copiedHeaderFields = '';
-        $foundExtraHeaders = [];
-        $extraHeaderKeys = '';
-        $extraHeaderValues = '';
-        $extraCopyHeaderFields = '';
-        foreach ($headers as $header) {
-            if (strpos($header, 'From:') === 0) {
-                $from_header = $header;
-                $current = 'from_header';
-            } elseif (strpos($header, 'To:') === 0) {
-                $to_header = $header;
-                $current = 'to_header';
-            } elseif (strpos($header, 'Date:') === 0) {
-                $date_header = $header;
-                $current = 'date_header';
-            } elseif (!empty($this->DKIM_extraHeaders)) {
-                foreach ($this->DKIM_extraHeaders as $extraHeader) {
-                    if (strpos($header, $extraHeader . ':') === 0) {
-                        $headerValue = $header;
-                        foreach ($this->CustomHeader as $customHeader) {
-                            if ($customHeader[0] === $extraHeader) {
-                                $headerValue = trim($customHeader[0]) .
-                                               ': ' .
-                                               $this->encodeHeader(trim($customHeader[1]));
-                                break;
-                            }
+        $DKIMtime = time();
+        //Always sign these headers without being asked
+        //Recommended list from https://tools.ietf.org/html/rfc6376#section-5.4.1
+        $autoSignHeaders = [
+            'from',
+            'to',
+            'cc',
+            'date',
+            'subject',
+            'reply-to',
+            'message-id',
+            'content-type',
+            'mime-version',
+            'x-mailer',
+        ];
+        if (stripos($headers_line, 'Subject') === false) {
+            $headers_line .= 'Subject: ' . $subject . static::$LE;
+        }
+        $headerLines = explode(static::$LE, $headers_line);
+        $currentHeaderLabel = '';
+        $currentHeaderValue = '';
+        $parsedHeaders = [];
+        $headerLineIndex = 0;
+        $headerLineCount = count($headerLines);
+        foreach ($headerLines as $headerLine) {
+            $matches = [];
+            if (preg_match('/^([^ \t]*?)(?::[ \t]*)(.*)$/', $headerLine, $matches)) {
+                if ($currentHeaderLabel !== '') {
+                    //We were previously in another header; This is the start of a new header, so save the previous one
+                    $parsedHeaders[] = ['label' => $currentHeaderLabel, 'value' => $currentHeaderValue];
+                }
+                $currentHeaderLabel = $matches[1];
+                $currentHeaderValue = $matches[2];
+            } elseif (preg_match('/^[ \t]+(.*)$/', $headerLine, $matches)) {
+                //This is a folded continuation of the current header, so unfold it
+                $currentHeaderValue .= ' ' . $matches[1];
+            }
+            ++$headerLineIndex;
+            if ($headerLineIndex >= $headerLineCount) {
+                //This was the last line, so finish off this header
+                $parsedHeaders[] = ['label' => $currentHeaderLabel, 'value' => $currentHeaderValue];
+            }
+        }
+        $copiedHeaders = [];
+        $headersToSignKeys = [];
+        $headersToSign = [];
+        foreach ($parsedHeaders as $header) {
+            //Is this header one that must be included in the DKIM signature?
+            if (in_array(strtolower($header['label']), $autoSignHeaders, true)) {
+                $headersToSignKeys[] = $header['label'];
+                $headersToSign[] = $header['label'] . ': ' . $header['value'];
+                if ($this->DKIM_copyHeaderFields) {
+                    $copiedHeaders[] = $header['label'] . ':' . //Note no space after this, as per RFC
+                        str_replace('|', '=7C', $this->DKIM_QP($header['value']));
+                }
+                continue;
+            }
+            //Is this an extra custom header we've been asked to sign?
+            if (in_array($header['label'], $this->DKIM_extraHeaders, true)) {
+                //Find its value in custom headers
+                foreach ($this->CustomHeader as $customHeader) {
+                    if ($customHeader[0] === $header['label']) {
+                        $headersToSignKeys[] = $header['label'];
+                        $headersToSign[] = $header['label'] . ': ' . $header['value'];
+                        if ($this->DKIM_copyHeaderFields) {
+                            $copiedHeaders[] = $header['label'] . ':' . //Note no space after this, as per RFC
+                                str_replace('|', '=7C', $this->DKIM_QP($header['value']));
                         }
-                        $foundExtraHeaders[$extraHeader] = $headerValue;
-                        $current = '';
-                        break;
+                        //Skip straight to the next header
+                        continue 2;
                     }
                 }
-            } else {
-                if (!empty($$current) and strpos($header, ' =?') === 0) {
-                    $$current .= $header;
-                } else {
-                    $current = '';
-                }
             }
         }
-        foreach ($foundExtraHeaders as $key => $value) {
-            $extraHeaderKeys .= ':' . $key;
-            $extraHeaderValues .= $value . "\r\n";
-            if ($this->DKIM_copyHeaderFields) {
-                $extraCopyHeaderFields .= "\t|" . str_replace('|', '=7C', $this->DKIM_QP($value)) . ";\r\n";
+        $copiedHeaderFields = '';
+        if ($this->DKIM_copyHeaderFields && count($copiedHeaders) > 0) {
+            //Assemble a DKIM 'z' tag
+            $copiedHeaderFields = ' z=';
+            $first = true;
+            foreach ($copiedHeaders as $copiedHeader) {
+                if (!$first) {
+                    $copiedHeaderFields .= static::$LE . ' |';
+                }
+                //Fold long values
+                if (strlen($copiedHeader) > self::STD_LINE_LENGTH - 3) {
+                    $copiedHeaderFields .= substr(
+                        chunk_split($copiedHeader, self::STD_LINE_LENGTH - 3, static::$LE . self::FWS),
+                        0,
+                        -strlen(static::$LE . self::FWS)
+                    );
+                } else {
+                    $copiedHeaderFields .= $copiedHeader;
+                }
+                $first = false;
             }
+            $copiedHeaderFields .= ';' . static::$LE;
         }
-        if ($this->DKIM_copyHeaderFields) {
-            $from = str_replace('|', '=7C', $this->DKIM_QP($from_header));
-            $to = str_replace('|', '=7C', $this->DKIM_QP($to_header));
-            $date = str_replace('|', '=7C', $this->DKIM_QP($date_header));
-            $subject = str_replace('|', '=7C', $this->DKIM_QP($subject_header));
-            $copiedHeaderFields = "\tz=$from\r\n" .
-                                  "\t|$to\r\n" .
-                                  "\t|$date\r\n" .
-                                  "\t|$subject;\r\n" .
-                                  $extraCopyHeaderFields;
-        }
+        $headerKeys = ' h=' . implode(':', $headersToSignKeys) . ';' . static::$LE;
+        $headerValues = implode(static::$LE, $headersToSign);
         $body = $this->DKIM_BodyC($body);
-        $DKIMlen = strlen($body); // Length of body
         $DKIMb64 = base64_encode(pack('H*', hash('sha256', $body))); // Base64 of packed binary SHA-256 hash of body
-        if ('' == $this->DKIM_identity) {
-            $ident = '';
-        } else {
-            $ident = ' i=' . $this->DKIM_identity . ';';
-        }
-        $dkimhdrs = 'DKIM-Signature: v=1; a=' .
-            $DKIMsignatureType . '; q=' .
-            $DKIMquery . '; l=' .
-            $DKIMlen . '; s=' .
-            $this->DKIM_selector .
-            ";\r\n" .
-            "\tt=" . $DKIMtime . '; c=' . $DKIMcanonicalization . ";\r\n" .
-            "\th=From:To:Date:Subject" . $extraHeaderKeys . ";\r\n" .
-            "\td=" . $this->DKIM_domain . ';' . $ident . "\r\n" .
+        $ident = '';
+        if ('' !== $this->DKIM_identity) {
+            $ident = ' i=' . $this->DKIM_identity . ';' . static::$LE;
+        }
+        //The DKIM-Signature header is included in the signature *except for* the value of the `b` tag
+        //which is appended after calculating the signature
+        //https://tools.ietf.org/html/rfc6376#section-3.5
+        $dkimSignatureHeader = 'DKIM-Signature: v=1;' .
+            ' d=' . $this->DKIM_domain . ';' .
+            ' s=' . $this->DKIM_selector . ';' . static::$LE .
+            ' a=' . $DKIMsignatureType . ';' .
+            ' q=' . $DKIMquery . ';' .
+            ' t=' . $DKIMtime . ';' .
+            ' c=' . $DKIMcanonicalization . ';' . static::$LE .
+            $headerKeys .
+            $ident .
             $copiedHeaderFields .
-            "\tbh=" . $DKIMb64 . ";\r\n" .
-            "\tb=";
-        $toSign = $this->DKIM_HeaderC(
-            $from_header . "\r\n" .
-            $to_header . "\r\n" .
-            $date_header . "\r\n" .
-            $subject_header . "\r\n" .
-            $extraHeaderValues .
-            $dkimhdrs
+            ' bh=' . $DKIMb64 . ';' . static::$LE .
+            ' b=';
+        //Canonicalize the set of headers
+        $canonicalizedHeaders = $this->DKIM_HeaderC(
+            $headerValues . static::$LE . $dkimSignatureHeader
         );
-        $signed = $this->DKIM_Sign($toSign);
+        $signature = $this->DKIM_Sign($canonicalizedHeaders);
+        $signature = trim(chunk_split($signature, self::STD_LINE_LENGTH - 3, static::$LE . self::FWS));
 
-        return static::normalizeBreaks($dkimhdrs . $signed) . static::$LE;
+        return static::normalizeBreaks($dkimSignatureHeader . $signature);
     }
 
     /**
@@ -4406,6 +4720,28 @@ class PHPMailer
         return (bool) preg_match('/^(.{' . (self::MAX_LINE_LENGTH + strlen(static::$LE)) . ',})/m', $str);
     }
 
+    /**
+     * If a string contains any "special" characters, double-quote the name,
+     * and escape any double quotes with a backslash.
+     *
+     * @param string $str
+     *
+     * @return string
+     *
+     * @see RFC822 3.4.1
+     */
+    public static function quotedString($str)
+    {
+        if (preg_match('/[ ()<>@,;:"\/\[\]?=]/', $str)) {
+            //If the string contains any of these chars, it must be double-quoted
+            //and any double quotes must be escaped with a backslash
+            return '"' . str_replace('"', '\\"', $str) . '"';
+        }
+
+        //Return the string untouched, it doesn't need quoting
+        return $str;
+    }
+
     /**
      * Allows for public read access to 'to' property.
      * Before the send() call, queued addresses (i.e. with IDN) are not yet included.
@@ -4475,7 +4811,7 @@ class PHPMailer
      */
     protected function doCallback($isSent, $to, $cc, $bcc, $subject, $body, $from, $extra)
     {
-        if (!empty($this->action_function) and is_callable($this->action_function)) {
+        if (!empty($this->action_function) && is_callable($this->action_function)) {
             call_user_func($this->action_function, $isSent, $to, $cc, $bcc, $subject, $body, $from, $extra);
         }
     }
@@ -4492,8 +4828,6 @@ class PHPMailer
 
     /**
      * Set an OAuth instance.
-     *
-     * @param OAuth $oauth
      */
     public function setOAuth(OAuth $oauth)
     {
diff --git a/vendor/phpmailer/phpmailer/src/POP3.php b/vendor/phpmailer/phpmailer/src/POP3.php
index 66cf27304198e45bbb31c28369bee461940f9ed8..9a3b07ccab4061eb8458601c8b6231492b8abc81 100644
--- a/vendor/phpmailer/phpmailer/src/POP3.php
+++ b/vendor/phpmailer/phpmailer/src/POP3.php
@@ -3,13 +3,13 @@
  * PHPMailer POP-Before-SMTP Authentication Class.
  * PHP Version 5.5.
  *
- * @see       https://github.com/PHPMailer/PHPMailer/ The PHPMailer GitHub project
+ * @see https://github.com/PHPMailer/PHPMailer/ The PHPMailer GitHub project
  *
  * @author    Marcus Bointon (Synchro/coolbru) <phpmailer@synchromedia.co.uk>
  * @author    Jim Jagielski (jimjag) <jimjag@gmail.com>
  * @author    Andy Prevost (codeworxtech) <codeworxtech@users.sourceforge.net>
  * @author    Brent R. Matzelle (original founder)
- * @copyright 2012 - 2017 Marcus Bointon
+ * @copyright 2012 - 2019 Marcus Bointon
  * @copyright 2010 - 2012 Jim Jagielski
  * @copyright 2004 - 2009 Andy Prevost
  * @license   http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
@@ -29,14 +29,14 @@ namespace PHPMailer\PHPMailer;
  *   and then loop through your mail sending script. Providing this process doesn't
  *   take longer than the verification period lasts on your POP3 server, you should be fine.
  * 3) This is really ancient technology; you should only need to use it to talk to very old systems.
- * 4) This POP3 class is deliberately lightweight and incomplete, and implements just
+ * 4) This POP3 class is deliberately lightweight and incomplete, implementing just
  *   enough to do authentication.
  *   If you want a more complete class there are other POP3 classes for PHP available.
  *
- * @author  Richard Davey (original author) <rich@corephp.co.uk>
- * @author  Marcus Bointon (Synchro/coolbru) <phpmailer@synchromedia.co.uk>
- * @author  Jim Jagielski (jimjag) <jimjag@gmail.com>
- * @author  Andy Prevost (codeworxtech) <codeworxtech@users.sourceforge.net>
+ * @author Richard Davey (original author) <rich@corephp.co.uk>
+ * @author Marcus Bointon (Synchro/coolbru) <phpmailer@synchromedia.co.uk>
+ * @author Jim Jagielski (jimjag) <jimjag@gmail.com>
+ * @author Andy Prevost (codeworxtech) <codeworxtech@users.sourceforge.net>
  */
 class POP3
 {
@@ -45,7 +45,7 @@ class POP3
      *
      * @var string
      */
-    const VERSION = '6.0.7';
+    const VERSION = '6.1.7';
 
     /**
      * Default POP3 port number.
@@ -230,6 +230,8 @@ class POP3
         }
 
         //  connect to the POP3 server
+        $errno = 0;
+        $errstr = '';
         $this->pop_conn = fsockopen(
             $host, //  POP3 Host
             $port, //  Port #
@@ -364,7 +366,7 @@ class POP3
      */
     protected function checkResponse($string)
     {
-        if (substr($string, 0, 3) !== '+OK') {
+        if (strpos($string, '+OK') !== 0) {
             $this->setError("Server reported an error: $string");
 
             return false;
diff --git a/vendor/phpmailer/phpmailer/src/SMTP.php b/vendor/phpmailer/phpmailer/src/SMTP.php
index da85442bf2c79e7d6df4af1978017d0405c14ffd..6b0b73ddd99015a3a443bc7c3883ac8fa9e780aa 100644
--- a/vendor/phpmailer/phpmailer/src/SMTP.php
+++ b/vendor/phpmailer/phpmailer/src/SMTP.php
@@ -9,7 +9,7 @@
  * @author    Jim Jagielski (jimjag) <jimjag@gmail.com>
  * @author    Andy Prevost (codeworxtech) <codeworxtech@users.sourceforge.net>
  * @author    Brent R. Matzelle (original founder)
- * @copyright 2012 - 2017 Marcus Bointon
+ * @copyright 2012 - 2019 Marcus Bointon
  * @copyright 2010 - 2012 Jim Jagielski
  * @copyright 2004 - 2009 Andy Prevost
  * @license   http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
@@ -24,8 +24,8 @@ namespace PHPMailer\PHPMailer;
  * PHPMailer RFC821 SMTP email transport class.
  * Implements RFC 821 SMTP commands and provides some utility methods for sending mail to an SMTP server.
  *
- * @author  Chris Ryan
- * @author  Marcus Bointon <phpmailer@synchromedia.co.uk>
+ * @author Chris Ryan
+ * @author Marcus Bointon <phpmailer@synchromedia.co.uk>
  */
 class SMTP
 {
@@ -34,7 +34,7 @@ class SMTP
      *
      * @var string
      */
-    const VERSION = '6.0.7';
+    const VERSION = '6.1.7';
 
     /**
      * SMTP line break constant.
@@ -51,34 +51,57 @@ class SMTP
     const DEFAULT_PORT = 25;
 
     /**
-     * The maximum line length allowed by RFC 2822 section 2.1.1.
+     * The maximum line length allowed by RFC 5321 section 4.5.3.1.6,
+     * *excluding* a trailing CRLF break.
+     *
+     * @see https://tools.ietf.org/html/rfc5321#section-4.5.3.1.6
      *
      * @var int
      */
     const MAX_LINE_LENGTH = 998;
 
+    /**
+     * The maximum line length allowed for replies in RFC 5321 section 4.5.3.1.5,
+     * *including* a trailing CRLF line break.
+     *
+     * @see https://tools.ietf.org/html/rfc5321#section-4.5.3.1.5
+     *
+     * @var int
+     */
+    const MAX_REPLY_LENGTH = 512;
+
     /**
      * Debug level for no output.
+     *
+     * @var int
      */
     const DEBUG_OFF = 0;
 
     /**
      * Debug level to show client -> server messages.
+     *
+     * @var int
      */
     const DEBUG_CLIENT = 1;
 
     /**
      * Debug level to show client -> server and server -> client messages.
+     *
+     * @var int
      */
     const DEBUG_SERVER = 2;
 
     /**
      * Debug level to show connection status, client -> server and server -> client messages.
+     *
+     * @var int
      */
     const DEBUG_CONNECTION = 3;
 
     /**
      * Debug level to show all messages.
+     *
+     * @var int
      */
     const DEBUG_LOWLEVEL = 4;
 
@@ -197,7 +220,7 @@ class SMTP
      *
      * @var string|null
      */
-    protected $helo_rply = null;
+    protected $helo_rply;
 
     /**
      * The set of SMTP extensions sent in reply to EHLO command.
@@ -209,7 +232,7 @@ class SMTP
      *
      * @var array|null
      */
-    protected $server_caps = null;
+    protected $server_caps;
 
     /**
      * The most recent reply received from the server.
@@ -239,7 +262,7 @@ class SMTP
             return;
         }
         //Avoid clash with built-in function names
-        if (!in_array($this->Debugoutput, ['error_log', 'html', 'echo']) and is_callable($this->Debugoutput)) {
+        if (is_callable($this->Debugoutput) && !in_array($this->Debugoutput, ['error_log', 'html', 'echo'])) {
             call_user_func($this->Debugoutput, $str, $level);
 
             return;
@@ -260,12 +283,12 @@ class SMTP
             case 'echo':
             default:
                 //Normalize line breaks
-                $str = preg_replace('/\r\n|\r/ms', "\n", $str);
+                $str = preg_replace('/\r\n|\r/m', "\n", $str);
                 echo gmdate('Y-m-d H:i:s'),
                 "\t",
                     //Trim trailing space
                 trim(
-                //Indent for readability, except for trailing break
+                    //Indent for readability, except for trailing break
                     str_replace(
                         "\n",
                         "\n                   \t                  ",
@@ -288,12 +311,6 @@ class SMTP
      */
     public function connect($host, $port = null, $timeout = 30, $options = [])
     {
-        static $streamok;
-        //This is enabled by default since 5.0.0 but some providers disable it
-        //Check this once and cache the result
-        if (null === $streamok) {
-            $streamok = function_exists('stream_socket_client');
-        }
         // Clear errors to avoid confusion
         $this->setError('');
         // Make sure we are __not__ connected
@@ -312,12 +329,48 @@ class SMTP
             (count($options) > 0 ? var_export($options, true) : 'array()'),
             self::DEBUG_CONNECTION
         );
+
+        $this->smtp_conn = $this->getSMTPConnection($host, $port, $timeout, $options);
+
+        if ($this->smtp_conn === false) {
+            //Error info already set inside `getSMTPConnection()`
+            return false;
+        }
+
+        $this->edebug('Connection: opened', self::DEBUG_CONNECTION);
+
+        // Get any announcement
+        $this->last_reply = $this->get_lines();
+        $this->edebug('SERVER -> CLIENT: ' . $this->last_reply, self::DEBUG_SERVER);
+
+        return true;
+    }
+
+    /**
+     * Create connection to the SMTP server.
+     *
+     * @param string $host    SMTP server IP or host name
+     * @param int    $port    The port number to connect to
+     * @param int    $timeout How long to wait for the connection to open
+     * @param array  $options An array of options for stream_context_create()
+     *
+     * @return false|resource
+     */
+    protected function getSMTPConnection($host, $port = null, $timeout = 30, $options = [])
+    {
+        static $streamok;
+        //This is enabled by default since 5.0.0 but some providers disable it
+        //Check this once and cache the result
+        if (null === $streamok) {
+            $streamok = function_exists('stream_socket_client');
+        }
+
         $errno = 0;
         $errstr = '';
         if ($streamok) {
             $socket_context = stream_context_create($options);
             set_error_handler([$this, 'errorHandler']);
-            $this->smtp_conn = stream_socket_client(
+            $connection = stream_socket_client(
                 $host . ':' . $port,
                 $errno,
                 $errstr,
@@ -333,7 +386,7 @@ class SMTP
                 self::DEBUG_CONNECTION
             );
             set_error_handler([$this, 'errorHandler']);
-            $this->smtp_conn = fsockopen(
+            $connection = fsockopen(
                 $host,
                 $port,
                 $errno,
@@ -342,13 +395,14 @@ class SMTP
             );
             restore_error_handler();
         }
+
         // Verify we connected properly
-        if (!is_resource($this->smtp_conn)) {
+        if (!is_resource($connection)) {
             $this->setError(
                 'Failed to connect to server',
                 '',
                 (string) $errno,
-                (string) $errstr
+                $errstr
             );
             $this->edebug(
                 'SMTP ERROR: ' . $this->error['error']
@@ -358,22 +412,19 @@ class SMTP
 
             return false;
         }
-        $this->edebug('Connection: opened', self::DEBUG_CONNECTION);
+
         // SMTP server can take longer to respond, give longer timeout for first read
         // Windows does not have support for this timeout function
-        if (substr(PHP_OS, 0, 3) != 'WIN') {
-            $max = ini_get('max_execution_time');
+        if (strpos(PHP_OS, 'WIN') !== 0) {
+            $max = (int)ini_get('max_execution_time');
             // Don't bother if unlimited
-            if (0 != $max and $timeout > $max) {
+            if (0 !== $max && $timeout > $max) {
                 @set_time_limit($timeout);
             }
-            stream_set_timeout($this->smtp_conn, $timeout, 0);
+            stream_set_timeout($connection, $timeout, 0);
         }
-        // Get any announcement
-        $announce = $this->get_lines();
-        $this->edebug('SERVER -> CLIENT: ' . $announce, self::DEBUG_SERVER);
 
-        return true;
+        return $connection;
     }
 
     /**
@@ -444,14 +495,14 @@ class SMTP
                 return false;
             }
 
-            $this->edebug('Auth method requested: ' . ($authtype ? $authtype : 'UNSPECIFIED'), self::DEBUG_LOWLEVEL);
+            $this->edebug('Auth method requested: ' . ($authtype ?: 'UNSPECIFIED'), self::DEBUG_LOWLEVEL);
             $this->edebug(
                 'Auth methods available on the server: ' . implode(',', $this->server_caps['AUTH']),
                 self::DEBUG_LOWLEVEL
             );
 
             //If we have requested a specific auth type, check the server supports it before trying others
-            if (null !== $authtype and !in_array($authtype, $this->server_caps['AUTH'])) {
+            if (null !== $authtype && !in_array($authtype, $this->server_caps['AUTH'], true)) {
                 $this->edebug('Requested auth method not available: ' . $authtype, self::DEBUG_LOWLEVEL);
                 $authtype = null;
             }
@@ -460,7 +511,7 @@ class SMTP
                 //If no auth mechanism is specified, attempt to use these, in this order
                 //Try CRAM-MD5 first as it's more secure than the others
                 foreach (['CRAM-MD5', 'LOGIN', 'PLAIN', 'XOAUTH2'] as $method) {
-                    if (in_array($method, $this->server_caps['AUTH'])) {
+                    if (in_array($method, $this->server_caps['AUTH'], true)) {
                         $authtype = $method;
                         break;
                     }
@@ -470,10 +521,10 @@ class SMTP
 
                     return false;
                 }
-                self::edebug('Auth method selected: ' . $authtype, self::DEBUG_LOWLEVEL);
+                $this->edebug('Auth method selected: ' . $authtype, self::DEBUG_LOWLEVEL);
             }
 
-            if (!in_array($authtype, $this->server_caps['AUTH'])) {
+            if (!in_array($authtype, $this->server_caps['AUTH'], true)) {
                 $this->setError("The requested authentication method \"$authtype\" is not supported by the server");
 
                 return false;
@@ -663,13 +714,13 @@ class SMTP
 
         $field = substr($lines[0], 0, strpos($lines[0], ':'));
         $in_headers = false;
-        if (!empty($field) and strpos($field, ' ') === false) {
+        if (!empty($field) && strpos($field, ' ') === false) {
             $in_headers = true;
         }
 
         foreach ($lines as $line) {
             $lines_out = [];
-            if ($in_headers and $line == '') {
+            if ($in_headers && $line === '') {
                 $in_headers = false;
             }
             //Break this line up into several smaller lines if it's too long
@@ -700,7 +751,7 @@ class SMTP
             //Send the lines to the server
             foreach ($lines_out as $line_out) {
                 //RFC2821 section 4.5.2
-                if (!empty($line_out) and $line_out[0] == '.') {
+                if (!empty($line_out) && $line_out[0] === '.') {
                     $line_out = '.' . $line_out;
                 }
                 $this->client_send($line_out . static::LE, 'DATA');
@@ -710,7 +761,7 @@ class SMTP
         //Message data has been sent, complete the command
         //Increase timelimit for end of DATA command
         $savetimelimit = $this->Timelimit;
-        $this->Timelimit = $this->Timelimit * 2;
+        $this->Timelimit *= 2;
         $result = $this->sendCommand('DATA END', '.', 250);
         $this->recordLastTransactionID();
         //Restore timelimit
@@ -745,7 +796,7 @@ class SMTP
      *
      * @return bool
      *
-     * @see    hello()
+     * @see hello()
      */
     protected function sendHello($hello, $host)
     {
@@ -838,7 +889,7 @@ class SMTP
     {
         $noerror = $this->sendCommand('QUIT', 'QUIT', 221);
         $err = $this->error; //Save any error
-        if ($noerror or $close_on_error) {
+        if ($noerror || $close_on_error) {
             $this->close();
             $this->error = $err; //Restore any error from the quit command
         }
@@ -853,14 +904,35 @@ class SMTP
      * Implements from RFC 821: RCPT <SP> TO:<forward-path> <CRLF>.
      *
      * @param string $address The address the message is being sent to
+     * @param string $dsn     Comma separated list of DSN notifications. NEVER, SUCCESS, FAILURE
+     *                        or DELAY. If you specify NEVER all other notifications are ignored.
      *
      * @return bool
      */
-    public function recipient($address)
+    public function recipient($address, $dsn = '')
     {
+        if (empty($dsn)) {
+            $rcpt = 'RCPT TO:<' . $address . '>';
+        } else {
+            $dsn = strtoupper($dsn);
+            $notify = [];
+
+            if (strpos($dsn, 'NEVER') !== false) {
+                $notify[] = 'NEVER';
+            } else {
+                foreach (['SUCCESS', 'FAILURE', 'DELAY'] as $value) {
+                    if (strpos($dsn, $value) !== false) {
+                        $notify[] = $value;
+                    }
+                }
+            }
+
+            $rcpt = 'RCPT TO:<' . $address . '> NOTIFY=' . implode(',', $notify);
+        }
+
         return $this->sendCommand(
             'RCPT TO',
-            'RCPT TO:<' . $address . '>',
+            $rcpt,
             [250, 251]
         );
     }
@@ -894,7 +966,7 @@ class SMTP
             return false;
         }
         //Reject line breaks in all commands
-        if (strpos($commandstring, "\n") !== false or strpos($commandstring, "\r") !== false) {
+        if ((strpos($commandstring, "\n") !== false) || (strpos($commandstring, "\r") !== false)) {
             $this->setError("Command '$command' contained line breaks");
 
             return false;
@@ -904,8 +976,8 @@ class SMTP
         $this->last_reply = $this->get_lines();
         // Fetch SMTP code and possible error code explanation
         $matches = [];
-        if (preg_match('/^([0-9]{3})[ -](?:([0-9]\\.[0-9]\\.[0-9]) )?/', $this->last_reply, $matches)) {
-            $code = $matches[1];
+        if (preg_match('/^([\d]{3})[ -](?:([\d]\\.[\d]\\.[\d]{1,2}) )?/', $this->last_reply, $matches)) {
+            $code = (int) $matches[1];
             $code_ex = (count($matches) > 2 ? $matches[2] : null);
             // Cut off error code from each response line
             $detail = preg_replace(
@@ -916,14 +988,14 @@ class SMTP
             );
         } else {
             // Fall back to simple parsing if regex fails
-            $code = substr($this->last_reply, 0, 3);
+            $code = (int) substr($this->last_reply, 0, 3);
             $code_ex = null;
             $detail = substr($this->last_reply, 4);
         }
 
         $this->edebug('SERVER -> CLIENT: ' . $this->last_reply, self::DEBUG_SERVER);
 
-        if (!in_array($code, (array) $expect)) {
+        if (!in_array($code, (array) $expect, true)) {
             $this->setError(
                 "$command command failed",
                 $detail,
@@ -1014,9 +1086,9 @@ class SMTP
     {
         //If SMTP transcripts are left enabled, or debug output is posted online
         //it can leak credentials, so hide credentials in all but lowest level
-        if (self::DEBUG_LOWLEVEL > $this->do_debug and
+        if (self::DEBUG_LOWLEVEL > $this->do_debug &&
             in_array($command, ['User & Password', 'Username', 'Password'], true)) {
-            $this->edebug('CLIENT -> SERVER: <credentials hidden>', self::DEBUG_CLIENT);
+            $this->edebug('CLIENT -> SERVER: [credentials hidden]', self::DEBUG_CLIENT);
         } else {
             $this->edebug('CLIENT -> SERVER: ' . $data, self::DEBUG_CLIENT);
         }
@@ -1062,7 +1134,7 @@ class SMTP
      *
      * @param string $name Name of SMTP extension or 'HELO'|'EHLO'
      *
-     * @return mixed
+     * @return string|bool|null
      */
     public function getServerExt($name)
     {
@@ -1073,10 +1145,10 @@ class SMTP
         }
 
         if (!array_key_exists($name, $this->server_caps)) {
-            if ('HELO' == $name) {
+            if ('HELO' === $name) {
                 return $this->server_caps['EHLO'];
             }
-            if ('EHLO' == $name || array_key_exists('EHLO', $this->server_caps)) {
+            if ('EHLO' === $name || array_key_exists('EHLO', $this->server_caps)) {
                 return false;
             }
             $this->setError('HELO handshake was used; No information about server extensions available');
@@ -1120,36 +1192,63 @@ class SMTP
         }
         $selR = [$this->smtp_conn];
         $selW = null;
-        while (is_resource($this->smtp_conn) and !feof($this->smtp_conn)) {
+        while (is_resource($this->smtp_conn) && !feof($this->smtp_conn)) {
             //Must pass vars in here as params are by reference
-            if (!stream_select($selR, $selW, $selW, $this->Timelimit)) {
+            //solution for signals inspired by https://github.com/symfony/symfony/pull/6540
+            set_error_handler([$this, 'errorHandler']);
+            $n = stream_select($selR, $selW, $selW, $this->Timelimit);
+            restore_error_handler();
+
+            if ($n === false) {
+                $message = $this->getError()['detail'];
+
                 $this->edebug(
-                    'SMTP -> get_lines(): timed-out (' . $this->Timeout . ' sec)',
+                    'SMTP -> get_lines(): select failed (' . $message . ')',
+                    self::DEBUG_LOWLEVEL
+                );
+
+                //stream_select returns false when the `select` system call is interrupted by an incoming signal, try the select again
+                if (stripos($message, 'interrupted system call') !== false) {
+                    $this->edebug(
+                        'SMTP -> get_lines(): retrying stream_select',
+                        self::DEBUG_LOWLEVEL
+                    );
+                    $this->setError('');
+                    continue;
+                }
+
+                break;
+            }
+
+            if (!$n) {
+                $this->edebug(
+                    'SMTP -> get_lines(): select timed-out in (' . $this->Timelimit . ' sec)',
                     self::DEBUG_LOWLEVEL
                 );
                 break;
             }
+
             //Deliberate noise suppression - errors are handled afterwards
-            $str = @fgets($this->smtp_conn, 515);
+            $str = @fgets($this->smtp_conn, self::MAX_REPLY_LENGTH);
             $this->edebug('SMTP INBOUND: "' . trim($str) . '"', self::DEBUG_LOWLEVEL);
             $data .= $str;
             // If response is only 3 chars (not valid, but RFC5321 S4.2 says it must be handled),
-            // or 4th character is a space, we are done reading, break the loop,
-            // string array access is a micro-optimisation over strlen
-            if (!isset($str[3]) or (isset($str[3]) and $str[3] == ' ')) {
+            // or 4th character is a space or a line break char, we are done reading, break the loop.
+            // String array access is a significant micro-optimisation over strlen
+            if (!isset($str[3]) || $str[3] === ' ' || $str[3] === "\r" || $str[3] === "\n") {
                 break;
             }
             // Timed-out? Log and break
             $info = stream_get_meta_data($this->smtp_conn);
             if ($info['timed_out']) {
                 $this->edebug(
-                    'SMTP -> get_lines(): timed-out (' . $this->Timeout . ' sec)',
+                    'SMTP -> get_lines(): stream timed-out (' . $this->Timeout . ' sec)',
                     self::DEBUG_LOWLEVEL
                 );
                 break;
             }
             // Now check if reads took too long
-            if ($endtime and time() > $endtime) {
+            if ($endtime && time() > $endtime) {
                 $this->edebug(
                     'SMTP -> get_lines(): timelimit reached (' .
                     $this->Timelimit . ' sec)',
@@ -1289,7 +1388,7 @@ class SMTP
      * If no reply has been received yet, it will return null.
      * If no pattern was matched, it will return false.
      *
-     * @return bool|null|string
+     * @return bool|string|null
      */
     protected function recordLastTransactionID()
     {
@@ -1300,6 +1399,7 @@ class SMTP
         } else {
             $this->last_smtp_transaction_id = false;
             foreach ($this->smtp_transaction_id_patterns as $smtp_transaction_id_pattern) {
+                $matches = [];
                 if (preg_match($smtp_transaction_id_pattern, $reply, $matches)) {
                     $this->last_smtp_transaction_id = trim($matches[1]);
                     break;
@@ -1315,7 +1415,7 @@ class SMTP
      * If no reply has been received yet, it will return null.
      * If no pattern was matched, it will return false.
      *
-     * @return bool|null|string
+     * @return bool|string|null
      *
      * @see recordLastTransactionID()
      */
diff --git a/vendor/phpspec/prophecy/CHANGES.md b/vendor/phpspec/prophecy/CHANGES.md
new file mode 100644
index 0000000000000000000000000000000000000000..30ac3fc68b23e32d0bfda612476f6059a4093537
--- /dev/null
+++ b/vendor/phpspec/prophecy/CHANGES.md
@@ -0,0 +1,288 @@
+1.13.0 / 2021/03/17
+===================
+
+* [added] willYield can now specify a return value [@camilledejoye]
+* [added] Prophecy exception interfaces are explicitly Throwable [@ciaranmcnulty]
+* [fixed] Argument::in() and notIn() now marked as static [@tyteen4a03]
+* [fixed] Can now double unions containing false [@ciaranmcnulty]
+* [fixed] Virtual magic methods with arguments are now doublable in PHP 8 [@ciaranmcnulty]
+
+1.12.2 / 2020/12/19
+===================
+
+* [fixed] MethodNotFoundException sometimes thrown with wrong class attached [@ciaranmcnulty]
+
+1.12.1 / 2020/10/29
+===================
+
+* [fixed] Incorrect handling of inherited 'self' return types [@ciaranmcnulty]
+
+1.12.0 / 2020/10/28
+===================
+
+* [added] PHP 8 support [@ciaranmcnulty]
+* [added] Argument::in() and Argument::notIn() [@viniciusalonso]
+* [added] Support for union and mixed types [@ciaranmcnulty]
+* [fixed] Issues caused by introduction of named parameters [@ciaranmcnulty]
+* [fixed] Issues caused by stricter rounding [@ciaranmcnulty]
+
+1.11.1 / 2020/07/08
+===================
+
+* [fixed] can't double objects with `self` type hints (@greg0ire)
+* [fixed] cloned doubes were not loosely comparable (@tkulka)
+
+1.11.0 / 2020/07/07
+===================
+
+* [changed] dropped support for PHP versions earlier than 7.2 (@ciaranmcnulty)
+* [fixed] removed use of Reflection APIs deprecated in PHP 8.0 (@Ayesh)
+
+1.10.3 / 2020/03/05
+===================
+
+* [fixed] removed fatal error when phpdocumentor/reflection-docblock 5 parses an invalid `@method` tag (@stof)
+
+1.10.2 / 2020/01/20
+===================
+
+* [added] support for new versions of `sebastian/comparator` and `sebastian/recursion-context` (@sebastianbergmann)
+
+1.10.1 / 2019/12/22
+===================
+
+* [fixed] identical callables no longer match as arguments (@ciaranmcnulty)
+
+1.10.0 / 2019/12/17
+===================
+
+* [added] shouldHaveBeenCalled evaluation happens later so un-stubbed calls don't throw (@elvetemedve)
+* [added] methods can now be doubled case-insensitively to match PHP semantics (@michalbundyra)
+* [fixed] reduced memory usage by optimising CachedDoubler (@DonCallisto)
+* [fixed] removed fatal error nesting level when comparing large objects (@scroach)
+
+1.9.0 / 2019/10/03
+==================
+
+* [added] Add willYield feature to Method Prophecy(@tkotosz)
+* [fixed] Allow `MethodProphecy::willThrow()` to accept Throwable as string (@timoschinkel )
+* [fixed] Allow new version of phpdocumentor/reflection-docblock (@ricpelo)
+
+1.8.1 / 2019/06/13
+==================
+
+* [fixed] Don't try to patch final constructors (@NiR)
+
+1.8.0 / 2018/08/05
+==================
+
+* Support for void return types without explicit will (@crellbar)
+* Clearer error message for unexpected method calls (@meridius)
+* Clearer error message for aggregate exceptions (@meridius)
+* More verbose `shouldBeCalledOnce` expectation (@olvlvl)
+* Ability to double Throwable, or methods that extend it (@ciaranmcnulty)
+* [fixed] Doubling methods where class has additional arguments to interface (@webimpress)
+* [fixed] Doubling methods where arguments are nullable but default is not null (@webimpress)
+* [fixed] Doubling magic methods on parent class (@dsnopek)
+* [fixed] Check method predictions only once (@dontub)
+* [fixed] Argument::containingString throwing error when called with non-string (@dcabrejas)
+
+1.7.6 / 2018/04/18
+==================
+
+* Allow sebastian/comparator ^3.0 (@sebastianbergmann)
+
+1.7.5 / 2018/02/11
+==================
+
+* Support for object return type hints (thanks @greg0ire)
+
+1.7.4 / 2018/02/11
+==================
+
+* Fix issues with PHP 7.2 (thanks @greg0ire)
+* Support object type hints in PHP 7.2 (thanks @@jansvoboda11)
+
+1.7.3 / 2017/11/24
+==================
+
+* Fix SplInfo ClassPatch to work with Symfony 4 (Thanks @gnugat)
+
+1.7.2 / 2017-10-04
+==================
+
+* Reverted "check method predictions only once" due to it breaking Spies
+
+1.7.1 / 2017-10-03
+==================
+
+* Allow PHP5 keywords methods generation on PHP7 (thanks @bycosta)
+* Allow reflection-docblock v4 (thanks @GrahamCampbell)
+* Check method predictions only once (thanks @dontub)
+* Escape file path sent to \SplFileObjectConstructor when running on Windows (thanks @danmartin-epiphany)
+
+1.7.0 / 2017-03-02
+==================
+
+* Add full PHP 7.1 Support (thanks @prolic)
+* Allow `sebastian/comparator ^2.0` (thanks @sebastianbergmann)
+* Allow `sebastian/recursion-context ^3.0` (thanks @sebastianbergmann)
+* Allow `\Error` instances in `ThrowPromise` (thanks @jameshalsall)
+* Support `phpspec/phpspect ^3.2` (thanks @Sam-Burns)
+* Fix failing builds (thanks @Sam-Burns)
+
+1.6.2 / 2016-11-21
+==================
+
+* Added support for detecting @method on interfaces that the class itself implements, or when the stubbed class is an interface itself (thanks @Seldaek)
+* Added support for sebastian/recursion-context 2 (thanks @sebastianbergmann)
+* Added testing on PHP 7.1 on Travis (thanks @danizord)
+* Fixed the usage of the phpunit comparator (thanks @Anyqax)
+
+1.6.1 / 2016-06-07
+==================
+
+  * Ignored empty method names in invalid `@method` phpdoc
+  * Fixed the mocking of SplFileObject
+  * Added compatibility with phpdocumentor/reflection-docblock 3
+
+1.6.0 / 2016-02-15
+==================
+
+  * Add Variadics support (thanks @pamil)
+  * Add ProphecyComparator for comparing objects that need revealing (thanks @jon-acker)
+  * Add ApproximateValueToken (thanks @dantleech)
+  * Add support for 'self' and 'parent' return type (thanks @bendavies)
+  * Add __invoke to allowed reflectable methods list (thanks @ftrrtf)
+  * Updated ExportUtil to reflect the latest changes by Sebastian (thanks @jakari)
+  * Specify the required php version for composer (thanks @jakzal)
+  * Exclude 'args' in the generated backtrace (thanks @oradwell)
+  * Fix code generation for scalar parameters (thanks @trowski)
+  * Fix missing sprintf in InvalidArgumentException __construct call (thanks @emmanuelballery)
+  * Fix phpdoc for magic methods (thanks @Tobion)
+  * Fix PhpDoc for interfaces usage (thanks @ImmRanneft)
+  * Prevent final methods from being manually extended (thanks @kamioftea)
+  * Enhance exception for invalid argument to ThrowPromise (thanks @Tobion)
+
+1.5.0 / 2015-04-27
+==================
+
+  * Add support for PHP7 scalar type hints (thanks @trowski)
+  * Add support for PHP7 return types (thanks @trowski)
+  * Update internal test suite to support PHP7
+
+1.4.1 / 2015-04-27
+==================
+
+  * Fixed bug in closure-based argument tokens (#181)
+
+1.4.0 / 2015-03-27
+==================
+
+  * Fixed errors in return type phpdocs (thanks @sobit)
+  * Fixed stringifying of hash containing one value (thanks @avant1)
+  * Improved clarity of method call expectation exception (thanks @dantleech)
+  * Add ability to specify which argument is returned in willReturnArgument (thanks @coderbyheart)
+  * Add more information to MethodNotFound exceptions (thanks @ciaranmcnulty)
+  * Support for mocking classes with methods that return references (thanks @edsonmedina)
+  * Improved object comparison (thanks @whatthejeff)
+  * Adopted '^' in composer dependencies (thanks @GrahamCampbell)
+  * Fixed non-typehinted arguments being treated as optional (thanks @whatthejeff)
+  * Magic methods are now filtered for keywords (thanks @seagoj)
+  * More readable errors for failure when expecting single calls (thanks @dantleech)
+
+1.3.1 / 2014-11-17
+==================
+
+  * Fix the edge case when failed predictions weren't recorded for `getCheckedPredictions()`
+
+1.3.0 / 2014-11-14
+==================
+
+  * Add a way to get checked predictions with `MethodProphecy::getCheckedPredictions()`
+  * Fix HHVM compatibility
+  * Remove dead code (thanks @stof)
+  * Add support for DirectoryIterators (thanks @shanethehat)
+
+1.2.0 / 2014-07-18
+==================
+
+  * Added support for doubling magic methods documented in the class phpdoc (thanks @armetiz)
+  * Fixed a segfault appearing in some cases (thanks @dmoreaulf)
+  * Fixed the doubling of methods with typehints on non-existent classes (thanks @gquemener)
+  * Added support for internal classes using keywords as method names (thanks @milan)
+  * Added IdenticalValueToken and Argument::is (thanks @florianv)
+  * Removed the usage of scalar typehints in HHVM as HHVM 3 does not support them anymore in PHP code (thanks @whatthejeff)
+
+1.1.2 / 2014-01-24
+==================
+
+  * Spy automatically promotes spied method call to an expected one
+
+1.1.1 / 2014-01-15
+==================
+
+  * Added support for HHVM
+
+1.1.0 / 2014-01-01
+==================
+
+  * Changed the generated class names to use a static counter instead of a random number
+  * Added a clss patch for ReflectionClass::newInstance to make its argument optional consistently (thanks @docteurklein)
+  * Fixed mirroring of classes with typehints on non-existent classes (thanks @docteurklein)
+  * Fixed the support of array callables in CallbackPromise and CallbackPrediction (thanks @ciaranmcnulty)
+  * Added support for properties in ObjectStateToken (thanks @adrienbrault)
+  * Added support for mocking classes with a final constructor (thanks @ciaranmcnulty)
+  * Added ArrayEveryEntryToken and Argument::withEveryEntry() (thanks @adrienbrault)
+  * Added an exception when trying to prophesize on a final method instead of ignoring silently (thanks @docteurklein)
+  * Added StringContainToken and Argument::containingString() (thanks @peterjmit)
+  * Added ``shouldNotHaveBeenCalled`` on the MethodProphecy (thanks @ciaranmcnulty)
+  * Fixed the comparison of objects in ExactValuetoken (thanks @sstok)
+  * Deprecated ``shouldNotBeenCalled`` in favor of ``shouldNotHaveBeenCalled``
+
+1.0.4 / 2013-08-10
+==================
+
+  * Better randomness for generated class names (thanks @sstok)
+  * Add support for interfaces into TypeToken and Argument::type() (thanks @sstok)
+  * Add support for old-style (method name === class name) constructors (thanks @l310 for report)
+
+1.0.3 / 2013-07-04
+==================
+
+  * Support callable typehints (thanks @stof)
+  * Do not attempt to autoload arrays when generating code (thanks @MarcoDeBortoli)
+  * New ArrayEntryToken (thanks @kagux)
+
+1.0.2 / 2013-05-19
+==================
+
+  * Logical `AND` token added (thanks @kagux)
+  * Logical `NOT` token added (thanks @kagux)
+  * Add support for setting custom constructor arguments
+  * Properly stringify hashes
+  * Record calls that throw exceptions
+  * Migrate spec suite to PhpSpec 2.0
+
+1.0.1 / 2013-04-30
+==================
+
+  * Fix broken UnexpectedCallException message
+  * Trim AggregateException message
+
+1.0.0 / 2013-04-29
+==================
+
+  * Improve exception messages
+
+1.0.0-BETA2 / 2013-04-03
+========================
+
+  * Add more debug information to CallTimes and Call prediction exception messages
+  * Fix MethodNotFoundException wrong namespace (thanks @gunnarlium)
+  * Fix some typos in the exception messages (thanks @pborreli)
+
+1.0.0-BETA1 / 2013-03-25
+========================
+
+  * Initial release
diff --git a/vendor/phpspec/prophecy/LICENSE b/vendor/phpspec/prophecy/LICENSE
new file mode 100644
index 0000000000000000000000000000000000000000..c8b364711a50e5bbb07f2f046411138645cb8008
--- /dev/null
+++ b/vendor/phpspec/prophecy/LICENSE
@@ -0,0 +1,23 @@
+Copyright (c) 2013 Konstantin Kudryashov <ever.zet@gmail.com>
+                   Marcello Duarte <marcello.duarte@gmail.com>
+
+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/phpspec/prophecy/README.md b/vendor/phpspec/prophecy/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..f0d2ff08985c96ae6fbf0efcfd308f489d9c28c5
--- /dev/null
+++ b/vendor/phpspec/prophecy/README.md
@@ -0,0 +1,404 @@
+# Prophecy
+
+[![Stable release](https://poser.pugx.org/phpspec/prophecy/version.svg)](https://packagist.org/packages/phpspec/prophecy)
+[![Build Status](https://travis-ci.org/phpspec/prophecy.svg?branch=master)](https://travis-ci.org/phpspec/prophecy)
+
+Prophecy is a highly opinionated yet very powerful and flexible PHP object mocking
+framework. Though initially it was created to fulfil phpspec2 needs, it is flexible
+enough to be used inside any testing framework out there with minimal effort.
+
+## A simple example
+
+```php
+<?php
+
+class UserTest extends PHPUnit\Framework\TestCase
+{
+    private $prophet;
+
+    public function testPasswordHashing()
+    {
+        $hasher = $this->prophet->prophesize('App\Security\Hasher');
+        $user   = new App\Entity\User($hasher->reveal());
+
+        $hasher->generateHash($user, 'qwerty')->willReturn('hashed_pass');
+
+        $user->setPassword('qwerty');
+
+        $this->assertEquals('hashed_pass', $user->getPassword());
+    }
+
+    protected function setUp()
+    {
+        $this->prophet = new \Prophecy\Prophet;
+    }
+
+    protected function tearDown()
+    {
+        $this->prophet->checkPredictions();
+    }
+}
+```
+
+## Installation
+
+### Prerequisites
+
+Prophecy requires PHP 7.2.0 or greater.
+
+### Setup through composer
+
+First, add Prophecy to the list of dependencies inside your `composer.json`:
+
+```json
+{
+    "require-dev": {
+        "phpspec/prophecy": "~1.0"
+    }
+}
+```
+
+Then simply install it with composer:
+
+```bash
+$> composer install --prefer-dist
+```
+
+You can read more about Composer on its [official webpage](http://getcomposer.org).
+
+## How to use it
+
+First of all, in Prophecy every word has a logical meaning, even the name of the library
+itself (Prophecy). When you start feeling that, you'll become very fluid with this
+tool.
+
+For example, Prophecy has been named that way because it concentrates on describing the future
+behavior of objects with very limited knowledge about them. But as with any other prophecy,
+those object prophecies can't create themselves - there should be a Prophet:
+
+```php
+$prophet = new Prophecy\Prophet;
+```
+
+The Prophet creates prophecies by *prophesizing* them:
+
+```php
+$prophecy = $prophet->prophesize();
+```
+
+The result of the `prophesize()` method call is a new object of class `ObjectProphecy`. Yes,
+that's your specific object prophecy, which describes how your object would behave
+in the near future. But first, you need to specify which object you're talking about,
+right?
+
+```php
+$prophecy->willExtend('stdClass');
+$prophecy->willImplement('SessionHandlerInterface');
+```
+
+There are 2 interesting calls - `willExtend` and `willImplement`. The first one tells
+object prophecy that our object should extend a specific class. The second one says that
+it should implement some interface. Obviously, objects in PHP can implement multiple
+interfaces, but extend only one parent class.
+
+### Dummies
+
+Ok, now we have our object prophecy. What can we do with it? First of all, we can get
+our object *dummy* by revealing its prophecy:
+
+```php
+$dummy = $prophecy->reveal();
+```
+
+The `$dummy` variable now holds a special dummy object. Dummy objects are objects that extend
+and/or implement preset classes/interfaces by overriding all their public methods. The key
+point about dummies is that they do not hold any logic - they just do nothing. Any method
+of the dummy will always return `null` and the dummy will never throw any exceptions.
+Dummy is your friend if you don't care about the actual behavior of this double and just need
+a token object to satisfy a method typehint.
+
+You need to understand one thing - a dummy is not a prophecy. Your object prophecy is still
+assigned to `$prophecy` variable and in order to manipulate with your expectations, you
+should work with it. `$dummy` is a dummy - a simple php object that tries to fulfil your
+prophecy.
+
+### Stubs
+
+Ok, now we know how to create basic prophecies and reveal dummies from them. That's
+awesome if we don't care about our _doubles_ (objects that reflect originals)
+interactions. If we do, we need to use *stubs* or *mocks*.
+
+A stub is an object double, which doesn't have any expectations about the object behavior,
+but when put in specific environment, behaves in specific way. Ok, I know, it's cryptic,
+but bear with me for a minute. Simply put, a stub is a dummy, which depending on the called
+method signature does different things (has logic). To create stubs in Prophecy:
+
+```php
+$prophecy->read('123')->willReturn('value');
+```
+
+Oh wow. We've just made an arbitrary call on the object prophecy? Yes, we did. And this
+call returned us a new object instance of class `MethodProphecy`. Yep, that's a specific
+method with arguments prophecy. Method prophecies give you the ability to create method
+promises or predictions. We'll talk about method predictions later in the _Mocks_ section.
+
+#### Promises
+
+Promises are logical blocks, that represent your fictional methods in prophecy terms
+and they are handled by the `MethodProphecy::will(PromiseInterface $promise)` method.
+As a matter of fact, the call that we made earlier (`willReturn('value')`) is a simple
+shortcut to:
+
+```php
+$prophecy->read('123')->will(new Prophecy\Promise\ReturnPromise(array('value')));
+```
+
+This promise will cause any call to our double's `read()` method with exactly one
+argument - `'123'` to always return `'value'`. But that's only for this
+promise, there's plenty others you can use:
+
+- `ReturnPromise` or `->willReturn(1)` - returns a value from a method call
+- `ReturnArgumentPromise` or `->willReturnArgument($index)` - returns the nth method argument from call
+- `ThrowPromise` or `->willThrow($exception)` - causes the method to throw specific exception
+- `CallbackPromise` or `->will($callback)` - gives you a quick way to define your own custom logic
+
+Keep in mind, that you can always add even more promises by implementing
+`Prophecy\Promise\PromiseInterface`.
+
+#### Method prophecies idempotency
+
+Prophecy enforces same method prophecies and, as a consequence, same promises and
+predictions for the same method calls with the same arguments. This means:
+
+```php
+$methodProphecy1 = $prophecy->read('123');
+$methodProphecy2 = $prophecy->read('123');
+$methodProphecy3 = $prophecy->read('321');
+
+$methodProphecy1 === $methodProphecy2;
+$methodProphecy1 !== $methodProphecy3;
+```
+
+That's interesting, right? Now you might ask me how would you define more complex
+behaviors where some method call changes behavior of others. In PHPUnit or Mockery
+you do that by predicting how many times your method will be called. In Prophecy,
+you'll use promises for that:
+
+```php
+$user->getName()->willReturn(null);
+
+// For PHP 5.4
+$user->setName('everzet')->will(function () {
+    $this->getName()->willReturn('everzet');
+});
+
+// For PHP 5.3
+$user->setName('everzet')->will(function ($args, $user) {
+    $user->getName()->willReturn('everzet');
+});
+
+// Or
+$user->setName('everzet')->will(function ($args) use ($user) {
+    $user->getName()->willReturn('everzet');
+});
+```
+
+And now it doesn't matter how many times or in which order your methods are called.
+What matters is their behaviors and how well you faked it.
+
+Note: If the method is called several times, you can use the following syntax to return different
+values for each call:
+
+```php
+$prophecy->read('123')->willReturn(1, 2, 3);
+```
+
+This feature is actually not recommended for most cases. Relying on the order of
+calls for the same arguments tends to make test fragile, as adding one more call
+can break everything.
+
+#### Arguments wildcarding
+
+The previous example is awesome (at least I hope it is for you), but that's not
+optimal enough. We hardcoded `'everzet'` in our expectation. Isn't there a better
+way? In fact there is, but it involves understanding what this `'everzet'`
+actually is.
+
+You see, even if method arguments used during method prophecy creation look
+like simple method arguments, in reality they are not. They are argument token
+wildcards.  As a matter of fact, `->setName('everzet')` looks like a simple call just
+because Prophecy automatically transforms it under the hood into:
+
+```php
+$user->setName(new Prophecy\Argument\Token\ExactValueToken('everzet'));
+```
+
+Those argument tokens are simple PHP classes, that implement
+`Prophecy\Argument\Token\TokenInterface` and tell Prophecy how to compare real arguments
+with your expectations. And yes, those classnames are damn big. That's why there's a
+shortcut class `Prophecy\Argument`, which you can use to create tokens like that:
+
+```php
+use Prophecy\Argument;
+
+$user->setName(Argument::exact('everzet'));
+```
+
+`ExactValueToken` is not very useful in our case as it forced us to hardcode the username.
+That's why Prophecy comes bundled with a bunch of other tokens:
+
+- `IdenticalValueToken` or `Argument::is($value)` - checks that the argument is identical to a specific value
+- `ExactValueToken` or `Argument::exact($value)` - checks that the argument matches a specific value
+- `TypeToken` or `Argument::type($typeOrClass)` - checks that the argument matches a specific type or
+  classname
+- `ObjectStateToken` or `Argument::which($method, $value)` - checks that the argument method returns
+  a specific value
+- `CallbackToken` or `Argument::that(callback)` - checks that the argument matches a custom callback
+- `AnyValueToken` or `Argument::any()` - matches any argument
+- `AnyValuesToken` or `Argument::cetera()` - matches any arguments to the rest of the signature
+- `StringContainsToken` or `Argument::containingString($value)` - checks that the argument contains a specific string value
+- `InArrayToken` or `Argument::in($array)` - checks if value is in array
+- `NotInArrayToken` or `Argument::notIn($array)` - checks if value is not in array
+
+And you can add even more by implementing `TokenInterface` with your own custom classes.
+
+So, let's refactor our initial `{set,get}Name()` logic with argument tokens:
+
+```php
+use Prophecy\Argument;
+
+$user->getName()->willReturn(null);
+
+// For PHP 5.4
+$user->setName(Argument::type('string'))->will(function ($args) {
+    $this->getName()->willReturn($args[0]);
+});
+
+// For PHP 5.3
+$user->setName(Argument::type('string'))->will(function ($args, $user) {
+    $user->getName()->willReturn($args[0]);
+});
+
+// Or
+$user->setName(Argument::type('string'))->will(function ($args) use ($user) {
+    $user->getName()->willReturn($args[0]);
+});
+```
+
+That's it. Now our `{set,get}Name()` prophecy will work with any string argument provided to it.
+We've just described how our stub object should behave, even though the original object could have
+no behavior whatsoever.
+
+One last bit about arguments now. You might ask, what happens in case of:
+
+```php
+use Prophecy\Argument;
+
+$user->getName()->willReturn(null);
+
+// For PHP 5.4
+$user->setName(Argument::type('string'))->will(function ($args) {
+    $this->getName()->willReturn($args[0]);
+});
+
+// For PHP 5.3
+$user->setName(Argument::type('string'))->will(function ($args, $user) {
+    $user->getName()->willReturn($args[0]);
+});
+
+// Or
+$user->setName(Argument::type('string'))->will(function ($args) use ($user) {
+    $user->getName()->willReturn($args[0]);
+});
+
+$user->setName(Argument::any())->will(function () {
+});
+```
+
+Nothing. Your stub will continue behaving the way it did before. That's because of how
+arguments wildcarding works. Every argument token type has a different score level, which
+wildcard then uses to calculate the final arguments match score and use the method prophecy
+promise that has the highest score. In this case, `Argument::type()` in case of success
+scores `5` and `Argument::any()` scores `3`. So the type token wins, as does the first
+`setName()` method prophecy and its promise. The simple rule of thumb - more precise token
+always wins.
+
+#### Getting stub objects
+
+Ok, now we know how to define our prophecy method promises, let's get our stub from
+it:
+
+```php
+$stub = $prophecy->reveal();
+```
+
+As you might see, the only difference between how we get dummies and stubs is that with
+stubs we describe every object conversation instead of just agreeing with `null` returns
+(object being *dummy*). As a matter of fact, after you define your first promise
+(method call), Prophecy will force you to define all the communications - it throws
+the `UnexpectedCallException` for any call you didn't describe with object prophecy before
+calling it on a stub.
+
+### Mocks
+
+Now we know how to define doubles without behavior (dummies) and doubles with behavior, but
+no expectations (stubs). What's left is doubles for which we have some expectations. These
+are called mocks and in Prophecy they look almost exactly the same as stubs, except that
+they define *predictions* instead of *promises* on method prophecies:
+
+```php
+$entityManager->flush()->shouldBeCalled();
+```
+
+#### Predictions
+
+The `shouldBeCalled()` method here assigns `CallPrediction` to our method prophecy.
+Predictions are a delayed behavior check for your prophecies. You see, during the entire lifetime
+of your doubles, Prophecy records every single call you're making against it inside your
+code. After that, Prophecy can use this collected information to check if it matches defined
+predictions. You can assign predictions to method prophecies using the
+`MethodProphecy::should(PredictionInterface $prediction)` method. As a matter of fact,
+the `shouldBeCalled()` method we used earlier is just a shortcut to:
+
+```php
+$entityManager->flush()->should(new Prophecy\Prediction\CallPrediction());
+```
+
+It checks if your method of interest (that matches both the method name and the arguments wildcard)
+was called 1 or more times. If the prediction failed then it throws an exception. When does this
+check happen? Whenever you call `checkPredictions()` on the main Prophet object:
+
+```php
+$prophet->checkPredictions();
+```
+
+In PHPUnit, you would want to put this call into the `tearDown()` method. If no predictions
+are defined, it would do nothing. So it won't harm to call it after every test.
+
+There are plenty more predictions you can play with:
+
+- `CallPrediction` or `shouldBeCalled()` - checks that the method has been called 1 or more times
+- `NoCallsPrediction` or `shouldNotBeCalled()` - checks that the method has not been called
+- `CallTimesPrediction` or `shouldBeCalledTimes($count)` - checks that the method has been called
+  `$count` times
+- `CallbackPrediction` or `should($callback)` - checks the method against your own custom callback
+
+Of course, you can always create your own custom prediction any time by implementing
+`PredictionInterface`.
+
+### Spies
+
+The last bit of awesomeness in Prophecy is out-of-the-box spies support. As I said in the previous
+section, Prophecy records every call made during the double's entire lifetime. This means
+you don't need to record predictions in order to check them. You can also do it
+manually by using the `MethodProphecy::shouldHave(PredictionInterface $prediction)` method:
+
+```php
+$em = $prophet->prophesize('Doctrine\ORM\EntityManager');
+
+$controller->createUser($em->reveal());
+
+$em->flush()->shouldHaveBeenCalled();
+```
+
+Such manipulation with doubles is called spying. And with Prophecy it just works.
diff --git a/vendor/phpspec/prophecy/composer.json b/vendor/phpspec/prophecy/composer.json
new file mode 100644
index 0000000000000000000000000000000000000000..de6b7c2b9540d9e9de1db1d18bc8c359e8f3fe5e
--- /dev/null
+++ b/vendor/phpspec/prophecy/composer.json
@@ -0,0 +1,50 @@
+{
+    "name":         "phpspec/prophecy",
+    "description":  "Highly opinionated mocking framework for PHP 5.3+",
+    "keywords":     ["Mock", "Stub", "Dummy", "Double", "Fake", "Spy"],
+    "homepage":     "https://github.com/phpspec/prophecy",
+    "type":         "library",
+    "license":      "MIT",
+    "authors":      [
+        {
+            "name":      "Konstantin Kudryashov",
+            "email":     "ever.zet@gmail.com",
+            "homepage":  "http://everzet.com"
+        },
+        {
+            "name":      "Marcello Duarte",
+            "email":     "marcello.duarte@gmail.com"
+        }
+    ],
+
+    "require": {
+        "php":                               "^7.2 || ~8.0, <8.1",
+        "phpdocumentor/reflection-docblock": "^5.2",
+        "sebastian/comparator":              "^3.0 || ^4.0",
+        "doctrine/instantiator":             "^1.2",
+        "sebastian/recursion-context":       "^3.0 || ^4.0"
+    },
+
+    "require-dev": {
+        "phpspec/phpspec": "^6.0",
+        "phpunit/phpunit": "^8.0 || ^9.0"
+    },
+
+    "autoload": {
+        "psr-4": {
+            "Prophecy\\": "src/Prophecy"
+        }
+    },
+
+    "autoload-dev": {
+        "psr-4": {
+            "Fixtures\\Prophecy\\": "fixtures"
+        }
+    },
+
+    "extra": {
+        "branch-alias": {
+            "dev-master": "1.11.x-dev"
+        }
+    }
+}
diff --git a/vendor/phpspec/prophecy/src/Prophecy/Argument.php b/vendor/phpspec/prophecy/src/Prophecy/Argument.php
new file mode 100644
index 0000000000000000000000000000000000000000..674255a27959c2a12b219430ed0aeae3c99c18bd
--- /dev/null
+++ b/vendor/phpspec/prophecy/src/Prophecy/Argument.php
@@ -0,0 +1,239 @@
+<?php
+
+/*
+ * This file is part of the Prophecy.
+ * (c) Konstantin Kudryashov <ever.zet@gmail.com>
+ *     Marcello Duarte <marcello.duarte@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Prophecy;
+
+use Prophecy\Argument\Token;
+
+/**
+ * Argument tokens shortcuts.
+ *
+ * @author Konstantin Kudryashov <ever.zet@gmail.com>
+ */
+class Argument
+{
+    /**
+     * Checks that argument is exact value or object.
+     *
+     * @param mixed $value
+     *
+     * @return Token\ExactValueToken
+     */
+    public static function exact($value)
+    {
+        return new Token\ExactValueToken($value);
+    }
+
+    /**
+     * Checks that argument is of specific type or instance of specific class.
+     *
+     * @param string $type Type name (`integer`, `string`) or full class name
+     *
+     * @return Token\TypeToken
+     */
+    public static function type($type)
+    {
+        return new Token\TypeToken($type);
+    }
+
+    /**
+     * Checks that argument object has specific state.
+     *
+     * @param string $methodName
+     * @param mixed  $value
+     *
+     * @return Token\ObjectStateToken
+     */
+    public static function which($methodName, $value)
+    {
+        return new Token\ObjectStateToken($methodName, $value);
+    }
+
+    /**
+     * Checks that argument matches provided callback.
+     *
+     * @param callable $callback
+     *
+     * @return Token\CallbackToken
+     */
+    public static function that($callback)
+    {
+        return new Token\CallbackToken($callback);
+    }
+
+    /**
+     * Matches any single value.
+     *
+     * @return Token\AnyValueToken
+     */
+    public static function any()
+    {
+        return new Token\AnyValueToken;
+    }
+
+    /**
+     * Matches all values to the rest of the signature.
+     *
+     * @return Token\AnyValuesToken
+     */
+    public static function cetera()
+    {
+        return new Token\AnyValuesToken;
+    }
+
+    /**
+     * Checks that argument matches all tokens
+     *
+     * @param mixed ... a list of tokens
+     *
+     * @return Token\LogicalAndToken
+     */
+    public static function allOf()
+    {
+        return new Token\LogicalAndToken(func_get_args());
+    }
+
+    /**
+     * Checks that argument array or countable object has exact number of elements.
+     *
+     * @param integer $value array elements count
+     *
+     * @return Token\ArrayCountToken
+     */
+    public static function size($value)
+    {
+        return new Token\ArrayCountToken($value);
+    }
+
+    /**
+     * Checks that argument array contains (key, value) pair
+     *
+     * @param mixed $key   exact value or token
+     * @param mixed $value exact value or token
+     *
+     * @return Token\ArrayEntryToken
+     */
+    public static function withEntry($key, $value)
+    {
+        return new Token\ArrayEntryToken($key, $value);
+    }
+
+    /**
+     * Checks that arguments array entries all match value
+     *
+     * @param mixed $value
+     *
+     * @return Token\ArrayEveryEntryToken
+     */
+    public static function withEveryEntry($value)
+    {
+        return new Token\ArrayEveryEntryToken($value);
+    }
+
+    /**
+     * Checks that argument array contains value
+     *
+     * @param mixed $value
+     *
+     * @return Token\ArrayEntryToken
+     */
+    public static function containing($value)
+    {
+        return new Token\ArrayEntryToken(self::any(), $value);
+    }
+
+    /**
+     * Checks that argument array has key
+     *
+     * @param mixed $key exact value or token
+     *
+     * @return Token\ArrayEntryToken
+     */
+    public static function withKey($key)
+    {
+        return new Token\ArrayEntryToken($key, self::any());
+    }
+
+    /**
+     * Checks that argument does not match the value|token.
+     *
+     * @param mixed $value either exact value or argument token
+     *
+     * @return Token\LogicalNotToken
+     */
+    public static function not($value)
+    {
+        return new Token\LogicalNotToken($value);
+    }
+
+    /**
+     * @param string $value
+     *
+     * @return Token\StringContainsToken
+     */
+    public static function containingString($value)
+    {
+        return new Token\StringContainsToken($value);
+    }
+
+    /**
+     * Checks that argument is identical value.
+     *
+     * @param mixed $value
+     *
+     * @return Token\IdenticalValueToken
+     */
+    public static function is($value)
+    {
+        return new Token\IdenticalValueToken($value);
+    }
+
+    /**
+     * Check that argument is same value when rounding to the
+     * given precision.
+     *
+     * @param float $value
+     * @param float $precision
+     *
+     * @return Token\ApproximateValueToken
+     */
+    public static function approximate($value, $precision = 0)
+    {
+        return new Token\ApproximateValueToken($value, $precision);
+    }
+
+    /**
+     * Checks that argument is in array.
+     *
+     * @param array $value
+     *
+     * @return Token\InArrayToken
+     */
+
+    public static function in($value)
+    {
+        return new Token\InArrayToken($value);
+    }
+
+    /**
+     * Checks that argument is not in array.
+     *
+     * @param array $value
+     *
+     * @return Token\NotInArrayToken
+     */
+
+    public static function notIn($value)
+    {
+        return new Token\NotInArrayToken($value);
+    }
+
+}
diff --git a/vendor/phpspec/prophecy/src/Prophecy/Argument/ArgumentsWildcard.php b/vendor/phpspec/prophecy/src/Prophecy/Argument/ArgumentsWildcard.php
new file mode 100644
index 0000000000000000000000000000000000000000..a088f21d21df4e9d233b7003cf40f2fdd1bfd5ab
--- /dev/null
+++ b/vendor/phpspec/prophecy/src/Prophecy/Argument/ArgumentsWildcard.php
@@ -0,0 +1,101 @@
+<?php
+
+/*
+ * This file is part of the Prophecy.
+ * (c) Konstantin Kudryashov <ever.zet@gmail.com>
+ *     Marcello Duarte <marcello.duarte@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Prophecy\Argument;
+
+/**
+ * Arguments wildcarding.
+ *
+ * @author Konstantin Kudryashov <ever.zet@gmail.com>
+ */
+class ArgumentsWildcard
+{
+    /**
+     * @var Token\TokenInterface[]
+     */
+    private $tokens = array();
+    private $string;
+
+    /**
+     * Initializes wildcard.
+     *
+     * @param array $arguments Array of argument tokens or values
+     */
+    public function __construct(array $arguments)
+    {
+        foreach ($arguments as $argument) {
+            if (!$argument instanceof Token\TokenInterface) {
+                $argument = new Token\ExactValueToken($argument);
+            }
+
+            $this->tokens[] = $argument;
+        }
+    }
+
+    /**
+     * Calculates wildcard match score for provided arguments.
+     *
+     * @param array $arguments
+     *
+     * @return false|int False OR integer score (higher - better)
+     */
+    public function scoreArguments(array $arguments)
+    {
+        if (0 == count($arguments) && 0 == count($this->tokens)) {
+            return 1;
+        }
+
+        $arguments  = array_values($arguments);
+        $totalScore = 0;
+        foreach ($this->tokens as $i => $token) {
+            $argument = isset($arguments[$i]) ? $arguments[$i] : null;
+            if (1 >= $score = $token->scoreArgument($argument)) {
+                return false;
+            }
+
+            $totalScore += $score;
+
+            if (true === $token->isLast()) {
+                return $totalScore;
+            }
+        }
+
+        if (count($arguments) > count($this->tokens)) {
+            return false;
+        }
+
+        return $totalScore;
+    }
+
+    /**
+     * Returns string representation for wildcard.
+     *
+     * @return string
+     */
+    public function __toString()
+    {
+        if (null === $this->string) {
+            $this->string = implode(', ', array_map(function ($token) {
+                return (string) $token;
+            }, $this->tokens));
+        }
+
+        return $this->string;
+    }
+
+    /**
+     * @return array
+     */
+    public function getTokens()
+    {
+        return $this->tokens;
+    }
+}
diff --git a/vendor/phpspec/prophecy/src/Prophecy/Argument/Token/AnyValueToken.php b/vendor/phpspec/prophecy/src/Prophecy/Argument/Token/AnyValueToken.php
new file mode 100644
index 0000000000000000000000000000000000000000..50988112c5a59c90f2ba06d8a6405ae4a75c37e9
--- /dev/null
+++ b/vendor/phpspec/prophecy/src/Prophecy/Argument/Token/AnyValueToken.php
@@ -0,0 +1,52 @@
+<?php
+
+/*
+ * This file is part of the Prophecy.
+ * (c) Konstantin Kudryashov <ever.zet@gmail.com>
+ *     Marcello Duarte <marcello.duarte@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Prophecy\Argument\Token;
+
+/**
+ * Any single value token.
+ *
+ * @author Konstantin Kudryashov <ever.zet@gmail.com>
+ */
+class AnyValueToken implements TokenInterface
+{
+    /**
+     * Always scores 3 for any argument.
+     *
+     * @param $argument
+     *
+     * @return int
+     */
+    public function scoreArgument($argument)
+    {
+        return 3;
+    }
+
+    /**
+     * Returns false.
+     *
+     * @return bool
+     */
+    public function isLast()
+    {
+        return false;
+    }
+
+    /**
+     * Returns string representation for token.
+     *
+     * @return string
+     */
+    public function __toString()
+    {
+        return '*';
+    }
+}
diff --git a/vendor/phpspec/prophecy/src/Prophecy/Argument/Token/AnyValuesToken.php b/vendor/phpspec/prophecy/src/Prophecy/Argument/Token/AnyValuesToken.php
new file mode 100644
index 0000000000000000000000000000000000000000..f76b17bc0ba3748624c757b555f7f77ea7252589
--- /dev/null
+++ b/vendor/phpspec/prophecy/src/Prophecy/Argument/Token/AnyValuesToken.php
@@ -0,0 +1,52 @@
+<?php
+
+/*
+ * This file is part of the Prophecy.
+ * (c) Konstantin Kudryashov <ever.zet@gmail.com>
+ *     Marcello Duarte <marcello.duarte@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Prophecy\Argument\Token;
+
+/**
+ * Any values token.
+ *
+ * @author Konstantin Kudryashov <ever.zet@gmail.com>
+ */
+class AnyValuesToken implements TokenInterface
+{
+    /**
+     * Always scores 2 for any argument.
+     *
+     * @param $argument
+     *
+     * @return int
+     */
+    public function scoreArgument($argument)
+    {
+        return 2;
+    }
+
+    /**
+     * Returns true to stop wildcard from processing other tokens.
+     *
+     * @return bool
+     */
+    public function isLast()
+    {
+        return true;
+    }
+
+    /**
+     * Returns string representation for token.
+     *
+     * @return string
+     */
+    public function __toString()
+    {
+        return '* [, ...]';
+    }
+}
diff --git a/vendor/phpspec/prophecy/src/Prophecy/Argument/Token/ApproximateValueToken.php b/vendor/phpspec/prophecy/src/Prophecy/Argument/Token/ApproximateValueToken.php
new file mode 100644
index 0000000000000000000000000000000000000000..901744ab0a7c6c1269d35c4a5ed035e7fea2ae94
--- /dev/null
+++ b/vendor/phpspec/prophecy/src/Prophecy/Argument/Token/ApproximateValueToken.php
@@ -0,0 +1,55 @@
+<?php
+
+/*
+ * This file is part of the Prophecy.
+ * (c) Konstantin Kudryashov <ever.zet@gmail.com>
+ *     Marcello Duarte <marcello.duarte@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Prophecy\Argument\Token;
+
+/**
+ * Approximate value token
+ *
+ * @author Daniel Leech <daniel@dantleech.com>
+ */
+class ApproximateValueToken implements TokenInterface
+{
+    private $value;
+    private $precision;
+
+    public function __construct($value, $precision = 0)
+    {
+        $this->value = $value;
+        $this->precision = $precision;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function scoreArgument($argument)
+    {
+        return round((float)$argument, $this->precision) === round($this->value, $this->precision) ? 10 : false;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function isLast()
+    {
+        return false;
+    }
+
+    /**
+     * Returns string representation for token.
+     *
+     * @return string
+     */
+    public function __toString()
+    {
+        return sprintf('≅%s', round($this->value, $this->precision));
+    }
+}
diff --git a/vendor/phpspec/prophecy/src/Prophecy/Argument/Token/ArrayCountToken.php b/vendor/phpspec/prophecy/src/Prophecy/Argument/Token/ArrayCountToken.php
new file mode 100644
index 0000000000000000000000000000000000000000..96b4befd7f512d8e8690107a01dcd1077e33870e
--- /dev/null
+++ b/vendor/phpspec/prophecy/src/Prophecy/Argument/Token/ArrayCountToken.php
@@ -0,0 +1,86 @@
+<?php
+
+/*
+ * This file is part of the Prophecy.
+ * (c) Konstantin Kudryashov <ever.zet@gmail.com>
+ *     Marcello Duarte <marcello.duarte@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Prophecy\Argument\Token;
+
+/**
+ * Array elements count token.
+ *
+ * @author Boris Mikhaylov <kaguxmail@gmail.com>
+ */
+
+class ArrayCountToken implements TokenInterface
+{
+    private $count;
+
+    /**
+     * @param integer $value
+     */
+    public function __construct($value)
+    {
+        $this->count = $value;
+    }
+
+    /**
+     * Scores 6 when argument has preset number of elements.
+     *
+     * @param $argument
+     *
+     * @return bool|int
+     */
+    public function scoreArgument($argument)
+    {
+        return $this->isCountable($argument) && $this->hasProperCount($argument) ? 6 : false;
+    }
+
+    /**
+     * Returns false.
+     *
+     * @return boolean
+     */
+    public function isLast()
+    {
+        return false;
+    }
+
+    /**
+     * Returns string representation for token.
+     *
+     * @return string
+     */
+    public function __toString()
+    {
+        return sprintf('count(%s)', $this->count);
+    }
+
+    /**
+     * Returns true if object is either array or instance of \Countable
+     *
+     * @param $argument
+     * @return bool
+     */
+    private function isCountable($argument)
+    {
+        return (is_array($argument) || $argument instanceof \Countable);
+    }
+
+    /**
+     * Returns true if $argument has expected number of elements
+     *
+     * @param array|\Countable $argument
+     *
+     * @return bool
+     */
+    private function hasProperCount($argument)
+    {
+        return $this->count === count($argument);
+    }
+}
diff --git a/vendor/phpspec/prophecy/src/Prophecy/Argument/Token/ArrayEntryToken.php b/vendor/phpspec/prophecy/src/Prophecy/Argument/Token/ArrayEntryToken.php
new file mode 100644
index 0000000000000000000000000000000000000000..0305fc7207c4c55c22e844e519718171b489811b
--- /dev/null
+++ b/vendor/phpspec/prophecy/src/Prophecy/Argument/Token/ArrayEntryToken.php
@@ -0,0 +1,143 @@
+<?php
+
+/*
+ * This file is part of the Prophecy.
+ * (c) Konstantin Kudryashov <ever.zet@gmail.com>
+ *     Marcello Duarte <marcello.duarte@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Prophecy\Argument\Token;
+
+use Prophecy\Exception\InvalidArgumentException;
+
+/**
+ * Array entry token.
+ *
+ * @author Boris Mikhaylov <kaguxmail@gmail.com>
+ */
+class ArrayEntryToken implements TokenInterface
+{
+    /** @var \Prophecy\Argument\Token\TokenInterface */
+    private $key;
+    /** @var \Prophecy\Argument\Token\TokenInterface */
+    private $value;
+
+    /**
+     * @param mixed $key   exact value or token
+     * @param mixed $value exact value or token
+     */
+    public function __construct($key, $value)
+    {
+        $this->key = $this->wrapIntoExactValueToken($key);
+        $this->value = $this->wrapIntoExactValueToken($value);
+    }
+
+    /**
+     * Scores half of combined scores from key and value tokens for same entry. Capped at 8.
+     * If argument implements \ArrayAccess without \Traversable, then key token is restricted to ExactValueToken.
+     *
+     * @param array|\ArrayAccess|\Traversable $argument
+     *
+     * @throws \Prophecy\Exception\InvalidArgumentException
+     * @return bool|int
+     */
+    public function scoreArgument($argument)
+    {
+        if ($argument instanceof \Traversable) {
+            $argument = iterator_to_array($argument);
+        }
+
+        if ($argument instanceof \ArrayAccess) {
+            $argument = $this->convertArrayAccessToEntry($argument);
+        }
+
+        if (!is_array($argument) || empty($argument)) {
+            return false;
+        }
+
+        $keyScores = array_map(array($this->key,'scoreArgument'), array_keys($argument));
+        $valueScores = array_map(array($this->value,'scoreArgument'), $argument);
+        $scoreEntry = function ($value, $key) {
+            return $value && $key ? min(8, ($key + $value) / 2) : false;
+        };
+
+        return max(array_map($scoreEntry, $valueScores, $keyScores));
+    }
+
+    /**
+     * Returns false.
+     *
+     * @return boolean
+     */
+    public function isLast()
+    {
+        return false;
+    }
+
+    /**
+     * Returns string representation for token.
+     *
+     * @return string
+     */
+    public function __toString()
+    {
+        return sprintf('[..., %s => %s, ...]', $this->key, $this->value);
+    }
+
+    /**
+     * Returns key
+     *
+     * @return TokenInterface
+     */
+    public function getKey()
+    {
+        return $this->key;
+    }
+
+    /**
+     * Returns value
+     *
+     * @return TokenInterface
+     */
+    public function getValue()
+    {
+        return $this->value;
+    }
+
+    /**
+     * Wraps non token $value into ExactValueToken
+     *
+     * @param $value
+     * @return TokenInterface
+     */
+    private function wrapIntoExactValueToken($value)
+    {
+        return $value instanceof TokenInterface ? $value : new ExactValueToken($value);
+    }
+
+    /**
+     * Converts instance of \ArrayAccess to key => value array entry
+     *
+     * @param \ArrayAccess $object
+     *
+     * @return array|null
+     * @throws \Prophecy\Exception\InvalidArgumentException
+     */
+    private function convertArrayAccessToEntry(\ArrayAccess $object)
+    {
+        if (!$this->key instanceof ExactValueToken) {
+            throw new InvalidArgumentException(sprintf(
+                'You can only use exact value tokens to match key of ArrayAccess object'.PHP_EOL.
+                'But you used `%s`.',
+                $this->key
+            ));
+        }
+
+        $key = $this->key->getValue();
+
+        return $object->offsetExists($key) ? array($key => $object[$key]) : array();
+    }
+}
diff --git a/vendor/phpspec/prophecy/src/Prophecy/Argument/Token/ArrayEveryEntryToken.php b/vendor/phpspec/prophecy/src/Prophecy/Argument/Token/ArrayEveryEntryToken.php
new file mode 100644
index 0000000000000000000000000000000000000000..5d41fa487c4c0332f14cdc9521ff602a12296a07
--- /dev/null
+++ b/vendor/phpspec/prophecy/src/Prophecy/Argument/Token/ArrayEveryEntryToken.php
@@ -0,0 +1,82 @@
+<?php
+
+/*
+ * This file is part of the Prophecy.
+ * (c) Konstantin Kudryashov <ever.zet@gmail.com>
+ *     Marcello Duarte <marcello.duarte@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Prophecy\Argument\Token;
+
+/**
+ * Array every entry token.
+ *
+ * @author Adrien Brault <adrien.brault@gmail.com>
+ */
+class ArrayEveryEntryToken implements TokenInterface
+{
+    /**
+     * @var TokenInterface
+     */
+    private $value;
+
+    /**
+     * @param mixed $value exact value or token
+     */
+    public function __construct($value)
+    {
+        if (!$value instanceof TokenInterface) {
+            $value = new ExactValueToken($value);
+        }
+
+        $this->value = $value;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function scoreArgument($argument)
+    {
+        if (!$argument instanceof \Traversable && !is_array($argument)) {
+            return false;
+        }
+
+        $scores = array();
+        foreach ($argument as $key => $argumentEntry) {
+            $scores[] = $this->value->scoreArgument($argumentEntry);
+        }
+
+        if (empty($scores) || in_array(false, $scores, true)) {
+            return false;
+        }
+
+        return array_sum($scores) / count($scores);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function isLast()
+    {
+        return false;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function __toString()
+    {
+        return sprintf('[%s, ..., %s]', $this->value, $this->value);
+    }
+
+    /**
+     * @return TokenInterface
+     */
+    public function getValue()
+    {
+        return $this->value;
+    }
+}
diff --git a/vendor/phpspec/prophecy/src/Prophecy/Argument/Token/CallbackToken.php b/vendor/phpspec/prophecy/src/Prophecy/Argument/Token/CallbackToken.php
new file mode 100644
index 0000000000000000000000000000000000000000..f45ba20becd0d180bedc003efb83e0b743bfa148
--- /dev/null
+++ b/vendor/phpspec/prophecy/src/Prophecy/Argument/Token/CallbackToken.php
@@ -0,0 +1,75 @@
+<?php
+
+/*
+ * This file is part of the Prophecy.
+ * (c) Konstantin Kudryashov <ever.zet@gmail.com>
+ *     Marcello Duarte <marcello.duarte@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Prophecy\Argument\Token;
+
+use Prophecy\Exception\InvalidArgumentException;
+
+/**
+ * Callback-verified token.
+ *
+ * @author Konstantin Kudryashov <ever.zet@gmail.com>
+ */
+class CallbackToken implements TokenInterface
+{
+    private $callback;
+
+    /**
+     * Initializes token.
+     *
+     * @param callable $callback
+     *
+     * @throws \Prophecy\Exception\InvalidArgumentException
+     */
+    public function __construct($callback)
+    {
+        if (!is_callable($callback)) {
+            throw new InvalidArgumentException(sprintf(
+                'Callable expected as an argument to CallbackToken, but got %s.',
+                gettype($callback)
+            ));
+        }
+
+        $this->callback = $callback;
+    }
+
+    /**
+     * Scores 7 if callback returns true, false otherwise.
+     *
+     * @param $argument
+     *
+     * @return bool|int
+     */
+    public function scoreArgument($argument)
+    {
+        return call_user_func($this->callback, $argument) ? 7 : false;
+    }
+
+    /**
+     * Returns false.
+     *
+     * @return bool
+     */
+    public function isLast()
+    {
+        return false;
+    }
+
+    /**
+     * Returns string representation for token.
+     *
+     * @return string
+     */
+    public function __toString()
+    {
+        return 'callback()';
+    }
+}
diff --git a/vendor/phpspec/prophecy/src/Prophecy/Argument/Token/ExactValueToken.php b/vendor/phpspec/prophecy/src/Prophecy/Argument/Token/ExactValueToken.php
new file mode 100644
index 0000000000000000000000000000000000000000..045a1b90f988b09de43a1fbc84b92c4470be1844
--- /dev/null
+++ b/vendor/phpspec/prophecy/src/Prophecy/Argument/Token/ExactValueToken.php
@@ -0,0 +1,118 @@
+<?php
+
+/*
+ * This file is part of the Prophecy.
+ * (c) Konstantin Kudryashov <ever.zet@gmail.com>
+ *     Marcello Duarte <marcello.duarte@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Prophecy\Argument\Token;
+
+use SebastianBergmann\Comparator\ComparisonFailure;
+use Prophecy\Comparator\Factory as ComparatorFactory;
+use Prophecy\Util\StringUtil;
+
+/**
+ * Exact value token.
+ *
+ * @author Konstantin Kudryashov <ever.zet@gmail.com>
+ */
+class ExactValueToken implements TokenInterface
+{
+    private $value;
+    private $string;
+    private $util;
+    private $comparatorFactory;
+
+    /**
+     * Initializes token.
+     *
+     * @param mixed             $value
+     * @param StringUtil        $util
+     * @param ComparatorFactory $comparatorFactory
+     */
+    public function __construct($value, StringUtil $util = null, ComparatorFactory $comparatorFactory = null)
+    {
+        $this->value = $value;
+        $this->util  = $util ?: new StringUtil();
+
+        $this->comparatorFactory = $comparatorFactory ?: ComparatorFactory::getInstance();
+    }
+
+    /**
+     * Scores 10 if argument matches preset value.
+     *
+     * @param $argument
+     *
+     * @return bool|int
+     */
+    public function scoreArgument($argument)
+    {
+        if (is_object($argument) && is_object($this->value)) {
+            $comparator = $this->comparatorFactory->getComparatorFor(
+                $argument, $this->value
+            );
+
+            try {
+                $comparator->assertEquals($argument, $this->value);
+                return 10;
+            } catch (ComparisonFailure $failure) {
+            	return false;
+			}
+        }
+
+        // If either one is an object it should be castable to a string
+        if (is_object($argument) xor is_object($this->value)) {
+            if (is_object($argument) && !method_exists($argument, '__toString')) {
+                return false;
+            }
+
+            if (is_object($this->value) && !method_exists($this->value, '__toString')) {
+                return false;
+            }
+        } elseif (is_numeric($argument) && is_numeric($this->value)) {
+            // noop
+        } elseif (gettype($argument) !== gettype($this->value)) {
+            return false;
+        }
+
+        return $argument == $this->value ? 10 : false;
+    }
+
+    /**
+     * Returns preset value against which token checks arguments.
+     *
+     * @return mixed
+     */
+    public function getValue()
+    {
+        return $this->value;
+    }
+
+    /**
+     * Returns false.
+     *
+     * @return bool
+     */
+    public function isLast()
+    {
+        return false;
+    }
+
+    /**
+     * Returns string representation for token.
+     *
+     * @return string
+     */
+    public function __toString()
+    {
+        if (null === $this->string) {
+            $this->string = sprintf('exact(%s)', $this->util->stringify($this->value));
+        }
+
+        return $this->string;
+    }
+}
diff --git a/vendor/phpspec/prophecy/src/Prophecy/Argument/Token/IdenticalValueToken.php b/vendor/phpspec/prophecy/src/Prophecy/Argument/Token/IdenticalValueToken.php
new file mode 100644
index 0000000000000000000000000000000000000000..0b6d23ab667daa1dc6cb7d62031e083006c142ee
--- /dev/null
+++ b/vendor/phpspec/prophecy/src/Prophecy/Argument/Token/IdenticalValueToken.php
@@ -0,0 +1,74 @@
+<?php
+
+/*
+ * This file is part of the Prophecy.
+ * (c) Konstantin Kudryashov <ever.zet@gmail.com>
+ *     Marcello Duarte <marcello.duarte@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Prophecy\Argument\Token;
+
+use Prophecy\Util\StringUtil;
+
+/**
+ * Identical value token.
+ *
+ * @author Florian Voutzinos <florian@voutzinos.com>
+ */
+class IdenticalValueToken implements TokenInterface
+{
+    private $value;
+    private $string;
+    private $util;
+
+    /**
+     * Initializes token.
+     *
+     * @param mixed      $value
+     * @param StringUtil $util
+     */
+    public function __construct($value, StringUtil $util = null)
+    {
+        $this->value = $value;
+        $this->util  = $util ?: new StringUtil();
+    }
+
+    /**
+     * Scores 11 if argument matches preset value.
+     *
+     * @param $argument
+     *
+     * @return bool|int
+     */
+    public function scoreArgument($argument)
+    {
+        return $argument === $this->value ? 11 : false;
+    }
+
+    /**
+     * Returns false.
+     *
+     * @return bool
+     */
+    public function isLast()
+    {
+        return false;
+    }
+
+    /**
+     * Returns string representation for token.
+     *
+     * @return string
+     */
+    public function __toString()
+    {
+        if (null === $this->string) {
+            $this->string = sprintf('identical(%s)', $this->util->stringify($this->value));
+        }
+
+        return $this->string;
+    }
+}
diff --git a/vendor/phpspec/prophecy/src/Prophecy/Argument/Token/InArrayToken.php b/vendor/phpspec/prophecy/src/Prophecy/Argument/Token/InArrayToken.php
new file mode 100644
index 0000000000000000000000000000000000000000..f727aea422ef92b889087c3e6cc740accc40bab2
--- /dev/null
+++ b/vendor/phpspec/prophecy/src/Prophecy/Argument/Token/InArrayToken.php
@@ -0,0 +1,74 @@
+<?php
+
+/*
+ * This file is part of the Prophecy.
+ * (c) Konstantin Kudryashov <ever.zet@gmail.com>
+ *     Marcello Duarte <marcello.duarte@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Prophecy\Argument\Token;
+
+/**
+ * Check if values is in array
+ *
+ * @author Vinícius Alonso <vba321@hotmail.com>
+ */
+class InArrayToken implements TokenInterface
+{
+    private $token = array();
+    private $strict;
+
+    /**
+     * @param array $arguments tokens
+     * @param bool $strict
+     */
+    public function __construct(array $arguments, $strict = true)
+    {
+        $this->token = $arguments;
+        $this->strict = $strict;
+    }
+
+    /**
+     * Return scores 8 score if argument is in array.
+     *
+     * @param $argument
+     *
+     * @return bool|int
+     */
+    public function scoreArgument($argument)
+    {
+        if (count($this->token) === 0) {
+            return false;
+        }
+
+        if (\in_array($argument, $this->token, $this->strict)) {
+            return 8;
+        }
+
+        return false;
+    }
+
+    /**
+     * Returns false.
+     *
+     * @return boolean
+     */
+    public function isLast()
+    {
+        return false;
+    }
+
+    /**
+     * Returns string representation for token.
+     *
+     * @return string
+     */
+    public function __toString()
+    {
+        $arrayAsString = implode(', ', $this->token);
+        return "[{$arrayAsString}]";
+    }
+}
diff --git a/vendor/phpspec/prophecy/src/Prophecy/Argument/Token/LogicalAndToken.php b/vendor/phpspec/prophecy/src/Prophecy/Argument/Token/LogicalAndToken.php
new file mode 100644
index 0000000000000000000000000000000000000000..4ee1b25e11f22d633999058b6c1a13e5e761659d
--- /dev/null
+++ b/vendor/phpspec/prophecy/src/Prophecy/Argument/Token/LogicalAndToken.php
@@ -0,0 +1,80 @@
+<?php
+
+/*
+ * This file is part of the Prophecy.
+ * (c) Konstantin Kudryashov <ever.zet@gmail.com>
+ *     Marcello Duarte <marcello.duarte@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Prophecy\Argument\Token;
+
+/**
+ * Logical AND token.
+ *
+ * @author Boris Mikhaylov <kaguxmail@gmail.com>
+ */
+class LogicalAndToken implements TokenInterface
+{
+    private $tokens = array();
+
+    /**
+     * @param array $arguments exact values or tokens
+     */
+    public function __construct(array $arguments)
+    {
+        foreach ($arguments as $argument) {
+            if (!$argument instanceof TokenInterface) {
+                $argument = new ExactValueToken($argument);
+            }
+            $this->tokens[] = $argument;
+        }
+    }
+
+    /**
+     * Scores maximum score from scores returned by tokens for this argument if all of them score.
+     *
+     * @param $argument
+     *
+     * @return bool|int
+     */
+    public function scoreArgument($argument)
+    {
+        if (0 === count($this->tokens)) {
+            return false;
+        }
+
+        $maxScore = 0;
+        foreach ($this->tokens as $token) {
+            $score = $token->scoreArgument($argument);
+            if (false === $score) {
+                return false;
+            }
+            $maxScore = max($score, $maxScore);
+        }
+
+        return $maxScore;
+    }
+
+    /**
+     * Returns false.
+     *
+     * @return boolean
+     */
+    public function isLast()
+    {
+        return false;
+    }
+
+    /**
+     * Returns string representation for token.
+     *
+     * @return string
+     */
+    public function __toString()
+    {
+        return sprintf('bool(%s)', implode(' AND ', $this->tokens));
+    }
+}
diff --git a/vendor/phpspec/prophecy/src/Prophecy/Argument/Token/LogicalNotToken.php b/vendor/phpspec/prophecy/src/Prophecy/Argument/Token/LogicalNotToken.php
new file mode 100644
index 0000000000000000000000000000000000000000..623efa57a7f7c1f6600cbb360517094a8ec86a35
--- /dev/null
+++ b/vendor/phpspec/prophecy/src/Prophecy/Argument/Token/LogicalNotToken.php
@@ -0,0 +1,73 @@
+<?php
+
+/*
+ * This file is part of the Prophecy.
+ * (c) Konstantin Kudryashov <ever.zet@gmail.com>
+ *     Marcello Duarte <marcello.duarte@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Prophecy\Argument\Token;
+
+/**
+ * Logical NOT token.
+ *
+ * @author Boris Mikhaylov <kaguxmail@gmail.com>
+ */
+class LogicalNotToken implements TokenInterface
+{
+    /** @var \Prophecy\Argument\Token\TokenInterface  */
+    private $token;
+
+    /**
+     * @param mixed $value exact value or token
+     */
+    public function __construct($value)
+    {
+        $this->token = $value instanceof TokenInterface? $value : new ExactValueToken($value);
+    }
+
+    /**
+     * Scores 4 when preset token does not match the argument.
+     *
+     * @param $argument
+     *
+     * @return bool|int
+     */
+    public function scoreArgument($argument)
+    {
+        return false === $this->token->scoreArgument($argument) ? 4 : false;
+    }
+
+    /**
+     * Returns true if preset token is last.
+     *
+     * @return bool|int
+     */
+    public function isLast()
+    {
+        return $this->token->isLast();
+    }
+
+    /**
+     * Returns originating token.
+     *
+     * @return TokenInterface
+     */
+    public function getOriginatingToken()
+    {
+        return $this->token;
+    }
+
+    /**
+     * Returns string representation for token.
+     *
+     * @return string
+     */
+    public function __toString()
+    {
+        return sprintf('not(%s)', $this->token);
+    }
+}
diff --git a/vendor/phpspec/prophecy/src/Prophecy/Argument/Token/NotInArrayToken.php b/vendor/phpspec/prophecy/src/Prophecy/Argument/Token/NotInArrayToken.php
new file mode 100644
index 0000000000000000000000000000000000000000..6aed8aa506fc99c510ae770521e86e56fd8a749c
--- /dev/null
+++ b/vendor/phpspec/prophecy/src/Prophecy/Argument/Token/NotInArrayToken.php
@@ -0,0 +1,75 @@
+<?php
+
+/*
+ * This file is part of the Prophecy.
+ * (c) Konstantin Kudryashov <ever.zet@gmail.com>
+ *     Marcello Duarte <marcello.duarte@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Prophecy\Argument\Token;
+
+/**
+ * Check if values is not in array
+ *
+ * @author Vinícius Alonso <vba321@hotmail.com>
+ */
+class NotInArrayToken implements TokenInterface
+{
+    private $token = array();
+    private $strict;
+
+    /**
+     * @param array $arguments tokens
+     * @param bool $strict
+     */
+    public function __construct(array $arguments, $strict = true)
+    {
+        $this->token = $arguments;
+        $this->strict = $strict;
+    }
+
+    /**
+     * Return scores 8 score if argument is in array.
+     *
+     * @param $argument
+     *
+     * @return bool|int
+     */
+    public function scoreArgument($argument)
+    {
+        if (count($this->token) === 0) {
+            return false;
+        }
+
+        if (!\in_array($argument, $this->token, $this->strict)) {
+            return 8;
+        }
+
+        return false;
+    }
+
+    /**
+     * Returns false.
+     *
+     * @return boolean
+     */
+    public function isLast()
+    {
+        return false;
+    }
+
+    /**
+     * Returns string representation for token.
+     *
+     * @return string
+     */
+    public function __toString()
+    {
+        $arrayAsString = implode(', ', $this->token);
+        return "[{$arrayAsString}]";
+    }
+}
+
diff --git a/vendor/phpspec/prophecy/src/Prophecy/Argument/Token/ObjectStateToken.php b/vendor/phpspec/prophecy/src/Prophecy/Argument/Token/ObjectStateToken.php
new file mode 100644
index 0000000000000000000000000000000000000000..d7710776761da2660371e58a9519f8939b986829
--- /dev/null
+++ b/vendor/phpspec/prophecy/src/Prophecy/Argument/Token/ObjectStateToken.php
@@ -0,0 +1,104 @@
+<?php
+
+/*
+ * This file is part of the Prophecy.
+ * (c) Konstantin Kudryashov <ever.zet@gmail.com>
+ *     Marcello Duarte <marcello.duarte@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Prophecy\Argument\Token;
+
+use SebastianBergmann\Comparator\ComparisonFailure;
+use Prophecy\Comparator\Factory as ComparatorFactory;
+use Prophecy\Util\StringUtil;
+
+/**
+ * Object state-checker token.
+ *
+ * @author Konstantin Kudryashov <ever.zet@gmail.com>
+ */
+class ObjectStateToken implements TokenInterface
+{
+    private $name;
+    private $value;
+    private $util;
+    private $comparatorFactory;
+
+    /**
+     * Initializes token.
+     *
+     * @param string            $methodName
+     * @param mixed             $value             Expected return value
+     * @param null|StringUtil   $util
+     * @param ComparatorFactory $comparatorFactory
+     */
+    public function __construct(
+        $methodName,
+        $value,
+        StringUtil $util = null,
+        ComparatorFactory $comparatorFactory = null
+    ) {
+        $this->name  = $methodName;
+        $this->value = $value;
+        $this->util  = $util ?: new StringUtil;
+
+        $this->comparatorFactory = $comparatorFactory ?: ComparatorFactory::getInstance();
+    }
+
+    /**
+     * Scores 8 if argument is an object, which method returns expected value.
+     *
+     * @param mixed $argument
+     *
+     * @return bool|int
+     */
+    public function scoreArgument($argument)
+    {
+        if (is_object($argument) && method_exists($argument, $this->name)) {
+            $actual = call_user_func(array($argument, $this->name));
+
+            $comparator = $this->comparatorFactory->getComparatorFor(
+                $this->value, $actual
+            );
+
+            try {
+                $comparator->assertEquals($this->value, $actual);
+                return 8;
+            } catch (ComparisonFailure $failure) {
+                return false;
+            }
+        }
+
+        if (is_object($argument) && property_exists($argument, $this->name)) {
+            return $argument->{$this->name} === $this->value ? 8 : false;
+        }
+
+        return false;
+    }
+
+    /**
+     * Returns false.
+     *
+     * @return bool
+     */
+    public function isLast()
+    {
+        return false;
+    }
+
+    /**
+     * Returns string representation for token.
+     *
+     * @return string
+     */
+    public function __toString()
+    {
+        return sprintf('state(%s(), %s)',
+            $this->name,
+            $this->util->stringify($this->value)
+        );
+    }
+}
diff --git a/vendor/phpspec/prophecy/src/Prophecy/Argument/Token/StringContainsToken.php b/vendor/phpspec/prophecy/src/Prophecy/Argument/Token/StringContainsToken.php
new file mode 100644
index 0000000000000000000000000000000000000000..bd8d423f9164216165be17a6fe1cf743a0045c7d
--- /dev/null
+++ b/vendor/phpspec/prophecy/src/Prophecy/Argument/Token/StringContainsToken.php
@@ -0,0 +1,67 @@
+<?php
+
+/*
+ * This file is part of the Prophecy.
+ * (c) Konstantin Kudryashov <ever.zet@gmail.com>
+ *     Marcello Duarte <marcello.duarte@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Prophecy\Argument\Token;
+
+/**
+ * String contains token.
+ *
+ * @author Peter Mitchell <pete@peterjmit.com>
+ */
+class StringContainsToken implements TokenInterface
+{
+    private $value;
+
+    /**
+     * Initializes token.
+     *
+     * @param string $value
+     */
+    public function __construct($value)
+    {
+        $this->value = $value;
+    }
+
+    public function scoreArgument($argument)
+    {
+        return is_string($argument) && strpos($argument, $this->value) !== false ? 6 : false;
+    }
+
+    /**
+     * Returns preset value against which token checks arguments.
+     *
+     * @return mixed
+     */
+    public function getValue()
+    {
+        return $this->value;
+    }
+
+    /**
+     * Returns false.
+     *
+     * @return bool
+     */
+    public function isLast()
+    {
+        return false;
+    }
+
+    /**
+     * Returns string representation for token.
+     *
+     * @return string
+     */
+    public function __toString()
+    {
+        return sprintf('contains("%s")', $this->value);
+    }
+}
diff --git a/vendor/phpspec/prophecy/src/Prophecy/Argument/Token/TokenInterface.php b/vendor/phpspec/prophecy/src/Prophecy/Argument/Token/TokenInterface.php
new file mode 100644
index 0000000000000000000000000000000000000000..625d3bad22f06bf2524b75cf069d18c7e3b0775a
--- /dev/null
+++ b/vendor/phpspec/prophecy/src/Prophecy/Argument/Token/TokenInterface.php
@@ -0,0 +1,43 @@
+<?php
+
+/*
+ * This file is part of the Prophecy.
+ * (c) Konstantin Kudryashov <ever.zet@gmail.com>
+ *     Marcello Duarte <marcello.duarte@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Prophecy\Argument\Token;
+
+/**
+ * Argument token interface.
+ *
+ * @author Konstantin Kudryashov <ever.zet@gmail.com>
+ */
+interface TokenInterface
+{
+    /**
+     * Calculates token match score for provided argument.
+     *
+     * @param $argument
+     *
+     * @return bool|int
+     */
+    public function scoreArgument($argument);
+
+    /**
+     * Returns true if this token prevents check of other tokens (is last one).
+     *
+     * @return bool|int
+     */
+    public function isLast();
+
+    /**
+     * Returns string representation for token.
+     *
+     * @return string
+     */
+    public function __toString();
+}
diff --git a/vendor/phpspec/prophecy/src/Prophecy/Argument/Token/TypeToken.php b/vendor/phpspec/prophecy/src/Prophecy/Argument/Token/TypeToken.php
new file mode 100644
index 0000000000000000000000000000000000000000..cb65132ca0e034ba8e898fbf647be6327544f144
--- /dev/null
+++ b/vendor/phpspec/prophecy/src/Prophecy/Argument/Token/TypeToken.php
@@ -0,0 +1,76 @@
+<?php
+
+/*
+ * This file is part of the Prophecy.
+ * (c) Konstantin Kudryashov <ever.zet@gmail.com>
+ *     Marcello Duarte <marcello.duarte@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Prophecy\Argument\Token;
+
+use Prophecy\Exception\InvalidArgumentException;
+
+/**
+ * Value type token.
+ *
+ * @author Konstantin Kudryashov <ever.zet@gmail.com>
+ */
+class TypeToken implements TokenInterface
+{
+    private $type;
+
+    /**
+     * @param string $type
+     */
+    public function __construct($type)
+    {
+        $checker = "is_{$type}";
+        if (!function_exists($checker) && !interface_exists($type) && !class_exists($type)) {
+            throw new InvalidArgumentException(sprintf(
+                'Type or class name expected as an argument to TypeToken, but got %s.', $type
+            ));
+        }
+
+        $this->type = $type;
+    }
+
+    /**
+     * Scores 5 if argument has the same type this token was constructed with.
+     *
+     * @param $argument
+     *
+     * @return bool|int
+     */
+    public function scoreArgument($argument)
+    {
+        $checker = "is_{$this->type}";
+        if (function_exists($checker)) {
+            return call_user_func($checker, $argument) ? 5 : false;
+        }
+
+        return $argument instanceof $this->type ? 5 : false;
+    }
+
+    /**
+     * Returns false.
+     *
+     * @return bool
+     */
+    public function isLast()
+    {
+        return false;
+    }
+
+    /**
+     * Returns string representation for token.
+     *
+     * @return string
+     */
+    public function __toString()
+    {
+        return sprintf('type(%s)', $this->type);
+    }
+}
diff --git a/vendor/phpspec/prophecy/src/Prophecy/Call/Call.php b/vendor/phpspec/prophecy/src/Prophecy/Call/Call.php
new file mode 100644
index 0000000000000000000000000000000000000000..2652235453ded23b0910dff6bf5f69b7a76dbacb
--- /dev/null
+++ b/vendor/phpspec/prophecy/src/Prophecy/Call/Call.php
@@ -0,0 +1,162 @@
+<?php
+
+/*
+ * This file is part of the Prophecy.
+ * (c) Konstantin Kudryashov <ever.zet@gmail.com>
+ *     Marcello Duarte <marcello.duarte@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Prophecy\Call;
+
+use Exception;
+use Prophecy\Argument\ArgumentsWildcard;
+
+/**
+ * Call object.
+ *
+ * @author Konstantin Kudryashov <ever.zet@gmail.com>
+ */
+class Call
+{
+    private $methodName;
+    private $arguments;
+    private $returnValue;
+    private $exception;
+    private $file;
+    private $line;
+    private $scores;
+
+    /**
+     * Initializes call.
+     *
+     * @param string      $methodName
+     * @param array       $arguments
+     * @param mixed       $returnValue
+     * @param Exception   $exception
+     * @param null|string $file
+     * @param null|int    $line
+     */
+    public function __construct($methodName, array $arguments, $returnValue,
+                                Exception $exception = null, $file, $line)
+    {
+        $this->methodName  = $methodName;
+        $this->arguments   = $arguments;
+        $this->returnValue = $returnValue;
+        $this->exception   = $exception;
+        $this->scores      = new \SplObjectStorage();
+
+        if ($file) {
+            $this->file = $file;
+            $this->line = intval($line);
+        }
+    }
+
+    /**
+     * Returns called method name.
+     *
+     * @return string
+     */
+    public function getMethodName()
+    {
+        return $this->methodName;
+    }
+
+    /**
+     * Returns called method arguments.
+     *
+     * @return array
+     */
+    public function getArguments()
+    {
+        return $this->arguments;
+    }
+
+    /**
+     * Returns called method return value.
+     *
+     * @return null|mixed
+     */
+    public function getReturnValue()
+    {
+        return $this->returnValue;
+    }
+
+    /**
+     * Returns exception that call thrown.
+     *
+     * @return null|Exception
+     */
+    public function getException()
+    {
+        return $this->exception;
+    }
+
+    /**
+     * Returns callee filename.
+     *
+     * @return string
+     */
+    public function getFile()
+    {
+        return $this->file;
+    }
+
+    /**
+     * Returns callee line number.
+     *
+     * @return int
+     */
+    public function getLine()
+    {
+        return $this->line;
+    }
+
+    /**
+     * Returns short notation for callee place.
+     *
+     * @return string
+     */
+    public function getCallPlace()
+    {
+        if (null === $this->file) {
+            return 'unknown';
+        }
+
+        return sprintf('%s:%d', $this->file, $this->line);
+    }
+
+    /**
+     * Adds the wildcard match score for the provided wildcard.
+     *
+     * @param ArgumentsWildcard $wildcard
+     * @param false|int $score
+     *
+     * @return $this
+     */
+    public function addScore(ArgumentsWildcard $wildcard, $score)
+    {
+        $this->scores[$wildcard] = $score;
+
+        return $this;
+    }
+
+    /**
+     * Returns wildcard match score for the provided wildcard. The score is
+     * calculated if not already done.
+     *
+     * @param ArgumentsWildcard $wildcard
+     *
+     * @return false|int False OR integer score (higher - better)
+     */
+    public function getScore(ArgumentsWildcard $wildcard)
+    {
+        if (isset($this->scores[$wildcard])) {
+            return $this->scores[$wildcard];
+        }
+
+        return $this->scores[$wildcard] = $wildcard->scoreArguments($this->getArguments());
+    }
+}
diff --git a/vendor/phpspec/prophecy/src/Prophecy/Call/CallCenter.php b/vendor/phpspec/prophecy/src/Prophecy/Call/CallCenter.php
new file mode 100644
index 0000000000000000000000000000000000000000..00c526d7e2f8edec81696a73d8ca3f063848fb6b
--- /dev/null
+++ b/vendor/phpspec/prophecy/src/Prophecy/Call/CallCenter.php
@@ -0,0 +1,240 @@
+<?php
+
+/*
+ * This file is part of the Prophecy.
+ * (c) Konstantin Kudryashov <ever.zet@gmail.com>
+ *     Marcello Duarte <marcello.duarte@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Prophecy\Call;
+
+use Prophecy\Exception\Prophecy\MethodProphecyException;
+use Prophecy\Prophecy\ObjectProphecy;
+use Prophecy\Argument\ArgumentsWildcard;
+use Prophecy\Util\StringUtil;
+use Prophecy\Exception\Call\UnexpectedCallException;
+use SplObjectStorage;
+
+/**
+ * Calls receiver & manager.
+ *
+ * @author Konstantin Kudryashov <ever.zet@gmail.com>
+ */
+class CallCenter
+{
+    private $util;
+
+    /**
+     * @var Call[]
+     */
+    private $recordedCalls = array();
+
+    /**
+     * @var SplObjectStorage
+     */
+    private $unexpectedCalls;
+
+    /**
+     * Initializes call center.
+     *
+     * @param StringUtil $util
+     */
+    public function __construct(StringUtil $util = null)
+    {
+        $this->util = $util ?: new StringUtil;
+        $this->unexpectedCalls = new SplObjectStorage();
+    }
+
+    /**
+     * Makes and records specific method call for object prophecy.
+     *
+     * @param ObjectProphecy $prophecy
+     * @param string         $methodName
+     * @param array          $arguments
+     *
+     * @return mixed Returns null if no promise for prophecy found or promise return value.
+     *
+     * @throws \Prophecy\Exception\Call\UnexpectedCallException If no appropriate method prophecy found
+     */
+    public function makeCall(ObjectProphecy $prophecy, $methodName, array $arguments)
+    {
+        // For efficiency exclude 'args' from the generated backtrace
+        // Limit backtrace to last 3 calls as we don't use the rest
+        $backtrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 3);
+
+        $file = $line = null;
+        if (isset($backtrace[2]) && isset($backtrace[2]['file'])) {
+            $file = $backtrace[2]['file'];
+            $line = $backtrace[2]['line'];
+        }
+
+        // If no method prophecies defined, then it's a dummy, so we'll just return null
+        if ('__destruct' === strtolower($methodName) || 0 == count($prophecy->getMethodProphecies())) {
+            $this->recordedCalls[] = new Call($methodName, $arguments, null, null, $file, $line);
+
+            return null;
+        }
+
+        // There are method prophecies, so it's a fake/stub. Searching prophecy for this call
+        $matches = $this->findMethodProphecies($prophecy, $methodName, $arguments);
+
+        // If fake/stub doesn't have method prophecy for this call - throw exception
+        if (!count($matches)) {
+            $this->unexpectedCalls->attach(new Call($methodName, $arguments, null, null, $file, $line), $prophecy);
+            $this->recordedCalls[] = new Call($methodName, $arguments, null, null, $file, $line);
+
+            return null;
+        }
+
+        // Sort matches by their score value
+        @usort($matches, function ($match1, $match2) { return $match2[0] - $match1[0]; });
+
+        $score = $matches[0][0];
+        // If Highest rated method prophecy has a promise - execute it or return null instead
+        $methodProphecy = $matches[0][1];
+        $returnValue = null;
+        $exception   = null;
+        if ($promise = $methodProphecy->getPromise()) {
+            try {
+                $returnValue = $promise->execute($arguments, $prophecy, $methodProphecy);
+            } catch (\Exception $e) {
+                $exception = $e;
+            }
+        }
+
+        if ($methodProphecy->hasReturnVoid() && $returnValue !== null) {
+            throw new MethodProphecyException(
+                "The method \"$methodName\" has a void return type, but the promise returned a value",
+                $methodProphecy
+            );
+        }
+
+        $this->recordedCalls[] = $call = new Call(
+            $methodName, $arguments, $returnValue, $exception, $file, $line
+        );
+        $call->addScore($methodProphecy->getArgumentsWildcard(), $score);
+
+        if (null !== $exception) {
+            throw $exception;
+        }
+
+        return $returnValue;
+    }
+
+    /**
+     * Searches for calls by method name & arguments wildcard.
+     *
+     * @param string            $methodName
+     * @param ArgumentsWildcard $wildcard
+     *
+     * @return Call[]
+     */
+    public function findCalls($methodName, ArgumentsWildcard $wildcard)
+    {
+        $methodName = strtolower($methodName);
+
+        return array_values(
+            array_filter($this->recordedCalls, function (Call $call) use ($methodName, $wildcard) {
+                return $methodName === strtolower($call->getMethodName())
+                    && 0 < $call->getScore($wildcard)
+                ;
+            })
+        );
+    }
+
+    /**
+     * @throws UnexpectedCallException
+     */
+    public function checkUnexpectedCalls()
+    {
+        /** @var Call $call */
+        foreach ($this->unexpectedCalls as $call) {
+            $prophecy = $this->unexpectedCalls[$call];
+
+            // If fake/stub doesn't have method prophecy for this call - throw exception
+            if (!count($this->findMethodProphecies($prophecy, $call->getMethodName(), $call->getArguments()))) {
+                throw $this->createUnexpectedCallException($prophecy, $call->getMethodName(), $call->getArguments());
+            }
+        }
+    }
+
+    private function createUnexpectedCallException(ObjectProphecy $prophecy, $methodName,
+                                                   array $arguments)
+    {
+        $classname = get_class($prophecy->reveal());
+        $indentationLength = 8; // looks good
+        $argstring = implode(
+            ",\n",
+            $this->indentArguments(
+                array_map(array($this->util, 'stringify'), $arguments),
+                $indentationLength
+            )
+        );
+
+        $expected = array();
+
+        foreach (array_merge(...array_values($prophecy->getMethodProphecies())) as $methodProphecy) {
+            $expected[] = sprintf(
+                "  - %s(\n" .
+                "%s\n" .
+                "    )",
+                $methodProphecy->getMethodName(),
+                implode(
+                    ",\n",
+                    $this->indentArguments(
+                        array_map('strval', $methodProphecy->getArgumentsWildcard()->getTokens()),
+                        $indentationLength
+                    )
+                )
+            );
+        }
+
+        return new UnexpectedCallException(
+            sprintf(
+                "Unexpected method call on %s:\n".
+                "  - %s(\n".
+                "%s\n".
+                "    )\n".
+                "expected calls were:\n".
+                "%s",
+
+                $classname, $methodName, $argstring, implode("\n", $expected)
+            ),
+            $prophecy, $methodName, $arguments
+
+        );
+    }
+
+    private function indentArguments(array $arguments, $indentationLength)
+    {
+        return preg_replace_callback(
+            '/^/m',
+            function () use ($indentationLength) {
+                return str_repeat(' ', $indentationLength);
+            },
+            $arguments
+        );
+    }
+
+    /**
+     * @param ObjectProphecy $prophecy
+     * @param string $methodName
+     * @param array $arguments
+     *
+     * @return array
+     */
+    private function findMethodProphecies(ObjectProphecy $prophecy, $methodName, array $arguments)
+    {
+        $matches = array();
+        foreach ($prophecy->getMethodProphecies($methodName) as $methodProphecy) {
+            if (0 < $score = $methodProphecy->getArgumentsWildcard()->scoreArguments($arguments)) {
+                $matches[] = array($score, $methodProphecy);
+            }
+        }
+
+        return $matches;
+    }
+}
diff --git a/vendor/phpspec/prophecy/src/Prophecy/Comparator/ClosureComparator.php b/vendor/phpspec/prophecy/src/Prophecy/Comparator/ClosureComparator.php
new file mode 100644
index 0000000000000000000000000000000000000000..fa4f578ee5059272e3befffe7639df7619864a8b
--- /dev/null
+++ b/vendor/phpspec/prophecy/src/Prophecy/Comparator/ClosureComparator.php
@@ -0,0 +1,44 @@
+<?php
+
+/*
+ * This file is part of the Prophecy.
+ * (c) Konstantin Kudryashov <ever.zet@gmail.com>
+ *     Marcello Duarte <marcello.duarte@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Prophecy\Comparator;
+
+use SebastianBergmann\Comparator\Comparator;
+use SebastianBergmann\Comparator\ComparisonFailure;
+
+/**
+ * Closure comparator.
+ *
+ * @author Konstantin Kudryashov <ever.zet@gmail.com>
+ */
+final class ClosureComparator extends Comparator
+{
+    public function accepts($expected, $actual)
+    {
+        return is_object($expected) && $expected instanceof \Closure
+            && is_object($actual) && $actual instanceof \Closure;
+    }
+
+    public function assertEquals($expected, $actual, $delta = 0.0, $canonicalize = false, $ignoreCase = false, array &$processed = array())
+    {
+        if ($expected !== $actual) {
+            throw new ComparisonFailure(
+                $expected,
+                $actual,
+                // we don't need a diff
+                '',
+                '',
+                false,
+                'all closures are different if not identical'
+            );
+        }
+    }
+}
diff --git a/vendor/phpspec/prophecy/src/Prophecy/Comparator/Factory.php b/vendor/phpspec/prophecy/src/Prophecy/Comparator/Factory.php
new file mode 100644
index 0000000000000000000000000000000000000000..2070db142b51c01b6deca0e0704def67ff6f9535
--- /dev/null
+++ b/vendor/phpspec/prophecy/src/Prophecy/Comparator/Factory.php
@@ -0,0 +1,47 @@
+<?php
+
+/*
+ * This file is part of the Prophecy.
+ * (c) Konstantin Kudryashov <ever.zet@gmail.com>
+ *     Marcello Duarte <marcello.duarte@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Prophecy\Comparator;
+
+use SebastianBergmann\Comparator\Factory as BaseFactory;
+
+/**
+ * Prophecy comparator factory.
+ *
+ * @author Konstantin Kudryashov <ever.zet@gmail.com>
+ */
+final class Factory extends BaseFactory
+{
+    /**
+     * @var Factory
+     */
+    private static $instance;
+
+    public function __construct()
+    {
+        parent::__construct();
+
+        $this->register(new ClosureComparator());
+        $this->register(new ProphecyComparator());
+    }
+
+    /**
+     * @return Factory
+     */
+    public static function getInstance()
+    {
+        if (self::$instance === null) {
+            self::$instance = new Factory;
+        }
+
+        return self::$instance;
+    }
+}
diff --git a/vendor/phpspec/prophecy/src/Prophecy/Comparator/ProphecyComparator.php b/vendor/phpspec/prophecy/src/Prophecy/Comparator/ProphecyComparator.php
new file mode 100644
index 0000000000000000000000000000000000000000..298a8e35683ffd3ee23595a759202d9e22bdeb21
--- /dev/null
+++ b/vendor/phpspec/prophecy/src/Prophecy/Comparator/ProphecyComparator.php
@@ -0,0 +1,28 @@
+<?php
+
+/*
+ * This file is part of the Prophecy.
+ * (c) Konstantin Kudryashov <ever.zet@gmail.com>
+ *     Marcello Duarte <marcello.duarte@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Prophecy\Comparator;
+
+use Prophecy\Prophecy\ProphecyInterface;
+use SebastianBergmann\Comparator\ObjectComparator;
+
+class ProphecyComparator extends ObjectComparator
+{
+    public function accepts($expected, $actual)
+    {
+        return is_object($expected) && is_object($actual) && $actual instanceof ProphecyInterface;
+    }
+
+    public function assertEquals($expected, $actual, $delta = 0.0, $canonicalize = false, $ignoreCase = false, array &$processed = array())
+    {
+        parent::assertEquals($expected, $actual->reveal(), $delta, $canonicalize, $ignoreCase, $processed);
+    }
+}
diff --git a/vendor/phpspec/prophecy/src/Prophecy/Doubler/CachedDoubler.php b/vendor/phpspec/prophecy/src/Prophecy/Doubler/CachedDoubler.php
new file mode 100644
index 0000000000000000000000000000000000000000..2b875211a310757191b45df6a8f0504befee945e
--- /dev/null
+++ b/vendor/phpspec/prophecy/src/Prophecy/Doubler/CachedDoubler.php
@@ -0,0 +1,66 @@
+<?php
+
+/*
+ * This file is part of the Prophecy.
+ * (c) Konstantin Kudryashov <ever.zet@gmail.com>
+ *     Marcello Duarte <marcello.duarte@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Prophecy\Doubler;
+
+use ReflectionClass;
+
+/**
+ * Cached class doubler.
+ * Prevents mirroring/creation of the same structure twice.
+ *
+ * @author Konstantin Kudryashov <ever.zet@gmail.com>
+ */
+class CachedDoubler extends Doubler
+{
+    private static $classes = array();
+
+    /**
+     * {@inheritdoc}
+     */
+    protected function createDoubleClass(ReflectionClass $class = null, array $interfaces)
+    {
+        $classId = $this->generateClassId($class, $interfaces);
+        if (isset(self::$classes[$classId])) {
+            return self::$classes[$classId];
+        }
+
+        return self::$classes[$classId] = parent::createDoubleClass($class, $interfaces);
+    }
+
+    /**
+     * @param ReflectionClass   $class
+     * @param ReflectionClass[] $interfaces
+     *
+     * @return string
+     */
+    private function generateClassId(ReflectionClass $class = null, array $interfaces)
+    {
+        $parts = array();
+        if (null !== $class) {
+            $parts[] = $class->getName();
+        }
+        foreach ($interfaces as $interface) {
+            $parts[] = $interface->getName();
+        }
+        foreach ($this->getClassPatches() as $patch) {
+            $parts[] = get_class($patch);
+        }
+        sort($parts);
+
+        return md5(implode('', $parts));
+    }
+
+    public function resetCache()
+    {
+        self::$classes = array();
+    }
+}
diff --git a/vendor/phpspec/prophecy/src/Prophecy/Doubler/ClassPatch/ClassPatchInterface.php b/vendor/phpspec/prophecy/src/Prophecy/Doubler/ClassPatch/ClassPatchInterface.php
new file mode 100644
index 0000000000000000000000000000000000000000..d6d196850c743a26aa849d8f8234995f5b2c1d7f
--- /dev/null
+++ b/vendor/phpspec/prophecy/src/Prophecy/Doubler/ClassPatch/ClassPatchInterface.php
@@ -0,0 +1,48 @@
+<?php
+
+/*
+ * This file is part of the Prophecy.
+ * (c) Konstantin Kudryashov <ever.zet@gmail.com>
+ *     Marcello Duarte <marcello.duarte@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Prophecy\Doubler\ClassPatch;
+
+use Prophecy\Doubler\Generator\Node\ClassNode;
+
+/**
+ * Class patch interface.
+ * Class patches extend doubles functionality or help
+ * Prophecy to avoid some internal PHP bugs.
+ *
+ * @author Konstantin Kudryashov <ever.zet@gmail.com>
+ */
+interface ClassPatchInterface
+{
+    /**
+     * Checks if patch supports specific class node.
+     *
+     * @param ClassNode $node
+     *
+     * @return bool
+     */
+    public function supports(ClassNode $node);
+
+    /**
+     * Applies patch to the specific class node.
+     *
+     * @param ClassNode $node
+     * @return void
+     */
+    public function apply(ClassNode $node);
+
+    /**
+     * Returns patch priority, which determines when patch will be applied.
+     *
+     * @return int Priority number (higher - earlier)
+     */
+    public function getPriority();
+}
diff --git a/vendor/phpspec/prophecy/src/Prophecy/Doubler/ClassPatch/DisableConstructorPatch.php b/vendor/phpspec/prophecy/src/Prophecy/Doubler/ClassPatch/DisableConstructorPatch.php
new file mode 100644
index 0000000000000000000000000000000000000000..9d843099d6e977a7791cdd05b6009d975796cd43
--- /dev/null
+++ b/vendor/phpspec/prophecy/src/Prophecy/Doubler/ClassPatch/DisableConstructorPatch.php
@@ -0,0 +1,76 @@
+<?php
+
+/*
+ * This file is part of the Prophecy.
+ * (c) Konstantin Kudryashov <ever.zet@gmail.com>
+ *     Marcello Duarte <marcello.duarte@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Prophecy\Doubler\ClassPatch;
+
+use Prophecy\Doubler\Generator\Node\ClassNode;
+use Prophecy\Doubler\Generator\Node\MethodNode;
+
+/**
+ * Disable constructor.
+ * Makes all constructor arguments optional.
+ *
+ * @author Konstantin Kudryashov <ever.zet@gmail.com>
+ */
+class DisableConstructorPatch implements ClassPatchInterface
+{
+    /**
+     * Checks if class has `__construct` method.
+     *
+     * @param ClassNode $node
+     *
+     * @return bool
+     */
+    public function supports(ClassNode $node)
+    {
+        return true;
+    }
+
+    /**
+     * Makes all class constructor arguments optional.
+     *
+     * @param ClassNode $node
+     */
+    public function apply(ClassNode $node)
+    {
+        if (!$node->isExtendable('__construct')) {
+            return;
+        }
+
+        if (!$node->hasMethod('__construct')) {
+            $node->addMethod(new MethodNode('__construct', ''));
+
+            return;
+        }
+
+        $constructor = $node->getMethod('__construct');
+        foreach ($constructor->getArguments() as $argument) {
+            $argument->setDefault(null);
+        }
+
+        $constructor->setCode(<<<PHP
+if (0 < func_num_args()) {
+    call_user_func_array(array('parent', '__construct'), func_get_args());
+}
+PHP
+        );
+    }
+
+    /**
+     * Returns patch priority, which determines when patch will be applied.
+     *
+     * @return int Priority number (higher - earlier)
+     */
+    public function getPriority()
+    {
+        return 100;
+    }
+}
diff --git a/vendor/phpspec/prophecy/src/Prophecy/Doubler/ClassPatch/HhvmExceptionPatch.php b/vendor/phpspec/prophecy/src/Prophecy/Doubler/ClassPatch/HhvmExceptionPatch.php
new file mode 100644
index 0000000000000000000000000000000000000000..fa38fc0d1c6d75fa9f5f31bbdd8fffec71b13b4e
--- /dev/null
+++ b/vendor/phpspec/prophecy/src/Prophecy/Doubler/ClassPatch/HhvmExceptionPatch.php
@@ -0,0 +1,63 @@
+<?php
+
+/*
+ * This file is part of the Prophecy.
+ * (c) Konstantin Kudryashov <ever.zet@gmail.com>
+ *     Marcello Duarte <marcello.duarte@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Prophecy\Doubler\ClassPatch;
+
+use Prophecy\Doubler\Generator\Node\ClassNode;
+
+/**
+ * Exception patch for HHVM to remove the stubs from special methods
+ *
+ * @author Christophe Coevoet <stof@notk.org>
+ */
+class HhvmExceptionPatch implements ClassPatchInterface
+{
+    /**
+     * Supports exceptions on HHVM.
+     *
+     * @param ClassNode $node
+     *
+     * @return bool
+     */
+    public function supports(ClassNode $node)
+    {
+        if (!defined('HHVM_VERSION')) {
+            return false;
+        }
+
+        return 'Exception' === $node->getParentClass() || is_subclass_of($node->getParentClass(), 'Exception');
+    }
+
+    /**
+     * Removes special exception static methods from the doubled methods.
+     *
+     * @param ClassNode $node
+     *
+     * @return void
+     */
+    public function apply(ClassNode $node)
+    {
+        if ($node->hasMethod('setTraceOptions')) {
+            $node->getMethod('setTraceOptions')->useParentCode();
+        }
+        if ($node->hasMethod('getTraceOptions')) {
+            $node->getMethod('getTraceOptions')->useParentCode();
+        }
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getPriority()
+    {
+        return -50;
+    }
+}
diff --git a/vendor/phpspec/prophecy/src/Prophecy/Doubler/ClassPatch/KeywordPatch.php b/vendor/phpspec/prophecy/src/Prophecy/Doubler/ClassPatch/KeywordPatch.php
new file mode 100644
index 0000000000000000000000000000000000000000..ab99f74be4717066d6bda70ea88842be60fa5194
--- /dev/null
+++ b/vendor/phpspec/prophecy/src/Prophecy/Doubler/ClassPatch/KeywordPatch.php
@@ -0,0 +1,68 @@
+<?php
+
+/*
+ * This file is part of the Prophecy.
+ * (c) Konstantin Kudryashov <ever.zet@gmail.com>
+ *     Marcello Duarte <marcello.duarte@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Prophecy\Doubler\ClassPatch;
+
+use Prophecy\Doubler\Generator\Node\ClassNode;
+
+/**
+ * Remove method functionality from the double which will clash with php keywords.
+ *
+ * @author Milan Magudia <milan@magudia.com>
+ */
+class KeywordPatch implements ClassPatchInterface
+{
+    /**
+     * Support any class
+     *
+     * @param ClassNode $node
+     *
+     * @return boolean
+     */
+    public function supports(ClassNode $node)
+    {
+        return true;
+    }
+
+    /**
+     * Remove methods that clash with php keywords
+     *
+     * @param ClassNode $node
+     */
+    public function apply(ClassNode $node)
+    {
+        $methodNames = array_keys($node->getMethods());
+        $methodsToRemove = array_intersect($methodNames, $this->getKeywords());
+        foreach ($methodsToRemove as $methodName) {
+            $node->removeMethod($methodName);
+        }
+    }
+
+    /**
+     * Returns patch priority, which determines when patch will be applied.
+     *
+     * @return int Priority number (higher - earlier)
+     */
+    public function getPriority()
+    {
+        return 49;
+    }
+
+    /**
+     * Returns array of php keywords.
+     *
+     * @return array
+     */
+    private function getKeywords()
+    {
+        return ['__halt_compiler'];
+    }
+}
diff --git a/vendor/phpspec/prophecy/src/Prophecy/Doubler/ClassPatch/MagicCallPatch.php b/vendor/phpspec/prophecy/src/Prophecy/Doubler/ClassPatch/MagicCallPatch.php
new file mode 100644
index 0000000000000000000000000000000000000000..a545eeff57a549654f281357f3015fb97f0e8777
--- /dev/null
+++ b/vendor/phpspec/prophecy/src/Prophecy/Doubler/ClassPatch/MagicCallPatch.php
@@ -0,0 +1,105 @@
+<?php
+
+/*
+ * This file is part of the Prophecy.
+ * (c) Konstantin Kudryashov <ever.zet@gmail.com>
+ *     Marcello Duarte <marcello.duarte@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Prophecy\Doubler\ClassPatch;
+
+use Prophecy\Doubler\Generator\Node\ArgumentNode;
+use Prophecy\Doubler\Generator\Node\ClassNode;
+use Prophecy\Doubler\Generator\Node\MethodNode;
+use Prophecy\PhpDocumentor\ClassAndInterfaceTagRetriever;
+use Prophecy\PhpDocumentor\MethodTagRetrieverInterface;
+
+/**
+ * Discover Magical API using "@method" PHPDoc format.
+ *
+ * @author Thomas Tourlourat <thomas@tourlourat.com>
+ * @author Kévin Dunglas <dunglas@gmail.com>
+ * @author Théo FIDRY <theo.fidry@gmail.com>
+ */
+class MagicCallPatch implements ClassPatchInterface
+{
+    const MAGIC_METHODS_WITH_ARGUMENTS = ['__call', '__callStatic', '__get', '__isset', '__set', '__set_state', '__unserialize', '__unset'];
+
+    private $tagRetriever;
+
+    public function __construct(MethodTagRetrieverInterface $tagRetriever = null)
+    {
+        $this->tagRetriever = null === $tagRetriever ? new ClassAndInterfaceTagRetriever() : $tagRetriever;
+    }
+
+    /**
+     * Support any class
+     *
+     * @param ClassNode $node
+     *
+     * @return boolean
+     */
+    public function supports(ClassNode $node)
+    {
+        return true;
+    }
+
+    /**
+     * Discover Magical API
+     *
+     * @param ClassNode $node
+     */
+    public function apply(ClassNode $node)
+    {
+        $types = array_filter($node->getInterfaces(), function ($interface) {
+            return 0 !== strpos($interface, 'Prophecy\\');
+        });
+        $types[] = $node->getParentClass();
+
+        foreach ($types as $type) {
+            $reflectionClass = new \ReflectionClass($type);
+
+            while ($reflectionClass) {
+                $tagList = $this->tagRetriever->getTagList($reflectionClass);
+
+                foreach ($tagList as $tag) {
+                    $methodName = $tag->getMethodName();
+
+                    if (empty($methodName)) {
+                        continue;
+                    }
+
+                    if (!$reflectionClass->hasMethod($methodName)) {
+                        $methodNode = new MethodNode($methodName);
+
+                        // only magic methods can have a contract that needs to be enforced
+                        if (in_array($methodName, self::MAGIC_METHODS_WITH_ARGUMENTS)) {
+                            foreach($tag->getArguments() as $argument) {
+                                $argumentNode = new ArgumentNode($argument['name']);
+                                $methodNode->addArgument($argumentNode);
+                            }
+                        }
+
+                        $methodNode->setStatic($tag->isStatic());
+                        $node->addMethod($methodNode);
+                    }
+                }
+
+                $reflectionClass = $reflectionClass->getParentClass();
+            }
+        }
+    }
+
+    /**
+     * Returns patch priority, which determines when patch will be applied.
+     *
+     * @return integer Priority number (higher - earlier)
+     */
+    public function getPriority()
+    {
+        return 50;
+    }
+}
diff --git a/vendor/phpspec/prophecy/src/Prophecy/Doubler/ClassPatch/ProphecySubjectPatch.php b/vendor/phpspec/prophecy/src/Prophecy/Doubler/ClassPatch/ProphecySubjectPatch.php
new file mode 100644
index 0000000000000000000000000000000000000000..0330ebc85b098fe39ccc2b88fb1d262e58624189
--- /dev/null
+++ b/vendor/phpspec/prophecy/src/Prophecy/Doubler/ClassPatch/ProphecySubjectPatch.php
@@ -0,0 +1,113 @@
+<?php
+
+/*
+ * This file is part of the Prophecy.
+ * (c) Konstantin Kudryashov <ever.zet@gmail.com>
+ *     Marcello Duarte <marcello.duarte@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Prophecy\Doubler\ClassPatch;
+
+use Prophecy\Doubler\Generator\Node\ArgumentTypeNode;
+use Prophecy\Doubler\Generator\Node\ClassNode;
+use Prophecy\Doubler\Generator\Node\MethodNode;
+use Prophecy\Doubler\Generator\Node\ArgumentNode;
+use Prophecy\Doubler\Generator\Node\ReturnTypeNode;
+
+/**
+ * Add Prophecy functionality to the double.
+ * This is a core class patch for Prophecy.
+ *
+ * @author Konstantin Kudryashov <ever.zet@gmail.com>
+ */
+class ProphecySubjectPatch implements ClassPatchInterface
+{
+    /**
+     * Always returns true.
+     *
+     * @param ClassNode $node
+     *
+     * @return bool
+     */
+    public function supports(ClassNode $node)
+    {
+        return true;
+    }
+
+    /**
+     * Apply Prophecy functionality to class node.
+     *
+     * @param ClassNode $node
+     */
+    public function apply(ClassNode $node)
+    {
+        $node->addInterface('Prophecy\Prophecy\ProphecySubjectInterface');
+        $node->addProperty('objectProphecyClosure', 'private');
+
+        foreach ($node->getMethods() as $name => $method) {
+            if ('__construct' === strtolower($name)) {
+                continue;
+            }
+
+            if ($method->getReturnTypeNode()->isVoid()) {
+                $method->setCode(
+                    '$this->getProphecy()->makeProphecyMethodCall(__FUNCTION__, func_get_args());'
+                );
+            } else {
+                $method->setCode(
+                    'return $this->getProphecy()->makeProphecyMethodCall(__FUNCTION__, func_get_args());'
+                );
+            }
+        }
+
+        $prophecySetter = new MethodNode('setProphecy');
+        $prophecyArgument = new ArgumentNode('prophecy');
+        $prophecyArgument->setTypeNode(new ArgumentTypeNode('Prophecy\Prophecy\ProphecyInterface'));
+        $prophecySetter->addArgument($prophecyArgument);
+        $prophecySetter->setCode(<<<PHP
+if (null === \$this->objectProphecyClosure) {
+    \$this->objectProphecyClosure = static function () use (\$prophecy) {
+        return \$prophecy;
+    };
+}
+PHP
+    );
+
+        $prophecyGetter = new MethodNode('getProphecy');
+        $prophecyGetter->setCode('return \call_user_func($this->objectProphecyClosure);');
+
+        if ($node->hasMethod('__call')) {
+            $__call = $node->getMethod('__call');
+        } else {
+            $__call = new MethodNode('__call');
+            $__call->addArgument(new ArgumentNode('name'));
+            $__call->addArgument(new ArgumentNode('arguments'));
+
+            $node->addMethod($__call, true);
+        }
+
+        $__call->setCode(<<<PHP
+throw new \Prophecy\Exception\Doubler\MethodNotFoundException(
+    sprintf('Method `%s::%s()` not found.', get_class(\$this), func_get_arg(0)),
+    get_class(\$this), func_get_arg(0)
+);
+PHP
+        );
+
+        $node->addMethod($prophecySetter, true);
+        $node->addMethod($prophecyGetter, true);
+    }
+
+    /**
+     * Returns patch priority, which determines when patch will be applied.
+     *
+     * @return int Priority number (higher - earlier)
+     */
+    public function getPriority()
+    {
+        return 0;
+    }
+}
diff --git a/vendor/phpspec/prophecy/src/Prophecy/Doubler/ClassPatch/ReflectionClassNewInstancePatch.php b/vendor/phpspec/prophecy/src/Prophecy/Doubler/ClassPatch/ReflectionClassNewInstancePatch.php
new file mode 100644
index 0000000000000000000000000000000000000000..9166aeefacf62ee4cbdd865ec2bfdab112a7cc32
--- /dev/null
+++ b/vendor/phpspec/prophecy/src/Prophecy/Doubler/ClassPatch/ReflectionClassNewInstancePatch.php
@@ -0,0 +1,57 @@
+<?php
+
+/*
+ * This file is part of the Prophecy.
+ * (c) Konstantin Kudryashov <ever.zet@gmail.com>
+ *     Marcello Duarte <marcello.duarte@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Prophecy\Doubler\ClassPatch;
+
+use Prophecy\Doubler\Generator\Node\ClassNode;
+
+/**
+ * ReflectionClass::newInstance patch.
+ * Makes first argument of newInstance optional, since it works but signature is misleading
+ *
+ * @author Florian Klein <florian.klein@free.fr>
+ */
+class ReflectionClassNewInstancePatch implements ClassPatchInterface
+{
+    /**
+     * Supports ReflectionClass
+     *
+     * @param ClassNode $node
+     *
+     * @return bool
+     */
+    public function supports(ClassNode $node)
+    {
+        return 'ReflectionClass' === $node->getParentClass();
+    }
+
+    /**
+     * Updates newInstance's first argument to make it optional
+     *
+     * @param ClassNode $node
+     */
+    public function apply(ClassNode $node)
+    {
+        foreach ($node->getMethod('newInstance')->getArguments() as $argument) {
+            $argument->setDefault(null);
+        }
+    }
+
+    /**
+     * Returns patch priority, which determines when patch will be applied.
+     *
+     * @return int Priority number (higher = earlier)
+     */
+    public function getPriority()
+    {
+        return 50;
+    }
+}
diff --git a/vendor/phpspec/prophecy/src/Prophecy/Doubler/ClassPatch/SplFileInfoPatch.php b/vendor/phpspec/prophecy/src/Prophecy/Doubler/ClassPatch/SplFileInfoPatch.php
new file mode 100644
index 0000000000000000000000000000000000000000..ceee94a2efde267c85c6e806a88c2de6aa695265
--- /dev/null
+++ b/vendor/phpspec/prophecy/src/Prophecy/Doubler/ClassPatch/SplFileInfoPatch.php
@@ -0,0 +1,123 @@
+<?php
+
+/*
+ * This file is part of the Prophecy.
+ * (c) Konstantin Kudryashov <ever.zet@gmail.com>
+ *     Marcello Duarte <marcello.duarte@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Prophecy\Doubler\ClassPatch;
+
+use Prophecy\Doubler\Generator\Node\ClassNode;
+use Prophecy\Doubler\Generator\Node\MethodNode;
+
+/**
+ * SplFileInfo patch.
+ * Makes SplFileInfo and derivative classes usable with Prophecy.
+ *
+ * @author Konstantin Kudryashov <ever.zet@gmail.com>
+ */
+class SplFileInfoPatch implements ClassPatchInterface
+{
+    /**
+     * Supports everything that extends SplFileInfo.
+     *
+     * @param ClassNode $node
+     *
+     * @return bool
+     */
+    public function supports(ClassNode $node)
+    {
+        if (null === $node->getParentClass()) {
+            return false;
+        }
+        return 'SplFileInfo' === $node->getParentClass()
+            || is_subclass_of($node->getParentClass(), 'SplFileInfo')
+        ;
+    }
+
+    /**
+     * Updated constructor code to call parent one with dummy file argument.
+     *
+     * @param ClassNode $node
+     */
+    public function apply(ClassNode $node)
+    {
+        if ($node->hasMethod('__construct')) {
+            $constructor = $node->getMethod('__construct');
+        } else {
+            $constructor = new MethodNode('__construct');
+            $node->addMethod($constructor);
+        }
+
+        if ($this->nodeIsDirectoryIterator($node)) {
+            $constructor->setCode('return parent::__construct("' . __DIR__ . '");');
+
+            return;
+        }
+
+        if ($this->nodeIsSplFileObject($node)) {
+            $filePath = str_replace('\\','\\\\',__FILE__);
+            $constructor->setCode('return parent::__construct("' . $filePath .'");');
+
+            return;
+        }
+
+        if ($this->nodeIsSymfonySplFileInfo($node)) {
+            $filePath = str_replace('\\','\\\\',__FILE__);
+            $constructor->setCode('return parent::__construct("' . $filePath .'", "", "");');
+
+            return;
+        }
+
+        $constructor->useParentCode();
+    }
+
+    /**
+     * Returns patch priority, which determines when patch will be applied.
+     *
+     * @return int Priority number (higher - earlier)
+     */
+    public function getPriority()
+    {
+        return 50;
+    }
+
+    /**
+     * @param ClassNode $node
+     * @return boolean
+     */
+    private function nodeIsDirectoryIterator(ClassNode $node)
+    {
+        $parent = $node->getParentClass();
+
+        return 'DirectoryIterator' === $parent
+            || is_subclass_of($parent, 'DirectoryIterator');
+    }
+
+    /**
+     * @param ClassNode $node
+     * @return boolean
+     */
+    private function nodeIsSplFileObject(ClassNode $node)
+    {
+        $parent = $node->getParentClass();
+
+        return 'SplFileObject' === $parent
+            || is_subclass_of($parent, 'SplFileObject');
+    }
+
+    /**
+     * @param ClassNode $node
+     * @return boolean
+     */
+    private function nodeIsSymfonySplFileInfo(ClassNode $node)
+    {
+        $parent = $node->getParentClass();
+
+        return 'Symfony\\Component\\Finder\\SplFileInfo' === $parent;
+    }
+}
diff --git a/vendor/phpspec/prophecy/src/Prophecy/Doubler/ClassPatch/ThrowablePatch.php b/vendor/phpspec/prophecy/src/Prophecy/Doubler/ClassPatch/ThrowablePatch.php
new file mode 100644
index 0000000000000000000000000000000000000000..b98e94327503b2f21e4730c485e81815c643e7a7
--- /dev/null
+++ b/vendor/phpspec/prophecy/src/Prophecy/Doubler/ClassPatch/ThrowablePatch.php
@@ -0,0 +1,95 @@
+<?php
+
+namespace Prophecy\Doubler\ClassPatch;
+
+use Prophecy\Doubler\Generator\Node\ClassNode;
+use Prophecy\Exception\Doubler\ClassCreatorException;
+
+class ThrowablePatch implements ClassPatchInterface
+{
+    /**
+     * Checks if patch supports specific class node.
+     *
+     * @param ClassNode $node
+     * @return bool
+     */
+    public function supports(ClassNode $node)
+    {
+        return $this->implementsAThrowableInterface($node) && $this->doesNotExtendAThrowableClass($node);
+    }
+
+    /**
+     * @param ClassNode $node
+     * @return bool
+     */
+    private function implementsAThrowableInterface(ClassNode $node)
+    {
+        foreach ($node->getInterfaces() as $type) {
+            if (is_a($type, 'Throwable', true)) {
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+    /**
+     * @param ClassNode $node
+     * @return bool
+     */
+    private function doesNotExtendAThrowableClass(ClassNode $node)
+    {
+        return !is_a($node->getParentClass(), 'Throwable', true);
+    }
+
+    /**
+     * Applies patch to the specific class node.
+     *
+     * @param ClassNode $node
+     *
+     * @return void
+     */
+    public function apply(ClassNode $node)
+    {
+        $this->checkItCanBeDoubled($node);
+        $this->setParentClassToException($node);
+    }
+
+    private function checkItCanBeDoubled(ClassNode $node)
+    {
+        $className = $node->getParentClass();
+        if ($className !== 'stdClass') {
+            throw new ClassCreatorException(
+                sprintf(
+                    'Cannot double concrete class %s as well as implement Traversable',
+                    $className
+                ),
+                $node
+            );
+        }
+    }
+
+    private function setParentClassToException(ClassNode $node)
+    {
+        $node->setParentClass('Exception');
+
+        $node->removeMethod('getMessage');
+        $node->removeMethod('getCode');
+        $node->removeMethod('getFile');
+        $node->removeMethod('getLine');
+        $node->removeMethod('getTrace');
+        $node->removeMethod('getPrevious');
+        $node->removeMethod('getNext');
+        $node->removeMethod('getTraceAsString');
+    }
+
+    /**
+     * Returns patch priority, which determines when patch will be applied.
+     *
+     * @return int Priority number (higher - earlier)
+     */
+    public function getPriority()
+    {
+        return 100;
+    }
+}
diff --git a/vendor/phpspec/prophecy/src/Prophecy/Doubler/ClassPatch/TraversablePatch.php b/vendor/phpspec/prophecy/src/Prophecy/Doubler/ClassPatch/TraversablePatch.php
new file mode 100644
index 0000000000000000000000000000000000000000..eea0202825a284d16da496ad807551d9ffedb474
--- /dev/null
+++ b/vendor/phpspec/prophecy/src/Prophecy/Doubler/ClassPatch/TraversablePatch.php
@@ -0,0 +1,83 @@
+<?php
+
+/*
+ * This file is part of the Prophecy.
+ * (c) Konstantin Kudryashov <ever.zet@gmail.com>
+ *     Marcello Duarte <marcello.duarte@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Prophecy\Doubler\ClassPatch;
+
+use Prophecy\Doubler\Generator\Node\ClassNode;
+use Prophecy\Doubler\Generator\Node\MethodNode;
+
+/**
+ * Traversable interface patch.
+ * Forces classes that implement interfaces, that extend Traversable to also implement Iterator.
+ *
+ * @author Konstantin Kudryashov <ever.zet@gmail.com>
+ */
+class TraversablePatch implements ClassPatchInterface
+{
+    /**
+     * Supports nodetree, that implement Traversable, but not Iterator or IteratorAggregate.
+     *
+     * @param ClassNode $node
+     *
+     * @return bool
+     */
+    public function supports(ClassNode $node)
+    {
+        if (in_array('Iterator', $node->getInterfaces())) {
+            return false;
+        }
+        if (in_array('IteratorAggregate', $node->getInterfaces())) {
+            return false;
+        }
+
+        foreach ($node->getInterfaces() as $interface) {
+            if ('Traversable' !== $interface && !is_subclass_of($interface, 'Traversable')) {
+                continue;
+            }
+            if ('Iterator' === $interface || is_subclass_of($interface, 'Iterator')) {
+                continue;
+            }
+            if ('IteratorAggregate' === $interface || is_subclass_of($interface, 'IteratorAggregate')) {
+                continue;
+            }
+
+            return true;
+        }
+
+        return false;
+    }
+
+    /**
+     * Forces class to implement Iterator interface.
+     *
+     * @param ClassNode $node
+     */
+    public function apply(ClassNode $node)
+    {
+        $node->addInterface('Iterator');
+
+        $node->addMethod(new MethodNode('current'));
+        $node->addMethod(new MethodNode('key'));
+        $node->addMethod(new MethodNode('next'));
+        $node->addMethod(new MethodNode('rewind'));
+        $node->addMethod(new MethodNode('valid'));
+    }
+
+    /**
+     * Returns patch priority, which determines when patch will be applied.
+     *
+     * @return int Priority number (higher - earlier)
+     */
+    public function getPriority()
+    {
+        return 100;
+    }
+}
diff --git a/vendor/phpspec/prophecy/src/Prophecy/Doubler/DoubleInterface.php b/vendor/phpspec/prophecy/src/Prophecy/Doubler/DoubleInterface.php
new file mode 100644
index 0000000000000000000000000000000000000000..699be3a2ad2cec607415d8f40cd95c6fbc8c68c1
--- /dev/null
+++ b/vendor/phpspec/prophecy/src/Prophecy/Doubler/DoubleInterface.php
@@ -0,0 +1,22 @@
+<?php
+
+/*
+ * This file is part of the Prophecy.
+ * (c) Konstantin Kudryashov <ever.zet@gmail.com>
+ *     Marcello Duarte <marcello.duarte@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Prophecy\Doubler;
+
+/**
+ * Core double interface.
+ * All doubled classes will implement this one.
+ *
+ * @author Konstantin Kudryashov <ever.zet@gmail.com>
+ */
+interface DoubleInterface
+{
+}
diff --git a/vendor/phpspec/prophecy/src/Prophecy/Doubler/Doubler.php b/vendor/phpspec/prophecy/src/Prophecy/Doubler/Doubler.php
new file mode 100644
index 0000000000000000000000000000000000000000..a378ae27906bd877eea68301850a915c1876afbb
--- /dev/null
+++ b/vendor/phpspec/prophecy/src/Prophecy/Doubler/Doubler.php
@@ -0,0 +1,146 @@
+<?php
+
+/*
+ * This file is part of the Prophecy.
+ * (c) Konstantin Kudryashov <ever.zet@gmail.com>
+ *     Marcello Duarte <marcello.duarte@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Prophecy\Doubler;
+
+use Doctrine\Instantiator\Instantiator;
+use Prophecy\Doubler\ClassPatch\ClassPatchInterface;
+use Prophecy\Doubler\Generator\ClassMirror;
+use Prophecy\Doubler\Generator\ClassCreator;
+use Prophecy\Exception\InvalidArgumentException;
+use ReflectionClass;
+
+/**
+ * Cached class doubler.
+ * Prevents mirroring/creation of the same structure twice.
+ *
+ * @author Konstantin Kudryashov <ever.zet@gmail.com>
+ */
+class Doubler
+{
+    private $mirror;
+    private $creator;
+    private $namer;
+
+    /**
+     * @var ClassPatchInterface[]
+     */
+    private $patches = array();
+
+    /**
+     * @var \Doctrine\Instantiator\Instantiator
+     */
+    private $instantiator;
+
+    /**
+     * Initializes doubler.
+     *
+     * @param ClassMirror   $mirror
+     * @param ClassCreator  $creator
+     * @param NameGenerator $namer
+     */
+    public function __construct(ClassMirror $mirror = null, ClassCreator $creator = null,
+                                NameGenerator $namer = null)
+    {
+        $this->mirror  = $mirror  ?: new ClassMirror;
+        $this->creator = $creator ?: new ClassCreator;
+        $this->namer   = $namer   ?: new NameGenerator;
+    }
+
+    /**
+     * Returns list of registered class patches.
+     *
+     * @return ClassPatchInterface[]
+     */
+    public function getClassPatches()
+    {
+        return $this->patches;
+    }
+
+    /**
+     * Registers new class patch.
+     *
+     * @param ClassPatchInterface $patch
+     */
+    public function registerClassPatch(ClassPatchInterface $patch)
+    {
+        $this->patches[] = $patch;
+
+        @usort($this->patches, function (ClassPatchInterface $patch1, ClassPatchInterface $patch2) {
+            return $patch2->getPriority() - $patch1->getPriority();
+        });
+    }
+
+    /**
+     * Creates double from specific class or/and list of interfaces.
+     *
+     * @param ReflectionClass   $class
+     * @param ReflectionClass[] $interfaces Array of ReflectionClass instances
+     * @param array             $args       Constructor arguments
+     *
+     * @return DoubleInterface
+     *
+     * @throws \Prophecy\Exception\InvalidArgumentException
+     */
+    public function double(ReflectionClass $class = null, array $interfaces, array $args = null)
+    {
+        foreach ($interfaces as $interface) {
+            if (!$interface instanceof ReflectionClass) {
+                throw new InvalidArgumentException(sprintf(
+                    "[ReflectionClass \$interface1 [, ReflectionClass \$interface2]] array expected as\n".
+                    "a second argument to `Doubler::double(...)`, but got %s.",
+                    is_object($interface) ? get_class($interface).' class' : gettype($interface)
+                ));
+            }
+        }
+
+        $classname  = $this->createDoubleClass($class, $interfaces);
+        $reflection = new ReflectionClass($classname);
+
+        if (null !== $args) {
+            return $reflection->newInstanceArgs($args);
+        }
+        if ((null === $constructor = $reflection->getConstructor())
+            || ($constructor->isPublic() && !$constructor->isFinal())) {
+            return $reflection->newInstance();
+        }
+
+        if (!$this->instantiator) {
+            $this->instantiator = new Instantiator();
+        }
+
+        return $this->instantiator->instantiate($classname);
+    }
+
+    /**
+     * Creates double class and returns its FQN.
+     *
+     * @param ReflectionClass   $class
+     * @param ReflectionClass[] $interfaces
+     *
+     * @return string
+     */
+    protected function createDoubleClass(ReflectionClass $class = null, array $interfaces)
+    {
+        $name = $this->namer->name($class, $interfaces);
+        $node = $this->mirror->reflect($class, $interfaces);
+
+        foreach ($this->patches as $patch) {
+            if ($patch->supports($node)) {
+                $patch->apply($node);
+            }
+        }
+
+        $this->creator->create($name, $node);
+
+        return $name;
+    }
+}
diff --git a/vendor/phpspec/prophecy/src/Prophecy/Doubler/Generator/ClassCodeGenerator.php b/vendor/phpspec/prophecy/src/Prophecy/Doubler/Generator/ClassCodeGenerator.php
new file mode 100644
index 0000000000000000000000000000000000000000..52e5e0455e6e0903e5abeae945eb4ae4198e4a77
--- /dev/null
+++ b/vendor/phpspec/prophecy/src/Prophecy/Doubler/Generator/ClassCodeGenerator.php
@@ -0,0 +1,110 @@
+<?php
+
+/*
+ * This file is part of the Prophecy.
+ * (c) Konstantin Kudryashov <ever.zet@gmail.com>
+ *     Marcello Duarte <marcello.duarte@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Prophecy\Doubler\Generator;
+
+use Prophecy\Doubler\Generator\Node\ReturnTypeNode;
+use Prophecy\Doubler\Generator\Node\TypeNodeAbstract;
+
+/**
+ * Class code creator.
+ * Generates PHP code for specific class node tree.
+ *
+ * @author Konstantin Kudryashov <ever.zet@gmail.com>
+ */
+class ClassCodeGenerator
+{
+    public function __construct(TypeHintReference $typeHintReference = null)
+    {
+    }
+
+    /**
+     * Generates PHP code for class node.
+     *
+     * @param string         $classname
+     * @param Node\ClassNode $class
+     *
+     * @return string
+     */
+    public function generate($classname, Node\ClassNode $class)
+    {
+        $parts     = explode('\\', $classname);
+        $classname = array_pop($parts);
+        $namespace = implode('\\', $parts);
+
+        $code = sprintf("class %s extends \%s implements %s {\n",
+            $classname, $class->getParentClass(), implode(', ',
+                array_map(function ($interface) {return '\\'.$interface;}, $class->getInterfaces())
+            )
+        );
+
+        foreach ($class->getProperties() as $name => $visibility) {
+            $code .= sprintf("%s \$%s;\n", $visibility, $name);
+        }
+        $code .= "\n";
+
+        foreach ($class->getMethods() as $method) {
+            $code .= $this->generateMethod($method)."\n";
+        }
+        $code .= "\n}";
+
+        return sprintf("namespace %s {\n%s\n}", $namespace, $code);
+    }
+
+    private function generateMethod(Node\MethodNode $method)
+    {
+        $php = sprintf("%s %s function %s%s(%s)%s {\n",
+            $method->getVisibility(),
+            $method->isStatic() ? 'static' : '',
+            $method->returnsReference() ? '&':'',
+            $method->getName(),
+            implode(', ', $this->generateArguments($method->getArguments())),
+            ($ret = $this->generateTypes($method->getReturnTypeNode())) ? ': '.$ret : ''
+        );
+        $php .= $method->getCode()."\n";
+
+        return $php.'}';
+    }
+
+    private function generateTypes(TypeNodeAbstract $typeNode): string
+    {
+        if (!$typeNode->getTypes()) {
+            return '';
+        }
+
+        // When we require PHP 8 we can stop generating ?foo nullables and remove this first block
+        if ($typeNode->canUseNullShorthand()) {
+            return sprintf( '?%s', $typeNode->getNonNullTypes()[0]);
+        } else {
+            return join('|', $typeNode->getTypes());
+        }
+    }
+
+    private function generateArguments(array $arguments)
+    {
+        return array_map(function (Node\ArgumentNode $argument){
+
+            $php = $this->generateTypes($argument->getTypeNode());
+
+            $php .= ' '.($argument->isPassedByReference() ? '&' : '');
+
+            $php .= $argument->isVariadic() ? '...' : '';
+
+            $php .= '$'.$argument->getName();
+
+            if ($argument->isOptional() && !$argument->isVariadic()) {
+                $php .= ' = '.var_export($argument->getDefault(), true);
+            }
+
+            return $php;
+        }, $arguments);
+    }
+}
diff --git a/vendor/phpspec/prophecy/src/Prophecy/Doubler/Generator/ClassCreator.php b/vendor/phpspec/prophecy/src/Prophecy/Doubler/Generator/ClassCreator.php
new file mode 100644
index 0000000000000000000000000000000000000000..882a4a4b7f14eb05c1f9c6acc0c3d1076e923c52
--- /dev/null
+++ b/vendor/phpspec/prophecy/src/Prophecy/Doubler/Generator/ClassCreator.php
@@ -0,0 +1,67 @@
+<?php
+
+/*
+ * This file is part of the Prophecy.
+ * (c) Konstantin Kudryashov <ever.zet@gmail.com>
+ *     Marcello Duarte <marcello.duarte@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Prophecy\Doubler\Generator;
+
+use Prophecy\Exception\Doubler\ClassCreatorException;
+
+/**
+ * Class creator.
+ * Creates specific class in current environment.
+ *
+ * @author Konstantin Kudryashov <ever.zet@gmail.com>
+ */
+class ClassCreator
+{
+    private $generator;
+
+    /**
+     * Initializes creator.
+     *
+     * @param ClassCodeGenerator $generator
+     */
+    public function __construct(ClassCodeGenerator $generator = null)
+    {
+        $this->generator = $generator ?: new ClassCodeGenerator;
+    }
+
+    /**
+     * Creates class.
+     *
+     * @param string         $classname
+     * @param Node\ClassNode $class
+     *
+     * @return mixed
+     *
+     * @throws \Prophecy\Exception\Doubler\ClassCreatorException
+     */
+    public function create($classname, Node\ClassNode $class)
+    {
+        $code = $this->generator->generate($classname, $class);
+        $return = eval($code);
+
+        if (!class_exists($classname, false)) {
+            if (count($class->getInterfaces())) {
+                throw new ClassCreatorException(sprintf(
+                    'Could not double `%s` and implement interfaces: [%s].',
+                    $class->getParentClass(), implode(', ', $class->getInterfaces())
+                ), $class);
+            }
+
+            throw new ClassCreatorException(
+                sprintf('Could not double `%s`.', $class->getParentClass()),
+                $class
+            );
+        }
+
+        return $return;
+    }
+}
diff --git a/vendor/phpspec/prophecy/src/Prophecy/Doubler/Generator/ClassMirror.php b/vendor/phpspec/prophecy/src/Prophecy/Doubler/Generator/ClassMirror.php
new file mode 100644
index 0000000000000000000000000000000000000000..6b21623b4bd6b86a357d58da1d0063d183a5f05c
--- /dev/null
+++ b/vendor/phpspec/prophecy/src/Prophecy/Doubler/Generator/ClassMirror.php
@@ -0,0 +1,243 @@
+<?php
+
+/*
+ * This file is part of the Prophecy.
+ * (c) Konstantin Kudryashov <ever.zet@gmail.com>
+ *     Marcello Duarte <marcello.duarte@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Prophecy\Doubler\Generator;
+
+use Prophecy\Doubler\Generator\Node\ArgumentTypeNode;
+use Prophecy\Doubler\Generator\Node\ReturnTypeNode;
+use Prophecy\Exception\InvalidArgumentException;
+use Prophecy\Exception\Doubler\ClassMirrorException;
+use ReflectionClass;
+use ReflectionMethod;
+use ReflectionNamedType;
+use ReflectionParameter;
+use ReflectionType;
+use ReflectionUnionType;
+
+/**
+ * Class mirror.
+ * Core doubler class. Mirrors specific class and/or interfaces into class node tree.
+ *
+ * @author Konstantin Kudryashov <ever.zet@gmail.com>
+ */
+class ClassMirror
+{
+    private static $reflectableMethods = array(
+        '__construct',
+        '__destruct',
+        '__sleep',
+        '__wakeup',
+        '__toString',
+        '__call',
+        '__invoke'
+    );
+
+    /**
+     * Reflects provided arguments into class node.
+     *
+     * @param ReflectionClass|null $class
+     * @param ReflectionClass[] $interfaces
+     *
+     * @return Node\ClassNode
+     *
+     */
+    public function reflect(?ReflectionClass $class, array $interfaces)
+    {
+        $node = new Node\ClassNode;
+
+        if (null !== $class) {
+            if (true === $class->isInterface()) {
+                throw new InvalidArgumentException(sprintf(
+                    "Could not reflect %s as a class, because it\n".
+                    "is interface - use the second argument instead.",
+                    $class->getName()
+                ));
+            }
+
+            $this->reflectClassToNode($class, $node);
+        }
+
+        foreach ($interfaces as $interface) {
+            if (!$interface instanceof ReflectionClass) {
+                throw new InvalidArgumentException(sprintf(
+                    "[ReflectionClass \$interface1 [, ReflectionClass \$interface2]] array expected as\n".
+                    "a second argument to `ClassMirror::reflect(...)`, but got %s.",
+                    is_object($interface) ? get_class($interface).' class' : gettype($interface)
+                ));
+            }
+            if (false === $interface->isInterface()) {
+                throw new InvalidArgumentException(sprintf(
+                    "Could not reflect %s as an interface, because it\n".
+                    "is class - use the first argument instead.",
+                    $interface->getName()
+                ));
+            }
+
+            $this->reflectInterfaceToNode($interface, $node);
+        }
+
+        $node->addInterface('Prophecy\Doubler\Generator\ReflectionInterface');
+
+        return $node;
+    }
+
+    private function reflectClassToNode(ReflectionClass $class, Node\ClassNode $node)
+    {
+        if (true === $class->isFinal()) {
+            throw new ClassMirrorException(sprintf(
+                'Could not reflect class %s as it is marked final.', $class->getName()
+            ), $class);
+        }
+
+        $node->setParentClass($class->getName());
+
+        foreach ($class->getMethods(ReflectionMethod::IS_ABSTRACT) as $method) {
+            if (false === $method->isProtected()) {
+                continue;
+            }
+
+            $this->reflectMethodToNode($method, $node);
+        }
+
+        foreach ($class->getMethods(ReflectionMethod::IS_PUBLIC) as $method) {
+            if (0 === strpos($method->getName(), '_')
+                && !in_array($method->getName(), self::$reflectableMethods)) {
+                continue;
+            }
+
+            if (true === $method->isFinal()) {
+                $node->addUnextendableMethod($method->getName());
+                continue;
+            }
+
+            $this->reflectMethodToNode($method, $node);
+        }
+    }
+
+    private function reflectInterfaceToNode(ReflectionClass $interface, Node\ClassNode $node)
+    {
+        $node->addInterface($interface->getName());
+
+        foreach ($interface->getMethods() as $method) {
+            $this->reflectMethodToNode($method, $node);
+        }
+    }
+
+    private function reflectMethodToNode(ReflectionMethod $method, Node\ClassNode $classNode)
+    {
+        $node = new Node\MethodNode($method->getName());
+
+        if (true === $method->isProtected()) {
+            $node->setVisibility('protected');
+        }
+
+        if (true === $method->isStatic()) {
+            $node->setStatic();
+        }
+
+        if (true === $method->returnsReference()) {
+            $node->setReturnsReference();
+        }
+
+        if ($method->hasReturnType()) {
+            $returnTypes = $this->getTypeHints($method->getReturnType(), $method->getDeclaringClass(), $method->getReturnType()->allowsNull());
+            $node->setReturnTypeNode(new ReturnTypeNode(...$returnTypes));
+        }
+
+        if (is_array($params = $method->getParameters()) && count($params)) {
+            foreach ($params as $param) {
+                $this->reflectArgumentToNode($param, $node);
+            }
+        }
+
+        $classNode->addMethod($node);
+    }
+
+    private function reflectArgumentToNode(ReflectionParameter $parameter, Node\MethodNode $methodNode)
+    {
+        $name = $parameter->getName() == '...' ? '__dot_dot_dot__' : $parameter->getName();
+        $node = new Node\ArgumentNode($name);
+
+        $typeHints = $this->getTypeHints($parameter->getType(), $parameter->getDeclaringClass(), $parameter->allowsNull());
+
+        $node->setTypeNode(new ArgumentTypeNode(...$typeHints));
+
+        if ($parameter->isVariadic()) {
+            $node->setAsVariadic();
+        }
+
+        if ($this->hasDefaultValue($parameter)) {
+            $node->setDefault($this->getDefaultValue($parameter));
+        }
+
+        if ($parameter->isPassedByReference()) {
+            $node->setAsPassedByReference();
+        }
+
+
+        $methodNode->addArgument($node);
+    }
+
+    private function hasDefaultValue(ReflectionParameter $parameter)
+    {
+        if ($parameter->isVariadic()) {
+            return false;
+        }
+
+        if ($parameter->isDefaultValueAvailable()) {
+            return true;
+        }
+
+        return $parameter->isOptional() || ($parameter->allowsNull() && $parameter->getType());
+    }
+
+    private function getDefaultValue(ReflectionParameter $parameter)
+    {
+        if (!$parameter->isDefaultValueAvailable()) {
+            return null;
+        }
+
+        return $parameter->getDefaultValue();
+    }
+
+    private function getTypeHints(?ReflectionType $type, ?ReflectionClass $class, bool $allowsNull) : array
+    {
+        $types = [];
+
+        if ($type instanceof ReflectionNamedType) {
+            $types = [$type->getName()];
+
+        }
+        elseif ($type instanceof ReflectionUnionType) {
+            $types = $type->getTypes();
+        }
+
+        $types = array_map(
+            function(string $type) use ($class) {
+                if ($type === 'self') {
+                    return $class->getName();
+                }
+                if ($type === 'parent') {
+                    return $class->getParentClass()->getName();
+                }
+
+                return $type;
+            },
+            $types
+        );
+
+        if ($types && $types != ['mixed'] && $allowsNull) {
+            $types[] = 'null';
+        }
+
+        return $types;
+    }
+}
diff --git a/vendor/phpspec/prophecy/src/Prophecy/Doubler/Generator/Node/ArgumentNode.php b/vendor/phpspec/prophecy/src/Prophecy/Doubler/Generator/Node/ArgumentNode.php
new file mode 100644
index 0000000000000000000000000000000000000000..da7fed4e1a813d6de7f054c884fa8ed1dc812fa3
--- /dev/null
+++ b/vendor/phpspec/prophecy/src/Prophecy/Doubler/Generator/Node/ArgumentNode.php
@@ -0,0 +1,133 @@
+<?php
+
+/*
+ * This file is part of the Prophecy.
+ * (c) Konstantin Kudryashov <ever.zet@gmail.com>
+ *     Marcello Duarte <marcello.duarte@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Prophecy\Doubler\Generator\Node;
+
+/**
+ * Argument node.
+ *
+ * @author Konstantin Kudryashov <ever.zet@gmail.com>
+ */
+class ArgumentNode
+{
+    private $name;
+    private $default;
+    private $optional    = false;
+    private $byReference = false;
+    private $isVariadic  = false;
+
+    /** @var ArgumentTypeNode */
+    private $typeNode;
+
+    /**
+     * @param string $name
+     */
+    public function __construct($name)
+    {
+        $this->name = $name;
+        $this->typeNode = new ArgumentTypeNode();
+    }
+
+    public function getName()
+    {
+        return $this->name;
+    }
+
+    public function setTypeNode(ArgumentTypeNode $typeNode)
+    {
+        $this->typeNode = $typeNode;
+    }
+
+    public function getTypeNode() : ArgumentTypeNode
+    {
+        return $this->typeNode;
+    }
+
+    public function hasDefault()
+    {
+        return $this->isOptional() && !$this->isVariadic();
+    }
+
+    public function getDefault()
+    {
+        return $this->default;
+    }
+
+    public function setDefault($default = null)
+    {
+        $this->optional = true;
+        $this->default  = $default;
+    }
+
+    public function isOptional()
+    {
+        return $this->optional;
+    }
+
+    public function setAsPassedByReference($byReference = true)
+    {
+        $this->byReference = $byReference;
+    }
+
+    public function isPassedByReference()
+    {
+        return $this->byReference;
+    }
+
+    public function setAsVariadic($isVariadic = true)
+    {
+        $this->isVariadic = $isVariadic;
+    }
+
+    public function isVariadic()
+    {
+        return $this->isVariadic;
+    }
+
+    /**
+     * @deprecated use getArgumentTypeNode instead
+     * @return string|null
+     */
+    public function getTypeHint()
+    {
+        $type = $this->typeNode->getNonNullTypes() ? $this->typeNode->getNonNullTypes()[0] : null;
+
+        return $type ? ltrim($type, '\\') : null;
+    }
+
+    /**
+     * @deprecated use setArgumentTypeNode instead
+     * @param string|null $typeHint
+     */
+    public function setTypeHint($typeHint = null)
+    {
+        $this->typeNode = ($typeHint === null) ? new ArgumentTypeNode() : new ArgumentTypeNode($typeHint);
+    }
+
+    /**
+     * @deprecated use getArgumentTypeNode instead
+     * @return bool
+     */
+    public function isNullable()
+    {
+        return $this->typeNode->canUseNullShorthand();
+    }
+
+    /**
+     * @deprecated use getArgumentTypeNode instead
+     * @param bool $isNullable
+     */
+    public function setAsNullable($isNullable = true)
+    {
+        $nonNullTypes = $this->typeNode->getNonNullTypes();
+        $this->typeNode = $isNullable ? new ArgumentTypeNode('null', ...$nonNullTypes) : new ArgumentTypeNode(...$nonNullTypes);
+    }
+}
diff --git a/vendor/phpspec/prophecy/src/Prophecy/Doubler/Generator/Node/ArgumentTypeNode.php b/vendor/phpspec/prophecy/src/Prophecy/Doubler/Generator/Node/ArgumentTypeNode.php
new file mode 100644
index 0000000000000000000000000000000000000000..0a18b91e10f8571f22fbab0ff0d7ec922540e06a
--- /dev/null
+++ b/vendor/phpspec/prophecy/src/Prophecy/Doubler/Generator/Node/ArgumentTypeNode.php
@@ -0,0 +1,10 @@
+<?php
+
+namespace Prophecy\Doubler\Generator\Node;
+
+use Prophecy\Exception\Doubler\DoubleException;
+
+class ArgumentTypeNode extends TypeNodeAbstract
+{
+
+}
diff --git a/vendor/phpspec/prophecy/src/Prophecy/Doubler/Generator/Node/ClassNode.php b/vendor/phpspec/prophecy/src/Prophecy/Doubler/Generator/Node/ClassNode.php
new file mode 100644
index 0000000000000000000000000000000000000000..f7bd2857a420e03b6039880722ef25952206cb1f
--- /dev/null
+++ b/vendor/phpspec/prophecy/src/Prophecy/Doubler/Generator/Node/ClassNode.php
@@ -0,0 +1,169 @@
+<?php
+
+/*
+ * This file is part of the Prophecy.
+ * (c) Konstantin Kudryashov <ever.zet@gmail.com>
+ *     Marcello Duarte <marcello.duarte@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Prophecy\Doubler\Generator\Node;
+
+use Prophecy\Exception\Doubler\MethodNotExtendableException;
+use Prophecy\Exception\InvalidArgumentException;
+
+/**
+ * Class node.
+ *
+ * @author Konstantin Kudryashov <ever.zet@gmail.com>
+ */
+class ClassNode
+{
+    private $parentClass = 'stdClass';
+    private $interfaces  = array();
+    private $properties  = array();
+    private $unextendableMethods = array();
+
+    /**
+     * @var MethodNode[]
+     */
+    private $methods     = array();
+
+    public function getParentClass()
+    {
+        return $this->parentClass;
+    }
+
+    /**
+     * @param string $class
+     */
+    public function setParentClass($class)
+    {
+        $this->parentClass = $class ?: 'stdClass';
+    }
+
+    /**
+     * @return string[]
+     */
+    public function getInterfaces()
+    {
+        return $this->interfaces;
+    }
+
+    /**
+     * @param string $interface
+     */
+    public function addInterface($interface)
+    {
+        if ($this->hasInterface($interface)) {
+            return;
+        }
+
+        array_unshift($this->interfaces, $interface);
+    }
+
+    /**
+     * @param string $interface
+     *
+     * @return bool
+     */
+    public function hasInterface($interface)
+    {
+        return in_array($interface, $this->interfaces);
+    }
+
+    public function getProperties()
+    {
+        return $this->properties;
+    }
+
+    public function addProperty($name, $visibility = 'public')
+    {
+        $visibility = strtolower($visibility);
+
+        if (!in_array($visibility, array('public', 'private', 'protected'))) {
+            throw new InvalidArgumentException(sprintf(
+                '`%s` property visibility is not supported.', $visibility
+            ));
+        }
+
+        $this->properties[$name] = $visibility;
+    }
+
+    /**
+     * @return MethodNode[]
+     */
+    public function getMethods()
+    {
+        return $this->methods;
+    }
+
+    public function addMethod(MethodNode $method, $force = false)
+    {
+        if (!$this->isExtendable($method->getName())){
+            $message = sprintf(
+                'Method `%s` is not extendable, so can not be added.', $method->getName()
+            );
+            throw new MethodNotExtendableException($message, $this->getParentClass(), $method->getName());
+        }
+
+        if ($force || !isset($this->methods[$method->getName()])) {
+            $this->methods[$method->getName()] = $method;
+        }
+    }
+
+    public function removeMethod($name)
+    {
+        unset($this->methods[$name]);
+    }
+
+    /**
+     * @param string $name
+     *
+     * @return MethodNode|null
+     */
+    public function getMethod($name)
+    {
+        return $this->hasMethod($name) ? $this->methods[$name] : null;
+    }
+
+    /**
+     * @param string $name
+     *
+     * @return bool
+     */
+    public function hasMethod($name)
+    {
+        return isset($this->methods[$name]);
+    }
+
+    /**
+     * @return string[]
+     */
+    public function getUnextendableMethods()
+    {
+        return $this->unextendableMethods;
+    }
+
+    /**
+     * @param string $unextendableMethod
+     */
+    public function addUnextendableMethod($unextendableMethod)
+    {
+        if (!$this->isExtendable($unextendableMethod)){
+            return;
+        }
+        $this->unextendableMethods[] = $unextendableMethod;
+    }
+
+    /**
+     * @param string $method
+     * @return bool
+     */
+    public function isExtendable($method)
+    {
+        return !in_array($method, $this->unextendableMethods);
+    }
+}
diff --git a/vendor/phpspec/prophecy/src/Prophecy/Doubler/Generator/Node/MethodNode.php b/vendor/phpspec/prophecy/src/Prophecy/Doubler/Generator/Node/MethodNode.php
new file mode 100644
index 0000000000000000000000000000000000000000..ece652f9ff5491434b9e704caf775f8cd168d115
--- /dev/null
+++ b/vendor/phpspec/prophecy/src/Prophecy/Doubler/Generator/Node/MethodNode.php
@@ -0,0 +1,210 @@
+<?php
+
+/*
+ * This file is part of the Prophecy.
+ * (c) Konstantin Kudryashov <ever.zet@gmail.com>
+ *     Marcello Duarte <marcello.duarte@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Prophecy\Doubler\Generator\Node;
+
+use Prophecy\Doubler\Generator\TypeHintReference;
+use Prophecy\Exception\InvalidArgumentException;
+
+/**
+ * Method node.
+ *
+ * @author Konstantin Kudryashov <ever.zet@gmail.com>
+ */
+class MethodNode
+{
+    private $name;
+    private $code;
+    private $visibility = 'public';
+    private $static = false;
+    private $returnsReference = false;
+
+    /** @var ReturnTypeNode */
+    private $returnTypeNode;
+
+    /**
+     * @var ArgumentNode[]
+     */
+    private $arguments = array();
+
+    /**
+     * @param string $name
+     * @param string $code
+     */
+    public function __construct($name, $code = null, TypeHintReference $typeHintReference = null)
+    {
+        $this->name = $name;
+        $this->code = $code;
+        $this->returnTypeNode = new ReturnTypeNode();
+    }
+
+    public function getVisibility()
+    {
+        return $this->visibility;
+    }
+
+    /**
+     * @param string $visibility
+     */
+    public function setVisibility($visibility)
+    {
+        $visibility = strtolower($visibility);
+
+        if (!in_array($visibility, array('public', 'private', 'protected'))) {
+            throw new InvalidArgumentException(sprintf(
+                '`%s` method visibility is not supported.', $visibility
+            ));
+        }
+
+        $this->visibility = $visibility;
+    }
+
+    public function isStatic()
+    {
+        return $this->static;
+    }
+
+    public function setStatic($static = true)
+    {
+        $this->static = (bool) $static;
+    }
+
+    public function returnsReference()
+    {
+        return $this->returnsReference;
+    }
+
+    public function setReturnsReference()
+    {
+        $this->returnsReference = true;
+    }
+
+    public function getName()
+    {
+        return $this->name;
+    }
+
+    public function addArgument(ArgumentNode $argument)
+    {
+        $this->arguments[] = $argument;
+    }
+
+    /**
+     * @return ArgumentNode[]
+     */
+    public function getArguments()
+    {
+        return $this->arguments;
+    }
+
+    /**
+     * @deprecated use getReturnTypeNode instead
+     * @return bool
+     */
+    public function hasReturnType()
+    {
+        return (bool) $this->returnTypeNode->getNonNullTypes();
+    }
+
+    public function setReturnTypeNode(ReturnTypeNode $returnTypeNode): void
+    {
+        $this->returnTypeNode = $returnTypeNode;
+    }
+
+    /**
+     * @deprecated use setReturnTypeNode instead
+     * @param string $type
+     */
+    public function setReturnType($type = null)
+    {
+        $this->returnTypeNode = ($type === '' || $type === null) ? new ReturnTypeNode() : new ReturnTypeNode($type);
+    }
+
+    /**
+     * @deprecated use setReturnTypeNode instead
+     * @param bool $bool
+     */
+    public function setNullableReturnType($bool = true)
+    {
+        if ($bool) {
+            $this->returnTypeNode = new ReturnTypeNode('null', ...$this->returnTypeNode->getTypes());
+        }
+        else {
+            $this->returnTypeNode = new ReturnTypeNode(...$this->returnTypeNode->getNonNullTypes());
+        }
+    }
+
+    /**
+     * @deprecated use getReturnTypeNode instead
+     * @return string|null
+     */
+    public function getReturnType()
+    {
+        if ($types = $this->returnTypeNode->getNonNullTypes())
+        {
+            return $types[0];
+        }
+
+        return null;
+    }
+
+    public function getReturnTypeNode() : ReturnTypeNode
+    {
+        return $this->returnTypeNode;
+    }
+
+    /**
+     * @deprecated use getReturnTypeNode instead
+     * @return bool
+     */
+    public function hasNullableReturnType()
+    {
+        return $this->returnTypeNode->canUseNullShorthand();
+    }
+
+    /**
+     * @param string $code
+     */
+    public function setCode($code)
+    {
+        $this->code = $code;
+    }
+
+    public function getCode()
+    {
+        if ($this->returnsReference)
+        {
+            return "throw new \Prophecy\Exception\Doubler\ReturnByReferenceException('Returning by reference not supported', get_class(\$this), '{$this->name}');";
+        }
+
+        return (string) $this->code;
+    }
+
+    public function useParentCode()
+    {
+        $this->code = sprintf(
+            'return parent::%s(%s);', $this->getName(), implode(', ',
+                array_map(array($this, 'generateArgument'), $this->arguments)
+            )
+        );
+    }
+
+    private function generateArgument(ArgumentNode $arg)
+    {
+        $argument = '$'.$arg->getName();
+
+        if ($arg->isVariadic()) {
+            $argument = '...'.$argument;
+        }
+
+        return $argument;
+    }
+}
diff --git a/vendor/phpspec/prophecy/src/Prophecy/Doubler/Generator/Node/ReturnTypeNode.php b/vendor/phpspec/prophecy/src/Prophecy/Doubler/Generator/Node/ReturnTypeNode.php
new file mode 100644
index 0000000000000000000000000000000000000000..f688537581dc1af3f12ad30339eb0d064e008617
--- /dev/null
+++ b/vendor/phpspec/prophecy/src/Prophecy/Doubler/Generator/Node/ReturnTypeNode.php
@@ -0,0 +1,31 @@
+<?php
+
+namespace Prophecy\Doubler\Generator\Node;
+
+use Prophecy\Exception\Doubler\DoubleException;
+
+final class ReturnTypeNode extends TypeNodeAbstract
+{
+    protected function getRealType(string $type): string
+    {
+        if ($type == 'void') {
+            return $type;
+        }
+
+        return parent::getRealType($type);
+    }
+
+    protected function guardIsValidType()
+    {
+        if (isset($this->types['void']) && count($this->types) !== 1) {
+            throw new DoubleException('void cannot be part of a union');
+        }
+
+        parent::guardIsValidType();
+    }
+
+    public function isVoid(): bool
+    {
+        return $this->types == ['void' => 'void'];
+    }
+}
diff --git a/vendor/phpspec/prophecy/src/Prophecy/Doubler/Generator/Node/TypeNodeAbstract.php b/vendor/phpspec/prophecy/src/Prophecy/Doubler/Generator/Node/TypeNodeAbstract.php
new file mode 100644
index 0000000000000000000000000000000000000000..e6b10dd6253f16f3daabdda0671790f5a4bc9bf1
--- /dev/null
+++ b/vendor/phpspec/prophecy/src/Prophecy/Doubler/Generator/Node/TypeNodeAbstract.php
@@ -0,0 +1,96 @@
+<?php
+
+namespace Prophecy\Doubler\Generator\Node;
+
+use Prophecy\Exception\Doubler\DoubleException;
+
+abstract class TypeNodeAbstract
+{
+    /** @var string[] */
+    protected $types = [];
+
+    public function __construct(string ...$types)
+    {
+        foreach ($types as $type) {
+            $type = $this->getRealType($type);
+            $this->types[$type] = $type;
+        }
+
+        $this->guardIsValidType();
+    }
+
+    public function canUseNullShorthand(): bool
+    {
+        return isset($this->types['null']) && count($this->types) <= 2;
+    }
+
+    public function getTypes(): array
+    {
+        return array_values($this->types);
+    }
+
+    public function getNonNullTypes(): array
+    {
+        $nonNullTypes = $this->types;
+        unset($nonNullTypes['null']);
+
+        return array_values($nonNullTypes);
+    }
+
+    protected function prefixWithNsSeparator(string $type): string
+    {
+        return '\\' . ltrim($type, '\\');
+    }
+
+    protected function getRealType(string $type): string
+    {
+        switch ($type) {
+            // type aliases
+            case 'double':
+            case 'real':
+                return 'float';
+            case 'boolean':
+                return 'bool';
+            case 'integer':
+                return 'int';
+
+            //  built in types
+            case 'self':
+            case 'array':
+            case 'callable':
+            case 'bool':
+            case 'false':
+            case 'float':
+            case 'int':
+            case 'string':
+            case 'iterable':
+            case 'object':
+            case 'null':
+                return $type;
+            case 'mixed':
+                return \PHP_VERSION_ID < 80000 ? $this->prefixWithNsSeparator($type) : $type;
+
+            default:
+                return $this->prefixWithNsSeparator($type);
+        }
+    }
+
+    protected function guardIsValidType()
+    {
+        if ($this->types == ['null' => 'null']) {
+            throw new DoubleException('Type cannot be standalone null');
+        }
+
+        if ($this->types == ['false' => 'false']) {
+            throw new DoubleException('Type cannot be standalone false');
+        }
+
+        if ($this->types == ['false' => 'false', 'null' => 'null']) {
+            throw new DoubleException('Type cannot be nullable false');
+        }
+
+        if (\PHP_VERSION_ID >= 80000 && isset($this->types['mixed']) && count($this->types) !== 1) {
+            throw new DoubleException('mixed cannot be part of a union');
+        }
+    }
+}
diff --git a/vendor/phpspec/prophecy/src/Prophecy/Doubler/Generator/ReflectionInterface.php b/vendor/phpspec/prophecy/src/Prophecy/Doubler/Generator/ReflectionInterface.php
new file mode 100644
index 0000000000000000000000000000000000000000..d720b15159a6ac5cee44929912e795b265c609cc
--- /dev/null
+++ b/vendor/phpspec/prophecy/src/Prophecy/Doubler/Generator/ReflectionInterface.php
@@ -0,0 +1,22 @@
+<?php
+
+/*
+ * This file is part of the Prophecy.
+ * (c) Konstantin Kudryashov <ever.zet@gmail.com>
+ *     Marcello Duarte <marcello.duarte@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Prophecy\Doubler\Generator;
+
+/**
+ * Reflection interface.
+ * All reflected classes implement this interface.
+ *
+ * @author Konstantin Kudryashov <ever.zet@gmail.com>
+ */
+interface ReflectionInterface
+{
+}
diff --git a/vendor/phpspec/prophecy/src/Prophecy/Doubler/Generator/TypeHintReference.php b/vendor/phpspec/prophecy/src/Prophecy/Doubler/Generator/TypeHintReference.php
new file mode 100644
index 0000000000000000000000000000000000000000..5e8aa303d68a9224fea69b3489d0f4c0ecc1e697
--- /dev/null
+++ b/vendor/phpspec/prophecy/src/Prophecy/Doubler/Generator/TypeHintReference.php
@@ -0,0 +1,43 @@
+<?php
+
+namespace Prophecy\Doubler\Generator;
+
+/**
+ * Tells whether a keyword refers to a class or to a built-in type for the
+ * current version of php
+ *
+ * @deprecated in favour of Node\TypeNodeAbstract
+ */
+final class TypeHintReference
+{
+    public function isBuiltInParamTypeHint($type)
+    {
+        switch ($type) {
+            case 'self':
+            case 'array':
+            case 'callable':
+            case 'bool':
+            case 'float':
+            case 'int':
+            case 'string':
+            case 'iterable':
+            case 'object':
+                return true;
+
+            case 'mixed':
+                return PHP_VERSION_ID >= 80000;
+
+            default:
+                return false;
+        }
+    }
+
+    public function isBuiltInReturnTypeHint($type)
+    {
+        if ($type === 'void') {
+            return true;
+        }
+
+        return $this->isBuiltInParamTypeHint($type);
+    }
+}
diff --git a/vendor/phpspec/prophecy/src/Prophecy/Doubler/LazyDouble.php b/vendor/phpspec/prophecy/src/Prophecy/Doubler/LazyDouble.php
new file mode 100644
index 0000000000000000000000000000000000000000..8a99c4ce8615252b33418edaa8c7010526e171f1
--- /dev/null
+++ b/vendor/phpspec/prophecy/src/Prophecy/Doubler/LazyDouble.php
@@ -0,0 +1,127 @@
+<?php
+
+/*
+ * This file is part of the Prophecy.
+ * (c) Konstantin Kudryashov <ever.zet@gmail.com>
+ *     Marcello Duarte <marcello.duarte@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Prophecy\Doubler;
+
+use Prophecy\Exception\Doubler\DoubleException;
+use Prophecy\Exception\Doubler\ClassNotFoundException;
+use Prophecy\Exception\Doubler\InterfaceNotFoundException;
+use ReflectionClass;
+
+/**
+ * Lazy double.
+ * Gives simple interface to describe double before creating it.
+ *
+ * @author Konstantin Kudryashov <ever.zet@gmail.com>
+ */
+class LazyDouble
+{
+    private $doubler;
+    private $class;
+    private $interfaces = array();
+    private $arguments  = null;
+    private $double;
+
+    /**
+     * Initializes lazy double.
+     *
+     * @param Doubler $doubler
+     */
+    public function __construct(Doubler $doubler)
+    {
+        $this->doubler = $doubler;
+    }
+
+    /**
+     * Tells doubler to use specific class as parent one for double.
+     *
+     * @param string|ReflectionClass $class
+     *
+     * @throws \Prophecy\Exception\Doubler\ClassNotFoundException
+     * @throws \Prophecy\Exception\Doubler\DoubleException
+     */
+    public function setParentClass($class)
+    {
+        if (null !== $this->double) {
+            throw new DoubleException('Can not extend class with already instantiated double.');
+        }
+
+        if (!$class instanceof ReflectionClass) {
+            if (!class_exists($class)) {
+                throw new ClassNotFoundException(sprintf('Class %s not found.', $class), $class);
+            }
+
+            $class = new ReflectionClass($class);
+        }
+
+        $this->class = $class;
+    }
+
+    /**
+     * Tells doubler to implement specific interface with double.
+     *
+     * @param string|ReflectionClass $interface
+     *
+     * @throws \Prophecy\Exception\Doubler\InterfaceNotFoundException
+     * @throws \Prophecy\Exception\Doubler\DoubleException
+     */
+    public function addInterface($interface)
+    {
+        if (null !== $this->double) {
+            throw new DoubleException(
+                'Can not implement interface with already instantiated double.'
+            );
+        }
+
+        if (!$interface instanceof ReflectionClass) {
+            if (!interface_exists($interface)) {
+                throw new InterfaceNotFoundException(
+                    sprintf('Interface %s not found.', $interface),
+                    $interface
+                );
+            }
+
+            $interface = new ReflectionClass($interface);
+        }
+
+        $this->interfaces[] = $interface;
+    }
+
+    /**
+     * Sets constructor arguments.
+     *
+     * @param array $arguments
+     */
+    public function setArguments(array $arguments = null)
+    {
+        $this->arguments = $arguments;
+    }
+
+    /**
+     * Creates double instance or returns already created one.
+     *
+     * @return DoubleInterface
+     */
+    public function getInstance()
+    {
+        if (null === $this->double) {
+            if (null !== $this->arguments) {
+                return $this->double = $this->doubler->double(
+                    $this->class, $this->interfaces, $this->arguments
+                );
+            }
+
+            $this->double = $this->doubler->double($this->class, $this->interfaces);
+        }
+
+        return $this->double;
+    }
+}
diff --git a/vendor/phpspec/prophecy/src/Prophecy/Doubler/NameGenerator.php b/vendor/phpspec/prophecy/src/Prophecy/Doubler/NameGenerator.php
new file mode 100644
index 0000000000000000000000000000000000000000..d67ec6a4db9a15d199aac6fcf7f5186d10a313bf
--- /dev/null
+++ b/vendor/phpspec/prophecy/src/Prophecy/Doubler/NameGenerator.php
@@ -0,0 +1,52 @@
+<?php
+
+/*
+ * This file is part of the Prophecy.
+ * (c) Konstantin Kudryashov <ever.zet@gmail.com>
+ *     Marcello Duarte <marcello.duarte@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Prophecy\Doubler;
+
+use ReflectionClass;
+
+/**
+ * Name generator.
+ * Generates classname for double.
+ *
+ * @author Konstantin Kudryashov <ever.zet@gmail.com>
+ */
+class NameGenerator
+{
+    private static $counter = 1;
+
+    /**
+     * Generates name.
+     *
+     * @param ReflectionClass   $class
+     * @param ReflectionClass[] $interfaces
+     *
+     * @return string
+     */
+    public function name(ReflectionClass $class = null, array $interfaces)
+    {
+        $parts = array();
+
+        if (null !== $class) {
+            $parts[] = $class->getName();
+        } else {
+            foreach ($interfaces as $interface) {
+                $parts[] = $interface->getShortName();
+            }
+        }
+
+        if (!count($parts)) {
+            $parts[] = 'stdClass';
+        }
+
+        return sprintf('Double\%s\P%d', implode('\\', $parts), self::$counter++);
+    }
+}
diff --git a/vendor/phpspec/prophecy/src/Prophecy/Exception/Call/UnexpectedCallException.php b/vendor/phpspec/prophecy/src/Prophecy/Exception/Call/UnexpectedCallException.php
new file mode 100644
index 0000000000000000000000000000000000000000..48ed22542db31473c1466e9220ca26f19465dfa9
--- /dev/null
+++ b/vendor/phpspec/prophecy/src/Prophecy/Exception/Call/UnexpectedCallException.php
@@ -0,0 +1,40 @@
+<?php
+
+/*
+ * This file is part of the Prophecy.
+ * (c) Konstantin Kudryashov <ever.zet@gmail.com>
+ *     Marcello Duarte <marcello.duarte@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Prophecy\Exception\Call;
+
+use Prophecy\Exception\Prophecy\ObjectProphecyException;
+use Prophecy\Prophecy\ObjectProphecy;
+
+class UnexpectedCallException extends ObjectProphecyException
+{
+    private $methodName;
+    private $arguments;
+
+    public function __construct($message, ObjectProphecy $objectProphecy,
+                                $methodName, array $arguments)
+    {
+        parent::__construct($message, $objectProphecy);
+
+        $this->methodName = $methodName;
+        $this->arguments = $arguments;
+    }
+
+    public function getMethodName()
+    {
+        return $this->methodName;
+    }
+
+    public function getArguments()
+    {
+        return $this->arguments;
+    }
+}
diff --git a/vendor/phpspec/prophecy/src/Prophecy/Exception/Doubler/ClassCreatorException.php b/vendor/phpspec/prophecy/src/Prophecy/Exception/Doubler/ClassCreatorException.php
new file mode 100644
index 0000000000000000000000000000000000000000..822918a2943263af7166beda7b4c4bd8f8430604
--- /dev/null
+++ b/vendor/phpspec/prophecy/src/Prophecy/Exception/Doubler/ClassCreatorException.php
@@ -0,0 +1,31 @@
+<?php
+
+/*
+ * This file is part of the Prophecy.
+ * (c) Konstantin Kudryashov <ever.zet@gmail.com>
+ *     Marcello Duarte <marcello.duarte@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Prophecy\Exception\Doubler;
+
+use Prophecy\Doubler\Generator\Node\ClassNode;
+
+class ClassCreatorException extends \RuntimeException implements DoublerException
+{
+    private $node;
+
+    public function __construct($message, ClassNode $node)
+    {
+        parent::__construct($message);
+
+        $this->node = $node;
+    }
+
+    public function getClassNode()
+    {
+        return $this->node;
+    }
+}
diff --git a/vendor/phpspec/prophecy/src/Prophecy/Exception/Doubler/ClassMirrorException.php b/vendor/phpspec/prophecy/src/Prophecy/Exception/Doubler/ClassMirrorException.php
new file mode 100644
index 0000000000000000000000000000000000000000..8fc53b8b527db218edff755a4f8d2d9c276643ef
--- /dev/null
+++ b/vendor/phpspec/prophecy/src/Prophecy/Exception/Doubler/ClassMirrorException.php
@@ -0,0 +1,31 @@
+<?php
+
+/*
+ * This file is part of the Prophecy.
+ * (c) Konstantin Kudryashov <ever.zet@gmail.com>
+ *     Marcello Duarte <marcello.duarte@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Prophecy\Exception\Doubler;
+
+use ReflectionClass;
+
+class ClassMirrorException extends \RuntimeException implements DoublerException
+{
+    private $class;
+
+    public function __construct($message, ReflectionClass $class)
+    {
+        parent::__construct($message);
+
+        $this->class = $class;
+    }
+
+    public function getReflectedClass()
+    {
+        return $this->class;
+    }
+}
diff --git a/vendor/phpspec/prophecy/src/Prophecy/Exception/Doubler/ClassNotFoundException.php b/vendor/phpspec/prophecy/src/Prophecy/Exception/Doubler/ClassNotFoundException.php
new file mode 100644
index 0000000000000000000000000000000000000000..5bc826d75e409359bd5541e6121923219c2deb57
--- /dev/null
+++ b/vendor/phpspec/prophecy/src/Prophecy/Exception/Doubler/ClassNotFoundException.php
@@ -0,0 +1,33 @@
+<?php
+
+/*
+ * This file is part of the Prophecy.
+ * (c) Konstantin Kudryashov <ever.zet@gmail.com>
+ *     Marcello Duarte <marcello.duarte@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Prophecy\Exception\Doubler;
+
+class ClassNotFoundException extends DoubleException
+{
+    private $classname;
+
+    /**
+     * @param string $message
+     * @param string $classname
+     */
+    public function __construct($message, $classname)
+    {
+        parent::__construct($message);
+
+        $this->classname = $classname;
+    }
+
+    public function getClassname()
+    {
+        return $this->classname;
+    }
+}
diff --git a/vendor/phpspec/prophecy/src/Prophecy/Exception/Doubler/DoubleException.php b/vendor/phpspec/prophecy/src/Prophecy/Exception/Doubler/DoubleException.php
new file mode 100644
index 0000000000000000000000000000000000000000..6642a58f20c4586799c0aab262d89c894e6061c8
--- /dev/null
+++ b/vendor/phpspec/prophecy/src/Prophecy/Exception/Doubler/DoubleException.php
@@ -0,0 +1,18 @@
+<?php
+
+/*
+ * This file is part of the Prophecy.
+ * (c) Konstantin Kudryashov <ever.zet@gmail.com>
+ *     Marcello Duarte <marcello.duarte@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Prophecy\Exception\Doubler;
+
+use RuntimeException;
+
+class DoubleException extends RuntimeException implements DoublerException
+{
+}
diff --git a/vendor/phpspec/prophecy/src/Prophecy/Exception/Doubler/DoublerException.php b/vendor/phpspec/prophecy/src/Prophecy/Exception/Doubler/DoublerException.php
new file mode 100644
index 0000000000000000000000000000000000000000..9d6be17969b9588ead2abcf4fc12e4134c666922
--- /dev/null
+++ b/vendor/phpspec/prophecy/src/Prophecy/Exception/Doubler/DoublerException.php
@@ -0,0 +1,18 @@
+<?php
+
+/*
+ * This file is part of the Prophecy.
+ * (c) Konstantin Kudryashov <ever.zet@gmail.com>
+ *     Marcello Duarte <marcello.duarte@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Prophecy\Exception\Doubler;
+
+use Prophecy\Exception\Exception;
+
+interface DoublerException extends Exception
+{
+}
diff --git a/vendor/phpspec/prophecy/src/Prophecy/Exception/Doubler/InterfaceNotFoundException.php b/vendor/phpspec/prophecy/src/Prophecy/Exception/Doubler/InterfaceNotFoundException.php
new file mode 100644
index 0000000000000000000000000000000000000000..e344dead2b30e8159200477867a3f89bfe1ffff8
--- /dev/null
+++ b/vendor/phpspec/prophecy/src/Prophecy/Exception/Doubler/InterfaceNotFoundException.php
@@ -0,0 +1,20 @@
+<?php
+
+/*
+ * This file is part of the Prophecy.
+ * (c) Konstantin Kudryashov <ever.zet@gmail.com>
+ *     Marcello Duarte <marcello.duarte@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Prophecy\Exception\Doubler;
+
+class InterfaceNotFoundException extends ClassNotFoundException
+{
+    public function getInterfaceName()
+    {
+        return $this->getClassname();
+    }
+}
diff --git a/vendor/phpspec/prophecy/src/Prophecy/Exception/Doubler/MethodNotExtendableException.php b/vendor/phpspec/prophecy/src/Prophecy/Exception/Doubler/MethodNotExtendableException.php
new file mode 100644
index 0000000000000000000000000000000000000000..56f47b11057ce9341df7408892598d9c6efd3393
--- /dev/null
+++ b/vendor/phpspec/prophecy/src/Prophecy/Exception/Doubler/MethodNotExtendableException.php
@@ -0,0 +1,41 @@
+<?php
+
+    namespace Prophecy\Exception\Doubler;
+
+    class MethodNotExtendableException extends DoubleException
+    {
+        private $methodName;
+
+        private $className;
+
+        /**
+         * @param string $message
+         * @param string $className
+         * @param string $methodName
+         */
+        public function __construct($message, $className, $methodName)
+        {
+            parent::__construct($message);
+
+            $this->methodName = $methodName;
+            $this->className = $className;
+        }
+
+
+        /**
+         * @return string
+         */
+        public function getMethodName()
+        {
+            return $this->methodName;
+        }
+
+        /**
+         * @return string
+         */
+        public function getClassName()
+        {
+            return $this->className;
+        }
+
+    }
diff --git a/vendor/phpspec/prophecy/src/Prophecy/Exception/Doubler/MethodNotFoundException.php b/vendor/phpspec/prophecy/src/Prophecy/Exception/Doubler/MethodNotFoundException.php
new file mode 100644
index 0000000000000000000000000000000000000000..a53834948042125f6204d21a9aaf4eb6fb236344
--- /dev/null
+++ b/vendor/phpspec/prophecy/src/Prophecy/Exception/Doubler/MethodNotFoundException.php
@@ -0,0 +1,60 @@
+<?php
+
+/*
+ * This file is part of the Prophecy.
+ * (c) Konstantin Kudryashov <ever.zet@gmail.com>
+ *     Marcello Duarte <marcello.duarte@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Prophecy\Exception\Doubler;
+
+class MethodNotFoundException extends DoubleException
+{
+    /**
+     * @var string|object
+     */
+    private $classname;
+
+    /**
+     * @var string
+     */
+    private $methodName;
+
+    /**
+     * @var array
+     */
+    private $arguments;
+
+    /**
+     * @param string $message
+     * @param string|object $classname
+     * @param string $methodName
+     * @param null|Argument\ArgumentsWildcard|array $arguments
+     */
+    public function __construct($message, $classname, $methodName, $arguments = null)
+    {
+        parent::__construct($message);
+
+        $this->classname  = $classname;
+        $this->methodName = $methodName;
+        $this->arguments = $arguments;
+    }
+
+    public function getClassname()
+    {
+        return $this->classname;
+    }
+
+    public function getMethodName()
+    {
+        return $this->methodName;
+    }
+
+    public function getArguments()
+    {
+        return $this->arguments;
+    }
+}
diff --git a/vendor/phpspec/prophecy/src/Prophecy/Exception/Doubler/ReturnByReferenceException.php b/vendor/phpspec/prophecy/src/Prophecy/Exception/Doubler/ReturnByReferenceException.php
new file mode 100644
index 0000000000000000000000000000000000000000..6303049700fabe30d246cc0b38fcc774a63166ec
--- /dev/null
+++ b/vendor/phpspec/prophecy/src/Prophecy/Exception/Doubler/ReturnByReferenceException.php
@@ -0,0 +1,41 @@
+<?php
+
+/*
+ * This file is part of the Prophecy.
+ * (c) Konstantin Kudryashov <ever.zet@gmail.com>
+ *     Marcello Duarte <marcello.duarte@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Prophecy\Exception\Doubler;
+
+class ReturnByReferenceException extends DoubleException
+{
+    private $classname;
+    private $methodName;
+
+    /**
+     * @param string $message
+     * @param string $classname
+     * @param string $methodName
+     */
+    public function __construct($message, $classname, $methodName)
+    {
+        parent::__construct($message);
+
+        $this->classname  = $classname;
+        $this->methodName = $methodName;
+    }
+
+    public function getClassname()
+    {
+        return $this->classname;
+    }
+
+    public function getMethodName()
+    {
+        return $this->methodName;
+    }
+}
diff --git a/vendor/phpspec/prophecy/src/Prophecy/Exception/Exception.php b/vendor/phpspec/prophecy/src/Prophecy/Exception/Exception.php
new file mode 100644
index 0000000000000000000000000000000000000000..4161912842cf5ae99ba358322a6a754b69f5d88d
--- /dev/null
+++ b/vendor/phpspec/prophecy/src/Prophecy/Exception/Exception.php
@@ -0,0 +1,22 @@
+<?php
+
+/*
+ * This file is part of the Prophecy.
+ * (c) Konstantin Kudryashov <ever.zet@gmail.com>
+ *     Marcello Duarte <marcello.duarte@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Prophecy\Exception;
+
+/**
+ * Core Prophecy exception interface.
+ * All Prophecy exceptions implement it.
+ *
+ * @author Konstantin Kudryashov <ever.zet@gmail.com>
+ */
+interface Exception extends \Throwable
+{
+}
diff --git a/vendor/phpspec/prophecy/src/Prophecy/Exception/InvalidArgumentException.php b/vendor/phpspec/prophecy/src/Prophecy/Exception/InvalidArgumentException.php
new file mode 100644
index 0000000000000000000000000000000000000000..bc91c690fa23dd8b34dfcaa5ce202b152e89c268
--- /dev/null
+++ b/vendor/phpspec/prophecy/src/Prophecy/Exception/InvalidArgumentException.php
@@ -0,0 +1,16 @@
+<?php
+
+/*
+ * This file is part of the Prophecy.
+ * (c) Konstantin Kudryashov <ever.zet@gmail.com>
+ *     Marcello Duarte <marcello.duarte@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Prophecy\Exception;
+
+class InvalidArgumentException extends \InvalidArgumentException implements Exception
+{
+}
diff --git a/vendor/phpspec/prophecy/src/Prophecy/Exception/Prediction/AggregateException.php b/vendor/phpspec/prophecy/src/Prophecy/Exception/Prediction/AggregateException.php
new file mode 100644
index 0000000000000000000000000000000000000000..a00dfb03cba3482aeec4781dfb1cc4729dff845b
--- /dev/null
+++ b/vendor/phpspec/prophecy/src/Prophecy/Exception/Prediction/AggregateException.php
@@ -0,0 +1,51 @@
+<?php
+
+/*
+ * This file is part of the Prophecy.
+ * (c) Konstantin Kudryashov <ever.zet@gmail.com>
+ *     Marcello Duarte <marcello.duarte@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Prophecy\Exception\Prediction;
+
+use Prophecy\Prophecy\ObjectProphecy;
+
+class AggregateException extends \RuntimeException implements PredictionException
+{
+    private $exceptions = array();
+    private $objectProphecy;
+
+    public function append(PredictionException $exception)
+    {
+        $message = $exception->getMessage();
+        $message = strtr($message, array("\n" => "\n  "))."\n";
+        $message = empty($this->exceptions) ? $message : "\n" . $message;
+
+        $this->message      = rtrim($this->message.$message);
+        $this->exceptions[] = $exception;
+    }
+
+    /**
+     * @return PredictionException[]
+     */
+    public function getExceptions()
+    {
+        return $this->exceptions;
+    }
+
+    public function setObjectProphecy(ObjectProphecy $objectProphecy)
+    {
+        $this->objectProphecy = $objectProphecy;
+    }
+
+    /**
+     * @return ObjectProphecy
+     */
+    public function getObjectProphecy()
+    {
+        return $this->objectProphecy;
+    }
+}
diff --git a/vendor/phpspec/prophecy/src/Prophecy/Exception/Prediction/FailedPredictionException.php b/vendor/phpspec/prophecy/src/Prophecy/Exception/Prediction/FailedPredictionException.php
new file mode 100644
index 0000000000000000000000000000000000000000..bbbbc3d97a19dc8b7c86348007179c1902f9be97
--- /dev/null
+++ b/vendor/phpspec/prophecy/src/Prophecy/Exception/Prediction/FailedPredictionException.php
@@ -0,0 +1,24 @@
+<?php
+
+/*
+ * This file is part of the Prophecy.
+ * (c) Konstantin Kudryashov <ever.zet@gmail.com>
+ *     Marcello Duarte <marcello.duarte@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Prophecy\Exception\Prediction;
+
+use RuntimeException;
+
+/**
+ * Basic failed prediction exception.
+ * Use it for custom prediction failures.
+ *
+ * @author Konstantin Kudryashov <ever.zet@gmail.com>
+ */
+class FailedPredictionException extends RuntimeException implements PredictionException
+{
+}
diff --git a/vendor/phpspec/prophecy/src/Prophecy/Exception/Prediction/NoCallsException.php b/vendor/phpspec/prophecy/src/Prophecy/Exception/Prediction/NoCallsException.php
new file mode 100644
index 0000000000000000000000000000000000000000..05ea4aad862ea66f24450eaed5ac5fb2b3ac7f6f
--- /dev/null
+++ b/vendor/phpspec/prophecy/src/Prophecy/Exception/Prediction/NoCallsException.php
@@ -0,0 +1,18 @@
+<?php
+
+/*
+ * This file is part of the Prophecy.
+ * (c) Konstantin Kudryashov <ever.zet@gmail.com>
+ *     Marcello Duarte <marcello.duarte@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Prophecy\Exception\Prediction;
+
+use Prophecy\Exception\Prophecy\MethodProphecyException;
+
+class NoCallsException extends MethodProphecyException implements PredictionException
+{
+}
diff --git a/vendor/phpspec/prophecy/src/Prophecy/Exception/Prediction/PredictionException.php b/vendor/phpspec/prophecy/src/Prophecy/Exception/Prediction/PredictionException.php
new file mode 100644
index 0000000000000000000000000000000000000000..2596b1ef1f161272fa152bd04d1add6a6bdad50e
--- /dev/null
+++ b/vendor/phpspec/prophecy/src/Prophecy/Exception/Prediction/PredictionException.php
@@ -0,0 +1,18 @@
+<?php
+
+/*
+ * This file is part of the Prophecy.
+ * (c) Konstantin Kudryashov <ever.zet@gmail.com>
+ *     Marcello Duarte <marcello.duarte@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Prophecy\Exception\Prediction;
+
+use Prophecy\Exception\Exception;
+
+interface PredictionException extends Exception
+{
+}
diff --git a/vendor/phpspec/prophecy/src/Prophecy/Exception/Prediction/UnexpectedCallsCountException.php b/vendor/phpspec/prophecy/src/Prophecy/Exception/Prediction/UnexpectedCallsCountException.php
new file mode 100644
index 0000000000000000000000000000000000000000..9d905431f8dbd40f0f35f8b1d8832462c27f40fd
--- /dev/null
+++ b/vendor/phpspec/prophecy/src/Prophecy/Exception/Prediction/UnexpectedCallsCountException.php
@@ -0,0 +1,31 @@
+<?php
+
+/*
+ * This file is part of the Prophecy.
+ * (c) Konstantin Kudryashov <ever.zet@gmail.com>
+ *     Marcello Duarte <marcello.duarte@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Prophecy\Exception\Prediction;
+
+use Prophecy\Prophecy\MethodProphecy;
+
+class UnexpectedCallsCountException extends UnexpectedCallsException
+{
+    private $expectedCount;
+
+    public function __construct($message, MethodProphecy $methodProphecy, $count, array $calls)
+    {
+        parent::__construct($message, $methodProphecy, $calls);
+
+        $this->expectedCount = intval($count);
+    }
+
+    public function getExpectedCount()
+    {
+        return $this->expectedCount;
+    }
+}
diff --git a/vendor/phpspec/prophecy/src/Prophecy/Exception/Prediction/UnexpectedCallsException.php b/vendor/phpspec/prophecy/src/Prophecy/Exception/Prediction/UnexpectedCallsException.php
new file mode 100644
index 0000000000000000000000000000000000000000..7a99c2d7963ea8892591460c1356481cddabbd44
--- /dev/null
+++ b/vendor/phpspec/prophecy/src/Prophecy/Exception/Prediction/UnexpectedCallsException.php
@@ -0,0 +1,32 @@
+<?php
+
+/*
+ * This file is part of the Prophecy.
+ * (c) Konstantin Kudryashov <ever.zet@gmail.com>
+ *     Marcello Duarte <marcello.duarte@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Prophecy\Exception\Prediction;
+
+use Prophecy\Prophecy\MethodProphecy;
+use Prophecy\Exception\Prophecy\MethodProphecyException;
+
+class UnexpectedCallsException extends MethodProphecyException implements PredictionException
+{
+    private $calls = array();
+
+    public function __construct($message, MethodProphecy $methodProphecy, array $calls)
+    {
+        parent::__construct($message, $methodProphecy);
+
+        $this->calls = $calls;
+    }
+
+    public function getCalls()
+    {
+        return $this->calls;
+    }
+}
diff --git a/vendor/phpspec/prophecy/src/Prophecy/Exception/Prophecy/MethodProphecyException.php b/vendor/phpspec/prophecy/src/Prophecy/Exception/Prophecy/MethodProphecyException.php
new file mode 100644
index 0000000000000000000000000000000000000000..1b03eaf4726cc22111e0fb86bdc66a9aa3702f3e
--- /dev/null
+++ b/vendor/phpspec/prophecy/src/Prophecy/Exception/Prophecy/MethodProphecyException.php
@@ -0,0 +1,34 @@
+<?php
+
+/*
+ * This file is part of the Prophecy.
+ * (c) Konstantin Kudryashov <ever.zet@gmail.com>
+ *     Marcello Duarte <marcello.duarte@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Prophecy\Exception\Prophecy;
+
+use Prophecy\Prophecy\MethodProphecy;
+
+class MethodProphecyException extends ObjectProphecyException
+{
+    private $methodProphecy;
+
+    public function __construct($message, MethodProphecy $methodProphecy)
+    {
+        parent::__construct($message, $methodProphecy->getObjectProphecy());
+
+        $this->methodProphecy = $methodProphecy;
+    }
+
+    /**
+     * @return MethodProphecy
+     */
+    public function getMethodProphecy()
+    {
+        return $this->methodProphecy;
+    }
+}
diff --git a/vendor/phpspec/prophecy/src/Prophecy/Exception/Prophecy/ObjectProphecyException.php b/vendor/phpspec/prophecy/src/Prophecy/Exception/Prophecy/ObjectProphecyException.php
new file mode 100644
index 0000000000000000000000000000000000000000..e345402e016e28fffd1a6bad8a430caf7662b670
--- /dev/null
+++ b/vendor/phpspec/prophecy/src/Prophecy/Exception/Prophecy/ObjectProphecyException.php
@@ -0,0 +1,34 @@
+<?php
+
+/*
+ * This file is part of the Prophecy.
+ * (c) Konstantin Kudryashov <ever.zet@gmail.com>
+ *     Marcello Duarte <marcello.duarte@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Prophecy\Exception\Prophecy;
+
+use Prophecy\Prophecy\ObjectProphecy;
+
+class ObjectProphecyException extends \RuntimeException implements ProphecyException
+{
+    private $objectProphecy;
+
+    public function __construct($message, ObjectProphecy $objectProphecy)
+    {
+        parent::__construct($message);
+
+        $this->objectProphecy = $objectProphecy;
+    }
+
+    /**
+     * @return ObjectProphecy
+     */
+    public function getObjectProphecy()
+    {
+        return $this->objectProphecy;
+    }
+}
diff --git a/vendor/phpspec/prophecy/src/Prophecy/Exception/Prophecy/ProphecyException.php b/vendor/phpspec/prophecy/src/Prophecy/Exception/Prophecy/ProphecyException.php
new file mode 100644
index 0000000000000000000000000000000000000000..91573328724e2cf4a485665741ad001463d4884e
--- /dev/null
+++ b/vendor/phpspec/prophecy/src/Prophecy/Exception/Prophecy/ProphecyException.php
@@ -0,0 +1,18 @@
+<?php
+
+/*
+ * This file is part of the Prophecy.
+ * (c) Konstantin Kudryashov <ever.zet@gmail.com>
+ *     Marcello Duarte <marcello.duarte@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Prophecy\Exception\Prophecy;
+
+use Prophecy\Exception\Exception;
+
+interface ProphecyException extends Exception
+{
+}
diff --git a/vendor/phpspec/prophecy/src/Prophecy/PhpDocumentor/ClassAndInterfaceTagRetriever.php b/vendor/phpspec/prophecy/src/Prophecy/PhpDocumentor/ClassAndInterfaceTagRetriever.php
new file mode 100644
index 0000000000000000000000000000000000000000..209821ce91e6ef442fc39ae05124d4cea8657046
--- /dev/null
+++ b/vendor/phpspec/prophecy/src/Prophecy/PhpDocumentor/ClassAndInterfaceTagRetriever.php
@@ -0,0 +1,69 @@
+<?php
+
+/*
+ * This file is part of the Prophecy.
+ * (c) Konstantin Kudryashov <ever.zet@gmail.com>
+ *     Marcello Duarte <marcello.duarte@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Prophecy\PhpDocumentor;
+
+use phpDocumentor\Reflection\DocBlock\Tag\MethodTag as LegacyMethodTag;
+use phpDocumentor\Reflection\DocBlock\Tags\Method;
+
+/**
+ * @author Théo FIDRY <theo.fidry@gmail.com>
+ *
+ * @internal
+ */
+final class ClassAndInterfaceTagRetriever implements MethodTagRetrieverInterface
+{
+    private $classRetriever;
+
+    public function __construct(MethodTagRetrieverInterface $classRetriever = null)
+    {
+        if (null !== $classRetriever) {
+            $this->classRetriever = $classRetriever;
+
+            return;
+        }
+
+        $this->classRetriever = class_exists('phpDocumentor\Reflection\DocBlockFactory') && class_exists('phpDocumentor\Reflection\Types\ContextFactory')
+            ? new ClassTagRetriever()
+            : new LegacyClassTagRetriever()
+        ;
+    }
+
+    /**
+     * @param \ReflectionClass $reflectionClass
+     *
+     * @return LegacyMethodTag[]|Method[]
+     */
+    public function getTagList(\ReflectionClass $reflectionClass)
+    {
+        return array_merge(
+            $this->classRetriever->getTagList($reflectionClass),
+            $this->getInterfacesTagList($reflectionClass)
+        );
+    }
+
+    /**
+     * @param \ReflectionClass $reflectionClass
+     *
+     * @return LegacyMethodTag[]|Method[]
+     */
+    private function getInterfacesTagList(\ReflectionClass $reflectionClass)
+    {
+        $interfaces = $reflectionClass->getInterfaces();
+        $tagList = array();
+
+        foreach($interfaces as $interface) {
+            $tagList = array_merge($tagList, $this->classRetriever->getTagList($interface));
+        }
+
+        return $tagList;
+    }
+}
diff --git a/vendor/phpspec/prophecy/src/Prophecy/PhpDocumentor/ClassTagRetriever.php b/vendor/phpspec/prophecy/src/Prophecy/PhpDocumentor/ClassTagRetriever.php
new file mode 100644
index 0000000000000000000000000000000000000000..9817a44797f8741cca6c7ae4e90b38b7992ba18b
--- /dev/null
+++ b/vendor/phpspec/prophecy/src/Prophecy/PhpDocumentor/ClassTagRetriever.php
@@ -0,0 +1,60 @@
+<?php
+
+/*
+ * This file is part of the Prophecy.
+ * (c) Konstantin Kudryashov <ever.zet@gmail.com>
+ *     Marcello Duarte <marcello.duarte@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Prophecy\PhpDocumentor;
+
+use phpDocumentor\Reflection\DocBlock\Tags\Method;
+use phpDocumentor\Reflection\DocBlockFactory;
+use phpDocumentor\Reflection\Types\ContextFactory;
+
+/**
+ * @author Théo FIDRY <theo.fidry@gmail.com>
+ *
+ * @internal
+ */
+final class ClassTagRetriever implements MethodTagRetrieverInterface
+{
+    private $docBlockFactory;
+    private $contextFactory;
+
+    public function __construct()
+    {
+        $this->docBlockFactory = DocBlockFactory::createInstance();
+        $this->contextFactory = new ContextFactory();
+    }
+
+    /**
+     * @param \ReflectionClass $reflectionClass
+     *
+     * @return Method[]
+     */
+    public function getTagList(\ReflectionClass $reflectionClass)
+    {
+        try {
+            $phpdoc = $this->docBlockFactory->create(
+                $reflectionClass,
+                $this->contextFactory->createFromReflector($reflectionClass)
+            );
+
+            $methods = array();
+
+            foreach ($phpdoc->getTagsByName('method') as $tag) {
+                if ($tag instanceof Method) {
+                    $methods[] = $tag;
+                }
+            }
+
+            return $methods;
+        } catch (\InvalidArgumentException $e) {
+            return array();
+        }
+    }
+}
diff --git a/vendor/phpspec/prophecy/src/Prophecy/PhpDocumentor/LegacyClassTagRetriever.php b/vendor/phpspec/prophecy/src/Prophecy/PhpDocumentor/LegacyClassTagRetriever.php
new file mode 100644
index 0000000000000000000000000000000000000000..c0dec3de82122e8a9b8f543103e05331a2d94bb7
--- /dev/null
+++ b/vendor/phpspec/prophecy/src/Prophecy/PhpDocumentor/LegacyClassTagRetriever.php
@@ -0,0 +1,35 @@
+<?php
+
+/*
+ * This file is part of the Prophecy.
+ * (c) Konstantin Kudryashov <ever.zet@gmail.com>
+ *     Marcello Duarte <marcello.duarte@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Prophecy\PhpDocumentor;
+
+use phpDocumentor\Reflection\DocBlock;
+use phpDocumentor\Reflection\DocBlock\Tag\MethodTag as LegacyMethodTag;
+
+/**
+ * @author Théo FIDRY <theo.fidry@gmail.com>
+ *
+ * @internal
+ */
+final class LegacyClassTagRetriever implements MethodTagRetrieverInterface
+{
+    /**
+     * @param \ReflectionClass $reflectionClass
+     *
+     * @return LegacyMethodTag[]
+     */
+    public function getTagList(\ReflectionClass $reflectionClass)
+    {
+        $phpdoc = new DocBlock($reflectionClass->getDocComment());
+
+        return $phpdoc->getTagsByName('method');
+    }
+}
diff --git a/vendor/phpspec/prophecy/src/Prophecy/PhpDocumentor/MethodTagRetrieverInterface.php b/vendor/phpspec/prophecy/src/Prophecy/PhpDocumentor/MethodTagRetrieverInterface.php
new file mode 100644
index 0000000000000000000000000000000000000000..d3989dad5883322552666458a47436df051967b3
--- /dev/null
+++ b/vendor/phpspec/prophecy/src/Prophecy/PhpDocumentor/MethodTagRetrieverInterface.php
@@ -0,0 +1,30 @@
+<?php
+
+/*
+ * This file is part of the Prophecy.
+ * (c) Konstantin Kudryashov <ever.zet@gmail.com>
+ *     Marcello Duarte <marcello.duarte@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Prophecy\PhpDocumentor;
+
+use phpDocumentor\Reflection\DocBlock\Tag\MethodTag as LegacyMethodTag;
+use phpDocumentor\Reflection\DocBlock\Tags\Method;
+
+/**
+ * @author Théo FIDRY <theo.fidry@gmail.com>
+ *
+ * @internal
+ */
+interface MethodTagRetrieverInterface
+{
+    /**
+     * @param \ReflectionClass $reflectionClass
+     *
+     * @return LegacyMethodTag[]|Method[]
+     */
+    public function getTagList(\ReflectionClass $reflectionClass);
+}
diff --git a/vendor/phpspec/prophecy/src/Prophecy/Prediction/CallPrediction.php b/vendor/phpspec/prophecy/src/Prophecy/Prediction/CallPrediction.php
new file mode 100644
index 0000000000000000000000000000000000000000..b478736695b0abc38cc41804661fa7828626e87f
--- /dev/null
+++ b/vendor/phpspec/prophecy/src/Prophecy/Prediction/CallPrediction.php
@@ -0,0 +1,86 @@
+<?php
+
+/*
+ * This file is part of the Prophecy.
+ * (c) Konstantin Kudryashov <ever.zet@gmail.com>
+ *     Marcello Duarte <marcello.duarte@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Prophecy\Prediction;
+
+use Prophecy\Call\Call;
+use Prophecy\Prophecy\ObjectProphecy;
+use Prophecy\Prophecy\MethodProphecy;
+use Prophecy\Argument\ArgumentsWildcard;
+use Prophecy\Argument\Token\AnyValuesToken;
+use Prophecy\Util\StringUtil;
+use Prophecy\Exception\Prediction\NoCallsException;
+
+/**
+ * Call prediction.
+ *
+ * @author Konstantin Kudryashov <ever.zet@gmail.com>
+ */
+class CallPrediction implements PredictionInterface
+{
+    private $util;
+
+    /**
+     * Initializes prediction.
+     *
+     * @param StringUtil $util
+     */
+    public function __construct(StringUtil $util = null)
+    {
+        $this->util = $util ?: new StringUtil;
+    }
+
+    /**
+     * Tests that there was at least one call.
+     *
+     * @param Call[]         $calls
+     * @param ObjectProphecy $object
+     * @param MethodProphecy $method
+     *
+     * @throws \Prophecy\Exception\Prediction\NoCallsException
+     */
+    public function check(array $calls, ObjectProphecy $object, MethodProphecy $method)
+    {
+        if (count($calls)) {
+            return;
+        }
+
+        $methodCalls = $object->findProphecyMethodCalls(
+            $method->getMethodName(),
+            new ArgumentsWildcard(array(new AnyValuesToken))
+        );
+
+        if (count($methodCalls)) {
+            throw new NoCallsException(sprintf(
+                "No calls have been made that match:\n".
+                "  %s->%s(%s)\n".
+                "but expected at least one.\n".
+                "Recorded `%s(...)` calls:\n%s",
+
+                get_class($object->reveal()),
+                $method->getMethodName(),
+                $method->getArgumentsWildcard(),
+                $method->getMethodName(),
+                $this->util->stringifyCalls($methodCalls)
+            ), $method);
+        }
+
+        throw new NoCallsException(sprintf(
+            "No calls have been made that match:\n".
+            "  %s->%s(%s)\n".
+            "but expected at least one.",
+
+            get_class($object->reveal()),
+            $method->getMethodName(),
+            $method->getArgumentsWildcard()
+        ), $method);
+    }
+}
diff --git a/vendor/phpspec/prophecy/src/Prophecy/Prediction/CallTimesPrediction.php b/vendor/phpspec/prophecy/src/Prophecy/Prediction/CallTimesPrediction.php
new file mode 100644
index 0000000000000000000000000000000000000000..31c6c575acd28ddcb13e0ae86a025dccc2b068b1
--- /dev/null
+++ b/vendor/phpspec/prophecy/src/Prophecy/Prediction/CallTimesPrediction.php
@@ -0,0 +1,107 @@
+<?php
+
+/*
+ * This file is part of the Prophecy.
+ * (c) Konstantin Kudryashov <ever.zet@gmail.com>
+ *     Marcello Duarte <marcello.duarte@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Prophecy\Prediction;
+
+use Prophecy\Call\Call;
+use Prophecy\Prophecy\ObjectProphecy;
+use Prophecy\Prophecy\MethodProphecy;
+use Prophecy\Argument\ArgumentsWildcard;
+use Prophecy\Argument\Token\AnyValuesToken;
+use Prophecy\Util\StringUtil;
+use Prophecy\Exception\Prediction\UnexpectedCallsCountException;
+
+/**
+ * Prediction interface.
+ * Predictions are logical test blocks, tied to `should...` keyword.
+ *
+ * @author Konstantin Kudryashov <ever.zet@gmail.com>
+ */
+class CallTimesPrediction implements PredictionInterface
+{
+    private $times;
+    private $util;
+
+    /**
+     * Initializes prediction.
+     *
+     * @param int        $times
+     * @param StringUtil $util
+     */
+    public function __construct($times, StringUtil $util = null)
+    {
+        $this->times = intval($times);
+        $this->util  = $util ?: new StringUtil;
+    }
+
+    /**
+     * Tests that there was exact amount of calls made.
+     *
+     * @param Call[]         $calls
+     * @param ObjectProphecy $object
+     * @param MethodProphecy $method
+     *
+     * @throws \Prophecy\Exception\Prediction\UnexpectedCallsCountException
+     */
+    public function check(array $calls, ObjectProphecy $object, MethodProphecy $method)
+    {
+        if ($this->times == count($calls)) {
+            return;
+        }
+
+        $methodCalls = $object->findProphecyMethodCalls(
+            $method->getMethodName(),
+            new ArgumentsWildcard(array(new AnyValuesToken))
+        );
+
+        if (count($calls)) {
+            $message = sprintf(
+                "Expected exactly %d calls that match:\n".
+                "  %s->%s(%s)\n".
+                "but %d were made:\n%s",
+
+                $this->times,
+                get_class($object->reveal()),
+                $method->getMethodName(),
+                $method->getArgumentsWildcard(),
+                count($calls),
+                $this->util->stringifyCalls($calls)
+            );
+        } elseif (count($methodCalls)) {
+            $message = sprintf(
+                "Expected exactly %d calls that match:\n".
+                "  %s->%s(%s)\n".
+                "but none were made.\n".
+                "Recorded `%s(...)` calls:\n%s",
+
+                $this->times,
+                get_class($object->reveal()),
+                $method->getMethodName(),
+                $method->getArgumentsWildcard(),
+                $method->getMethodName(),
+                $this->util->stringifyCalls($methodCalls)
+            );
+        } else {
+            $message = sprintf(
+                "Expected exactly %d calls that match:\n".
+                "  %s->%s(%s)\n".
+                "but none were made.",
+
+                $this->times,
+                get_class($object->reveal()),
+                $method->getMethodName(),
+                $method->getArgumentsWildcard()
+            );
+        }
+
+        throw new UnexpectedCallsCountException($message, $method, $this->times, $calls);
+    }
+}
diff --git a/vendor/phpspec/prophecy/src/Prophecy/Prediction/CallbackPrediction.php b/vendor/phpspec/prophecy/src/Prophecy/Prediction/CallbackPrediction.php
new file mode 100644
index 0000000000000000000000000000000000000000..44bc782c8a15123ab0d043d52c8f3fe375f9655b
--- /dev/null
+++ b/vendor/phpspec/prophecy/src/Prophecy/Prediction/CallbackPrediction.php
@@ -0,0 +1,65 @@
+<?php
+
+/*
+ * This file is part of the Prophecy.
+ * (c) Konstantin Kudryashov <ever.zet@gmail.com>
+ *     Marcello Duarte <marcello.duarte@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Prophecy\Prediction;
+
+use Prophecy\Call\Call;
+use Prophecy\Prophecy\ObjectProphecy;
+use Prophecy\Prophecy\MethodProphecy;
+use Prophecy\Exception\InvalidArgumentException;
+use Closure;
+
+/**
+ * Callback prediction.
+ *
+ * @author Konstantin Kudryashov <ever.zet@gmail.com>
+ */
+class CallbackPrediction implements PredictionInterface
+{
+    private $callback;
+
+    /**
+     * Initializes callback prediction.
+     *
+     * @param callable $callback Custom callback
+     *
+     * @throws \Prophecy\Exception\InvalidArgumentException
+     */
+    public function __construct($callback)
+    {
+        if (!is_callable($callback)) {
+            throw new InvalidArgumentException(sprintf(
+                'Callable expected as an argument to CallbackPrediction, but got %s.',
+                gettype($callback)
+            ));
+        }
+
+        $this->callback = $callback;
+    }
+
+    /**
+     * Executes preset callback.
+     *
+     * @param Call[]         $calls
+     * @param ObjectProphecy $object
+     * @param MethodProphecy $method
+     */
+    public function check(array $calls, ObjectProphecy $object, MethodProphecy $method)
+    {
+        $callback = $this->callback;
+
+        if ($callback instanceof Closure && method_exists('Closure', 'bind')) {
+            $callback = Closure::bind($callback, $object);
+        }
+
+        call_user_func($callback, $calls, $object, $method);
+    }
+}
diff --git a/vendor/phpspec/prophecy/src/Prophecy/Prediction/NoCallsPrediction.php b/vendor/phpspec/prophecy/src/Prophecy/Prediction/NoCallsPrediction.php
new file mode 100644
index 0000000000000000000000000000000000000000..46ac5bfc062d7cc04b29a6ddcf5c91ec38423903
--- /dev/null
+++ b/vendor/phpspec/prophecy/src/Prophecy/Prediction/NoCallsPrediction.php
@@ -0,0 +1,68 @@
+<?php
+
+/*
+ * This file is part of the Prophecy.
+ * (c) Konstantin Kudryashov <ever.zet@gmail.com>
+ *     Marcello Duarte <marcello.duarte@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Prophecy\Prediction;
+
+use Prophecy\Call\Call;
+use Prophecy\Prophecy\ObjectProphecy;
+use Prophecy\Prophecy\MethodProphecy;
+use Prophecy\Util\StringUtil;
+use Prophecy\Exception\Prediction\UnexpectedCallsException;
+
+/**
+ * No calls prediction.
+ *
+ * @author Konstantin Kudryashov <ever.zet@gmail.com>
+ */
+class NoCallsPrediction implements PredictionInterface
+{
+    private $util;
+
+    /**
+     * Initializes prediction.
+     *
+     * @param null|StringUtil $util
+     */
+    public function __construct(StringUtil $util = null)
+    {
+        $this->util = $util ?: new StringUtil;
+    }
+
+    /**
+     * Tests that there were no calls made.
+     *
+     * @param Call[]         $calls
+     * @param ObjectProphecy $object
+     * @param MethodProphecy $method
+     *
+     * @throws \Prophecy\Exception\Prediction\UnexpectedCallsException
+     */
+    public function check(array $calls, ObjectProphecy $object, MethodProphecy $method)
+    {
+        if (!count($calls)) {
+            return;
+        }
+
+        $verb = count($calls) === 1 ? 'was' : 'were';
+
+        throw new UnexpectedCallsException(sprintf(
+            "No calls expected that match:\n".
+            "  %s->%s(%s)\n".
+            "but %d %s made:\n%s",
+            get_class($object->reveal()),
+            $method->getMethodName(),
+            $method->getArgumentsWildcard(),
+            count($calls),
+            $verb,
+            $this->util->stringifyCalls($calls)
+        ), $method, $calls);
+    }
+}
diff --git a/vendor/phpspec/prophecy/src/Prophecy/Prediction/PredictionInterface.php b/vendor/phpspec/prophecy/src/Prophecy/Prediction/PredictionInterface.php
new file mode 100644
index 0000000000000000000000000000000000000000..f7fb06a9963c963d15b6c7905996f02561e74d51
--- /dev/null
+++ b/vendor/phpspec/prophecy/src/Prophecy/Prediction/PredictionInterface.php
@@ -0,0 +1,37 @@
+<?php
+
+/*
+ * This file is part of the Prophecy.
+ * (c) Konstantin Kudryashov <ever.zet@gmail.com>
+ *     Marcello Duarte <marcello.duarte@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Prophecy\Prediction;
+
+use Prophecy\Call\Call;
+use Prophecy\Prophecy\ObjectProphecy;
+use Prophecy\Prophecy\MethodProphecy;
+
+/**
+ * Prediction interface.
+ * Predictions are logical test blocks, tied to `should...` keyword.
+ *
+ * @author Konstantin Kudryashov <ever.zet@gmail.com>
+ */
+interface PredictionInterface
+{
+    /**
+     * Tests that double fulfilled prediction.
+     *
+     * @param Call[]        $calls
+     * @param ObjectProphecy $object
+     * @param MethodProphecy $method
+     *
+     * @throws object
+     * @return void
+     */
+    public function check(array $calls, ObjectProphecy $object, MethodProphecy $method);
+}
diff --git a/vendor/phpspec/prophecy/src/Prophecy/Promise/CallbackPromise.php b/vendor/phpspec/prophecy/src/Prophecy/Promise/CallbackPromise.php
new file mode 100644
index 0000000000000000000000000000000000000000..5f406bf7a8ce0fb67dddaf1a66308e6467df904c
--- /dev/null
+++ b/vendor/phpspec/prophecy/src/Prophecy/Promise/CallbackPromise.php
@@ -0,0 +1,66 @@
+<?php
+
+/*
+ * This file is part of the Prophecy.
+ * (c) Konstantin Kudryashov <ever.zet@gmail.com>
+ *     Marcello Duarte <marcello.duarte@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Prophecy\Promise;
+
+use Prophecy\Prophecy\ObjectProphecy;
+use Prophecy\Prophecy\MethodProphecy;
+use Prophecy\Exception\InvalidArgumentException;
+use Closure;
+
+/**
+ * Callback promise.
+ *
+ * @author Konstantin Kudryashov <ever.zet@gmail.com>
+ */
+class CallbackPromise implements PromiseInterface
+{
+    private $callback;
+
+    /**
+     * Initializes callback promise.
+     *
+     * @param callable $callback Custom callback
+     *
+     * @throws \Prophecy\Exception\InvalidArgumentException
+     */
+    public function __construct($callback)
+    {
+        if (!is_callable($callback)) {
+            throw new InvalidArgumentException(sprintf(
+                'Callable expected as an argument to CallbackPromise, but got %s.',
+                gettype($callback)
+            ));
+        }
+
+        $this->callback = $callback;
+    }
+
+    /**
+     * Evaluates promise callback.
+     *
+     * @param array          $args
+     * @param ObjectProphecy $object
+     * @param MethodProphecy $method
+     *
+     * @return mixed
+     */
+    public function execute(array $args, ObjectProphecy $object, MethodProphecy $method)
+    {
+        $callback = $this->callback;
+
+        if ($callback instanceof Closure && method_exists('Closure', 'bind')) {
+            $callback = Closure::bind($callback, $object);
+        }
+
+        return call_user_func($callback, $args, $object, $method);
+    }
+}
diff --git a/vendor/phpspec/prophecy/src/Prophecy/Promise/PromiseInterface.php b/vendor/phpspec/prophecy/src/Prophecy/Promise/PromiseInterface.php
new file mode 100644
index 0000000000000000000000000000000000000000..382537b47da80e26bd713a8ee5c7d1386f393786
--- /dev/null
+++ b/vendor/phpspec/prophecy/src/Prophecy/Promise/PromiseInterface.php
@@ -0,0 +1,35 @@
+<?php
+
+/*
+ * This file is part of the Prophecy.
+ * (c) Konstantin Kudryashov <ever.zet@gmail.com>
+ *     Marcello Duarte <marcello.duarte@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Prophecy\Promise;
+
+use Prophecy\Prophecy\ObjectProphecy;
+use Prophecy\Prophecy\MethodProphecy;
+
+/**
+ * Promise interface.
+ * Promises are logical blocks, tied to `will...` keyword.
+ *
+ * @author Konstantin Kudryashov <ever.zet@gmail.com>
+ */
+interface PromiseInterface
+{
+    /**
+     * Evaluates promise.
+     *
+     * @param array          $args
+     * @param ObjectProphecy $object
+     * @param MethodProphecy $method
+     *
+     * @return mixed
+     */
+    public function execute(array $args, ObjectProphecy $object, MethodProphecy $method);
+}
diff --git a/vendor/phpspec/prophecy/src/Prophecy/Promise/ReturnArgumentPromise.php b/vendor/phpspec/prophecy/src/Prophecy/Promise/ReturnArgumentPromise.php
new file mode 100644
index 0000000000000000000000000000000000000000..39bfeea07076f3a6f8ccb1e291fd487431417738
--- /dev/null
+++ b/vendor/phpspec/prophecy/src/Prophecy/Promise/ReturnArgumentPromise.php
@@ -0,0 +1,61 @@
+<?php
+
+/*
+ * This file is part of the Prophecy.
+ * (c) Konstantin Kudryashov <ever.zet@gmail.com>
+ *     Marcello Duarte <marcello.duarte@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Prophecy\Promise;
+
+use Prophecy\Exception\InvalidArgumentException;
+use Prophecy\Prophecy\ObjectProphecy;
+use Prophecy\Prophecy\MethodProphecy;
+
+/**
+ * Return argument promise.
+ *
+ * @author Konstantin Kudryashov <ever.zet@gmail.com>
+ */
+class ReturnArgumentPromise implements PromiseInterface
+{
+    /**
+     * @var int
+     */
+    private $index;
+
+    /**
+     * Initializes callback promise.
+     *
+     * @param int $index The zero-indexed number of the argument to return
+     *
+     * @throws \Prophecy\Exception\InvalidArgumentException
+     */
+    public function __construct($index = 0)
+    {
+        if (!is_int($index) || $index < 0) {
+            throw new InvalidArgumentException(sprintf(
+                'Zero-based index expected as argument to ReturnArgumentPromise, but got %s.',
+                $index
+            ));
+        }
+        $this->index = $index;
+    }
+
+    /**
+     * Returns nth argument if has one, null otherwise.
+     *
+     * @param array          $args
+     * @param ObjectProphecy $object
+     * @param MethodProphecy $method
+     *
+     * @return null|mixed
+     */
+    public function execute(array $args, ObjectProphecy $object, MethodProphecy $method)
+    {
+        return count($args) > $this->index ? $args[$this->index] : null;
+    }
+}
diff --git a/vendor/phpspec/prophecy/src/Prophecy/Promise/ReturnPromise.php b/vendor/phpspec/prophecy/src/Prophecy/Promise/ReturnPromise.php
new file mode 100644
index 0000000000000000000000000000000000000000..c7d5ac5988348aed44f0b7a751c09ce98a15e27c
--- /dev/null
+++ b/vendor/phpspec/prophecy/src/Prophecy/Promise/ReturnPromise.php
@@ -0,0 +1,55 @@
+<?php
+
+/*
+ * This file is part of the Prophecy.
+ * (c) Konstantin Kudryashov <ever.zet@gmail.com>
+ *     Marcello Duarte <marcello.duarte@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Prophecy\Promise;
+
+use Prophecy\Prophecy\ObjectProphecy;
+use Prophecy\Prophecy\MethodProphecy;
+
+/**
+ * Return promise.
+ *
+ * @author Konstantin Kudryashov <ever.zet@gmail.com>
+ */
+class ReturnPromise implements PromiseInterface
+{
+    private $returnValues = array();
+
+    /**
+     * Initializes promise.
+     *
+     * @param array $returnValues Array of values
+     */
+    public function __construct(array $returnValues)
+    {
+        $this->returnValues = $returnValues;
+    }
+
+    /**
+     * Returns saved values one by one until last one, then continuously returns last value.
+     *
+     * @param array          $args
+     * @param ObjectProphecy $object
+     * @param MethodProphecy $method
+     *
+     * @return mixed
+     */
+    public function execute(array $args, ObjectProphecy $object, MethodProphecy $method)
+    {
+        $value = array_shift($this->returnValues);
+
+        if (!count($this->returnValues)) {
+            $this->returnValues[] = $value;
+        }
+
+        return $value;
+    }
+}
diff --git a/vendor/phpspec/prophecy/src/Prophecy/Promise/ThrowPromise.php b/vendor/phpspec/prophecy/src/Prophecy/Promise/ThrowPromise.php
new file mode 100644
index 0000000000000000000000000000000000000000..26ec19edfa24457daaa810c289357800b015a008
--- /dev/null
+++ b/vendor/phpspec/prophecy/src/Prophecy/Promise/ThrowPromise.php
@@ -0,0 +1,100 @@
+<?php
+
+/*
+ * This file is part of the Prophecy.
+ * (c) Konstantin Kudryashov <ever.zet@gmail.com>
+ *     Marcello Duarte <marcello.duarte@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Prophecy\Promise;
+
+use Doctrine\Instantiator\Instantiator;
+use Prophecy\Prophecy\ObjectProphecy;
+use Prophecy\Prophecy\MethodProphecy;
+use Prophecy\Exception\InvalidArgumentException;
+use ReflectionClass;
+
+/**
+ * Throw promise.
+ *
+ * @author Konstantin Kudryashov <ever.zet@gmail.com>
+ */
+class ThrowPromise implements PromiseInterface
+{
+    private $exception;
+
+    /**
+     * @var \Doctrine\Instantiator\Instantiator
+     */
+    private $instantiator;
+
+    /**
+     * Initializes promise.
+     *
+     * @param string|\Exception|\Throwable $exception Exception class name or instance
+     *
+     * @throws \Prophecy\Exception\InvalidArgumentException
+     */
+    public function __construct($exception)
+    {
+        if (is_string($exception)) {
+            if ((!class_exists($exception) && !interface_exists($exception)) || !$this->isAValidThrowable($exception)) {
+                throw new InvalidArgumentException(sprintf(
+                    'Exception / Throwable class or instance expected as argument to ThrowPromise, but got %s.',
+                    $exception
+                ));
+            }
+        } elseif (!$exception instanceof \Exception && !$exception instanceof \Throwable) {
+            throw new InvalidArgumentException(sprintf(
+                'Exception / Throwable class or instance expected as argument to ThrowPromise, but got %s.',
+                is_object($exception) ? get_class($exception) : gettype($exception)
+            ));
+        }
+
+        $this->exception = $exception;
+    }
+
+    /**
+     * Throws predefined exception.
+     *
+     * @param array          $args
+     * @param ObjectProphecy $object
+     * @param MethodProphecy $method
+     *
+     * @throws object
+     */
+    public function execute(array $args, ObjectProphecy $object, MethodProphecy $method)
+    {
+        if (is_string($this->exception)) {
+            $classname   = $this->exception;
+            $reflection  = new ReflectionClass($classname);
+            $constructor = $reflection->getConstructor();
+
+            if ($constructor->isPublic() && 0 == $constructor->getNumberOfRequiredParameters()) {
+                throw $reflection->newInstance();
+            }
+
+            if (!$this->instantiator) {
+                $this->instantiator = new Instantiator();
+            }
+
+            throw $this->instantiator->instantiate($classname);
+        }
+
+        throw $this->exception;
+    }
+
+    /**
+     * @param string $exception
+     *
+     * @return bool
+     */
+    private function isAValidThrowable($exception)
+    {
+        return is_a($exception, 'Exception', true)
+            || is_a($exception, 'Throwable', true);
+    }
+}
diff --git a/vendor/phpspec/prophecy/src/Prophecy/Prophecy/MethodProphecy.php b/vendor/phpspec/prophecy/src/Prophecy/Prophecy/MethodProphecy.php
new file mode 100644
index 0000000000000000000000000000000000000000..c2c1913dae261a388d1a6562de0e46870849b959
--- /dev/null
+++ b/vendor/phpspec/prophecy/src/Prophecy/Prophecy/MethodProphecy.php
@@ -0,0 +1,566 @@
+<?php
+
+/*
+ * This file is part of the Prophecy.
+ * (c) Konstantin Kudryashov <ever.zet@gmail.com>
+ *     Marcello Duarte <marcello.duarte@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Prophecy\Prophecy;
+
+use Prophecy\Argument;
+use Prophecy\Prophet;
+use Prophecy\Promise;
+use Prophecy\Prediction;
+use Prophecy\Exception\Doubler\MethodNotFoundException;
+use Prophecy\Exception\InvalidArgumentException;
+use Prophecy\Exception\Prophecy\MethodProphecyException;
+use ReflectionNamedType;
+use ReflectionType;
+use ReflectionUnionType;
+
+/**
+ * Method prophecy.
+ *
+ * @author Konstantin Kudryashov <ever.zet@gmail.com>
+ */
+class MethodProphecy
+{
+    private $objectProphecy;
+    private $methodName;
+    private $argumentsWildcard;
+    private $promise;
+    private $prediction;
+    private $checkedPredictions = array();
+    private $bound = false;
+    private $voidReturnType = false;
+
+    /**
+     * Initializes method prophecy.
+     *
+     * @param ObjectProphecy                        $objectProphecy
+     * @param string                                $methodName
+     * @param null|Argument\ArgumentsWildcard|array $arguments
+     *
+     * @throws \Prophecy\Exception\Doubler\MethodNotFoundException If method not found
+     */
+    public function __construct(ObjectProphecy $objectProphecy, $methodName, $arguments = null)
+    {
+        $double = $objectProphecy->reveal();
+        if (!method_exists($double, $methodName)) {
+            throw new MethodNotFoundException(sprintf(
+                'Method `%s::%s()` is not defined.', get_class($double), $methodName
+            ), get_class($double), $methodName, $arguments);
+        }
+
+        $this->objectProphecy = $objectProphecy;
+        $this->methodName     = $methodName;
+
+        $reflectedMethod = new \ReflectionMethod($double, $methodName);
+        if ($reflectedMethod->isFinal()) {
+            throw new MethodProphecyException(sprintf(
+                "Can not add prophecy for a method `%s::%s()`\n".
+                "as it is a final method.",
+                get_class($double),
+                $methodName
+            ), $this);
+        }
+
+        if (null !== $arguments) {
+            $this->withArguments($arguments);
+        }
+
+        if (true === $reflectedMethod->hasReturnType()) {
+
+            $reflectionType = $reflectedMethod->getReturnType();
+
+            if ($reflectionType instanceof ReflectionNamedType) {
+                $types = [$reflectionType];
+            }
+            elseif ($reflectionType instanceof ReflectionUnionType) {
+                $types = $reflectionType->getTypes();
+            }
+
+            $types = array_map(
+                function(ReflectionType $type) { return $type->getName(); },
+                $types
+            );
+
+            usort(
+                $types,
+                static function(string $type1, string $type2) {
+
+                    // null is lowest priority
+                    if ($type2 == 'null') {
+                        return -1;
+                    }
+                    elseif ($type1 == 'null') {
+                        return 1;
+                    }
+
+                    // objects are higher priority than scalars
+                    $isObject = static function($type) {
+                        return class_exists($type) || interface_exists($type);
+                    };
+
+                    if($isObject($type1) && !$isObject($type2)) {
+                        return -1;
+                    }
+                    elseif(!$isObject($type1) && $isObject($type2))
+                    {
+                        return 1;
+                    }
+
+                    // don't sort both-scalars or both-objects
+                    return 0;
+                }
+            );
+
+            $defaultType = $types[0];
+
+            if ('void' === $defaultType) {
+                $this->voidReturnType = true;
+            }
+
+            $this->will(function () use ($defaultType) {
+                switch ($defaultType) {
+                    case 'void': return;
+                    case 'string': return '';
+                    case 'float':  return 0.0;
+                    case 'int':    return 0;
+                    case 'bool':   return false;
+                    case 'array':  return array();
+
+                    case 'callable':
+                    case 'Closure':
+                        return function () {};
+
+                    case 'Traversable':
+                    case 'Generator':
+                        return (function () { yield; })();
+
+                    default:
+                        $prophet = new Prophet;
+                        return $prophet->prophesize($defaultType)->reveal();
+                }
+            });
+        }
+    }
+
+    /**
+     * Sets argument wildcard.
+     *
+     * @param array|Argument\ArgumentsWildcard $arguments
+     *
+     * @return $this
+     *
+     * @throws \Prophecy\Exception\InvalidArgumentException
+     */
+    public function withArguments($arguments)
+    {
+        if (is_array($arguments)) {
+            $arguments = new Argument\ArgumentsWildcard($arguments);
+        }
+
+        if (!$arguments instanceof Argument\ArgumentsWildcard) {
+            throw new InvalidArgumentException(sprintf(
+                "Either an array or an instance of ArgumentsWildcard expected as\n".
+                'a `MethodProphecy::withArguments()` argument, but got %s.',
+                gettype($arguments)
+            ));
+        }
+
+        $this->argumentsWildcard = $arguments;
+
+        return $this;
+    }
+
+    /**
+     * Sets custom promise to the prophecy.
+     *
+     * @param callable|Promise\PromiseInterface $promise
+     *
+     * @return $this
+     *
+     * @throws \Prophecy\Exception\InvalidArgumentException
+     */
+    public function will($promise)
+    {
+        if (is_callable($promise)) {
+            $promise = new Promise\CallbackPromise($promise);
+        }
+
+        if (!$promise instanceof Promise\PromiseInterface) {
+            throw new InvalidArgumentException(sprintf(
+                'Expected callable or instance of PromiseInterface, but got %s.',
+                gettype($promise)
+            ));
+        }
+
+        $this->bindToObjectProphecy();
+        $this->promise = $promise;
+
+        return $this;
+    }
+
+    /**
+     * Sets return promise to the prophecy.
+     *
+     * @see \Prophecy\Promise\ReturnPromise
+     *
+     * @return $this
+     */
+    public function willReturn()
+    {
+        if ($this->voidReturnType) {
+            throw new MethodProphecyException(
+                "The method \"$this->methodName\" has a void return type, and so cannot return anything",
+                $this
+            );
+        }
+
+        return $this->will(new Promise\ReturnPromise(func_get_args()));
+    }
+
+    /**
+     * @param array $items
+     * @param mixed $return
+     *
+     * @return $this
+     *
+     * @throws \Prophecy\Exception\InvalidArgumentException
+     */
+    public function willYield($items, $return = null)
+    {
+        if ($this->voidReturnType) {
+            throw new MethodProphecyException(
+                "The method \"$this->methodName\" has a void return type, and so cannot yield anything",
+                $this
+            );
+        }
+
+        if (!is_array($items)) {
+            throw new InvalidArgumentException(sprintf(
+                'Expected array, but got %s.',
+                gettype($items)
+            ));
+        }
+
+        $generator =  function() use ($items, $return) {
+            yield from $items;
+
+            return $return;
+        };
+
+        return $this->will($generator);
+    }
+
+    /**
+     * Sets return argument promise to the prophecy.
+     *
+     * @param int $index The zero-indexed number of the argument to return
+     *
+     * @see \Prophecy\Promise\ReturnArgumentPromise
+     *
+     * @return $this
+     */
+    public function willReturnArgument($index = 0)
+    {
+        if ($this->voidReturnType) {
+            throw new MethodProphecyException("The method \"$this->methodName\" has a void return type", $this);
+        }
+
+        return $this->will(new Promise\ReturnArgumentPromise($index));
+    }
+
+    /**
+     * Sets throw promise to the prophecy.
+     *
+     * @see \Prophecy\Promise\ThrowPromise
+     *
+     * @param string|\Exception $exception Exception class or instance
+     *
+     * @return $this
+     */
+    public function willThrow($exception)
+    {
+        return $this->will(new Promise\ThrowPromise($exception));
+    }
+
+    /**
+     * Sets custom prediction to the prophecy.
+     *
+     * @param callable|Prediction\PredictionInterface $prediction
+     *
+     * @return $this
+     *
+     * @throws \Prophecy\Exception\InvalidArgumentException
+     */
+    public function should($prediction)
+    {
+        if (is_callable($prediction)) {
+            $prediction = new Prediction\CallbackPrediction($prediction);
+        }
+
+        if (!$prediction instanceof Prediction\PredictionInterface) {
+            throw new InvalidArgumentException(sprintf(
+                'Expected callable or instance of PredictionInterface, but got %s.',
+                gettype($prediction)
+            ));
+        }
+
+        $this->bindToObjectProphecy();
+        $this->prediction = $prediction;
+
+        return $this;
+    }
+
+    /**
+     * Sets call prediction to the prophecy.
+     *
+     * @see \Prophecy\Prediction\CallPrediction
+     *
+     * @return $this
+     */
+    public function shouldBeCalled()
+    {
+        return $this->should(new Prediction\CallPrediction);
+    }
+
+    /**
+     * Sets no calls prediction to the prophecy.
+     *
+     * @see \Prophecy\Prediction\NoCallsPrediction
+     *
+     * @return $this
+     */
+    public function shouldNotBeCalled()
+    {
+        return $this->should(new Prediction\NoCallsPrediction);
+    }
+
+    /**
+     * Sets call times prediction to the prophecy.
+     *
+     * @see \Prophecy\Prediction\CallTimesPrediction
+     *
+     * @param $count
+     *
+     * @return $this
+     */
+    public function shouldBeCalledTimes($count)
+    {
+        return $this->should(new Prediction\CallTimesPrediction($count));
+    }
+
+    /**
+     * Sets call times prediction to the prophecy.
+     *
+     * @see \Prophecy\Prediction\CallTimesPrediction
+     *
+     * @return $this
+     */
+    public function shouldBeCalledOnce()
+    {
+        return $this->shouldBeCalledTimes(1);
+    }
+
+    /**
+     * Checks provided prediction immediately.
+     *
+     * @param callable|Prediction\PredictionInterface $prediction
+     *
+     * @return $this
+     *
+     * @throws \Prophecy\Exception\InvalidArgumentException
+     */
+    public function shouldHave($prediction)
+    {
+        if (is_callable($prediction)) {
+            $prediction = new Prediction\CallbackPrediction($prediction);
+        }
+
+        if (!$prediction instanceof Prediction\PredictionInterface) {
+            throw new InvalidArgumentException(sprintf(
+                'Expected callable or instance of PredictionInterface, but got %s.',
+                gettype($prediction)
+            ));
+        }
+
+        if (null === $this->promise && !$this->voidReturnType) {
+            $this->willReturn();
+        }
+
+        $calls = $this->getObjectProphecy()->findProphecyMethodCalls(
+            $this->getMethodName(),
+            $this->getArgumentsWildcard()
+        );
+
+        try {
+            $prediction->check($calls, $this->getObjectProphecy(), $this);
+            $this->checkedPredictions[] = $prediction;
+        } catch (\Exception $e) {
+            $this->checkedPredictions[] = $prediction;
+
+            throw $e;
+        }
+
+        return $this;
+    }
+
+    /**
+     * Checks call prediction.
+     *
+     * @see \Prophecy\Prediction\CallPrediction
+     *
+     * @return $this
+     */
+    public function shouldHaveBeenCalled()
+    {
+        return $this->shouldHave(new Prediction\CallPrediction);
+    }
+
+    /**
+     * Checks no calls prediction.
+     *
+     * @see \Prophecy\Prediction\NoCallsPrediction
+     *
+     * @return $this
+     */
+    public function shouldNotHaveBeenCalled()
+    {
+        return $this->shouldHave(new Prediction\NoCallsPrediction);
+    }
+
+    /**
+     * Checks no calls prediction.
+     *
+     * @see \Prophecy\Prediction\NoCallsPrediction
+     * @deprecated
+     *
+     * @return $this
+     */
+    public function shouldNotBeenCalled()
+    {
+        return $this->shouldNotHaveBeenCalled();
+    }
+
+    /**
+     * Checks call times prediction.
+     *
+     * @see \Prophecy\Prediction\CallTimesPrediction
+     *
+     * @param int $count
+     *
+     * @return $this
+     */
+    public function shouldHaveBeenCalledTimes($count)
+    {
+        return $this->shouldHave(new Prediction\CallTimesPrediction($count));
+    }
+
+    /**
+     * Checks call times prediction.
+     *
+     * @see \Prophecy\Prediction\CallTimesPrediction
+     *
+     * @return $this
+     */
+    public function shouldHaveBeenCalledOnce()
+    {
+        return $this->shouldHaveBeenCalledTimes(1);
+    }
+
+    /**
+     * Checks currently registered [with should(...)] prediction.
+     */
+    public function checkPrediction()
+    {
+        if (null === $this->prediction) {
+            return;
+        }
+
+        $this->shouldHave($this->prediction);
+    }
+
+    /**
+     * Returns currently registered promise.
+     *
+     * @return null|Promise\PromiseInterface
+     */
+    public function getPromise()
+    {
+        return $this->promise;
+    }
+
+    /**
+     * Returns currently registered prediction.
+     *
+     * @return null|Prediction\PredictionInterface
+     */
+    public function getPrediction()
+    {
+        return $this->prediction;
+    }
+
+    /**
+     * Returns predictions that were checked on this object.
+     *
+     * @return Prediction\PredictionInterface[]
+     */
+    public function getCheckedPredictions()
+    {
+        return $this->checkedPredictions;
+    }
+
+    /**
+     * Returns object prophecy this method prophecy is tied to.
+     *
+     * @return ObjectProphecy
+     */
+    public function getObjectProphecy()
+    {
+        return $this->objectProphecy;
+    }
+
+    /**
+     * Returns method name.
+     *
+     * @return string
+     */
+    public function getMethodName()
+    {
+        return $this->methodName;
+    }
+
+    /**
+     * Returns arguments wildcard.
+     *
+     * @return Argument\ArgumentsWildcard
+     */
+    public function getArgumentsWildcard()
+    {
+        return $this->argumentsWildcard;
+    }
+
+    /**
+     * @return bool
+     */
+    public function hasReturnVoid()
+    {
+        return $this->voidReturnType;
+    }
+
+    private function bindToObjectProphecy()
+    {
+        if ($this->bound) {
+            return;
+        }
+
+        $this->getObjectProphecy()->addMethodProphecy($this);
+        $this->bound = true;
+    }
+}
diff --git a/vendor/phpspec/prophecy/src/Prophecy/Prophecy/ObjectProphecy.php b/vendor/phpspec/prophecy/src/Prophecy/Prophecy/ObjectProphecy.php
new file mode 100644
index 0000000000000000000000000000000000000000..11b87cf1b2fe3c556509ccafd6d341b2029b4b2e
--- /dev/null
+++ b/vendor/phpspec/prophecy/src/Prophecy/Prophecy/ObjectProphecy.php
@@ -0,0 +1,286 @@
+<?php
+
+/*
+ * This file is part of the Prophecy.
+ * (c) Konstantin Kudryashov <ever.zet@gmail.com>
+ *     Marcello Duarte <marcello.duarte@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Prophecy\Prophecy;
+
+use SebastianBergmann\Comparator\ComparisonFailure;
+use Prophecy\Comparator\Factory as ComparatorFactory;
+use Prophecy\Call\Call;
+use Prophecy\Doubler\LazyDouble;
+use Prophecy\Argument\ArgumentsWildcard;
+use Prophecy\Call\CallCenter;
+use Prophecy\Exception\Prophecy\ObjectProphecyException;
+use Prophecy\Exception\Prophecy\MethodProphecyException;
+use Prophecy\Exception\Prediction\AggregateException;
+use Prophecy\Exception\Prediction\PredictionException;
+
+/**
+ * Object prophecy.
+ *
+ * @author Konstantin Kudryashov <ever.zet@gmail.com>
+ */
+class ObjectProphecy implements ProphecyInterface
+{
+    private $lazyDouble;
+    private $callCenter;
+    private $revealer;
+    private $comparatorFactory;
+
+    /**
+     * @var MethodProphecy[][]
+     */
+    private $methodProphecies = array();
+
+    /**
+     * Initializes object prophecy.
+     *
+     * @param LazyDouble        $lazyDouble
+     * @param CallCenter        $callCenter
+     * @param RevealerInterface $revealer
+     * @param ComparatorFactory $comparatorFactory
+     */
+    public function __construct(
+        LazyDouble $lazyDouble,
+        CallCenter $callCenter = null,
+        RevealerInterface $revealer = null,
+        ComparatorFactory $comparatorFactory = null
+    ) {
+        $this->lazyDouble = $lazyDouble;
+        $this->callCenter = $callCenter ?: new CallCenter;
+        $this->revealer   = $revealer ?: new Revealer;
+
+        $this->comparatorFactory = $comparatorFactory ?: ComparatorFactory::getInstance();
+    }
+
+    /**
+     * Forces double to extend specific class.
+     *
+     * @param string $class
+     *
+     * @return $this
+     */
+    public function willExtend($class)
+    {
+        $this->lazyDouble->setParentClass($class);
+
+        return $this;
+    }
+
+    /**
+     * Forces double to implement specific interface.
+     *
+     * @param string $interface
+     *
+     * @return $this
+     */
+    public function willImplement($interface)
+    {
+        $this->lazyDouble->addInterface($interface);
+
+        return $this;
+    }
+
+    /**
+     * Sets constructor arguments.
+     *
+     * @param array $arguments
+     *
+     * @return $this
+     */
+    public function willBeConstructedWith(array $arguments = null)
+    {
+        $this->lazyDouble->setArguments($arguments);
+
+        return $this;
+    }
+
+    /**
+     * Reveals double.
+     *
+     * @return object
+     *
+     * @throws \Prophecy\Exception\Prophecy\ObjectProphecyException If double doesn't implement needed interface
+     */
+    public function reveal()
+    {
+        $double = $this->lazyDouble->getInstance();
+
+        if (null === $double || !$double instanceof ProphecySubjectInterface) {
+            throw new ObjectProphecyException(
+                "Generated double must implement ProphecySubjectInterface, but it does not.\n".
+                'It seems you have wrongly configured doubler without required ClassPatch.',
+                $this
+            );
+        }
+
+        $double->setProphecy($this);
+
+        return $double;
+    }
+
+    /**
+     * Adds method prophecy to object prophecy.
+     *
+     * @param MethodProphecy $methodProphecy
+     *
+     * @throws \Prophecy\Exception\Prophecy\MethodProphecyException If method prophecy doesn't
+     *                                                              have arguments wildcard
+     */
+    public function addMethodProphecy(MethodProphecy $methodProphecy)
+    {
+        $argumentsWildcard = $methodProphecy->getArgumentsWildcard();
+        if (null === $argumentsWildcard) {
+            throw new MethodProphecyException(sprintf(
+                "Can not add prophecy for a method `%s::%s()`\n".
+                "as you did not specify arguments wildcard for it.",
+                get_class($this->reveal()),
+                $methodProphecy->getMethodName()
+            ), $methodProphecy);
+        }
+
+        $methodName = strtolower($methodProphecy->getMethodName());
+
+        if (!isset($this->methodProphecies[$methodName])) {
+            $this->methodProphecies[$methodName] = array();
+        }
+
+        $this->methodProphecies[$methodName][] = $methodProphecy;
+    }
+
+    /**
+     * Returns either all or related to single method prophecies.
+     *
+     * @param null|string $methodName
+     *
+     * @return MethodProphecy[]
+     */
+    public function getMethodProphecies($methodName = null)
+    {
+        if (null === $methodName) {
+            return $this->methodProphecies;
+        }
+
+        $methodName = strtolower($methodName);
+
+        if (!isset($this->methodProphecies[$methodName])) {
+            return array();
+        }
+
+        return $this->methodProphecies[$methodName];
+    }
+
+    /**
+     * Makes specific method call.
+     *
+     * @param string $methodName
+     * @param array  $arguments
+     *
+     * @return mixed
+     */
+    public function makeProphecyMethodCall($methodName, array $arguments)
+    {
+        $arguments = $this->revealer->reveal($arguments);
+        $return    = $this->callCenter->makeCall($this, $methodName, $arguments);
+
+        return $this->revealer->reveal($return);
+    }
+
+    /**
+     * Finds calls by method name & arguments wildcard.
+     *
+     * @param string            $methodName
+     * @param ArgumentsWildcard $wildcard
+     *
+     * @return Call[]
+     */
+    public function findProphecyMethodCalls($methodName, ArgumentsWildcard $wildcard)
+    {
+        return $this->callCenter->findCalls($methodName, $wildcard);
+    }
+
+    /**
+     * Checks that registered method predictions do not fail.
+     *
+     * @throws \Prophecy\Exception\Prediction\AggregateException If any of registered predictions fail
+     * @throws \Prophecy\Exception\Call\UnexpectedCallException
+     */
+    public function checkProphecyMethodsPredictions()
+    {
+        $exception = new AggregateException(sprintf("%s:\n", get_class($this->reveal())));
+        $exception->setObjectProphecy($this);
+
+        $this->callCenter->checkUnexpectedCalls();
+
+        foreach ($this->methodProphecies as $prophecies) {
+            foreach ($prophecies as $prophecy) {
+                try {
+                    $prophecy->checkPrediction();
+                } catch (PredictionException $e) {
+                    $exception->append($e);
+                }
+            }
+        }
+
+        if (count($exception->getExceptions())) {
+            throw $exception;
+        }
+    }
+
+    /**
+     * Creates new method prophecy using specified method name and arguments.
+     *
+     * @param string $methodName
+     * @param array  $arguments
+     *
+     * @return MethodProphecy
+     */
+    public function __call($methodName, array $arguments)
+    {
+        $arguments = new ArgumentsWildcard($this->revealer->reveal($arguments));
+
+        foreach ($this->getMethodProphecies($methodName) as $prophecy) {
+            $argumentsWildcard = $prophecy->getArgumentsWildcard();
+            $comparator = $this->comparatorFactory->getComparatorFor(
+                $argumentsWildcard, $arguments
+            );
+
+            try {
+                $comparator->assertEquals($argumentsWildcard, $arguments);
+                return $prophecy;
+            } catch (ComparisonFailure $failure) {}
+        }
+
+        return new MethodProphecy($this, $methodName, $arguments);
+    }
+
+    /**
+     * Tries to get property value from double.
+     *
+     * @param string $name
+     *
+     * @return mixed
+     */
+    public function __get($name)
+    {
+        return $this->reveal()->$name;
+    }
+
+    /**
+     * Tries to set property value to double.
+     *
+     * @param string $name
+     * @param mixed  $value
+     */
+    public function __set($name, $value)
+    {
+        $this->reveal()->$name = $this->revealer->reveal($value);
+    }
+}
diff --git a/vendor/phpspec/prophecy/src/Prophecy/Prophecy/ProphecyInterface.php b/vendor/phpspec/prophecy/src/Prophecy/Prophecy/ProphecyInterface.php
new file mode 100644
index 0000000000000000000000000000000000000000..462f15a90275153e99f040ad3378b794c2573a47
--- /dev/null
+++ b/vendor/phpspec/prophecy/src/Prophecy/Prophecy/ProphecyInterface.php
@@ -0,0 +1,27 @@
+<?php
+
+/*
+ * This file is part of the Prophecy.
+ * (c) Konstantin Kudryashov <ever.zet@gmail.com>
+ *     Marcello Duarte <marcello.duarte@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Prophecy\Prophecy;
+
+/**
+ * Core Prophecy interface.
+ *
+ * @author Konstantin Kudryashov <ever.zet@gmail.com>
+ */
+interface ProphecyInterface
+{
+    /**
+     * Reveals prophecy object (double) .
+     *
+     * @return object
+     */
+    public function reveal();
+}
diff --git a/vendor/phpspec/prophecy/src/Prophecy/Prophecy/ProphecySubjectInterface.php b/vendor/phpspec/prophecy/src/Prophecy/Prophecy/ProphecySubjectInterface.php
new file mode 100644
index 0000000000000000000000000000000000000000..2d839585f90c43b255973256066bbd95062bedc4
--- /dev/null
+++ b/vendor/phpspec/prophecy/src/Prophecy/Prophecy/ProphecySubjectInterface.php
@@ -0,0 +1,34 @@
+<?php
+
+/*
+ * This file is part of the Prophecy.
+ * (c) Konstantin Kudryashov <ever.zet@gmail.com>
+ *     Marcello Duarte <marcello.duarte@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Prophecy\Prophecy;
+
+/**
+ * Controllable doubles interface.
+ *
+ * @author Konstantin Kudryashov <ever.zet@gmail.com>
+ */
+interface ProphecySubjectInterface
+{
+    /**
+     * Sets subject prophecy.
+     *
+     * @param ProphecyInterface $prophecy
+     */
+    public function setProphecy(ProphecyInterface $prophecy);
+
+    /**
+     * Returns subject prophecy.
+     *
+     * @return ProphecyInterface
+     */
+    public function getProphecy();
+}
diff --git a/vendor/phpspec/prophecy/src/Prophecy/Prophecy/Revealer.php b/vendor/phpspec/prophecy/src/Prophecy/Prophecy/Revealer.php
new file mode 100644
index 0000000000000000000000000000000000000000..60ecdac814eb1d1e146cea7b903ae9e2fb3108fb
--- /dev/null
+++ b/vendor/phpspec/prophecy/src/Prophecy/Prophecy/Revealer.php
@@ -0,0 +1,44 @@
+<?php
+
+/*
+ * This file is part of the Prophecy.
+ * (c) Konstantin Kudryashov <ever.zet@gmail.com>
+ *     Marcello Duarte <marcello.duarte@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Prophecy\Prophecy;
+
+/**
+ * Basic prophecies revealer.
+ *
+ * @author Konstantin Kudryashov <ever.zet@gmail.com>
+ */
+class Revealer implements RevealerInterface
+{
+    /**
+     * Unwraps value(s).
+     *
+     * @param mixed $value
+     *
+     * @return mixed
+     */
+    public function reveal($value)
+    {
+        if (is_array($value)) {
+            return array_map(array($this, __FUNCTION__), $value);
+        }
+
+        if (!is_object($value)) {
+            return $value;
+        }
+
+        if ($value instanceof ProphecyInterface) {
+            $value = $value->reveal();
+        }
+
+        return $value;
+    }
+}
diff --git a/vendor/phpspec/prophecy/src/Prophecy/Prophecy/RevealerInterface.php b/vendor/phpspec/prophecy/src/Prophecy/Prophecy/RevealerInterface.php
new file mode 100644
index 0000000000000000000000000000000000000000..ffc82bb6f57ada17f1e77119f1cbe352b5855de6
--- /dev/null
+++ b/vendor/phpspec/prophecy/src/Prophecy/Prophecy/RevealerInterface.php
@@ -0,0 +1,29 @@
+<?php
+
+/*
+ * This file is part of the Prophecy.
+ * (c) Konstantin Kudryashov <ever.zet@gmail.com>
+ *     Marcello Duarte <marcello.duarte@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Prophecy\Prophecy;
+
+/**
+ * Prophecies revealer interface.
+ *
+ * @author Konstantin Kudryashov <ever.zet@gmail.com>
+ */
+interface RevealerInterface
+{
+    /**
+     * Unwraps value(s).
+     *
+     * @param mixed $value
+     *
+     * @return mixed
+     */
+    public function reveal($value);
+}
diff --git a/vendor/phpspec/prophecy/src/Prophecy/Prophet.php b/vendor/phpspec/prophecy/src/Prophecy/Prophet.php
new file mode 100644
index 0000000000000000000000000000000000000000..d37c92a343547a9a24ce8ce11149cf86ca4f8cc2
--- /dev/null
+++ b/vendor/phpspec/prophecy/src/Prophecy/Prophet.php
@@ -0,0 +1,138 @@
+<?php
+
+/*
+ * This file is part of the Prophecy.
+ * (c) Konstantin Kudryashov <ever.zet@gmail.com>
+ *     Marcello Duarte <marcello.duarte@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Prophecy;
+
+use Prophecy\Doubler\CachedDoubler;
+use Prophecy\Doubler\Doubler;
+use Prophecy\Doubler\LazyDouble;
+use Prophecy\Doubler\ClassPatch;
+use Prophecy\Prophecy\ObjectProphecy;
+use Prophecy\Prophecy\RevealerInterface;
+use Prophecy\Prophecy\Revealer;
+use Prophecy\Call\CallCenter;
+use Prophecy\Util\StringUtil;
+use Prophecy\Exception\Prediction\PredictionException;
+use Prophecy\Exception\Prediction\AggregateException;
+
+/**
+ * Prophet creates prophecies.
+ *
+ * @author Konstantin Kudryashov <ever.zet@gmail.com>
+ */
+class Prophet
+{
+    private $doubler;
+    private $revealer;
+    private $util;
+
+    /**
+     * @var ObjectProphecy[]
+     */
+    private $prophecies = array();
+
+    /**
+     * Initializes Prophet.
+     *
+     * @param null|Doubler           $doubler
+     * @param null|RevealerInterface $revealer
+     * @param null|StringUtil        $util
+     */
+    public function __construct(
+        Doubler $doubler = null,
+        RevealerInterface $revealer = null,
+        StringUtil $util = null
+    ) {
+        if (null === $doubler) {
+            $doubler = new CachedDoubler();
+            $doubler->registerClassPatch(new ClassPatch\SplFileInfoPatch);
+            $doubler->registerClassPatch(new ClassPatch\TraversablePatch);
+            $doubler->registerClassPatch(new ClassPatch\ThrowablePatch);
+            $doubler->registerClassPatch(new ClassPatch\DisableConstructorPatch);
+            $doubler->registerClassPatch(new ClassPatch\ProphecySubjectPatch);
+            $doubler->registerClassPatch(new ClassPatch\ReflectionClassNewInstancePatch);
+            $doubler->registerClassPatch(new ClassPatch\HhvmExceptionPatch());
+            $doubler->registerClassPatch(new ClassPatch\MagicCallPatch);
+            $doubler->registerClassPatch(new ClassPatch\KeywordPatch);
+        }
+
+        $this->doubler  = $doubler;
+        $this->revealer = $revealer ?: new Revealer;
+        $this->util     = $util ?: new StringUtil;
+    }
+
+    /**
+     * Creates new object prophecy.
+     *
+     * @param null|string $classOrInterface Class or interface name
+     *
+     * @return ObjectProphecy
+     */
+    public function prophesize($classOrInterface = null)
+    {
+        $this->prophecies[] = $prophecy = new ObjectProphecy(
+            new LazyDouble($this->doubler),
+            new CallCenter($this->util),
+            $this->revealer
+        );
+
+        if ($classOrInterface && class_exists($classOrInterface)) {
+            return $prophecy->willExtend($classOrInterface);
+        }
+
+        if ($classOrInterface && interface_exists($classOrInterface)) {
+            return $prophecy->willImplement($classOrInterface);
+        }
+
+        return $prophecy;
+    }
+
+    /**
+     * Returns all created object prophecies.
+     *
+     * @return ObjectProphecy[]
+     */
+    public function getProphecies()
+    {
+        return $this->prophecies;
+    }
+
+    /**
+     * Returns Doubler instance assigned to this Prophet.
+     *
+     * @return Doubler
+     */
+    public function getDoubler()
+    {
+        return $this->doubler;
+    }
+
+    /**
+     * Checks all predictions defined by prophecies of this Prophet.
+     *
+     * @throws Exception\Prediction\AggregateException If any prediction fails
+     */
+    public function checkPredictions()
+    {
+        $exception = new AggregateException("Some predictions failed:\n");
+        foreach ($this->prophecies as $prophecy) {
+            try {
+                $prophecy->checkProphecyMethodsPredictions();
+            } catch (PredictionException $e) {
+                $exception->append($e);
+            }
+        }
+
+        if (count($exception->getExceptions())) {
+            throw $exception;
+        }
+    }
+}
diff --git a/vendor/phpspec/prophecy/src/Prophecy/Util/ExportUtil.php b/vendor/phpspec/prophecy/src/Prophecy/Util/ExportUtil.php
new file mode 100644
index 0000000000000000000000000000000000000000..1090a801e2d6ddbcb18e36c6202fc09fe90c9eda
--- /dev/null
+++ b/vendor/phpspec/prophecy/src/Prophecy/Util/ExportUtil.php
@@ -0,0 +1,210 @@
+<?php
+
+namespace Prophecy\Util;
+
+use Prophecy\Prophecy\ProphecyInterface;
+use SebastianBergmann\RecursionContext\Context;
+
+/*
+ * This file is part of the Prophecy.
+ * (c) Konstantin Kudryashov <ever.zet@gmail.com>
+ *     Marcello Duarte <marcello.duarte@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * This class is a modification from sebastianbergmann/exporter
+ * @see https://github.com/sebastianbergmann/exporter
+ */
+class ExportUtil
+{
+    /**
+     * Exports a value as a string
+     *
+     * The output of this method is similar to the output of print_r(), but
+     * improved in various aspects:
+     *
+     *  - NULL is rendered as "null" (instead of "")
+     *  - TRUE is rendered as "true" (instead of "1")
+     *  - FALSE is rendered as "false" (instead of "")
+     *  - Strings are always quoted with single quotes
+     *  - Carriage returns and newlines are normalized to \n
+     *  - Recursion and repeated rendering is treated properly
+     *
+     * @param  mixed  $value
+     * @param  int    $indentation The indentation level of the 2nd+ line
+     * @return string
+     */
+    public static function export($value, $indentation = 0)
+    {
+        return self::recursiveExport($value, $indentation);
+    }
+
+    /**
+     * Converts an object to an array containing all of its private, protected
+     * and public properties.
+     *
+     * @param  mixed $value
+     * @return array
+     */
+    public static function toArray($value)
+    {
+        if (!is_object($value)) {
+            return (array) $value;
+        }
+
+        $array = array();
+
+        foreach ((array) $value as $key => $val) {
+            // properties are transformed to keys in the following way:
+            // private   $property => "\0Classname\0property"
+            // protected $property => "\0*\0property"
+            // public    $property => "property"
+            if (preg_match('/^\0.+\0(.+)$/', $key, $matches)) {
+                $key = $matches[1];
+            }
+
+            // See https://github.com/php/php-src/commit/5721132
+            if ($key === "\0gcdata") {
+                continue;
+            }
+
+            $array[$key] = $val;
+        }
+
+        // Some internal classes like SplObjectStorage don't work with the
+        // above (fast) mechanism nor with reflection in Zend.
+        // Format the output similarly to print_r() in this case
+        if ($value instanceof \SplObjectStorage) {
+            // However, the fast method does work in HHVM, and exposes the
+            // internal implementation. Hide it again.
+            if (property_exists('\SplObjectStorage', '__storage')) {
+                unset($array['__storage']);
+            } elseif (property_exists('\SplObjectStorage', 'storage')) {
+                unset($array['storage']);
+            }
+
+            if (property_exists('\SplObjectStorage', '__key')) {
+                unset($array['__key']);
+            }
+
+            foreach ($value as $key => $val) {
+                $array[spl_object_hash($val)] = array(
+                    'obj' => $val,
+                    'inf' => $value->getInfo(),
+                );
+            }
+        }
+
+        return $array;
+    }
+
+    /**
+     * Recursive implementation of export
+     *
+     * @param  mixed                                       $value       The value to export
+     * @param  int                                         $indentation The indentation level of the 2nd+ line
+     * @param  \SebastianBergmann\RecursionContext\Context $processed   Previously processed objects
+     * @return string
+     * @see    SebastianBergmann\Exporter\Exporter::export
+     */
+    protected static function recursiveExport(&$value, $indentation, $processed = null)
+    {
+        if ($value === null) {
+            return 'null';
+        }
+
+        if ($value === true) {
+            return 'true';
+        }
+
+        if ($value === false) {
+            return 'false';
+        }
+
+        if (is_float($value) && floatval(intval($value)) === $value) {
+            return "$value.0";
+        }
+
+        if (is_resource($value)) {
+            return sprintf(
+                'resource(%d) of type (%s)',
+                $value,
+                get_resource_type($value)
+            );
+        }
+
+        if (is_string($value)) {
+            // Match for most non printable chars somewhat taking multibyte chars into account
+            if (preg_match('/[^\x09-\x0d\x20-\xff]/', $value)) {
+                return 'Binary String: 0x' . bin2hex($value);
+            }
+
+            return "'" .
+            str_replace(array("\r\n", "\n\r", "\r"), array("\n", "\n", "\n"), $value) .
+            "'";
+        }
+
+        $whitespace = str_repeat(' ', 4 * $indentation);
+
+        if (!$processed) {
+            $processed = new Context;
+        }
+
+        if (is_array($value)) {
+            if (($key = $processed->contains($value)) !== false) {
+                return 'Array &' . $key;
+            }
+
+            $array  = $value;
+            $key    = $processed->add($value);
+            $values = '';
+
+            if (count($array) > 0) {
+                foreach ($array as $k => $v) {
+                    $values .= sprintf(
+                        '%s    %s => %s' . "\n",
+                        $whitespace,
+                        self::recursiveExport($k, $indentation),
+                        self::recursiveExport($value[$k], $indentation + 1, $processed)
+                    );
+                }
+
+                $values = "\n" . $values . $whitespace;
+            }
+
+            return sprintf('Array &%s (%s)', $key, $values);
+        }
+
+        if (is_object($value)) {
+            $class = get_class($value);
+
+            if ($hash = $processed->contains($value)) {
+                return sprintf('%s:%s Object', $class, $hash);
+            }
+
+            $hash   = $processed->add($value);
+            $values = '';
+            $array  = self::toArray($value);
+
+            if (count($array) > 0) {
+                foreach ($array as $k => $v) {
+                    $values .= sprintf(
+                        '%s    %s => %s' . "\n",
+                        $whitespace,
+                        self::recursiveExport($k, $indentation),
+                        self::recursiveExport($v, $indentation + 1, $processed)
+                    );
+                }
+
+                $values = "\n" . $values . $whitespace;
+            }
+
+            return sprintf('%s:%s Object (%s)', $class, $hash, $values);
+        }
+
+        return var_export($value, true);
+    }
+}
diff --git a/vendor/phpspec/prophecy/src/Prophecy/Util/StringUtil.php b/vendor/phpspec/prophecy/src/Prophecy/Util/StringUtil.php
new file mode 100644
index 0000000000000000000000000000000000000000..ba4faff57a4b3735a60ce1eede14b836de5b2ee3
--- /dev/null
+++ b/vendor/phpspec/prophecy/src/Prophecy/Util/StringUtil.php
@@ -0,0 +1,99 @@
+<?php
+
+/*
+ * This file is part of the Prophecy.
+ * (c) Konstantin Kudryashov <ever.zet@gmail.com>
+ *     Marcello Duarte <marcello.duarte@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Prophecy\Util;
+
+use Prophecy\Call\Call;
+
+/**
+ * String utility.
+ *
+ * @author Konstantin Kudryashov <ever.zet@gmail.com>
+ */
+class StringUtil
+{
+    private $verbose;
+
+    /**
+     * @param bool $verbose
+     */
+    public function __construct($verbose = true)
+    {
+        $this->verbose = $verbose;
+    }
+
+    /**
+     * Stringifies any provided value.
+     *
+     * @param mixed   $value
+     * @param boolean $exportObject
+     *
+     * @return string
+     */
+    public function stringify($value, $exportObject = true)
+    {
+        if (is_array($value)) {
+            if (range(0, count($value) - 1) === array_keys($value)) {
+                return '['.implode(', ', array_map(array($this, __FUNCTION__), $value)).']';
+            }
+
+            $stringify = array($this, __FUNCTION__);
+
+            return '['.implode(', ', array_map(function ($item, $key) use ($stringify) {
+                return (is_integer($key) ? $key : '"'.$key.'"').
+                    ' => '.call_user_func($stringify, $item);
+            }, $value, array_keys($value))).']';
+        }
+        if (is_resource($value)) {
+            return get_resource_type($value).':'.$value;
+        }
+        if (is_object($value)) {
+            return $exportObject ? ExportUtil::export($value) : sprintf('%s:%s', get_class($value), spl_object_hash($value));
+        }
+        if (true === $value || false === $value) {
+            return $value ? 'true' : 'false';
+        }
+        if (is_string($value)) {
+            $str = sprintf('"%s"', str_replace("\n", '\\n', $value));
+
+            if (!$this->verbose && 50 <= strlen($str)) {
+                return substr($str, 0, 50).'"...';
+            }
+
+            return $str;
+        }
+        if (null === $value) {
+            return 'null';
+        }
+
+        return (string) $value;
+    }
+
+    /**
+     * Stringifies provided array of calls.
+     *
+     * @param Call[] $calls Array of Call instances
+     *
+     * @return string
+     */
+    public function stringifyCalls(array $calls)
+    {
+        $self = $this;
+
+        return implode(PHP_EOL, array_map(function (Call $call) use ($self) {
+            return sprintf('  - %s(%s) @ %s',
+                $call->getMethodName(),
+                implode(', ', array_map(array($self, 'stringify'), $call->getArguments())),
+                str_replace(GETCWD().DIRECTORY_SEPARATOR, '', $call->getCallPlace())
+            );
+        }, $calls));
+    }
+}
diff --git a/vendor/phpunit/php-code-coverage/ChangeLog.md b/vendor/phpunit/php-code-coverage/ChangeLog.md
new file mode 100644
index 0000000000000000000000000000000000000000..49b6403faba47a253646971a04e2ac91fb5af691
--- /dev/null
+++ b/vendor/phpunit/php-code-coverage/ChangeLog.md
@@ -0,0 +1,359 @@
+# ChangeLog
+
+All notable changes are documented in this file using the [Keep a CHANGELOG](http://keepachangelog.com/) principles.
+
+## [9.2.5] - 2020-11-28
+
+### Fixed
+
+* [#831](https://github.com/sebastianbergmann/php-code-coverage/issues/831): Files that do not contain a newline are not handled correctly
+
+## [9.2.4] - 2020-11-27
+
+### Added
+
+* [#834](https://github.com/sebastianbergmann/php-code-coverage/issues/834): Support `XDEBUG_MODE` environment variable
+
+## [9.2.3] - 2020-10-30
+
+### Changed
+
+* Bumped required version of `nikic/php-parser`
+
+## [9.2.2] - 2020-10-28
+
+### Fixed
+
+* [#820](https://github.com/sebastianbergmann/php-code-coverage/issues/820): Hidden dependency on PHPUnit
+
+## [9.2.1] - 2020-10-26
+
+### Fixed
+
+* `SebastianBergmann\CodeCoverage\Exception` now correctly extends `\Throwable`
+
+## [9.2.0] - 2020-10-02
+
+### Added
+
+* [#812](https://github.com/sebastianbergmann/php-code-coverage/pull/812): Support for Cobertura XML report format
+
+### Changed
+
+* Reduced the number of I/O operations performed by the static analysis cache
+
+## [9.1.11] - 2020-09-19
+
+### Fixed
+
+* [#811](https://github.com/sebastianbergmann/php-code-coverage/issues/811): `T_FN` constant is used on PHP 7.3 where it is not available
+
+## [9.1.10] - 2020-09-18
+
+### Added
+
+* `SebastianBergmann\CodeCoverage\Driver\Selector::forLineCoverage()` and `SebastianBergmann\CodeCoverage\Driver\Selector::forLineAndPathCoverage()` have been added
+
+### Fixed
+
+* [#810](https://github.com/sebastianbergmann/php-code-coverage/issues/810): `SebastianBergmann\CodeCoverage\Driver\Driver::forLineCoverage()` and `SebastianBergmann\CodeCoverage\Driver\Driver::forLineAndPathCoverage()` are marked as internal 
+
+### Removed
+
+* `SebastianBergmann\CodeCoverage\Driver\Driver::forLineCoverage()` and `SebastianBergmann\CodeCoverage\Driver\Driver::forLineAndPathCoverage()` are now deprecated
+
+## [9.1.9] - 2020-09-15
+
+### Fixed
+
+* [#808](https://github.com/sebastianbergmann/php-code-coverage/issues/808): `PHP Warning: Use of undefined constant T_MATCH`
+
+## [9.1.8] - 2020-09-07
+
+### Changed
+
+* [#800](https://github.com/sebastianbergmann/php-code-coverage/pull/800): All files on the inclusion list are no longer loaded when `SebastianBergmann\CodeCoverage::start()` is called for the first time and `processUncoveredFiles` is set to `true`
+
+### Fixed
+
+* [#799](https://github.com/sebastianbergmann/php-code-coverage/issues/799): Uncovered new line at end of file
+
+## [9.1.7] - 2020-09-03
+
+### Fixed
+
+* Fixed regressions introduced in versions 9.1.5 and 9.1.6
+
+## [9.1.6] - 2020-08-31
+
+### Fixed
+
+* [#799](https://github.com/sebastianbergmann/php-code-coverage/issues/799): Uncovered new line at end of file
+* [#803](https://github.com/sebastianbergmann/php-code-coverage/issues/803): HTML report does not sort directories and files anymore
+
+## [9.1.5] - 2020-08-27
+
+### Changed
+
+* [#800](https://github.com/sebastianbergmann/php-code-coverage/pull/800): All files on the inclusion list are no longer loaded when `SebastianBergmann\CodeCoverage::start()` is called for the first time and `processUncoveredFiles` is set to `true`
+
+### Fixed
+
+* [#797](https://github.com/sebastianbergmann/php-code-coverage/pull/797): Class name is wrongly removed from namespace name
+
+## [9.1.4] - 2020-08-13
+
+### Fixed
+
+* [#793](https://github.com/sebastianbergmann/php-code-coverage/issues/793): Lines with `::class` constant are not covered
+
+## [9.1.3] - 2020-08-10
+
+### Changed
+
+* Changed PHP-Parser usage to parse sourcecode according to the PHP version we are currently running on instead of using emulative lexing
+
+## [9.1.2] - 2020-08-10
+
+### Fixed
+
+* [#791](https://github.com/sebastianbergmann/php-code-coverage/pull/791): Cache Warmer does not warm all caches
+
+## [9.1.1] - 2020-08-10
+
+### Added
+
+* Added `SebastianBergmann\CodeCoverage::cacheDirectory()` method for querying where the cache writes its files
+
+## [9.1.0] - 2020-08-10
+
+### Added
+
+* Implemented a persistent cache for information gathered using PHP-Parser based static analysis (hereinafter referred to as "cache")
+* Added `SebastianBergmann\CodeCoverage::cacheStaticAnalysis(string $cacheDirectory)` method for enabling the cache; it will write its files to `$directory`
+* Added `SebastianBergmann\CodeCoverage::doNotCacheStaticAnalysis` method for disabling the cache
+* Added `SebastianBergmann\CodeCoverage::cachesStaticAnalysis()` method for querying whether the cache is enabled
+* Added `SebastianBergmann\CodeCoverage\StaticAnalysis\CacheWarmer::warmCache()` method for warming the cache
+
+## [9.0.0] - 2020-08-07
+
+### Added
+
+* [#761](https://github.com/sebastianbergmann/php-code-coverage/pull/761): Support for Branch Coverage and Path Coverage
+* Added `SebastianBergmann\CodeCoverage\Driver\Driver::forLineCoverage()` for selecting the best available driver for line coverage
+* Added `SebastianBergmann\CodeCoverage\Driver\Driver::forLineAndPathCoverage()` for selecting the best available driver for path coverage
+* This component is now supported on PHP 8
+* This component now supports Xdebug 3
+
+### Changed
+
+* [#746](https://github.com/sebastianbergmann/php-code-coverage/pull/746): Remove some ancient workarounds for very old Xdebug versions
+* [#747](https://github.com/sebastianbergmann/php-code-coverage/pull/747): Use native filtering in PCOV and Xdebug drivers
+* [#748](https://github.com/sebastianbergmann/php-code-coverage/pull/748): Store raw code coverage in value objects instead of arrays
+* [#749](https://github.com/sebastianbergmann/php-code-coverage/pull/749): Store processed code coverage in value objects instead of arrays
+* [#752](https://github.com/sebastianbergmann/php-code-coverage/pull/752): Rework how code coverage settings are propagated to the driver
+* [#754](https://github.com/sebastianbergmann/php-code-coverage/pull/754): Implement collection of raw branch and path coverage
+* [#755](https://github.com/sebastianbergmann/php-code-coverage/pull/755): Implement processing of raw branch and path coverage
+* [#756](https://github.com/sebastianbergmann/php-code-coverage/pull/756): Improve handling of uncovered files
+* `SebastianBergmann\CodeCoverage\Filter::addDirectoryToWhitelist()` has been renamed to `SebastianBergmann\CodeCoverage\Filter::includeDirectory()`
+* `SebastianBergmann\CodeCoverage\Filter::addFilesToWhitelist()` has been renamed to `SebastianBergmann\CodeCoverage\Filter::includeFiles()`
+* `SebastianBergmann\CodeCoverage\Filter::addFileToWhitelist()` has been renamed to `SebastianBergmann\CodeCoverage\Filter::includeFile()`
+* `SebastianBergmann\CodeCoverage\Filter::removeDirectoryFromWhitelist()` has been renamed to `SebastianBergmann\CodeCoverage\Filter::excludeDirectory()`
+* `SebastianBergmann\CodeCoverage\Filter::removeFileFromWhitelist()` has been renamed to `SebastianBergmann\CodeCoverage\Filter::excludeFile()`
+* `SebastianBergmann\CodeCoverage\Filter::isFiltered()` has been renamed to `SebastianBergmann\CodeCoverage\Filter::isExcluded()`
+* `SebastianBergmann\CodeCoverage\Filter::getWhitelist()` has been renamed to `SebastianBergmann\CodeCoverage\Filter::files()`
+* The arguments for `CodeCoverage::__construct()` are no longer optional
+
+### Fixed
+
+* [#700](https://github.com/sebastianbergmann/php-code-coverage/pull/700): Throw an exception if code coverage fails to write to disk
+
+### Removed
+
+* `SebastianBergmann\CodeCoverage\CodeCoverage::setCacheTokens()` and `SebastianBergmann\CodeCoverage\CodeCoverage::getCacheTokens()` have been removed
+* `SebastianBergmann\CodeCoverage\CodeCoverage::setCheckForUnintentionallyCoveredCode()` has been removed, please use `SebastianBergmann\CodeCoverage\CodeCoverage::enableCheckForUnintentionallyCoveredCode()` or `SebastianBergmann\CodeCoverage\CodeCoverage::disableCheckForUnintentionallyCoveredCode()` instead
+* `SebastianBergmann\CodeCoverage\CodeCoverage::setSubclassesExcludedFromUnintentionallyCoveredCodeCheck()` has been removed, please use `SebastianBergmann\CodeCoverage\CodeCoverage::excludeSubclassesOfThisClassFromUnintentionallyCoveredCodeCheck()` instead
+* `SebastianBergmann\CodeCoverage\CodeCoverage::setAddUncoveredFilesFromWhitelist()` has been removed, please use `SebastianBergmann\CodeCoverage\CodeCoverage::includeUncoveredFiles()` or `SebastianBergmann\CodeCoverage\CodeCoverage::excludeUncoveredFiles()` instead
+* `SebastianBergmann\CodeCoverage\CodeCoverage::setProcessUncoveredFiles()` has been removed, please use `SebastianBergmann\CodeCoverage\CodeCoverage::processUncoveredFiles()` or `SebastianBergmann\CodeCoverage\CodeCoverage::doNotProcessUncoveredFiles()` instead
+* `SebastianBergmann\CodeCoverage\CodeCoverage::setIgnoreDeprecatedCode()` has been removed, please use `SebastianBergmann\CodeCoverage\CodeCoverage::ignoreDeprecatedCode()` or `SebastianBergmann\CodeCoverage\CodeCoverage::doNotIgnoreDeprecatedCode()` instead
+* `SebastianBergmann\CodeCoverage\CodeCoverage::setDisableIgnoredLines()` has been removed, please use `SebastianBergmann\CodeCoverage\CodeCoverage::enableAnnotationsForIgnoringCode()` or `SebastianBergmann\CodeCoverage\CodeCoverage::disableAnnotationsForIgnoringCode()` instead
+* `SebastianBergmann\CodeCoverage\CodeCoverage::setCheckForMissingCoversAnnotation()` has been removed
+* `SebastianBergmann\CodeCoverage\CodeCoverage::setCheckForUnexecutedCoveredCode()` has been removed
+* `SebastianBergmann\CodeCoverage\CodeCoverage::setForceCoversAnnotation()` has been removed
+* `SebastianBergmann\CodeCoverage\Filter::hasWhitelist()` has been removed, please use `SebastianBergmann\CodeCoverage\Filter::isEmpty()` instead
+* `SebastianBergmann\CodeCoverage\Filter::getWhitelistedFiles()` has been removed
+* `SebastianBergmann\CodeCoverage\Filter::setWhitelistedFiles()` has been removed
+
+## [8.0.2] - 2020-05-23
+
+### Fixed
+
+* [#750](https://github.com/sebastianbergmann/php-code-coverage/pull/750): Inconsistent handling of namespaces
+* [#751](https://github.com/sebastianbergmann/php-code-coverage/pull/751): Dead code is not highlighted correctly
+* [#753](https://github.com/sebastianbergmann/php-code-coverage/issues/753): Do not use `$_SERVER['REQUEST_TIME']` because the test(ed) code might unset it
+
+## [8.0.1] - 2020-02-19
+
+### Fixed
+
+* [#731](https://github.com/sebastianbergmann/php-code-coverage/pull/731): Confusing footer in the HTML report
+
+## [8.0.0] - 2020-02-07
+
+### Fixed
+
+* [#721](https://github.com/sebastianbergmann/php-code-coverage/pull/721): Workaround for PHP bug [#79191](https://bugs.php.net/bug.php?id=79191)
+
+### Removed
+
+* This component is no longer supported on PHP 7.2
+
+## [7.0.10] - 2019-11-20
+
+### Fixed
+
+* [#710](https://github.com/sebastianbergmann/php-code-coverage/pull/710): Code Coverage does not work in PhpStorm
+
+## [7.0.9] - 2019-11-20
+
+### Changed
+
+* [#709](https://github.com/sebastianbergmann/php-code-coverage/pull/709): Prioritize PCOV over Xdebug
+
+## [7.0.8] - 2019-09-17
+
+### Changed
+
+* Update HTML report Bootstrap 4.3.1, jQuery 3.4.1, and popper.js 1.15.0
+
+## [7.0.7] - 2019-07-25
+
+### Changed
+
+* Bumped required version of php-token-stream
+
+## [7.0.6] - 2019-07-08
+
+### Changed
+
+* Bumped required version of php-token-stream
+
+## [7.0.5] - 2019-06-06
+
+### Fixed
+
+* [#681](https://github.com/sebastianbergmann/php-code-coverage/pull/681): `use function` statements are not ignored
+
+## [7.0.4] - 2019-05-29
+
+### Fixed
+
+* [#682](https://github.com/sebastianbergmann/php-code-coverage/pull/682): Code that is not executed is reported as being executed when using PCOV
+
+## [7.0.3] - 2019-02-26
+
+### Fixed
+
+* [#671](https://github.com/sebastianbergmann/php-code-coverage/issues/671): `TypeError` when directory name is a number
+
+## [7.0.2] - 2019-02-15
+
+### Changed
+
+* Updated HTML report to Bootstrap 4.3.0
+
+### Fixed
+
+* [#667](https://github.com/sebastianbergmann/php-code-coverage/pull/667): `TypeError` in PHP reporter
+
+## [7.0.1] - 2019-02-01
+
+### Fixed
+
+* [#664](https://github.com/sebastianbergmann/php-code-coverage/issues/664): `TypeError` when whitelisted file does not exist
+
+## [7.0.0] - 2019-02-01
+
+### Added
+
+* [#663](https://github.com/sebastianbergmann/php-code-coverage/pull/663): Support for PCOV
+
+### Fixed
+
+* [#654](https://github.com/sebastianbergmann/php-code-coverage/issues/654): HTML report fails to load assets
+* [#655](https://github.com/sebastianbergmann/php-code-coverage/issues/655): Popin pops in outside of screen
+
+### Removed
+
+* This component is no longer supported on PHP 7.1
+
+## [6.1.4] - 2018-10-31
+
+### Fixed
+
+* [#650](https://github.com/sebastianbergmann/php-code-coverage/issues/650): Wasted screen space in HTML code coverage report
+
+## [6.1.3] - 2018-10-23
+
+### Changed
+
+* Use `^3.1` of `sebastian/environment` again due to [regression](https://github.com/sebastianbergmann/environment/issues/31)
+
+## [6.1.2] - 2018-10-23
+
+### Fixed
+
+* [#645](https://github.com/sebastianbergmann/php-code-coverage/pull/645): Crash that can occur when php-token-stream parses invalid files
+
+## [6.1.1] - 2018-10-18
+
+### Changed
+
+* This component now allows `^4` of `sebastian/environment`
+
+## [6.1.0] - 2018-10-16
+
+### Changed
+
+* Class names are now abbreviated (unqualified name shown, fully qualified name shown on hover) in the file view of the HTML report
+* Update HTML report to Bootstrap 4
+
+[9.2.5]: https://github.com/sebastianbergmann/php-code-coverage/compare/9.2.4...9.2.5
+[9.2.4]: https://github.com/sebastianbergmann/php-code-coverage/compare/9.2.3...9.2.4
+[9.2.3]: https://github.com/sebastianbergmann/php-code-coverage/compare/9.2.2...9.2.3
+[9.2.2]: https://github.com/sebastianbergmann/php-code-coverage/compare/9.2.1...9.2.2
+[9.2.1]: https://github.com/sebastianbergmann/php-code-coverage/compare/9.2.0...9.2.1
+[9.2.0]: https://github.com/sebastianbergmann/php-code-coverage/compare/9.1.11...9.2.0
+[9.1.11]: https://github.com/sebastianbergmann/php-code-coverage/compare/9.1.10...9.1.11
+[9.1.10]: https://github.com/sebastianbergmann/php-code-coverage/compare/9.1.9...9.1.10
+[9.1.9]: https://github.com/sebastianbergmann/php-code-coverage/compare/9.1.8...9.1.9
+[9.1.8]: https://github.com/sebastianbergmann/php-code-coverage/compare/9.1.7...9.1.8
+[9.1.7]: https://github.com/sebastianbergmann/php-code-coverage/compare/9.1.6...9.1.7
+[9.1.6]: https://github.com/sebastianbergmann/php-code-coverage/compare/9.1.5...9.1.6
+[9.1.5]: https://github.com/sebastianbergmann/php-code-coverage/compare/9.1.4...9.1.5
+[9.1.4]: https://github.com/sebastianbergmann/php-code-coverage/compare/9.1.3...9.1.4
+[9.1.3]: https://github.com/sebastianbergmann/php-code-coverage/compare/9.1.2...9.1.3
+[9.1.2]: https://github.com/sebastianbergmann/php-code-coverage/compare/9.1.1...9.1.2
+[9.1.1]: https://github.com/sebastianbergmann/php-code-coverage/compare/9.1.0...9.1.1
+[9.1.0]: https://github.com/sebastianbergmann/php-code-coverage/compare/9.0.0...9.1.0
+[9.0.0]: https://github.com/sebastianbergmann/php-code-coverage/compare/8.0...9.0.0
+[8.0.2]: https://github.com/sebastianbergmann/php-code-coverage/compare/8.0.1...8.0.2
+[8.0.1]: https://github.com/sebastianbergmann/php-code-coverage/compare/8.0.0...8.0.1
+[8.0.0]: https://github.com/sebastianbergmann/php-code-coverage/compare/7.0.10...8.0.0
+[7.0.10]: https://github.com/sebastianbergmann/php-code-coverage/compare/7.0.9...7.0.10
+[7.0.9]: https://github.com/sebastianbergmann/php-code-coverage/compare/7.0.8...7.0.9
+[7.0.8]: https://github.com/sebastianbergmann/php-code-coverage/compare/7.0.7...7.0.8
+[7.0.7]: https://github.com/sebastianbergmann/php-code-coverage/compare/7.0.6...7.0.7
+[7.0.6]: https://github.com/sebastianbergmann/php-code-coverage/compare/7.0.5...7.0.6
+[7.0.5]: https://github.com/sebastianbergmann/php-code-coverage/compare/7.0.4...7.0.5
+[7.0.4]: https://github.com/sebastianbergmann/php-code-coverage/compare/7.0.3...7.0.4
+[7.0.3]: https://github.com/sebastianbergmann/php-code-coverage/compare/7.0.2...7.0.3
+[7.0.2]: https://github.com/sebastianbergmann/php-code-coverage/compare/7.0.1...7.0.2
+[7.0.1]: https://github.com/sebastianbergmann/php-code-coverage/compare/7.0.0...7.0.1
+[7.0.0]: https://github.com/sebastianbergmann/php-code-coverage/compare/6.1.4...7.0.0
+[6.1.4]: https://github.com/sebastianbergmann/php-code-coverage/compare/6.1.3...6.1.4
+[6.1.3]: https://github.com/sebastianbergmann/php-code-coverage/compare/6.1.2...6.1.3
+[6.1.2]: https://github.com/sebastianbergmann/php-code-coverage/compare/6.1.1...6.1.2
+[6.1.1]: https://github.com/sebastianbergmann/php-code-coverage/compare/6.1.0...6.1.1
+[6.1.0]: https://github.com/sebastianbergmann/php-code-coverage/compare/6.0...6.1.0
+
diff --git a/vendor/phpunit/php-code-coverage/LICENSE b/vendor/phpunit/php-code-coverage/LICENSE
new file mode 100644
index 0000000000000000000000000000000000000000..34bc89d95327695adc26b713a541723b15b2487f
--- /dev/null
+++ b/vendor/phpunit/php-code-coverage/LICENSE
@@ -0,0 +1,33 @@
+php-code-coverage
+
+Copyright (c) 2009-2020, Sebastian Bergmann <sebastian@phpunit.de>.
+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 Sebastian Bergmann nor the names of his
+   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/phpunit/php-code-coverage/README.md b/vendor/phpunit/php-code-coverage/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..53ce9b33864988ad054f93e5bd0c4e63886f73f3
--- /dev/null
+++ b/vendor/phpunit/php-code-coverage/README.md
@@ -0,0 +1,48 @@
+# phpunit/php-code-coverage
+
+[![Latest Stable Version](https://poser.pugx.org/phpunit/php-code-coverage/v/stable.png)](https://packagist.org/packages/phpunit/php-code-coverage)
+[![CI Status](https://github.com/sebastianbergmann/php-code-coverage/workflows/CI/badge.svg)](https://github.com/sebastianbergmann/php-code-coverage/actions)
+[![Type Coverage](https://shepherd.dev/github/sebastianbergmann/php-code-coverage/coverage.svg)](https://shepherd.dev/github/sebastianbergmann/php-code-coverage)
+
+Provides collection, processing, and rendering functionality for PHP code coverage information.
+
+## Installation
+
+You can add this library as a local, per-project dependency to your project using [Composer](https://getcomposer.org/):
+
+```
+composer require phpunit/php-code-coverage
+```
+
+If you only need this library during development, for instance to run your project's test suite, then you should add it as a development-time dependency:
+
+```
+composer require --dev phpunit/php-code-coverage
+```
+
+## Usage
+
+```php
+<?php declare(strict_types=1);
+use SebastianBergmann\CodeCoverage\Filter;
+use SebastianBergmann\CodeCoverage\Driver\Selector;
+use SebastianBergmann\CodeCoverage\CodeCoverage;
+use SebastianBergmann\CodeCoverage\Report\Html\Facade as HtmlReport;
+
+$filter = new Filter;
+$filter->includeDirectory('/path/to/directory');
+
+$coverage = new CodeCoverage(
+    (new Selector)->forLineCoverage($filter),
+    $filter
+);
+
+$coverage->start('<name of test>');
+
+// ...
+
+$coverage->stop();
+
+
+(new HtmlReport)->process($coverage, '/tmp/code-coverage-report');
+```
diff --git a/vendor/phpunit/php-code-coverage/composer.json b/vendor/phpunit/php-code-coverage/composer.json
new file mode 100644
index 0000000000000000000000000000000000000000..fbc108118f963ad6fb5b9e1c859ee9c91bf1339a
--- /dev/null
+++ b/vendor/phpunit/php-code-coverage/composer.json
@@ -0,0 +1,68 @@
+{
+    "name": "phpunit/php-code-coverage",
+    "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.",
+    "type": "library",
+    "keywords": [
+        "coverage",
+        "testing",
+        "xunit"
+    ],
+    "homepage": "https://github.com/sebastianbergmann/php-code-coverage",
+    "license": "BSD-3-Clause",
+    "authors": [
+        {
+            "name": "Sebastian Bergmann",
+            "email": "sebastian@phpunit.de",
+            "role": "lead"
+        }
+    ],
+    "support": {
+        "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues"
+    },
+    "config": {
+        "platform": {
+            "php": "7.3.0"
+        },
+        "optimize-autoloader": true,
+        "sort-packages": true
+    },
+    "prefer-stable": true,
+    "require": {
+        "php": ">=7.3",
+        "ext-dom": "*",
+        "ext-libxml": "*",
+        "ext-xmlwriter": "*",
+        "nikic/php-parser": "^4.10.2",
+        "phpunit/php-file-iterator": "^3.0.3",
+        "phpunit/php-text-template": "^2.0.2",
+        "sebastian/code-unit-reverse-lookup": "^2.0.2",
+        "sebastian/complexity": "^2.0",
+        "sebastian/environment": "^5.1.2",
+        "sebastian/lines-of-code": "^1.0.3",
+        "sebastian/version": "^3.0.1",
+        "theseer/tokenizer": "^1.2.0"
+    },
+    "require-dev": {
+        "phpunit/phpunit": "^9.3"
+    },
+    "suggest": {
+        "ext-pcov": "*",
+        "ext-xdebug": "*"
+    },
+    "autoload": {
+        "classmap": [
+            "src/"
+        ]
+    },
+    "autoload-dev": {
+        "files": [
+            "tests/TestCase.php",
+            "tests/_files/BankAccountTest.php"
+        ]
+    },
+    "extra": {
+        "branch-alias": {
+            "dev-master": "9.2-dev"
+        }
+    }
+}
diff --git a/vendor/phpunit/php-code-coverage/src/CodeCoverage.php b/vendor/phpunit/php-code-coverage/src/CodeCoverage.php
new file mode 100644
index 0000000000000000000000000000000000000000..314bd968a9235a2f7213d287051aa37813cfa0e0
--- /dev/null
+++ b/vendor/phpunit/php-code-coverage/src/CodeCoverage.php
@@ -0,0 +1,685 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of phpunit/php-code-coverage.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\CodeCoverage;
+
+use function array_diff;
+use function array_diff_key;
+use function array_flip;
+use function array_keys;
+use function array_merge;
+use function array_unique;
+use function array_values;
+use function count;
+use function explode;
+use function get_class;
+use function is_array;
+use function is_file;
+use function sort;
+use PHPUnit\Framework\TestCase;
+use PHPUnit\Runner\PhptTestCase;
+use PHPUnit\Util\Test;
+use ReflectionClass;
+use SebastianBergmann\CodeCoverage\Driver\Driver;
+use SebastianBergmann\CodeCoverage\Node\Builder;
+use SebastianBergmann\CodeCoverage\Node\Directory;
+use SebastianBergmann\CodeCoverage\StaticAnalysis\CachingCoveredFileAnalyser;
+use SebastianBergmann\CodeCoverage\StaticAnalysis\CachingUncoveredFileAnalyser;
+use SebastianBergmann\CodeCoverage\StaticAnalysis\CoveredFileAnalyser;
+use SebastianBergmann\CodeCoverage\StaticAnalysis\ParsingCoveredFileAnalyser;
+use SebastianBergmann\CodeCoverage\StaticAnalysis\ParsingUncoveredFileAnalyser;
+use SebastianBergmann\CodeCoverage\StaticAnalysis\UncoveredFileAnalyser;
+use SebastianBergmann\CodeUnitReverseLookup\Wizard;
+
+/**
+ * Provides collection functionality for PHP code coverage information.
+ */
+final class CodeCoverage
+{
+    private const UNCOVERED_FILES = 'UNCOVERED_FILES';
+
+    /**
+     * @var Driver
+     */
+    private $driver;
+
+    /**
+     * @var Filter
+     */
+    private $filter;
+
+    /**
+     * @var Wizard
+     */
+    private $wizard;
+
+    /**
+     * @var bool
+     */
+    private $checkForUnintentionallyCoveredCode = false;
+
+    /**
+     * @var bool
+     */
+    private $includeUncoveredFiles = true;
+
+    /**
+     * @var bool
+     */
+    private $processUncoveredFiles = false;
+
+    /**
+     * @var bool
+     */
+    private $ignoreDeprecatedCode = false;
+
+    /**
+     * @var PhptTestCase|string|TestCase
+     */
+    private $currentId;
+
+    /**
+     * Code coverage data.
+     *
+     * @var ProcessedCodeCoverageData
+     */
+    private $data;
+
+    /**
+     * @var bool
+     */
+    private $useAnnotationsForIgnoringCode = true;
+
+    /**
+     * Test data.
+     *
+     * @var array
+     */
+    private $tests = [];
+
+    /**
+     * @psalm-var list<class-string>
+     */
+    private $parentClassesExcludedFromUnintentionallyCoveredCodeCheck = [];
+
+    /**
+     * @var ?CoveredFileAnalyser
+     */
+    private $coveredFileAnalyser;
+
+    /**
+     * @var ?UncoveredFileAnalyser
+     */
+    private $uncoveredFileAnalyser;
+
+    /**
+     * @var ?string
+     */
+    private $cacheDirectory;
+
+    public function __construct(Driver $driver, Filter $filter)
+    {
+        $this->driver = $driver;
+        $this->filter = $filter;
+        $this->data   = new ProcessedCodeCoverageData;
+        $this->wizard = new Wizard;
+    }
+
+    /**
+     * Returns the code coverage information as a graph of node objects.
+     */
+    public function getReport(): Directory
+    {
+        return (new Builder($this->coveredFileAnalyser()))->build($this);
+    }
+
+    /**
+     * Clears collected code coverage data.
+     */
+    public function clear(): void
+    {
+        $this->currentId = null;
+        $this->data      = new ProcessedCodeCoverageData;
+        $this->tests     = [];
+    }
+
+    /**
+     * Returns the filter object used.
+     */
+    public function filter(): Filter
+    {
+        return $this->filter;
+    }
+
+    /**
+     * Returns the collected code coverage data.
+     */
+    public function getData(bool $raw = false): ProcessedCodeCoverageData
+    {
+        if (!$raw) {
+            if ($this->processUncoveredFiles) {
+                $this->processUncoveredFilesFromFilter();
+            } elseif ($this->includeUncoveredFiles) {
+                $this->addUncoveredFilesFromFilter();
+            }
+        }
+
+        return $this->data;
+    }
+
+    /**
+     * Sets the coverage data.
+     */
+    public function setData(ProcessedCodeCoverageData $data): void
+    {
+        $this->data = $data;
+    }
+
+    /**
+     * Returns the test data.
+     */
+    public function getTests(): array
+    {
+        return $this->tests;
+    }
+
+    /**
+     * Sets the test data.
+     */
+    public function setTests(array $tests): void
+    {
+        $this->tests = $tests;
+    }
+
+    /**
+     * Start collection of code coverage information.
+     *
+     * @param PhptTestCase|string|TestCase $id
+     */
+    public function start($id, bool $clear = false): void
+    {
+        if ($clear) {
+            $this->clear();
+        }
+
+        $this->currentId = $id;
+
+        $this->driver->start();
+    }
+
+    /**
+     * Stop collection of code coverage information.
+     *
+     * @param array|false $linesToBeCovered
+     */
+    public function stop(bool $append = true, $linesToBeCovered = [], array $linesToBeUsed = []): RawCodeCoverageData
+    {
+        if (!is_array($linesToBeCovered) && $linesToBeCovered !== false) {
+            throw new InvalidArgumentException(
+                '$linesToBeCovered must be an array or false'
+            );
+        }
+
+        $data = $this->driver->stop();
+        $this->append($data, null, $append, $linesToBeCovered, $linesToBeUsed);
+
+        $this->currentId = null;
+
+        return $data;
+    }
+
+    /**
+     * Appends code coverage data.
+     *
+     * @param PhptTestCase|string|TestCase $id
+     * @param array|false                  $linesToBeCovered
+     *
+     * @throws UnintentionallyCoveredCodeException
+     * @throws TestIdMissingException
+     * @throws ReflectionException
+     */
+    public function append(RawCodeCoverageData $rawData, $id = null, bool $append = true, $linesToBeCovered = [], array $linesToBeUsed = []): void
+    {
+        if ($id === null) {
+            $id = $this->currentId;
+        }
+
+        if ($id === null) {
+            throw new TestIdMissingException;
+        }
+
+        $this->applyFilter($rawData);
+
+        if ($this->useAnnotationsForIgnoringCode) {
+            $this->applyIgnoredLinesFilter($rawData);
+        }
+
+        $this->data->initializeUnseenData($rawData);
+
+        if (!$append) {
+            return;
+        }
+
+        if ($id !== self::UNCOVERED_FILES) {
+            $this->applyCoversAnnotationFilter(
+                $rawData,
+                $linesToBeCovered,
+                $linesToBeUsed
+            );
+
+            if (empty($rawData->lineCoverage())) {
+                return;
+            }
+
+            $size         = 'unknown';
+            $status       = -1;
+            $fromTestcase = false;
+
+            if ($id instanceof TestCase) {
+                $fromTestcase = true;
+                $_size        = $id->getSize();
+
+                if ($_size === Test::SMALL) {
+                    $size = 'small';
+                } elseif ($_size === Test::MEDIUM) {
+                    $size = 'medium';
+                } elseif ($_size === Test::LARGE) {
+                    $size = 'large';
+                }
+
+                $status = $id->getStatus();
+                $id     = get_class($id) . '::' . $id->getName();
+            } elseif ($id instanceof PhptTestCase) {
+                $fromTestcase = true;
+                $size         = 'large';
+                $id           = $id->getName();
+            }
+
+            $this->tests[$id] = ['size' => $size, 'status' => $status, 'fromTestcase' => $fromTestcase];
+
+            $this->data->markCodeAsExecutedByTestCase($id, $rawData);
+        }
+    }
+
+    /**
+     * Merges the data from another instance.
+     */
+    public function merge(self $that): void
+    {
+        $this->filter->includeFiles(
+            $that->filter()->files()
+        );
+
+        $this->data->merge($that->data);
+
+        $this->tests = array_merge($this->tests, $that->getTests());
+    }
+
+    public function enableCheckForUnintentionallyCoveredCode(): void
+    {
+        $this->checkForUnintentionallyCoveredCode = true;
+    }
+
+    public function disableCheckForUnintentionallyCoveredCode(): void
+    {
+        $this->checkForUnintentionallyCoveredCode = false;
+    }
+
+    public function includeUncoveredFiles(): void
+    {
+        $this->includeUncoveredFiles = true;
+    }
+
+    public function excludeUncoveredFiles(): void
+    {
+        $this->includeUncoveredFiles = false;
+    }
+
+    public function processUncoveredFiles(): void
+    {
+        $this->processUncoveredFiles = true;
+    }
+
+    public function doNotProcessUncoveredFiles(): void
+    {
+        $this->processUncoveredFiles = false;
+    }
+
+    public function enableAnnotationsForIgnoringCode(): void
+    {
+        $this->useAnnotationsForIgnoringCode = true;
+    }
+
+    public function disableAnnotationsForIgnoringCode(): void
+    {
+        $this->useAnnotationsForIgnoringCode = false;
+    }
+
+    public function ignoreDeprecatedCode(): void
+    {
+        $this->ignoreDeprecatedCode = true;
+    }
+
+    public function doNotIgnoreDeprecatedCode(): void
+    {
+        $this->ignoreDeprecatedCode = false;
+    }
+
+    /**
+     * @psalm-assert-if-true !null $this->cacheDirectory
+     */
+    public function cachesStaticAnalysis(): bool
+    {
+        return $this->cacheDirectory !== null;
+    }
+
+    public function cacheStaticAnalysis(string $directory): void
+    {
+        $this->cacheDirectory = $directory;
+    }
+
+    public function doNotCacheStaticAnalysis(): void
+    {
+        $this->cacheDirectory = null;
+    }
+
+    /**
+     * @throws StaticAnalysisCacheNotConfiguredException
+     */
+    public function cacheDirectory(): string
+    {
+        if (!$this->cachesStaticAnalysis()) {
+            throw new StaticAnalysisCacheNotConfiguredException(
+                'The static analysis cache is not configured'
+            );
+        }
+
+        return $this->cacheDirectory;
+    }
+
+    /**
+     * @psalm-param class-string $className
+     */
+    public function excludeSubclassesOfThisClassFromUnintentionallyCoveredCodeCheck(string $className): void
+    {
+        $this->parentClassesExcludedFromUnintentionallyCoveredCodeCheck[] = $className;
+    }
+
+    public function enableBranchAndPathCoverage(): void
+    {
+        $this->driver->enableBranchAndPathCoverage();
+    }
+
+    public function disableBranchAndPathCoverage(): void
+    {
+        $this->driver->disableBranchAndPathCoverage();
+    }
+
+    public function collectsBranchAndPathCoverage(): bool
+    {
+        return $this->driver->collectsBranchAndPathCoverage();
+    }
+
+    public function detectsDeadCode(): bool
+    {
+        return $this->driver->detectsDeadCode();
+    }
+
+    /**
+     * Applies the @covers annotation filtering.
+     *
+     * @param array|false $linesToBeCovered
+     *
+     * @throws UnintentionallyCoveredCodeException
+     * @throws ReflectionException
+     */
+    private function applyCoversAnnotationFilter(RawCodeCoverageData $rawData, $linesToBeCovered, array $linesToBeUsed): void
+    {
+        if ($linesToBeCovered === false) {
+            $rawData->clear();
+
+            return;
+        }
+
+        if (empty($linesToBeCovered)) {
+            return;
+        }
+
+        if ($this->checkForUnintentionallyCoveredCode &&
+            (!$this->currentId instanceof TestCase ||
+            (!$this->currentId->isMedium() && !$this->currentId->isLarge()))) {
+            $this->performUnintentionallyCoveredCodeCheck($rawData, $linesToBeCovered, $linesToBeUsed);
+        }
+
+        $rawLineData         = $rawData->lineCoverage();
+        $filesWithNoCoverage = array_diff_key($rawLineData, $linesToBeCovered);
+
+        foreach (array_keys($filesWithNoCoverage) as $fileWithNoCoverage) {
+            $rawData->removeCoverageDataForFile($fileWithNoCoverage);
+        }
+
+        if (is_array($linesToBeCovered)) {
+            foreach ($linesToBeCovered as $fileToBeCovered => $includedLines) {
+                $rawData->keepCoverageDataOnlyForLines($fileToBeCovered, $includedLines);
+            }
+        }
+    }
+
+    private function applyFilter(RawCodeCoverageData $data): void
+    {
+        if ($this->filter->isEmpty()) {
+            return;
+        }
+
+        foreach (array_keys($data->lineCoverage()) as $filename) {
+            if ($this->filter->isExcluded($filename)) {
+                $data->removeCoverageDataForFile($filename);
+            }
+        }
+    }
+
+    private function applyIgnoredLinesFilter(RawCodeCoverageData $data): void
+    {
+        foreach (array_keys($data->lineCoverage()) as $filename) {
+            if (!$this->filter->isFile($filename)) {
+                continue;
+            }
+
+            $data->removeCoverageDataForLines(
+                $filename,
+                $this->coveredFileAnalyser()->ignoredLinesFor($filename)
+            );
+        }
+    }
+
+    /**
+     * @throws UnintentionallyCoveredCodeException
+     */
+    private function addUncoveredFilesFromFilter(): void
+    {
+        $uncoveredFiles = array_diff(
+            $this->filter->files(),
+            $this->data->coveredFiles()
+        );
+
+        foreach ($uncoveredFiles as $uncoveredFile) {
+            if (is_file($uncoveredFile)) {
+                $this->append(
+                    RawCodeCoverageData::fromUncoveredFile(
+                        $uncoveredFile,
+                        $this->uncoveredFileAnalyser()
+                    ),
+                    self::UNCOVERED_FILES
+                );
+            }
+        }
+    }
+
+    /**
+     * @throws UnintentionallyCoveredCodeException
+     */
+    private function processUncoveredFilesFromFilter(): void
+    {
+        $uncoveredFiles = array_diff(
+            $this->filter->files(),
+            $this->data->coveredFiles()
+        );
+
+        $this->driver->start();
+
+        foreach ($uncoveredFiles as $uncoveredFile) {
+            if (is_file($uncoveredFile)) {
+                include_once $uncoveredFile;
+            }
+        }
+
+        $this->append($this->driver->stop(), self::UNCOVERED_FILES);
+    }
+
+    /**
+     * @throws UnintentionallyCoveredCodeException
+     * @throws ReflectionException
+     */
+    private function performUnintentionallyCoveredCodeCheck(RawCodeCoverageData $data, array $linesToBeCovered, array $linesToBeUsed): void
+    {
+        $allowedLines = $this->getAllowedLines(
+            $linesToBeCovered,
+            $linesToBeUsed
+        );
+
+        $unintentionallyCoveredUnits = [];
+
+        foreach ($data->lineCoverage() as $file => $_data) {
+            foreach ($_data as $line => $flag) {
+                if ($flag === 1 && !isset($allowedLines[$file][$line])) {
+                    $unintentionallyCoveredUnits[] = $this->wizard->lookup($file, $line);
+                }
+            }
+        }
+
+        $unintentionallyCoveredUnits = $this->processUnintentionallyCoveredUnits($unintentionallyCoveredUnits);
+
+        if (!empty($unintentionallyCoveredUnits)) {
+            throw new UnintentionallyCoveredCodeException(
+                $unintentionallyCoveredUnits
+            );
+        }
+    }
+
+    private function getAllowedLines(array $linesToBeCovered, array $linesToBeUsed): array
+    {
+        $allowedLines = [];
+
+        foreach (array_keys($linesToBeCovered) as $file) {
+            if (!isset($allowedLines[$file])) {
+                $allowedLines[$file] = [];
+            }
+
+            $allowedLines[$file] = array_merge(
+                $allowedLines[$file],
+                $linesToBeCovered[$file]
+            );
+        }
+
+        foreach (array_keys($linesToBeUsed) as $file) {
+            if (!isset($allowedLines[$file])) {
+                $allowedLines[$file] = [];
+            }
+
+            $allowedLines[$file] = array_merge(
+                $allowedLines[$file],
+                $linesToBeUsed[$file]
+            );
+        }
+
+        foreach (array_keys($allowedLines) as $file) {
+            $allowedLines[$file] = array_flip(
+                array_unique($allowedLines[$file])
+            );
+        }
+
+        return $allowedLines;
+    }
+
+    /**
+     * @throws ReflectionException
+     */
+    private function processUnintentionallyCoveredUnits(array $unintentionallyCoveredUnits): array
+    {
+        $unintentionallyCoveredUnits = array_unique($unintentionallyCoveredUnits);
+        sort($unintentionallyCoveredUnits);
+
+        foreach (array_keys($unintentionallyCoveredUnits) as $k => $v) {
+            $unit = explode('::', $unintentionallyCoveredUnits[$k]);
+
+            if (count($unit) !== 2) {
+                continue;
+            }
+
+            try {
+                $class = new ReflectionClass($unit[0]);
+
+                foreach ($this->parentClassesExcludedFromUnintentionallyCoveredCodeCheck as $parentClass) {
+                    if ($class->isSubclassOf($parentClass)) {
+                        unset($unintentionallyCoveredUnits[$k]);
+
+                        break;
+                    }
+                }
+            } catch (\ReflectionException $e) {
+                throw new ReflectionException(
+                    $e->getMessage(),
+                    (int) $e->getCode(),
+                    $e
+                );
+            }
+        }
+
+        return array_values($unintentionallyCoveredUnits);
+    }
+
+    private function coveredFileAnalyser(): CoveredFileAnalyser
+    {
+        if ($this->coveredFileAnalyser !== null) {
+            return $this->coveredFileAnalyser;
+        }
+
+        $this->coveredFileAnalyser = new ParsingCoveredFileAnalyser(
+            $this->useAnnotationsForIgnoringCode,
+            $this->ignoreDeprecatedCode
+        );
+
+        if ($this->cachesStaticAnalysis()) {
+            $this->coveredFileAnalyser = new CachingCoveredFileAnalyser(
+                $this->cacheDirectory,
+                $this->coveredFileAnalyser
+            );
+        }
+
+        return $this->coveredFileAnalyser;
+    }
+
+    private function uncoveredFileAnalyser(): UncoveredFileAnalyser
+    {
+        if ($this->uncoveredFileAnalyser !== null) {
+            return $this->uncoveredFileAnalyser;
+        }
+
+        $this->uncoveredFileAnalyser = new ParsingUncoveredFileAnalyser;
+
+        if ($this->cachesStaticAnalysis()) {
+            $this->uncoveredFileAnalyser = new CachingUncoveredFileAnalyser(
+                $this->cacheDirectory,
+                $this->uncoveredFileAnalyser
+            );
+        }
+
+        return $this->uncoveredFileAnalyser;
+    }
+}
diff --git a/vendor/phpunit/php-code-coverage/src/CrapIndex.php b/vendor/phpunit/php-code-coverage/src/CrapIndex.php
new file mode 100644
index 0000000000000000000000000000000000000000..bd1639019f9f5e931520bd5cc3647079ef5872ce
--- /dev/null
+++ b/vendor/phpunit/php-code-coverage/src/CrapIndex.php
@@ -0,0 +1,55 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of phpunit/php-code-coverage.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\CodeCoverage;
+
+use function sprintf;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage
+ */
+final class CrapIndex
+{
+    /**
+     * @var int
+     */
+    private $cyclomaticComplexity;
+
+    /**
+     * @var float
+     */
+    private $codeCoverage;
+
+    public static function fromCyclomaticComplexityAndCoveragePercentage(int $cyclomaticComplexity, float $codeCoverage): self
+    {
+        return new self($cyclomaticComplexity, $codeCoverage);
+    }
+
+    public function __construct(int $cyclomaticComplexity, float $codeCoverage)
+    {
+        $this->cyclomaticComplexity = $cyclomaticComplexity;
+        $this->codeCoverage         = $codeCoverage;
+    }
+
+    public function asString(): string
+    {
+        if ($this->codeCoverage === 0.0) {
+            return (string) ($this->cyclomaticComplexity ** 2 + $this->cyclomaticComplexity);
+        }
+
+        if ($this->codeCoverage >= 95) {
+            return (string) $this->cyclomaticComplexity;
+        }
+
+        return sprintf(
+            '%01.2F',
+            $this->cyclomaticComplexity ** 2 * (1 - $this->codeCoverage / 100) ** 3 + $this->cyclomaticComplexity
+        );
+    }
+}
diff --git a/vendor/phpunit/php-code-coverage/src/Directory.php b/vendor/phpunit/php-code-coverage/src/Directory.php
new file mode 100644
index 0000000000000000000000000000000000000000..cd96e7858fea3e863de6105d82b3dc017e15844b
--- /dev/null
+++ b/vendor/phpunit/php-code-coverage/src/Directory.php
@@ -0,0 +1,37 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of phpunit/php-code-coverage.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\CodeCoverage;
+
+use function is_dir;
+use function mkdir;
+use function sprintf;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage
+ */
+final class Directory
+{
+    /**
+     * @throws DirectoryCouldNotBeCreatedException
+     */
+    public static function create(string $directory): void
+    {
+        $success = !(!is_dir($directory) && !@mkdir($directory, 0777, true) && !is_dir($directory));
+
+        if (!$success) {
+            throw new DirectoryCouldNotBeCreatedException(
+                sprintf(
+                    'Directory "%s" could not be created',
+                    $directory
+                )
+            );
+        }
+    }
+}
diff --git a/vendor/phpunit/php-code-coverage/src/Driver/Driver.php b/vendor/phpunit/php-code-coverage/src/Driver/Driver.php
new file mode 100644
index 0000000000000000000000000000000000000000..b8961113eba16733d1fda05241fb61019bfcb698
--- /dev/null
+++ b/vendor/phpunit/php-code-coverage/src/Driver/Driver.php
@@ -0,0 +1,167 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of phpunit/php-code-coverage.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\CodeCoverage\Driver;
+
+use function sprintf;
+use SebastianBergmann\CodeCoverage\BranchAndPathCoverageNotSupportedException;
+use SebastianBergmann\CodeCoverage\DeadCodeDetectionNotSupportedException;
+use SebastianBergmann\CodeCoverage\Filter;
+use SebastianBergmann\CodeCoverage\NoCodeCoverageDriverAvailableException;
+use SebastianBergmann\CodeCoverage\NoCodeCoverageDriverWithPathCoverageSupportAvailableException;
+use SebastianBergmann\CodeCoverage\RawCodeCoverageData;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage
+ */
+abstract class Driver
+{
+    /**
+     * @var int
+     *
+     * @see http://xdebug.org/docs/code_coverage
+     */
+    public const LINE_NOT_EXECUTABLE = -2;
+
+    /**
+     * @var int
+     *
+     * @see http://xdebug.org/docs/code_coverage
+     */
+    public const LINE_NOT_EXECUTED = -1;
+
+    /**
+     * @var int
+     *
+     * @see http://xdebug.org/docs/code_coverage
+     */
+    public const LINE_EXECUTED = 1;
+
+    /**
+     * @var int
+     *
+     * @see http://xdebug.org/docs/code_coverage
+     */
+    public const BRANCH_NOT_HIT = 0;
+
+    /**
+     * @var int
+     *
+     * @see http://xdebug.org/docs/code_coverage
+     */
+    public const BRANCH_HIT = 1;
+
+    /**
+     * @var bool
+     */
+    private $collectBranchAndPathCoverage = false;
+
+    /**
+     * @var bool
+     */
+    private $detectDeadCode = false;
+
+    /**
+     * @throws NoCodeCoverageDriverAvailableException
+     * @throws PcovNotAvailableException
+     * @throws PhpdbgNotAvailableException
+     * @throws XdebugNotAvailableException
+     * @throws Xdebug2NotEnabledException
+     * @throws Xdebug3NotEnabledException
+     *
+     * @deprecated Use DriverSelector::forLineCoverage() instead
+     */
+    public static function forLineCoverage(Filter $filter): self
+    {
+        return (new Selector)->forLineCoverage($filter);
+    }
+
+    /**
+     * @throws NoCodeCoverageDriverWithPathCoverageSupportAvailableException
+     * @throws XdebugNotAvailableException
+     * @throws Xdebug2NotEnabledException
+     * @throws Xdebug3NotEnabledException
+     *
+     * @deprecated Use DriverSelector::forLineAndPathCoverage() instead
+     */
+    public static function forLineAndPathCoverage(Filter $filter): self
+    {
+        return (new Selector)->forLineAndPathCoverage($filter);
+    }
+
+    public function canCollectBranchAndPathCoverage(): bool
+    {
+        return false;
+    }
+
+    public function collectsBranchAndPathCoverage(): bool
+    {
+        return $this->collectBranchAndPathCoverage;
+    }
+
+    /**
+     * @throws BranchAndPathCoverageNotSupportedException
+     */
+    public function enableBranchAndPathCoverage(): void
+    {
+        if (!$this->canCollectBranchAndPathCoverage()) {
+            throw new BranchAndPathCoverageNotSupportedException(
+                sprintf(
+                    '%s does not support branch and path coverage',
+                    $this->nameAndVersion()
+                )
+            );
+        }
+
+        $this->collectBranchAndPathCoverage = true;
+    }
+
+    public function disableBranchAndPathCoverage(): void
+    {
+        $this->collectBranchAndPathCoverage = false;
+    }
+
+    public function canDetectDeadCode(): bool
+    {
+        return false;
+    }
+
+    public function detectsDeadCode(): bool
+    {
+        return $this->detectDeadCode;
+    }
+
+    /**
+     * @throws DeadCodeDetectionNotSupportedException
+     */
+    public function enableDeadCodeDetection(): void
+    {
+        if (!$this->canDetectDeadCode()) {
+            throw new DeadCodeDetectionNotSupportedException(
+                sprintf(
+                    '%s does not support dead code detection',
+                    $this->nameAndVersion()
+                )
+            );
+        }
+
+        $this->detectDeadCode = true;
+    }
+
+    public function disableDeadCodeDetection(): void
+    {
+        $this->detectDeadCode = false;
+    }
+
+    abstract public function nameAndVersion(): string;
+
+    abstract public function start(): void;
+
+    abstract public function stop(): RawCodeCoverageData;
+}
diff --git a/vendor/phpunit/php-code-coverage/src/Driver/PcovDriver.php b/vendor/phpunit/php-code-coverage/src/Driver/PcovDriver.php
new file mode 100644
index 0000000000000000000000000000000000000000..f4eca6031254dd14c4ff77fbc84355c1c9b8fbd4
--- /dev/null
+++ b/vendor/phpunit/php-code-coverage/src/Driver/PcovDriver.php
@@ -0,0 +1,62 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of phpunit/php-code-coverage.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\CodeCoverage\Driver;
+
+use function extension_loaded;
+use function phpversion;
+use SebastianBergmann\CodeCoverage\Filter;
+use SebastianBergmann\CodeCoverage\RawCodeCoverageData;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage
+ */
+final class PcovDriver extends Driver
+{
+    /**
+     * @var Filter
+     */
+    private $filter;
+
+    /**
+     * @throws PcovNotAvailableException
+     */
+    public function __construct(Filter $filter)
+    {
+        if (!extension_loaded('pcov')) {
+            throw new PcovNotAvailableException;
+        }
+
+        $this->filter = $filter;
+    }
+
+    public function start(): void
+    {
+        \pcov\start();
+    }
+
+    public function stop(): RawCodeCoverageData
+    {
+        \pcov\stop();
+
+        $collect = \pcov\collect(
+            \pcov\inclusive,
+            !$this->filter->isEmpty() ? $this->filter->files() : \pcov\waiting()
+        );
+
+        \pcov\clear();
+
+        return RawCodeCoverageData::fromXdebugWithoutPathCoverage($collect);
+    }
+
+    public function nameAndVersion(): string
+    {
+        return 'PCOV ' . phpversion('pcov');
+    }
+}
diff --git a/vendor/phpunit/php-code-coverage/src/Driver/PhpdbgDriver.php b/vendor/phpunit/php-code-coverage/src/Driver/PhpdbgDriver.php
new file mode 100644
index 0000000000000000000000000000000000000000..7ee13b00fad3e52ac78e3bf0f9884f23a56ffe22
--- /dev/null
+++ b/vendor/phpunit/php-code-coverage/src/Driver/PhpdbgDriver.php
@@ -0,0 +1,93 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of phpunit/php-code-coverage.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\CodeCoverage\Driver;
+
+use const PHP_SAPI;
+use const PHP_VERSION;
+use function array_diff;
+use function array_keys;
+use function array_merge;
+use function get_included_files;
+use function phpdbg_end_oplog;
+use function phpdbg_get_executable;
+use function phpdbg_start_oplog;
+use SebastianBergmann\CodeCoverage\RawCodeCoverageData;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage
+ */
+final class PhpdbgDriver extends Driver
+{
+    /**
+     * @throws PhpdbgNotAvailableException
+     */
+    public function __construct()
+    {
+        if (PHP_SAPI !== 'phpdbg') {
+            throw new PhpdbgNotAvailableException;
+        }
+    }
+
+    public function start(): void
+    {
+        phpdbg_start_oplog();
+    }
+
+    public function stop(): RawCodeCoverageData
+    {
+        static $fetchedLines = [];
+
+        $dbgData = phpdbg_end_oplog();
+
+        if ($fetchedLines === []) {
+            $sourceLines = phpdbg_get_executable();
+        } else {
+            $newFiles = array_diff(get_included_files(), array_keys($fetchedLines));
+
+            $sourceLines = [];
+
+            if ($newFiles) {
+                $sourceLines = phpdbg_get_executable(['files' => $newFiles]);
+            }
+        }
+
+        foreach ($sourceLines as $file => $lines) {
+            foreach ($lines as $lineNo => $numExecuted) {
+                $sourceLines[$file][$lineNo] = self::LINE_NOT_EXECUTED;
+            }
+        }
+
+        $fetchedLines = array_merge($fetchedLines, $sourceLines);
+
+        return RawCodeCoverageData::fromXdebugWithoutPathCoverage(
+            $this->detectExecutedLines($fetchedLines, $dbgData)
+        );
+    }
+
+    public function nameAndVersion(): string
+    {
+        return 'PHPDBG ' . PHP_VERSION;
+    }
+
+    private function detectExecutedLines(array $sourceLines, array $dbgData): array
+    {
+        foreach ($dbgData as $file => $coveredLines) {
+            foreach ($coveredLines as $lineNo => $numExecuted) {
+                // phpdbg also reports $lineNo=0 when e.g. exceptions get thrown.
+                // make sure we only mark lines executed which are actually executable.
+                if (isset($sourceLines[$file][$lineNo])) {
+                    $sourceLines[$file][$lineNo] = self::LINE_EXECUTED;
+                }
+            }
+        }
+
+        return $sourceLines;
+    }
+}
diff --git a/vendor/phpunit/php-code-coverage/src/Driver/Selector.php b/vendor/phpunit/php-code-coverage/src/Driver/Selector.php
new file mode 100644
index 0000000000000000000000000000000000000000..709e9bc04605e630860f0169bd4c2afbc2650a22
--- /dev/null
+++ b/vendor/phpunit/php-code-coverage/src/Driver/Selector.php
@@ -0,0 +1,79 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of phpunit/php-code-coverage.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\CodeCoverage\Driver;
+
+use function phpversion;
+use function version_compare;
+use SebastianBergmann\CodeCoverage\Filter;
+use SebastianBergmann\CodeCoverage\NoCodeCoverageDriverAvailableException;
+use SebastianBergmann\CodeCoverage\NoCodeCoverageDriverWithPathCoverageSupportAvailableException;
+use SebastianBergmann\Environment\Runtime;
+
+final class Selector
+{
+    /**
+     * @throws NoCodeCoverageDriverAvailableException
+     * @throws PcovNotAvailableException
+     * @throws PhpdbgNotAvailableException
+     * @throws XdebugNotAvailableException
+     * @throws Xdebug2NotEnabledException
+     * @throws Xdebug3NotEnabledException
+     */
+    public function forLineCoverage(Filter $filter): Driver
+    {
+        $runtime = new Runtime;
+
+        if ($runtime->hasPHPDBGCodeCoverage()) {
+            return new PhpdbgDriver;
+        }
+
+        if ($runtime->hasPCOV()) {
+            return new PcovDriver($filter);
+        }
+
+        if ($runtime->hasXdebug()) {
+            if (version_compare(phpversion('xdebug'), '3', '>=')) {
+                $driver = new Xdebug3Driver($filter);
+            } else {
+                $driver = new Xdebug2Driver($filter);
+            }
+
+            $driver->enableDeadCodeDetection();
+
+            return $driver;
+        }
+
+        throw new NoCodeCoverageDriverAvailableException;
+    }
+
+    /**
+     * @throws NoCodeCoverageDriverWithPathCoverageSupportAvailableException
+     * @throws XdebugNotAvailableException
+     * @throws Xdebug2NotEnabledException
+     * @throws Xdebug3NotEnabledException
+     */
+    public function forLineAndPathCoverage(Filter $filter): Driver
+    {
+        if ((new Runtime)->hasXdebug()) {
+            if (version_compare(phpversion('xdebug'), '3', '>=')) {
+                $driver = new Xdebug3Driver($filter);
+            } else {
+                $driver = new Xdebug2Driver($filter);
+            }
+
+            $driver->enableDeadCodeDetection();
+            $driver->enableBranchAndPathCoverage();
+
+            return $driver;
+        }
+
+        throw new NoCodeCoverageDriverWithPathCoverageSupportAvailableException;
+    }
+}
diff --git a/vendor/phpunit/php-code-coverage/src/Driver/Xdebug2Driver.php b/vendor/phpunit/php-code-coverage/src/Driver/Xdebug2Driver.php
new file mode 100644
index 0000000000000000000000000000000000000000..a7238442d2bab72267e7bcbf9366949e3ea2e89f
--- /dev/null
+++ b/vendor/phpunit/php-code-coverage/src/Driver/Xdebug2Driver.php
@@ -0,0 +1,128 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of phpunit/php-code-coverage.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\CodeCoverage\Driver;
+
+use const XDEBUG_CC_BRANCH_CHECK;
+use const XDEBUG_CC_DEAD_CODE;
+use const XDEBUG_CC_UNUSED;
+use const XDEBUG_FILTER_CODE_COVERAGE;
+use const XDEBUG_PATH_INCLUDE;
+use const XDEBUG_PATH_WHITELIST;
+use function defined;
+use function extension_loaded;
+use function ini_get;
+use function phpversion;
+use function sprintf;
+use function version_compare;
+use function xdebug_get_code_coverage;
+use function xdebug_set_filter;
+use function xdebug_start_code_coverage;
+use function xdebug_stop_code_coverage;
+use SebastianBergmann\CodeCoverage\Filter;
+use SebastianBergmann\CodeCoverage\RawCodeCoverageData;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage
+ */
+final class Xdebug2Driver extends Driver
+{
+    /**
+     * @var bool
+     */
+    private $pathCoverageIsMixedCoverage;
+
+    /**
+     * @throws XdebugNotAvailableException
+     * @throws WrongXdebugVersionException
+     * @throws Xdebug2NotEnabledException
+     */
+    public function __construct(Filter $filter)
+    {
+        if (!extension_loaded('xdebug')) {
+            throw new XdebugNotAvailableException;
+        }
+
+        if (version_compare(phpversion('xdebug'), '3', '>=')) {
+            throw new WrongXdebugVersionException(
+                sprintf(
+                    'This driver requires Xdebug 2 but version %s is loaded',
+                    phpversion('xdebug')
+                )
+            );
+        }
+
+        if (!ini_get('xdebug.coverage_enable')) {
+            throw new Xdebug2NotEnabledException;
+        }
+
+        if (!$filter->isEmpty()) {
+            if (defined('XDEBUG_PATH_WHITELIST')) {
+                $listType = XDEBUG_PATH_WHITELIST;
+            } else {
+                $listType = XDEBUG_PATH_INCLUDE;
+            }
+
+            xdebug_set_filter(
+                XDEBUG_FILTER_CODE_COVERAGE,
+                $listType,
+                $filter->files()
+            );
+        }
+
+        $this->pathCoverageIsMixedCoverage = version_compare(phpversion('xdebug'), '2.9.6', '<');
+    }
+
+    public function canCollectBranchAndPathCoverage(): bool
+    {
+        return true;
+    }
+
+    public function canDetectDeadCode(): bool
+    {
+        return true;
+    }
+
+    public function start(): void
+    {
+        $flags = XDEBUG_CC_UNUSED;
+
+        if ($this->detectsDeadCode() || $this->collectsBranchAndPathCoverage()) {
+            $flags |= XDEBUG_CC_DEAD_CODE;
+        }
+
+        if ($this->collectsBranchAndPathCoverage()) {
+            $flags |= XDEBUG_CC_BRANCH_CHECK;
+        }
+
+        xdebug_start_code_coverage($flags);
+    }
+
+    public function stop(): RawCodeCoverageData
+    {
+        $data = xdebug_get_code_coverage();
+
+        xdebug_stop_code_coverage();
+
+        if ($this->collectsBranchAndPathCoverage()) {
+            if ($this->pathCoverageIsMixedCoverage) {
+                return RawCodeCoverageData::fromXdebugWithMixedCoverage($data);
+            }
+
+            return RawCodeCoverageData::fromXdebugWithPathCoverage($data);
+        }
+
+        return RawCodeCoverageData::fromXdebugWithoutPathCoverage($data);
+    }
+
+    public function nameAndVersion(): string
+    {
+        return 'Xdebug ' . phpversion('xdebug');
+    }
+}
diff --git a/vendor/phpunit/php-code-coverage/src/Driver/Xdebug3Driver.php b/vendor/phpunit/php-code-coverage/src/Driver/Xdebug3Driver.php
new file mode 100644
index 0000000000000000000000000000000000000000..b85bfab0e054cbd087a8b531d546e4a6219f309d
--- /dev/null
+++ b/vendor/phpunit/php-code-coverage/src/Driver/Xdebug3Driver.php
@@ -0,0 +1,119 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of phpunit/php-code-coverage.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\CodeCoverage\Driver;
+
+use const XDEBUG_CC_BRANCH_CHECK;
+use const XDEBUG_CC_DEAD_CODE;
+use const XDEBUG_CC_UNUSED;
+use const XDEBUG_FILTER_CODE_COVERAGE;
+use const XDEBUG_PATH_INCLUDE;
+use function explode;
+use function extension_loaded;
+use function getenv;
+use function in_array;
+use function ini_get;
+use function phpversion;
+use function sprintf;
+use function version_compare;
+use function xdebug_get_code_coverage;
+use function xdebug_set_filter;
+use function xdebug_start_code_coverage;
+use function xdebug_stop_code_coverage;
+use SebastianBergmann\CodeCoverage\Filter;
+use SebastianBergmann\CodeCoverage\RawCodeCoverageData;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage
+ */
+final class Xdebug3Driver extends Driver
+{
+    /**
+     * @throws XdebugNotAvailableException
+     * @throws WrongXdebugVersionException
+     * @throws Xdebug3NotEnabledException
+     */
+    public function __construct(Filter $filter)
+    {
+        if (!extension_loaded('xdebug')) {
+            throw new XdebugNotAvailableException;
+        }
+
+        if (version_compare(phpversion('xdebug'), '3', '<')) {
+            throw new WrongXdebugVersionException(
+                sprintf(
+                    'This driver requires Xdebug 3 but version %s is loaded',
+                    phpversion('xdebug')
+                )
+            );
+        }
+
+        $mode = getenv('XDEBUG_MODE');
+
+        if ($mode === false) {
+            $mode = ini_get('xdebug.mode');
+        }
+
+        if ($mode === false ||
+            !in_array('coverage', explode(',', $mode), true)) {
+            throw new Xdebug3NotEnabledException;
+        }
+
+        if (!$filter->isEmpty()) {
+            xdebug_set_filter(
+                XDEBUG_FILTER_CODE_COVERAGE,
+                XDEBUG_PATH_INCLUDE,
+                $filter->files()
+            );
+        }
+    }
+
+    public function canCollectBranchAndPathCoverage(): bool
+    {
+        return true;
+    }
+
+    public function canDetectDeadCode(): bool
+    {
+        return true;
+    }
+
+    public function start(): void
+    {
+        $flags = XDEBUG_CC_UNUSED;
+
+        if ($this->detectsDeadCode() || $this->collectsBranchAndPathCoverage()) {
+            $flags |= XDEBUG_CC_DEAD_CODE;
+        }
+
+        if ($this->collectsBranchAndPathCoverage()) {
+            $flags |= XDEBUG_CC_BRANCH_CHECK;
+        }
+
+        xdebug_start_code_coverage($flags);
+    }
+
+    public function stop(): RawCodeCoverageData
+    {
+        $data = xdebug_get_code_coverage();
+
+        xdebug_stop_code_coverage();
+
+        if ($this->collectsBranchAndPathCoverage()) {
+            return RawCodeCoverageData::fromXdebugWithPathCoverage($data);
+        }
+
+        return RawCodeCoverageData::fromXdebugWithoutPathCoverage($data);
+    }
+
+    public function nameAndVersion(): string
+    {
+        return 'Xdebug ' . phpversion('xdebug');
+    }
+}
diff --git a/vendor/phpunit/php-code-coverage/src/Exception/BranchAndPathCoverageNotSupportedException.php b/vendor/phpunit/php-code-coverage/src/Exception/BranchAndPathCoverageNotSupportedException.php
new file mode 100644
index 0000000000000000000000000000000000000000..ab2089197a90f0c5401baa30d6df8df58051439a
--- /dev/null
+++ b/vendor/phpunit/php-code-coverage/src/Exception/BranchAndPathCoverageNotSupportedException.php
@@ -0,0 +1,16 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of phpunit/php-code-coverage.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\CodeCoverage;
+
+use RuntimeException;
+
+final class BranchAndPathCoverageNotSupportedException extends RuntimeException implements Exception
+{
+}
diff --git a/vendor/phpunit/php-code-coverage/src/Exception/DeadCodeDetectionNotSupportedException.php b/vendor/phpunit/php-code-coverage/src/Exception/DeadCodeDetectionNotSupportedException.php
new file mode 100644
index 0000000000000000000000000000000000000000..d36006489359bde3767f0c4bee2b845bc971762d
--- /dev/null
+++ b/vendor/phpunit/php-code-coverage/src/Exception/DeadCodeDetectionNotSupportedException.php
@@ -0,0 +1,16 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of phpunit/php-code-coverage.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\CodeCoverage;
+
+use RuntimeException;
+
+final class DeadCodeDetectionNotSupportedException extends RuntimeException implements Exception
+{
+}
diff --git a/vendor/phpunit/php-code-coverage/src/Exception/DirectoryCouldNotBeCreatedException.php b/vendor/phpunit/php-code-coverage/src/Exception/DirectoryCouldNotBeCreatedException.php
new file mode 100644
index 0000000000000000000000000000000000000000..c1e9213ac3579977befc2ab75e00075e12a20699
--- /dev/null
+++ b/vendor/phpunit/php-code-coverage/src/Exception/DirectoryCouldNotBeCreatedException.php
@@ -0,0 +1,16 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of phpunit/php-code-coverage.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\CodeCoverage;
+
+use RuntimeException;
+
+final class DirectoryCouldNotBeCreatedException extends RuntimeException implements Exception
+{
+}
diff --git a/vendor/phpunit/php-code-coverage/src/Exception/Exception.php b/vendor/phpunit/php-code-coverage/src/Exception/Exception.php
new file mode 100644
index 0000000000000000000000000000000000000000..28dc48b8a1b33a2cad0925a40bd873a08832bf7c
--- /dev/null
+++ b/vendor/phpunit/php-code-coverage/src/Exception/Exception.php
@@ -0,0 +1,16 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of phpunit/php-code-coverage.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\CodeCoverage;
+
+use Throwable;
+
+interface Exception extends Throwable
+{
+}
diff --git a/vendor/phpunit/php-code-coverage/src/Exception/InvalidArgumentException.php b/vendor/phpunit/php-code-coverage/src/Exception/InvalidArgumentException.php
new file mode 100644
index 0000000000000000000000000000000000000000..17e4b7076a608ffcf1de95429fd4e71f4e098813
--- /dev/null
+++ b/vendor/phpunit/php-code-coverage/src/Exception/InvalidArgumentException.php
@@ -0,0 +1,14 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of phpunit/php-code-coverage.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\CodeCoverage;
+
+final class InvalidArgumentException extends \InvalidArgumentException implements Exception
+{
+}
diff --git a/vendor/phpunit/php-code-coverage/src/Exception/NoCodeCoverageDriverAvailableException.php b/vendor/phpunit/php-code-coverage/src/Exception/NoCodeCoverageDriverAvailableException.php
new file mode 100644
index 0000000000000000000000000000000000000000..b1494e267b9d43a80c25e53b3949033fb676c3ca
--- /dev/null
+++ b/vendor/phpunit/php-code-coverage/src/Exception/NoCodeCoverageDriverAvailableException.php
@@ -0,0 +1,20 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of phpunit/php-code-coverage.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\CodeCoverage;
+
+use RuntimeException;
+
+final class NoCodeCoverageDriverAvailableException extends RuntimeException implements Exception
+{
+    public function __construct()
+    {
+        parent::__construct('No code coverage driver available');
+    }
+}
diff --git a/vendor/phpunit/php-code-coverage/src/Exception/NoCodeCoverageDriverWithPathCoverageSupportAvailableException.php b/vendor/phpunit/php-code-coverage/src/Exception/NoCodeCoverageDriverWithPathCoverageSupportAvailableException.php
new file mode 100644
index 0000000000000000000000000000000000000000..0065b740d1f1fb74c71064ae55392ac8f05379cb
--- /dev/null
+++ b/vendor/phpunit/php-code-coverage/src/Exception/NoCodeCoverageDriverWithPathCoverageSupportAvailableException.php
@@ -0,0 +1,20 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of phpunit/php-code-coverage.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\CodeCoverage;
+
+use RuntimeException;
+
+final class NoCodeCoverageDriverWithPathCoverageSupportAvailableException extends RuntimeException implements Exception
+{
+    public function __construct()
+    {
+        parent::__construct('No code coverage driver with path coverage support available');
+    }
+}
diff --git a/vendor/phpunit/php-code-coverage/src/Exception/ParserException.php b/vendor/phpunit/php-code-coverage/src/Exception/ParserException.php
new file mode 100644
index 0000000000000000000000000000000000000000..a907e34e84c8d29053dff5e8cfaf56e137562faa
--- /dev/null
+++ b/vendor/phpunit/php-code-coverage/src/Exception/ParserException.php
@@ -0,0 +1,16 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of phpunit/php-code-coverage.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\CodeCoverage;
+
+use RuntimeException;
+
+final class ParserException extends RuntimeException implements Exception
+{
+}
diff --git a/vendor/phpunit/php-code-coverage/src/Exception/PathExistsButIsNotDirectoryException.php b/vendor/phpunit/php-code-coverage/src/Exception/PathExistsButIsNotDirectoryException.php
new file mode 100644
index 0000000000000000000000000000000000000000..54bd73f58c693bd349dd6e0e8303439c7b8282c9
--- /dev/null
+++ b/vendor/phpunit/php-code-coverage/src/Exception/PathExistsButIsNotDirectoryException.php
@@ -0,0 +1,22 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of phpunit/php-code-coverage.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\CodeCoverage\Driver;
+
+use function sprintf;
+use RuntimeException;
+use SebastianBergmann\CodeCoverage\Exception;
+
+final class PathExistsButIsNotDirectoryException extends RuntimeException implements Exception
+{
+    public function __construct(string $path)
+    {
+        parent::__construct(sprintf('"%s" exists but is not a directory', $path));
+    }
+}
diff --git a/vendor/phpunit/php-code-coverage/src/Exception/PcovNotAvailableException.php b/vendor/phpunit/php-code-coverage/src/Exception/PcovNotAvailableException.php
new file mode 100644
index 0000000000000000000000000000000000000000..2f0a66e5afe16c318208da2d35e05d88c40128cf
--- /dev/null
+++ b/vendor/phpunit/php-code-coverage/src/Exception/PcovNotAvailableException.php
@@ -0,0 +1,21 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of phpunit/php-code-coverage.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\CodeCoverage\Driver;
+
+use RuntimeException;
+use SebastianBergmann\CodeCoverage\Exception;
+
+final class PcovNotAvailableException extends RuntimeException implements Exception
+{
+    public function __construct()
+    {
+        parent::__construct('The PCOV extension is not available');
+    }
+}
diff --git a/vendor/phpunit/php-code-coverage/src/Exception/PhpdbgNotAvailableException.php b/vendor/phpunit/php-code-coverage/src/Exception/PhpdbgNotAvailableException.php
new file mode 100644
index 0000000000000000000000000000000000000000..bfb183d5c7c2f3d3bd7cf5cee0eaf1b4a70babbc
--- /dev/null
+++ b/vendor/phpunit/php-code-coverage/src/Exception/PhpdbgNotAvailableException.php
@@ -0,0 +1,21 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of phpunit/php-code-coverage.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\CodeCoverage\Driver;
+
+use RuntimeException;
+use SebastianBergmann\CodeCoverage\Exception;
+
+final class PhpdbgNotAvailableException extends RuntimeException implements Exception
+{
+    public function __construct()
+    {
+        parent::__construct('The PHPDBG SAPI is not available');
+    }
+}
diff --git a/vendor/phpunit/php-code-coverage/src/Exception/ReflectionException.php b/vendor/phpunit/php-code-coverage/src/Exception/ReflectionException.php
new file mode 100644
index 0000000000000000000000000000000000000000..78db430bed9e627b99b782ca12912250842de975
--- /dev/null
+++ b/vendor/phpunit/php-code-coverage/src/Exception/ReflectionException.php
@@ -0,0 +1,16 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of phpunit/php-code-coverage.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\CodeCoverage;
+
+use RuntimeException;
+
+final class ReflectionException extends RuntimeException implements Exception
+{
+}
diff --git a/vendor/phpunit/php-code-coverage/src/Exception/ReportAlreadyFinalizedException.php b/vendor/phpunit/php-code-coverage/src/Exception/ReportAlreadyFinalizedException.php
new file mode 100644
index 0000000000000000000000000000000000000000..0481f1610efb8ad756441c871ce9057d0fcd2b82
--- /dev/null
+++ b/vendor/phpunit/php-code-coverage/src/Exception/ReportAlreadyFinalizedException.php
@@ -0,0 +1,20 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of phpunit/php-code-coverage.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\CodeCoverage;
+
+use RuntimeException;
+
+final class ReportAlreadyFinalizedException extends RuntimeException implements Exception
+{
+    public function __construct()
+    {
+        parent::__construct('The code coverage report has already been finalized');
+    }
+}
diff --git a/vendor/phpunit/php-code-coverage/src/Exception/StaticAnalysisCacheNotConfiguredException.php b/vendor/phpunit/php-code-coverage/src/Exception/StaticAnalysisCacheNotConfiguredException.php
new file mode 100644
index 0000000000000000000000000000000000000000..fd58fd6b63e6bb2c400e104512fce28e8d5905bc
--- /dev/null
+++ b/vendor/phpunit/php-code-coverage/src/Exception/StaticAnalysisCacheNotConfiguredException.php
@@ -0,0 +1,16 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of phpunit/php-code-coverage.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\CodeCoverage;
+
+use RuntimeException;
+
+final class StaticAnalysisCacheNotConfiguredException extends RuntimeException implements Exception
+{
+}
diff --git a/vendor/phpunit/php-code-coverage/src/Exception/TestIdMissingException.php b/vendor/phpunit/php-code-coverage/src/Exception/TestIdMissingException.php
new file mode 100644
index 0000000000000000000000000000000000000000..4cc3e0c2bc32c27eb0b2b65619dac87e24492c90
--- /dev/null
+++ b/vendor/phpunit/php-code-coverage/src/Exception/TestIdMissingException.php
@@ -0,0 +1,20 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of phpunit/php-code-coverage.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\CodeCoverage;
+
+use RuntimeException;
+
+final class TestIdMissingException extends RuntimeException implements Exception
+{
+    public function __construct()
+    {
+        parent::__construct('Test ID is missing');
+    }
+}
diff --git a/vendor/phpunit/php-code-coverage/src/Exception/UnintentionallyCoveredCodeException.php b/vendor/phpunit/php-code-coverage/src/Exception/UnintentionallyCoveredCodeException.php
new file mode 100644
index 0000000000000000000000000000000000000000..cb7a975f7fff9e8a5fdd9fb766144b876d77aa57
--- /dev/null
+++ b/vendor/phpunit/php-code-coverage/src/Exception/UnintentionallyCoveredCodeException.php
@@ -0,0 +1,43 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of phpunit/php-code-coverage.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\CodeCoverage;
+
+use RuntimeException;
+
+final class UnintentionallyCoveredCodeException extends RuntimeException implements Exception
+{
+    /**
+     * @var array
+     */
+    private $unintentionallyCoveredUnits;
+
+    public function __construct(array $unintentionallyCoveredUnits)
+    {
+        $this->unintentionallyCoveredUnits = $unintentionallyCoveredUnits;
+
+        parent::__construct($this->toString());
+    }
+
+    public function getUnintentionallyCoveredUnits(): array
+    {
+        return $this->unintentionallyCoveredUnits;
+    }
+
+    private function toString(): string
+    {
+        $message = '';
+
+        foreach ($this->unintentionallyCoveredUnits as $unit) {
+            $message .= '- ' . $unit . "\n";
+        }
+
+        return $message;
+    }
+}
diff --git a/vendor/phpunit/php-code-coverage/src/Exception/WriteOperationFailedException.php b/vendor/phpunit/php-code-coverage/src/Exception/WriteOperationFailedException.php
new file mode 100644
index 0000000000000000000000000000000000000000..be549e17bbec7cc51474670319a033fc2e4b45a8
--- /dev/null
+++ b/vendor/phpunit/php-code-coverage/src/Exception/WriteOperationFailedException.php
@@ -0,0 +1,22 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of phpunit/php-code-coverage.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\CodeCoverage\Driver;
+
+use function sprintf;
+use RuntimeException;
+use SebastianBergmann\CodeCoverage\Exception;
+
+final class WriteOperationFailedException extends RuntimeException implements Exception
+{
+    public function __construct(string $path)
+    {
+        parent::__construct(sprintf('Cannot write to "%s"', $path));
+    }
+}
diff --git a/vendor/phpunit/php-code-coverage/src/Exception/WrongXdebugVersionException.php b/vendor/phpunit/php-code-coverage/src/Exception/WrongXdebugVersionException.php
new file mode 100644
index 0000000000000000000000000000000000000000..6e8f10a924828d3e5b5376d5a66a0c63582e061b
--- /dev/null
+++ b/vendor/phpunit/php-code-coverage/src/Exception/WrongXdebugVersionException.php
@@ -0,0 +1,17 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of phpunit/php-code-coverage.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\CodeCoverage\Driver;
+
+use RuntimeException;
+use SebastianBergmann\CodeCoverage\Exception;
+
+final class WrongXdebugVersionException extends RuntimeException implements Exception
+{
+}
diff --git a/vendor/phpunit/php-code-coverage/src/Exception/Xdebug2NotEnabledException.php b/vendor/phpunit/php-code-coverage/src/Exception/Xdebug2NotEnabledException.php
new file mode 100644
index 0000000000000000000000000000000000000000..3039e77c03df38e11fb11197a616369fc4293b13
--- /dev/null
+++ b/vendor/phpunit/php-code-coverage/src/Exception/Xdebug2NotEnabledException.php
@@ -0,0 +1,21 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of phpunit/php-code-coverage.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\CodeCoverage\Driver;
+
+use RuntimeException;
+use SebastianBergmann\CodeCoverage\Exception;
+
+final class Xdebug2NotEnabledException extends RuntimeException implements Exception
+{
+    public function __construct()
+    {
+        parent::__construct('xdebug.coverage_enable=On has to be set');
+    }
+}
diff --git a/vendor/phpunit/php-code-coverage/src/Exception/Xdebug3NotEnabledException.php b/vendor/phpunit/php-code-coverage/src/Exception/Xdebug3NotEnabledException.php
new file mode 100644
index 0000000000000000000000000000000000000000..5d3b106ce86240b93a19d13d230797316debf63c
--- /dev/null
+++ b/vendor/phpunit/php-code-coverage/src/Exception/Xdebug3NotEnabledException.php
@@ -0,0 +1,21 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of phpunit/php-code-coverage.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\CodeCoverage\Driver;
+
+use RuntimeException;
+use SebastianBergmann\CodeCoverage\Exception;
+
+final class Xdebug3NotEnabledException extends RuntimeException implements Exception
+{
+    public function __construct()
+    {
+        parent::__construct('XDEBUG_MODE=coverage or xdebug.mode=coverage has to be set');
+    }
+}
diff --git a/vendor/phpunit/php-code-coverage/src/Exception/XdebugNotAvailableException.php b/vendor/phpunit/php-code-coverage/src/Exception/XdebugNotAvailableException.php
new file mode 100644
index 0000000000000000000000000000000000000000..1622c5a63622df9a50d0401281d43a6c600662b1
--- /dev/null
+++ b/vendor/phpunit/php-code-coverage/src/Exception/XdebugNotAvailableException.php
@@ -0,0 +1,21 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of phpunit/php-code-coverage.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\CodeCoverage\Driver;
+
+use RuntimeException;
+use SebastianBergmann\CodeCoverage\Exception;
+
+final class XdebugNotAvailableException extends RuntimeException implements Exception
+{
+    public function __construct()
+    {
+        parent::__construct('The Xdebug extension is not available');
+    }
+}
diff --git a/vendor/phpunit/php-code-coverage/src/Exception/XmlException.php b/vendor/phpunit/php-code-coverage/src/Exception/XmlException.php
new file mode 100644
index 0000000000000000000000000000000000000000..31e4623df5c270bc4aca1c80d1cf98fd1c9388d2
--- /dev/null
+++ b/vendor/phpunit/php-code-coverage/src/Exception/XmlException.php
@@ -0,0 +1,16 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of phpunit/php-code-coverage.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\CodeCoverage;
+
+use RuntimeException;
+
+final class XmlException extends RuntimeException implements Exception
+{
+}
diff --git a/vendor/phpunit/php-code-coverage/src/Filter.php b/vendor/phpunit/php-code-coverage/src/Filter.php
new file mode 100644
index 0000000000000000000000000000000000000000..ef0a2c62f390d25fb9dde278ac9dd523f8c290af
--- /dev/null
+++ b/vendor/phpunit/php-code-coverage/src/Filter.php
@@ -0,0 +1,122 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of phpunit/php-code-coverage.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\CodeCoverage;
+
+use function array_keys;
+use function is_file;
+use function realpath;
+use function strpos;
+use SebastianBergmann\FileIterator\Facade as FileIteratorFacade;
+
+final class Filter
+{
+    /**
+     * @psalm-var array<string,true>
+     */
+    private $files = [];
+
+    /**
+     * @psalm-var array<string,bool>
+     */
+    private $isFileCache = [];
+
+    public function includeDirectory(string $directory, string $suffix = '.php', string $prefix = ''): void
+    {
+        foreach ((new FileIteratorFacade)->getFilesAsArray($directory, $suffix, $prefix) as $file) {
+            $this->includeFile($file);
+        }
+    }
+
+    /**
+     * @psalm-param list<string> $files
+     */
+    public function includeFiles(array $filenames): void
+    {
+        foreach ($filenames as $filename) {
+            $this->includeFile($filename);
+        }
+    }
+
+    public function includeFile(string $filename): void
+    {
+        $filename = realpath($filename);
+
+        if (!$filename) {
+            return;
+        }
+
+        $this->files[$filename] = true;
+    }
+
+    public function excludeDirectory(string $directory, string $suffix = '.php', string $prefix = ''): void
+    {
+        foreach ((new FileIteratorFacade)->getFilesAsArray($directory, $suffix, $prefix) as $file) {
+            $this->excludeFile($file);
+        }
+    }
+
+    public function excludeFile(string $filename): void
+    {
+        $filename = realpath($filename);
+
+        if (!$filename || !isset($this->files[$filename])) {
+            return;
+        }
+
+        unset($this->files[$filename]);
+    }
+
+    public function isFile(string $filename): bool
+    {
+        if (isset($this->isFileCache[$filename])) {
+            return $this->isFileCache[$filename];
+        }
+
+        if ($filename === '-' ||
+            strpos($filename, 'vfs://') === 0 ||
+            strpos($filename, 'xdebug://debug-eval') !== false ||
+            strpos($filename, 'eval()\'d code') !== false ||
+            strpos($filename, 'runtime-created function') !== false ||
+            strpos($filename, 'runkit created function') !== false ||
+            strpos($filename, 'assert code') !== false ||
+            strpos($filename, 'regexp code') !== false ||
+            strpos($filename, 'Standard input code') !== false) {
+            $isFile = false;
+        } else {
+            $isFile = is_file($filename);
+        }
+
+        $this->isFileCache[$filename] = $isFile;
+
+        return $isFile;
+    }
+
+    public function isExcluded(string $filename): bool
+    {
+        if (!$this->isFile($filename)) {
+            return true;
+        }
+
+        return !isset($this->files[$filename]);
+    }
+
+    /**
+     * @psalm-return list<string>
+     */
+    public function files(): array
+    {
+        return array_keys($this->files);
+    }
+
+    public function isEmpty(): bool
+    {
+        return empty($this->files);
+    }
+}
diff --git a/vendor/phpunit/php-code-coverage/src/Node/AbstractNode.php b/vendor/phpunit/php-code-coverage/src/Node/AbstractNode.php
new file mode 100644
index 0000000000000000000000000000000000000000..bfa6729020114e036b2c50d476e08a74b49102ca
--- /dev/null
+++ b/vendor/phpunit/php-code-coverage/src/Node/AbstractNode.php
@@ -0,0 +1,251 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of phpunit/php-code-coverage.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\CodeCoverage\Node;
+
+use const DIRECTORY_SEPARATOR;
+use function array_merge;
+use function str_replace;
+use function substr;
+use Countable;
+use SebastianBergmann\CodeCoverage\Percentage;
+use SebastianBergmann\LinesOfCode\LinesOfCode;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage
+ */
+abstract class AbstractNode implements Countable
+{
+    /**
+     * @var string
+     */
+    private $name;
+
+    /**
+     * @var string
+     */
+    private $pathAsString;
+
+    /**
+     * @var array
+     */
+    private $pathAsArray;
+
+    /**
+     * @var AbstractNode
+     */
+    private $parent;
+
+    /**
+     * @var string
+     */
+    private $id;
+
+    public function __construct(string $name, self $parent = null)
+    {
+        if (substr($name, -1) === DIRECTORY_SEPARATOR) {
+            $name = substr($name, 0, -1);
+        }
+
+        $this->name   = $name;
+        $this->parent = $parent;
+    }
+
+    public function name(): string
+    {
+        return $this->name;
+    }
+
+    public function id(): string
+    {
+        if ($this->id === null) {
+            $parent = $this->parent();
+
+            if ($parent === null) {
+                $this->id = 'index';
+            } else {
+                $parentId = $parent->id();
+
+                if ($parentId === 'index') {
+                    $this->id = str_replace(':', '_', $this->name);
+                } else {
+                    $this->id = $parentId . '/' . $this->name;
+                }
+            }
+        }
+
+        return $this->id;
+    }
+
+    public function pathAsString(): string
+    {
+        if ($this->pathAsString === null) {
+            if ($this->parent === null) {
+                $this->pathAsString = $this->name;
+            } else {
+                $this->pathAsString = $this->parent->pathAsString() . DIRECTORY_SEPARATOR . $this->name;
+            }
+        }
+
+        return $this->pathAsString;
+    }
+
+    public function pathAsArray(): array
+    {
+        if ($this->pathAsArray === null) {
+            if ($this->parent === null) {
+                $this->pathAsArray = [];
+            } else {
+                $this->pathAsArray = $this->parent->pathAsArray();
+            }
+
+            $this->pathAsArray[] = $this;
+        }
+
+        return $this->pathAsArray;
+    }
+
+    public function parent(): ?self
+    {
+        return $this->parent;
+    }
+
+    public function percentageOfTestedClasses(): Percentage
+    {
+        return Percentage::fromFractionAndTotal(
+            $this->numberOfTestedClasses(),
+            $this->numberOfClasses(),
+        );
+    }
+
+    public function percentageOfTestedTraits(): Percentage
+    {
+        return Percentage::fromFractionAndTotal(
+            $this->numberOfTestedTraits(),
+            $this->numberOfTraits(),
+        );
+    }
+
+    public function percentageOfTestedClassesAndTraits(): Percentage
+    {
+        return Percentage::fromFractionAndTotal(
+            $this->numberOfTestedClassesAndTraits(),
+            $this->numberOfClassesAndTraits(),
+        );
+    }
+
+    public function percentageOfTestedFunctions(): Percentage
+    {
+        return Percentage::fromFractionAndTotal(
+            $this->numberOfTestedFunctions(),
+            $this->numberOfFunctions(),
+        );
+    }
+
+    public function percentageOfTestedMethods(): Percentage
+    {
+        return Percentage::fromFractionAndTotal(
+            $this->numberOfTestedMethods(),
+            $this->numberOfMethods(),
+        );
+    }
+
+    public function percentageOfTestedFunctionsAndMethods(): Percentage
+    {
+        return Percentage::fromFractionAndTotal(
+            $this->numberOfTestedFunctionsAndMethods(),
+            $this->numberOfFunctionsAndMethods(),
+        );
+    }
+
+    public function percentageOfExecutedLines(): Percentage
+    {
+        return Percentage::fromFractionAndTotal(
+            $this->numberOfExecutedLines(),
+            $this->numberOfExecutableLines(),
+        );
+    }
+
+    public function percentageOfExecutedBranches(): Percentage
+    {
+        return Percentage::fromFractionAndTotal(
+            $this->numberOfExecutedBranches(),
+            $this->numberOfExecutableBranches()
+        );
+    }
+
+    public function percentageOfExecutedPaths(): Percentage
+    {
+        return Percentage::fromFractionAndTotal(
+            $this->numberOfExecutedPaths(),
+            $this->numberOfExecutablePaths()
+        );
+    }
+
+    public function numberOfClassesAndTraits(): int
+    {
+        return $this->numberOfClasses() + $this->numberOfTraits();
+    }
+
+    public function numberOfTestedClassesAndTraits(): int
+    {
+        return $this->numberOfTestedClasses() + $this->numberOfTestedTraits();
+    }
+
+    public function classesAndTraits(): array
+    {
+        return array_merge($this->classes(), $this->traits());
+    }
+
+    public function numberOfFunctionsAndMethods(): int
+    {
+        return $this->numberOfFunctions() + $this->numberOfMethods();
+    }
+
+    public function numberOfTestedFunctionsAndMethods(): int
+    {
+        return $this->numberOfTestedFunctions() + $this->numberOfTestedMethods();
+    }
+
+    abstract public function classes(): array;
+
+    abstract public function traits(): array;
+
+    abstract public function functions(): array;
+
+    abstract public function linesOfCode(): LinesOfCode;
+
+    abstract public function numberOfExecutableLines(): int;
+
+    abstract public function numberOfExecutedLines(): int;
+
+    abstract public function numberOfExecutableBranches(): int;
+
+    abstract public function numberOfExecutedBranches(): int;
+
+    abstract public function numberOfExecutablePaths(): int;
+
+    abstract public function numberOfExecutedPaths(): int;
+
+    abstract public function numberOfClasses(): int;
+
+    abstract public function numberOfTestedClasses(): int;
+
+    abstract public function numberOfTraits(): int;
+
+    abstract public function numberOfTestedTraits(): int;
+
+    abstract public function numberOfMethods(): int;
+
+    abstract public function numberOfTestedMethods(): int;
+
+    abstract public function numberOfFunctions(): int;
+
+    abstract public function numberOfTestedFunctions(): int;
+}
diff --git a/vendor/phpunit/php-code-coverage/src/Node/Builder.php b/vendor/phpunit/php-code-coverage/src/Node/Builder.php
new file mode 100644
index 0000000000000000000000000000000000000000..c2aa1d18097d31e0557a3dfa69950ecba7051b80
--- /dev/null
+++ b/vendor/phpunit/php-code-coverage/src/Node/Builder.php
@@ -0,0 +1,264 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of phpunit/php-code-coverage.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\CodeCoverage\Node;
+
+use const DIRECTORY_SEPARATOR;
+use function array_shift;
+use function basename;
+use function count;
+use function dirname;
+use function explode;
+use function implode;
+use function is_file;
+use function str_replace;
+use function strpos;
+use function substr;
+use SebastianBergmann\CodeCoverage\CodeCoverage;
+use SebastianBergmann\CodeCoverage\ProcessedCodeCoverageData;
+use SebastianBergmann\CodeCoverage\StaticAnalysis\CoveredFileAnalyser;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage
+ */
+final class Builder
+{
+    /**
+     * @var CoveredFileAnalyser
+     */
+    private $coveredFileAnalyser;
+
+    public function __construct(CoveredFileAnalyser $coveredFileAnalyser)
+    {
+        $this->coveredFileAnalyser = $coveredFileAnalyser;
+    }
+
+    public function build(CodeCoverage $coverage): Directory
+    {
+        $data       = clone $coverage->getData(); // clone because path munging is destructive to the original data
+        $commonPath = $this->reducePaths($data);
+        $root       = new Directory(
+            $commonPath,
+            null
+        );
+
+        $this->addItems(
+            $root,
+            $this->buildDirectoryStructure($data),
+            $coverage->getTests()
+        );
+
+        return $root;
+    }
+
+    private function addItems(Directory $root, array $items, array $tests): void
+    {
+        foreach ($items as $key => $value) {
+            $key = (string) $key;
+
+            if (substr($key, -2) === '/f') {
+                $key      = substr($key, 0, -2);
+                $filename = $root->pathAsString() . DIRECTORY_SEPARATOR . $key;
+
+                if (is_file($filename)) {
+                    $root->addFile(
+                        new File(
+                            $key,
+                            $root,
+                            $value['lineCoverage'],
+                            $value['functionCoverage'],
+                            $tests,
+                            $this->coveredFileAnalyser->classesIn($filename),
+                            $this->coveredFileAnalyser->traitsIn($filename),
+                            $this->coveredFileAnalyser->functionsIn($filename),
+                            $this->coveredFileAnalyser->linesOfCodeFor($filename)
+                        )
+                    );
+                }
+            } else {
+                $child = $root->addDirectory($key);
+
+                $this->addItems($child, $value, $tests);
+            }
+        }
+    }
+
+    /**
+     * Builds an array representation of the directory structure.
+     *
+     * For instance,
+     *
+     * <code>
+     * Array
+     * (
+     *     [Money.php] => Array
+     *         (
+     *             ...
+     *         )
+     *
+     *     [MoneyBag.php] => Array
+     *         (
+     *             ...
+     *         )
+     * )
+     * </code>
+     *
+     * is transformed into
+     *
+     * <code>
+     * Array
+     * (
+     *     [.] => Array
+     *         (
+     *             [Money.php] => Array
+     *                 (
+     *                     ...
+     *                 )
+     *
+     *             [MoneyBag.php] => Array
+     *                 (
+     *                     ...
+     *                 )
+     *         )
+     * )
+     * </code>
+     */
+    private function buildDirectoryStructure(ProcessedCodeCoverageData $data): array
+    {
+        $result = [];
+
+        foreach ($data->coveredFiles() as $originalPath) {
+            $path    = explode(DIRECTORY_SEPARATOR, $originalPath);
+            $pointer = &$result;
+            $max     = count($path);
+
+            for ($i = 0; $i < $max; $i++) {
+                $type = '';
+
+                if ($i === ($max - 1)) {
+                    $type = '/f';
+                }
+
+                $pointer = &$pointer[$path[$i] . $type];
+            }
+
+            $pointer = [
+                'lineCoverage'     => $data->lineCoverage()[$originalPath] ?? [],
+                'functionCoverage' => $data->functionCoverage()[$originalPath] ?? [],
+            ];
+        }
+
+        return $result;
+    }
+
+    /**
+     * Reduces the paths by cutting the longest common start path.
+     *
+     * For instance,
+     *
+     * <code>
+     * Array
+     * (
+     *     [/home/sb/Money/Money.php] => Array
+     *         (
+     *             ...
+     *         )
+     *
+     *     [/home/sb/Money/MoneyBag.php] => Array
+     *         (
+     *             ...
+     *         )
+     * )
+     * </code>
+     *
+     * is reduced to
+     *
+     * <code>
+     * Array
+     * (
+     *     [Money.php] => Array
+     *         (
+     *             ...
+     *         )
+     *
+     *     [MoneyBag.php] => Array
+     *         (
+     *             ...
+     *         )
+     * )
+     * </code>
+     */
+    private function reducePaths(ProcessedCodeCoverageData $coverage): string
+    {
+        if (empty($coverage->coveredFiles())) {
+            return '.';
+        }
+
+        $commonPath = '';
+        $paths      = $coverage->coveredFiles();
+
+        if (count($paths) === 1) {
+            $commonPath = dirname($paths[0]) . DIRECTORY_SEPARATOR;
+            $coverage->renameFile($paths[0], basename($paths[0]));
+
+            return $commonPath;
+        }
+
+        $max = count($paths);
+
+        for ($i = 0; $i < $max; $i++) {
+            // strip phar:// prefixes
+            if (strpos($paths[$i], 'phar://') === 0) {
+                $paths[$i] = substr($paths[$i], 7);
+                $paths[$i] = str_replace('/', DIRECTORY_SEPARATOR, $paths[$i]);
+            }
+            $paths[$i] = explode(DIRECTORY_SEPARATOR, $paths[$i]);
+
+            if (empty($paths[$i][0])) {
+                $paths[$i][0] = DIRECTORY_SEPARATOR;
+            }
+        }
+
+        $done = false;
+        $max  = count($paths);
+
+        while (!$done) {
+            for ($i = 0; $i < $max - 1; $i++) {
+                if (!isset($paths[$i][0]) ||
+                    !isset($paths[$i + 1][0]) ||
+                    $paths[$i][0] !== $paths[$i + 1][0]) {
+                    $done = true;
+
+                    break;
+                }
+            }
+
+            if (!$done) {
+                $commonPath .= $paths[0][0];
+
+                if ($paths[0][0] !== DIRECTORY_SEPARATOR) {
+                    $commonPath .= DIRECTORY_SEPARATOR;
+                }
+
+                for ($i = 0; $i < $max; $i++) {
+                    array_shift($paths[$i]);
+                }
+            }
+        }
+
+        $original = $coverage->coveredFiles();
+        $max      = count($original);
+
+        for ($i = 0; $i < $max; $i++) {
+            $coverage->renameFile($original[$i], implode(DIRECTORY_SEPARATOR, $paths[$i]));
+        }
+
+        return substr($commonPath, 0, -1);
+    }
+}
diff --git a/vendor/phpunit/php-code-coverage/src/Node/Directory.php b/vendor/phpunit/php-code-coverage/src/Node/Directory.php
new file mode 100644
index 0000000000000000000000000000000000000000..572cc2a4e0363ada410b4bf7750bcfd676aebafb
--- /dev/null
+++ b/vendor/phpunit/php-code-coverage/src/Node/Directory.php
@@ -0,0 +1,430 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of phpunit/php-code-coverage.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\CodeCoverage\Node;
+
+use function array_merge;
+use function count;
+use IteratorAggregate;
+use RecursiveIteratorIterator;
+use SebastianBergmann\LinesOfCode\LinesOfCode;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage
+ */
+final class Directory extends AbstractNode implements IteratorAggregate
+{
+    /**
+     * @var AbstractNode[]
+     */
+    private $children = [];
+
+    /**
+     * @var Directory[]
+     */
+    private $directories = [];
+
+    /**
+     * @var File[]
+     */
+    private $files = [];
+
+    /**
+     * @var array
+     */
+    private $classes;
+
+    /**
+     * @var array
+     */
+    private $traits;
+
+    /**
+     * @var array
+     */
+    private $functions;
+
+    /**
+     * @var LinesOfCode
+     */
+    private $linesOfCode;
+
+    /**
+     * @var int
+     */
+    private $numFiles = -1;
+
+    /**
+     * @var int
+     */
+    private $numExecutableLines = -1;
+
+    /**
+     * @var int
+     */
+    private $numExecutedLines = -1;
+
+    /**
+     * @var int
+     */
+    private $numExecutableBranches = -1;
+
+    /**
+     * @var int
+     */
+    private $numExecutedBranches = -1;
+
+    /**
+     * @var int
+     */
+    private $numExecutablePaths = -1;
+
+    /**
+     * @var int
+     */
+    private $numExecutedPaths = -1;
+
+    /**
+     * @var int
+     */
+    private $numClasses = -1;
+
+    /**
+     * @var int
+     */
+    private $numTestedClasses = -1;
+
+    /**
+     * @var int
+     */
+    private $numTraits = -1;
+
+    /**
+     * @var int
+     */
+    private $numTestedTraits = -1;
+
+    /**
+     * @var int
+     */
+    private $numMethods = -1;
+
+    /**
+     * @var int
+     */
+    private $numTestedMethods = -1;
+
+    /**
+     * @var int
+     */
+    private $numFunctions = -1;
+
+    /**
+     * @var int
+     */
+    private $numTestedFunctions = -1;
+
+    public function count(): int
+    {
+        if ($this->numFiles === -1) {
+            $this->numFiles = 0;
+
+            foreach ($this->children as $child) {
+                $this->numFiles += count($child);
+            }
+        }
+
+        return $this->numFiles;
+    }
+
+    public function getIterator(): RecursiveIteratorIterator
+    {
+        return new RecursiveIteratorIterator(
+            new Iterator($this),
+            RecursiveIteratorIterator::SELF_FIRST
+        );
+    }
+
+    public function addDirectory(string $name): self
+    {
+        $directory = new self($name, $this);
+
+        $this->children[]    = $directory;
+        $this->directories[] = &$this->children[count($this->children) - 1];
+
+        return $directory;
+    }
+
+    public function addFile(File $file): void
+    {
+        $this->children[] = $file;
+        $this->files[]    = &$this->children[count($this->children) - 1];
+
+        $this->numExecutableLines = -1;
+        $this->numExecutedLines   = -1;
+    }
+
+    public function directories(): array
+    {
+        return $this->directories;
+    }
+
+    public function files(): array
+    {
+        return $this->files;
+    }
+
+    public function children(): array
+    {
+        return $this->children;
+    }
+
+    public function classes(): array
+    {
+        if ($this->classes === null) {
+            $this->classes = [];
+
+            foreach ($this->children as $child) {
+                $this->classes = array_merge(
+                    $this->classes,
+                    $child->classes()
+                );
+            }
+        }
+
+        return $this->classes;
+    }
+
+    public function traits(): array
+    {
+        if ($this->traits === null) {
+            $this->traits = [];
+
+            foreach ($this->children as $child) {
+                $this->traits = array_merge(
+                    $this->traits,
+                    $child->traits()
+                );
+            }
+        }
+
+        return $this->traits;
+    }
+
+    public function functions(): array
+    {
+        if ($this->functions === null) {
+            $this->functions = [];
+
+            foreach ($this->children as $child) {
+                $this->functions = array_merge(
+                    $this->functions,
+                    $child->functions()
+                );
+            }
+        }
+
+        return $this->functions;
+    }
+
+    public function linesOfCode(): LinesOfCode
+    {
+        if ($this->linesOfCode === null) {
+            $this->linesOfCode = new LinesOfCode(0, 0, 0, 0);
+
+            foreach ($this->children as $child) {
+                $this->linesOfCode = $this->linesOfCode->plus($child->linesOfCode());
+            }
+        }
+
+        return $this->linesOfCode;
+    }
+
+    public function numberOfExecutableLines(): int
+    {
+        if ($this->numExecutableLines === -1) {
+            $this->numExecutableLines = 0;
+
+            foreach ($this->children as $child) {
+                $this->numExecutableLines += $child->numberOfExecutableLines();
+            }
+        }
+
+        return $this->numExecutableLines;
+    }
+
+    public function numberOfExecutedLines(): int
+    {
+        if ($this->numExecutedLines === -1) {
+            $this->numExecutedLines = 0;
+
+            foreach ($this->children as $child) {
+                $this->numExecutedLines += $child->numberOfExecutedLines();
+            }
+        }
+
+        return $this->numExecutedLines;
+    }
+
+    public function numberOfExecutableBranches(): int
+    {
+        if ($this->numExecutableBranches === -1) {
+            $this->numExecutableBranches = 0;
+
+            foreach ($this->children as $child) {
+                $this->numExecutableBranches += $child->numberOfExecutableBranches();
+            }
+        }
+
+        return $this->numExecutableBranches;
+    }
+
+    public function numberOfExecutedBranches(): int
+    {
+        if ($this->numExecutedBranches === -1) {
+            $this->numExecutedBranches = 0;
+
+            foreach ($this->children as $child) {
+                $this->numExecutedBranches += $child->numberOfExecutedBranches();
+            }
+        }
+
+        return $this->numExecutedBranches;
+    }
+
+    public function numberOfExecutablePaths(): int
+    {
+        if ($this->numExecutablePaths === -1) {
+            $this->numExecutablePaths = 0;
+
+            foreach ($this->children as $child) {
+                $this->numExecutablePaths += $child->numberOfExecutablePaths();
+            }
+        }
+
+        return $this->numExecutablePaths;
+    }
+
+    public function numberOfExecutedPaths(): int
+    {
+        if ($this->numExecutedPaths === -1) {
+            $this->numExecutedPaths = 0;
+
+            foreach ($this->children as $child) {
+                $this->numExecutedPaths += $child->numberOfExecutedPaths();
+            }
+        }
+
+        return $this->numExecutedPaths;
+    }
+
+    public function numberOfClasses(): int
+    {
+        if ($this->numClasses === -1) {
+            $this->numClasses = 0;
+
+            foreach ($this->children as $child) {
+                $this->numClasses += $child->numberOfClasses();
+            }
+        }
+
+        return $this->numClasses;
+    }
+
+    public function numberOfTestedClasses(): int
+    {
+        if ($this->numTestedClasses === -1) {
+            $this->numTestedClasses = 0;
+
+            foreach ($this->children as $child) {
+                $this->numTestedClasses += $child->numberOfTestedClasses();
+            }
+        }
+
+        return $this->numTestedClasses;
+    }
+
+    public function numberOfTraits(): int
+    {
+        if ($this->numTraits === -1) {
+            $this->numTraits = 0;
+
+            foreach ($this->children as $child) {
+                $this->numTraits += $child->numberOfTraits();
+            }
+        }
+
+        return $this->numTraits;
+    }
+
+    public function numberOfTestedTraits(): int
+    {
+        if ($this->numTestedTraits === -1) {
+            $this->numTestedTraits = 0;
+
+            foreach ($this->children as $child) {
+                $this->numTestedTraits += $child->numberOfTestedTraits();
+            }
+        }
+
+        return $this->numTestedTraits;
+    }
+
+    public function numberOfMethods(): int
+    {
+        if ($this->numMethods === -1) {
+            $this->numMethods = 0;
+
+            foreach ($this->children as $child) {
+                $this->numMethods += $child->numberOfMethods();
+            }
+        }
+
+        return $this->numMethods;
+    }
+
+    public function numberOfTestedMethods(): int
+    {
+        if ($this->numTestedMethods === -1) {
+            $this->numTestedMethods = 0;
+
+            foreach ($this->children as $child) {
+                $this->numTestedMethods += $child->numberOfTestedMethods();
+            }
+        }
+
+        return $this->numTestedMethods;
+    }
+
+    public function numberOfFunctions(): int
+    {
+        if ($this->numFunctions === -1) {
+            $this->numFunctions = 0;
+
+            foreach ($this->children as $child) {
+                $this->numFunctions += $child->numberOfFunctions();
+            }
+        }
+
+        return $this->numFunctions;
+    }
+
+    public function numberOfTestedFunctions(): int
+    {
+        if ($this->numTestedFunctions === -1) {
+            $this->numTestedFunctions = 0;
+
+            foreach ($this->children as $child) {
+                $this->numTestedFunctions += $child->numberOfTestedFunctions();
+            }
+        }
+
+        return $this->numTestedFunctions;
+    }
+}
diff --git a/vendor/phpunit/php-code-coverage/src/Node/File.php b/vendor/phpunit/php-code-coverage/src/Node/File.php
new file mode 100644
index 0000000000000000000000000000000000000000..290ae731a1af9747c03f095bf1676c7e5ca22c6d
--- /dev/null
+++ b/vendor/phpunit/php-code-coverage/src/Node/File.php
@@ -0,0 +1,643 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of phpunit/php-code-coverage.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\CodeCoverage\Node;
+
+use function array_filter;
+use function count;
+use function range;
+use SebastianBergmann\CodeCoverage\CrapIndex;
+use SebastianBergmann\LinesOfCode\LinesOfCode;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage
+ */
+final class File extends AbstractNode
+{
+    /**
+     * @var array
+     */
+    private $lineCoverageData;
+
+    /**
+     * @var array
+     */
+    private $functionCoverageData;
+
+    /**
+     * @var array
+     */
+    private $testData;
+
+    /**
+     * @var int
+     */
+    private $numExecutableLines = 0;
+
+    /**
+     * @var int
+     */
+    private $numExecutedLines = 0;
+
+    /**
+     * @var int
+     */
+    private $numExecutableBranches = 0;
+
+    /**
+     * @var int
+     */
+    private $numExecutedBranches = 0;
+
+    /**
+     * @var int
+     */
+    private $numExecutablePaths = 0;
+
+    /**
+     * @var int
+     */
+    private $numExecutedPaths = 0;
+
+    /**
+     * @var array
+     */
+    private $classes = [];
+
+    /**
+     * @var array
+     */
+    private $traits = [];
+
+    /**
+     * @var array
+     */
+    private $functions = [];
+
+    /**
+     * @var LinesOfCode
+     */
+    private $linesOfCode;
+
+    /**
+     * @var int
+     */
+    private $numClasses;
+
+    /**
+     * @var int
+     */
+    private $numTestedClasses = 0;
+
+    /**
+     * @var int
+     */
+    private $numTraits;
+
+    /**
+     * @var int
+     */
+    private $numTestedTraits = 0;
+
+    /**
+     * @var int
+     */
+    private $numMethods;
+
+    /**
+     * @var int
+     */
+    private $numTestedMethods;
+
+    /**
+     * @var int
+     */
+    private $numTestedFunctions;
+
+    /**
+     * @var array
+     */
+    private $codeUnitsByLine = [];
+
+    public function __construct(string $name, AbstractNode $parent, array $lineCoverageData, array $functionCoverageData, array $testData, array $classes, array $traits, array $functions, LinesOfCode $linesOfCode)
+    {
+        parent::__construct($name, $parent);
+
+        $this->lineCoverageData     = $lineCoverageData;
+        $this->functionCoverageData = $functionCoverageData;
+        $this->testData             = $testData;
+        $this->linesOfCode          = $linesOfCode;
+
+        $this->calculateStatistics($classes, $traits, $functions);
+    }
+
+    public function count(): int
+    {
+        return 1;
+    }
+
+    public function lineCoverageData(): array
+    {
+        return $this->lineCoverageData;
+    }
+
+    public function functionCoverageData(): array
+    {
+        return $this->functionCoverageData;
+    }
+
+    public function testData(): array
+    {
+        return $this->testData;
+    }
+
+    public function classes(): array
+    {
+        return $this->classes;
+    }
+
+    public function traits(): array
+    {
+        return $this->traits;
+    }
+
+    public function functions(): array
+    {
+        return $this->functions;
+    }
+
+    public function linesOfCode(): LinesOfCode
+    {
+        return $this->linesOfCode;
+    }
+
+    public function numberOfExecutableLines(): int
+    {
+        return $this->numExecutableLines;
+    }
+
+    public function numberOfExecutedLines(): int
+    {
+        return $this->numExecutedLines;
+    }
+
+    public function numberOfExecutableBranches(): int
+    {
+        return $this->numExecutableBranches;
+    }
+
+    public function numberOfExecutedBranches(): int
+    {
+        return $this->numExecutedBranches;
+    }
+
+    public function numberOfExecutablePaths(): int
+    {
+        return $this->numExecutablePaths;
+    }
+
+    public function numberOfExecutedPaths(): int
+    {
+        return $this->numExecutedPaths;
+    }
+
+    public function numberOfClasses(): int
+    {
+        if ($this->numClasses === null) {
+            $this->numClasses = 0;
+
+            foreach ($this->classes as $class) {
+                foreach ($class['methods'] as $method) {
+                    if ($method['executableLines'] > 0) {
+                        $this->numClasses++;
+
+                        continue 2;
+                    }
+                }
+            }
+        }
+
+        return $this->numClasses;
+    }
+
+    public function numberOfTestedClasses(): int
+    {
+        return $this->numTestedClasses;
+    }
+
+    public function numberOfTraits(): int
+    {
+        if ($this->numTraits === null) {
+            $this->numTraits = 0;
+
+            foreach ($this->traits as $trait) {
+                foreach ($trait['methods'] as $method) {
+                    if ($method['executableLines'] > 0) {
+                        $this->numTraits++;
+
+                        continue 2;
+                    }
+                }
+            }
+        }
+
+        return $this->numTraits;
+    }
+
+    public function numberOfTestedTraits(): int
+    {
+        return $this->numTestedTraits;
+    }
+
+    public function numberOfMethods(): int
+    {
+        if ($this->numMethods === null) {
+            $this->numMethods = 0;
+
+            foreach ($this->classes as $class) {
+                foreach ($class['methods'] as $method) {
+                    if ($method['executableLines'] > 0) {
+                        $this->numMethods++;
+                    }
+                }
+            }
+
+            foreach ($this->traits as $trait) {
+                foreach ($trait['methods'] as $method) {
+                    if ($method['executableLines'] > 0) {
+                        $this->numMethods++;
+                    }
+                }
+            }
+        }
+
+        return $this->numMethods;
+    }
+
+    public function numberOfTestedMethods(): int
+    {
+        if ($this->numTestedMethods === null) {
+            $this->numTestedMethods = 0;
+
+            foreach ($this->classes as $class) {
+                foreach ($class['methods'] as $method) {
+                    if ($method['executableLines'] > 0 &&
+                        $method['coverage'] === 100) {
+                        $this->numTestedMethods++;
+                    }
+                }
+            }
+
+            foreach ($this->traits as $trait) {
+                foreach ($trait['methods'] as $method) {
+                    if ($method['executableLines'] > 0 &&
+                        $method['coverage'] === 100) {
+                        $this->numTestedMethods++;
+                    }
+                }
+            }
+        }
+
+        return $this->numTestedMethods;
+    }
+
+    public function numberOfFunctions(): int
+    {
+        return count($this->functions);
+    }
+
+    public function numberOfTestedFunctions(): int
+    {
+        if ($this->numTestedFunctions === null) {
+            $this->numTestedFunctions = 0;
+
+            foreach ($this->functions as $function) {
+                if ($function['executableLines'] > 0 &&
+                    $function['coverage'] === 100) {
+                    $this->numTestedFunctions++;
+                }
+            }
+        }
+
+        return $this->numTestedFunctions;
+    }
+
+    private function calculateStatistics(array $classes, array $traits, array $functions): void
+    {
+        foreach (range(1, $this->linesOfCode->linesOfCode()) as $lineNumber) {
+            $this->codeUnitsByLine[$lineNumber] = [];
+        }
+
+        $this->processClasses($classes);
+        $this->processTraits($traits);
+        $this->processFunctions($functions);
+
+        foreach (range(1, $this->linesOfCode->linesOfCode()) as $lineNumber) {
+            if (isset($this->lineCoverageData[$lineNumber])) {
+                foreach ($this->codeUnitsByLine[$lineNumber] as &$codeUnit) {
+                    $codeUnit['executableLines']++;
+                }
+
+                unset($codeUnit);
+
+                $this->numExecutableLines++;
+
+                if (count($this->lineCoverageData[$lineNumber]) > 0) {
+                    foreach ($this->codeUnitsByLine[$lineNumber] as &$codeUnit) {
+                        $codeUnit['executedLines']++;
+                    }
+
+                    unset($codeUnit);
+
+                    $this->numExecutedLines++;
+                }
+            }
+        }
+
+        foreach ($this->traits as &$trait) {
+            foreach ($trait['methods'] as &$method) {
+                $methodLineCoverage   = $method['executableLines'] ? ($method['executedLines'] / $method['executableLines']) * 100 : 100;
+                $methodBranchCoverage = $method['executableBranches'] ? ($method['executedBranches'] / $method['executableBranches']) * 100 : 0;
+                $methodPathCoverage   = $method['executablePaths'] ? ($method['executedPaths'] / $method['executablePaths']) * 100 : 0;
+
+                $method['coverage'] = $methodBranchCoverage ?: $methodLineCoverage;
+                $method['crap']     = (new CrapIndex($method['ccn'], $methodPathCoverage ?: $methodLineCoverage))->asString();
+
+                $trait['ccn'] += $method['ccn'];
+            }
+
+            unset($method);
+
+            $traitLineCoverage   = $trait['executableLines'] ? ($trait['executedLines'] / $trait['executableLines']) * 100 : 100;
+            $traitBranchCoverage = $trait['executableBranches'] ? ($trait['executedBranches'] / $trait['executableBranches']) * 100 : 0;
+            $traitPathCoverage   = $trait['executablePaths'] ? ($trait['executedPaths'] / $trait['executablePaths']) * 100 : 0;
+
+            $trait['coverage'] = $traitBranchCoverage ?: $traitLineCoverage;
+            $trait['crap']     = (new CrapIndex($trait['ccn'], $traitPathCoverage ?: $traitLineCoverage))->asString();
+
+            if ($trait['executableLines'] > 0 && $trait['coverage'] === 100) {
+                $this->numTestedClasses++;
+            }
+        }
+
+        unset($trait);
+
+        foreach ($this->classes as &$class) {
+            foreach ($class['methods'] as &$method) {
+                $methodLineCoverage   = $method['executableLines'] ? ($method['executedLines'] / $method['executableLines']) * 100 : 100;
+                $methodBranchCoverage = $method['executableBranches'] ? ($method['executedBranches'] / $method['executableBranches']) * 100 : 0;
+                $methodPathCoverage   = $method['executablePaths'] ? ($method['executedPaths'] / $method['executablePaths']) * 100 : 0;
+
+                $method['coverage'] = $methodBranchCoverage ?: $methodLineCoverage;
+                $method['crap']     = (new CrapIndex($method['ccn'], $methodPathCoverage ?: $methodLineCoverage))->asString();
+
+                $class['ccn'] += $method['ccn'];
+            }
+
+            unset($method);
+
+            $classLineCoverage   = $class['executableLines'] ? ($class['executedLines'] / $class['executableLines']) * 100 : 100;
+            $classBranchCoverage = $class['executableBranches'] ? ($class['executedBranches'] / $class['executableBranches']) * 100 : 0;
+            $classPathCoverage   = $class['executablePaths'] ? ($class['executedPaths'] / $class['executablePaths']) * 100 : 0;
+
+            $class['coverage'] = $classBranchCoverage ?: $classLineCoverage;
+            $class['crap']     = (new CrapIndex($class['ccn'], $classPathCoverage ?: $classLineCoverage))->asString();
+
+            if ($class['executableLines'] > 0 && $class['coverage'] === 100) {
+                $this->numTestedClasses++;
+            }
+        }
+
+        unset($class);
+
+        foreach ($this->functions as &$function) {
+            $functionLineCoverage   = $function['executableLines'] ? ($function['executedLines'] / $function['executableLines']) * 100 : 100;
+            $functionBranchCoverage = $function['executableBranches'] ? ($function['executedBranches'] / $function['executableBranches']) * 100 : 0;
+            $functionPathCoverage   = $function['executablePaths'] ? ($function['executedPaths'] / $function['executablePaths']) * 100 : 0;
+
+            $function['coverage'] = $functionBranchCoverage ?: $functionLineCoverage;
+            $function['crap']     = (new CrapIndex($function['ccn'], $functionPathCoverage ?: $functionLineCoverage))->asString();
+
+            if ($function['coverage'] === 100) {
+                $this->numTestedFunctions++;
+            }
+        }
+    }
+
+    private function processClasses(array $classes): void
+    {
+        $link = $this->id() . '.html#';
+
+        foreach ($classes as $className => $class) {
+            $this->classes[$className] = [
+                'className'          => $className,
+                'namespace'          => $class['namespace'],
+                'methods'            => [],
+                'startLine'          => $class['startLine'],
+                'executableLines'    => 0,
+                'executedLines'      => 0,
+                'executableBranches' => 0,
+                'executedBranches'   => 0,
+                'executablePaths'    => 0,
+                'executedPaths'      => 0,
+                'ccn'                => 0,
+                'coverage'           => 0,
+                'crap'               => 0,
+                'link'               => $link . $class['startLine'],
+            ];
+
+            foreach ($class['methods'] as $methodName => $method) {
+                $methodData                                        = $this->newMethod($className, $methodName, $method, $link);
+                $this->classes[$className]['methods'][$methodName] = $methodData;
+
+                $this->classes[$className]['executableBranches'] += $methodData['executableBranches'];
+                $this->classes[$className]['executedBranches'] += $methodData['executedBranches'];
+                $this->classes[$className]['executablePaths'] += $methodData['executablePaths'];
+                $this->classes[$className]['executedPaths'] += $methodData['executedPaths'];
+
+                $this->numExecutableBranches += $methodData['executableBranches'];
+                $this->numExecutedBranches += $methodData['executedBranches'];
+                $this->numExecutablePaths += $methodData['executablePaths'];
+                $this->numExecutedPaths += $methodData['executedPaths'];
+
+                foreach (range($method['startLine'], $method['endLine']) as $lineNumber) {
+                    $this->codeUnitsByLine[$lineNumber] = [
+                        &$this->classes[$className],
+                        &$this->classes[$className]['methods'][$methodName],
+                    ];
+                }
+            }
+        }
+    }
+
+    private function processTraits(array $traits): void
+    {
+        $link = $this->id() . '.html#';
+
+        foreach ($traits as $traitName => $trait) {
+            $this->traits[$traitName] = [
+                'traitName'          => $traitName,
+                'namespace'          => $trait['namespace'],
+                'methods'            => [],
+                'startLine'          => $trait['startLine'],
+                'executableLines'    => 0,
+                'executedLines'      => 0,
+                'executableBranches' => 0,
+                'executedBranches'   => 0,
+                'executablePaths'    => 0,
+                'executedPaths'      => 0,
+                'ccn'                => 0,
+                'coverage'           => 0,
+                'crap'               => 0,
+                'link'               => $link . $trait['startLine'],
+            ];
+
+            foreach ($trait['methods'] as $methodName => $method) {
+                $methodData                                       = $this->newMethod($traitName, $methodName, $method, $link);
+                $this->traits[$traitName]['methods'][$methodName] = $methodData;
+
+                $this->traits[$traitName]['executableBranches'] += $methodData['executableBranches'];
+                $this->traits[$traitName]['executedBranches'] += $methodData['executedBranches'];
+                $this->traits[$traitName]['executablePaths'] += $methodData['executablePaths'];
+                $this->traits[$traitName]['executedPaths'] += $methodData['executedPaths'];
+
+                $this->numExecutableBranches += $methodData['executableBranches'];
+                $this->numExecutedBranches += $methodData['executedBranches'];
+                $this->numExecutablePaths += $methodData['executablePaths'];
+                $this->numExecutedPaths += $methodData['executedPaths'];
+
+                foreach (range($method['startLine'], $method['endLine']) as $lineNumber) {
+                    $this->codeUnitsByLine[$lineNumber] = [
+                        &$this->traits[$traitName],
+                        &$this->traits[$traitName]['methods'][$methodName],
+                    ];
+                }
+            }
+        }
+    }
+
+    private function processFunctions(array $functions): void
+    {
+        $link = $this->id() . '.html#';
+
+        foreach ($functions as $functionName => $function) {
+            $this->functions[$functionName] = [
+                'functionName'       => $functionName,
+                'namespace'          => $function['namespace'],
+                'signature'          => $function['signature'],
+                'startLine'          => $function['startLine'],
+                'endLine'            => $function['endLine'],
+                'executableLines'    => 0,
+                'executedLines'      => 0,
+                'executableBranches' => 0,
+                'executedBranches'   => 0,
+                'executablePaths'    => 0,
+                'executedPaths'      => 0,
+                'ccn'                => $function['ccn'],
+                'coverage'           => 0,
+                'crap'               => 0,
+                'link'               => $link . $function['startLine'],
+            ];
+
+            foreach (range($function['startLine'], $function['endLine']) as $lineNumber) {
+                $this->codeUnitsByLine[$lineNumber] = [&$this->functions[$functionName]];
+            }
+
+            if (isset($this->functionCoverageData[$functionName]['branches'])) {
+                $this->functions[$functionName]['executableBranches'] = count(
+                    $this->functionCoverageData[$functionName]['branches']
+                );
+
+                $this->functions[$functionName]['executedBranches'] = count(
+                    array_filter(
+                        $this->functionCoverageData[$functionName]['branches'],
+                        static function (array $branch) {
+                            return (bool) $branch['hit'];
+                        }
+                    )
+                );
+            }
+
+            if (isset($this->functionCoverageData[$functionName]['paths'])) {
+                $this->functions[$functionName]['executablePaths'] = count(
+                    $this->functionCoverageData[$functionName]['paths']
+                );
+
+                $this->functions[$functionName]['executedPaths'] = count(
+                    array_filter(
+                        $this->functionCoverageData[$functionName]['paths'],
+                        static function (array $path) {
+                            return (bool) $path['hit'];
+                        }
+                    )
+                );
+            }
+
+            $this->numExecutableBranches += $this->functions[$functionName]['executableBranches'];
+            $this->numExecutedBranches += $this->functions[$functionName]['executedBranches'];
+            $this->numExecutablePaths += $this->functions[$functionName]['executablePaths'];
+            $this->numExecutedPaths += $this->functions[$functionName]['executedPaths'];
+        }
+    }
+
+    private function newMethod(string $className, string $methodName, array $method, string $link): array
+    {
+        $methodData = [
+            'methodName'         => $methodName,
+            'visibility'         => $method['visibility'],
+            'signature'          => $method['signature'],
+            'startLine'          => $method['startLine'],
+            'endLine'            => $method['endLine'],
+            'executableLines'    => 0,
+            'executedLines'      => 0,
+            'executableBranches' => 0,
+            'executedBranches'   => 0,
+            'executablePaths'    => 0,
+            'executedPaths'      => 0,
+            'ccn'                => $method['ccn'],
+            'coverage'           => 0,
+            'crap'               => 0,
+            'link'               => $link . $method['startLine'],
+        ];
+
+        $key = $className . '->' . $methodName;
+
+        if (isset($this->functionCoverageData[$key]['branches'])) {
+            $methodData['executableBranches'] = count(
+                $this->functionCoverageData[$key]['branches']
+            );
+
+            $methodData['executedBranches'] = count(
+                array_filter(
+                    $this->functionCoverageData[$key]['branches'],
+                    static function (array $branch) {
+                        return (bool) $branch['hit'];
+                    }
+                )
+            );
+        }
+
+        if (isset($this->functionCoverageData[$key]['paths'])) {
+            $methodData['executablePaths'] = count(
+                $this->functionCoverageData[$key]['paths']
+            );
+
+            $methodData['executedPaths'] = count(
+                array_filter(
+                    $this->functionCoverageData[$key]['paths'],
+                    static function (array $path) {
+                        return (bool) $path['hit'];
+                    }
+                )
+            );
+        }
+
+        return $methodData;
+    }
+}
diff --git a/vendor/phpunit/php-code-coverage/src/Node/Iterator.php b/vendor/phpunit/php-code-coverage/src/Node/Iterator.php
new file mode 100644
index 0000000000000000000000000000000000000000..d0a5a065400f4c520907ae46071692db10d82524
--- /dev/null
+++ b/vendor/phpunit/php-code-coverage/src/Node/Iterator.php
@@ -0,0 +1,92 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of phpunit/php-code-coverage.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\CodeCoverage\Node;
+
+use function count;
+use RecursiveIterator;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage
+ */
+final class Iterator implements RecursiveIterator
+{
+    /**
+     * @var int
+     */
+    private $position;
+
+    /**
+     * @var AbstractNode[]
+     */
+    private $nodes;
+
+    public function __construct(Directory $node)
+    {
+        $this->nodes = $node->children();
+    }
+
+    /**
+     * Rewinds the Iterator to the first element.
+     */
+    public function rewind(): void
+    {
+        $this->position = 0;
+    }
+
+    /**
+     * Checks if there is a current element after calls to rewind() or next().
+     */
+    public function valid(): bool
+    {
+        return $this->position < count($this->nodes);
+    }
+
+    /**
+     * Returns the key of the current element.
+     */
+    public function key(): int
+    {
+        return $this->position;
+    }
+
+    /**
+     * Returns the current element.
+     */
+    public function current(): ?AbstractNode
+    {
+        return $this->valid() ? $this->nodes[$this->position] : null;
+    }
+
+    /**
+     * Moves forward to next element.
+     */
+    public function next(): void
+    {
+        $this->position++;
+    }
+
+    /**
+     * Returns the sub iterator for the current element.
+     *
+     * @return Iterator
+     */
+    public function getChildren(): self
+    {
+        return new self($this->nodes[$this->position]);
+    }
+
+    /**
+     * Checks whether the current element has children.
+     */
+    public function hasChildren(): bool
+    {
+        return $this->nodes[$this->position] instanceof Directory;
+    }
+}
diff --git a/vendor/phpunit/php-code-coverage/src/Percentage.php b/vendor/phpunit/php-code-coverage/src/Percentage.php
new file mode 100644
index 0000000000000000000000000000000000000000..2a468058c6d38765e0f2401022638272a37873bd
--- /dev/null
+++ b/vendor/phpunit/php-code-coverage/src/Percentage.php
@@ -0,0 +1,66 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of phpunit/php-code-coverage.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\CodeCoverage;
+
+use function sprintf;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage
+ */
+final class Percentage
+{
+    /**
+     * @var float
+     */
+    private $fraction;
+
+    /**
+     * @var float
+     */
+    private $total;
+
+    public static function fromFractionAndTotal(float $fraction, float $total): self
+    {
+        return new self($fraction, $total);
+    }
+
+    private function __construct(float $fraction, float $total)
+    {
+        $this->fraction = $fraction;
+        $this->total    = $total;
+    }
+
+    public function asFloat(): float
+    {
+        if ($this->total > 0) {
+            return (float) ($this->fraction / $this->total) * 100;
+        }
+
+        return 100.0;
+    }
+
+    public function asString(): string
+    {
+        if ($this->total > 0) {
+            return sprintf('%01.2F%%', $this->asFloat());
+        }
+
+        return '';
+    }
+
+    public function asFixedWidthString(): string
+    {
+        if ($this->total > 0) {
+            return sprintf('%6.2F%%', $this->asFloat());
+        }
+
+        return '';
+    }
+}
diff --git a/vendor/phpunit/php-code-coverage/src/ProcessedCodeCoverageData.php b/vendor/phpunit/php-code-coverage/src/ProcessedCodeCoverageData.php
new file mode 100644
index 0000000000000000000000000000000000000000..1ed29ad522d9b8f32d32fbd5ea0a204408c67357
--- /dev/null
+++ b/vendor/phpunit/php-code-coverage/src/ProcessedCodeCoverageData.php
@@ -0,0 +1,255 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of phpunit/php-code-coverage.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\CodeCoverage;
+
+use function array_key_exists;
+use function array_keys;
+use function array_merge;
+use function array_unique;
+use function count;
+use function is_array;
+use function ksort;
+use SebastianBergmann\CodeCoverage\Driver\Driver;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage
+ */
+final class ProcessedCodeCoverageData
+{
+    /**
+     * Line coverage data.
+     * An array of filenames, each having an array of linenumbers, each executable line having an array of testcase ids.
+     *
+     * @var array
+     */
+    private $lineCoverage = [];
+
+    /**
+     * Function coverage data.
+     * Maintains base format of raw data (@see https://xdebug.org/docs/code_coverage), but each 'hit' entry is an array
+     * of testcase ids.
+     *
+     * @var array
+     */
+    private $functionCoverage = [];
+
+    public function initializeUnseenData(RawCodeCoverageData $rawData): void
+    {
+        foreach ($rawData->lineCoverage() as $file => $lines) {
+            if (!isset($this->lineCoverage[$file])) {
+                $this->lineCoverage[$file] = [];
+
+                foreach ($lines as $k => $v) {
+                    $this->lineCoverage[$file][$k] = $v === Driver::LINE_NOT_EXECUTABLE ? null : [];
+                }
+            }
+        }
+
+        foreach ($rawData->functionCoverage() as $file => $functions) {
+            foreach ($functions as $functionName => $functionData) {
+                if (isset($this->functionCoverage[$file][$functionName])) {
+                    $this->initPreviouslySeenFunction($file, $functionName, $functionData);
+                } else {
+                    $this->initPreviouslyUnseenFunction($file, $functionName, $functionData);
+                }
+            }
+        }
+    }
+
+    public function markCodeAsExecutedByTestCase(string $testCaseId, RawCodeCoverageData $executedCode): void
+    {
+        foreach ($executedCode->lineCoverage() as $file => $lines) {
+            foreach ($lines as $k => $v) {
+                if ($v === Driver::LINE_EXECUTED) {
+                    $this->lineCoverage[$file][$k][] = $testCaseId;
+                }
+            }
+        }
+
+        foreach ($executedCode->functionCoverage() as $file => $functions) {
+            foreach ($functions as $functionName => $functionData) {
+                foreach ($functionData['branches'] as $branchId => $branchData) {
+                    if ($branchData['hit'] === Driver::BRANCH_HIT) {
+                        $this->functionCoverage[$file][$functionName]['branches'][$branchId]['hit'][] = $testCaseId;
+                    }
+                }
+
+                foreach ($functionData['paths'] as $pathId => $pathData) {
+                    if ($pathData['hit'] === Driver::BRANCH_HIT) {
+                        $this->functionCoverage[$file][$functionName]['paths'][$pathId]['hit'][] = $testCaseId;
+                    }
+                }
+            }
+        }
+    }
+
+    public function setLineCoverage(array $lineCoverage): void
+    {
+        $this->lineCoverage = $lineCoverage;
+    }
+
+    public function lineCoverage(): array
+    {
+        ksort($this->lineCoverage);
+
+        return $this->lineCoverage;
+    }
+
+    public function setFunctionCoverage(array $functionCoverage): void
+    {
+        $this->functionCoverage = $functionCoverage;
+    }
+
+    public function functionCoverage(): array
+    {
+        ksort($this->functionCoverage);
+
+        return $this->functionCoverage;
+    }
+
+    public function coveredFiles(): array
+    {
+        ksort($this->lineCoverage);
+
+        return array_keys($this->lineCoverage);
+    }
+
+    public function renameFile(string $oldFile, string $newFile): void
+    {
+        $this->lineCoverage[$newFile] = $this->lineCoverage[$oldFile];
+
+        if (isset($this->functionCoverage[$oldFile])) {
+            $this->functionCoverage[$newFile] = $this->functionCoverage[$oldFile];
+        }
+
+        unset($this->lineCoverage[$oldFile], $this->functionCoverage[$oldFile]);
+    }
+
+    public function merge(self $newData): void
+    {
+        foreach ($newData->lineCoverage as $file => $lines) {
+            if (!isset($this->lineCoverage[$file])) {
+                $this->lineCoverage[$file] = $lines;
+
+                continue;
+            }
+
+            // we should compare the lines if any of two contains data
+            $compareLineNumbers = array_unique(
+                array_merge(
+                    array_keys($this->lineCoverage[$file]),
+                    array_keys($newData->lineCoverage[$file])
+                )
+            );
+
+            foreach ($compareLineNumbers as $line) {
+                $thatPriority = $this->priorityForLine($newData->lineCoverage[$file], $line);
+                $thisPriority = $this->priorityForLine($this->lineCoverage[$file], $line);
+
+                if ($thatPriority > $thisPriority) {
+                    $this->lineCoverage[$file][$line] = $newData->lineCoverage[$file][$line];
+                } elseif ($thatPriority === $thisPriority && is_array($this->lineCoverage[$file][$line])) {
+                    $this->lineCoverage[$file][$line] = array_unique(
+                        array_merge($this->lineCoverage[$file][$line], $newData->lineCoverage[$file][$line])
+                    );
+                }
+            }
+        }
+
+        foreach ($newData->functionCoverage as $file => $functions) {
+            if (!isset($this->functionCoverage[$file])) {
+                $this->functionCoverage[$file] = $functions;
+
+                continue;
+            }
+
+            foreach ($functions as $functionName => $functionData) {
+                if (isset($this->functionCoverage[$file][$functionName])) {
+                    $this->initPreviouslySeenFunction($file, $functionName, $functionData);
+                } else {
+                    $this->initPreviouslyUnseenFunction($file, $functionName, $functionData);
+                }
+
+                foreach ($functionData['branches'] as $branchId => $branchData) {
+                    $this->functionCoverage[$file][$functionName]['branches'][$branchId]['hit'] = array_unique(array_merge($this->functionCoverage[$file][$functionName]['branches'][$branchId]['hit'], $branchData['hit']));
+                }
+
+                foreach ($functionData['paths'] as $pathId => $pathData) {
+                    $this->functionCoverage[$file][$functionName]['paths'][$pathId]['hit'] = array_unique(array_merge($this->functionCoverage[$file][$functionName]['paths'][$pathId]['hit'], $pathData['hit']));
+                }
+            }
+        }
+    }
+
+    /**
+     * Determine the priority for a line.
+     *
+     * 1 = the line is not set
+     * 2 = the line has not been tested
+     * 3 = the line is dead code
+     * 4 = the line has been tested
+     *
+     * During a merge, a higher number is better.
+     */
+    private function priorityForLine(array $data, int $line): int
+    {
+        if (!array_key_exists($line, $data)) {
+            return 1;
+        }
+
+        if (is_array($data[$line]) && count($data[$line]) === 0) {
+            return 2;
+        }
+
+        if ($data[$line] === null) {
+            return 3;
+        }
+
+        return 4;
+    }
+
+    /**
+     * For a function we have never seen before, copy all data over and simply init the 'hit' array.
+     */
+    private function initPreviouslyUnseenFunction(string $file, string $functionName, array $functionData): void
+    {
+        $this->functionCoverage[$file][$functionName] = $functionData;
+
+        foreach (array_keys($functionData['branches']) as $branchId) {
+            $this->functionCoverage[$file][$functionName]['branches'][$branchId]['hit'] = [];
+        }
+
+        foreach (array_keys($functionData['paths']) as $pathId) {
+            $this->functionCoverage[$file][$functionName]['paths'][$pathId]['hit'] = [];
+        }
+    }
+
+    /**
+     * For a function we have seen before, only copy over and init the 'hit' array for any unseen branches and paths.
+     * Techniques such as mocking and where the contents of a file are different vary during tests (e.g. compiling
+     * containers) mean that the functions inside a file cannot be relied upon to be static.
+     */
+    private function initPreviouslySeenFunction(string $file, string $functionName, array $functionData): void
+    {
+        foreach ($functionData['branches'] as $branchId => $branchData) {
+            if (!isset($this->functionCoverage[$file][$functionName]['branches'][$branchId])) {
+                $this->functionCoverage[$file][$functionName]['branches'][$branchId]        = $branchData;
+                $this->functionCoverage[$file][$functionName]['branches'][$branchId]['hit'] = [];
+            }
+        }
+
+        foreach ($functionData['paths'] as $pathId => $pathData) {
+            if (!isset($this->functionCoverage[$file][$functionName]['paths'][$pathId])) {
+                $this->functionCoverage[$file][$functionName]['paths'][$pathId]        = $pathData;
+                $this->functionCoverage[$file][$functionName]['paths'][$pathId]['hit'] = [];
+            }
+        }
+    }
+}
diff --git a/vendor/phpunit/php-code-coverage/src/RawCodeCoverageData.php b/vendor/phpunit/php-code-coverage/src/RawCodeCoverageData.php
new file mode 100644
index 0000000000000000000000000000000000000000..ae5044ffeb628d313c99dc91930e921fad35b1e6
--- /dev/null
+++ b/vendor/phpunit/php-code-coverage/src/RawCodeCoverageData.php
@@ -0,0 +1,227 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of phpunit/php-code-coverage.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\CodeCoverage;
+
+use function array_diff;
+use function array_diff_key;
+use function array_flip;
+use function array_intersect;
+use function array_intersect_key;
+use function count;
+use function file;
+use function in_array;
+use function range;
+use SebastianBergmann\CodeCoverage\Driver\Driver;
+use SebastianBergmann\CodeCoverage\StaticAnalysis\UncoveredFileAnalyser;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage
+ */
+final class RawCodeCoverageData
+{
+    /**
+     * @var array<string, array<int>>
+     */
+    private static $emptyLineCache = [];
+
+    /**
+     * @var array
+     *
+     * @see https://xdebug.org/docs/code_coverage for format
+     */
+    private $lineCoverage;
+
+    /**
+     * @var array
+     *
+     * @see https://xdebug.org/docs/code_coverage for format
+     */
+    private $functionCoverage;
+
+    public static function fromXdebugWithoutPathCoverage(array $rawCoverage): self
+    {
+        return new self($rawCoverage, []);
+    }
+
+    public static function fromXdebugWithPathCoverage(array $rawCoverage): self
+    {
+        $lineCoverage     = [];
+        $functionCoverage = [];
+
+        foreach ($rawCoverage as $file => $fileCoverageData) {
+            $lineCoverage[$file]     = $fileCoverageData['lines'];
+            $functionCoverage[$file] = $fileCoverageData['functions'];
+        }
+
+        return new self($lineCoverage, $functionCoverage);
+    }
+
+    public static function fromXdebugWithMixedCoverage(array $rawCoverage): self
+    {
+        $lineCoverage     = [];
+        $functionCoverage = [];
+
+        foreach ($rawCoverage as $file => $fileCoverageData) {
+            if (!isset($fileCoverageData['functions'])) {
+                // Current file does not have functions, so line coverage
+                // is stored in $fileCoverageData, not in $fileCoverageData['lines']
+                $lineCoverage[$file] = $fileCoverageData;
+
+                continue;
+            }
+
+            $lineCoverage[$file]     = $fileCoverageData['lines'];
+            $functionCoverage[$file] = $fileCoverageData['functions'];
+        }
+
+        return new self($lineCoverage, $functionCoverage);
+    }
+
+    public static function fromUncoveredFile(string $filename, UncoveredFileAnalyser $uncoveredFileAnalyser): self
+    {
+        $lineCoverage = [];
+
+        foreach ($uncoveredFileAnalyser->executableLinesIn($filename) as $line) {
+            $lineCoverage[$line] = Driver::LINE_NOT_EXECUTED;
+        }
+
+        return new self([$filename => $lineCoverage], []);
+    }
+
+    private function __construct(array $lineCoverage, array $functionCoverage)
+    {
+        $this->lineCoverage     = $lineCoverage;
+        $this->functionCoverage = $functionCoverage;
+
+        $this->skipEmptyLines();
+    }
+
+    public function clear(): void
+    {
+        $this->lineCoverage = $this->functionCoverage = [];
+    }
+
+    public function lineCoverage(): array
+    {
+        return $this->lineCoverage;
+    }
+
+    public function functionCoverage(): array
+    {
+        return $this->functionCoverage;
+    }
+
+    public function removeCoverageDataForFile(string $filename): void
+    {
+        unset($this->lineCoverage[$filename], $this->functionCoverage[$filename]);
+    }
+
+    /**
+     * @param int[] $lines
+     */
+    public function keepCoverageDataOnlyForLines(string $filename, array $lines): void
+    {
+        if (!isset($this->lineCoverage[$filename])) {
+            return;
+        }
+
+        $this->lineCoverage[$filename] = array_intersect_key(
+            $this->lineCoverage[$filename],
+            array_flip($lines)
+        );
+
+        if (isset($this->functionCoverage[$filename])) {
+            foreach ($this->functionCoverage[$filename] as $functionName => $functionData) {
+                foreach ($functionData['branches'] as $branchId => $branch) {
+                    if (count(array_diff(range($branch['line_start'], $branch['line_end']), $lines)) > 0) {
+                        unset($this->functionCoverage[$filename][$functionName]['branches'][$branchId]);
+
+                        foreach ($functionData['paths'] as $pathId => $path) {
+                            if (in_array($branchId, $path['path'], true)) {
+                                unset($this->functionCoverage[$filename][$functionName]['paths'][$pathId]);
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     * @param int[] $lines
+     */
+    public function removeCoverageDataForLines(string $filename, array $lines): void
+    {
+        if (empty($lines)) {
+            return;
+        }
+
+        if (!isset($this->lineCoverage[$filename])) {
+            return;
+        }
+
+        $this->lineCoverage[$filename] = array_diff_key(
+            $this->lineCoverage[$filename],
+            array_flip($lines)
+        );
+
+        if (isset($this->functionCoverage[$filename])) {
+            foreach ($this->functionCoverage[$filename] as $functionName => $functionData) {
+                foreach ($functionData['branches'] as $branchId => $branch) {
+                    if (count(array_intersect($lines, range($branch['line_start'], $branch['line_end']))) > 0) {
+                        unset($this->functionCoverage[$filename][$functionName]['branches'][$branchId]);
+
+                        foreach ($functionData['paths'] as $pathId => $path) {
+                            if (in_array($branchId, $path['path'], true)) {
+                                unset($this->functionCoverage[$filename][$functionName]['paths'][$pathId]);
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     * At the end of a file, the PHP interpreter always sees an implicit return. Where this occurs in a file that has
+     * e.g. a class definition, that line cannot be invoked from a test and results in confusing coverage. This engine
+     * implementation detail therefore needs to be masked which is done here by simply ensuring that all empty lines
+     * are skipped over for coverage purposes.
+     *
+     * @see https://github.com/sebastianbergmann/php-code-coverage/issues/799
+     */
+    private function skipEmptyLines(): void
+    {
+        foreach ($this->lineCoverage as $filename => $coverage) {
+            foreach ($this->getEmptyLinesForFile($filename) as $emptyLine) {
+                unset($this->lineCoverage[$filename][$emptyLine]);
+            }
+        }
+    }
+
+    private function getEmptyLinesForFile(string $filename): array
+    {
+        if (!isset(self::$emptyLineCache[$filename])) {
+            self::$emptyLineCache[$filename] = [];
+
+            if (is_file($filename)) {
+                $sourceLines = explode("\n", file_get_contents($filename));
+
+                foreach ($sourceLines as $line => $source) {
+                    if (trim($source) === '') {
+                        self::$emptyLineCache[$filename][] = ($line + 1);
+                    }
+                }
+            }
+        }
+
+        return self::$emptyLineCache[$filename];
+    }
+}
diff --git a/vendor/phpunit/php-code-coverage/src/Report/Clover.php b/vendor/phpunit/php-code-coverage/src/Report/Clover.php
new file mode 100644
index 0000000000000000000000000000000000000000..4634fbafd700b5df4a34d21444d2857ca806e10a
--- /dev/null
+++ b/vendor/phpunit/php-code-coverage/src/Report/Clover.php
@@ -0,0 +1,255 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of phpunit/php-code-coverage.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\CodeCoverage\Report;
+
+use function count;
+use function dirname;
+use function file_put_contents;
+use function is_string;
+use function ksort;
+use function max;
+use function range;
+use function time;
+use DOMDocument;
+use SebastianBergmann\CodeCoverage\CodeCoverage;
+use SebastianBergmann\CodeCoverage\Directory;
+use SebastianBergmann\CodeCoverage\Driver\WriteOperationFailedException;
+use SebastianBergmann\CodeCoverage\Node\File;
+
+final class Clover
+{
+    /**
+     * @throws WriteOperationFailedException
+     */
+    public function process(CodeCoverage $coverage, ?string $target = null, ?string $name = null): string
+    {
+        $time = (string) time();
+
+        $xmlDocument               = new DOMDocument('1.0', 'UTF-8');
+        $xmlDocument->formatOutput = true;
+
+        $xmlCoverage = $xmlDocument->createElement('coverage');
+        $xmlCoverage->setAttribute('generated', $time);
+        $xmlDocument->appendChild($xmlCoverage);
+
+        $xmlProject = $xmlDocument->createElement('project');
+        $xmlProject->setAttribute('timestamp', $time);
+
+        if (is_string($name)) {
+            $xmlProject->setAttribute('name', $name);
+        }
+
+        $xmlCoverage->appendChild($xmlProject);
+
+        $packages = [];
+        $report   = $coverage->getReport();
+
+        foreach ($report as $item) {
+            if (!$item instanceof File) {
+                continue;
+            }
+
+            /* @var File $item */
+
+            $xmlFile = $xmlDocument->createElement('file');
+            $xmlFile->setAttribute('name', $item->pathAsString());
+
+            $classes      = $item->classesAndTraits();
+            $coverageData = $item->lineCoverageData();
+            $lines        = [];
+            $namespace    = 'global';
+
+            foreach ($classes as $className => $class) {
+                $classStatements        = 0;
+                $coveredClassStatements = 0;
+                $coveredMethods         = 0;
+                $classMethods           = 0;
+
+                foreach ($class['methods'] as $methodName => $method) {
+                    if ($method['executableLines'] == 0) {
+                        continue;
+                    }
+
+                    $classMethods++;
+                    $classStatements += $method['executableLines'];
+                    $coveredClassStatements += $method['executedLines'];
+
+                    if ($method['coverage'] == 100) {
+                        $coveredMethods++;
+                    }
+
+                    $methodCount = 0;
+
+                    foreach (range($method['startLine'], $method['endLine']) as $line) {
+                        if (isset($coverageData[$line]) && ($coverageData[$line] !== null)) {
+                            $methodCount = max($methodCount, count($coverageData[$line]));
+                        }
+                    }
+
+                    $lines[$method['startLine']] = [
+                        'ccn'        => $method['ccn'],
+                        'count'      => $methodCount,
+                        'crap'       => $method['crap'],
+                        'type'       => 'method',
+                        'visibility' => $method['visibility'],
+                        'name'       => $methodName,
+                    ];
+                }
+
+                if (!empty($class['package']['namespace'])) {
+                    $namespace = $class['package']['namespace'];
+                }
+
+                $xmlClass = $xmlDocument->createElement('class');
+                $xmlClass->setAttribute('name', $className);
+                $xmlClass->setAttribute('namespace', $namespace);
+
+                if (!empty($class['package']['fullPackage'])) {
+                    $xmlClass->setAttribute(
+                        'fullPackage',
+                        $class['package']['fullPackage']
+                    );
+                }
+
+                if (!empty($class['package']['category'])) {
+                    $xmlClass->setAttribute(
+                        'category',
+                        $class['package']['category']
+                    );
+                }
+
+                if (!empty($class['package']['package'])) {
+                    $xmlClass->setAttribute(
+                        'package',
+                        $class['package']['package']
+                    );
+                }
+
+                if (!empty($class['package']['subpackage'])) {
+                    $xmlClass->setAttribute(
+                        'subpackage',
+                        $class['package']['subpackage']
+                    );
+                }
+
+                $xmlFile->appendChild($xmlClass);
+
+                $xmlMetrics = $xmlDocument->createElement('metrics');
+                $xmlMetrics->setAttribute('complexity', (string) $class['ccn']);
+                $xmlMetrics->setAttribute('methods', (string) $classMethods);
+                $xmlMetrics->setAttribute('coveredmethods', (string) $coveredMethods);
+                $xmlMetrics->setAttribute('conditionals', (string) $class['executableBranches']);
+                $xmlMetrics->setAttribute('coveredconditionals', (string) $class['executedBranches']);
+                $xmlMetrics->setAttribute('statements', (string) $classStatements);
+                $xmlMetrics->setAttribute('coveredstatements', (string) $coveredClassStatements);
+                $xmlMetrics->setAttribute('elements', (string) ($classMethods + $classStatements + $class['executableBranches']));
+                $xmlMetrics->setAttribute('coveredelements', (string) ($coveredMethods + $coveredClassStatements + $class['executedBranches']));
+                $xmlClass->appendChild($xmlMetrics);
+            }
+
+            foreach ($coverageData as $line => $data) {
+                if ($data === null || isset($lines[$line])) {
+                    continue;
+                }
+
+                $lines[$line] = [
+                    'count' => count($data), 'type' => 'stmt',
+                ];
+            }
+
+            ksort($lines);
+
+            foreach ($lines as $line => $data) {
+                $xmlLine = $xmlDocument->createElement('line');
+                $xmlLine->setAttribute('num', (string) $line);
+                $xmlLine->setAttribute('type', $data['type']);
+
+                if (isset($data['name'])) {
+                    $xmlLine->setAttribute('name', $data['name']);
+                }
+
+                if (isset($data['visibility'])) {
+                    $xmlLine->setAttribute('visibility', $data['visibility']);
+                }
+
+                if (isset($data['ccn'])) {
+                    $xmlLine->setAttribute('complexity', (string) $data['ccn']);
+                }
+
+                if (isset($data['crap'])) {
+                    $xmlLine->setAttribute('crap', (string) $data['crap']);
+                }
+
+                $xmlLine->setAttribute('count', (string) $data['count']);
+                $xmlFile->appendChild($xmlLine);
+            }
+
+            $linesOfCode = $item->linesOfCode();
+
+            $xmlMetrics = $xmlDocument->createElement('metrics');
+            $xmlMetrics->setAttribute('loc', (string) $linesOfCode->linesOfCode());
+            $xmlMetrics->setAttribute('ncloc', (string) $linesOfCode->nonCommentLinesOfCode());
+            $xmlMetrics->setAttribute('classes', (string) $item->numberOfClassesAndTraits());
+            $xmlMetrics->setAttribute('methods', (string) $item->numberOfMethods());
+            $xmlMetrics->setAttribute('coveredmethods', (string) $item->numberOfTestedMethods());
+            $xmlMetrics->setAttribute('conditionals', (string) $item->numberOfExecutableBranches());
+            $xmlMetrics->setAttribute('coveredconditionals', (string) $item->numberOfExecutedBranches());
+            $xmlMetrics->setAttribute('statements', (string) $item->numberOfExecutableLines());
+            $xmlMetrics->setAttribute('coveredstatements', (string) $item->numberOfExecutedLines());
+            $xmlMetrics->setAttribute('elements', (string) ($item->numberOfMethods() + $item->numberOfExecutableLines() + $item->numberOfExecutableBranches()));
+            $xmlMetrics->setAttribute('coveredelements', (string) ($item->numberOfTestedMethods() + $item->numberOfExecutedLines() + $item->numberOfExecutedBranches()));
+            $xmlFile->appendChild($xmlMetrics);
+
+            if ($namespace === 'global') {
+                $xmlProject->appendChild($xmlFile);
+            } else {
+                if (!isset($packages[$namespace])) {
+                    $packages[$namespace] = $xmlDocument->createElement(
+                        'package'
+                    );
+
+                    $packages[$namespace]->setAttribute('name', $namespace);
+                    $xmlProject->appendChild($packages[$namespace]);
+                }
+
+                $packages[$namespace]->appendChild($xmlFile);
+            }
+        }
+
+        $linesOfCode = $report->linesOfCode();
+
+        $xmlMetrics = $xmlDocument->createElement('metrics');
+        $xmlMetrics->setAttribute('files', (string) count($report));
+        $xmlMetrics->setAttribute('loc', (string) $linesOfCode->linesOfCode());
+        $xmlMetrics->setAttribute('ncloc', (string) $linesOfCode->nonCommentLinesOfCode());
+        $xmlMetrics->setAttribute('classes', (string) $report->numberOfClassesAndTraits());
+        $xmlMetrics->setAttribute('methods', (string) $report->numberOfMethods());
+        $xmlMetrics->setAttribute('coveredmethods', (string) $report->numberOfTestedMethods());
+        $xmlMetrics->setAttribute('conditionals', (string) $report->numberOfExecutableBranches());
+        $xmlMetrics->setAttribute('coveredconditionals', (string) $report->numberOfExecutedBranches());
+        $xmlMetrics->setAttribute('statements', (string) $report->numberOfExecutableLines());
+        $xmlMetrics->setAttribute('coveredstatements', (string) $report->numberOfExecutedLines());
+        $xmlMetrics->setAttribute('elements', (string) ($report->numberOfMethods() + $report->numberOfExecutableLines() + $report->numberOfExecutableBranches()));
+        $xmlMetrics->setAttribute('coveredelements', (string) ($report->numberOfTestedMethods() + $report->numberOfExecutedLines() + $report->numberOfExecutedBranches()));
+        $xmlProject->appendChild($xmlMetrics);
+
+        $buffer = $xmlDocument->saveXML();
+
+        if ($target !== null) {
+            Directory::create(dirname($target));
+
+            if (@file_put_contents($target, $buffer) === false) {
+                throw new WriteOperationFailedException($target);
+            }
+        }
+
+        return $buffer;
+    }
+}
diff --git a/vendor/phpunit/php-code-coverage/src/Report/Cobertura.php b/vendor/phpunit/php-code-coverage/src/Report/Cobertura.php
new file mode 100644
index 0000000000000000000000000000000000000000..16801a1a8795699872bde2f898f4e51fcd0ae2b2
--- /dev/null
+++ b/vendor/phpunit/php-code-coverage/src/Report/Cobertura.php
@@ -0,0 +1,302 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of phpunit/php-code-coverage.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\CodeCoverage\Report;
+
+use function count;
+use function dirname;
+use function file_put_contents;
+use function range;
+use function time;
+use DOMImplementation;
+use SebastianBergmann\CodeCoverage\CodeCoverage;
+use SebastianBergmann\CodeCoverage\Directory;
+use SebastianBergmann\CodeCoverage\Driver\WriteOperationFailedException;
+use SebastianBergmann\CodeCoverage\Node\File;
+
+final class Cobertura
+{
+    /**
+     * @throws WriteOperationFailedException
+     */
+    public function process(CodeCoverage $coverage, ?string $target = null, ?string $name = null): string
+    {
+        $time = (string) time();
+
+        $report = $coverage->getReport();
+
+        $implementation = new DOMImplementation;
+
+        $documentType = $implementation->createDocumentType(
+            'coverage',
+            '',
+            'http://cobertura.sourceforge.net/xml/coverage-04.dtd'
+        );
+
+        $document               = $implementation->createDocument('', '', $documentType);
+        $document->xmlVersion   = '1.0';
+        $document->encoding     = 'UTF-8';
+        $document->formatOutput = true;
+
+        $coverageElement = $document->createElement('coverage');
+
+        $linesValid   = $report->numberOfExecutableLines();
+        $linesCovered = $report->numberOfExecutedLines();
+        $lineRate     = $linesValid === 0 ? 0 : ($linesCovered / $linesValid);
+        $coverageElement->setAttribute('line-rate', (string) $lineRate);
+
+        $branchesValid   = $report->numberOfExecutableBranches();
+        $branchesCovered = $report->numberOfExecutedBranches();
+        $branchRate      = $branchesValid === 0 ? 0 : ($branchesCovered / $branchesValid);
+        $coverageElement->setAttribute('branch-rate', (string) $branchRate);
+
+        $coverageElement->setAttribute('lines-covered', (string) $report->numberOfExecutedLines());
+        $coverageElement->setAttribute('lines-valid', (string) $report->numberOfExecutableLines());
+        $coverageElement->setAttribute('branches-covered', (string) $report->numberOfExecutedBranches());
+        $coverageElement->setAttribute('branches-valid', (string) $report->numberOfExecutableBranches());
+        $coverageElement->setAttribute('complexity', '');
+        $coverageElement->setAttribute('version', '0.4');
+        $coverageElement->setAttribute('timestamp', $time);
+
+        $document->appendChild($coverageElement);
+
+        $sourcesElement = $document->createElement('sources');
+        $coverageElement->appendChild($sourcesElement);
+
+        $sourceElement = $document->createElement('source', $report->pathAsString());
+        $sourcesElement->appendChild($sourceElement);
+
+        $packagesElement = $document->createElement('packages');
+        $coverageElement->appendChild($packagesElement);
+
+        $complexity = 0;
+
+        foreach ($report as $item) {
+            if (!$item instanceof File) {
+                continue;
+            }
+
+            $packageElement    = $document->createElement('package');
+            $packageComplexity = 0;
+            $packageName       = $name ?? '';
+
+            $packageElement->setAttribute('name', $packageName);
+
+            $linesValid   = $item->numberOfExecutableLines();
+            $linesCovered = $item->numberOfExecutedLines();
+            $lineRate     = $linesValid === 0 ? 0 : ($linesCovered / $linesValid);
+
+            $packageElement->setAttribute('line-rate', (string) $lineRate);
+
+            $branchesValid   = $item->numberOfExecutableBranches();
+            $branchesCovered = $item->numberOfExecutedBranches();
+            $branchRate      = $branchesValid === 0 ? 0 : ($branchesCovered / $branchesValid);
+
+            $packageElement->setAttribute('branch-rate', (string) $branchRate);
+
+            $packageElement->setAttribute('complexity', '');
+            $packagesElement->appendChild($packageElement);
+
+            $classesElement = $document->createElement('classes');
+
+            $packageElement->appendChild($classesElement);
+
+            $classes      = $item->classesAndTraits();
+            $coverageData = $item->lineCoverageData();
+
+            foreach ($classes as $className => $class) {
+                $complexity += $class['ccn'];
+                $packageComplexity += $class['ccn'];
+
+                if (!empty($class['package']['namespace'])) {
+                    $className = $class['package']['namespace'] . '\\' . $className;
+                }
+
+                $linesValid   = $class['executableLines'];
+                $linesCovered = $class['executedLines'];
+                $lineRate     = $linesValid === 0 ? 0 : ($linesCovered / $linesValid);
+
+                $branchesValid   = $class['executableBranches'];
+                $branchesCovered = $class['executedBranches'];
+                $branchRate      = $branchesValid === 0 ? 0 : ($branchesCovered / $branchesValid);
+
+                $classElement = $document->createElement('class');
+
+                $classElement->setAttribute('name', $className);
+                $classElement->setAttribute('filename', str_replace($report->pathAsString() . DIRECTORY_SEPARATOR, '', $item->pathAsString()));
+                $classElement->setAttribute('line-rate', (string) $lineRate);
+                $classElement->setAttribute('branch-rate', (string) $branchRate);
+                $classElement->setAttribute('complexity', (string) $class['ccn']);
+
+                $classesElement->appendChild($classElement);
+
+                $methodsElement = $document->createElement('methods');
+
+                $classElement->appendChild($methodsElement);
+
+                $classLinesElement = $document->createElement('lines');
+
+                $classElement->appendChild($classLinesElement);
+
+                foreach ($class['methods'] as $methodName => $method) {
+                    if ($method['executableLines'] === 0) {
+                        continue;
+                    }
+
+                    $linesValid   = $method['executableLines'];
+                    $linesCovered = $method['executedLines'];
+                    $lineRate     = $linesValid === 0 ? 0 : ($linesCovered / $linesValid);
+
+                    $branchesValid   = $method['executableBranches'];
+                    $branchesCovered = $method['executedBranches'];
+                    $branchRate      = $branchesValid === 0 ? 0 : ($branchesCovered / $branchesValid);
+
+                    $methodElement = $document->createElement('method');
+
+                    $methodElement->setAttribute('name', $methodName);
+                    $methodElement->setAttribute('signature', $method['signature']);
+                    $methodElement->setAttribute('line-rate', (string) $lineRate);
+                    $methodElement->setAttribute('branch-rate', (string) $branchRate);
+                    $methodElement->setAttribute('complexity', (string) $method['ccn']);
+
+                    $methodLinesElement = $document->createElement('lines');
+
+                    $methodElement->appendChild($methodLinesElement);
+
+                    foreach (range($method['startLine'], $method['endLine']) as $line) {
+                        if (!isset($coverageData[$line]) || $coverageData[$line] === null) {
+                            continue;
+                        }
+                        $methodLineElement = $document->createElement('line');
+
+                        $methodLineElement->setAttribute('number', (string) $line);
+                        $methodLineElement->setAttribute('hits', (string) count($coverageData[$line]));
+
+                        $methodLinesElement->appendChild($methodLineElement);
+
+                        $classLineElement = $methodLineElement->cloneNode();
+
+                        $classLinesElement->appendChild($classLineElement);
+                    }
+
+                    $methodsElement->appendChild($methodElement);
+                }
+            }
+
+            if ($report->numberOfFunctions() === 0) {
+                $packageElement->setAttribute('complexity', (string) $packageComplexity);
+
+                continue;
+            }
+
+            $functionsComplexity      = 0;
+            $functionsLinesValid      = 0;
+            $functionsLinesCovered    = 0;
+            $functionsBranchesValid   = 0;
+            $functionsBranchesCovered = 0;
+
+            $classElement = $document->createElement('class');
+            $classElement->setAttribute('name', basename($item->pathAsString()));
+            $classElement->setAttribute('filename', str_replace($report->pathAsString() . DIRECTORY_SEPARATOR, '', $item->pathAsString()));
+
+            $methodsElement = $document->createElement('methods');
+
+            $classElement->appendChild($methodsElement);
+
+            $classLinesElement = $document->createElement('lines');
+
+            $classElement->appendChild($classLinesElement);
+
+            $functions = $report->functions();
+
+            foreach ($functions as $functionName => $function) {
+                if ($function['executableLines'] === 0) {
+                    continue;
+                }
+
+                $complexity += $function['ccn'];
+                $packageComplexity += $function['ccn'];
+                $functionsComplexity += $function['ccn'];
+
+                $linesValid   = $function['executableLines'];
+                $linesCovered = $function['executedLines'];
+                $lineRate     = $linesValid === 0 ? 0 : ($linesCovered / $linesValid);
+
+                $functionsLinesValid += $linesValid;
+                $functionsLinesCovered += $linesCovered;
+
+                $branchesValid   = $function['executableBranches'];
+                $branchesCovered = $function['executedBranches'];
+                $branchRate      = $branchesValid === 0 ? 0 : ($branchesCovered / $branchesValid);
+
+                $functionsBranchesValid += $branchesValid;
+                $functionsBranchesCovered += $branchesValid;
+
+                $methodElement = $document->createElement('method');
+
+                $methodElement->setAttribute('name', $functionName);
+                $methodElement->setAttribute('signature', $function['signature']);
+                $methodElement->setAttribute('line-rate', (string) $lineRate);
+                $methodElement->setAttribute('branch-rate', (string) $branchRate);
+                $methodElement->setAttribute('complexity', (string) $function['ccn']);
+
+                $methodLinesElement = $document->createElement('lines');
+
+                $methodElement->appendChild($methodLinesElement);
+
+                foreach (range($function['startLine'], $function['endLine']) as $line) {
+                    if (!isset($coverageData[$line]) || $coverageData[$line] === null) {
+                        continue;
+                    }
+                    $methodLineElement = $document->createElement('line');
+
+                    $methodLineElement->setAttribute('number', (string) $line);
+                    $methodLineElement->setAttribute('hits', (string) count($coverageData[$line]));
+
+                    $methodLinesElement->appendChild($methodLineElement);
+
+                    $classLineElement = $methodLineElement->cloneNode();
+
+                    $classLinesElement->appendChild($classLineElement);
+                }
+
+                $methodsElement->appendChild($methodElement);
+            }
+
+            $packageElement->setAttribute('complexity', (string) $packageComplexity);
+
+            if ($functionsLinesValid === 0) {
+                continue;
+            }
+
+            $lineRate   = $functionsLinesCovered / $functionsLinesValid;
+            $branchRate = $functionsBranchesValid === 0 ? 0 : ($functionsBranchesCovered / $functionsBranchesValid);
+
+            $classElement->setAttribute('line-rate', (string) $lineRate);
+            $classElement->setAttribute('branch-rate', (string) $branchRate);
+            $classElement->setAttribute('complexity', (string) $functionsComplexity);
+
+            $classesElement->appendChild($classElement);
+        }
+
+        $coverageElement->setAttribute('complexity', (string) $complexity);
+
+        $buffer = $document->saveXML();
+
+        if ($target !== null) {
+            Directory::create(dirname($target));
+
+            if (@file_put_contents($target, $buffer) === false) {
+                throw new WriteOperationFailedException($target);
+            }
+        }
+
+        return $buffer;
+    }
+}
diff --git a/vendor/phpunit/php-code-coverage/src/Report/Crap4j.php b/vendor/phpunit/php-code-coverage/src/Report/Crap4j.php
new file mode 100644
index 0000000000000000000000000000000000000000..bed16bcdd7aaa674af34cac7a6607470b159c1e6
--- /dev/null
+++ b/vendor/phpunit/php-code-coverage/src/Report/Crap4j.php
@@ -0,0 +1,153 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of phpunit/php-code-coverage.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\CodeCoverage\Report;
+
+use function date;
+use function dirname;
+use function file_put_contents;
+use function htmlspecialchars;
+use function is_string;
+use function round;
+use DOMDocument;
+use SebastianBergmann\CodeCoverage\CodeCoverage;
+use SebastianBergmann\CodeCoverage\Directory;
+use SebastianBergmann\CodeCoverage\Driver\WriteOperationFailedException;
+use SebastianBergmann\CodeCoverage\Node\File;
+
+final class Crap4j
+{
+    /**
+     * @var int
+     */
+    private $threshold;
+
+    public function __construct(int $threshold = 30)
+    {
+        $this->threshold = $threshold;
+    }
+
+    /**
+     * @throws WriteOperationFailedException
+     */
+    public function process(CodeCoverage $coverage, ?string $target = null, ?string $name = null): string
+    {
+        $document               = new DOMDocument('1.0', 'UTF-8');
+        $document->formatOutput = true;
+
+        $root = $document->createElement('crap_result');
+        $document->appendChild($root);
+
+        $project = $document->createElement('project', is_string($name) ? $name : '');
+        $root->appendChild($project);
+        $root->appendChild($document->createElement('timestamp', date('Y-m-d H:i:s')));
+
+        $stats       = $document->createElement('stats');
+        $methodsNode = $document->createElement('methods');
+
+        $report = $coverage->getReport();
+        unset($coverage);
+
+        $fullMethodCount     = 0;
+        $fullCrapMethodCount = 0;
+        $fullCrapLoad        = 0;
+        $fullCrap            = 0;
+
+        foreach ($report as $item) {
+            $namespace = 'global';
+
+            if (!$item instanceof File) {
+                continue;
+            }
+
+            $file = $document->createElement('file');
+            $file->setAttribute('name', $item->pathAsString());
+
+            $classes = $item->classesAndTraits();
+
+            foreach ($classes as $className => $class) {
+                foreach ($class['methods'] as $methodName => $method) {
+                    $crapLoad = $this->crapLoad((float) $method['crap'], $method['ccn'], $method['coverage']);
+
+                    $fullCrap += $method['crap'];
+                    $fullCrapLoad += $crapLoad;
+                    $fullMethodCount++;
+
+                    if ($method['crap'] >= $this->threshold) {
+                        $fullCrapMethodCount++;
+                    }
+
+                    $methodNode = $document->createElement('method');
+
+                    if (!empty($class['namespace'])) {
+                        $namespace = $class['namespace'];
+                    }
+
+                    $methodNode->appendChild($document->createElement('package', $namespace));
+                    $methodNode->appendChild($document->createElement('className', $className));
+                    $methodNode->appendChild($document->createElement('methodName', $methodName));
+                    $methodNode->appendChild($document->createElement('methodSignature', htmlspecialchars($method['signature'])));
+                    $methodNode->appendChild($document->createElement('fullMethod', htmlspecialchars($method['signature'])));
+                    $methodNode->appendChild($document->createElement('crap', (string) $this->roundValue((float) $method['crap'])));
+                    $methodNode->appendChild($document->createElement('complexity', (string) $method['ccn']));
+                    $methodNode->appendChild($document->createElement('coverage', (string) $this->roundValue($method['coverage'])));
+                    $methodNode->appendChild($document->createElement('crapLoad', (string) round($crapLoad)));
+
+                    $methodsNode->appendChild($methodNode);
+                }
+            }
+        }
+
+        $stats->appendChild($document->createElement('name', 'Method Crap Stats'));
+        $stats->appendChild($document->createElement('methodCount', (string) $fullMethodCount));
+        $stats->appendChild($document->createElement('crapMethodCount', (string) $fullCrapMethodCount));
+        $stats->appendChild($document->createElement('crapLoad', (string) round($fullCrapLoad)));
+        $stats->appendChild($document->createElement('totalCrap', (string) $fullCrap));
+
+        $crapMethodPercent = 0;
+
+        if ($fullMethodCount > 0) {
+            $crapMethodPercent = $this->roundValue((100 * $fullCrapMethodCount) / $fullMethodCount);
+        }
+
+        $stats->appendChild($document->createElement('crapMethodPercent', (string) $crapMethodPercent));
+
+        $root->appendChild($stats);
+        $root->appendChild($methodsNode);
+
+        $buffer = $document->saveXML();
+
+        if ($target !== null) {
+            Directory::create(dirname($target));
+
+            if (@file_put_contents($target, $buffer) === false) {
+                throw new WriteOperationFailedException($target);
+            }
+        }
+
+        return $buffer;
+    }
+
+    private function crapLoad(float $crapValue, int $cyclomaticComplexity, float $coveragePercent): float
+    {
+        $crapLoad = 0;
+
+        if ($crapValue >= $this->threshold) {
+            $crapLoad += $cyclomaticComplexity * (1.0 - $coveragePercent / 100);
+            $crapLoad += $cyclomaticComplexity / $this->threshold;
+        }
+
+        return $crapLoad;
+    }
+
+    private function roundValue(float $value): float
+    {
+        return round($value, 2);
+    }
+}
diff --git a/vendor/phpunit/php-code-coverage/src/Report/Html/Facade.php b/vendor/phpunit/php-code-coverage/src/Report/Html/Facade.php
new file mode 100644
index 0000000000000000000000000000000000000000..c22b5ec3dd7f0cb186879c6e4862cd23fa9452cd
--- /dev/null
+++ b/vendor/phpunit/php-code-coverage/src/Report/Html/Facade.php
@@ -0,0 +1,140 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of phpunit/php-code-coverage.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\CodeCoverage\Report\Html;
+
+use const DIRECTORY_SEPARATOR;
+use function copy;
+use function date;
+use function dirname;
+use function substr;
+use SebastianBergmann\CodeCoverage\CodeCoverage;
+use SebastianBergmann\CodeCoverage\Directory as DirectoryUtil;
+use SebastianBergmann\CodeCoverage\Node\Directory as DirectoryNode;
+
+final class Facade
+{
+    /**
+     * @var string
+     */
+    private $templatePath;
+
+    /**
+     * @var string
+     */
+    private $generator;
+
+    /**
+     * @var int
+     */
+    private $lowUpperBound;
+
+    /**
+     * @var int
+     */
+    private $highLowerBound;
+
+    public function __construct(int $lowUpperBound = 50, int $highLowerBound = 90, string $generator = '')
+    {
+        $this->generator      = $generator;
+        $this->highLowerBound = $highLowerBound;
+        $this->lowUpperBound  = $lowUpperBound;
+        $this->templatePath   = __DIR__ . '/Renderer/Template/';
+    }
+
+    public function process(CodeCoverage $coverage, string $target): void
+    {
+        $target = $this->directory($target);
+        $report = $coverage->getReport();
+        $date   = (string) date('D M j G:i:s T Y');
+
+        $dashboard = new Dashboard(
+            $this->templatePath,
+            $this->generator,
+            $date,
+            $this->lowUpperBound,
+            $this->highLowerBound,
+            $coverage->collectsBranchAndPathCoverage()
+        );
+
+        $directory = new Directory(
+            $this->templatePath,
+            $this->generator,
+            $date,
+            $this->lowUpperBound,
+            $this->highLowerBound,
+            $coverage->collectsBranchAndPathCoverage()
+        );
+
+        $file = new File(
+            $this->templatePath,
+            $this->generator,
+            $date,
+            $this->lowUpperBound,
+            $this->highLowerBound,
+            $coverage->collectsBranchAndPathCoverage()
+        );
+
+        $directory->render($report, $target . 'index.html');
+        $dashboard->render($report, $target . 'dashboard.html');
+
+        foreach ($report as $node) {
+            $id = $node->id();
+
+            if ($node instanceof DirectoryNode) {
+                DirectoryUtil::create($target . $id);
+
+                $directory->render($node, $target . $id . '/index.html');
+                $dashboard->render($node, $target . $id . '/dashboard.html');
+            } else {
+                $dir = dirname($target . $id);
+
+                DirectoryUtil::create($dir);
+
+                $file->render($node, $target . $id);
+            }
+        }
+
+        $this->copyFiles($target);
+    }
+
+    private function copyFiles(string $target): void
+    {
+        $dir = $this->directory($target . '_css');
+
+        copy($this->templatePath . 'css/bootstrap.min.css', $dir . 'bootstrap.min.css');
+        copy($this->templatePath . 'css/nv.d3.min.css', $dir . 'nv.d3.min.css');
+        copy($this->templatePath . 'css/style.css', $dir . 'style.css');
+        copy($this->templatePath . 'css/custom.css', $dir . 'custom.css');
+        copy($this->templatePath . 'css/octicons.css', $dir . 'octicons.css');
+
+        $dir = $this->directory($target . '_icons');
+        copy($this->templatePath . 'icons/file-code.svg', $dir . 'file-code.svg');
+        copy($this->templatePath . 'icons/file-directory.svg', $dir . 'file-directory.svg');
+
+        $dir = $this->directory($target . '_js');
+        copy($this->templatePath . 'js/bootstrap.min.js', $dir . 'bootstrap.min.js');
+        copy($this->templatePath . 'js/popper.min.js', $dir . 'popper.min.js');
+        copy($this->templatePath . 'js/d3.min.js', $dir . 'd3.min.js');
+        copy($this->templatePath . 'js/jquery.min.js', $dir . 'jquery.min.js');
+        copy($this->templatePath . 'js/nv.d3.min.js', $dir . 'nv.d3.min.js');
+        copy($this->templatePath . 'js/file.js', $dir . 'file.js');
+    }
+
+    private function directory(string $directory): string
+    {
+        if (substr($directory, -1, 1) != DIRECTORY_SEPARATOR) {
+            $directory .= DIRECTORY_SEPARATOR;
+        }
+
+        DirectoryUtil::create($directory);
+
+        return $directory;
+    }
+}
diff --git a/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer.php b/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer.php
new file mode 100644
index 0000000000000000000000000000000000000000..df2753a56fc07de67e9e3e36279a3e96a6635400
--- /dev/null
+++ b/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer.php
@@ -0,0 +1,333 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of phpunit/php-code-coverage.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\CodeCoverage\Report\Html;
+
+use function array_pop;
+use function count;
+use function phpversion;
+use function sprintf;
+use function str_repeat;
+use function substr_count;
+use SebastianBergmann\CodeCoverage\Node\AbstractNode;
+use SebastianBergmann\CodeCoverage\Node\Directory as DirectoryNode;
+use SebastianBergmann\CodeCoverage\Node\File as FileNode;
+use SebastianBergmann\CodeCoverage\Version;
+use SebastianBergmann\Environment\Runtime;
+use SebastianBergmann\Template\Template;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage
+ */
+abstract class Renderer
+{
+    /**
+     * @var string
+     */
+    protected $templatePath;
+
+    /**
+     * @var string
+     */
+    protected $generator;
+
+    /**
+     * @var string
+     */
+    protected $date;
+
+    /**
+     * @var int
+     */
+    protected $lowUpperBound;
+
+    /**
+     * @var int
+     */
+    protected $highLowerBound;
+
+    /**
+     * @var bool
+     */
+    protected $hasBranchCoverage;
+
+    /**
+     * @var string
+     */
+    protected $version;
+
+    public function __construct(string $templatePath, string $generator, string $date, int $lowUpperBound, int $highLowerBound, bool $hasBranchCoverage)
+    {
+        $this->templatePath      = $templatePath;
+        $this->generator         = $generator;
+        $this->date              = $date;
+        $this->lowUpperBound     = $lowUpperBound;
+        $this->highLowerBound    = $highLowerBound;
+        $this->version           = Version::id();
+        $this->hasBranchCoverage = $hasBranchCoverage;
+    }
+
+    protected function renderItemTemplate(Template $template, array $data): string
+    {
+        $numSeparator = '&nbsp;/&nbsp;';
+
+        if (isset($data['numClasses']) && $data['numClasses'] > 0) {
+            $classesLevel = $this->colorLevel($data['testedClassesPercent']);
+
+            $classesNumber = $data['numTestedClasses'] . $numSeparator .
+                $data['numClasses'];
+
+            $classesBar = $this->coverageBar(
+                $data['testedClassesPercent']
+            );
+        } else {
+            $classesLevel                         = '';
+            $classesNumber                        = '0' . $numSeparator . '0';
+            $classesBar                           = '';
+            $data['testedClassesPercentAsString'] = 'n/a';
+        }
+
+        if ($data['numMethods'] > 0) {
+            $methodsLevel = $this->colorLevel($data['testedMethodsPercent']);
+
+            $methodsNumber = $data['numTestedMethods'] . $numSeparator .
+                $data['numMethods'];
+
+            $methodsBar = $this->coverageBar(
+                $data['testedMethodsPercent']
+            );
+        } else {
+            $methodsLevel                         = '';
+            $methodsNumber                        = '0' . $numSeparator . '0';
+            $methodsBar                           = '';
+            $data['testedMethodsPercentAsString'] = 'n/a';
+        }
+
+        if ($data['numExecutableLines'] > 0) {
+            $linesLevel = $this->colorLevel($data['linesExecutedPercent']);
+
+            $linesNumber = $data['numExecutedLines'] . $numSeparator .
+                $data['numExecutableLines'];
+
+            $linesBar = $this->coverageBar(
+                $data['linesExecutedPercent']
+            );
+        } else {
+            $linesLevel                           = '';
+            $linesNumber                          = '0' . $numSeparator . '0';
+            $linesBar                             = '';
+            $data['linesExecutedPercentAsString'] = 'n/a';
+        }
+
+        if ($data['numExecutablePaths'] > 0) {
+            $pathsLevel = $this->colorLevel($data['pathsExecutedPercent']);
+
+            $pathsNumber = $data['numExecutedPaths'] . $numSeparator .
+                $data['numExecutablePaths'];
+
+            $pathsBar = $this->coverageBar(
+                $data['pathsExecutedPercent']
+            );
+        } else {
+            $pathsLevel                           = '';
+            $pathsNumber                          = '0' . $numSeparator . '0';
+            $pathsBar                             = '';
+            $data['pathsExecutedPercentAsString'] = 'n/a';
+        }
+
+        if ($data['numExecutableBranches'] > 0) {
+            $branchesLevel = $this->colorLevel($data['branchesExecutedPercent']);
+
+            $branchesNumber = $data['numExecutedBranches'] . $numSeparator .
+                $data['numExecutableBranches'];
+
+            $branchesBar = $this->coverageBar(
+                $data['branchesExecutedPercent']
+            );
+        } else {
+            $branchesLevel                           = '';
+            $branchesNumber                          = '0' . $numSeparator . '0';
+            $branchesBar                             = '';
+            $data['branchesExecutedPercentAsString'] = 'n/a';
+        }
+
+        $template->setVar(
+            [
+                'icon'                      => $data['icon'] ?? '',
+                'crap'                      => $data['crap'] ?? '',
+                'name'                      => $data['name'],
+                'lines_bar'                 => $linesBar,
+                'lines_executed_percent'    => $data['linesExecutedPercentAsString'],
+                'lines_level'               => $linesLevel,
+                'lines_number'              => $linesNumber,
+                'paths_bar'                 => $pathsBar,
+                'paths_executed_percent'    => $data['pathsExecutedPercentAsString'],
+                'paths_level'               => $pathsLevel,
+                'paths_number'              => $pathsNumber,
+                'branches_bar'              => $branchesBar,
+                'branches_executed_percent' => $data['branchesExecutedPercentAsString'],
+                'branches_level'            => $branchesLevel,
+                'branches_number'           => $branchesNumber,
+                'methods_bar'               => $methodsBar,
+                'methods_tested_percent'    => $data['testedMethodsPercentAsString'],
+                'methods_level'             => $methodsLevel,
+                'methods_number'            => $methodsNumber,
+                'classes_bar'               => $classesBar,
+                'classes_tested_percent'    => $data['testedClassesPercentAsString'] ?? '',
+                'classes_level'             => $classesLevel,
+                'classes_number'            => $classesNumber,
+            ]
+        );
+
+        return $template->render();
+    }
+
+    protected function setCommonTemplateVariables(Template $template, AbstractNode $node): void
+    {
+        $template->setVar(
+            [
+                'id'               => $node->id(),
+                'full_path'        => $node->pathAsString(),
+                'path_to_root'     => $this->pathToRoot($node),
+                'breadcrumbs'      => $this->breadcrumbs($node),
+                'date'             => $this->date,
+                'version'          => $this->version,
+                'runtime'          => $this->runtimeString(),
+                'generator'        => $this->generator,
+                'low_upper_bound'  => $this->lowUpperBound,
+                'high_lower_bound' => $this->highLowerBound,
+            ]
+        );
+    }
+
+    protected function breadcrumbs(AbstractNode $node): string
+    {
+        $breadcrumbs = '';
+        $path        = $node->pathAsArray();
+        $pathToRoot  = [];
+        $max         = count($path);
+
+        if ($node instanceof FileNode) {
+            $max--;
+        }
+
+        for ($i = 0; $i < $max; $i++) {
+            $pathToRoot[] = str_repeat('../', $i);
+        }
+
+        foreach ($path as $step) {
+            if ($step !== $node) {
+                $breadcrumbs .= $this->inactiveBreadcrumb(
+                    $step,
+                    array_pop($pathToRoot)
+                );
+            } else {
+                $breadcrumbs .= $this->activeBreadcrumb($step);
+            }
+        }
+
+        return $breadcrumbs;
+    }
+
+    protected function activeBreadcrumb(AbstractNode $node): string
+    {
+        $buffer = sprintf(
+            '         <li class="breadcrumb-item active">%s</li>' . "\n",
+            $node->name()
+        );
+
+        if ($node instanceof DirectoryNode) {
+            $buffer .= '         <li class="breadcrumb-item">(<a href="dashboard.html">Dashboard</a>)</li>' . "\n";
+        }
+
+        return $buffer;
+    }
+
+    protected function inactiveBreadcrumb(AbstractNode $node, string $pathToRoot): string
+    {
+        return sprintf(
+            '         <li class="breadcrumb-item"><a href="%sindex.html">%s</a></li>' . "\n",
+            $pathToRoot,
+            $node->name()
+        );
+    }
+
+    protected function pathToRoot(AbstractNode $node): string
+    {
+        $id    = $node->id();
+        $depth = substr_count($id, '/');
+
+        if ($id !== 'index' &&
+            $node instanceof DirectoryNode) {
+            $depth++;
+        }
+
+        return str_repeat('../', $depth);
+    }
+
+    protected function coverageBar(float $percent): string
+    {
+        $level = $this->colorLevel($percent);
+
+        $templateName = $this->templatePath . ($this->hasBranchCoverage ? 'coverage_bar_branch.html' : 'coverage_bar.html');
+        $template     = new Template(
+            $templateName,
+            '{{',
+            '}}'
+        );
+
+        $template->setVar(['level' => $level, 'percent' => sprintf('%.2F', $percent)]);
+
+        return $template->render();
+    }
+
+    protected function colorLevel(float $percent): string
+    {
+        if ($percent <= $this->lowUpperBound) {
+            return 'danger';
+        }
+
+        if ($percent > $this->lowUpperBound &&
+            $percent < $this->highLowerBound) {
+            return 'warning';
+        }
+
+        return 'success';
+    }
+
+    private function runtimeString(): string
+    {
+        $runtime = new Runtime;
+
+        $buffer = sprintf(
+            '<a href="%s" target="_top">%s %s</a>',
+            $runtime->getVendorUrl(),
+            $runtime->getName(),
+            $runtime->getVersion()
+        );
+
+        if ($runtime->hasPHPDBGCodeCoverage()) {
+            return $buffer;
+        }
+
+        if ($runtime->hasPCOV()) {
+            $buffer .= sprintf(
+                ' with <a href="https://github.com/krakjoe/pcov">PCOV %s</a>',
+                phpversion('pcov')
+            );
+        } elseif ($runtime->hasXdebug()) {
+            $buffer .= sprintf(
+                ' with <a href="https://xdebug.org/">Xdebug %s</a>',
+                phpversion('xdebug')
+            );
+        }
+
+        return $buffer;
+    }
+}
diff --git a/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Dashboard.php b/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Dashboard.php
new file mode 100644
index 0000000000000000000000000000000000000000..b44870b53d37440b257ce3aeccb3561f68989020
--- /dev/null
+++ b/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Dashboard.php
@@ -0,0 +1,288 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of phpunit/php-code-coverage.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\CodeCoverage\Report\Html;
+
+use function array_values;
+use function arsort;
+use function asort;
+use function count;
+use function explode;
+use function floor;
+use function json_encode;
+use function sprintf;
+use function str_replace;
+use SebastianBergmann\CodeCoverage\Node\AbstractNode;
+use SebastianBergmann\CodeCoverage\Node\Directory as DirectoryNode;
+use SebastianBergmann\Template\Template;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage
+ */
+final class Dashboard extends Renderer
+{
+    public function render(DirectoryNode $node, string $file): void
+    {
+        $classes      = $node->classesAndTraits();
+        $templateName = $this->templatePath . ($this->hasBranchCoverage ? 'dashboard_branch.html' : 'dashboard.html');
+        $template     = new Template(
+            $templateName,
+            '{{',
+            '}}'
+        );
+
+        $this->setCommonTemplateVariables($template, $node);
+
+        $baseLink             = $node->id() . '/';
+        $complexity           = $this->complexity($classes, $baseLink);
+        $coverageDistribution = $this->coverageDistribution($classes);
+        $insufficientCoverage = $this->insufficientCoverage($classes, $baseLink);
+        $projectRisks         = $this->projectRisks($classes, $baseLink);
+
+        $template->setVar(
+            [
+                'insufficient_coverage_classes' => $insufficientCoverage['class'],
+                'insufficient_coverage_methods' => $insufficientCoverage['method'],
+                'project_risks_classes'         => $projectRisks['class'],
+                'project_risks_methods'         => $projectRisks['method'],
+                'complexity_class'              => $complexity['class'],
+                'complexity_method'             => $complexity['method'],
+                'class_coverage_distribution'   => $coverageDistribution['class'],
+                'method_coverage_distribution'  => $coverageDistribution['method'],
+            ]
+        );
+
+        $template->renderTo($file);
+    }
+
+    protected function activeBreadcrumb(AbstractNode $node): string
+    {
+        return sprintf(
+            '         <li class="breadcrumb-item"><a href="index.html">%s</a></li>' . "\n" .
+            '         <li class="breadcrumb-item active">(Dashboard)</li>' . "\n",
+            $node->name()
+        );
+    }
+
+    /**
+     * Returns the data for the Class/Method Complexity charts.
+     */
+    private function complexity(array $classes, string $baseLink): array
+    {
+        $result = ['class' => [], 'method' => []];
+
+        foreach ($classes as $className => $class) {
+            foreach ($class['methods'] as $methodName => $method) {
+                if ($className !== '*') {
+                    $methodName = $className . '::' . $methodName;
+                }
+
+                $result['method'][] = [
+                    $method['coverage'],
+                    $method['ccn'],
+                    sprintf(
+                        '<a href="%s">%s</a>',
+                        str_replace($baseLink, '', $method['link']),
+                        $methodName
+                    ),
+                ];
+            }
+
+            $result['class'][] = [
+                $class['coverage'],
+                $class['ccn'],
+                sprintf(
+                    '<a href="%s">%s</a>',
+                    str_replace($baseLink, '', $class['link']),
+                    $className
+                ),
+            ];
+        }
+
+        return [
+            'class'  => json_encode($result['class']),
+            'method' => json_encode($result['method']),
+        ];
+    }
+
+    /**
+     * Returns the data for the Class / Method Coverage Distribution chart.
+     */
+    private function coverageDistribution(array $classes): array
+    {
+        $result = [
+            'class' => [
+                '0%'      => 0,
+                '0-10%'   => 0,
+                '10-20%'  => 0,
+                '20-30%'  => 0,
+                '30-40%'  => 0,
+                '40-50%'  => 0,
+                '50-60%'  => 0,
+                '60-70%'  => 0,
+                '70-80%'  => 0,
+                '80-90%'  => 0,
+                '90-100%' => 0,
+                '100%'    => 0,
+            ],
+            'method' => [
+                '0%'      => 0,
+                '0-10%'   => 0,
+                '10-20%'  => 0,
+                '20-30%'  => 0,
+                '30-40%'  => 0,
+                '40-50%'  => 0,
+                '50-60%'  => 0,
+                '60-70%'  => 0,
+                '70-80%'  => 0,
+                '80-90%'  => 0,
+                '90-100%' => 0,
+                '100%'    => 0,
+            ],
+        ];
+
+        foreach ($classes as $class) {
+            foreach ($class['methods'] as $methodName => $method) {
+                if ($method['coverage'] === 0) {
+                    $result['method']['0%']++;
+                } elseif ($method['coverage'] === 100) {
+                    $result['method']['100%']++;
+                } else {
+                    $key = floor($method['coverage'] / 10) * 10;
+                    $key = $key . '-' . ($key + 10) . '%';
+                    $result['method'][$key]++;
+                }
+            }
+
+            if ($class['coverage'] === 0) {
+                $result['class']['0%']++;
+            } elseif ($class['coverage'] === 100) {
+                $result['class']['100%']++;
+            } else {
+                $key = floor($class['coverage'] / 10) * 10;
+                $key = $key . '-' . ($key + 10) . '%';
+                $result['class'][$key]++;
+            }
+        }
+
+        return [
+            'class'  => json_encode(array_values($result['class'])),
+            'method' => json_encode(array_values($result['method'])),
+        ];
+    }
+
+    /**
+     * Returns the classes / methods with insufficient coverage.
+     */
+    private function insufficientCoverage(array $classes, string $baseLink): array
+    {
+        $leastTestedClasses = [];
+        $leastTestedMethods = [];
+        $result             = ['class' => '', 'method' => ''];
+
+        foreach ($classes as $className => $class) {
+            foreach ($class['methods'] as $methodName => $method) {
+                if ($method['coverage'] < $this->highLowerBound) {
+                    $key = $methodName;
+
+                    if ($className !== '*') {
+                        $key = $className . '::' . $methodName;
+                    }
+
+                    $leastTestedMethods[$key] = $method['coverage'];
+                }
+            }
+
+            if ($class['coverage'] < $this->highLowerBound) {
+                $leastTestedClasses[$className] = $class['coverage'];
+            }
+        }
+
+        asort($leastTestedClasses);
+        asort($leastTestedMethods);
+
+        foreach ($leastTestedClasses as $className => $coverage) {
+            $result['class'] .= sprintf(
+                '       <tr><td><a href="%s">%s</a></td><td class="text-right">%d%%</td></tr>' . "\n",
+                str_replace($baseLink, '', $classes[$className]['link']),
+                $className,
+                $coverage
+            );
+        }
+
+        foreach ($leastTestedMethods as $methodName => $coverage) {
+            [$class, $method] = explode('::', $methodName);
+
+            $result['method'] .= sprintf(
+                '       <tr><td><a href="%s"><abbr title="%s">%s</abbr></a></td><td class="text-right">%d%%</td></tr>' . "\n",
+                str_replace($baseLink, '', $classes[$class]['methods'][$method]['link']),
+                $methodName,
+                $method,
+                $coverage
+            );
+        }
+
+        return $result;
+    }
+
+    /**
+     * Returns the project risks according to the CRAP index.
+     */
+    private function projectRisks(array $classes, string $baseLink): array
+    {
+        $classRisks  = [];
+        $methodRisks = [];
+        $result      = ['class' => '', 'method' => ''];
+
+        foreach ($classes as $className => $class) {
+            foreach ($class['methods'] as $methodName => $method) {
+                if ($method['coverage'] < $this->highLowerBound && $method['ccn'] > 1) {
+                    $key = $methodName;
+
+                    if ($className !== '*') {
+                        $key = $className . '::' . $methodName;
+                    }
+
+                    $methodRisks[$key] = $method['crap'];
+                }
+            }
+
+            if ($class['coverage'] < $this->highLowerBound &&
+                $class['ccn'] > count($class['methods'])) {
+                $classRisks[$className] = $class['crap'];
+            }
+        }
+
+        arsort($classRisks);
+        arsort($methodRisks);
+
+        foreach ($classRisks as $className => $crap) {
+            $result['class'] .= sprintf(
+                '       <tr><td><a href="%s">%s</a></td><td class="text-right">%d</td></tr>' . "\n",
+                str_replace($baseLink, '', $classes[$className]['link']),
+                $className,
+                $crap
+            );
+        }
+
+        foreach ($methodRisks as $methodName => $crap) {
+            [$class, $method] = explode('::', $methodName);
+
+            $result['method'] .= sprintf(
+                '       <tr><td><a href="%s"><abbr title="%s">%s</abbr></a></td><td class="text-right">%d</td></tr>' . "\n",
+                str_replace($baseLink, '', $classes[$class]['methods'][$method]['link']),
+                $methodName,
+                $method,
+                $crap
+            );
+        }
+
+        return $result;
+    }
+}
diff --git a/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Directory.php b/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Directory.php
new file mode 100644
index 0000000000000000000000000000000000000000..faacbc31d0c67ebb53bfe9777837f6a9ec4472ae
--- /dev/null
+++ b/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Directory.php
@@ -0,0 +1,113 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of phpunit/php-code-coverage.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\CodeCoverage\Report\Html;
+
+use function count;
+use function sprintf;
+use function str_repeat;
+use SebastianBergmann\CodeCoverage\Node\AbstractNode as Node;
+use SebastianBergmann\CodeCoverage\Node\Directory as DirectoryNode;
+use SebastianBergmann\Template\Template;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage
+ */
+final class Directory extends Renderer
+{
+    public function render(DirectoryNode $node, string $file): void
+    {
+        $templateName = $this->templatePath . ($this->hasBranchCoverage ? 'directory_branch.html' : 'directory.html');
+        $template     = new Template($templateName, '{{', '}}');
+
+        $this->setCommonTemplateVariables($template, $node);
+
+        $items = $this->renderItem($node, true);
+
+        foreach ($node->directories() as $item) {
+            $items .= $this->renderItem($item);
+        }
+
+        foreach ($node->files() as $item) {
+            $items .= $this->renderItem($item);
+        }
+
+        $template->setVar(
+            [
+                'id'    => $node->id(),
+                'items' => $items,
+            ]
+        );
+
+        $template->renderTo($file);
+    }
+
+    private function renderItem(Node $node, bool $total = false): string
+    {
+        $data = [
+            'numClasses'                      => $node->numberOfClassesAndTraits(),
+            'numTestedClasses'                => $node->numberOfTestedClassesAndTraits(),
+            'numMethods'                      => $node->numberOfFunctionsAndMethods(),
+            'numTestedMethods'                => $node->numberOfTestedFunctionsAndMethods(),
+            'linesExecutedPercent'            => $node->percentageOfExecutedLines()->asFloat(),
+            'linesExecutedPercentAsString'    => $node->percentageOfExecutedLines()->asString(),
+            'numExecutedLines'                => $node->numberOfExecutedLines(),
+            'numExecutableLines'              => $node->numberOfExecutableLines(),
+            'branchesExecutedPercent'         => $node->percentageOfExecutedBranches()->asFloat(),
+            'branchesExecutedPercentAsString' => $node->percentageOfExecutedBranches()->asString(),
+            'numExecutedBranches'             => $node->numberOfExecutedBranches(),
+            'numExecutableBranches'           => $node->numberOfExecutableBranches(),
+            'pathsExecutedPercent'            => $node->percentageOfExecutedPaths()->asFloat(),
+            'pathsExecutedPercentAsString'    => $node->percentageOfExecutedPaths()->asString(),
+            'numExecutedPaths'                => $node->numberOfExecutedPaths(),
+            'numExecutablePaths'              => $node->numberOfExecutablePaths(),
+            'testedMethodsPercent'            => $node->percentageOfTestedFunctionsAndMethods()->asFloat(),
+            'testedMethodsPercentAsString'    => $node->percentageOfTestedFunctionsAndMethods()->asString(),
+            'testedClassesPercent'            => $node->percentageOfTestedClassesAndTraits()->asFloat(),
+            'testedClassesPercentAsString'    => $node->percentageOfTestedClassesAndTraits()->asString(),
+        ];
+
+        if ($total) {
+            $data['name'] = 'Total';
+        } else {
+            $up           = str_repeat('../', count($node->pathAsArray()) - 2);
+            $data['icon'] = sprintf('<img src="%s_icons/file-code.svg" class="octicon" />', $up);
+
+            if ($node instanceof DirectoryNode) {
+                $data['name'] = sprintf(
+                    '<a href="%s/index.html">%s</a>',
+                    $node->name(),
+                    $node->name()
+                );
+                $data['icon'] = sprintf('<img src="%s_icons/file-directory.svg" class="octicon" />', $up);
+            } elseif ($this->hasBranchCoverage) {
+                $data['name'] = sprintf(
+                    '%s <a class="small" href="%s.html">[line]</a> <a class="small" href="%s_branch.html">[branch]</a> <a class="small" href="%s_path.html">[path]</a>',
+                    $node->name(),
+                    $node->name(),
+                    $node->name(),
+                    $node->name()
+                );
+            } else {
+                $data['name'] = sprintf(
+                    '<a href="%s.html">%s</a>',
+                    $node->name(),
+                    $node->name()
+                );
+            }
+        }
+
+        $templateName = $this->templatePath . ($this->hasBranchCoverage ? 'directory_item_branch.html' : 'directory_item.html');
+
+        return $this->renderItemTemplate(
+            new Template($templateName, '{{', '}}'),
+            $data
+        );
+    }
+}
diff --git a/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/File.php b/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/File.php
new file mode 100644
index 0000000000000000000000000000000000000000..09c1ae7bdb4eacd191e4e7cb40099737239ce06c
--- /dev/null
+++ b/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/File.php
@@ -0,0 +1,1141 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of phpunit/php-code-coverage.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\CodeCoverage\Report\Html;
+
+use const ENT_COMPAT;
+use const ENT_HTML401;
+use const ENT_SUBSTITUTE;
+use const T_ABSTRACT;
+use const T_ARRAY;
+use const T_AS;
+use const T_BREAK;
+use const T_CALLABLE;
+use const T_CASE;
+use const T_CATCH;
+use const T_CLASS;
+use const T_CLONE;
+use const T_COMMENT;
+use const T_CONST;
+use const T_CONTINUE;
+use const T_DECLARE;
+use const T_DEFAULT;
+use const T_DO;
+use const T_DOC_COMMENT;
+use const T_ECHO;
+use const T_ELSE;
+use const T_ELSEIF;
+use const T_EMPTY;
+use const T_ENDDECLARE;
+use const T_ENDFOR;
+use const T_ENDFOREACH;
+use const T_ENDIF;
+use const T_ENDSWITCH;
+use const T_ENDWHILE;
+use const T_EVAL;
+use const T_EXIT;
+use const T_EXTENDS;
+use const T_FINAL;
+use const T_FINALLY;
+use const T_FOR;
+use const T_FOREACH;
+use const T_FUNCTION;
+use const T_GLOBAL;
+use const T_GOTO;
+use const T_HALT_COMPILER;
+use const T_IF;
+use const T_IMPLEMENTS;
+use const T_INCLUDE;
+use const T_INCLUDE_ONCE;
+use const T_INLINE_HTML;
+use const T_INSTANCEOF;
+use const T_INSTEADOF;
+use const T_INTERFACE;
+use const T_ISSET;
+use const T_LIST;
+use const T_NAMESPACE;
+use const T_NEW;
+use const T_PRINT;
+use const T_PRIVATE;
+use const T_PROTECTED;
+use const T_PUBLIC;
+use const T_REQUIRE;
+use const T_REQUIRE_ONCE;
+use const T_RETURN;
+use const T_STATIC;
+use const T_SWITCH;
+use const T_THROW;
+use const T_TRAIT;
+use const T_TRY;
+use const T_UNSET;
+use const T_USE;
+use const T_VAR;
+use const T_WHILE;
+use const T_YIELD;
+use const T_YIELD_FROM;
+use function array_key_exists;
+use function array_pop;
+use function array_unique;
+use function constant;
+use function count;
+use function defined;
+use function explode;
+use function file_get_contents;
+use function htmlspecialchars;
+use function is_string;
+use function sprintf;
+use function str_replace;
+use function substr;
+use function token_get_all;
+use function trim;
+use PHPUnit\Runner\BaseTestRunner;
+use SebastianBergmann\CodeCoverage\Node\File as FileNode;
+use SebastianBergmann\CodeCoverage\Percentage;
+use SebastianBergmann\Template\Template;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage
+ */
+final class File extends Renderer
+{
+    /**
+     * @psalm-var array<int,true>
+     */
+    private static $keywordTokens = [];
+
+    /**
+     * @var array
+     */
+    private static $formattedSourceCache = [];
+
+    /**
+     * @var int
+     */
+    private $htmlSpecialCharsFlags = ENT_COMPAT | ENT_HTML401 | ENT_SUBSTITUTE;
+
+    public function render(FileNode $node, string $file): void
+    {
+        $templateName = $this->templatePath . ($this->hasBranchCoverage ? 'file_branch.html' : 'file.html');
+        $template     = new Template($templateName, '{{', '}}');
+        $this->setCommonTemplateVariables($template, $node);
+
+        $template->setVar(
+            [
+                'items'     => $this->renderItems($node),
+                'lines'     => $this->renderSourceWithLineCoverage($node),
+                'legend'    => '<p><span class="success"><strong>Executed</strong></span><span class="danger"><strong>Not Executed</strong></span><span class="warning"><strong>Dead Code</strong></span></p>',
+                'structure' => '',
+            ]
+        );
+
+        $template->renderTo($file . '.html');
+
+        if ($this->hasBranchCoverage) {
+            $template->setVar(
+                [
+                    'items'     => $this->renderItems($node),
+                    'lines'     => $this->renderSourceWithBranchCoverage($node),
+                    'legend'    => '<p><span class="success"><strong>Fully covered</strong></span><span class="warning"><strong>Partially covered</strong></span><span class="danger"><strong>Not covered</strong></span></p>',
+                    'structure' => $this->renderBranchStructure($node),
+                ]
+            );
+
+            $template->renderTo($file . '_branch.html');
+
+            $template->setVar(
+                [
+                    'items'     => $this->renderItems($node),
+                    'lines'     => $this->renderSourceWithPathCoverage($node),
+                    'legend'    => '<p><span class="success"><strong>Fully covered</strong></span><span class="warning"><strong>Partially covered</strong></span><span class="danger"><strong>Not covered</strong></span></p>',
+                    'structure' => $this->renderPathStructure($node),
+                ]
+            );
+
+            $template->renderTo($file . '_path.html');
+        }
+    }
+
+    private function renderItems(FileNode $node): string
+    {
+        $templateName = $this->templatePath . ($this->hasBranchCoverage ? 'file_item_branch.html' : 'file_item.html');
+        $template     = new Template($templateName, '{{', '}}');
+
+        $methodTemplateName = $this->templatePath . ($this->hasBranchCoverage ? 'method_item_branch.html' : 'method_item.html');
+        $methodItemTemplate = new Template(
+            $methodTemplateName,
+            '{{',
+            '}}'
+        );
+
+        $items = $this->renderItemTemplate(
+            $template,
+            [
+                'name'                            => 'Total',
+                'numClasses'                      => $node->numberOfClassesAndTraits(),
+                'numTestedClasses'                => $node->numberOfTestedClassesAndTraits(),
+                'numMethods'                      => $node->numberOfFunctionsAndMethods(),
+                'numTestedMethods'                => $node->numberOfTestedFunctionsAndMethods(),
+                'linesExecutedPercent'            => $node->percentageOfExecutedLines()->asFloat(),
+                'linesExecutedPercentAsString'    => $node->percentageOfExecutedLines()->asString(),
+                'numExecutedLines'                => $node->numberOfExecutedLines(),
+                'numExecutableLines'              => $node->numberOfExecutableLines(),
+                'branchesExecutedPercent'         => $node->percentageOfExecutedBranches()->asFloat(),
+                'branchesExecutedPercentAsString' => $node->percentageOfExecutedBranches()->asString(),
+                'numExecutedBranches'             => $node->numberOfExecutedBranches(),
+                'numExecutableBranches'           => $node->numberOfExecutableBranches(),
+                'pathsExecutedPercent'            => $node->percentageOfExecutedPaths()->asFloat(),
+                'pathsExecutedPercentAsString'    => $node->percentageOfExecutedPaths()->asString(),
+                'numExecutedPaths'                => $node->numberOfExecutedPaths(),
+                'numExecutablePaths'              => $node->numberOfExecutablePaths(),
+                'testedMethodsPercent'            => $node->percentageOfTestedFunctionsAndMethods()->asFloat(),
+                'testedMethodsPercentAsString'    => $node->percentageOfTestedFunctionsAndMethods()->asString(),
+                'testedClassesPercent'            => $node->percentageOfTestedClassesAndTraits()->asFloat(),
+                'testedClassesPercentAsString'    => $node->percentageOfTestedClassesAndTraits()->asString(),
+                'crap'                            => '<abbr title="Change Risk Anti-Patterns (CRAP) Index">CRAP</abbr>',
+            ]
+        );
+
+        $items .= $this->renderFunctionItems(
+            $node->functions(),
+            $methodItemTemplate
+        );
+
+        $items .= $this->renderTraitOrClassItems(
+            $node->traits(),
+            $template,
+            $methodItemTemplate
+        );
+
+        $items .= $this->renderTraitOrClassItems(
+            $node->classes(),
+            $template,
+            $methodItemTemplate
+        );
+
+        return $items;
+    }
+
+    private function renderTraitOrClassItems(array $items, Template $template, Template $methodItemTemplate): string
+    {
+        $buffer = '';
+
+        if (empty($items)) {
+            return $buffer;
+        }
+
+        foreach ($items as $name => $item) {
+            $numMethods       = 0;
+            $numTestedMethods = 0;
+
+            foreach ($item['methods'] as $method) {
+                if ($method['executableLines'] > 0) {
+                    $numMethods++;
+
+                    if ($method['executedLines'] === $method['executableLines']) {
+                        $numTestedMethods++;
+                    }
+                }
+            }
+
+            if ($item['executableLines'] > 0) {
+                $numClasses                   = 1;
+                $numTestedClasses             = $numTestedMethods === $numMethods ? 1 : 0;
+                $linesExecutedPercentAsString = Percentage::fromFractionAndTotal(
+                    $item['executedLines'],
+                    $item['executableLines']
+                )->asString();
+                $branchesExecutedPercentAsString = Percentage::fromFractionAndTotal(
+                    $item['executedBranches'],
+                    $item['executableBranches']
+                )->asString();
+                $pathsExecutedPercentAsString = Percentage::fromFractionAndTotal(
+                    $item['executedPaths'],
+                    $item['executablePaths']
+                )->asString();
+            } else {
+                $numClasses                      = 0;
+                $numTestedClasses                = 0;
+                $linesExecutedPercentAsString    = 'n/a';
+                $branchesExecutedPercentAsString = 'n/a';
+                $pathsExecutedPercentAsString    = 'n/a';
+            }
+
+            $testedMethodsPercentage = Percentage::fromFractionAndTotal(
+                $numTestedMethods,
+                $numMethods
+            );
+
+            $testedClassesPercentage = Percentage::fromFractionAndTotal(
+                $numTestedMethods === $numMethods ? 1 : 0,
+                1
+            );
+
+            $buffer .= $this->renderItemTemplate(
+                $template,
+                [
+                    'name'                 => $this->abbreviateClassName($name),
+                    'numClasses'           => $numClasses,
+                    'numTestedClasses'     => $numTestedClasses,
+                    'numMethods'           => $numMethods,
+                    'numTestedMethods'     => $numTestedMethods,
+                    'linesExecutedPercent' => Percentage::fromFractionAndTotal(
+                        $item['executedLines'],
+                        $item['executableLines'],
+                    )->asFloat(),
+                    'linesExecutedPercentAsString' => $linesExecutedPercentAsString,
+                    'numExecutedLines'             => $item['executedLines'],
+                    'numExecutableLines'           => $item['executableLines'],
+                    'branchesExecutedPercent'      => Percentage::fromFractionAndTotal(
+                        $item['executedBranches'],
+                        $item['executableBranches'],
+                    )->asFloat(),
+                    'branchesExecutedPercentAsString' => $branchesExecutedPercentAsString,
+                    'numExecutedBranches'             => $item['executedBranches'],
+                    'numExecutableBranches'           => $item['executableBranches'],
+                    'pathsExecutedPercent'            => Percentage::fromFractionAndTotal(
+                        $item['executedPaths'],
+                        $item['executablePaths']
+                    )->asFloat(),
+                    'pathsExecutedPercentAsString' => $pathsExecutedPercentAsString,
+                    'numExecutedPaths'             => $item['executedPaths'],
+                    'numExecutablePaths'           => $item['executablePaths'],
+                    'testedMethodsPercent'         => $testedMethodsPercentage->asFloat(),
+                    'testedMethodsPercentAsString' => $testedMethodsPercentage->asString(),
+                    'testedClassesPercent'         => $testedClassesPercentage->asFloat(),
+                    'testedClassesPercentAsString' => $testedClassesPercentage->asString(),
+                    'crap'                         => $item['crap'],
+                ]
+            );
+
+            foreach ($item['methods'] as $method) {
+                $buffer .= $this->renderFunctionOrMethodItem(
+                    $methodItemTemplate,
+                    $method,
+                    '&nbsp;'
+                );
+            }
+        }
+
+        return $buffer;
+    }
+
+    private function renderFunctionItems(array $functions, Template $template): string
+    {
+        if (empty($functions)) {
+            return '';
+        }
+
+        $buffer = '';
+
+        foreach ($functions as $function) {
+            $buffer .= $this->renderFunctionOrMethodItem(
+                $template,
+                $function
+            );
+        }
+
+        return $buffer;
+    }
+
+    private function renderFunctionOrMethodItem(Template $template, array $item, string $indent = ''): string
+    {
+        $numMethods       = 0;
+        $numTestedMethods = 0;
+
+        if ($item['executableLines'] > 0) {
+            $numMethods = 1;
+
+            if ($item['executedLines'] === $item['executableLines']) {
+                $numTestedMethods = 1;
+            }
+        }
+
+        $executedLinesPercentage = Percentage::fromFractionAndTotal(
+            $item['executedLines'],
+            $item['executableLines']
+        );
+
+        $executedBranchesPercentage = Percentage::fromFractionAndTotal(
+            $item['executedBranches'],
+            $item['executableBranches']
+        );
+
+        $executedPathsPercentage = Percentage::fromFractionAndTotal(
+            $item['executedPaths'],
+            $item['executablePaths']
+        );
+
+        $testedMethodsPercentage = Percentage::fromFractionAndTotal(
+            $numTestedMethods,
+            1
+        );
+
+        return $this->renderItemTemplate(
+            $template,
+            [
+                'name' => sprintf(
+                    '%s<a href="#%d"><abbr title="%s">%s</abbr></a>',
+                    $indent,
+                    $item['startLine'],
+                    htmlspecialchars($item['signature'], $this->htmlSpecialCharsFlags),
+                    $item['functionName'] ?? $item['methodName']
+                ),
+                'numMethods'                      => $numMethods,
+                'numTestedMethods'                => $numTestedMethods,
+                'linesExecutedPercent'            => $executedLinesPercentage->asFloat(),
+                'linesExecutedPercentAsString'    => $executedLinesPercentage->asString(),
+                'numExecutedLines'                => $item['executedLines'],
+                'numExecutableLines'              => $item['executableLines'],
+                'branchesExecutedPercent'         => $executedBranchesPercentage->asFloat(),
+                'branchesExecutedPercentAsString' => $executedBranchesPercentage->asString(),
+                'numExecutedBranches'             => $item['executedBranches'],
+                'numExecutableBranches'           => $item['executableBranches'],
+                'pathsExecutedPercent'            => $executedPathsPercentage->asFloat(),
+                'pathsExecutedPercentAsString'    => $executedPathsPercentage->asString(),
+                'numExecutedPaths'                => $item['executedPaths'],
+                'numExecutablePaths'              => $item['executablePaths'],
+                'testedMethodsPercent'            => $testedMethodsPercentage->asFloat(),
+                'testedMethodsPercentAsString'    => $testedMethodsPercentage->asString(),
+                'crap'                            => $item['crap'],
+            ]
+        );
+    }
+
+    private function renderSourceWithLineCoverage(FileNode $node): string
+    {
+        $linesTemplate      = new Template($this->templatePath . 'lines.html.dist', '{{', '}}');
+        $singleLineTemplate = new Template($this->templatePath . 'line.html.dist', '{{', '}}');
+
+        $coverageData = $node->lineCoverageData();
+        $testData     = $node->testData();
+        $codeLines    = $this->loadFile($node->pathAsString());
+        $lines        = '';
+        $i            = 1;
+
+        foreach ($codeLines as $line) {
+            $trClass        = '';
+            $popoverContent = '';
+            $popoverTitle   = '';
+
+            if (array_key_exists($i, $coverageData)) {
+                $numTests = ($coverageData[$i] ? count($coverageData[$i]) : 0);
+
+                if ($coverageData[$i] === null) {
+                    $trClass = 'warning';
+                } elseif ($numTests === 0) {
+                    $trClass = 'danger';
+                } else {
+                    if ($numTests > 1) {
+                        $popoverTitle = $numTests . ' tests cover line ' . $i;
+                    } else {
+                        $popoverTitle = '1 test covers line ' . $i;
+                    }
+
+                    $lineCss        = 'covered-by-large-tests';
+                    $popoverContent = '<ul>';
+
+                    foreach ($coverageData[$i] as $test) {
+                        if ($lineCss === 'covered-by-large-tests' && $testData[$test]['size'] === 'medium') {
+                            $lineCss = 'covered-by-medium-tests';
+                        } elseif ($testData[$test]['size'] === 'small') {
+                            $lineCss = 'covered-by-small-tests';
+                        }
+
+                        $popoverContent .= $this->createPopoverContentForTest($test, $testData[$test]);
+                    }
+
+                    $popoverContent .= '</ul>';
+                    $trClass = $lineCss . ' popin';
+                }
+            }
+
+            $popover = '';
+
+            if (!empty($popoverTitle)) {
+                $popover = sprintf(
+                    ' data-title="%s" data-content="%s" data-placement="top" data-html="true"',
+                    $popoverTitle,
+                    htmlspecialchars($popoverContent, $this->htmlSpecialCharsFlags)
+                );
+            }
+
+            $lines .= $this->renderLine($singleLineTemplate, $i, $line, $trClass, $popover);
+
+            $i++;
+        }
+
+        $linesTemplate->setVar(['lines' => $lines]);
+
+        return $linesTemplate->render();
+    }
+
+    private function renderSourceWithBranchCoverage(FileNode $node): string
+    {
+        $linesTemplate      = new Template($this->templatePath . 'lines.html.dist', '{{', '}}');
+        $singleLineTemplate = new Template($this->templatePath . 'line.html.dist', '{{', '}}');
+
+        $functionCoverageData = $node->functionCoverageData();
+        $testData             = $node->testData();
+        $codeLines            = $this->loadFile($node->pathAsString());
+
+        $lineData = [];
+
+        /** @var int $line */
+        foreach (array_keys($codeLines) as $line) {
+            $lineData[$line + 1] = [
+                'includedInBranches'    => 0,
+                'includedInHitBranches' => 0,
+                'tests'                 => [],
+            ];
+        }
+
+        foreach ($functionCoverageData as $method) {
+            foreach ($method['branches'] as $branch) {
+                foreach (range($branch['line_start'], $branch['line_end']) as $line) {
+                    if (!isset($lineData[$line])) { // blank line at end of file is sometimes included here
+                        continue;
+                    }
+
+                    $lineData[$line]['includedInBranches']++;
+
+                    if ($branch['hit']) {
+                        $lineData[$line]['includedInHitBranches']++;
+                        $lineData[$line]['tests'] = array_unique(array_merge($lineData[$line]['tests'], $branch['hit']));
+                    }
+                }
+            }
+        }
+
+        $lines = '';
+        $i     = 1;
+
+        /** @var string $line */
+        foreach ($codeLines as $line) {
+            $trClass = '';
+            $popover = '';
+
+            if ($lineData[$i]['includedInBranches'] > 0) {
+                $lineCss = 'success';
+
+                if ($lineData[$i]['includedInHitBranches'] === 0) {
+                    $lineCss = 'danger';
+                } elseif ($lineData[$i]['includedInHitBranches'] !== $lineData[$i]['includedInBranches']) {
+                    $lineCss = 'warning';
+                }
+
+                $popoverContent = '<ul>';
+
+                if (count($lineData[$i]['tests']) === 1) {
+                    $popoverTitle = '1 test covers line ' . $i;
+                } else {
+                    $popoverTitle = count($lineData[$i]['tests']) . ' tests cover line ' . $i;
+                }
+                $popoverTitle .= '. These are covering ' . $lineData[$i]['includedInHitBranches'] . ' out of the ' . $lineData[$i]['includedInBranches'] . ' code branches.';
+
+                foreach ($lineData[$i]['tests'] as $test) {
+                    $popoverContent .= $this->createPopoverContentForTest($test, $testData[$test]);
+                }
+
+                $popoverContent .= '</ul>';
+                $trClass = $lineCss . ' popin';
+
+                $popover = sprintf(
+                    ' data-title="%s" data-content="%s" data-placement="top" data-html="true"',
+                    $popoverTitle,
+                    htmlspecialchars($popoverContent, $this->htmlSpecialCharsFlags)
+                );
+            }
+
+            $lines .= $this->renderLine($singleLineTemplate, $i, $line, $trClass, $popover);
+
+            $i++;
+        }
+
+        $linesTemplate->setVar(['lines' => $lines]);
+
+        return $linesTemplate->render();
+    }
+
+    private function renderSourceWithPathCoverage(FileNode $node): string
+    {
+        $linesTemplate      = new Template($this->templatePath . 'lines.html.dist', '{{', '}}');
+        $singleLineTemplate = new Template($this->templatePath . 'line.html.dist', '{{', '}}');
+
+        $functionCoverageData = $node->functionCoverageData();
+        $testData             = $node->testData();
+        $codeLines            = $this->loadFile($node->pathAsString());
+
+        $lineData = [];
+
+        /** @var int $line */
+        foreach (array_keys($codeLines) as $line) {
+            $lineData[$line + 1] = [
+                'includedInPaths'    => [],
+                'includedInHitPaths' => [],
+                'tests'              => [],
+            ];
+        }
+
+        foreach ($functionCoverageData as $method) {
+            foreach ($method['paths'] as $pathId => $path) {
+                foreach ($path['path'] as $branchTaken) {
+                    foreach (range($method['branches'][$branchTaken]['line_start'], $method['branches'][$branchTaken]['line_end']) as $line) {
+                        if (!isset($lineData[$line])) {
+                            continue;
+                        }
+                        $lineData[$line]['includedInPaths'][] = $pathId;
+
+                        if ($path['hit']) {
+                            $lineData[$line]['includedInHitPaths'][] = $pathId;
+                            $lineData[$line]['tests']                = array_unique(array_merge($lineData[$line]['tests'], $path['hit']));
+                        }
+                    }
+                }
+            }
+        }
+
+        $lines = '';
+        $i     = 1;
+
+        /** @var string $line */
+        foreach ($codeLines as $line) {
+            $trClass                 = '';
+            $popover                 = '';
+            $includedInPathsCount    = count(array_unique($lineData[$i]['includedInPaths']));
+            $includedInHitPathsCount = count(array_unique($lineData[$i]['includedInHitPaths']));
+
+            if ($includedInPathsCount > 0) {
+                $lineCss = 'success';
+
+                if ($includedInHitPathsCount === 0) {
+                    $lineCss = 'danger';
+                } elseif ($includedInHitPathsCount !== $includedInPathsCount) {
+                    $lineCss = 'warning';
+                }
+
+                $popoverContent = '<ul>';
+
+                if (count($lineData[$i]['tests']) === 1) {
+                    $popoverTitle = '1 test covers line ' . $i;
+                } else {
+                    $popoverTitle = count($lineData[$i]['tests']) . ' tests cover line ' . $i;
+                }
+                $popoverTitle .= '. These are covering ' . $includedInHitPathsCount . ' out of the ' . $includedInPathsCount . ' code paths.';
+
+                foreach ($lineData[$i]['tests'] as $test) {
+                    $popoverContent .= $this->createPopoverContentForTest($test, $testData[$test]);
+                }
+
+                $popoverContent .= '</ul>';
+                $trClass = $lineCss . ' popin';
+
+                $popover = sprintf(
+                    ' data-title="%s" data-content="%s" data-placement="top" data-html="true"',
+                    $popoverTitle,
+                    htmlspecialchars($popoverContent, $this->htmlSpecialCharsFlags)
+                );
+            }
+
+            $lines .= $this->renderLine($singleLineTemplate, $i, $line, $trClass, $popover);
+
+            $i++;
+        }
+
+        $linesTemplate->setVar(['lines' => $lines]);
+
+        return $linesTemplate->render();
+    }
+
+    private function renderBranchStructure(FileNode $node): string
+    {
+        $branchesTemplate = new Template($this->templatePath . 'branches.html.dist', '{{', '}}');
+
+        $coverageData = $node->functionCoverageData();
+        $testData     = $node->testData();
+        $codeLines    = $this->loadFile($node->pathAsString());
+        $branches     = '';
+
+        ksort($coverageData);
+
+        foreach ($coverageData as $methodName => $methodData) {
+            if (!$methodData['branches']) {
+                continue;
+            }
+
+            $branchStructure = '';
+
+            foreach ($methodData['branches'] as $branch) {
+                $branchStructure .= $this->renderBranchLines($branch, $codeLines, $testData);
+            }
+
+            if ($branchStructure !== '') { // don't show empty branches
+                $branches .= '<h5 class="structure-heading"><a name="' . htmlspecialchars($methodName, $this->htmlSpecialCharsFlags) . '">' . $this->abbreviateMethodName($methodName) . '</a></h5>' . "\n";
+                $branches .= $branchStructure;
+            }
+        }
+
+        $branchesTemplate->setVar(['branches' => $branches]);
+
+        return $branchesTemplate->render();
+    }
+
+    private function renderBranchLines(array $branch, array $codeLines, array $testData): string
+    {
+        $linesTemplate      = new Template($this->templatePath . 'lines.html.dist', '{{', '}}');
+        $singleLineTemplate = new Template($this->templatePath . 'line.html.dist', '{{', '}}');
+
+        $lines = '';
+
+        $branchLines = range($branch['line_start'], $branch['line_end']);
+        sort($branchLines); // sometimes end_line < start_line
+
+        /** @var int $line */
+        foreach ($branchLines as $line) {
+            if (!isset($codeLines[$line])) { // blank line at end of file is sometimes included here
+                continue;
+            }
+
+            $popoverContent = '';
+            $popoverTitle   = '';
+
+            $numTests = count($branch['hit']);
+
+            if ($numTests === 0) {
+                $trClass = 'danger';
+            } else {
+                $lineCss        = 'covered-by-large-tests';
+                $popoverContent = '<ul>';
+
+                if ($numTests > 1) {
+                    $popoverTitle = $numTests . ' tests cover this branch';
+                } else {
+                    $popoverTitle = '1 test covers this branch';
+                }
+
+                foreach ($branch['hit'] as $test) {
+                    if ($lineCss === 'covered-by-large-tests' && $testData[$test]['size'] === 'medium') {
+                        $lineCss = 'covered-by-medium-tests';
+                    } elseif ($testData[$test]['size'] === 'small') {
+                        $lineCss = 'covered-by-small-tests';
+                    }
+
+                    $popoverContent .= $this->createPopoverContentForTest($test, $testData[$test]);
+                }
+                $trClass = $lineCss . ' popin';
+            }
+
+            $popover = '';
+
+            if (!empty($popoverTitle)) {
+                $popover = sprintf(
+                    ' data-title="%s" data-content="%s" data-placement="top" data-html="true"',
+                    $popoverTitle,
+                    htmlspecialchars($popoverContent, $this->htmlSpecialCharsFlags)
+                );
+            }
+
+            $lines .= $this->renderLine($singleLineTemplate, $line, $codeLines[$line - 1], $trClass, $popover);
+        }
+
+        if ($lines === '') {
+            return '';
+        }
+
+        $linesTemplate->setVar(['lines' => $lines]);
+
+        return $linesTemplate->render();
+    }
+
+    private function renderPathStructure(FileNode $node): string
+    {
+        $pathsTemplate = new Template($this->templatePath . 'paths.html.dist', '{{', '}}');
+
+        $coverageData = $node->functionCoverageData();
+        $testData     = $node->testData();
+        $codeLines    = $this->loadFile($node->pathAsString());
+        $paths        = '';
+
+        ksort($coverageData);
+
+        foreach ($coverageData as $methodName => $methodData) {
+            if (!$methodData['paths']) {
+                continue;
+            }
+
+            $pathStructure = '';
+
+            if (count($methodData['paths']) > 100) {
+                $pathStructure .= '<p>' . count($methodData['paths']) . ' is too many paths to sensibly render, consider refactoring your code to bring this number down.</p>';
+
+                continue;
+            }
+
+            foreach ($methodData['paths'] as $path) {
+                $pathStructure .= $this->renderPathLines($path, $methodData['branches'], $codeLines, $testData);
+            }
+
+            if ($pathStructure !== '') {
+                $paths .= '<h5 class="structure-heading"><a name="' . htmlspecialchars($methodName, $this->htmlSpecialCharsFlags) . '">' . $this->abbreviateMethodName($methodName) . '</a></h5>' . "\n";
+                $paths .= $pathStructure;
+            }
+        }
+
+        $pathsTemplate->setVar(['paths' => $paths]);
+
+        return $pathsTemplate->render();
+    }
+
+    private function renderPathLines(array $path, array $branches, array $codeLines, array $testData): string
+    {
+        $linesTemplate      = new Template($this->templatePath . 'lines.html.dist', '{{', '}}');
+        $singleLineTemplate = new Template($this->templatePath . 'line.html.dist', '{{', '}}');
+
+        $lines = '';
+
+        foreach ($path['path'] as $branchId) {
+            $branchLines = range($branches[$branchId]['line_start'], $branches[$branchId]['line_end']);
+            sort($branchLines); // sometimes end_line < start_line
+
+            /** @var int $line */
+            foreach ($branchLines as $line) {
+                if (!isset($codeLines[$line])) { // blank line at end of file is sometimes included here
+                    continue;
+                }
+
+                $popoverContent = '';
+                $popoverTitle   = '';
+
+                $numTests = count($path['hit']);
+
+                if ($numTests === 0) {
+                    $trClass = 'danger';
+                } else {
+                    $lineCss        = 'covered-by-large-tests';
+                    $popoverContent = '<ul>';
+
+                    if ($numTests > 1) {
+                        $popoverTitle = $numTests . ' tests cover this path';
+                    } else {
+                        $popoverTitle = '1 test covers this path';
+                    }
+
+                    foreach ($path['hit'] as $test) {
+                        if ($lineCss === 'covered-by-large-tests' && $testData[$test]['size'] === 'medium') {
+                            $lineCss = 'covered-by-medium-tests';
+                        } elseif ($testData[$test]['size'] === 'small') {
+                            $lineCss = 'covered-by-small-tests';
+                        }
+
+                        $popoverContent .= $this->createPopoverContentForTest($test, $testData[$test]);
+                    }
+                    $trClass = $lineCss . ' popin';
+                }
+
+                $popover = '';
+
+                if (!empty($popoverTitle)) {
+                    $popover = sprintf(
+                        ' data-title="%s" data-content="%s" data-placement="top" data-html="true"',
+                        $popoverTitle,
+                        htmlspecialchars($popoverContent, $this->htmlSpecialCharsFlags)
+                    );
+                }
+
+                $lines .= $this->renderLine($singleLineTemplate, $line, $codeLines[$line - 1], $trClass, $popover);
+            }
+        }
+
+        if ($lines === '') {
+            return '';
+        }
+
+        $linesTemplate->setVar(['lines' => $lines]);
+
+        return $linesTemplate->render();
+    }
+
+    private function renderLine(Template $template, int $lineNumber, string $lineContent, string $class, string $popover): string
+    {
+        $template->setVar(
+            [
+                'lineNumber'  => $lineNumber,
+                'lineContent' => $lineContent,
+                'class'       => $class,
+                'popover'     => $popover,
+            ]
+        );
+
+        return $template->render();
+    }
+
+    private function loadFile(string $file): array
+    {
+        if (isset(self::$formattedSourceCache[$file])) {
+            return self::$formattedSourceCache[$file];
+        }
+
+        $buffer              = file_get_contents($file);
+        $tokens              = token_get_all($buffer);
+        $result              = [''];
+        $i                   = 0;
+        $stringFlag          = false;
+        $fileEndsWithNewLine = substr($buffer, -1) === "\n";
+
+        unset($buffer);
+
+        foreach ($tokens as $j => $token) {
+            if (is_string($token)) {
+                if ($token === '"' && $tokens[$j - 1] !== '\\') {
+                    $result[$i] .= sprintf(
+                        '<span class="string">%s</span>',
+                        htmlspecialchars($token, $this->htmlSpecialCharsFlags)
+                    );
+
+                    $stringFlag = !$stringFlag;
+                } else {
+                    $result[$i] .= sprintf(
+                        '<span class="keyword">%s</span>',
+                        htmlspecialchars($token, $this->htmlSpecialCharsFlags)
+                    );
+                }
+
+                continue;
+            }
+
+            [$token, $value] = $token;
+
+            $value = str_replace(
+                ["\t", ' '],
+                ['&nbsp;&nbsp;&nbsp;&nbsp;', '&nbsp;'],
+                htmlspecialchars($value, $this->htmlSpecialCharsFlags)
+            );
+
+            if ($value === "\n") {
+                $result[++$i] = '';
+            } else {
+                $lines = explode("\n", $value);
+
+                foreach ($lines as $jj => $line) {
+                    $line = trim($line);
+
+                    if ($line !== '') {
+                        if ($stringFlag) {
+                            $colour = 'string';
+                        } else {
+                            $colour = 'default';
+
+                            if ($this->isInlineHtml($token)) {
+                                $colour = 'html';
+                            } elseif ($this->isComment($token)) {
+                                $colour = 'comment';
+                            } elseif ($this->isKeyword($token)) {
+                                $colour = 'keyword';
+                            }
+                        }
+
+                        $result[$i] .= sprintf(
+                            '<span class="%s">%s</span>',
+                            $colour,
+                            $line
+                        );
+                    }
+
+                    if (isset($lines[$jj + 1])) {
+                        $result[++$i] = '';
+                    }
+                }
+            }
+        }
+
+        if ($fileEndsWithNewLine) {
+            unset($result[count($result) - 1]);
+        }
+
+        self::$formattedSourceCache[$file] = $result;
+
+        return $result;
+    }
+
+    private function abbreviateClassName(string $className): string
+    {
+        $tmp = explode('\\', $className);
+
+        if (count($tmp) > 1) {
+            $className = sprintf(
+                '<abbr title="%s">%s</abbr>',
+                $className,
+                array_pop($tmp)
+            );
+        }
+
+        return $className;
+    }
+
+    private function abbreviateMethodName(string $methodName): string
+    {
+        $parts = explode('->', $methodName);
+
+        if (count($parts) === 2) {
+            return $this->abbreviateClassName($parts[0]) . '->' . $parts[1];
+        }
+
+        return $methodName;
+    }
+
+    private function createPopoverContentForTest(string $test, array $testData): string
+    {
+        $testCSS = '';
+
+        if ($testData['fromTestcase']) {
+            switch ($testData['status']) {
+                case BaseTestRunner::STATUS_PASSED:
+                    switch ($testData['size']) {
+                        case 'small':
+                            $testCSS = ' class="covered-by-small-tests"';
+
+                            break;
+
+                        case 'medium':
+                            $testCSS = ' class="covered-by-medium-tests"';
+
+                            break;
+
+                        default:
+                            $testCSS = ' class="covered-by-large-tests"';
+
+                            break;
+                    }
+
+                    break;
+
+                case BaseTestRunner::STATUS_SKIPPED:
+                case BaseTestRunner::STATUS_INCOMPLETE:
+                case BaseTestRunner::STATUS_RISKY:
+                case BaseTestRunner::STATUS_WARNING:
+                    $testCSS = ' class="warning"';
+
+                    break;
+
+                case BaseTestRunner::STATUS_FAILURE:
+                case BaseTestRunner::STATUS_ERROR:
+                    $testCSS = ' class="danger"';
+
+                    break;
+            }
+        }
+
+        return sprintf(
+            '<li%s>%s</li>',
+            $testCSS,
+            htmlspecialchars($test, $this->htmlSpecialCharsFlags)
+        );
+    }
+
+    private function isComment(int $token): bool
+    {
+        return $token === T_COMMENT || $token === T_DOC_COMMENT;
+    }
+
+    private function isInlineHtml(int $token): bool
+    {
+        return $token === T_INLINE_HTML;
+    }
+
+    private function isKeyword(int $token): bool
+    {
+        return isset(self::keywordTokens()[$token]);
+    }
+
+    /**
+     * @psalm-return array<int,true>
+     */
+    private static function keywordTokens(): array
+    {
+        if (self::$keywordTokens !== []) {
+            return self::$keywordTokens;
+        }
+
+        self::$keywordTokens = [
+            T_ABSTRACT      => true,
+            T_ARRAY         => true,
+            T_AS            => true,
+            T_BREAK         => true,
+            T_CALLABLE      => true,
+            T_CASE          => true,
+            T_CATCH         => true,
+            T_CLASS         => true,
+            T_CLONE         => true,
+            T_CONST         => true,
+            T_CONTINUE      => true,
+            T_DECLARE       => true,
+            T_DEFAULT       => true,
+            T_DO            => true,
+            T_ECHO          => true,
+            T_ELSE          => true,
+            T_ELSEIF        => true,
+            T_EMPTY         => true,
+            T_ENDDECLARE    => true,
+            T_ENDFOR        => true,
+            T_ENDFOREACH    => true,
+            T_ENDIF         => true,
+            T_ENDSWITCH     => true,
+            T_ENDWHILE      => true,
+            T_EVAL          => true,
+            T_EXIT          => true,
+            T_EXTENDS       => true,
+            T_FINAL         => true,
+            T_FINALLY       => true,
+            T_FOR           => true,
+            T_FOREACH       => true,
+            T_FUNCTION      => true,
+            T_GLOBAL        => true,
+            T_GOTO          => true,
+            T_HALT_COMPILER => true,
+            T_IF            => true,
+            T_IMPLEMENTS    => true,
+            T_INCLUDE       => true,
+            T_INCLUDE_ONCE  => true,
+            T_INSTANCEOF    => true,
+            T_INSTEADOF     => true,
+            T_INTERFACE     => true,
+            T_ISSET         => true,
+            T_LIST          => true,
+            T_NAMESPACE     => true,
+            T_NEW           => true,
+            T_PRINT         => true,
+            T_PRIVATE       => true,
+            T_PROTECTED     => true,
+            T_PUBLIC        => true,
+            T_REQUIRE       => true,
+            T_REQUIRE_ONCE  => true,
+            T_RETURN        => true,
+            T_STATIC        => true,
+            T_SWITCH        => true,
+            T_THROW         => true,
+            T_TRAIT         => true,
+            T_TRY           => true,
+            T_UNSET         => true,
+            T_USE           => true,
+            T_VAR           => true,
+            T_WHILE         => true,
+            T_YIELD         => true,
+            T_YIELD_FROM    => true,
+        ];
+
+        if (defined('T_FN')) {
+            self::$keywordTokens[constant('T_FN')] = true;
+        }
+
+        if (defined('T_MATCH')) {
+            self::$keywordTokens[constant('T_MATCH')] = true;
+        }
+
+        return self::$keywordTokens;
+    }
+}
diff --git a/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/branches.html.dist b/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/branches.html.dist
new file mode 100644
index 0000000000000000000000000000000000000000..5477026231a8a6df289794af5a5710d38feb67b1
--- /dev/null
+++ b/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/branches.html.dist
@@ -0,0 +1,9 @@
+<hr/>
+<h4>Branches</h4>
+<p>
+    Below are the source code lines that represent each code branch as identified by Xdebug. Please note a branch is not
+    necessarily coterminous with a line, a line may contain multiple branches and therefore show up more than once.
+    Please also be aware that some branches may be implicit rather than explicit, e.g. an <code>if</code> statement
+    <i>always</i> has an <code>else</code> as part of its logical flow even if you didn't write one.
+</p>
+{{branches}}
diff --git a/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/coverage_bar.html.dist b/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/coverage_bar.html.dist
new file mode 100644
index 0000000000000000000000000000000000000000..7fcf6f4906db29bb922b634c0046cd642c1d9335
--- /dev/null
+++ b/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/coverage_bar.html.dist
@@ -0,0 +1,5 @@
+       <div class="progress">
+         <div class="progress-bar bg-{{level}}" role="progressbar" aria-valuenow="{{percent}}" aria-valuemin="0" aria-valuemax="100" style="width: {{percent}}%">
+           <span class="sr-only">{{percent}}% covered ({{level}})</span>
+         </div>
+       </div>
diff --git a/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/coverage_bar_branch.html.dist b/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/coverage_bar_branch.html.dist
new file mode 100644
index 0000000000000000000000000000000000000000..7fcf6f4906db29bb922b634c0046cd642c1d9335
--- /dev/null
+++ b/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/coverage_bar_branch.html.dist
@@ -0,0 +1,5 @@
+       <div class="progress">
+         <div class="progress-bar bg-{{level}}" role="progressbar" aria-valuenow="{{percent}}" aria-valuemin="0" aria-valuemax="100" style="width: {{percent}}%">
+           <span class="sr-only">{{percent}}% covered ({{level}})</span>
+         </div>
+       </div>
diff --git a/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/css/bootstrap.min.css b/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/css/bootstrap.min.css
new file mode 100644
index 0000000000000000000000000000000000000000..7d2a868f578fb6f9d8febb6b2d3f3ff84a1b1086
--- /dev/null
+++ b/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/css/bootstrap.min.css
@@ -0,0 +1,7 @@
+/*!
+ * Bootstrap v4.5.0 (https://getbootstrap.com/)
+ * Copyright 2011-2020 The Bootstrap Authors
+ * Copyright 2011-2020 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ */:root{--blue:#007bff;--indigo:#6610f2;--purple:#6f42c1;--pink:#e83e8c;--red:#dc3545;--orange:#fd7e14;--yellow:#ffc107;--green:#28a745;--teal:#20c997;--cyan:#17a2b8;--white:#fff;--gray:#6c757d;--gray-dark:#343a40;--primary:#007bff;--secondary:#6c757d;--success:#28a745;--info:#17a2b8;--warning:#ffc107;--danger:#dc3545;--light:#f8f9fa;--dark:#343a40;--breakpoint-xs:0;--breakpoint-sm:576px;--breakpoint-md:768px;--breakpoint-lg:992px;--breakpoint-xl:1200px;--font-family-sans-serif:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";--font-family-monospace:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace}*,::after,::before{box-sizing:border-box}html{font-family:sans-serif;line-height:1.15;-webkit-text-size-adjust:100%;-webkit-tap-highlight-color:transparent}article,aside,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}body{margin:0;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";font-size:1rem;font-weight:400;line-height:1.5;color:#212529;text-align:left;background-color:#fff}[tabindex="-1"]:focus:not(:focus-visible){outline:0!important}hr{box-sizing:content-box;height:0;overflow:visible}h1,h2,h3,h4,h5,h6{margin-top:0;margin-bottom:.5rem}p{margin-top:0;margin-bottom:1rem}abbr[data-original-title],abbr[title]{text-decoration:underline;-webkit-text-decoration:underline dotted;text-decoration:underline dotted;cursor:help;border-bottom:0;-webkit-text-decoration-skip-ink:none;text-decoration-skip-ink:none}address{margin-bottom:1rem;font-style:normal;line-height:inherit}dl,ol,ul{margin-top:0;margin-bottom:1rem}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}dt{font-weight:700}dd{margin-bottom:.5rem;margin-left:0}blockquote{margin:0 0 1rem}b,strong{font-weight:bolder}small{font-size:80%}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}a{color:#007bff;text-decoration:none;background-color:transparent}a:hover{color:#0056b3;text-decoration:underline}a:not([href]){color:inherit;text-decoration:none}a:not([href]):hover{color:inherit;text-decoration:none}code,kbd,pre,samp{font-family:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;font-size:1em}pre{margin-top:0;margin-bottom:1rem;overflow:auto;-ms-overflow-style:scrollbar}figure{margin:0 0 1rem}img{vertical-align:middle;border-style:none}svg{overflow:hidden;vertical-align:middle}table{border-collapse:collapse}caption{padding-top:.75rem;padding-bottom:.75rem;color:#6c757d;text-align:left;caption-side:bottom}th{text-align:inherit}label{display:inline-block;margin-bottom:.5rem}button{border-radius:0}button:focus{outline:1px dotted;outline:5px auto -webkit-focus-ring-color}button,input,optgroup,select,textarea{margin:0;font-family:inherit;font-size:inherit;line-height:inherit}button,input{overflow:visible}button,select{text-transform:none}[role=button]{cursor:pointer}select{word-wrap:normal}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}[type=button]:not(:disabled),[type=reset]:not(:disabled),[type=submit]:not(:disabled),button:not(:disabled){cursor:pointer}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{padding:0;border-style:none}input[type=checkbox],input[type=radio]{box-sizing:border-box;padding:0}textarea{overflow:auto;resize:vertical}fieldset{min-width:0;padding:0;margin:0;border:0}legend{display:block;width:100%;max-width:100%;padding:0;margin-bottom:.5rem;font-size:1.5rem;line-height:inherit;color:inherit;white-space:normal}progress{vertical-align:baseline}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{outline-offset:-2px;-webkit-appearance:none}[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{font:inherit;-webkit-appearance:button}output{display:inline-block}summary{display:list-item;cursor:pointer}template{display:none}[hidden]{display:none!important}.h1,.h2,.h3,.h4,.h5,.h6,h1,h2,h3,h4,h5,h6{margin-bottom:.5rem;font-weight:500;line-height:1.2}.h1,h1{font-size:2.5rem}.h2,h2{font-size:2rem}.h3,h3{font-size:1.75rem}.h4,h4{font-size:1.5rem}.h5,h5{font-size:1.25rem}.h6,h6{font-size:1rem}.lead{font-size:1.25rem;font-weight:300}.display-1{font-size:6rem;font-weight:300;line-height:1.2}.display-2{font-size:5.5rem;font-weight:300;line-height:1.2}.display-3{font-size:4.5rem;font-weight:300;line-height:1.2}.display-4{font-size:3.5rem;font-weight:300;line-height:1.2}hr{margin-top:1rem;margin-bottom:1rem;border:0;border-top:1px solid rgba(0,0,0,.1)}.small,small{font-size:80%;font-weight:400}.mark,mark{padding:.2em;background-color:#fcf8e3}.list-unstyled{padding-left:0;list-style:none}.list-inline{padding-left:0;list-style:none}.list-inline-item{display:inline-block}.list-inline-item:not(:last-child){margin-right:.5rem}.initialism{font-size:90%;text-transform:uppercase}.blockquote{margin-bottom:1rem;font-size:1.25rem}.blockquote-footer{display:block;font-size:80%;color:#6c757d}.blockquote-footer::before{content:"\2014\00A0"}.img-fluid{max-width:100%;height:auto}.img-thumbnail{padding:.25rem;background-color:#fff;border:1px solid #dee2e6;border-radius:.25rem;max-width:100%;height:auto}.figure{display:inline-block}.figure-img{margin-bottom:.5rem;line-height:1}.figure-caption{font-size:90%;color:#6c757d}code{font-size:87.5%;color:#e83e8c;word-wrap:break-word}a>code{color:inherit}kbd{padding:.2rem .4rem;font-size:87.5%;color:#fff;background-color:#212529;border-radius:.2rem}kbd kbd{padding:0;font-size:100%;font-weight:700}pre{display:block;font-size:87.5%;color:#212529}pre code{font-size:inherit;color:inherit;word-break:normal}.pre-scrollable{max-height:340px;overflow-y:scroll}.container{width:100%;padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}@media (min-width:576px){.container{max-width:540px}}@media (min-width:768px){.container{max-width:720px}}@media (min-width:992px){.container{max-width:960px}}@media (min-width:1200px){.container{max-width:1140px}}.container-fluid,.container-lg,.container-md,.container-sm,.container-xl{width:100%;padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}@media (min-width:576px){.container,.container-sm{max-width:540px}}@media (min-width:768px){.container,.container-md,.container-sm{max-width:720px}}@media (min-width:992px){.container,.container-lg,.container-md,.container-sm{max-width:960px}}@media (min-width:1200px){.container,.container-lg,.container-md,.container-sm,.container-xl{max-width:1140px}}.row{display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;margin-right:-15px;margin-left:-15px}.no-gutters{margin-right:0;margin-left:0}.no-gutters>.col,.no-gutters>[class*=col-]{padding-right:0;padding-left:0}.col,.col-1,.col-10,.col-11,.col-12,.col-2,.col-3,.col-4,.col-5,.col-6,.col-7,.col-8,.col-9,.col-auto,.col-lg,.col-lg-1,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9,.col-lg-auto,.col-md,.col-md-1,.col-md-10,.col-md-11,.col-md-12,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-md-auto,.col-sm,.col-sm-1,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-sm-auto,.col-xl,.col-xl-1,.col-xl-10,.col-xl-11,.col-xl-12,.col-xl-2,.col-xl-3,.col-xl-4,.col-xl-5,.col-xl-6,.col-xl-7,.col-xl-8,.col-xl-9,.col-xl-auto{position:relative;width:100%;padding-right:15px;padding-left:15px}.col{-ms-flex-preferred-size:0;flex-basis:0;-ms-flex-positive:1;flex-grow:1;min-width:0;max-width:100%}.row-cols-1>*{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.row-cols-2>*{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.row-cols-3>*{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.row-cols-4>*{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.row-cols-5>*{-ms-flex:0 0 20%;flex:0 0 20%;max-width:20%}.row-cols-6>*{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:100%}.col-1{-ms-flex:0 0 8.333333%;flex:0 0 8.333333%;max-width:8.333333%}.col-2{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-3{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-4{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.col-5{-ms-flex:0 0 41.666667%;flex:0 0 41.666667%;max-width:41.666667%}.col-6{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-7{-ms-flex:0 0 58.333333%;flex:0 0 58.333333%;max-width:58.333333%}.col-8{-ms-flex:0 0 66.666667%;flex:0 0 66.666667%;max-width:66.666667%}.col-9{-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-10{-ms-flex:0 0 83.333333%;flex:0 0 83.333333%;max-width:83.333333%}.col-11{-ms-flex:0 0 91.666667%;flex:0 0 91.666667%;max-width:91.666667%}.col-12{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-first{-ms-flex-order:-1;order:-1}.order-last{-ms-flex-order:13;order:13}.order-0{-ms-flex-order:0;order:0}.order-1{-ms-flex-order:1;order:1}.order-2{-ms-flex-order:2;order:2}.order-3{-ms-flex-order:3;order:3}.order-4{-ms-flex-order:4;order:4}.order-5{-ms-flex-order:5;order:5}.order-6{-ms-flex-order:6;order:6}.order-7{-ms-flex-order:7;order:7}.order-8{-ms-flex-order:8;order:8}.order-9{-ms-flex-order:9;order:9}.order-10{-ms-flex-order:10;order:10}.order-11{-ms-flex-order:11;order:11}.order-12{-ms-flex-order:12;order:12}.offset-1{margin-left:8.333333%}.offset-2{margin-left:16.666667%}.offset-3{margin-left:25%}.offset-4{margin-left:33.333333%}.offset-5{margin-left:41.666667%}.offset-6{margin-left:50%}.offset-7{margin-left:58.333333%}.offset-8{margin-left:66.666667%}.offset-9{margin-left:75%}.offset-10{margin-left:83.333333%}.offset-11{margin-left:91.666667%}@media (min-width:576px){.col-sm{-ms-flex-preferred-size:0;flex-basis:0;-ms-flex-positive:1;flex-grow:1;min-width:0;max-width:100%}.row-cols-sm-1>*{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.row-cols-sm-2>*{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.row-cols-sm-3>*{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.row-cols-sm-4>*{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.row-cols-sm-5>*{-ms-flex:0 0 20%;flex:0 0 20%;max-width:20%}.row-cols-sm-6>*{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-sm-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:100%}.col-sm-1{-ms-flex:0 0 8.333333%;flex:0 0 8.333333%;max-width:8.333333%}.col-sm-2{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-sm-3{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-sm-4{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.col-sm-5{-ms-flex:0 0 41.666667%;flex:0 0 41.666667%;max-width:41.666667%}.col-sm-6{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-sm-7{-ms-flex:0 0 58.333333%;flex:0 0 58.333333%;max-width:58.333333%}.col-sm-8{-ms-flex:0 0 66.666667%;flex:0 0 66.666667%;max-width:66.666667%}.col-sm-9{-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-sm-10{-ms-flex:0 0 83.333333%;flex:0 0 83.333333%;max-width:83.333333%}.col-sm-11{-ms-flex:0 0 91.666667%;flex:0 0 91.666667%;max-width:91.666667%}.col-sm-12{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-sm-first{-ms-flex-order:-1;order:-1}.order-sm-last{-ms-flex-order:13;order:13}.order-sm-0{-ms-flex-order:0;order:0}.order-sm-1{-ms-flex-order:1;order:1}.order-sm-2{-ms-flex-order:2;order:2}.order-sm-3{-ms-flex-order:3;order:3}.order-sm-4{-ms-flex-order:4;order:4}.order-sm-5{-ms-flex-order:5;order:5}.order-sm-6{-ms-flex-order:6;order:6}.order-sm-7{-ms-flex-order:7;order:7}.order-sm-8{-ms-flex-order:8;order:8}.order-sm-9{-ms-flex-order:9;order:9}.order-sm-10{-ms-flex-order:10;order:10}.order-sm-11{-ms-flex-order:11;order:11}.order-sm-12{-ms-flex-order:12;order:12}.offset-sm-0{margin-left:0}.offset-sm-1{margin-left:8.333333%}.offset-sm-2{margin-left:16.666667%}.offset-sm-3{margin-left:25%}.offset-sm-4{margin-left:33.333333%}.offset-sm-5{margin-left:41.666667%}.offset-sm-6{margin-left:50%}.offset-sm-7{margin-left:58.333333%}.offset-sm-8{margin-left:66.666667%}.offset-sm-9{margin-left:75%}.offset-sm-10{margin-left:83.333333%}.offset-sm-11{margin-left:91.666667%}}@media (min-width:768px){.col-md{-ms-flex-preferred-size:0;flex-basis:0;-ms-flex-positive:1;flex-grow:1;min-width:0;max-width:100%}.row-cols-md-1>*{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.row-cols-md-2>*{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.row-cols-md-3>*{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.row-cols-md-4>*{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.row-cols-md-5>*{-ms-flex:0 0 20%;flex:0 0 20%;max-width:20%}.row-cols-md-6>*{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-md-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:100%}.col-md-1{-ms-flex:0 0 8.333333%;flex:0 0 8.333333%;max-width:8.333333%}.col-md-2{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-md-3{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-md-4{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.col-md-5{-ms-flex:0 0 41.666667%;flex:0 0 41.666667%;max-width:41.666667%}.col-md-6{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-md-7{-ms-flex:0 0 58.333333%;flex:0 0 58.333333%;max-width:58.333333%}.col-md-8{-ms-flex:0 0 66.666667%;flex:0 0 66.666667%;max-width:66.666667%}.col-md-9{-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-md-10{-ms-flex:0 0 83.333333%;flex:0 0 83.333333%;max-width:83.333333%}.col-md-11{-ms-flex:0 0 91.666667%;flex:0 0 91.666667%;max-width:91.666667%}.col-md-12{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-md-first{-ms-flex-order:-1;order:-1}.order-md-last{-ms-flex-order:13;order:13}.order-md-0{-ms-flex-order:0;order:0}.order-md-1{-ms-flex-order:1;order:1}.order-md-2{-ms-flex-order:2;order:2}.order-md-3{-ms-flex-order:3;order:3}.order-md-4{-ms-flex-order:4;order:4}.order-md-5{-ms-flex-order:5;order:5}.order-md-6{-ms-flex-order:6;order:6}.order-md-7{-ms-flex-order:7;order:7}.order-md-8{-ms-flex-order:8;order:8}.order-md-9{-ms-flex-order:9;order:9}.order-md-10{-ms-flex-order:10;order:10}.order-md-11{-ms-flex-order:11;order:11}.order-md-12{-ms-flex-order:12;order:12}.offset-md-0{margin-left:0}.offset-md-1{margin-left:8.333333%}.offset-md-2{margin-left:16.666667%}.offset-md-3{margin-left:25%}.offset-md-4{margin-left:33.333333%}.offset-md-5{margin-left:41.666667%}.offset-md-6{margin-left:50%}.offset-md-7{margin-left:58.333333%}.offset-md-8{margin-left:66.666667%}.offset-md-9{margin-left:75%}.offset-md-10{margin-left:83.333333%}.offset-md-11{margin-left:91.666667%}}@media (min-width:992px){.col-lg{-ms-flex-preferred-size:0;flex-basis:0;-ms-flex-positive:1;flex-grow:1;min-width:0;max-width:100%}.row-cols-lg-1>*{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.row-cols-lg-2>*{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.row-cols-lg-3>*{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.row-cols-lg-4>*{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.row-cols-lg-5>*{-ms-flex:0 0 20%;flex:0 0 20%;max-width:20%}.row-cols-lg-6>*{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-lg-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:100%}.col-lg-1{-ms-flex:0 0 8.333333%;flex:0 0 8.333333%;max-width:8.333333%}.col-lg-2{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-lg-3{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-lg-4{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.col-lg-5{-ms-flex:0 0 41.666667%;flex:0 0 41.666667%;max-width:41.666667%}.col-lg-6{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-lg-7{-ms-flex:0 0 58.333333%;flex:0 0 58.333333%;max-width:58.333333%}.col-lg-8{-ms-flex:0 0 66.666667%;flex:0 0 66.666667%;max-width:66.666667%}.col-lg-9{-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-lg-10{-ms-flex:0 0 83.333333%;flex:0 0 83.333333%;max-width:83.333333%}.col-lg-11{-ms-flex:0 0 91.666667%;flex:0 0 91.666667%;max-width:91.666667%}.col-lg-12{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-lg-first{-ms-flex-order:-1;order:-1}.order-lg-last{-ms-flex-order:13;order:13}.order-lg-0{-ms-flex-order:0;order:0}.order-lg-1{-ms-flex-order:1;order:1}.order-lg-2{-ms-flex-order:2;order:2}.order-lg-3{-ms-flex-order:3;order:3}.order-lg-4{-ms-flex-order:4;order:4}.order-lg-5{-ms-flex-order:5;order:5}.order-lg-6{-ms-flex-order:6;order:6}.order-lg-7{-ms-flex-order:7;order:7}.order-lg-8{-ms-flex-order:8;order:8}.order-lg-9{-ms-flex-order:9;order:9}.order-lg-10{-ms-flex-order:10;order:10}.order-lg-11{-ms-flex-order:11;order:11}.order-lg-12{-ms-flex-order:12;order:12}.offset-lg-0{margin-left:0}.offset-lg-1{margin-left:8.333333%}.offset-lg-2{margin-left:16.666667%}.offset-lg-3{margin-left:25%}.offset-lg-4{margin-left:33.333333%}.offset-lg-5{margin-left:41.666667%}.offset-lg-6{margin-left:50%}.offset-lg-7{margin-left:58.333333%}.offset-lg-8{margin-left:66.666667%}.offset-lg-9{margin-left:75%}.offset-lg-10{margin-left:83.333333%}.offset-lg-11{margin-left:91.666667%}}@media (min-width:1200px){.col-xl{-ms-flex-preferred-size:0;flex-basis:0;-ms-flex-positive:1;flex-grow:1;min-width:0;max-width:100%}.row-cols-xl-1>*{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.row-cols-xl-2>*{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.row-cols-xl-3>*{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.row-cols-xl-4>*{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.row-cols-xl-5>*{-ms-flex:0 0 20%;flex:0 0 20%;max-width:20%}.row-cols-xl-6>*{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-xl-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:100%}.col-xl-1{-ms-flex:0 0 8.333333%;flex:0 0 8.333333%;max-width:8.333333%}.col-xl-2{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-xl-3{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-xl-4{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.col-xl-5{-ms-flex:0 0 41.666667%;flex:0 0 41.666667%;max-width:41.666667%}.col-xl-6{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-xl-7{-ms-flex:0 0 58.333333%;flex:0 0 58.333333%;max-width:58.333333%}.col-xl-8{-ms-flex:0 0 66.666667%;flex:0 0 66.666667%;max-width:66.666667%}.col-xl-9{-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-xl-10{-ms-flex:0 0 83.333333%;flex:0 0 83.333333%;max-width:83.333333%}.col-xl-11{-ms-flex:0 0 91.666667%;flex:0 0 91.666667%;max-width:91.666667%}.col-xl-12{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-xl-first{-ms-flex-order:-1;order:-1}.order-xl-last{-ms-flex-order:13;order:13}.order-xl-0{-ms-flex-order:0;order:0}.order-xl-1{-ms-flex-order:1;order:1}.order-xl-2{-ms-flex-order:2;order:2}.order-xl-3{-ms-flex-order:3;order:3}.order-xl-4{-ms-flex-order:4;order:4}.order-xl-5{-ms-flex-order:5;order:5}.order-xl-6{-ms-flex-order:6;order:6}.order-xl-7{-ms-flex-order:7;order:7}.order-xl-8{-ms-flex-order:8;order:8}.order-xl-9{-ms-flex-order:9;order:9}.order-xl-10{-ms-flex-order:10;order:10}.order-xl-11{-ms-flex-order:11;order:11}.order-xl-12{-ms-flex-order:12;order:12}.offset-xl-0{margin-left:0}.offset-xl-1{margin-left:8.333333%}.offset-xl-2{margin-left:16.666667%}.offset-xl-3{margin-left:25%}.offset-xl-4{margin-left:33.333333%}.offset-xl-5{margin-left:41.666667%}.offset-xl-6{margin-left:50%}.offset-xl-7{margin-left:58.333333%}.offset-xl-8{margin-left:66.666667%}.offset-xl-9{margin-left:75%}.offset-xl-10{margin-left:83.333333%}.offset-xl-11{margin-left:91.666667%}}.table{width:100%;margin-bottom:1rem;color:#212529}.table td,.table th{padding:.75rem;vertical-align:top;border-top:1px solid #dee2e6}.table thead th{vertical-align:bottom;border-bottom:2px solid #dee2e6}.table tbody+tbody{border-top:2px solid #dee2e6}.table-sm td,.table-sm th{padding:.3rem}.table-bordered{border:1px solid #dee2e6}.table-bordered td,.table-bordered th{border:1px solid #dee2e6}.table-bordered thead td,.table-bordered thead th{border-bottom-width:2px}.table-borderless tbody+tbody,.table-borderless td,.table-borderless th,.table-borderless thead th{border:0}.table-striped tbody tr:nth-of-type(odd){background-color:rgba(0,0,0,.05)}.table-hover tbody tr:hover{color:#212529;background-color:rgba(0,0,0,.075)}.table-primary,.table-primary>td,.table-primary>th{background-color:#b8daff}.table-primary tbody+tbody,.table-primary td,.table-primary th,.table-primary thead th{border-color:#7abaff}.table-hover .table-primary:hover{background-color:#9fcdff}.table-hover .table-primary:hover>td,.table-hover .table-primary:hover>th{background-color:#9fcdff}.table-secondary,.table-secondary>td,.table-secondary>th{background-color:#d6d8db}.table-secondary tbody+tbody,.table-secondary td,.table-secondary th,.table-secondary thead th{border-color:#b3b7bb}.table-hover .table-secondary:hover{background-color:#c8cbcf}.table-hover .table-secondary:hover>td,.table-hover .table-secondary:hover>th{background-color:#c8cbcf}.table-success,.table-success>td,.table-success>th{background-color:#c3e6cb}.table-success tbody+tbody,.table-success td,.table-success th,.table-success thead th{border-color:#8fd19e}.table-hover .table-success:hover{background-color:#b1dfbb}.table-hover .table-success:hover>td,.table-hover .table-success:hover>th{background-color:#b1dfbb}.table-info,.table-info>td,.table-info>th{background-color:#bee5eb}.table-info tbody+tbody,.table-info td,.table-info th,.table-info thead th{border-color:#86cfda}.table-hover .table-info:hover{background-color:#abdde5}.table-hover .table-info:hover>td,.table-hover .table-info:hover>th{background-color:#abdde5}.table-warning,.table-warning>td,.table-warning>th{background-color:#ffeeba}.table-warning tbody+tbody,.table-warning td,.table-warning th,.table-warning thead th{border-color:#ffdf7e}.table-hover .table-warning:hover{background-color:#ffe8a1}.table-hover .table-warning:hover>td,.table-hover .table-warning:hover>th{background-color:#ffe8a1}.table-danger,.table-danger>td,.table-danger>th{background-color:#f5c6cb}.table-danger tbody+tbody,.table-danger td,.table-danger th,.table-danger thead th{border-color:#ed969e}.table-hover .table-danger:hover{background-color:#f1b0b7}.table-hover .table-danger:hover>td,.table-hover .table-danger:hover>th{background-color:#f1b0b7}.table-light,.table-light>td,.table-light>th{background-color:#fdfdfe}.table-light tbody+tbody,.table-light td,.table-light th,.table-light thead th{border-color:#fbfcfc}.table-hover .table-light:hover{background-color:#ececf6}.table-hover .table-light:hover>td,.table-hover .table-light:hover>th{background-color:#ececf6}.table-dark,.table-dark>td,.table-dark>th{background-color:#c6c8ca}.table-dark tbody+tbody,.table-dark td,.table-dark th,.table-dark thead th{border-color:#95999c}.table-hover .table-dark:hover{background-color:#b9bbbe}.table-hover .table-dark:hover>td,.table-hover .table-dark:hover>th{background-color:#b9bbbe}.table-active,.table-active>td,.table-active>th{background-color:rgba(0,0,0,.075)}.table-hover .table-active:hover{background-color:rgba(0,0,0,.075)}.table-hover .table-active:hover>td,.table-hover .table-active:hover>th{background-color:rgba(0,0,0,.075)}.table .thead-dark th{color:#fff;background-color:#343a40;border-color:#454d55}.table .thead-light th{color:#495057;background-color:#e9ecef;border-color:#dee2e6}.table-dark{color:#fff;background-color:#343a40}.table-dark td,.table-dark th,.table-dark thead th{border-color:#454d55}.table-dark.table-bordered{border:0}.table-dark.table-striped tbody tr:nth-of-type(odd){background-color:rgba(255,255,255,.05)}.table-dark.table-hover tbody tr:hover{color:#fff;background-color:rgba(255,255,255,.075)}@media (max-width:575.98px){.table-responsive-sm{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch}.table-responsive-sm>.table-bordered{border:0}}@media (max-width:767.98px){.table-responsive-md{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch}.table-responsive-md>.table-bordered{border:0}}@media (max-width:991.98px){.table-responsive-lg{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch}.table-responsive-lg>.table-bordered{border:0}}@media (max-width:1199.98px){.table-responsive-xl{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch}.table-responsive-xl>.table-bordered{border:0}}.table-responsive{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch}.table-responsive>.table-bordered{border:0}.form-control{display:block;width:100%;height:calc(1.5em + .75rem + 2px);padding:.375rem .75rem;font-size:1rem;font-weight:400;line-height:1.5;color:#495057;background-color:#fff;background-clip:padding-box;border:1px solid #ced4da;border-radius:.25rem;transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.form-control{transition:none}}.form-control::-ms-expand{background-color:transparent;border:0}.form-control:-moz-focusring{color:transparent;text-shadow:0 0 0 #495057}.form-control:focus{color:#495057;background-color:#fff;border-color:#80bdff;outline:0;box-shadow:0 0 0 .2rem rgba(0,123,255,.25)}.form-control::-webkit-input-placeholder{color:#6c757d;opacity:1}.form-control::-moz-placeholder{color:#6c757d;opacity:1}.form-control:-ms-input-placeholder{color:#6c757d;opacity:1}.form-control::-ms-input-placeholder{color:#6c757d;opacity:1}.form-control::placeholder{color:#6c757d;opacity:1}.form-control:disabled,.form-control[readonly]{background-color:#e9ecef;opacity:1}input[type=date].form-control,input[type=datetime-local].form-control,input[type=month].form-control,input[type=time].form-control{-webkit-appearance:none;-moz-appearance:none;appearance:none}select.form-control:focus::-ms-value{color:#495057;background-color:#fff}.form-control-file,.form-control-range{display:block;width:100%}.col-form-label{padding-top:calc(.375rem + 1px);padding-bottom:calc(.375rem + 1px);margin-bottom:0;font-size:inherit;line-height:1.5}.col-form-label-lg{padding-top:calc(.5rem + 1px);padding-bottom:calc(.5rem + 1px);font-size:1.25rem;line-height:1.5}.col-form-label-sm{padding-top:calc(.25rem + 1px);padding-bottom:calc(.25rem + 1px);font-size:.875rem;line-height:1.5}.form-control-plaintext{display:block;width:100%;padding:.375rem 0;margin-bottom:0;font-size:1rem;line-height:1.5;color:#212529;background-color:transparent;border:solid transparent;border-width:1px 0}.form-control-plaintext.form-control-lg,.form-control-plaintext.form-control-sm{padding-right:0;padding-left:0}.form-control-sm{height:calc(1.5em + .5rem + 2px);padding:.25rem .5rem;font-size:.875rem;line-height:1.5;border-radius:.2rem}.form-control-lg{height:calc(1.5em + 1rem + 2px);padding:.5rem 1rem;font-size:1.25rem;line-height:1.5;border-radius:.3rem}select.form-control[multiple],select.form-control[size]{height:auto}textarea.form-control{height:auto}.form-group{margin-bottom:1rem}.form-text{display:block;margin-top:.25rem}.form-row{display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;margin-right:-5px;margin-left:-5px}.form-row>.col,.form-row>[class*=col-]{padding-right:5px;padding-left:5px}.form-check{position:relative;display:block;padding-left:1.25rem}.form-check-input{position:absolute;margin-top:.3rem;margin-left:-1.25rem}.form-check-input:disabled~.form-check-label,.form-check-input[disabled]~.form-check-label{color:#6c757d}.form-check-label{margin-bottom:0}.form-check-inline{display:-ms-inline-flexbox;display:inline-flex;-ms-flex-align:center;align-items:center;padding-left:0;margin-right:.75rem}.form-check-inline .form-check-input{position:static;margin-top:0;margin-right:.3125rem;margin-left:0}.valid-feedback{display:none;width:100%;margin-top:.25rem;font-size:80%;color:#28a745}.valid-tooltip{position:absolute;top:100%;z-index:5;display:none;max-width:100%;padding:.25rem .5rem;margin-top:.1rem;font-size:.875rem;line-height:1.5;color:#fff;background-color:rgba(40,167,69,.9);border-radius:.25rem}.is-valid~.valid-feedback,.is-valid~.valid-tooltip,.was-validated :valid~.valid-feedback,.was-validated :valid~.valid-tooltip{display:block}.form-control.is-valid,.was-validated .form-control:valid{border-color:#28a745;padding-right:calc(1.5em + .75rem);background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='8' height='8' viewBox='0 0 8 8'%3e%3cpath fill='%2328a745' d='M2.3 6.73L.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3e%3c/svg%3e");background-repeat:no-repeat;background-position:right calc(.375em + .1875rem) center;background-size:calc(.75em + .375rem) calc(.75em + .375rem)}.form-control.is-valid:focus,.was-validated .form-control:valid:focus{border-color:#28a745;box-shadow:0 0 0 .2rem rgba(40,167,69,.25)}.was-validated textarea.form-control:valid,textarea.form-control.is-valid{padding-right:calc(1.5em + .75rem);background-position:top calc(.375em + .1875rem) right calc(.375em + .1875rem)}.custom-select.is-valid,.was-validated .custom-select:valid{border-color:#28a745;padding-right:calc(.75em + 2.3125rem);background:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='4' height='5' viewBox='0 0 4 5'%3e%3cpath fill='%23343a40' d='M2 0L0 2h4zm0 5L0 3h4z'/%3e%3c/svg%3e") no-repeat right .75rem center/8px 10px,url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='8' height='8' viewBox='0 0 8 8'%3e%3cpath fill='%2328a745' d='M2.3 6.73L.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3e%3c/svg%3e") #fff no-repeat center right 1.75rem/calc(.75em + .375rem) calc(.75em + .375rem)}.custom-select.is-valid:focus,.was-validated .custom-select:valid:focus{border-color:#28a745;box-shadow:0 0 0 .2rem rgba(40,167,69,.25)}.form-check-input.is-valid~.form-check-label,.was-validated .form-check-input:valid~.form-check-label{color:#28a745}.form-check-input.is-valid~.valid-feedback,.form-check-input.is-valid~.valid-tooltip,.was-validated .form-check-input:valid~.valid-feedback,.was-validated .form-check-input:valid~.valid-tooltip{display:block}.custom-control-input.is-valid~.custom-control-label,.was-validated .custom-control-input:valid~.custom-control-label{color:#28a745}.custom-control-input.is-valid~.custom-control-label::before,.was-validated .custom-control-input:valid~.custom-control-label::before{border-color:#28a745}.custom-control-input.is-valid:checked~.custom-control-label::before,.was-validated .custom-control-input:valid:checked~.custom-control-label::before{border-color:#34ce57;background-color:#34ce57}.custom-control-input.is-valid:focus~.custom-control-label::before,.was-validated .custom-control-input:valid:focus~.custom-control-label::before{box-shadow:0 0 0 .2rem rgba(40,167,69,.25)}.custom-control-input.is-valid:focus:not(:checked)~.custom-control-label::before,.was-validated .custom-control-input:valid:focus:not(:checked)~.custom-control-label::before{border-color:#28a745}.custom-file-input.is-valid~.custom-file-label,.was-validated .custom-file-input:valid~.custom-file-label{border-color:#28a745}.custom-file-input.is-valid:focus~.custom-file-label,.was-validated .custom-file-input:valid:focus~.custom-file-label{border-color:#28a745;box-shadow:0 0 0 .2rem rgba(40,167,69,.25)}.invalid-feedback{display:none;width:100%;margin-top:.25rem;font-size:80%;color:#dc3545}.invalid-tooltip{position:absolute;top:100%;z-index:5;display:none;max-width:100%;padding:.25rem .5rem;margin-top:.1rem;font-size:.875rem;line-height:1.5;color:#fff;background-color:rgba(220,53,69,.9);border-radius:.25rem}.is-invalid~.invalid-feedback,.is-invalid~.invalid-tooltip,.was-validated :invalid~.invalid-feedback,.was-validated :invalid~.invalid-tooltip{display:block}.form-control.is-invalid,.was-validated .form-control:invalid{border-color:#dc3545;padding-right:calc(1.5em + .75rem);background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' fill='none' stroke='%23dc3545' viewBox='0 0 12 12'%3e%3ccircle cx='6' cy='6' r='4.5'/%3e%3cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3e%3ccircle cx='6' cy='8.2' r='.6' fill='%23dc3545' stroke='none'/%3e%3c/svg%3e");background-repeat:no-repeat;background-position:right calc(.375em + .1875rem) center;background-size:calc(.75em + .375rem) calc(.75em + .375rem)}.form-control.is-invalid:focus,.was-validated .form-control:invalid:focus{border-color:#dc3545;box-shadow:0 0 0 .2rem rgba(220,53,69,.25)}.was-validated textarea.form-control:invalid,textarea.form-control.is-invalid{padding-right:calc(1.5em + .75rem);background-position:top calc(.375em + .1875rem) right calc(.375em + .1875rem)}.custom-select.is-invalid,.was-validated .custom-select:invalid{border-color:#dc3545;padding-right:calc(.75em + 2.3125rem);background:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='4' height='5' viewBox='0 0 4 5'%3e%3cpath fill='%23343a40' d='M2 0L0 2h4zm0 5L0 3h4z'/%3e%3c/svg%3e") no-repeat right .75rem center/8px 10px,url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' fill='none' stroke='%23dc3545' viewBox='0 0 12 12'%3e%3ccircle cx='6' cy='6' r='4.5'/%3e%3cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3e%3ccircle cx='6' cy='8.2' r='.6' fill='%23dc3545' stroke='none'/%3e%3c/svg%3e") #fff no-repeat center right 1.75rem/calc(.75em + .375rem) calc(.75em + .375rem)}.custom-select.is-invalid:focus,.was-validated .custom-select:invalid:focus{border-color:#dc3545;box-shadow:0 0 0 .2rem rgba(220,53,69,.25)}.form-check-input.is-invalid~.form-check-label,.was-validated .form-check-input:invalid~.form-check-label{color:#dc3545}.form-check-input.is-invalid~.invalid-feedback,.form-check-input.is-invalid~.invalid-tooltip,.was-validated .form-check-input:invalid~.invalid-feedback,.was-validated .form-check-input:invalid~.invalid-tooltip{display:block}.custom-control-input.is-invalid~.custom-control-label,.was-validated .custom-control-input:invalid~.custom-control-label{color:#dc3545}.custom-control-input.is-invalid~.custom-control-label::before,.was-validated .custom-control-input:invalid~.custom-control-label::before{border-color:#dc3545}.custom-control-input.is-invalid:checked~.custom-control-label::before,.was-validated .custom-control-input:invalid:checked~.custom-control-label::before{border-color:#e4606d;background-color:#e4606d}.custom-control-input.is-invalid:focus~.custom-control-label::before,.was-validated .custom-control-input:invalid:focus~.custom-control-label::before{box-shadow:0 0 0 .2rem rgba(220,53,69,.25)}.custom-control-input.is-invalid:focus:not(:checked)~.custom-control-label::before,.was-validated .custom-control-input:invalid:focus:not(:checked)~.custom-control-label::before{border-color:#dc3545}.custom-file-input.is-invalid~.custom-file-label,.was-validated .custom-file-input:invalid~.custom-file-label{border-color:#dc3545}.custom-file-input.is-invalid:focus~.custom-file-label,.was-validated .custom-file-input:invalid:focus~.custom-file-label{border-color:#dc3545;box-shadow:0 0 0 .2rem rgba(220,53,69,.25)}.form-inline{display:-ms-flexbox;display:flex;-ms-flex-flow:row wrap;flex-flow:row wrap;-ms-flex-align:center;align-items:center}.form-inline .form-check{width:100%}@media (min-width:576px){.form-inline label{display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;-ms-flex-pack:center;justify-content:center;margin-bottom:0}.form-inline .form-group{display:-ms-flexbox;display:flex;-ms-flex:0 0 auto;flex:0 0 auto;-ms-flex-flow:row wrap;flex-flow:row wrap;-ms-flex-align:center;align-items:center;margin-bottom:0}.form-inline .form-control{display:inline-block;width:auto;vertical-align:middle}.form-inline .form-control-plaintext{display:inline-block}.form-inline .custom-select,.form-inline .input-group{width:auto}.form-inline .form-check{display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;-ms-flex-pack:center;justify-content:center;width:auto;padding-left:0}.form-inline .form-check-input{position:relative;-ms-flex-negative:0;flex-shrink:0;margin-top:0;margin-right:.25rem;margin-left:0}.form-inline .custom-control{-ms-flex-align:center;align-items:center;-ms-flex-pack:center;justify-content:center}.form-inline .custom-control-label{margin-bottom:0}}.btn{display:inline-block;font-weight:400;color:#212529;text-align:center;vertical-align:middle;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;background-color:transparent;border:1px solid transparent;padding:.375rem .75rem;font-size:1rem;line-height:1.5;border-radius:.25rem;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.btn{transition:none}}.btn:hover{color:#212529;text-decoration:none}.btn.focus,.btn:focus{outline:0;box-shadow:0 0 0 .2rem rgba(0,123,255,.25)}.btn.disabled,.btn:disabled{opacity:.65}.btn:not(:disabled):not(.disabled){cursor:pointer}a.btn.disabled,fieldset:disabled a.btn{pointer-events:none}.btn-primary{color:#fff;background-color:#007bff;border-color:#007bff}.btn-primary:hover{color:#fff;background-color:#0069d9;border-color:#0062cc}.btn-primary.focus,.btn-primary:focus{color:#fff;background-color:#0069d9;border-color:#0062cc;box-shadow:0 0 0 .2rem rgba(38,143,255,.5)}.btn-primary.disabled,.btn-primary:disabled{color:#fff;background-color:#007bff;border-color:#007bff}.btn-primary:not(:disabled):not(.disabled).active,.btn-primary:not(:disabled):not(.disabled):active,.show>.btn-primary.dropdown-toggle{color:#fff;background-color:#0062cc;border-color:#005cbf}.btn-primary:not(:disabled):not(.disabled).active:focus,.btn-primary:not(:disabled):not(.disabled):active:focus,.show>.btn-primary.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(38,143,255,.5)}.btn-secondary{color:#fff;background-color:#6c757d;border-color:#6c757d}.btn-secondary:hover{color:#fff;background-color:#5a6268;border-color:#545b62}.btn-secondary.focus,.btn-secondary:focus{color:#fff;background-color:#5a6268;border-color:#545b62;box-shadow:0 0 0 .2rem rgba(130,138,145,.5)}.btn-secondary.disabled,.btn-secondary:disabled{color:#fff;background-color:#6c757d;border-color:#6c757d}.btn-secondary:not(:disabled):not(.disabled).active,.btn-secondary:not(:disabled):not(.disabled):active,.show>.btn-secondary.dropdown-toggle{color:#fff;background-color:#545b62;border-color:#4e555b}.btn-secondary:not(:disabled):not(.disabled).active:focus,.btn-secondary:not(:disabled):not(.disabled):active:focus,.show>.btn-secondary.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(130,138,145,.5)}.btn-success{color:#fff;background-color:#28a745;border-color:#28a745}.btn-success:hover{color:#fff;background-color:#218838;border-color:#1e7e34}.btn-success.focus,.btn-success:focus{color:#fff;background-color:#218838;border-color:#1e7e34;box-shadow:0 0 0 .2rem rgba(72,180,97,.5)}.btn-success.disabled,.btn-success:disabled{color:#fff;background-color:#28a745;border-color:#28a745}.btn-success:not(:disabled):not(.disabled).active,.btn-success:not(:disabled):not(.disabled):active,.show>.btn-success.dropdown-toggle{color:#fff;background-color:#1e7e34;border-color:#1c7430}.btn-success:not(:disabled):not(.disabled).active:focus,.btn-success:not(:disabled):not(.disabled):active:focus,.show>.btn-success.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(72,180,97,.5)}.btn-info{color:#fff;background-color:#17a2b8;border-color:#17a2b8}.btn-info:hover{color:#fff;background-color:#138496;border-color:#117a8b}.btn-info.focus,.btn-info:focus{color:#fff;background-color:#138496;border-color:#117a8b;box-shadow:0 0 0 .2rem rgba(58,176,195,.5)}.btn-info.disabled,.btn-info:disabled{color:#fff;background-color:#17a2b8;border-color:#17a2b8}.btn-info:not(:disabled):not(.disabled).active,.btn-info:not(:disabled):not(.disabled):active,.show>.btn-info.dropdown-toggle{color:#fff;background-color:#117a8b;border-color:#10707f}.btn-info:not(:disabled):not(.disabled).active:focus,.btn-info:not(:disabled):not(.disabled):active:focus,.show>.btn-info.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(58,176,195,.5)}.btn-warning{color:#212529;background-color:#ffc107;border-color:#ffc107}.btn-warning:hover{color:#212529;background-color:#e0a800;border-color:#d39e00}.btn-warning.focus,.btn-warning:focus{color:#212529;background-color:#e0a800;border-color:#d39e00;box-shadow:0 0 0 .2rem rgba(222,170,12,.5)}.btn-warning.disabled,.btn-warning:disabled{color:#212529;background-color:#ffc107;border-color:#ffc107}.btn-warning:not(:disabled):not(.disabled).active,.btn-warning:not(:disabled):not(.disabled):active,.show>.btn-warning.dropdown-toggle{color:#212529;background-color:#d39e00;border-color:#c69500}.btn-warning:not(:disabled):not(.disabled).active:focus,.btn-warning:not(:disabled):not(.disabled):active:focus,.show>.btn-warning.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(222,170,12,.5)}.btn-danger{color:#fff;background-color:#dc3545;border-color:#dc3545}.btn-danger:hover{color:#fff;background-color:#c82333;border-color:#bd2130}.btn-danger.focus,.btn-danger:focus{color:#fff;background-color:#c82333;border-color:#bd2130;box-shadow:0 0 0 .2rem rgba(225,83,97,.5)}.btn-danger.disabled,.btn-danger:disabled{color:#fff;background-color:#dc3545;border-color:#dc3545}.btn-danger:not(:disabled):not(.disabled).active,.btn-danger:not(:disabled):not(.disabled):active,.show>.btn-danger.dropdown-toggle{color:#fff;background-color:#bd2130;border-color:#b21f2d}.btn-danger:not(:disabled):not(.disabled).active:focus,.btn-danger:not(:disabled):not(.disabled):active:focus,.show>.btn-danger.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(225,83,97,.5)}.btn-light{color:#212529;background-color:#f8f9fa;border-color:#f8f9fa}.btn-light:hover{color:#212529;background-color:#e2e6ea;border-color:#dae0e5}.btn-light.focus,.btn-light:focus{color:#212529;background-color:#e2e6ea;border-color:#dae0e5;box-shadow:0 0 0 .2rem rgba(216,217,219,.5)}.btn-light.disabled,.btn-light:disabled{color:#212529;background-color:#f8f9fa;border-color:#f8f9fa}.btn-light:not(:disabled):not(.disabled).active,.btn-light:not(:disabled):not(.disabled):active,.show>.btn-light.dropdown-toggle{color:#212529;background-color:#dae0e5;border-color:#d3d9df}.btn-light:not(:disabled):not(.disabled).active:focus,.btn-light:not(:disabled):not(.disabled):active:focus,.show>.btn-light.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(216,217,219,.5)}.btn-dark{color:#fff;background-color:#343a40;border-color:#343a40}.btn-dark:hover{color:#fff;background-color:#23272b;border-color:#1d2124}.btn-dark.focus,.btn-dark:focus{color:#fff;background-color:#23272b;border-color:#1d2124;box-shadow:0 0 0 .2rem rgba(82,88,93,.5)}.btn-dark.disabled,.btn-dark:disabled{color:#fff;background-color:#343a40;border-color:#343a40}.btn-dark:not(:disabled):not(.disabled).active,.btn-dark:not(:disabled):not(.disabled):active,.show>.btn-dark.dropdown-toggle{color:#fff;background-color:#1d2124;border-color:#171a1d}.btn-dark:not(:disabled):not(.disabled).active:focus,.btn-dark:not(:disabled):not(.disabled):active:focus,.show>.btn-dark.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(82,88,93,.5)}.btn-outline-primary{color:#007bff;border-color:#007bff}.btn-outline-primary:hover{color:#fff;background-color:#007bff;border-color:#007bff}.btn-outline-primary.focus,.btn-outline-primary:focus{box-shadow:0 0 0 .2rem rgba(0,123,255,.5)}.btn-outline-primary.disabled,.btn-outline-primary:disabled{color:#007bff;background-color:transparent}.btn-outline-primary:not(:disabled):not(.disabled).active,.btn-outline-primary:not(:disabled):not(.disabled):active,.show>.btn-outline-primary.dropdown-toggle{color:#fff;background-color:#007bff;border-color:#007bff}.btn-outline-primary:not(:disabled):not(.disabled).active:focus,.btn-outline-primary:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-primary.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(0,123,255,.5)}.btn-outline-secondary{color:#6c757d;border-color:#6c757d}.btn-outline-secondary:hover{color:#fff;background-color:#6c757d;border-color:#6c757d}.btn-outline-secondary.focus,.btn-outline-secondary:focus{box-shadow:0 0 0 .2rem rgba(108,117,125,.5)}.btn-outline-secondary.disabled,.btn-outline-secondary:disabled{color:#6c757d;background-color:transparent}.btn-outline-secondary:not(:disabled):not(.disabled).active,.btn-outline-secondary:not(:disabled):not(.disabled):active,.show>.btn-outline-secondary.dropdown-toggle{color:#fff;background-color:#6c757d;border-color:#6c757d}.btn-outline-secondary:not(:disabled):not(.disabled).active:focus,.btn-outline-secondary:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-secondary.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(108,117,125,.5)}.btn-outline-success{color:#28a745;border-color:#28a745}.btn-outline-success:hover{color:#fff;background-color:#28a745;border-color:#28a745}.btn-outline-success.focus,.btn-outline-success:focus{box-shadow:0 0 0 .2rem rgba(40,167,69,.5)}.btn-outline-success.disabled,.btn-outline-success:disabled{color:#28a745;background-color:transparent}.btn-outline-success:not(:disabled):not(.disabled).active,.btn-outline-success:not(:disabled):not(.disabled):active,.show>.btn-outline-success.dropdown-toggle{color:#fff;background-color:#28a745;border-color:#28a745}.btn-outline-success:not(:disabled):not(.disabled).active:focus,.btn-outline-success:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-success.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(40,167,69,.5)}.btn-outline-info{color:#17a2b8;border-color:#17a2b8}.btn-outline-info:hover{color:#fff;background-color:#17a2b8;border-color:#17a2b8}.btn-outline-info.focus,.btn-outline-info:focus{box-shadow:0 0 0 .2rem rgba(23,162,184,.5)}.btn-outline-info.disabled,.btn-outline-info:disabled{color:#17a2b8;background-color:transparent}.btn-outline-info:not(:disabled):not(.disabled).active,.btn-outline-info:not(:disabled):not(.disabled):active,.show>.btn-outline-info.dropdown-toggle{color:#fff;background-color:#17a2b8;border-color:#17a2b8}.btn-outline-info:not(:disabled):not(.disabled).active:focus,.btn-outline-info:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-info.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(23,162,184,.5)}.btn-outline-warning{color:#ffc107;border-color:#ffc107}.btn-outline-warning:hover{color:#212529;background-color:#ffc107;border-color:#ffc107}.btn-outline-warning.focus,.btn-outline-warning:focus{box-shadow:0 0 0 .2rem rgba(255,193,7,.5)}.btn-outline-warning.disabled,.btn-outline-warning:disabled{color:#ffc107;background-color:transparent}.btn-outline-warning:not(:disabled):not(.disabled).active,.btn-outline-warning:not(:disabled):not(.disabled):active,.show>.btn-outline-warning.dropdown-toggle{color:#212529;background-color:#ffc107;border-color:#ffc107}.btn-outline-warning:not(:disabled):not(.disabled).active:focus,.btn-outline-warning:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-warning.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(255,193,7,.5)}.btn-outline-danger{color:#dc3545;border-color:#dc3545}.btn-outline-danger:hover{color:#fff;background-color:#dc3545;border-color:#dc3545}.btn-outline-danger.focus,.btn-outline-danger:focus{box-shadow:0 0 0 .2rem rgba(220,53,69,.5)}.btn-outline-danger.disabled,.btn-outline-danger:disabled{color:#dc3545;background-color:transparent}.btn-outline-danger:not(:disabled):not(.disabled).active,.btn-outline-danger:not(:disabled):not(.disabled):active,.show>.btn-outline-danger.dropdown-toggle{color:#fff;background-color:#dc3545;border-color:#dc3545}.btn-outline-danger:not(:disabled):not(.disabled).active:focus,.btn-outline-danger:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-danger.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(220,53,69,.5)}.btn-outline-light{color:#f8f9fa;border-color:#f8f9fa}.btn-outline-light:hover{color:#212529;background-color:#f8f9fa;border-color:#f8f9fa}.btn-outline-light.focus,.btn-outline-light:focus{box-shadow:0 0 0 .2rem rgba(248,249,250,.5)}.btn-outline-light.disabled,.btn-outline-light:disabled{color:#f8f9fa;background-color:transparent}.btn-outline-light:not(:disabled):not(.disabled).active,.btn-outline-light:not(:disabled):not(.disabled):active,.show>.btn-outline-light.dropdown-toggle{color:#212529;background-color:#f8f9fa;border-color:#f8f9fa}.btn-outline-light:not(:disabled):not(.disabled).active:focus,.btn-outline-light:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-light.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(248,249,250,.5)}.btn-outline-dark{color:#343a40;border-color:#343a40}.btn-outline-dark:hover{color:#fff;background-color:#343a40;border-color:#343a40}.btn-outline-dark.focus,.btn-outline-dark:focus{box-shadow:0 0 0 .2rem rgba(52,58,64,.5)}.btn-outline-dark.disabled,.btn-outline-dark:disabled{color:#343a40;background-color:transparent}.btn-outline-dark:not(:disabled):not(.disabled).active,.btn-outline-dark:not(:disabled):not(.disabled):active,.show>.btn-outline-dark.dropdown-toggle{color:#fff;background-color:#343a40;border-color:#343a40}.btn-outline-dark:not(:disabled):not(.disabled).active:focus,.btn-outline-dark:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-dark.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(52,58,64,.5)}.btn-link{font-weight:400;color:#007bff;text-decoration:none}.btn-link:hover{color:#0056b3;text-decoration:underline}.btn-link.focus,.btn-link:focus{text-decoration:underline}.btn-link.disabled,.btn-link:disabled{color:#6c757d;pointer-events:none}.btn-group-lg>.btn,.btn-lg{padding:.5rem 1rem;font-size:1.25rem;line-height:1.5;border-radius:.3rem}.btn-group-sm>.btn,.btn-sm{padding:.25rem .5rem;font-size:.875rem;line-height:1.5;border-radius:.2rem}.btn-block{display:block;width:100%}.btn-block+.btn-block{margin-top:.5rem}input[type=button].btn-block,input[type=reset].btn-block,input[type=submit].btn-block{width:100%}.fade{transition:opacity .15s linear}@media (prefers-reduced-motion:reduce){.fade{transition:none}}.fade:not(.show){opacity:0}.collapse:not(.show){display:none}.collapsing{position:relative;height:0;overflow:hidden;transition:height .35s ease}@media (prefers-reduced-motion:reduce){.collapsing{transition:none}}.dropdown,.dropleft,.dropright,.dropup{position:relative}.dropdown-toggle{white-space:nowrap}.dropdown-toggle::after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:"";border-top:.3em solid;border-right:.3em solid transparent;border-bottom:0;border-left:.3em solid transparent}.dropdown-toggle:empty::after{margin-left:0}.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;float:left;min-width:10rem;padding:.5rem 0;margin:.125rem 0 0;font-size:1rem;color:#212529;text-align:left;list-style:none;background-color:#fff;background-clip:padding-box;border:1px solid rgba(0,0,0,.15);border-radius:.25rem}.dropdown-menu-left{right:auto;left:0}.dropdown-menu-right{right:0;left:auto}@media (min-width:576px){.dropdown-menu-sm-left{right:auto;left:0}.dropdown-menu-sm-right{right:0;left:auto}}@media (min-width:768px){.dropdown-menu-md-left{right:auto;left:0}.dropdown-menu-md-right{right:0;left:auto}}@media (min-width:992px){.dropdown-menu-lg-left{right:auto;left:0}.dropdown-menu-lg-right{right:0;left:auto}}@media (min-width:1200px){.dropdown-menu-xl-left{right:auto;left:0}.dropdown-menu-xl-right{right:0;left:auto}}.dropup .dropdown-menu{top:auto;bottom:100%;margin-top:0;margin-bottom:.125rem}.dropup .dropdown-toggle::after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:"";border-top:0;border-right:.3em solid transparent;border-bottom:.3em solid;border-left:.3em solid transparent}.dropup .dropdown-toggle:empty::after{margin-left:0}.dropright .dropdown-menu{top:0;right:auto;left:100%;margin-top:0;margin-left:.125rem}.dropright .dropdown-toggle::after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:"";border-top:.3em solid transparent;border-right:0;border-bottom:.3em solid transparent;border-left:.3em solid}.dropright .dropdown-toggle:empty::after{margin-left:0}.dropright .dropdown-toggle::after{vertical-align:0}.dropleft .dropdown-menu{top:0;right:100%;left:auto;margin-top:0;margin-right:.125rem}.dropleft .dropdown-toggle::after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:""}.dropleft .dropdown-toggle::after{display:none}.dropleft .dropdown-toggle::before{display:inline-block;margin-right:.255em;vertical-align:.255em;content:"";border-top:.3em solid transparent;border-right:.3em solid;border-bottom:.3em solid transparent}.dropleft .dropdown-toggle:empty::after{margin-left:0}.dropleft .dropdown-toggle::before{vertical-align:0}.dropdown-menu[x-placement^=bottom],.dropdown-menu[x-placement^=left],.dropdown-menu[x-placement^=right],.dropdown-menu[x-placement^=top]{right:auto;bottom:auto}.dropdown-divider{height:0;margin:.5rem 0;overflow:hidden;border-top:1px solid #e9ecef}.dropdown-item{display:block;width:100%;padding:.25rem 1.5rem;clear:both;font-weight:400;color:#212529;text-align:inherit;white-space:nowrap;background-color:transparent;border:0}.dropdown-item:focus,.dropdown-item:hover{color:#16181b;text-decoration:none;background-color:#f8f9fa}.dropdown-item.active,.dropdown-item:active{color:#fff;text-decoration:none;background-color:#007bff}.dropdown-item.disabled,.dropdown-item:disabled{color:#6c757d;pointer-events:none;background-color:transparent}.dropdown-menu.show{display:block}.dropdown-header{display:block;padding:.5rem 1.5rem;margin-bottom:0;font-size:.875rem;color:#6c757d;white-space:nowrap}.dropdown-item-text{display:block;padding:.25rem 1.5rem;color:#212529}.btn-group,.btn-group-vertical{position:relative;display:-ms-inline-flexbox;display:inline-flex;vertical-align:middle}.btn-group-vertical>.btn,.btn-group>.btn{position:relative;-ms-flex:1 1 auto;flex:1 1 auto}.btn-group-vertical>.btn:hover,.btn-group>.btn:hover{z-index:1}.btn-group-vertical>.btn.active,.btn-group-vertical>.btn:active,.btn-group-vertical>.btn:focus,.btn-group>.btn.active,.btn-group>.btn:active,.btn-group>.btn:focus{z-index:1}.btn-toolbar{display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;-ms-flex-pack:start;justify-content:flex-start}.btn-toolbar .input-group{width:auto}.btn-group>.btn-group:not(:first-child),.btn-group>.btn:not(:first-child){margin-left:-1px}.btn-group>.btn-group:not(:last-child)>.btn,.btn-group>.btn:not(:last-child):not(.dropdown-toggle){border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn-group:not(:first-child)>.btn,.btn-group>.btn:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.dropdown-toggle-split{padding-right:.5625rem;padding-left:.5625rem}.dropdown-toggle-split::after,.dropright .dropdown-toggle-split::after,.dropup .dropdown-toggle-split::after{margin-left:0}.dropleft .dropdown-toggle-split::before{margin-right:0}.btn-group-sm>.btn+.dropdown-toggle-split,.btn-sm+.dropdown-toggle-split{padding-right:.375rem;padding-left:.375rem}.btn-group-lg>.btn+.dropdown-toggle-split,.btn-lg+.dropdown-toggle-split{padding-right:.75rem;padding-left:.75rem}.btn-group-vertical{-ms-flex-direction:column;flex-direction:column;-ms-flex-align:start;align-items:flex-start;-ms-flex-pack:center;justify-content:center}.btn-group-vertical>.btn,.btn-group-vertical>.btn-group{width:100%}.btn-group-vertical>.btn-group:not(:first-child),.btn-group-vertical>.btn:not(:first-child){margin-top:-1px}.btn-group-vertical>.btn-group:not(:last-child)>.btn,.btn-group-vertical>.btn:not(:last-child):not(.dropdown-toggle){border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn-group:not(:first-child)>.btn,.btn-group-vertical>.btn:not(:first-child){border-top-left-radius:0;border-top-right-radius:0}.btn-group-toggle>.btn,.btn-group-toggle>.btn-group>.btn{margin-bottom:0}.btn-group-toggle>.btn input[type=checkbox],.btn-group-toggle>.btn input[type=radio],.btn-group-toggle>.btn-group>.btn input[type=checkbox],.btn-group-toggle>.btn-group>.btn input[type=radio]{position:absolute;clip:rect(0,0,0,0);pointer-events:none}.input-group{position:relative;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;-ms-flex-align:stretch;align-items:stretch;width:100%}.input-group>.custom-file,.input-group>.custom-select,.input-group>.form-control,.input-group>.form-control-plaintext{position:relative;-ms-flex:1 1 auto;flex:1 1 auto;width:1%;min-width:0;margin-bottom:0}.input-group>.custom-file+.custom-file,.input-group>.custom-file+.custom-select,.input-group>.custom-file+.form-control,.input-group>.custom-select+.custom-file,.input-group>.custom-select+.custom-select,.input-group>.custom-select+.form-control,.input-group>.form-control+.custom-file,.input-group>.form-control+.custom-select,.input-group>.form-control+.form-control,.input-group>.form-control-plaintext+.custom-file,.input-group>.form-control-plaintext+.custom-select,.input-group>.form-control-plaintext+.form-control{margin-left:-1px}.input-group>.custom-file .custom-file-input:focus~.custom-file-label,.input-group>.custom-select:focus,.input-group>.form-control:focus{z-index:3}.input-group>.custom-file .custom-file-input:focus{z-index:4}.input-group>.custom-select:not(:last-child),.input-group>.form-control:not(:last-child){border-top-right-radius:0;border-bottom-right-radius:0}.input-group>.custom-select:not(:first-child),.input-group>.form-control:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.input-group>.custom-file{display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center}.input-group>.custom-file:not(:last-child) .custom-file-label,.input-group>.custom-file:not(:last-child) .custom-file-label::after{border-top-right-radius:0;border-bottom-right-radius:0}.input-group>.custom-file:not(:first-child) .custom-file-label{border-top-left-radius:0;border-bottom-left-radius:0}.input-group-append,.input-group-prepend{display:-ms-flexbox;display:flex}.input-group-append .btn,.input-group-prepend .btn{position:relative;z-index:2}.input-group-append .btn:focus,.input-group-prepend .btn:focus{z-index:3}.input-group-append .btn+.btn,.input-group-append .btn+.input-group-text,.input-group-append .input-group-text+.btn,.input-group-append .input-group-text+.input-group-text,.input-group-prepend .btn+.btn,.input-group-prepend .btn+.input-group-text,.input-group-prepend .input-group-text+.btn,.input-group-prepend .input-group-text+.input-group-text{margin-left:-1px}.input-group-prepend{margin-right:-1px}.input-group-append{margin-left:-1px}.input-group-text{display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;padding:.375rem .75rem;margin-bottom:0;font-size:1rem;font-weight:400;line-height:1.5;color:#495057;text-align:center;white-space:nowrap;background-color:#e9ecef;border:1px solid #ced4da;border-radius:.25rem}.input-group-text input[type=checkbox],.input-group-text input[type=radio]{margin-top:0}.input-group-lg>.custom-select,.input-group-lg>.form-control:not(textarea){height:calc(1.5em + 1rem + 2px)}.input-group-lg>.custom-select,.input-group-lg>.form-control,.input-group-lg>.input-group-append>.btn,.input-group-lg>.input-group-append>.input-group-text,.input-group-lg>.input-group-prepend>.btn,.input-group-lg>.input-group-prepend>.input-group-text{padding:.5rem 1rem;font-size:1.25rem;line-height:1.5;border-radius:.3rem}.input-group-sm>.custom-select,.input-group-sm>.form-control:not(textarea){height:calc(1.5em + .5rem + 2px)}.input-group-sm>.custom-select,.input-group-sm>.form-control,.input-group-sm>.input-group-append>.btn,.input-group-sm>.input-group-append>.input-group-text,.input-group-sm>.input-group-prepend>.btn,.input-group-sm>.input-group-prepend>.input-group-text{padding:.25rem .5rem;font-size:.875rem;line-height:1.5;border-radius:.2rem}.input-group-lg>.custom-select,.input-group-sm>.custom-select{padding-right:1.75rem}.input-group>.input-group-append:last-child>.btn:not(:last-child):not(.dropdown-toggle),.input-group>.input-group-append:last-child>.input-group-text:not(:last-child),.input-group>.input-group-append:not(:last-child)>.btn,.input-group>.input-group-append:not(:last-child)>.input-group-text,.input-group>.input-group-prepend>.btn,.input-group>.input-group-prepend>.input-group-text{border-top-right-radius:0;border-bottom-right-radius:0}.input-group>.input-group-append>.btn,.input-group>.input-group-append>.input-group-text,.input-group>.input-group-prepend:first-child>.btn:not(:first-child),.input-group>.input-group-prepend:first-child>.input-group-text:not(:first-child),.input-group>.input-group-prepend:not(:first-child)>.btn,.input-group>.input-group-prepend:not(:first-child)>.input-group-text{border-top-left-radius:0;border-bottom-left-radius:0}.custom-control{position:relative;display:block;min-height:1.5rem;padding-left:1.5rem}.custom-control-inline{display:-ms-inline-flexbox;display:inline-flex;margin-right:1rem}.custom-control-input{position:absolute;left:0;z-index:-1;width:1rem;height:1.25rem;opacity:0}.custom-control-input:checked~.custom-control-label::before{color:#fff;border-color:#007bff;background-color:#007bff}.custom-control-input:focus~.custom-control-label::before{box-shadow:0 0 0 .2rem rgba(0,123,255,.25)}.custom-control-input:focus:not(:checked)~.custom-control-label::before{border-color:#80bdff}.custom-control-input:not(:disabled):active~.custom-control-label::before{color:#fff;background-color:#b3d7ff;border-color:#b3d7ff}.custom-control-input:disabled~.custom-control-label,.custom-control-input[disabled]~.custom-control-label{color:#6c757d}.custom-control-input:disabled~.custom-control-label::before,.custom-control-input[disabled]~.custom-control-label::before{background-color:#e9ecef}.custom-control-label{position:relative;margin-bottom:0;vertical-align:top}.custom-control-label::before{position:absolute;top:.25rem;left:-1.5rem;display:block;width:1rem;height:1rem;pointer-events:none;content:"";background-color:#fff;border:#adb5bd solid 1px}.custom-control-label::after{position:absolute;top:.25rem;left:-1.5rem;display:block;width:1rem;height:1rem;content:"";background:no-repeat 50%/50% 50%}.custom-checkbox .custom-control-label::before{border-radius:.25rem}.custom-checkbox .custom-control-input:checked~.custom-control-label::after{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='8' height='8' viewBox='0 0 8 8'%3e%3cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26l2.974 2.99L8 2.193z'/%3e%3c/svg%3e")}.custom-checkbox .custom-control-input:indeterminate~.custom-control-label::before{border-color:#007bff;background-color:#007bff}.custom-checkbox .custom-control-input:indeterminate~.custom-control-label::after{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='4' height='4' viewBox='0 0 4 4'%3e%3cpath stroke='%23fff' d='M0 2h4'/%3e%3c/svg%3e")}.custom-checkbox .custom-control-input:disabled:checked~.custom-control-label::before{background-color:rgba(0,123,255,.5)}.custom-checkbox .custom-control-input:disabled:indeterminate~.custom-control-label::before{background-color:rgba(0,123,255,.5)}.custom-radio .custom-control-label::before{border-radius:50%}.custom-radio .custom-control-input:checked~.custom-control-label::after{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%23fff'/%3e%3c/svg%3e")}.custom-radio .custom-control-input:disabled:checked~.custom-control-label::before{background-color:rgba(0,123,255,.5)}.custom-switch{padding-left:2.25rem}.custom-switch .custom-control-label::before{left:-2.25rem;width:1.75rem;pointer-events:all;border-radius:.5rem}.custom-switch .custom-control-label::after{top:calc(.25rem + 2px);left:calc(-2.25rem + 2px);width:calc(1rem - 4px);height:calc(1rem - 4px);background-color:#adb5bd;border-radius:.5rem;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out,-webkit-transform .15s ease-in-out;transition:transform .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:transform .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out,-webkit-transform .15s ease-in-out}@media (prefers-reduced-motion:reduce){.custom-switch .custom-control-label::after{transition:none}}.custom-switch .custom-control-input:checked~.custom-control-label::after{background-color:#fff;-webkit-transform:translateX(.75rem);transform:translateX(.75rem)}.custom-switch .custom-control-input:disabled:checked~.custom-control-label::before{background-color:rgba(0,123,255,.5)}.custom-select{display:inline-block;width:100%;height:calc(1.5em + .75rem + 2px);padding:.375rem 1.75rem .375rem .75rem;font-size:1rem;font-weight:400;line-height:1.5;color:#495057;vertical-align:middle;background:#fff url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='4' height='5' viewBox='0 0 4 5'%3e%3cpath fill='%23343a40' d='M2 0L0 2h4zm0 5L0 3h4z'/%3e%3c/svg%3e") no-repeat right .75rem center/8px 10px;border:1px solid #ced4da;border-radius:.25rem;-webkit-appearance:none;-moz-appearance:none;appearance:none}.custom-select:focus{border-color:#80bdff;outline:0;box-shadow:0 0 0 .2rem rgba(0,123,255,.25)}.custom-select:focus::-ms-value{color:#495057;background-color:#fff}.custom-select[multiple],.custom-select[size]:not([size="1"]){height:auto;padding-right:.75rem;background-image:none}.custom-select:disabled{color:#6c757d;background-color:#e9ecef}.custom-select::-ms-expand{display:none}.custom-select:-moz-focusring{color:transparent;text-shadow:0 0 0 #495057}.custom-select-sm{height:calc(1.5em + .5rem + 2px);padding-top:.25rem;padding-bottom:.25rem;padding-left:.5rem;font-size:.875rem}.custom-select-lg{height:calc(1.5em + 1rem + 2px);padding-top:.5rem;padding-bottom:.5rem;padding-left:1rem;font-size:1.25rem}.custom-file{position:relative;display:inline-block;width:100%;height:calc(1.5em + .75rem + 2px);margin-bottom:0}.custom-file-input{position:relative;z-index:2;width:100%;height:calc(1.5em + .75rem + 2px);margin:0;opacity:0}.custom-file-input:focus~.custom-file-label{border-color:#80bdff;box-shadow:0 0 0 .2rem rgba(0,123,255,.25)}.custom-file-input:disabled~.custom-file-label,.custom-file-input[disabled]~.custom-file-label{background-color:#e9ecef}.custom-file-input:lang(en)~.custom-file-label::after{content:"Browse"}.custom-file-input~.custom-file-label[data-browse]::after{content:attr(data-browse)}.custom-file-label{position:absolute;top:0;right:0;left:0;z-index:1;height:calc(1.5em + .75rem + 2px);padding:.375rem .75rem;font-weight:400;line-height:1.5;color:#495057;background-color:#fff;border:1px solid #ced4da;border-radius:.25rem}.custom-file-label::after{position:absolute;top:0;right:0;bottom:0;z-index:3;display:block;height:calc(1.5em + .75rem);padding:.375rem .75rem;line-height:1.5;color:#495057;content:"Browse";background-color:#e9ecef;border-left:inherit;border-radius:0 .25rem .25rem 0}.custom-range{width:100%;height:1.4rem;padding:0;background-color:transparent;-webkit-appearance:none;-moz-appearance:none;appearance:none}.custom-range:focus{outline:0}.custom-range:focus::-webkit-slider-thumb{box-shadow:0 0 0 1px #fff,0 0 0 .2rem rgba(0,123,255,.25)}.custom-range:focus::-moz-range-thumb{box-shadow:0 0 0 1px #fff,0 0 0 .2rem rgba(0,123,255,.25)}.custom-range:focus::-ms-thumb{box-shadow:0 0 0 1px #fff,0 0 0 .2rem rgba(0,123,255,.25)}.custom-range::-moz-focus-outer{border:0}.custom-range::-webkit-slider-thumb{width:1rem;height:1rem;margin-top:-.25rem;background-color:#007bff;border:0;border-radius:1rem;-webkit-transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;-webkit-appearance:none;appearance:none}@media (prefers-reduced-motion:reduce){.custom-range::-webkit-slider-thumb{-webkit-transition:none;transition:none}}.custom-range::-webkit-slider-thumb:active{background-color:#b3d7ff}.custom-range::-webkit-slider-runnable-track{width:100%;height:.5rem;color:transparent;cursor:pointer;background-color:#dee2e6;border-color:transparent;border-radius:1rem}.custom-range::-moz-range-thumb{width:1rem;height:1rem;background-color:#007bff;border:0;border-radius:1rem;-moz-transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;-moz-appearance:none;appearance:none}@media (prefers-reduced-motion:reduce){.custom-range::-moz-range-thumb{-moz-transition:none;transition:none}}.custom-range::-moz-range-thumb:active{background-color:#b3d7ff}.custom-range::-moz-range-track{width:100%;height:.5rem;color:transparent;cursor:pointer;background-color:#dee2e6;border-color:transparent;border-radius:1rem}.custom-range::-ms-thumb{width:1rem;height:1rem;margin-top:0;margin-right:.2rem;margin-left:.2rem;background-color:#007bff;border:0;border-radius:1rem;-ms-transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;appearance:none}@media (prefers-reduced-motion:reduce){.custom-range::-ms-thumb{-ms-transition:none;transition:none}}.custom-range::-ms-thumb:active{background-color:#b3d7ff}.custom-range::-ms-track{width:100%;height:.5rem;color:transparent;cursor:pointer;background-color:transparent;border-color:transparent;border-width:.5rem}.custom-range::-ms-fill-lower{background-color:#dee2e6;border-radius:1rem}.custom-range::-ms-fill-upper{margin-right:15px;background-color:#dee2e6;border-radius:1rem}.custom-range:disabled::-webkit-slider-thumb{background-color:#adb5bd}.custom-range:disabled::-webkit-slider-runnable-track{cursor:default}.custom-range:disabled::-moz-range-thumb{background-color:#adb5bd}.custom-range:disabled::-moz-range-track{cursor:default}.custom-range:disabled::-ms-thumb{background-color:#adb5bd}.custom-control-label::before,.custom-file-label,.custom-select{transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.custom-control-label::before,.custom-file-label,.custom-select{transition:none}}.nav{display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;padding-left:0;margin-bottom:0;list-style:none}.nav-link{display:block;padding:.5rem 1rem}.nav-link:focus,.nav-link:hover{text-decoration:none}.nav-link.disabled{color:#6c757d;pointer-events:none;cursor:default}.nav-tabs{border-bottom:1px solid #dee2e6}.nav-tabs .nav-item{margin-bottom:-1px}.nav-tabs .nav-link{border:1px solid transparent;border-top-left-radius:.25rem;border-top-right-radius:.25rem}.nav-tabs .nav-link:focus,.nav-tabs .nav-link:hover{border-color:#e9ecef #e9ecef #dee2e6}.nav-tabs .nav-link.disabled{color:#6c757d;background-color:transparent;border-color:transparent}.nav-tabs .nav-item.show .nav-link,.nav-tabs .nav-link.active{color:#495057;background-color:#fff;border-color:#dee2e6 #dee2e6 #fff}.nav-tabs .dropdown-menu{margin-top:-1px;border-top-left-radius:0;border-top-right-radius:0}.nav-pills .nav-link{border-radius:.25rem}.nav-pills .nav-link.active,.nav-pills .show>.nav-link{color:#fff;background-color:#007bff}.nav-fill .nav-item{-ms-flex:1 1 auto;flex:1 1 auto;text-align:center}.nav-justified .nav-item{-ms-flex-preferred-size:0;flex-basis:0;-ms-flex-positive:1;flex-grow:1;text-align:center}.tab-content>.tab-pane{display:none}.tab-content>.active{display:block}.navbar{position:relative;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;-ms-flex-align:center;align-items:center;-ms-flex-pack:justify;justify-content:space-between;padding:.5rem 1rem}.navbar .container,.navbar .container-fluid,.navbar .container-lg,.navbar .container-md,.navbar .container-sm,.navbar .container-xl{display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;-ms-flex-align:center;align-items:center;-ms-flex-pack:justify;justify-content:space-between}.navbar-brand{display:inline-block;padding-top:.3125rem;padding-bottom:.3125rem;margin-right:1rem;font-size:1.25rem;line-height:inherit;white-space:nowrap}.navbar-brand:focus,.navbar-brand:hover{text-decoration:none}.navbar-nav{display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;padding-left:0;margin-bottom:0;list-style:none}.navbar-nav .nav-link{padding-right:0;padding-left:0}.navbar-nav .dropdown-menu{position:static;float:none}.navbar-text{display:inline-block;padding-top:.5rem;padding-bottom:.5rem}.navbar-collapse{-ms-flex-preferred-size:100%;flex-basis:100%;-ms-flex-positive:1;flex-grow:1;-ms-flex-align:center;align-items:center}.navbar-toggler{padding:.25rem .75rem;font-size:1.25rem;line-height:1;background-color:transparent;border:1px solid transparent;border-radius:.25rem}.navbar-toggler:focus,.navbar-toggler:hover{text-decoration:none}.navbar-toggler-icon{display:inline-block;width:1.5em;height:1.5em;vertical-align:middle;content:"";background:no-repeat center center;background-size:100% 100%}@media (max-width:575.98px){.navbar-expand-sm>.container,.navbar-expand-sm>.container-fluid,.navbar-expand-sm>.container-lg,.navbar-expand-sm>.container-md,.navbar-expand-sm>.container-sm,.navbar-expand-sm>.container-xl{padding-right:0;padding-left:0}}@media (min-width:576px){.navbar-expand-sm{-ms-flex-flow:row nowrap;flex-flow:row nowrap;-ms-flex-pack:start;justify-content:flex-start}.navbar-expand-sm .navbar-nav{-ms-flex-direction:row;flex-direction:row}.navbar-expand-sm .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-sm .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand-sm>.container,.navbar-expand-sm>.container-fluid,.navbar-expand-sm>.container-lg,.navbar-expand-sm>.container-md,.navbar-expand-sm>.container-sm,.navbar-expand-sm>.container-xl{-ms-flex-wrap:nowrap;flex-wrap:nowrap}.navbar-expand-sm .navbar-collapse{display:-ms-flexbox!important;display:flex!important;-ms-flex-preferred-size:auto;flex-basis:auto}.navbar-expand-sm .navbar-toggler{display:none}}@media (max-width:767.98px){.navbar-expand-md>.container,.navbar-expand-md>.container-fluid,.navbar-expand-md>.container-lg,.navbar-expand-md>.container-md,.navbar-expand-md>.container-sm,.navbar-expand-md>.container-xl{padding-right:0;padding-left:0}}@media (min-width:768px){.navbar-expand-md{-ms-flex-flow:row nowrap;flex-flow:row nowrap;-ms-flex-pack:start;justify-content:flex-start}.navbar-expand-md .navbar-nav{-ms-flex-direction:row;flex-direction:row}.navbar-expand-md .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-md .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand-md>.container,.navbar-expand-md>.container-fluid,.navbar-expand-md>.container-lg,.navbar-expand-md>.container-md,.navbar-expand-md>.container-sm,.navbar-expand-md>.container-xl{-ms-flex-wrap:nowrap;flex-wrap:nowrap}.navbar-expand-md .navbar-collapse{display:-ms-flexbox!important;display:flex!important;-ms-flex-preferred-size:auto;flex-basis:auto}.navbar-expand-md .navbar-toggler{display:none}}@media (max-width:991.98px){.navbar-expand-lg>.container,.navbar-expand-lg>.container-fluid,.navbar-expand-lg>.container-lg,.navbar-expand-lg>.container-md,.navbar-expand-lg>.container-sm,.navbar-expand-lg>.container-xl{padding-right:0;padding-left:0}}@media (min-width:992px){.navbar-expand-lg{-ms-flex-flow:row nowrap;flex-flow:row nowrap;-ms-flex-pack:start;justify-content:flex-start}.navbar-expand-lg .navbar-nav{-ms-flex-direction:row;flex-direction:row}.navbar-expand-lg .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-lg .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand-lg>.container,.navbar-expand-lg>.container-fluid,.navbar-expand-lg>.container-lg,.navbar-expand-lg>.container-md,.navbar-expand-lg>.container-sm,.navbar-expand-lg>.container-xl{-ms-flex-wrap:nowrap;flex-wrap:nowrap}.navbar-expand-lg .navbar-collapse{display:-ms-flexbox!important;display:flex!important;-ms-flex-preferred-size:auto;flex-basis:auto}.navbar-expand-lg .navbar-toggler{display:none}}@media (max-width:1199.98px){.navbar-expand-xl>.container,.navbar-expand-xl>.container-fluid,.navbar-expand-xl>.container-lg,.navbar-expand-xl>.container-md,.navbar-expand-xl>.container-sm,.navbar-expand-xl>.container-xl{padding-right:0;padding-left:0}}@media (min-width:1200px){.navbar-expand-xl{-ms-flex-flow:row nowrap;flex-flow:row nowrap;-ms-flex-pack:start;justify-content:flex-start}.navbar-expand-xl .navbar-nav{-ms-flex-direction:row;flex-direction:row}.navbar-expand-xl .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-xl .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand-xl>.container,.navbar-expand-xl>.container-fluid,.navbar-expand-xl>.container-lg,.navbar-expand-xl>.container-md,.navbar-expand-xl>.container-sm,.navbar-expand-xl>.container-xl{-ms-flex-wrap:nowrap;flex-wrap:nowrap}.navbar-expand-xl .navbar-collapse{display:-ms-flexbox!important;display:flex!important;-ms-flex-preferred-size:auto;flex-basis:auto}.navbar-expand-xl .navbar-toggler{display:none}}.navbar-expand{-ms-flex-flow:row nowrap;flex-flow:row nowrap;-ms-flex-pack:start;justify-content:flex-start}.navbar-expand>.container,.navbar-expand>.container-fluid,.navbar-expand>.container-lg,.navbar-expand>.container-md,.navbar-expand>.container-sm,.navbar-expand>.container-xl{padding-right:0;padding-left:0}.navbar-expand .navbar-nav{-ms-flex-direction:row;flex-direction:row}.navbar-expand .navbar-nav .dropdown-menu{position:absolute}.navbar-expand .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand>.container,.navbar-expand>.container-fluid,.navbar-expand>.container-lg,.navbar-expand>.container-md,.navbar-expand>.container-sm,.navbar-expand>.container-xl{-ms-flex-wrap:nowrap;flex-wrap:nowrap}.navbar-expand .navbar-collapse{display:-ms-flexbox!important;display:flex!important;-ms-flex-preferred-size:auto;flex-basis:auto}.navbar-expand .navbar-toggler{display:none}.navbar-light .navbar-brand{color:rgba(0,0,0,.9)}.navbar-light .navbar-brand:focus,.navbar-light .navbar-brand:hover{color:rgba(0,0,0,.9)}.navbar-light .navbar-nav .nav-link{color:rgba(0,0,0,.5)}.navbar-light .navbar-nav .nav-link:focus,.navbar-light .navbar-nav .nav-link:hover{color:rgba(0,0,0,.7)}.navbar-light .navbar-nav .nav-link.disabled{color:rgba(0,0,0,.3)}.navbar-light .navbar-nav .active>.nav-link,.navbar-light .navbar-nav .nav-link.active,.navbar-light .navbar-nav .nav-link.show,.navbar-light .navbar-nav .show>.nav-link{color:rgba(0,0,0,.9)}.navbar-light .navbar-toggler{color:rgba(0,0,0,.5);border-color:rgba(0,0,0,.1)}.navbar-light .navbar-toggler-icon{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='30' height='30' viewBox='0 0 30 30'%3e%3cpath stroke='rgba%280, 0, 0, 0.5%29' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e")}.navbar-light .navbar-text{color:rgba(0,0,0,.5)}.navbar-light .navbar-text a{color:rgba(0,0,0,.9)}.navbar-light .navbar-text a:focus,.navbar-light .navbar-text a:hover{color:rgba(0,0,0,.9)}.navbar-dark .navbar-brand{color:#fff}.navbar-dark .navbar-brand:focus,.navbar-dark .navbar-brand:hover{color:#fff}.navbar-dark .navbar-nav .nav-link{color:rgba(255,255,255,.5)}.navbar-dark .navbar-nav .nav-link:focus,.navbar-dark .navbar-nav .nav-link:hover{color:rgba(255,255,255,.75)}.navbar-dark .navbar-nav .nav-link.disabled{color:rgba(255,255,255,.25)}.navbar-dark .navbar-nav .active>.nav-link,.navbar-dark .navbar-nav .nav-link.active,.navbar-dark .navbar-nav .nav-link.show,.navbar-dark .navbar-nav .show>.nav-link{color:#fff}.navbar-dark .navbar-toggler{color:rgba(255,255,255,.5);border-color:rgba(255,255,255,.1)}.navbar-dark .navbar-toggler-icon{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='30' height='30' viewBox='0 0 30 30'%3e%3cpath stroke='rgba%28255, 255, 255, 0.5%29' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e")}.navbar-dark .navbar-text{color:rgba(255,255,255,.5)}.navbar-dark .navbar-text a{color:#fff}.navbar-dark .navbar-text a:focus,.navbar-dark .navbar-text a:hover{color:#fff}.card{position:relative;display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;min-width:0;word-wrap:break-word;background-color:#fff;background-clip:border-box;border:1px solid rgba(0,0,0,.125);border-radius:.25rem}.card>hr{margin-right:0;margin-left:0}.card>.list-group{border-top:inherit;border-bottom:inherit}.card>.list-group:first-child{border-top-width:0;border-top-left-radius:calc(.25rem - 1px);border-top-right-radius:calc(.25rem - 1px)}.card>.list-group:last-child{border-bottom-width:0;border-bottom-right-radius:calc(.25rem - 1px);border-bottom-left-radius:calc(.25rem - 1px)}.card-body{-ms-flex:1 1 auto;flex:1 1 auto;min-height:1px;padding:1.25rem}.card-title{margin-bottom:.75rem}.card-subtitle{margin-top:-.375rem;margin-bottom:0}.card-text:last-child{margin-bottom:0}.card-link:hover{text-decoration:none}.card-link+.card-link{margin-left:1.25rem}.card-header{padding:.75rem 1.25rem;margin-bottom:0;background-color:rgba(0,0,0,.03);border-bottom:1px solid rgba(0,0,0,.125)}.card-header:first-child{border-radius:calc(.25rem - 1px) calc(.25rem - 1px) 0 0}.card-header+.list-group .list-group-item:first-child{border-top:0}.card-footer{padding:.75rem 1.25rem;background-color:rgba(0,0,0,.03);border-top:1px solid rgba(0,0,0,.125)}.card-footer:last-child{border-radius:0 0 calc(.25rem - 1px) calc(.25rem - 1px)}.card-header-tabs{margin-right:-.625rem;margin-bottom:-.75rem;margin-left:-.625rem;border-bottom:0}.card-header-pills{margin-right:-.625rem;margin-left:-.625rem}.card-img-overlay{position:absolute;top:0;right:0;bottom:0;left:0;padding:1.25rem}.card-img,.card-img-bottom,.card-img-top{-ms-flex-negative:0;flex-shrink:0;width:100%}.card-img,.card-img-top{border-top-left-radius:calc(.25rem - 1px);border-top-right-radius:calc(.25rem - 1px)}.card-img,.card-img-bottom{border-bottom-right-radius:calc(.25rem - 1px);border-bottom-left-radius:calc(.25rem - 1px)}.card-deck .card{margin-bottom:15px}@media (min-width:576px){.card-deck{display:-ms-flexbox;display:flex;-ms-flex-flow:row wrap;flex-flow:row wrap;margin-right:-15px;margin-left:-15px}.card-deck .card{-ms-flex:1 0 0%;flex:1 0 0%;margin-right:15px;margin-bottom:0;margin-left:15px}}.card-group>.card{margin-bottom:15px}@media (min-width:576px){.card-group{display:-ms-flexbox;display:flex;-ms-flex-flow:row wrap;flex-flow:row wrap}.card-group>.card{-ms-flex:1 0 0%;flex:1 0 0%;margin-bottom:0}.card-group>.card+.card{margin-left:0;border-left:0}.card-group>.card:not(:last-child){border-top-right-radius:0;border-bottom-right-radius:0}.card-group>.card:not(:last-child) .card-header,.card-group>.card:not(:last-child) .card-img-top{border-top-right-radius:0}.card-group>.card:not(:last-child) .card-footer,.card-group>.card:not(:last-child) .card-img-bottom{border-bottom-right-radius:0}.card-group>.card:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.card-group>.card:not(:first-child) .card-header,.card-group>.card:not(:first-child) .card-img-top{border-top-left-radius:0}.card-group>.card:not(:first-child) .card-footer,.card-group>.card:not(:first-child) .card-img-bottom{border-bottom-left-radius:0}}.card-columns .card{margin-bottom:.75rem}@media (min-width:576px){.card-columns{-webkit-column-count:3;-moz-column-count:3;column-count:3;-webkit-column-gap:1.25rem;-moz-column-gap:1.25rem;column-gap:1.25rem;orphans:1;widows:1}.card-columns .card{display:inline-block;width:100%}}.accordion>.card{overflow:hidden}.accordion>.card:not(:last-of-type){border-bottom:0;border-bottom-right-radius:0;border-bottom-left-radius:0}.accordion>.card:not(:first-of-type){border-top-left-radius:0;border-top-right-radius:0}.accordion>.card>.card-header{border-radius:0;margin-bottom:-1px}.breadcrumb{display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;padding:.75rem 1rem;margin-bottom:1rem;list-style:none;background-color:#e9ecef;border-radius:.25rem}.breadcrumb-item{display:-ms-flexbox;display:flex}.breadcrumb-item+.breadcrumb-item{padding-left:.5rem}.breadcrumb-item+.breadcrumb-item::before{display:inline-block;padding-right:.5rem;color:#6c757d;content:"/"}.breadcrumb-item+.breadcrumb-item:hover::before{text-decoration:underline}.breadcrumb-item+.breadcrumb-item:hover::before{text-decoration:none}.breadcrumb-item.active{color:#6c757d}.pagination{display:-ms-flexbox;display:flex;padding-left:0;list-style:none;border-radius:.25rem}.page-link{position:relative;display:block;padding:.5rem .75rem;margin-left:-1px;line-height:1.25;color:#007bff;background-color:#fff;border:1px solid #dee2e6}.page-link:hover{z-index:2;color:#0056b3;text-decoration:none;background-color:#e9ecef;border-color:#dee2e6}.page-link:focus{z-index:3;outline:0;box-shadow:0 0 0 .2rem rgba(0,123,255,.25)}.page-item:first-child .page-link{margin-left:0;border-top-left-radius:.25rem;border-bottom-left-radius:.25rem}.page-item:last-child .page-link{border-top-right-radius:.25rem;border-bottom-right-radius:.25rem}.page-item.active .page-link{z-index:3;color:#fff;background-color:#007bff;border-color:#007bff}.page-item.disabled .page-link{color:#6c757d;pointer-events:none;cursor:auto;background-color:#fff;border-color:#dee2e6}.pagination-lg .page-link{padding:.75rem 1.5rem;font-size:1.25rem;line-height:1.5}.pagination-lg .page-item:first-child .page-link{border-top-left-radius:.3rem;border-bottom-left-radius:.3rem}.pagination-lg .page-item:last-child .page-link{border-top-right-radius:.3rem;border-bottom-right-radius:.3rem}.pagination-sm .page-link{padding:.25rem .5rem;font-size:.875rem;line-height:1.5}.pagination-sm .page-item:first-child .page-link{border-top-left-radius:.2rem;border-bottom-left-radius:.2rem}.pagination-sm .page-item:last-child .page-link{border-top-right-radius:.2rem;border-bottom-right-radius:.2rem}.badge{display:inline-block;padding:.25em .4em;font-size:75%;font-weight:700;line-height:1;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25rem;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.badge{transition:none}}a.badge:focus,a.badge:hover{text-decoration:none}.badge:empty{display:none}.btn .badge{position:relative;top:-1px}.badge-pill{padding-right:.6em;padding-left:.6em;border-radius:10rem}.badge-primary{color:#fff;background-color:#007bff}a.badge-primary:focus,a.badge-primary:hover{color:#fff;background-color:#0062cc}a.badge-primary.focus,a.badge-primary:focus{outline:0;box-shadow:0 0 0 .2rem rgba(0,123,255,.5)}.badge-secondary{color:#fff;background-color:#6c757d}a.badge-secondary:focus,a.badge-secondary:hover{color:#fff;background-color:#545b62}a.badge-secondary.focus,a.badge-secondary:focus{outline:0;box-shadow:0 0 0 .2rem rgba(108,117,125,.5)}.badge-success{color:#fff;background-color:#28a745}a.badge-success:focus,a.badge-success:hover{color:#fff;background-color:#1e7e34}a.badge-success.focus,a.badge-success:focus{outline:0;box-shadow:0 0 0 .2rem rgba(40,167,69,.5)}.badge-info{color:#fff;background-color:#17a2b8}a.badge-info:focus,a.badge-info:hover{color:#fff;background-color:#117a8b}a.badge-info.focus,a.badge-info:focus{outline:0;box-shadow:0 0 0 .2rem rgba(23,162,184,.5)}.badge-warning{color:#212529;background-color:#ffc107}a.badge-warning:focus,a.badge-warning:hover{color:#212529;background-color:#d39e00}a.badge-warning.focus,a.badge-warning:focus{outline:0;box-shadow:0 0 0 .2rem rgba(255,193,7,.5)}.badge-danger{color:#fff;background-color:#dc3545}a.badge-danger:focus,a.badge-danger:hover{color:#fff;background-color:#bd2130}a.badge-danger.focus,a.badge-danger:focus{outline:0;box-shadow:0 0 0 .2rem rgba(220,53,69,.5)}.badge-light{color:#212529;background-color:#f8f9fa}a.badge-light:focus,a.badge-light:hover{color:#212529;background-color:#dae0e5}a.badge-light.focus,a.badge-light:focus{outline:0;box-shadow:0 0 0 .2rem rgba(248,249,250,.5)}.badge-dark{color:#fff;background-color:#343a40}a.badge-dark:focus,a.badge-dark:hover{color:#fff;background-color:#1d2124}a.badge-dark.focus,a.badge-dark:focus{outline:0;box-shadow:0 0 0 .2rem rgba(52,58,64,.5)}.jumbotron{padding:2rem 1rem;margin-bottom:2rem;background-color:#e9ecef;border-radius:.3rem}@media (min-width:576px){.jumbotron{padding:4rem 2rem}}.jumbotron-fluid{padding-right:0;padding-left:0;border-radius:0}.alert{position:relative;padding:.75rem 1.25rem;margin-bottom:1rem;border:1px solid transparent;border-radius:.25rem}.alert-heading{color:inherit}.alert-link{font-weight:700}.alert-dismissible{padding-right:4rem}.alert-dismissible .close{position:absolute;top:0;right:0;padding:.75rem 1.25rem;color:inherit}.alert-primary{color:#004085;background-color:#cce5ff;border-color:#b8daff}.alert-primary hr{border-top-color:#9fcdff}.alert-primary .alert-link{color:#002752}.alert-secondary{color:#383d41;background-color:#e2e3e5;border-color:#d6d8db}.alert-secondary hr{border-top-color:#c8cbcf}.alert-secondary .alert-link{color:#202326}.alert-success{color:#155724;background-color:#d4edda;border-color:#c3e6cb}.alert-success hr{border-top-color:#b1dfbb}.alert-success .alert-link{color:#0b2e13}.alert-info{color:#0c5460;background-color:#d1ecf1;border-color:#bee5eb}.alert-info hr{border-top-color:#abdde5}.alert-info .alert-link{color:#062c33}.alert-warning{color:#856404;background-color:#fff3cd;border-color:#ffeeba}.alert-warning hr{border-top-color:#ffe8a1}.alert-warning .alert-link{color:#533f03}.alert-danger{color:#721c24;background-color:#f8d7da;border-color:#f5c6cb}.alert-danger hr{border-top-color:#f1b0b7}.alert-danger .alert-link{color:#491217}.alert-light{color:#818182;background-color:#fefefe;border-color:#fdfdfe}.alert-light hr{border-top-color:#ececf6}.alert-light .alert-link{color:#686868}.alert-dark{color:#1b1e21;background-color:#d6d8d9;border-color:#c6c8ca}.alert-dark hr{border-top-color:#b9bbbe}.alert-dark .alert-link{color:#040505}@-webkit-keyframes progress-bar-stripes{from{background-position:1rem 0}to{background-position:0 0}}@keyframes progress-bar-stripes{from{background-position:1rem 0}to{background-position:0 0}}.progress{display:-ms-flexbox;display:flex;height:1rem;overflow:hidden;line-height:0;font-size:.75rem;background-color:#e9ecef;border-radius:.25rem}.progress-bar{display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;-ms-flex-pack:center;justify-content:center;overflow:hidden;color:#fff;text-align:center;white-space:nowrap;background-color:#007bff;transition:width .6s ease}@media (prefers-reduced-motion:reduce){.progress-bar{transition:none}}.progress-bar-striped{background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-size:1rem 1rem}.progress-bar-animated{-webkit-animation:progress-bar-stripes 1s linear infinite;animation:progress-bar-stripes 1s linear infinite}@media (prefers-reduced-motion:reduce){.progress-bar-animated{-webkit-animation:none;animation:none}}.media{display:-ms-flexbox;display:flex;-ms-flex-align:start;align-items:flex-start}.media-body{-ms-flex:1;flex:1}.list-group{display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;padding-left:0;margin-bottom:0;border-radius:.25rem}.list-group-item-action{width:100%;color:#495057;text-align:inherit}.list-group-item-action:focus,.list-group-item-action:hover{z-index:1;color:#495057;text-decoration:none;background-color:#f8f9fa}.list-group-item-action:active{color:#212529;background-color:#e9ecef}.list-group-item{position:relative;display:block;padding:.75rem 1.25rem;background-color:#fff;border:1px solid rgba(0,0,0,.125)}.list-group-item:first-child{border-top-left-radius:inherit;border-top-right-radius:inherit}.list-group-item:last-child{border-bottom-right-radius:inherit;border-bottom-left-radius:inherit}.list-group-item.disabled,.list-group-item:disabled{color:#6c757d;pointer-events:none;background-color:#fff}.list-group-item.active{z-index:2;color:#fff;background-color:#007bff;border-color:#007bff}.list-group-item+.list-group-item{border-top-width:0}.list-group-item+.list-group-item.active{margin-top:-1px;border-top-width:1px}.list-group-horizontal{-ms-flex-direction:row;flex-direction:row}.list-group-horizontal>.list-group-item:first-child{border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal>.list-group-item:last-child{border-top-right-radius:.25rem;border-bottom-left-radius:0}.list-group-horizontal>.list-group-item.active{margin-top:0}.list-group-horizontal>.list-group-item+.list-group-item{border-top-width:1px;border-left-width:0}.list-group-horizontal>.list-group-item+.list-group-item.active{margin-left:-1px;border-left-width:1px}@media (min-width:576px){.list-group-horizontal-sm{-ms-flex-direction:row;flex-direction:row}.list-group-horizontal-sm>.list-group-item:first-child{border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal-sm>.list-group-item:last-child{border-top-right-radius:.25rem;border-bottom-left-radius:0}.list-group-horizontal-sm>.list-group-item.active{margin-top:0}.list-group-horizontal-sm>.list-group-item+.list-group-item{border-top-width:1px;border-left-width:0}.list-group-horizontal-sm>.list-group-item+.list-group-item.active{margin-left:-1px;border-left-width:1px}}@media (min-width:768px){.list-group-horizontal-md{-ms-flex-direction:row;flex-direction:row}.list-group-horizontal-md>.list-group-item:first-child{border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal-md>.list-group-item:last-child{border-top-right-radius:.25rem;border-bottom-left-radius:0}.list-group-horizontal-md>.list-group-item.active{margin-top:0}.list-group-horizontal-md>.list-group-item+.list-group-item{border-top-width:1px;border-left-width:0}.list-group-horizontal-md>.list-group-item+.list-group-item.active{margin-left:-1px;border-left-width:1px}}@media (min-width:992px){.list-group-horizontal-lg{-ms-flex-direction:row;flex-direction:row}.list-group-horizontal-lg>.list-group-item:first-child{border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal-lg>.list-group-item:last-child{border-top-right-radius:.25rem;border-bottom-left-radius:0}.list-group-horizontal-lg>.list-group-item.active{margin-top:0}.list-group-horizontal-lg>.list-group-item+.list-group-item{border-top-width:1px;border-left-width:0}.list-group-horizontal-lg>.list-group-item+.list-group-item.active{margin-left:-1px;border-left-width:1px}}@media (min-width:1200px){.list-group-horizontal-xl{-ms-flex-direction:row;flex-direction:row}.list-group-horizontal-xl>.list-group-item:first-child{border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal-xl>.list-group-item:last-child{border-top-right-radius:.25rem;border-bottom-left-radius:0}.list-group-horizontal-xl>.list-group-item.active{margin-top:0}.list-group-horizontal-xl>.list-group-item+.list-group-item{border-top-width:1px;border-left-width:0}.list-group-horizontal-xl>.list-group-item+.list-group-item.active{margin-left:-1px;border-left-width:1px}}.list-group-flush{border-radius:0}.list-group-flush>.list-group-item{border-width:0 0 1px}.list-group-flush>.list-group-item:last-child{border-bottom-width:0}.list-group-item-primary{color:#004085;background-color:#b8daff}.list-group-item-primary.list-group-item-action:focus,.list-group-item-primary.list-group-item-action:hover{color:#004085;background-color:#9fcdff}.list-group-item-primary.list-group-item-action.active{color:#fff;background-color:#004085;border-color:#004085}.list-group-item-secondary{color:#383d41;background-color:#d6d8db}.list-group-item-secondary.list-group-item-action:focus,.list-group-item-secondary.list-group-item-action:hover{color:#383d41;background-color:#c8cbcf}.list-group-item-secondary.list-group-item-action.active{color:#fff;background-color:#383d41;border-color:#383d41}.list-group-item-success{color:#155724;background-color:#c3e6cb}.list-group-item-success.list-group-item-action:focus,.list-group-item-success.list-group-item-action:hover{color:#155724;background-color:#b1dfbb}.list-group-item-success.list-group-item-action.active{color:#fff;background-color:#155724;border-color:#155724}.list-group-item-info{color:#0c5460;background-color:#bee5eb}.list-group-item-info.list-group-item-action:focus,.list-group-item-info.list-group-item-action:hover{color:#0c5460;background-color:#abdde5}.list-group-item-info.list-group-item-action.active{color:#fff;background-color:#0c5460;border-color:#0c5460}.list-group-item-warning{color:#856404;background-color:#ffeeba}.list-group-item-warning.list-group-item-action:focus,.list-group-item-warning.list-group-item-action:hover{color:#856404;background-color:#ffe8a1}.list-group-item-warning.list-group-item-action.active{color:#fff;background-color:#856404;border-color:#856404}.list-group-item-danger{color:#721c24;background-color:#f5c6cb}.list-group-item-danger.list-group-item-action:focus,.list-group-item-danger.list-group-item-action:hover{color:#721c24;background-color:#f1b0b7}.list-group-item-danger.list-group-item-action.active{color:#fff;background-color:#721c24;border-color:#721c24}.list-group-item-light{color:#818182;background-color:#fdfdfe}.list-group-item-light.list-group-item-action:focus,.list-group-item-light.list-group-item-action:hover{color:#818182;background-color:#ececf6}.list-group-item-light.list-group-item-action.active{color:#fff;background-color:#818182;border-color:#818182}.list-group-item-dark{color:#1b1e21;background-color:#c6c8ca}.list-group-item-dark.list-group-item-action:focus,.list-group-item-dark.list-group-item-action:hover{color:#1b1e21;background-color:#b9bbbe}.list-group-item-dark.list-group-item-action.active{color:#fff;background-color:#1b1e21;border-color:#1b1e21}.close{float:right;font-size:1.5rem;font-weight:700;line-height:1;color:#000;text-shadow:0 1px 0 #fff;opacity:.5}.close:hover{color:#000;text-decoration:none}.close:not(:disabled):not(.disabled):focus,.close:not(:disabled):not(.disabled):hover{opacity:.75}button.close{padding:0;background-color:transparent;border:0}a.close.disabled{pointer-events:none}.toast{max-width:350px;overflow:hidden;font-size:.875rem;background-color:rgba(255,255,255,.85);background-clip:padding-box;border:1px solid rgba(0,0,0,.1);box-shadow:0 .25rem .75rem rgba(0,0,0,.1);-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);opacity:0;border-radius:.25rem}.toast:not(:last-child){margin-bottom:.75rem}.toast.showing{opacity:1}.toast.show{display:block;opacity:1}.toast.hide{display:none}.toast-header{display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;padding:.25rem .75rem;color:#6c757d;background-color:rgba(255,255,255,.85);background-clip:padding-box;border-bottom:1px solid rgba(0,0,0,.05)}.toast-body{padding:.75rem}.modal-open{overflow:hidden}.modal-open .modal{overflow-x:hidden;overflow-y:auto}.modal{position:fixed;top:0;left:0;z-index:1050;display:none;width:100%;height:100%;overflow:hidden;outline:0}.modal-dialog{position:relative;width:auto;margin:.5rem;pointer-events:none}.modal.fade .modal-dialog{transition:-webkit-transform .3s ease-out;transition:transform .3s ease-out;transition:transform .3s ease-out,-webkit-transform .3s ease-out;-webkit-transform:translate(0,-50px);transform:translate(0,-50px)}@media (prefers-reduced-motion:reduce){.modal.fade .modal-dialog{transition:none}}.modal.show .modal-dialog{-webkit-transform:none;transform:none}.modal.modal-static .modal-dialog{-webkit-transform:scale(1.02);transform:scale(1.02)}.modal-dialog-scrollable{display:-ms-flexbox;display:flex;max-height:calc(100% - 1rem)}.modal-dialog-scrollable .modal-content{max-height:calc(100vh - 1rem);overflow:hidden}.modal-dialog-scrollable .modal-footer,.modal-dialog-scrollable .modal-header{-ms-flex-negative:0;flex-shrink:0}.modal-dialog-scrollable .modal-body{overflow-y:auto}.modal-dialog-centered{display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;min-height:calc(100% - 1rem)}.modal-dialog-centered::before{display:block;height:calc(100vh - 1rem);height:-webkit-min-content;height:-moz-min-content;height:min-content;content:""}.modal-dialog-centered.modal-dialog-scrollable{-ms-flex-direction:column;flex-direction:column;-ms-flex-pack:center;justify-content:center;height:100%}.modal-dialog-centered.modal-dialog-scrollable .modal-content{max-height:none}.modal-dialog-centered.modal-dialog-scrollable::before{content:none}.modal-content{position:relative;display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;width:100%;pointer-events:auto;background-color:#fff;background-clip:padding-box;border:1px solid rgba(0,0,0,.2);border-radius:.3rem;outline:0}.modal-backdrop{position:fixed;top:0;left:0;z-index:1040;width:100vw;height:100vh;background-color:#000}.modal-backdrop.fade{opacity:0}.modal-backdrop.show{opacity:.5}.modal-header{display:-ms-flexbox;display:flex;-ms-flex-align:start;align-items:flex-start;-ms-flex-pack:justify;justify-content:space-between;padding:1rem 1rem;border-bottom:1px solid #dee2e6;border-top-left-radius:calc(.3rem - 1px);border-top-right-radius:calc(.3rem - 1px)}.modal-header .close{padding:1rem 1rem;margin:-1rem -1rem -1rem auto}.modal-title{margin-bottom:0;line-height:1.5}.modal-body{position:relative;-ms-flex:1 1 auto;flex:1 1 auto;padding:1rem}.modal-footer{display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;-ms-flex-align:center;align-items:center;-ms-flex-pack:end;justify-content:flex-end;padding:.75rem;border-top:1px solid #dee2e6;border-bottom-right-radius:calc(.3rem - 1px);border-bottom-left-radius:calc(.3rem - 1px)}.modal-footer>*{margin:.25rem}.modal-scrollbar-measure{position:absolute;top:-9999px;width:50px;height:50px;overflow:scroll}@media (min-width:576px){.modal-dialog{max-width:500px;margin:1.75rem auto}.modal-dialog-scrollable{max-height:calc(100% - 3.5rem)}.modal-dialog-scrollable .modal-content{max-height:calc(100vh - 3.5rem)}.modal-dialog-centered{min-height:calc(100% - 3.5rem)}.modal-dialog-centered::before{height:calc(100vh - 3.5rem);height:-webkit-min-content;height:-moz-min-content;height:min-content}.modal-sm{max-width:300px}}@media (min-width:992px){.modal-lg,.modal-xl{max-width:800px}}@media (min-width:1200px){.modal-xl{max-width:1140px}}.tooltip{position:absolute;z-index:1070;display:block;margin:0;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";font-style:normal;font-weight:400;line-height:1.5;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;word-spacing:normal;white-space:normal;line-break:auto;font-size:.875rem;word-wrap:break-word;opacity:0}.tooltip.show{opacity:.9}.tooltip .arrow{position:absolute;display:block;width:.8rem;height:.4rem}.tooltip .arrow::before{position:absolute;content:"";border-color:transparent;border-style:solid}.bs-tooltip-auto[x-placement^=top],.bs-tooltip-top{padding:.4rem 0}.bs-tooltip-auto[x-placement^=top] .arrow,.bs-tooltip-top .arrow{bottom:0}.bs-tooltip-auto[x-placement^=top] .arrow::before,.bs-tooltip-top .arrow::before{top:0;border-width:.4rem .4rem 0;border-top-color:#000}.bs-tooltip-auto[x-placement^=right],.bs-tooltip-right{padding:0 .4rem}.bs-tooltip-auto[x-placement^=right] .arrow,.bs-tooltip-right .arrow{left:0;width:.4rem;height:.8rem}.bs-tooltip-auto[x-placement^=right] .arrow::before,.bs-tooltip-right .arrow::before{right:0;border-width:.4rem .4rem .4rem 0;border-right-color:#000}.bs-tooltip-auto[x-placement^=bottom],.bs-tooltip-bottom{padding:.4rem 0}.bs-tooltip-auto[x-placement^=bottom] .arrow,.bs-tooltip-bottom .arrow{top:0}.bs-tooltip-auto[x-placement^=bottom] .arrow::before,.bs-tooltip-bottom .arrow::before{bottom:0;border-width:0 .4rem .4rem;border-bottom-color:#000}.bs-tooltip-auto[x-placement^=left],.bs-tooltip-left{padding:0 .4rem}.bs-tooltip-auto[x-placement^=left] .arrow,.bs-tooltip-left .arrow{right:0;width:.4rem;height:.8rem}.bs-tooltip-auto[x-placement^=left] .arrow::before,.bs-tooltip-left .arrow::before{left:0;border-width:.4rem 0 .4rem .4rem;border-left-color:#000}.tooltip-inner{max-width:200px;padding:.25rem .5rem;color:#fff;text-align:center;background-color:#000;border-radius:.25rem}.popover{position:absolute;top:0;left:0;z-index:1060;display:block;max-width:276px;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";font-style:normal;font-weight:400;line-height:1.5;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;word-spacing:normal;white-space:normal;line-break:auto;font-size:.875rem;word-wrap:break-word;background-color:#fff;background-clip:padding-box;border:1px solid rgba(0,0,0,.2);border-radius:.3rem}.popover .arrow{position:absolute;display:block;width:1rem;height:.5rem;margin:0 .3rem}.popover .arrow::after,.popover .arrow::before{position:absolute;display:block;content:"";border-color:transparent;border-style:solid}.bs-popover-auto[x-placement^=top],.bs-popover-top{margin-bottom:.5rem}.bs-popover-auto[x-placement^=top]>.arrow,.bs-popover-top>.arrow{bottom:calc(-.5rem - 1px)}.bs-popover-auto[x-placement^=top]>.arrow::before,.bs-popover-top>.arrow::before{bottom:0;border-width:.5rem .5rem 0;border-top-color:rgba(0,0,0,.25)}.bs-popover-auto[x-placement^=top]>.arrow::after,.bs-popover-top>.arrow::after{bottom:1px;border-width:.5rem .5rem 0;border-top-color:#fff}.bs-popover-auto[x-placement^=right],.bs-popover-right{margin-left:.5rem}.bs-popover-auto[x-placement^=right]>.arrow,.bs-popover-right>.arrow{left:calc(-.5rem - 1px);width:.5rem;height:1rem;margin:.3rem 0}.bs-popover-auto[x-placement^=right]>.arrow::before,.bs-popover-right>.arrow::before{left:0;border-width:.5rem .5rem .5rem 0;border-right-color:rgba(0,0,0,.25)}.bs-popover-auto[x-placement^=right]>.arrow::after,.bs-popover-right>.arrow::after{left:1px;border-width:.5rem .5rem .5rem 0;border-right-color:#fff}.bs-popover-auto[x-placement^=bottom],.bs-popover-bottom{margin-top:.5rem}.bs-popover-auto[x-placement^=bottom]>.arrow,.bs-popover-bottom>.arrow{top:calc(-.5rem - 1px)}.bs-popover-auto[x-placement^=bottom]>.arrow::before,.bs-popover-bottom>.arrow::before{top:0;border-width:0 .5rem .5rem .5rem;border-bottom-color:rgba(0,0,0,.25)}.bs-popover-auto[x-placement^=bottom]>.arrow::after,.bs-popover-bottom>.arrow::after{top:1px;border-width:0 .5rem .5rem .5rem;border-bottom-color:#fff}.bs-popover-auto[x-placement^=bottom] .popover-header::before,.bs-popover-bottom .popover-header::before{position:absolute;top:0;left:50%;display:block;width:1rem;margin-left:-.5rem;content:"";border-bottom:1px solid #f7f7f7}.bs-popover-auto[x-placement^=left],.bs-popover-left{margin-right:.5rem}.bs-popover-auto[x-placement^=left]>.arrow,.bs-popover-left>.arrow{right:calc(-.5rem - 1px);width:.5rem;height:1rem;margin:.3rem 0}.bs-popover-auto[x-placement^=left]>.arrow::before,.bs-popover-left>.arrow::before{right:0;border-width:.5rem 0 .5rem .5rem;border-left-color:rgba(0,0,0,.25)}.bs-popover-auto[x-placement^=left]>.arrow::after,.bs-popover-left>.arrow::after{right:1px;border-width:.5rem 0 .5rem .5rem;border-left-color:#fff}.popover-header{padding:.5rem .75rem;margin-bottom:0;font-size:1rem;background-color:#f7f7f7;border-bottom:1px solid #ebebeb;border-top-left-radius:calc(.3rem - 1px);border-top-right-radius:calc(.3rem - 1px)}.popover-header:empty{display:none}.popover-body{padding:.5rem .75rem;color:#212529}.carousel{position:relative}.carousel.pointer-event{-ms-touch-action:pan-y;touch-action:pan-y}.carousel-inner{position:relative;width:100%;overflow:hidden}.carousel-inner::after{display:block;clear:both;content:""}.carousel-item{position:relative;display:none;float:left;width:100%;margin-right:-100%;-webkit-backface-visibility:hidden;backface-visibility:hidden;transition:-webkit-transform .6s ease-in-out;transition:transform .6s ease-in-out;transition:transform .6s ease-in-out,-webkit-transform .6s ease-in-out}@media (prefers-reduced-motion:reduce){.carousel-item{transition:none}}.carousel-item-next,.carousel-item-prev,.carousel-item.active{display:block}.active.carousel-item-right,.carousel-item-next:not(.carousel-item-left){-webkit-transform:translateX(100%);transform:translateX(100%)}.active.carousel-item-left,.carousel-item-prev:not(.carousel-item-right){-webkit-transform:translateX(-100%);transform:translateX(-100%)}.carousel-fade .carousel-item{opacity:0;transition-property:opacity;-webkit-transform:none;transform:none}.carousel-fade .carousel-item-next.carousel-item-left,.carousel-fade .carousel-item-prev.carousel-item-right,.carousel-fade .carousel-item.active{z-index:1;opacity:1}.carousel-fade .active.carousel-item-left,.carousel-fade .active.carousel-item-right{z-index:0;opacity:0;transition:opacity 0s .6s}@media (prefers-reduced-motion:reduce){.carousel-fade .active.carousel-item-left,.carousel-fade .active.carousel-item-right{transition:none}}.carousel-control-next,.carousel-control-prev{position:absolute;top:0;bottom:0;z-index:1;display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;-ms-flex-pack:center;justify-content:center;width:15%;color:#fff;text-align:center;opacity:.5;transition:opacity .15s ease}@media (prefers-reduced-motion:reduce){.carousel-control-next,.carousel-control-prev{transition:none}}.carousel-control-next:focus,.carousel-control-next:hover,.carousel-control-prev:focus,.carousel-control-prev:hover{color:#fff;text-decoration:none;outline:0;opacity:.9}.carousel-control-prev{left:0}.carousel-control-next{right:0}.carousel-control-next-icon,.carousel-control-prev-icon{display:inline-block;width:20px;height:20px;background:no-repeat 50%/100% 100%}.carousel-control-prev-icon{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' width='8' height='8' viewBox='0 0 8 8'%3e%3cpath d='M5.25 0l-4 4 4 4 1.5-1.5L4.25 4l2.5-2.5L5.25 0z'/%3e%3c/svg%3e")}.carousel-control-next-icon{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' width='8' height='8' viewBox='0 0 8 8'%3e%3cpath d='M2.75 0l-1.5 1.5L3.75 4l-2.5 2.5L2.75 8l4-4-4-4z'/%3e%3c/svg%3e")}.carousel-indicators{position:absolute;right:0;bottom:0;left:0;z-index:15;display:-ms-flexbox;display:flex;-ms-flex-pack:center;justify-content:center;padding-left:0;margin-right:15%;margin-left:15%;list-style:none}.carousel-indicators li{box-sizing:content-box;-ms-flex:0 1 auto;flex:0 1 auto;width:30px;height:3px;margin-right:3px;margin-left:3px;text-indent:-999px;cursor:pointer;background-color:#fff;background-clip:padding-box;border-top:10px solid transparent;border-bottom:10px solid transparent;opacity:.5;transition:opacity .6s ease}@media (prefers-reduced-motion:reduce){.carousel-indicators li{transition:none}}.carousel-indicators .active{opacity:1}.carousel-caption{position:absolute;right:15%;bottom:20px;left:15%;z-index:10;padding-top:20px;padding-bottom:20px;color:#fff;text-align:center}@-webkit-keyframes spinner-border{to{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}@keyframes spinner-border{to{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}.spinner-border{display:inline-block;width:2rem;height:2rem;vertical-align:text-bottom;border:.25em solid currentColor;border-right-color:transparent;border-radius:50%;-webkit-animation:spinner-border .75s linear infinite;animation:spinner-border .75s linear infinite}.spinner-border-sm{width:1rem;height:1rem;border-width:.2em}@-webkit-keyframes spinner-grow{0%{-webkit-transform:scale(0);transform:scale(0)}50%{opacity:1;-webkit-transform:none;transform:none}}@keyframes spinner-grow{0%{-webkit-transform:scale(0);transform:scale(0)}50%{opacity:1;-webkit-transform:none;transform:none}}.spinner-grow{display:inline-block;width:2rem;height:2rem;vertical-align:text-bottom;background-color:currentColor;border-radius:50%;opacity:0;-webkit-animation:spinner-grow .75s linear infinite;animation:spinner-grow .75s linear infinite}.spinner-grow-sm{width:1rem;height:1rem}.align-baseline{vertical-align:baseline!important}.align-top{vertical-align:top!important}.align-middle{vertical-align:middle!important}.align-bottom{vertical-align:bottom!important}.align-text-bottom{vertical-align:text-bottom!important}.align-text-top{vertical-align:text-top!important}.bg-primary{background-color:#007bff!important}a.bg-primary:focus,a.bg-primary:hover,button.bg-primary:focus,button.bg-primary:hover{background-color:#0062cc!important}.bg-secondary{background-color:#6c757d!important}a.bg-secondary:focus,a.bg-secondary:hover,button.bg-secondary:focus,button.bg-secondary:hover{background-color:#545b62!important}.bg-success{background-color:#28a745!important}a.bg-success:focus,a.bg-success:hover,button.bg-success:focus,button.bg-success:hover{background-color:#1e7e34!important}.bg-info{background-color:#17a2b8!important}a.bg-info:focus,a.bg-info:hover,button.bg-info:focus,button.bg-info:hover{background-color:#117a8b!important}.bg-warning{background-color:#ffc107!important}a.bg-warning:focus,a.bg-warning:hover,button.bg-warning:focus,button.bg-warning:hover{background-color:#d39e00!important}.bg-danger{background-color:#dc3545!important}a.bg-danger:focus,a.bg-danger:hover,button.bg-danger:focus,button.bg-danger:hover{background-color:#bd2130!important}.bg-light{background-color:#f8f9fa!important}a.bg-light:focus,a.bg-light:hover,button.bg-light:focus,button.bg-light:hover{background-color:#dae0e5!important}.bg-dark{background-color:#343a40!important}a.bg-dark:focus,a.bg-dark:hover,button.bg-dark:focus,button.bg-dark:hover{background-color:#1d2124!important}.bg-white{background-color:#fff!important}.bg-transparent{background-color:transparent!important}.border{border:1px solid #dee2e6!important}.border-top{border-top:1px solid #dee2e6!important}.border-right{border-right:1px solid #dee2e6!important}.border-bottom{border-bottom:1px solid #dee2e6!important}.border-left{border-left:1px solid #dee2e6!important}.border-0{border:0!important}.border-top-0{border-top:0!important}.border-right-0{border-right:0!important}.border-bottom-0{border-bottom:0!important}.border-left-0{border-left:0!important}.border-primary{border-color:#007bff!important}.border-secondary{border-color:#6c757d!important}.border-success{border-color:#28a745!important}.border-info{border-color:#17a2b8!important}.border-warning{border-color:#ffc107!important}.border-danger{border-color:#dc3545!important}.border-light{border-color:#f8f9fa!important}.border-dark{border-color:#343a40!important}.border-white{border-color:#fff!important}.rounded-sm{border-radius:.2rem!important}.rounded{border-radius:.25rem!important}.rounded-top{border-top-left-radius:.25rem!important;border-top-right-radius:.25rem!important}.rounded-right{border-top-right-radius:.25rem!important;border-bottom-right-radius:.25rem!important}.rounded-bottom{border-bottom-right-radius:.25rem!important;border-bottom-left-radius:.25rem!important}.rounded-left{border-top-left-radius:.25rem!important;border-bottom-left-radius:.25rem!important}.rounded-lg{border-radius:.3rem!important}.rounded-circle{border-radius:50%!important}.rounded-pill{border-radius:50rem!important}.rounded-0{border-radius:0!important}.clearfix::after{display:block;clear:both;content:""}.d-none{display:none!important}.d-inline{display:inline!important}.d-inline-block{display:inline-block!important}.d-block{display:block!important}.d-table{display:table!important}.d-table-row{display:table-row!important}.d-table-cell{display:table-cell!important}.d-flex{display:-ms-flexbox!important;display:flex!important}.d-inline-flex{display:-ms-inline-flexbox!important;display:inline-flex!important}@media (min-width:576px){.d-sm-none{display:none!important}.d-sm-inline{display:inline!important}.d-sm-inline-block{display:inline-block!important}.d-sm-block{display:block!important}.d-sm-table{display:table!important}.d-sm-table-row{display:table-row!important}.d-sm-table-cell{display:table-cell!important}.d-sm-flex{display:-ms-flexbox!important;display:flex!important}.d-sm-inline-flex{display:-ms-inline-flexbox!important;display:inline-flex!important}}@media (min-width:768px){.d-md-none{display:none!important}.d-md-inline{display:inline!important}.d-md-inline-block{display:inline-block!important}.d-md-block{display:block!important}.d-md-table{display:table!important}.d-md-table-row{display:table-row!important}.d-md-table-cell{display:table-cell!important}.d-md-flex{display:-ms-flexbox!important;display:flex!important}.d-md-inline-flex{display:-ms-inline-flexbox!important;display:inline-flex!important}}@media (min-width:992px){.d-lg-none{display:none!important}.d-lg-inline{display:inline!important}.d-lg-inline-block{display:inline-block!important}.d-lg-block{display:block!important}.d-lg-table{display:table!important}.d-lg-table-row{display:table-row!important}.d-lg-table-cell{display:table-cell!important}.d-lg-flex{display:-ms-flexbox!important;display:flex!important}.d-lg-inline-flex{display:-ms-inline-flexbox!important;display:inline-flex!important}}@media (min-width:1200px){.d-xl-none{display:none!important}.d-xl-inline{display:inline!important}.d-xl-inline-block{display:inline-block!important}.d-xl-block{display:block!important}.d-xl-table{display:table!important}.d-xl-table-row{display:table-row!important}.d-xl-table-cell{display:table-cell!important}.d-xl-flex{display:-ms-flexbox!important;display:flex!important}.d-xl-inline-flex{display:-ms-inline-flexbox!important;display:inline-flex!important}}@media print{.d-print-none{display:none!important}.d-print-inline{display:inline!important}.d-print-inline-block{display:inline-block!important}.d-print-block{display:block!important}.d-print-table{display:table!important}.d-print-table-row{display:table-row!important}.d-print-table-cell{display:table-cell!important}.d-print-flex{display:-ms-flexbox!important;display:flex!important}.d-print-inline-flex{display:-ms-inline-flexbox!important;display:inline-flex!important}}.embed-responsive{position:relative;display:block;width:100%;padding:0;overflow:hidden}.embed-responsive::before{display:block;content:""}.embed-responsive .embed-responsive-item,.embed-responsive embed,.embed-responsive iframe,.embed-responsive object,.embed-responsive video{position:absolute;top:0;bottom:0;left:0;width:100%;height:100%;border:0}.embed-responsive-21by9::before{padding-top:42.857143%}.embed-responsive-16by9::before{padding-top:56.25%}.embed-responsive-4by3::before{padding-top:75%}.embed-responsive-1by1::before{padding-top:100%}.flex-row{-ms-flex-direction:row!important;flex-direction:row!important}.flex-column{-ms-flex-direction:column!important;flex-direction:column!important}.flex-row-reverse{-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.flex-column-reverse{-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.flex-wrap{-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.flex-nowrap{-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.flex-wrap-reverse{-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.flex-fill{-ms-flex:1 1 auto!important;flex:1 1 auto!important}.flex-grow-0{-ms-flex-positive:0!important;flex-grow:0!important}.flex-grow-1{-ms-flex-positive:1!important;flex-grow:1!important}.flex-shrink-0{-ms-flex-negative:0!important;flex-shrink:0!important}.flex-shrink-1{-ms-flex-negative:1!important;flex-shrink:1!important}.justify-content-start{-ms-flex-pack:start!important;justify-content:flex-start!important}.justify-content-end{-ms-flex-pack:end!important;justify-content:flex-end!important}.justify-content-center{-ms-flex-pack:center!important;justify-content:center!important}.justify-content-between{-ms-flex-pack:justify!important;justify-content:space-between!important}.justify-content-around{-ms-flex-pack:distribute!important;justify-content:space-around!important}.align-items-start{-ms-flex-align:start!important;align-items:flex-start!important}.align-items-end{-ms-flex-align:end!important;align-items:flex-end!important}.align-items-center{-ms-flex-align:center!important;align-items:center!important}.align-items-baseline{-ms-flex-align:baseline!important;align-items:baseline!important}.align-items-stretch{-ms-flex-align:stretch!important;align-items:stretch!important}.align-content-start{-ms-flex-line-pack:start!important;align-content:flex-start!important}.align-content-end{-ms-flex-line-pack:end!important;align-content:flex-end!important}.align-content-center{-ms-flex-line-pack:center!important;align-content:center!important}.align-content-between{-ms-flex-line-pack:justify!important;align-content:space-between!important}.align-content-around{-ms-flex-line-pack:distribute!important;align-content:space-around!important}.align-content-stretch{-ms-flex-line-pack:stretch!important;align-content:stretch!important}.align-self-auto{-ms-flex-item-align:auto!important;align-self:auto!important}.align-self-start{-ms-flex-item-align:start!important;align-self:flex-start!important}.align-self-end{-ms-flex-item-align:end!important;align-self:flex-end!important}.align-self-center{-ms-flex-item-align:center!important;align-self:center!important}.align-self-baseline{-ms-flex-item-align:baseline!important;align-self:baseline!important}.align-self-stretch{-ms-flex-item-align:stretch!important;align-self:stretch!important}@media (min-width:576px){.flex-sm-row{-ms-flex-direction:row!important;flex-direction:row!important}.flex-sm-column{-ms-flex-direction:column!important;flex-direction:column!important}.flex-sm-row-reverse{-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.flex-sm-column-reverse{-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.flex-sm-wrap{-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.flex-sm-nowrap{-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.flex-sm-wrap-reverse{-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.flex-sm-fill{-ms-flex:1 1 auto!important;flex:1 1 auto!important}.flex-sm-grow-0{-ms-flex-positive:0!important;flex-grow:0!important}.flex-sm-grow-1{-ms-flex-positive:1!important;flex-grow:1!important}.flex-sm-shrink-0{-ms-flex-negative:0!important;flex-shrink:0!important}.flex-sm-shrink-1{-ms-flex-negative:1!important;flex-shrink:1!important}.justify-content-sm-start{-ms-flex-pack:start!important;justify-content:flex-start!important}.justify-content-sm-end{-ms-flex-pack:end!important;justify-content:flex-end!important}.justify-content-sm-center{-ms-flex-pack:center!important;justify-content:center!important}.justify-content-sm-between{-ms-flex-pack:justify!important;justify-content:space-between!important}.justify-content-sm-around{-ms-flex-pack:distribute!important;justify-content:space-around!important}.align-items-sm-start{-ms-flex-align:start!important;align-items:flex-start!important}.align-items-sm-end{-ms-flex-align:end!important;align-items:flex-end!important}.align-items-sm-center{-ms-flex-align:center!important;align-items:center!important}.align-items-sm-baseline{-ms-flex-align:baseline!important;align-items:baseline!important}.align-items-sm-stretch{-ms-flex-align:stretch!important;align-items:stretch!important}.align-content-sm-start{-ms-flex-line-pack:start!important;align-content:flex-start!important}.align-content-sm-end{-ms-flex-line-pack:end!important;align-content:flex-end!important}.align-content-sm-center{-ms-flex-line-pack:center!important;align-content:center!important}.align-content-sm-between{-ms-flex-line-pack:justify!important;align-content:space-between!important}.align-content-sm-around{-ms-flex-line-pack:distribute!important;align-content:space-around!important}.align-content-sm-stretch{-ms-flex-line-pack:stretch!important;align-content:stretch!important}.align-self-sm-auto{-ms-flex-item-align:auto!important;align-self:auto!important}.align-self-sm-start{-ms-flex-item-align:start!important;align-self:flex-start!important}.align-self-sm-end{-ms-flex-item-align:end!important;align-self:flex-end!important}.align-self-sm-center{-ms-flex-item-align:center!important;align-self:center!important}.align-self-sm-baseline{-ms-flex-item-align:baseline!important;align-self:baseline!important}.align-self-sm-stretch{-ms-flex-item-align:stretch!important;align-self:stretch!important}}@media (min-width:768px){.flex-md-row{-ms-flex-direction:row!important;flex-direction:row!important}.flex-md-column{-ms-flex-direction:column!important;flex-direction:column!important}.flex-md-row-reverse{-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.flex-md-column-reverse{-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.flex-md-wrap{-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.flex-md-nowrap{-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.flex-md-wrap-reverse{-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.flex-md-fill{-ms-flex:1 1 auto!important;flex:1 1 auto!important}.flex-md-grow-0{-ms-flex-positive:0!important;flex-grow:0!important}.flex-md-grow-1{-ms-flex-positive:1!important;flex-grow:1!important}.flex-md-shrink-0{-ms-flex-negative:0!important;flex-shrink:0!important}.flex-md-shrink-1{-ms-flex-negative:1!important;flex-shrink:1!important}.justify-content-md-start{-ms-flex-pack:start!important;justify-content:flex-start!important}.justify-content-md-end{-ms-flex-pack:end!important;justify-content:flex-end!important}.justify-content-md-center{-ms-flex-pack:center!important;justify-content:center!important}.justify-content-md-between{-ms-flex-pack:justify!important;justify-content:space-between!important}.justify-content-md-around{-ms-flex-pack:distribute!important;justify-content:space-around!important}.align-items-md-start{-ms-flex-align:start!important;align-items:flex-start!important}.align-items-md-end{-ms-flex-align:end!important;align-items:flex-end!important}.align-items-md-center{-ms-flex-align:center!important;align-items:center!important}.align-items-md-baseline{-ms-flex-align:baseline!important;align-items:baseline!important}.align-items-md-stretch{-ms-flex-align:stretch!important;align-items:stretch!important}.align-content-md-start{-ms-flex-line-pack:start!important;align-content:flex-start!important}.align-content-md-end{-ms-flex-line-pack:end!important;align-content:flex-end!important}.align-content-md-center{-ms-flex-line-pack:center!important;align-content:center!important}.align-content-md-between{-ms-flex-line-pack:justify!important;align-content:space-between!important}.align-content-md-around{-ms-flex-line-pack:distribute!important;align-content:space-around!important}.align-content-md-stretch{-ms-flex-line-pack:stretch!important;align-content:stretch!important}.align-self-md-auto{-ms-flex-item-align:auto!important;align-self:auto!important}.align-self-md-start{-ms-flex-item-align:start!important;align-self:flex-start!important}.align-self-md-end{-ms-flex-item-align:end!important;align-self:flex-end!important}.align-self-md-center{-ms-flex-item-align:center!important;align-self:center!important}.align-self-md-baseline{-ms-flex-item-align:baseline!important;align-self:baseline!important}.align-self-md-stretch{-ms-flex-item-align:stretch!important;align-self:stretch!important}}@media (min-width:992px){.flex-lg-row{-ms-flex-direction:row!important;flex-direction:row!important}.flex-lg-column{-ms-flex-direction:column!important;flex-direction:column!important}.flex-lg-row-reverse{-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.flex-lg-column-reverse{-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.flex-lg-wrap{-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.flex-lg-nowrap{-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.flex-lg-wrap-reverse{-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.flex-lg-fill{-ms-flex:1 1 auto!important;flex:1 1 auto!important}.flex-lg-grow-0{-ms-flex-positive:0!important;flex-grow:0!important}.flex-lg-grow-1{-ms-flex-positive:1!important;flex-grow:1!important}.flex-lg-shrink-0{-ms-flex-negative:0!important;flex-shrink:0!important}.flex-lg-shrink-1{-ms-flex-negative:1!important;flex-shrink:1!important}.justify-content-lg-start{-ms-flex-pack:start!important;justify-content:flex-start!important}.justify-content-lg-end{-ms-flex-pack:end!important;justify-content:flex-end!important}.justify-content-lg-center{-ms-flex-pack:center!important;justify-content:center!important}.justify-content-lg-between{-ms-flex-pack:justify!important;justify-content:space-between!important}.justify-content-lg-around{-ms-flex-pack:distribute!important;justify-content:space-around!important}.align-items-lg-start{-ms-flex-align:start!important;align-items:flex-start!important}.align-items-lg-end{-ms-flex-align:end!important;align-items:flex-end!important}.align-items-lg-center{-ms-flex-align:center!important;align-items:center!important}.align-items-lg-baseline{-ms-flex-align:baseline!important;align-items:baseline!important}.align-items-lg-stretch{-ms-flex-align:stretch!important;align-items:stretch!important}.align-content-lg-start{-ms-flex-line-pack:start!important;align-content:flex-start!important}.align-content-lg-end{-ms-flex-line-pack:end!important;align-content:flex-end!important}.align-content-lg-center{-ms-flex-line-pack:center!important;align-content:center!important}.align-content-lg-between{-ms-flex-line-pack:justify!important;align-content:space-between!important}.align-content-lg-around{-ms-flex-line-pack:distribute!important;align-content:space-around!important}.align-content-lg-stretch{-ms-flex-line-pack:stretch!important;align-content:stretch!important}.align-self-lg-auto{-ms-flex-item-align:auto!important;align-self:auto!important}.align-self-lg-start{-ms-flex-item-align:start!important;align-self:flex-start!important}.align-self-lg-end{-ms-flex-item-align:end!important;align-self:flex-end!important}.align-self-lg-center{-ms-flex-item-align:center!important;align-self:center!important}.align-self-lg-baseline{-ms-flex-item-align:baseline!important;align-self:baseline!important}.align-self-lg-stretch{-ms-flex-item-align:stretch!important;align-self:stretch!important}}@media (min-width:1200px){.flex-xl-row{-ms-flex-direction:row!important;flex-direction:row!important}.flex-xl-column{-ms-flex-direction:column!important;flex-direction:column!important}.flex-xl-row-reverse{-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.flex-xl-column-reverse{-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.flex-xl-wrap{-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.flex-xl-nowrap{-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.flex-xl-wrap-reverse{-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.flex-xl-fill{-ms-flex:1 1 auto!important;flex:1 1 auto!important}.flex-xl-grow-0{-ms-flex-positive:0!important;flex-grow:0!important}.flex-xl-grow-1{-ms-flex-positive:1!important;flex-grow:1!important}.flex-xl-shrink-0{-ms-flex-negative:0!important;flex-shrink:0!important}.flex-xl-shrink-1{-ms-flex-negative:1!important;flex-shrink:1!important}.justify-content-xl-start{-ms-flex-pack:start!important;justify-content:flex-start!important}.justify-content-xl-end{-ms-flex-pack:end!important;justify-content:flex-end!important}.justify-content-xl-center{-ms-flex-pack:center!important;justify-content:center!important}.justify-content-xl-between{-ms-flex-pack:justify!important;justify-content:space-between!important}.justify-content-xl-around{-ms-flex-pack:distribute!important;justify-content:space-around!important}.align-items-xl-start{-ms-flex-align:start!important;align-items:flex-start!important}.align-items-xl-end{-ms-flex-align:end!important;align-items:flex-end!important}.align-items-xl-center{-ms-flex-align:center!important;align-items:center!important}.align-items-xl-baseline{-ms-flex-align:baseline!important;align-items:baseline!important}.align-items-xl-stretch{-ms-flex-align:stretch!important;align-items:stretch!important}.align-content-xl-start{-ms-flex-line-pack:start!important;align-content:flex-start!important}.align-content-xl-end{-ms-flex-line-pack:end!important;align-content:flex-end!important}.align-content-xl-center{-ms-flex-line-pack:center!important;align-content:center!important}.align-content-xl-between{-ms-flex-line-pack:justify!important;align-content:space-between!important}.align-content-xl-around{-ms-flex-line-pack:distribute!important;align-content:space-around!important}.align-content-xl-stretch{-ms-flex-line-pack:stretch!important;align-content:stretch!important}.align-self-xl-auto{-ms-flex-item-align:auto!important;align-self:auto!important}.align-self-xl-start{-ms-flex-item-align:start!important;align-self:flex-start!important}.align-self-xl-end{-ms-flex-item-align:end!important;align-self:flex-end!important}.align-self-xl-center{-ms-flex-item-align:center!important;align-self:center!important}.align-self-xl-baseline{-ms-flex-item-align:baseline!important;align-self:baseline!important}.align-self-xl-stretch{-ms-flex-item-align:stretch!important;align-self:stretch!important}}.float-left{float:left!important}.float-right{float:right!important}.float-none{float:none!important}@media (min-width:576px){.float-sm-left{float:left!important}.float-sm-right{float:right!important}.float-sm-none{float:none!important}}@media (min-width:768px){.float-md-left{float:left!important}.float-md-right{float:right!important}.float-md-none{float:none!important}}@media (min-width:992px){.float-lg-left{float:left!important}.float-lg-right{float:right!important}.float-lg-none{float:none!important}}@media (min-width:1200px){.float-xl-left{float:left!important}.float-xl-right{float:right!important}.float-xl-none{float:none!important}}.user-select-all{-webkit-user-select:all!important;-moz-user-select:all!important;-ms-user-select:all!important;user-select:all!important}.user-select-auto{-webkit-user-select:auto!important;-moz-user-select:auto!important;-ms-user-select:auto!important;user-select:auto!important}.user-select-none{-webkit-user-select:none!important;-moz-user-select:none!important;-ms-user-select:none!important;user-select:none!important}.overflow-auto{overflow:auto!important}.overflow-hidden{overflow:hidden!important}.position-static{position:static!important}.position-relative{position:relative!important}.position-absolute{position:absolute!important}.position-fixed{position:fixed!important}.position-sticky{position:-webkit-sticky!important;position:sticky!important}.fixed-top{position:fixed;top:0;right:0;left:0;z-index:1030}.fixed-bottom{position:fixed;right:0;bottom:0;left:0;z-index:1030}@supports ((position:-webkit-sticky) or (position:sticky)){.sticky-top{position:-webkit-sticky;position:sticky;top:0;z-index:1020}}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;overflow:visible;clip:auto;white-space:normal}.shadow-sm{box-shadow:0 .125rem .25rem rgba(0,0,0,.075)!important}.shadow{box-shadow:0 .5rem 1rem rgba(0,0,0,.15)!important}.shadow-lg{box-shadow:0 1rem 3rem rgba(0,0,0,.175)!important}.shadow-none{box-shadow:none!important}.w-25{width:25%!important}.w-50{width:50%!important}.w-75{width:75%!important}.w-100{width:100%!important}.w-auto{width:auto!important}.h-25{height:25%!important}.h-50{height:50%!important}.h-75{height:75%!important}.h-100{height:100%!important}.h-auto{height:auto!important}.mw-100{max-width:100%!important}.mh-100{max-height:100%!important}.min-vw-100{min-width:100vw!important}.min-vh-100{min-height:100vh!important}.vw-100{width:100vw!important}.vh-100{height:100vh!important}.m-0{margin:0!important}.mt-0,.my-0{margin-top:0!important}.mr-0,.mx-0{margin-right:0!important}.mb-0,.my-0{margin-bottom:0!important}.ml-0,.mx-0{margin-left:0!important}.m-1{margin:.25rem!important}.mt-1,.my-1{margin-top:.25rem!important}.mr-1,.mx-1{margin-right:.25rem!important}.mb-1,.my-1{margin-bottom:.25rem!important}.ml-1,.mx-1{margin-left:.25rem!important}.m-2{margin:.5rem!important}.mt-2,.my-2{margin-top:.5rem!important}.mr-2,.mx-2{margin-right:.5rem!important}.mb-2,.my-2{margin-bottom:.5rem!important}.ml-2,.mx-2{margin-left:.5rem!important}.m-3{margin:1rem!important}.mt-3,.my-3{margin-top:1rem!important}.mr-3,.mx-3{margin-right:1rem!important}.mb-3,.my-3{margin-bottom:1rem!important}.ml-3,.mx-3{margin-left:1rem!important}.m-4{margin:1.5rem!important}.mt-4,.my-4{margin-top:1.5rem!important}.mr-4,.mx-4{margin-right:1.5rem!important}.mb-4,.my-4{margin-bottom:1.5rem!important}.ml-4,.mx-4{margin-left:1.5rem!important}.m-5{margin:3rem!important}.mt-5,.my-5{margin-top:3rem!important}.mr-5,.mx-5{margin-right:3rem!important}.mb-5,.my-5{margin-bottom:3rem!important}.ml-5,.mx-5{margin-left:3rem!important}.p-0{padding:0!important}.pt-0,.py-0{padding-top:0!important}.pr-0,.px-0{padding-right:0!important}.pb-0,.py-0{padding-bottom:0!important}.pl-0,.px-0{padding-left:0!important}.p-1{padding:.25rem!important}.pt-1,.py-1{padding-top:.25rem!important}.pr-1,.px-1{padding-right:.25rem!important}.pb-1,.py-1{padding-bottom:.25rem!important}.pl-1,.px-1{padding-left:.25rem!important}.p-2{padding:.5rem!important}.pt-2,.py-2{padding-top:.5rem!important}.pr-2,.px-2{padding-right:.5rem!important}.pb-2,.py-2{padding-bottom:.5rem!important}.pl-2,.px-2{padding-left:.5rem!important}.p-3{padding:1rem!important}.pt-3,.py-3{padding-top:1rem!important}.pr-3,.px-3{padding-right:1rem!important}.pb-3,.py-3{padding-bottom:1rem!important}.pl-3,.px-3{padding-left:1rem!important}.p-4{padding:1.5rem!important}.pt-4,.py-4{padding-top:1.5rem!important}.pr-4,.px-4{padding-right:1.5rem!important}.pb-4,.py-4{padding-bottom:1.5rem!important}.pl-4,.px-4{padding-left:1.5rem!important}.p-5{padding:3rem!important}.pt-5,.py-5{padding-top:3rem!important}.pr-5,.px-5{padding-right:3rem!important}.pb-5,.py-5{padding-bottom:3rem!important}.pl-5,.px-5{padding-left:3rem!important}.m-n1{margin:-.25rem!important}.mt-n1,.my-n1{margin-top:-.25rem!important}.mr-n1,.mx-n1{margin-right:-.25rem!important}.mb-n1,.my-n1{margin-bottom:-.25rem!important}.ml-n1,.mx-n1{margin-left:-.25rem!important}.m-n2{margin:-.5rem!important}.mt-n2,.my-n2{margin-top:-.5rem!important}.mr-n2,.mx-n2{margin-right:-.5rem!important}.mb-n2,.my-n2{margin-bottom:-.5rem!important}.ml-n2,.mx-n2{margin-left:-.5rem!important}.m-n3{margin:-1rem!important}.mt-n3,.my-n3{margin-top:-1rem!important}.mr-n3,.mx-n3{margin-right:-1rem!important}.mb-n3,.my-n3{margin-bottom:-1rem!important}.ml-n3,.mx-n3{margin-left:-1rem!important}.m-n4{margin:-1.5rem!important}.mt-n4,.my-n4{margin-top:-1.5rem!important}.mr-n4,.mx-n4{margin-right:-1.5rem!important}.mb-n4,.my-n4{margin-bottom:-1.5rem!important}.ml-n4,.mx-n4{margin-left:-1.5rem!important}.m-n5{margin:-3rem!important}.mt-n5,.my-n5{margin-top:-3rem!important}.mr-n5,.mx-n5{margin-right:-3rem!important}.mb-n5,.my-n5{margin-bottom:-3rem!important}.ml-n5,.mx-n5{margin-left:-3rem!important}.m-auto{margin:auto!important}.mt-auto,.my-auto{margin-top:auto!important}.mr-auto,.mx-auto{margin-right:auto!important}.mb-auto,.my-auto{margin-bottom:auto!important}.ml-auto,.mx-auto{margin-left:auto!important}@media (min-width:576px){.m-sm-0{margin:0!important}.mt-sm-0,.my-sm-0{margin-top:0!important}.mr-sm-0,.mx-sm-0{margin-right:0!important}.mb-sm-0,.my-sm-0{margin-bottom:0!important}.ml-sm-0,.mx-sm-0{margin-left:0!important}.m-sm-1{margin:.25rem!important}.mt-sm-1,.my-sm-1{margin-top:.25rem!important}.mr-sm-1,.mx-sm-1{margin-right:.25rem!important}.mb-sm-1,.my-sm-1{margin-bottom:.25rem!important}.ml-sm-1,.mx-sm-1{margin-left:.25rem!important}.m-sm-2{margin:.5rem!important}.mt-sm-2,.my-sm-2{margin-top:.5rem!important}.mr-sm-2,.mx-sm-2{margin-right:.5rem!important}.mb-sm-2,.my-sm-2{margin-bottom:.5rem!important}.ml-sm-2,.mx-sm-2{margin-left:.5rem!important}.m-sm-3{margin:1rem!important}.mt-sm-3,.my-sm-3{margin-top:1rem!important}.mr-sm-3,.mx-sm-3{margin-right:1rem!important}.mb-sm-3,.my-sm-3{margin-bottom:1rem!important}.ml-sm-3,.mx-sm-3{margin-left:1rem!important}.m-sm-4{margin:1.5rem!important}.mt-sm-4,.my-sm-4{margin-top:1.5rem!important}.mr-sm-4,.mx-sm-4{margin-right:1.5rem!important}.mb-sm-4,.my-sm-4{margin-bottom:1.5rem!important}.ml-sm-4,.mx-sm-4{margin-left:1.5rem!important}.m-sm-5{margin:3rem!important}.mt-sm-5,.my-sm-5{margin-top:3rem!important}.mr-sm-5,.mx-sm-5{margin-right:3rem!important}.mb-sm-5,.my-sm-5{margin-bottom:3rem!important}.ml-sm-5,.mx-sm-5{margin-left:3rem!important}.p-sm-0{padding:0!important}.pt-sm-0,.py-sm-0{padding-top:0!important}.pr-sm-0,.px-sm-0{padding-right:0!important}.pb-sm-0,.py-sm-0{padding-bottom:0!important}.pl-sm-0,.px-sm-0{padding-left:0!important}.p-sm-1{padding:.25rem!important}.pt-sm-1,.py-sm-1{padding-top:.25rem!important}.pr-sm-1,.px-sm-1{padding-right:.25rem!important}.pb-sm-1,.py-sm-1{padding-bottom:.25rem!important}.pl-sm-1,.px-sm-1{padding-left:.25rem!important}.p-sm-2{padding:.5rem!important}.pt-sm-2,.py-sm-2{padding-top:.5rem!important}.pr-sm-2,.px-sm-2{padding-right:.5rem!important}.pb-sm-2,.py-sm-2{padding-bottom:.5rem!important}.pl-sm-2,.px-sm-2{padding-left:.5rem!important}.p-sm-3{padding:1rem!important}.pt-sm-3,.py-sm-3{padding-top:1rem!important}.pr-sm-3,.px-sm-3{padding-right:1rem!important}.pb-sm-3,.py-sm-3{padding-bottom:1rem!important}.pl-sm-3,.px-sm-3{padding-left:1rem!important}.p-sm-4{padding:1.5rem!important}.pt-sm-4,.py-sm-4{padding-top:1.5rem!important}.pr-sm-4,.px-sm-4{padding-right:1.5rem!important}.pb-sm-4,.py-sm-4{padding-bottom:1.5rem!important}.pl-sm-4,.px-sm-4{padding-left:1.5rem!important}.p-sm-5{padding:3rem!important}.pt-sm-5,.py-sm-5{padding-top:3rem!important}.pr-sm-5,.px-sm-5{padding-right:3rem!important}.pb-sm-5,.py-sm-5{padding-bottom:3rem!important}.pl-sm-5,.px-sm-5{padding-left:3rem!important}.m-sm-n1{margin:-.25rem!important}.mt-sm-n1,.my-sm-n1{margin-top:-.25rem!important}.mr-sm-n1,.mx-sm-n1{margin-right:-.25rem!important}.mb-sm-n1,.my-sm-n1{margin-bottom:-.25rem!important}.ml-sm-n1,.mx-sm-n1{margin-left:-.25rem!important}.m-sm-n2{margin:-.5rem!important}.mt-sm-n2,.my-sm-n2{margin-top:-.5rem!important}.mr-sm-n2,.mx-sm-n2{margin-right:-.5rem!important}.mb-sm-n2,.my-sm-n2{margin-bottom:-.5rem!important}.ml-sm-n2,.mx-sm-n2{margin-left:-.5rem!important}.m-sm-n3{margin:-1rem!important}.mt-sm-n3,.my-sm-n3{margin-top:-1rem!important}.mr-sm-n3,.mx-sm-n3{margin-right:-1rem!important}.mb-sm-n3,.my-sm-n3{margin-bottom:-1rem!important}.ml-sm-n3,.mx-sm-n3{margin-left:-1rem!important}.m-sm-n4{margin:-1.5rem!important}.mt-sm-n4,.my-sm-n4{margin-top:-1.5rem!important}.mr-sm-n4,.mx-sm-n4{margin-right:-1.5rem!important}.mb-sm-n4,.my-sm-n4{margin-bottom:-1.5rem!important}.ml-sm-n4,.mx-sm-n4{margin-left:-1.5rem!important}.m-sm-n5{margin:-3rem!important}.mt-sm-n5,.my-sm-n5{margin-top:-3rem!important}.mr-sm-n5,.mx-sm-n5{margin-right:-3rem!important}.mb-sm-n5,.my-sm-n5{margin-bottom:-3rem!important}.ml-sm-n5,.mx-sm-n5{margin-left:-3rem!important}.m-sm-auto{margin:auto!important}.mt-sm-auto,.my-sm-auto{margin-top:auto!important}.mr-sm-auto,.mx-sm-auto{margin-right:auto!important}.mb-sm-auto,.my-sm-auto{margin-bottom:auto!important}.ml-sm-auto,.mx-sm-auto{margin-left:auto!important}}@media (min-width:768px){.m-md-0{margin:0!important}.mt-md-0,.my-md-0{margin-top:0!important}.mr-md-0,.mx-md-0{margin-right:0!important}.mb-md-0,.my-md-0{margin-bottom:0!important}.ml-md-0,.mx-md-0{margin-left:0!important}.m-md-1{margin:.25rem!important}.mt-md-1,.my-md-1{margin-top:.25rem!important}.mr-md-1,.mx-md-1{margin-right:.25rem!important}.mb-md-1,.my-md-1{margin-bottom:.25rem!important}.ml-md-1,.mx-md-1{margin-left:.25rem!important}.m-md-2{margin:.5rem!important}.mt-md-2,.my-md-2{margin-top:.5rem!important}.mr-md-2,.mx-md-2{margin-right:.5rem!important}.mb-md-2,.my-md-2{margin-bottom:.5rem!important}.ml-md-2,.mx-md-2{margin-left:.5rem!important}.m-md-3{margin:1rem!important}.mt-md-3,.my-md-3{margin-top:1rem!important}.mr-md-3,.mx-md-3{margin-right:1rem!important}.mb-md-3,.my-md-3{margin-bottom:1rem!important}.ml-md-3,.mx-md-3{margin-left:1rem!important}.m-md-4{margin:1.5rem!important}.mt-md-4,.my-md-4{margin-top:1.5rem!important}.mr-md-4,.mx-md-4{margin-right:1.5rem!important}.mb-md-4,.my-md-4{margin-bottom:1.5rem!important}.ml-md-4,.mx-md-4{margin-left:1.5rem!important}.m-md-5{margin:3rem!important}.mt-md-5,.my-md-5{margin-top:3rem!important}.mr-md-5,.mx-md-5{margin-right:3rem!important}.mb-md-5,.my-md-5{margin-bottom:3rem!important}.ml-md-5,.mx-md-5{margin-left:3rem!important}.p-md-0{padding:0!important}.pt-md-0,.py-md-0{padding-top:0!important}.pr-md-0,.px-md-0{padding-right:0!important}.pb-md-0,.py-md-0{padding-bottom:0!important}.pl-md-0,.px-md-0{padding-left:0!important}.p-md-1{padding:.25rem!important}.pt-md-1,.py-md-1{padding-top:.25rem!important}.pr-md-1,.px-md-1{padding-right:.25rem!important}.pb-md-1,.py-md-1{padding-bottom:.25rem!important}.pl-md-1,.px-md-1{padding-left:.25rem!important}.p-md-2{padding:.5rem!important}.pt-md-2,.py-md-2{padding-top:.5rem!important}.pr-md-2,.px-md-2{padding-right:.5rem!important}.pb-md-2,.py-md-2{padding-bottom:.5rem!important}.pl-md-2,.px-md-2{padding-left:.5rem!important}.p-md-3{padding:1rem!important}.pt-md-3,.py-md-3{padding-top:1rem!important}.pr-md-3,.px-md-3{padding-right:1rem!important}.pb-md-3,.py-md-3{padding-bottom:1rem!important}.pl-md-3,.px-md-3{padding-left:1rem!important}.p-md-4{padding:1.5rem!important}.pt-md-4,.py-md-4{padding-top:1.5rem!important}.pr-md-4,.px-md-4{padding-right:1.5rem!important}.pb-md-4,.py-md-4{padding-bottom:1.5rem!important}.pl-md-4,.px-md-4{padding-left:1.5rem!important}.p-md-5{padding:3rem!important}.pt-md-5,.py-md-5{padding-top:3rem!important}.pr-md-5,.px-md-5{padding-right:3rem!important}.pb-md-5,.py-md-5{padding-bottom:3rem!important}.pl-md-5,.px-md-5{padding-left:3rem!important}.m-md-n1{margin:-.25rem!important}.mt-md-n1,.my-md-n1{margin-top:-.25rem!important}.mr-md-n1,.mx-md-n1{margin-right:-.25rem!important}.mb-md-n1,.my-md-n1{margin-bottom:-.25rem!important}.ml-md-n1,.mx-md-n1{margin-left:-.25rem!important}.m-md-n2{margin:-.5rem!important}.mt-md-n2,.my-md-n2{margin-top:-.5rem!important}.mr-md-n2,.mx-md-n2{margin-right:-.5rem!important}.mb-md-n2,.my-md-n2{margin-bottom:-.5rem!important}.ml-md-n2,.mx-md-n2{margin-left:-.5rem!important}.m-md-n3{margin:-1rem!important}.mt-md-n3,.my-md-n3{margin-top:-1rem!important}.mr-md-n3,.mx-md-n3{margin-right:-1rem!important}.mb-md-n3,.my-md-n3{margin-bottom:-1rem!important}.ml-md-n3,.mx-md-n3{margin-left:-1rem!important}.m-md-n4{margin:-1.5rem!important}.mt-md-n4,.my-md-n4{margin-top:-1.5rem!important}.mr-md-n4,.mx-md-n4{margin-right:-1.5rem!important}.mb-md-n4,.my-md-n4{margin-bottom:-1.5rem!important}.ml-md-n4,.mx-md-n4{margin-left:-1.5rem!important}.m-md-n5{margin:-3rem!important}.mt-md-n5,.my-md-n5{margin-top:-3rem!important}.mr-md-n5,.mx-md-n5{margin-right:-3rem!important}.mb-md-n5,.my-md-n5{margin-bottom:-3rem!important}.ml-md-n5,.mx-md-n5{margin-left:-3rem!important}.m-md-auto{margin:auto!important}.mt-md-auto,.my-md-auto{margin-top:auto!important}.mr-md-auto,.mx-md-auto{margin-right:auto!important}.mb-md-auto,.my-md-auto{margin-bottom:auto!important}.ml-md-auto,.mx-md-auto{margin-left:auto!important}}@media (min-width:992px){.m-lg-0{margin:0!important}.mt-lg-0,.my-lg-0{margin-top:0!important}.mr-lg-0,.mx-lg-0{margin-right:0!important}.mb-lg-0,.my-lg-0{margin-bottom:0!important}.ml-lg-0,.mx-lg-0{margin-left:0!important}.m-lg-1{margin:.25rem!important}.mt-lg-1,.my-lg-1{margin-top:.25rem!important}.mr-lg-1,.mx-lg-1{margin-right:.25rem!important}.mb-lg-1,.my-lg-1{margin-bottom:.25rem!important}.ml-lg-1,.mx-lg-1{margin-left:.25rem!important}.m-lg-2{margin:.5rem!important}.mt-lg-2,.my-lg-2{margin-top:.5rem!important}.mr-lg-2,.mx-lg-2{margin-right:.5rem!important}.mb-lg-2,.my-lg-2{margin-bottom:.5rem!important}.ml-lg-2,.mx-lg-2{margin-left:.5rem!important}.m-lg-3{margin:1rem!important}.mt-lg-3,.my-lg-3{margin-top:1rem!important}.mr-lg-3,.mx-lg-3{margin-right:1rem!important}.mb-lg-3,.my-lg-3{margin-bottom:1rem!important}.ml-lg-3,.mx-lg-3{margin-left:1rem!important}.m-lg-4{margin:1.5rem!important}.mt-lg-4,.my-lg-4{margin-top:1.5rem!important}.mr-lg-4,.mx-lg-4{margin-right:1.5rem!important}.mb-lg-4,.my-lg-4{margin-bottom:1.5rem!important}.ml-lg-4,.mx-lg-4{margin-left:1.5rem!important}.m-lg-5{margin:3rem!important}.mt-lg-5,.my-lg-5{margin-top:3rem!important}.mr-lg-5,.mx-lg-5{margin-right:3rem!important}.mb-lg-5,.my-lg-5{margin-bottom:3rem!important}.ml-lg-5,.mx-lg-5{margin-left:3rem!important}.p-lg-0{padding:0!important}.pt-lg-0,.py-lg-0{padding-top:0!important}.pr-lg-0,.px-lg-0{padding-right:0!important}.pb-lg-0,.py-lg-0{padding-bottom:0!important}.pl-lg-0,.px-lg-0{padding-left:0!important}.p-lg-1{padding:.25rem!important}.pt-lg-1,.py-lg-1{padding-top:.25rem!important}.pr-lg-1,.px-lg-1{padding-right:.25rem!important}.pb-lg-1,.py-lg-1{padding-bottom:.25rem!important}.pl-lg-1,.px-lg-1{padding-left:.25rem!important}.p-lg-2{padding:.5rem!important}.pt-lg-2,.py-lg-2{padding-top:.5rem!important}.pr-lg-2,.px-lg-2{padding-right:.5rem!important}.pb-lg-2,.py-lg-2{padding-bottom:.5rem!important}.pl-lg-2,.px-lg-2{padding-left:.5rem!important}.p-lg-3{padding:1rem!important}.pt-lg-3,.py-lg-3{padding-top:1rem!important}.pr-lg-3,.px-lg-3{padding-right:1rem!important}.pb-lg-3,.py-lg-3{padding-bottom:1rem!important}.pl-lg-3,.px-lg-3{padding-left:1rem!important}.p-lg-4{padding:1.5rem!important}.pt-lg-4,.py-lg-4{padding-top:1.5rem!important}.pr-lg-4,.px-lg-4{padding-right:1.5rem!important}.pb-lg-4,.py-lg-4{padding-bottom:1.5rem!important}.pl-lg-4,.px-lg-4{padding-left:1.5rem!important}.p-lg-5{padding:3rem!important}.pt-lg-5,.py-lg-5{padding-top:3rem!important}.pr-lg-5,.px-lg-5{padding-right:3rem!important}.pb-lg-5,.py-lg-5{padding-bottom:3rem!important}.pl-lg-5,.px-lg-5{padding-left:3rem!important}.m-lg-n1{margin:-.25rem!important}.mt-lg-n1,.my-lg-n1{margin-top:-.25rem!important}.mr-lg-n1,.mx-lg-n1{margin-right:-.25rem!important}.mb-lg-n1,.my-lg-n1{margin-bottom:-.25rem!important}.ml-lg-n1,.mx-lg-n1{margin-left:-.25rem!important}.m-lg-n2{margin:-.5rem!important}.mt-lg-n2,.my-lg-n2{margin-top:-.5rem!important}.mr-lg-n2,.mx-lg-n2{margin-right:-.5rem!important}.mb-lg-n2,.my-lg-n2{margin-bottom:-.5rem!important}.ml-lg-n2,.mx-lg-n2{margin-left:-.5rem!important}.m-lg-n3{margin:-1rem!important}.mt-lg-n3,.my-lg-n3{margin-top:-1rem!important}.mr-lg-n3,.mx-lg-n3{margin-right:-1rem!important}.mb-lg-n3,.my-lg-n3{margin-bottom:-1rem!important}.ml-lg-n3,.mx-lg-n3{margin-left:-1rem!important}.m-lg-n4{margin:-1.5rem!important}.mt-lg-n4,.my-lg-n4{margin-top:-1.5rem!important}.mr-lg-n4,.mx-lg-n4{margin-right:-1.5rem!important}.mb-lg-n4,.my-lg-n4{margin-bottom:-1.5rem!important}.ml-lg-n4,.mx-lg-n4{margin-left:-1.5rem!important}.m-lg-n5{margin:-3rem!important}.mt-lg-n5,.my-lg-n5{margin-top:-3rem!important}.mr-lg-n5,.mx-lg-n5{margin-right:-3rem!important}.mb-lg-n5,.my-lg-n5{margin-bottom:-3rem!important}.ml-lg-n5,.mx-lg-n5{margin-left:-3rem!important}.m-lg-auto{margin:auto!important}.mt-lg-auto,.my-lg-auto{margin-top:auto!important}.mr-lg-auto,.mx-lg-auto{margin-right:auto!important}.mb-lg-auto,.my-lg-auto{margin-bottom:auto!important}.ml-lg-auto,.mx-lg-auto{margin-left:auto!important}}@media (min-width:1200px){.m-xl-0{margin:0!important}.mt-xl-0,.my-xl-0{margin-top:0!important}.mr-xl-0,.mx-xl-0{margin-right:0!important}.mb-xl-0,.my-xl-0{margin-bottom:0!important}.ml-xl-0,.mx-xl-0{margin-left:0!important}.m-xl-1{margin:.25rem!important}.mt-xl-1,.my-xl-1{margin-top:.25rem!important}.mr-xl-1,.mx-xl-1{margin-right:.25rem!important}.mb-xl-1,.my-xl-1{margin-bottom:.25rem!important}.ml-xl-1,.mx-xl-1{margin-left:.25rem!important}.m-xl-2{margin:.5rem!important}.mt-xl-2,.my-xl-2{margin-top:.5rem!important}.mr-xl-2,.mx-xl-2{margin-right:.5rem!important}.mb-xl-2,.my-xl-2{margin-bottom:.5rem!important}.ml-xl-2,.mx-xl-2{margin-left:.5rem!important}.m-xl-3{margin:1rem!important}.mt-xl-3,.my-xl-3{margin-top:1rem!important}.mr-xl-3,.mx-xl-3{margin-right:1rem!important}.mb-xl-3,.my-xl-3{margin-bottom:1rem!important}.ml-xl-3,.mx-xl-3{margin-left:1rem!important}.m-xl-4{margin:1.5rem!important}.mt-xl-4,.my-xl-4{margin-top:1.5rem!important}.mr-xl-4,.mx-xl-4{margin-right:1.5rem!important}.mb-xl-4,.my-xl-4{margin-bottom:1.5rem!important}.ml-xl-4,.mx-xl-4{margin-left:1.5rem!important}.m-xl-5{margin:3rem!important}.mt-xl-5,.my-xl-5{margin-top:3rem!important}.mr-xl-5,.mx-xl-5{margin-right:3rem!important}.mb-xl-5,.my-xl-5{margin-bottom:3rem!important}.ml-xl-5,.mx-xl-5{margin-left:3rem!important}.p-xl-0{padding:0!important}.pt-xl-0,.py-xl-0{padding-top:0!important}.pr-xl-0,.px-xl-0{padding-right:0!important}.pb-xl-0,.py-xl-0{padding-bottom:0!important}.pl-xl-0,.px-xl-0{padding-left:0!important}.p-xl-1{padding:.25rem!important}.pt-xl-1,.py-xl-1{padding-top:.25rem!important}.pr-xl-1,.px-xl-1{padding-right:.25rem!important}.pb-xl-1,.py-xl-1{padding-bottom:.25rem!important}.pl-xl-1,.px-xl-1{padding-left:.25rem!important}.p-xl-2{padding:.5rem!important}.pt-xl-2,.py-xl-2{padding-top:.5rem!important}.pr-xl-2,.px-xl-2{padding-right:.5rem!important}.pb-xl-2,.py-xl-2{padding-bottom:.5rem!important}.pl-xl-2,.px-xl-2{padding-left:.5rem!important}.p-xl-3{padding:1rem!important}.pt-xl-3,.py-xl-3{padding-top:1rem!important}.pr-xl-3,.px-xl-3{padding-right:1rem!important}.pb-xl-3,.py-xl-3{padding-bottom:1rem!important}.pl-xl-3,.px-xl-3{padding-left:1rem!important}.p-xl-4{padding:1.5rem!important}.pt-xl-4,.py-xl-4{padding-top:1.5rem!important}.pr-xl-4,.px-xl-4{padding-right:1.5rem!important}.pb-xl-4,.py-xl-4{padding-bottom:1.5rem!important}.pl-xl-4,.px-xl-4{padding-left:1.5rem!important}.p-xl-5{padding:3rem!important}.pt-xl-5,.py-xl-5{padding-top:3rem!important}.pr-xl-5,.px-xl-5{padding-right:3rem!important}.pb-xl-5,.py-xl-5{padding-bottom:3rem!important}.pl-xl-5,.px-xl-5{padding-left:3rem!important}.m-xl-n1{margin:-.25rem!important}.mt-xl-n1,.my-xl-n1{margin-top:-.25rem!important}.mr-xl-n1,.mx-xl-n1{margin-right:-.25rem!important}.mb-xl-n1,.my-xl-n1{margin-bottom:-.25rem!important}.ml-xl-n1,.mx-xl-n1{margin-left:-.25rem!important}.m-xl-n2{margin:-.5rem!important}.mt-xl-n2,.my-xl-n2{margin-top:-.5rem!important}.mr-xl-n2,.mx-xl-n2{margin-right:-.5rem!important}.mb-xl-n2,.my-xl-n2{margin-bottom:-.5rem!important}.ml-xl-n2,.mx-xl-n2{margin-left:-.5rem!important}.m-xl-n3{margin:-1rem!important}.mt-xl-n3,.my-xl-n3{margin-top:-1rem!important}.mr-xl-n3,.mx-xl-n3{margin-right:-1rem!important}.mb-xl-n3,.my-xl-n3{margin-bottom:-1rem!important}.ml-xl-n3,.mx-xl-n3{margin-left:-1rem!important}.m-xl-n4{margin:-1.5rem!important}.mt-xl-n4,.my-xl-n4{margin-top:-1.5rem!important}.mr-xl-n4,.mx-xl-n4{margin-right:-1.5rem!important}.mb-xl-n4,.my-xl-n4{margin-bottom:-1.5rem!important}.ml-xl-n4,.mx-xl-n4{margin-left:-1.5rem!important}.m-xl-n5{margin:-3rem!important}.mt-xl-n5,.my-xl-n5{margin-top:-3rem!important}.mr-xl-n5,.mx-xl-n5{margin-right:-3rem!important}.mb-xl-n5,.my-xl-n5{margin-bottom:-3rem!important}.ml-xl-n5,.mx-xl-n5{margin-left:-3rem!important}.m-xl-auto{margin:auto!important}.mt-xl-auto,.my-xl-auto{margin-top:auto!important}.mr-xl-auto,.mx-xl-auto{margin-right:auto!important}.mb-xl-auto,.my-xl-auto{margin-bottom:auto!important}.ml-xl-auto,.mx-xl-auto{margin-left:auto!important}}.stretched-link::after{position:absolute;top:0;right:0;bottom:0;left:0;z-index:1;pointer-events:auto;content:"";background-color:rgba(0,0,0,0)}.text-monospace{font-family:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace!important}.text-justify{text-align:justify!important}.text-wrap{white-space:normal!important}.text-nowrap{white-space:nowrap!important}.text-truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.text-left{text-align:left!important}.text-right{text-align:right!important}.text-center{text-align:center!important}@media (min-width:576px){.text-sm-left{text-align:left!important}.text-sm-right{text-align:right!important}.text-sm-center{text-align:center!important}}@media (min-width:768px){.text-md-left{text-align:left!important}.text-md-right{text-align:right!important}.text-md-center{text-align:center!important}}@media (min-width:992px){.text-lg-left{text-align:left!important}.text-lg-right{text-align:right!important}.text-lg-center{text-align:center!important}}@media (min-width:1200px){.text-xl-left{text-align:left!important}.text-xl-right{text-align:right!important}.text-xl-center{text-align:center!important}}.text-lowercase{text-transform:lowercase!important}.text-uppercase{text-transform:uppercase!important}.text-capitalize{text-transform:capitalize!important}.font-weight-light{font-weight:300!important}.font-weight-lighter{font-weight:lighter!important}.font-weight-normal{font-weight:400!important}.font-weight-bold{font-weight:700!important}.font-weight-bolder{font-weight:bolder!important}.font-italic{font-style:italic!important}.text-white{color:#fff!important}.text-primary{color:#007bff!important}a.text-primary:focus,a.text-primary:hover{color:#0056b3!important}.text-secondary{color:#6c757d!important}a.text-secondary:focus,a.text-secondary:hover{color:#494f54!important}.text-success{color:#28a745!important}a.text-success:focus,a.text-success:hover{color:#19692c!important}.text-info{color:#17a2b8!important}a.text-info:focus,a.text-info:hover{color:#0f6674!important}.text-warning{color:#ffc107!important}a.text-warning:focus,a.text-warning:hover{color:#ba8b00!important}.text-danger{color:#dc3545!important}a.text-danger:focus,a.text-danger:hover{color:#a71d2a!important}.text-light{color:#f8f9fa!important}a.text-light:focus,a.text-light:hover{color:#cbd3da!important}.text-dark{color:#343a40!important}a.text-dark:focus,a.text-dark:hover{color:#121416!important}.text-body{color:#212529!important}.text-muted{color:#6c757d!important}.text-black-50{color:rgba(0,0,0,.5)!important}.text-white-50{color:rgba(255,255,255,.5)!important}.text-hide{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.text-decoration-none{text-decoration:none!important}.text-break{word-wrap:break-word!important}.text-reset{color:inherit!important}.visible{visibility:visible!important}.invisible{visibility:hidden!important}@media print{*,::after,::before{text-shadow:none!important;box-shadow:none!important}a:not(.btn){text-decoration:underline}abbr[title]::after{content:" (" attr(title) ")"}pre{white-space:pre-wrap!important}blockquote,pre{border:1px solid #adb5bd;page-break-inside:avoid}thead{display:table-header-group}img,tr{page-break-inside:avoid}h2,h3,p{orphans:3;widows:3}h2,h3{page-break-after:avoid}@page{size:a3}body{min-width:992px!important}.container{min-width:992px!important}.navbar{display:none}.badge{border:1px solid #000}.table{border-collapse:collapse!important}.table td,.table th{background-color:#fff!important}.table-bordered td,.table-bordered th{border:1px solid #dee2e6!important}.table-dark{color:inherit}.table-dark tbody+tbody,.table-dark td,.table-dark th,.table-dark thead th{border-color:#dee2e6}.table .thead-dark th{color:inherit;border-color:#dee2e6}}
+/*# sourceMappingURL=bootstrap.min.css.map */
\ No newline at end of file
diff --git a/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/css/custom.css b/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/css/custom.css
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/css/nv.d3.min.css b/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/css/nv.d3.min.css
new file mode 100644
index 0000000000000000000000000000000000000000..7a6f7fe90c69cdbb23a7d27e5fcbd20286fe5b8f
--- /dev/null
+++ b/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/css/nv.d3.min.css
@@ -0,0 +1 @@
+.nvd3 .nv-axis{pointer-events:none;opacity:1}.nvd3 .nv-axis path{fill:none;stroke:#000;stroke-opacity:.75;shape-rendering:crispEdges}.nvd3 .nv-axis path.domain{stroke-opacity:.75}.nvd3 .nv-axis.nv-x path.domain{stroke-opacity:0}.nvd3 .nv-axis line{fill:none;stroke:#e5e5e5;shape-rendering:crispEdges}.nvd3 .nv-axis .zero line,.nvd3 .nv-axis line.zero{stroke-opacity:.75}.nvd3 .nv-axis .nv-axisMaxMin text{font-weight:700}.nvd3 .x .nv-axis .nv-axisMaxMin text,.nvd3 .x2 .nv-axis .nv-axisMaxMin text,.nvd3 .x3 .nv-axis .nv-axisMaxMin text{text-anchor:middle}.nvd3 .nv-axis.nv-disabled{opacity:0}.nvd3 .nv-bars rect{fill-opacity:.75;transition:fill-opacity 250ms linear;-moz-transition:fill-opacity 250ms linear;-webkit-transition:fill-opacity 250ms linear}.nvd3 .nv-bars rect.hover{fill-opacity:1}.nvd3 .nv-bars .hover rect{fill:#add8e6}.nvd3 .nv-bars text{fill:rgba(0,0,0,0)}.nvd3 .nv-bars .hover text{fill:rgba(0,0,0,1)}.nvd3 .nv-multibar .nv-groups rect,.nvd3 .nv-multibarHorizontal .nv-groups rect,.nvd3 .nv-discretebar .nv-groups rect{stroke-opacity:0;transition:fill-opacity 250ms linear;-moz-transition:fill-opacity 250ms linear;-webkit-transition:fill-opacity 250ms linear}.nvd3 .nv-multibar .nv-groups rect:hover,.nvd3 .nv-multibarHorizontal .nv-groups rect:hover,.nvd3 .nv-candlestickBar .nv-ticks rect:hover,.nvd3 .nv-discretebar .nv-groups rect:hover{fill-opacity:1}.nvd3 .nv-discretebar .nv-groups text,.nvd3 .nv-multibarHorizontal .nv-groups text{font-weight:700;fill:rgba(0,0,0,1);stroke:rgba(0,0,0,0)}.nvd3 .nv-boxplot circle{fill-opacity:.5}.nvd3 .nv-boxplot circle:hover{fill-opacity:1}.nvd3 .nv-boxplot rect:hover{fill-opacity:1}.nvd3 line.nv-boxplot-median{stroke:#000}.nv-boxplot-tick:hover{stroke-width:2.5px}.nvd3.nv-bullet{font:10px sans-serif}.nvd3.nv-bullet .nv-measure{fill-opacity:.8}.nvd3.nv-bullet .nv-measure:hover{fill-opacity:1}.nvd3.nv-bullet .nv-marker{stroke:#000;stroke-width:2px}.nvd3.nv-bullet .nv-markerTriangle{stroke:#000;fill:#fff;stroke-width:1.5px}.nvd3.nv-bullet .nv-tick line{stroke:#666;stroke-width:.5px}.nvd3.nv-bullet .nv-range.nv-s0{fill:#eee}.nvd3.nv-bullet .nv-range.nv-s1{fill:#ddd}.nvd3.nv-bullet .nv-range.nv-s2{fill:#ccc}.nvd3.nv-bullet .nv-title{font-size:14px;font-weight:700}.nvd3.nv-bullet .nv-subtitle{fill:#999}.nvd3.nv-bullet .nv-range{fill:#bababa;fill-opacity:.4}.nvd3.nv-bullet .nv-range:hover{fill-opacity:.7}.nvd3.nv-candlestickBar .nv-ticks .nv-tick{stroke-width:1px}.nvd3.nv-candlestickBar .nv-ticks .nv-tick.hover{stroke-width:2px}.nvd3.nv-candlestickBar .nv-ticks .nv-tick.positive rect{stroke:#2ca02c;fill:#2ca02c}.nvd3.nv-candlestickBar .nv-ticks .nv-tick.negative rect{stroke:#d62728;fill:#d62728}.with-transitions .nv-candlestickBar .nv-ticks .nv-tick{transition:stroke-width 250ms linear,stroke-opacity 250ms linear;-moz-transition:stroke-width 250ms linear,stroke-opacity 250ms linear;-webkit-transition:stroke-width 250ms linear,stroke-opacity 250ms linear}.nvd3.nv-candlestickBar .nv-ticks line{stroke:#333}.nvd3 .nv-legend .nv-disabled rect{}.nvd3 .nv-check-box .nv-box{fill-opacity:0;stroke-width:2}.nvd3 .nv-check-box .nv-check{fill-opacity:0;stroke-width:4}.nvd3 .nv-series.nv-disabled .nv-check-box .nv-check{fill-opacity:0;stroke-opacity:0}.nvd3 .nv-controlsWrap .nv-legend .nv-check-box .nv-check{opacity:0}.nvd3.nv-linePlusBar .nv-bar rect{fill-opacity:.75}.nvd3.nv-linePlusBar .nv-bar rect:hover{fill-opacity:1}.nvd3 .nv-groups path.nv-line{fill:none}.nvd3 .nv-groups path.nv-area{stroke:none}.nvd3.nv-line .nvd3.nv-scatter .nv-groups .nv-point{fill-opacity:0;stroke-opacity:0}.nvd3.nv-scatter.nv-single-point .nv-groups .nv-point{fill-opacity:.5!important;stroke-opacity:.5!important}.with-transitions .nvd3 .nv-groups .nv-point{transition:stroke-width 250ms linear,stroke-opacity 250ms linear;-moz-transition:stroke-width 250ms linear,stroke-opacity 250ms linear;-webkit-transition:stroke-width 250ms linear,stroke-opacity 250ms linear}.nvd3.nv-scatter .nv-groups .nv-point.hover,.nvd3 .nv-groups .nv-point.hover{stroke-width:7px;fill-opacity:.95!important;stroke-opacity:.95!important}.nvd3 .nv-point-paths path{stroke:#aaa;stroke-opacity:0;fill:#eee;fill-opacity:0}.nvd3 .nv-indexLine{cursor:ew-resize}svg.nvd3-svg{-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-ms-user-select:none;-moz-user-select:none;user-select:none;display:block;width:100%;height:100%}.nvtooltip.with-3d-shadow,.with-3d-shadow .nvtooltip{-moz-box-shadow:0 5px 10px rgba(0,0,0,.2);-webkit-box-shadow:0 5px 10px rgba(0,0,0,.2);box-shadow:0 5px 10px rgba(0,0,0,.2);-webkit-border-radius:5px;-moz-border-radius:5px;border-radius:5px}.nvd3 text{font:400 12px Arial}.nvd3 .title{font:700 14px Arial}.nvd3 .nv-background{fill:#fff;fill-opacity:0}.nvd3.nv-noData{font-size:18px;font-weight:700}.nv-brush .extent{fill-opacity:.125;shape-rendering:crispEdges}.nv-brush .resize path{fill:#eee;stroke:#666}.nvd3 .nv-legend .nv-series{cursor:pointer}.nvd3 .nv-legend .nv-disabled circle{fill-opacity:0}.nvd3 .nv-brush .extent{fill-opacity:0!important}.nvd3 .nv-brushBackground rect{stroke:#000;stroke-width:.4;fill:#fff;fill-opacity:.7}.nvd3.nv-ohlcBar .nv-ticks .nv-tick{stroke-width:1px}.nvd3.nv-ohlcBar .nv-ticks .nv-tick.hover{stroke-width:2px}.nvd3.nv-ohlcBar .nv-ticks .nv-tick.positive{stroke:#2ca02c}.nvd3.nv-ohlcBar .nv-ticks .nv-tick.negative{stroke:#d62728}.nvd3 .background path{fill:none;stroke:#EEE;stroke-opacity:.4;shape-rendering:crispEdges}.nvd3 .foreground path{fill:none;stroke-opacity:.7}.nvd3 .nv-parallelCoordinates-brush .extent{fill:#fff;fill-opacity:.6;stroke:gray;shape-rendering:crispEdges}.nvd3 .nv-parallelCoordinates .hover{fill-opacity:1;stroke-width:3px}.nvd3 .missingValuesline line{fill:none;stroke:#000;stroke-width:1;stroke-opacity:1;stroke-dasharray:5,5}.nvd3.nv-pie path{stroke-opacity:0;transition:fill-opacity 250ms linear,stroke-width 250ms linear,stroke-opacity 250ms linear;-moz-transition:fill-opacity 250ms linear,stroke-width 250ms linear,stroke-opacity 250ms linear;-webkit-transition:fill-opacity 250ms linear,stroke-width 250ms linear,stroke-opacity 250ms linear}.nvd3.nv-pie .nv-pie-title{font-size:24px;fill:rgba(19,196,249,.59)}.nvd3.nv-pie .nv-slice text{stroke:#000;stroke-width:0}.nvd3.nv-pie path{stroke:#fff;stroke-width:1px;stroke-opacity:1}.nvd3.nv-pie .hover path{fill-opacity:.7}.nvd3.nv-pie .nv-label{pointer-events:none}.nvd3.nv-pie .nv-label rect{fill-opacity:0;stroke-opacity:0}.nvd3 .nv-groups .nv-point.hover{stroke-width:20px;stroke-opacity:.5}.nvd3 .nv-scatter .nv-point.hover{fill-opacity:1}.nv-noninteractive{pointer-events:none}.nv-distx,.nv-disty{pointer-events:none}.nvd3.nv-sparkline path{fill:none}.nvd3.nv-sparklineplus g.nv-hoverValue{pointer-events:none}.nvd3.nv-sparklineplus .nv-hoverValue line{stroke:#333;stroke-width:1.5px}.nvd3.nv-sparklineplus,.nvd3.nv-sparklineplus g{pointer-events:all}.nvd3 .nv-hoverArea{fill-opacity:0;stroke-opacity:0}.nvd3.nv-sparklineplus .nv-xValue,.nvd3.nv-sparklineplus .nv-yValue{stroke-width:0;font-size:.9em;font-weight:400}.nvd3.nv-sparklineplus .nv-yValue{stroke:#f66}.nvd3.nv-sparklineplus .nv-maxValue{stroke:#2ca02c;fill:#2ca02c}.nvd3.nv-sparklineplus .nv-minValue{stroke:#d62728;fill:#d62728}.nvd3.nv-sparklineplus .nv-currentValue{font-weight:700;font-size:1.1em}.nvd3.nv-stackedarea path.nv-area{fill-opacity:.7;stroke-opacity:0;transition:fill-opacity 250ms linear,stroke-opacity 250ms linear;-moz-transition:fill-opacity 250ms linear,stroke-opacity 250ms linear;-webkit-transition:fill-opacity 250ms linear,stroke-opacity 250ms linear}.nvd3.nv-stackedarea path.nv-area.hover{fill-opacity:.9}.nvd3.nv-stackedarea .nv-groups .nv-point{stroke-opacity:0;fill-opacity:0}.nvtooltip{position:absolute;background-color:rgba(255,255,255,1);color:rgba(0,0,0,1);padding:1px;border:1px solid rgba(0,0,0,.2);z-index:10000;display:block;font-family:Arial;font-size:13px;text-align:left;pointer-events:none;white-space:nowrap;-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.nvtooltip{background:rgba(255,255,255,.8);border:1px solid rgba(0,0,0,.5);border-radius:4px}.nvtooltip.with-transitions,.with-transitions .nvtooltip{transition:opacity 50ms linear;-moz-transition:opacity 50ms linear;-webkit-transition:opacity 50ms linear;transition-delay:200ms;-moz-transition-delay:200ms;-webkit-transition-delay:200ms}.nvtooltip.x-nvtooltip,.nvtooltip.y-nvtooltip{padding:8px}.nvtooltip h3{margin:0;padding:4px 14px;line-height:18px;font-weight:400;background-color:rgba(247,247,247,.75);color:rgba(0,0,0,1);text-align:center;border-bottom:1px solid #ebebeb;-webkit-border-radius:5px 5px 0 0;-moz-border-radius:5px 5px 0 0;border-radius:5px 5px 0 0}.nvtooltip p{margin:0;padding:5px 14px;text-align:center}.nvtooltip span{display:inline-block;margin:2px 0}.nvtooltip table{margin:6px;border-spacing:0}.nvtooltip table td{padding:2px 9px 2px 0;vertical-align:middle}.nvtooltip table td.key{font-weight:400}.nvtooltip table td.value{text-align:right;font-weight:700}.nvtooltip table tr.highlight td{padding:1px 9px 1px 0;border-bottom-style:solid;border-bottom-width:1px;border-top-style:solid;border-top-width:1px}.nvtooltip table td.legend-color-guide div{width:8px;height:8px;vertical-align:middle}.nvtooltip table td.legend-color-guide div{width:12px;height:12px;border:1px solid #999}.nvtooltip .footer{padding:3px;text-align:center}.nvtooltip-pending-removal{pointer-events:none;display:none}.nvd3 .nv-interactiveGuideLine{pointer-events:none}.nvd3 line.nv-guideline{stroke:#ccc}
\ No newline at end of file
diff --git a/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/css/octicons.css b/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/css/octicons.css
new file mode 100644
index 0000000000000000000000000000000000000000..31d97867a129b824d6d4aeb505c2fabb23f80636
--- /dev/null
+++ b/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/css/octicons.css
@@ -0,0 +1,5 @@
+.octicon {
+  display: inline-block;
+  vertical-align: text-top;
+  fill: currentColor;
+}
diff --git a/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/css/style.css b/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/css/style.css
new file mode 100644
index 0000000000000000000000000000000000000000..088e9f781fafbb96ba329fcb65af2d54e9e1dcf4
--- /dev/null
+++ b/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/css/style.css
@@ -0,0 +1,127 @@
+body {
+ padding-top: 10px;
+}
+
+.popover {
+ max-width: none;
+}
+
+.octicon {
+ margin-right:.25em;
+}
+
+.table-bordered>thead>tr>td {
+ border-bottom-width: 1px;
+}
+
+.table tbody>tr>td, .table thead>tr>td {
+ padding-top: 3px;
+ padding-bottom: 3px;
+}
+
+.table-condensed tbody>tr>td {
+ padding-top: 0;
+ padding-bottom: 0;
+}
+
+.table .progress {
+ margin-bottom: inherit;
+}
+
+.table-borderless th, .table-borderless td {
+ border: 0 !important;
+}
+
+.table tbody tr.covered-by-large-tests, li.covered-by-large-tests, tr.success, td.success, li.success, span.success {
+ background-color: #dff0d8;
+}
+
+.table tbody tr.covered-by-medium-tests, li.covered-by-medium-tests {
+ background-color: #c3e3b5;
+}
+
+.table tbody tr.covered-by-small-tests, li.covered-by-small-tests {
+ background-color: #99cb84;
+}
+
+.table tbody tr.danger, .table tbody td.danger, li.danger, span.danger {
+ background-color: #f2dede;
+}
+
+.table tbody tr.warning, .table tbody td.warning, li.warning, span.warning {
+ background-color: #fcf8e3;
+}
+
+.table tbody td.info {
+ background-color: #d9edf7;
+}
+
+td.big {
+ width: 117px;
+}
+
+td.small {
+}
+
+td.codeLine {
+ font-family: "Source Code Pro", "SFMono-Regular", Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
+ white-space: pre-wrap;
+}
+
+td span.comment {
+ color: #888a85;
+}
+
+td span.default {
+ color: #2e3436;
+}
+
+td span.html {
+ color: #888a85;
+}
+
+td span.keyword {
+ color: #2e3436;
+ font-weight: bold;
+}
+
+pre span.string {
+ color: #2e3436;
+}
+
+span.success, span.warning, span.danger {
+ margin-right: 2px;
+ padding-left: 10px;
+ padding-right: 10px;
+ text-align: center;
+}
+
+#classCoverageDistribution, #classComplexity {
+ height: 200px;
+ width: 475px;
+}
+
+#toplink {
+ position: fixed;
+ left: 5px;
+ bottom: 5px;
+ outline: 0;
+}
+
+svg text {
+ font-family: "Lucida Grande", "Lucida Sans Unicode", Verdana, Arial, Helvetica, sans-serif;
+ font-size: 11px;
+ color: #666;
+ fill: #666;
+}
+
+.scrollbox {
+ height:245px;
+ overflow-x:hidden;
+ overflow-y:scroll;
+}
+
+table + .structure-heading {
+ border-top: 1px solid lightgrey;
+ padding-top: 0.5em;
+}
diff --git a/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/dashboard.html.dist b/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/dashboard.html.dist
new file mode 100644
index 0000000000000000000000000000000000000000..aa51bcb802c9f31a2e281e0709e7707b5b6a25fc
--- /dev/null
+++ b/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/dashboard.html.dist
@@ -0,0 +1,281 @@
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+  <meta charset="UTF-8">
+  <title>Dashboard for {{full_path}}</title>
+  <meta name="viewport" content="width=device-width, initial-scale=1.0">
+  <link href="{{path_to_root}}_css/bootstrap.min.css" rel="stylesheet" type="text/css">
+  <link href="{{path_to_root}}_css/nv.d3.min.css" rel="stylesheet" type="text/css">
+  <link href="{{path_to_root}}_css/style.css" rel="stylesheet" type="text/css">
+  <link href="{{path_to_root}}_css/custom.css" rel="stylesheet" type="text/css">
+ </head>
+ <body>
+  <header>
+   <div class="container-fluid">
+    <div class="row">
+     <div class="col-md-12">
+      <nav aria-label="breadcrumb">
+       <ol class="breadcrumb">
+{{breadcrumbs}}
+       </ol>
+      </nav>
+     </div>
+    </div>
+   </div>
+  </header>
+  <div class="container-fluid">
+   <div class="row">
+    <div class="col-md-12">
+     <h2>Classes</h2>
+    </div>
+   </div>
+   <div class="row">
+    <div class="col-md-6">
+     <h3>Coverage Distribution</h3>
+     <div id="classCoverageDistribution" style="height: 300px;">
+       <svg></svg>
+     </div>
+    </div>
+    <div class="col-md-6">
+     <h3>Complexity</h3>
+     <div id="classComplexity" style="height: 300px;">
+       <svg></svg>
+     </div>
+    </div>
+   </div>
+   <div class="row">
+    <div class="col-md-6">
+     <h3>Insufficient Coverage</h3>
+     <div class="scrollbox">
+      <table class="table">
+       <thead>
+        <tr>
+         <th>Class</th>
+         <th class="text-right">Coverage</th>
+        </tr>
+       </thead>
+       <tbody>
+{{insufficient_coverage_classes}}
+       </tbody>
+      </table>
+     </div>
+    </div>
+    <div class="col-md-6">
+     <h3>Project Risks</h3>
+     <div class="scrollbox">
+      <table class="table">
+       <thead>
+        <tr>
+         <th>Class</th>
+         <th class="text-right"><abbr title="Change Risk Anti-Patterns (CRAP) Index">CRAP</abbr></th>
+        </tr>
+       </thead>
+       <tbody>
+{{project_risks_classes}}
+       </tbody>
+      </table>
+     </div>
+    </div>
+   </div>
+   <div class="row">
+    <div class="col-md-12">
+     <h2>Methods</h2>
+    </div>
+   </div>
+   <div class="row">
+    <div class="col-md-6">
+     <h3>Coverage Distribution</h3>
+     <div id="methodCoverageDistribution" style="height: 300px;">
+       <svg></svg>
+     </div>
+    </div>
+    <div class="col-md-6">
+     <h3>Complexity</h3>
+     <div id="methodComplexity" style="height: 300px;">
+       <svg></svg>
+     </div>
+    </div>
+   </div>
+   <div class="row">
+    <div class="col-md-6">
+     <h3>Insufficient Coverage</h3>
+     <div class="scrollbox">
+      <table class="table">
+       <thead>
+        <tr>
+         <th>Method</th>
+         <th class="text-right">Coverage</th>
+        </tr>
+       </thead>
+       <tbody>
+{{insufficient_coverage_methods}}
+       </tbody>
+      </table>
+     </div>
+    </div>
+    <div class="col-md-6">
+     <h3>Project Risks</h3>
+     <div class="scrollbox">
+      <table class="table">
+       <thead>
+        <tr>
+         <th>Method</th>
+         <th class="text-right"><abbr title="Change Risk Anti-Patterns (CRAP) Index">CRAP</abbr></th>
+        </tr>
+       </thead>
+       <tbody>
+{{project_risks_methods}}
+       </tbody>
+      </table>
+     </div>
+    </div>
+   </div>
+   <footer>
+    <hr/>
+    <p>
+     <small>Generated by <a href="https://github.com/sebastianbergmann/php-code-coverage" target="_top">php-code-coverage {{version}}</a> using {{runtime}}{{generator}} at {{date}}.</small>
+    </p>
+   </footer>
+  </div>
+  <script src="{{path_to_root}}_js/jquery.min.js" type="text/javascript"></script>
+  <script src="{{path_to_root}}_js/d3.min.js" type="text/javascript"></script>
+  <script src="{{path_to_root}}_js/nv.d3.min.js" type="text/javascript"></script>
+  <script type="text/javascript">
+$(document).ready(function() {
+  nv.addGraph(function() {
+    var chart = nv.models.multiBarChart();
+    chart.tooltips(false)
+      .showControls(false)
+      .showLegend(false)
+      .reduceXTicks(false)
+      .staggerLabels(true)
+      .yAxis.tickFormat(d3.format('d'));
+
+    d3.select('#classCoverageDistribution svg')
+      .datum(getCoverageDistributionData({{class_coverage_distribution}}, "Class Coverage"))
+      .transition().duration(500).call(chart);
+
+    nv.utils.windowResize(chart.update);
+
+    return chart;
+  });
+
+  nv.addGraph(function() {
+    var chart = nv.models.multiBarChart();
+    chart.tooltips(false)
+      .showControls(false)
+      .showLegend(false)
+      .reduceXTicks(false)
+      .staggerLabels(true)
+      .yAxis.tickFormat(d3.format('d'));
+
+    d3.select('#methodCoverageDistribution svg')
+      .datum(getCoverageDistributionData({{method_coverage_distribution}}, "Method Coverage"))
+      .transition().duration(500).call(chart);
+
+    nv.utils.windowResize(chart.update);
+
+    return chart;
+  });
+
+  function getCoverageDistributionData(data, label) {
+    var labels = [
+      '0%',
+      '0-10%',
+      '10-20%',
+      '20-30%',
+      '30-40%',
+      '40-50%',
+      '50-60%',
+      '60-70%',
+      '70-80%',
+      '80-90%',
+      '90-100%',
+      '100%'
+    ];
+    var values = [];
+    $.each(labels, function(key) {
+      values.push({x: labels[key], y: data[key]});
+    });
+
+    return [
+      {
+        key: label,
+        values: values,
+        color: "#4572A7"
+      }
+    ];
+  }
+  nv.addGraph(function() {
+    var chart = nv.models.scatterChart()
+      .showDistX(true)
+      .showDistY(true)
+      .showLegend(false)
+      .forceX([0, 100]);
+    chart.tooltipContent(function(graph) {
+      return '<p>' + graph.point.class + '</p>';
+    });
+
+    chart.xAxis.axisLabel('Code Coverage (in percent)');
+    chart.yAxis.axisLabel('Cyclomatic Complexity');
+
+    d3.select('#classComplexity svg')
+      .datum(getComplexityData({{complexity_class}}, 'Class Complexity'))
+      .transition()
+      .duration(500)
+      .call(chart);
+
+    nv.utils.windowResize(chart.update);
+
+    return chart;
+  });
+
+  nv.addGraph(function() {
+    var chart = nv.models.scatterChart()
+      .showDistX(true)
+      .showDistY(true)
+      .showLegend(false)
+      .forceX([0, 100]);
+    chart.tooltipContent(function(graph) {
+      return '<p>' + graph.point.class + '</p>';
+    });
+
+    chart.xAxis.axisLabel('Code Coverage (in percent)');
+    chart.yAxis.axisLabel('Method Complexity');
+
+    d3.select('#methodComplexity svg')
+      .datum(getComplexityData({{complexity_method}}, 'Method Complexity'))
+      .transition()
+      .duration(500)
+      .call(chart);
+
+    nv.utils.windowResize(chart.update);
+
+    return chart;
+  });
+
+  function getComplexityData(data, label) {
+    var values = [];
+    $.each(data, function(key) {
+      var value = Math.round(data[key][0]*100) / 100;
+      values.push({
+        x: value,
+        y: data[key][1],
+        class: data[key][2],
+        size: 0.05,
+        shape: 'diamond'
+      });
+    });
+
+    return [
+      {
+        key: label,
+        values: values,
+        color: "#4572A7"
+      }
+    ];
+  }
+});
+  </script>
+ </body>
+</html>
diff --git a/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/dashboard_branch.html.dist b/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/dashboard_branch.html.dist
new file mode 100644
index 0000000000000000000000000000000000000000..aa51bcb802c9f31a2e281e0709e7707b5b6a25fc
--- /dev/null
+++ b/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/dashboard_branch.html.dist
@@ -0,0 +1,281 @@
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+  <meta charset="UTF-8">
+  <title>Dashboard for {{full_path}}</title>
+  <meta name="viewport" content="width=device-width, initial-scale=1.0">
+  <link href="{{path_to_root}}_css/bootstrap.min.css" rel="stylesheet" type="text/css">
+  <link href="{{path_to_root}}_css/nv.d3.min.css" rel="stylesheet" type="text/css">
+  <link href="{{path_to_root}}_css/style.css" rel="stylesheet" type="text/css">
+  <link href="{{path_to_root}}_css/custom.css" rel="stylesheet" type="text/css">
+ </head>
+ <body>
+  <header>
+   <div class="container-fluid">
+    <div class="row">
+     <div class="col-md-12">
+      <nav aria-label="breadcrumb">
+       <ol class="breadcrumb">
+{{breadcrumbs}}
+       </ol>
+      </nav>
+     </div>
+    </div>
+   </div>
+  </header>
+  <div class="container-fluid">
+   <div class="row">
+    <div class="col-md-12">
+     <h2>Classes</h2>
+    </div>
+   </div>
+   <div class="row">
+    <div class="col-md-6">
+     <h3>Coverage Distribution</h3>
+     <div id="classCoverageDistribution" style="height: 300px;">
+       <svg></svg>
+     </div>
+    </div>
+    <div class="col-md-6">
+     <h3>Complexity</h3>
+     <div id="classComplexity" style="height: 300px;">
+       <svg></svg>
+     </div>
+    </div>
+   </div>
+   <div class="row">
+    <div class="col-md-6">
+     <h3>Insufficient Coverage</h3>
+     <div class="scrollbox">
+      <table class="table">
+       <thead>
+        <tr>
+         <th>Class</th>
+         <th class="text-right">Coverage</th>
+        </tr>
+       </thead>
+       <tbody>
+{{insufficient_coverage_classes}}
+       </tbody>
+      </table>
+     </div>
+    </div>
+    <div class="col-md-6">
+     <h3>Project Risks</h3>
+     <div class="scrollbox">
+      <table class="table">
+       <thead>
+        <tr>
+         <th>Class</th>
+         <th class="text-right"><abbr title="Change Risk Anti-Patterns (CRAP) Index">CRAP</abbr></th>
+        </tr>
+       </thead>
+       <tbody>
+{{project_risks_classes}}
+       </tbody>
+      </table>
+     </div>
+    </div>
+   </div>
+   <div class="row">
+    <div class="col-md-12">
+     <h2>Methods</h2>
+    </div>
+   </div>
+   <div class="row">
+    <div class="col-md-6">
+     <h3>Coverage Distribution</h3>
+     <div id="methodCoverageDistribution" style="height: 300px;">
+       <svg></svg>
+     </div>
+    </div>
+    <div class="col-md-6">
+     <h3>Complexity</h3>
+     <div id="methodComplexity" style="height: 300px;">
+       <svg></svg>
+     </div>
+    </div>
+   </div>
+   <div class="row">
+    <div class="col-md-6">
+     <h3>Insufficient Coverage</h3>
+     <div class="scrollbox">
+      <table class="table">
+       <thead>
+        <tr>
+         <th>Method</th>
+         <th class="text-right">Coverage</th>
+        </tr>
+       </thead>
+       <tbody>
+{{insufficient_coverage_methods}}
+       </tbody>
+      </table>
+     </div>
+    </div>
+    <div class="col-md-6">
+     <h3>Project Risks</h3>
+     <div class="scrollbox">
+      <table class="table">
+       <thead>
+        <tr>
+         <th>Method</th>
+         <th class="text-right"><abbr title="Change Risk Anti-Patterns (CRAP) Index">CRAP</abbr></th>
+        </tr>
+       </thead>
+       <tbody>
+{{project_risks_methods}}
+       </tbody>
+      </table>
+     </div>
+    </div>
+   </div>
+   <footer>
+    <hr/>
+    <p>
+     <small>Generated by <a href="https://github.com/sebastianbergmann/php-code-coverage" target="_top">php-code-coverage {{version}}</a> using {{runtime}}{{generator}} at {{date}}.</small>
+    </p>
+   </footer>
+  </div>
+  <script src="{{path_to_root}}_js/jquery.min.js" type="text/javascript"></script>
+  <script src="{{path_to_root}}_js/d3.min.js" type="text/javascript"></script>
+  <script src="{{path_to_root}}_js/nv.d3.min.js" type="text/javascript"></script>
+  <script type="text/javascript">
+$(document).ready(function() {
+  nv.addGraph(function() {
+    var chart = nv.models.multiBarChart();
+    chart.tooltips(false)
+      .showControls(false)
+      .showLegend(false)
+      .reduceXTicks(false)
+      .staggerLabels(true)
+      .yAxis.tickFormat(d3.format('d'));
+
+    d3.select('#classCoverageDistribution svg')
+      .datum(getCoverageDistributionData({{class_coverage_distribution}}, "Class Coverage"))
+      .transition().duration(500).call(chart);
+
+    nv.utils.windowResize(chart.update);
+
+    return chart;
+  });
+
+  nv.addGraph(function() {
+    var chart = nv.models.multiBarChart();
+    chart.tooltips(false)
+      .showControls(false)
+      .showLegend(false)
+      .reduceXTicks(false)
+      .staggerLabels(true)
+      .yAxis.tickFormat(d3.format('d'));
+
+    d3.select('#methodCoverageDistribution svg')
+      .datum(getCoverageDistributionData({{method_coverage_distribution}}, "Method Coverage"))
+      .transition().duration(500).call(chart);
+
+    nv.utils.windowResize(chart.update);
+
+    return chart;
+  });
+
+  function getCoverageDistributionData(data, label) {
+    var labels = [
+      '0%',
+      '0-10%',
+      '10-20%',
+      '20-30%',
+      '30-40%',
+      '40-50%',
+      '50-60%',
+      '60-70%',
+      '70-80%',
+      '80-90%',
+      '90-100%',
+      '100%'
+    ];
+    var values = [];
+    $.each(labels, function(key) {
+      values.push({x: labels[key], y: data[key]});
+    });
+
+    return [
+      {
+        key: label,
+        values: values,
+        color: "#4572A7"
+      }
+    ];
+  }
+  nv.addGraph(function() {
+    var chart = nv.models.scatterChart()
+      .showDistX(true)
+      .showDistY(true)
+      .showLegend(false)
+      .forceX([0, 100]);
+    chart.tooltipContent(function(graph) {
+      return '<p>' + graph.point.class + '</p>';
+    });
+
+    chart.xAxis.axisLabel('Code Coverage (in percent)');
+    chart.yAxis.axisLabel('Cyclomatic Complexity');
+
+    d3.select('#classComplexity svg')
+      .datum(getComplexityData({{complexity_class}}, 'Class Complexity'))
+      .transition()
+      .duration(500)
+      .call(chart);
+
+    nv.utils.windowResize(chart.update);
+
+    return chart;
+  });
+
+  nv.addGraph(function() {
+    var chart = nv.models.scatterChart()
+      .showDistX(true)
+      .showDistY(true)
+      .showLegend(false)
+      .forceX([0, 100]);
+    chart.tooltipContent(function(graph) {
+      return '<p>' + graph.point.class + '</p>';
+    });
+
+    chart.xAxis.axisLabel('Code Coverage (in percent)');
+    chart.yAxis.axisLabel('Method Complexity');
+
+    d3.select('#methodComplexity svg')
+      .datum(getComplexityData({{complexity_method}}, 'Method Complexity'))
+      .transition()
+      .duration(500)
+      .call(chart);
+
+    nv.utils.windowResize(chart.update);
+
+    return chart;
+  });
+
+  function getComplexityData(data, label) {
+    var values = [];
+    $.each(data, function(key) {
+      var value = Math.round(data[key][0]*100) / 100;
+      values.push({
+        x: value,
+        y: data[key][1],
+        class: data[key][2],
+        size: 0.05,
+        shape: 'diamond'
+      });
+    });
+
+    return [
+      {
+        key: label,
+        values: values,
+        color: "#4572A7"
+      }
+    ];
+  }
+});
+  </script>
+ </body>
+</html>
diff --git a/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/directory.html.dist b/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/directory.html.dist
new file mode 100644
index 0000000000000000000000000000000000000000..a263463a68dde7c4da695c76fa0007dbaa3a881b
--- /dev/null
+++ b/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/directory.html.dist
@@ -0,0 +1,60 @@
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+  <meta charset="UTF-8">
+  <title>Code Coverage for {{full_path}}</title>
+  <meta name="viewport" content="width=device-width, initial-scale=1.0">
+  <link href="{{path_to_root}}_css/bootstrap.min.css" rel="stylesheet" type="text/css">
+  <link href="{{path_to_root}}_css/octicons.css" rel="stylesheet" type="text/css">
+  <link href="{{path_to_root}}_css/style.css" rel="stylesheet" type="text/css">
+  <link href="{{path_to_root}}_css/custom.css" rel="stylesheet" type="text/css">
+ </head>
+ <body>
+  <header>
+   <div class="container-fluid">
+    <div class="row">
+     <div class="col-md-12">
+      <nav aria-label="breadcrumb">
+       <ol class="breadcrumb">
+{{breadcrumbs}}
+       </ol>
+      </nav>
+     </div>
+    </div>
+   </div>
+  </header>
+  <div class="container-fluid">
+   <div class="table-responsive">
+    <table class="table table-bordered">
+     <thead>
+      <tr>
+       <td>&nbsp;</td>
+       <td colspan="9"><div align="center"><strong>Code Coverage</strong></div></td>
+      </tr>
+      <tr>
+       <td>&nbsp;</td>
+       <td colspan="3"><div align="center"><strong>Lines</strong></div></td>
+       <td colspan="3"><div align="center"><strong>Functions and Methods</strong></div></td>
+       <td colspan="3"><div align="center"><strong>Classes and Traits</strong></div></td>
+      </tr>
+     </thead>
+     <tbody>
+{{items}}
+     </tbody>
+    </table>
+   </div>
+   <footer>
+    <hr/>
+    <h4>Legend</h4>
+    <p>
+     <span class="danger"><strong>Low</strong>: 0% to {{low_upper_bound}}%</span>
+     <span class="warning"><strong>Medium</strong>: {{low_upper_bound}}% to {{high_lower_bound}}%</span>
+     <span class="success"><strong>High</strong>: {{high_lower_bound}}% to 100%</span>
+    </p>
+    <p>
+     <small>Generated by <a href="https://github.com/sebastianbergmann/php-code-coverage" target="_top">php-code-coverage {{version}}</a> using {{runtime}}{{generator}} at {{date}}.</small>
+    </p>
+   </footer>
+  </div>
+ </body>
+</html>
diff --git a/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/directory_branch.html.dist b/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/directory_branch.html.dist
new file mode 100644
index 0000000000000000000000000000000000000000..8c94861ffb99588349bb4758898c2b294c9f1d42
--- /dev/null
+++ b/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/directory_branch.html.dist
@@ -0,0 +1,62 @@
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+  <meta charset="UTF-8">
+  <title>Code Coverage for {{full_path}}</title>
+  <meta name="viewport" content="width=device-width, initial-scale=1.0">
+  <link href="{{path_to_root}}_css/bootstrap.min.css" rel="stylesheet" type="text/css">
+  <link href="{{path_to_root}}_css/octicons.css" rel="stylesheet" type="text/css">
+  <link href="{{path_to_root}}_css/style.css" rel="stylesheet" type="text/css">
+  <link href="{{path_to_root}}_css/custom.css" rel="stylesheet" type="text/css">
+ </head>
+ <body>
+  <header>
+   <div class="container-fluid">
+    <div class="row">
+     <div class="col-md-12">
+      <nav aria-label="breadcrumb">
+       <ol class="breadcrumb">
+{{breadcrumbs}}
+       </ol>
+      </nav>
+     </div>
+    </div>
+   </div>
+  </header>
+  <div class="container-fluid">
+   <div class="table-responsive">
+    <table class="table table-bordered">
+     <thead>
+      <tr>
+       <td>&nbsp;</td>
+       <td colspan="15"><div align="center"><strong>Code Coverage</strong></div></td>
+      </tr>
+      <tr>
+       <td>&nbsp;</td>
+       <td colspan="3"><div align="center"><strong>Lines</strong></div></td>
+       <td colspan="3"><div align="center"><strong>Branches</strong></div></td>
+       <td colspan="3"><div align="center"><strong>Paths</strong></div></td>
+       <td colspan="3"><div align="center"><strong>Functions and Methods</strong></div></td>
+       <td colspan="3"><div align="center"><strong>Classes and Traits</strong></div></td>
+      </tr>
+     </thead>
+     <tbody>
+{{items}}
+     </tbody>
+    </table>
+   </div>
+   <footer>
+    <hr/>
+    <h4>Legend</h4>
+    <p>
+     <span class="danger"><strong>Low</strong>: 0% to {{low_upper_bound}}%</span>
+     <span class="warning"><strong>Medium</strong>: {{low_upper_bound}}% to {{high_lower_bound}}%</span>
+     <span class="success"><strong>High</strong>: {{high_lower_bound}}% to 100%</span>
+    </p>
+    <p>
+     <small>Generated by <a href="https://github.com/sebastianbergmann/php-code-coverage" target="_top">php-code-coverage {{version}}</a> using {{runtime}}{{generator}} at {{date}}.</small>
+    </p>
+   </footer>
+  </div>
+ </body>
+</html>
diff --git a/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/directory_item.html.dist b/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/directory_item.html.dist
new file mode 100644
index 0000000000000000000000000000000000000000..f6941a4376c0e2499c1ec4aa8255f387e883017d
--- /dev/null
+++ b/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/directory_item.html.dist
@@ -0,0 +1,13 @@
+      <tr>
+       <td class="{{lines_level}}">{{icon}}{{name}}</td>
+       <td class="{{lines_level}} big">{{lines_bar}}</td>
+       <td class="{{lines_level}} small"><div align="right">{{lines_executed_percent}}</div></td>
+       <td class="{{lines_level}} small"><div align="right">{{lines_number}}</div></td>
+       <td class="{{methods_level}} big">{{methods_bar}}</td>
+       <td class="{{methods_level}} small"><div align="right">{{methods_tested_percent}}</div></td>
+       <td class="{{methods_level}} small"><div align="right">{{methods_number}}</div></td>
+       <td class="{{classes_level}} big">{{classes_bar}}</td>
+       <td class="{{classes_level}} small"><div align="right">{{classes_tested_percent}}</div></td>
+       <td class="{{classes_level}} small"><div align="right">{{classes_number}}</div></td>
+      </tr>
+
diff --git a/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/directory_item_branch.html.dist b/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/directory_item_branch.html.dist
new file mode 100644
index 0000000000000000000000000000000000000000..532a436c2c086f5085f2609b586c01a787d8db27
--- /dev/null
+++ b/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/directory_item_branch.html.dist
@@ -0,0 +1,19 @@
+      <tr>
+       <td class="{{lines_level}}">{{icon}}{{name}}</td>
+       <td class="{{lines_level}} big">{{lines_bar}}</td>
+       <td class="{{lines_level}} small"><div align="right">{{lines_executed_percent}}</div></td>
+       <td class="{{lines_level}} small"><div align="right">{{lines_number}}</div></td>
+       <td class="{{branches_level}} big">{{branches_bar}}</td>
+       <td class="{{branches_level}} small"><div align="right">{{branches_executed_percent}}</div></td>
+       <td class="{{branches_level}} small"><div align="right">{{branches_number}}</div></td>
+       <td class="{{paths_level}} big">{{paths_bar}}</td>
+       <td class="{{paths_level}} small"><div align="right">{{paths_executed_percent}}</div></td>
+       <td class="{{paths_level}} small"><div align="right">{{paths_number}}</div></td>
+       <td class="{{methods_level}} big">{{methods_bar}}</td>
+       <td class="{{methods_level}} small"><div align="right">{{methods_tested_percent}}</div></td>
+       <td class="{{methods_level}} small"><div align="right">{{methods_number}}</div></td>
+       <td class="{{classes_level}} big">{{classes_bar}}</td>
+       <td class="{{classes_level}} small"><div align="right">{{classes_tested_percent}}</div></td>
+       <td class="{{classes_level}} small"><div align="right">{{classes_number}}</div></td>
+      </tr>
+
diff --git a/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/file.html.dist b/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/file.html.dist
new file mode 100644
index 0000000000000000000000000000000000000000..686b8b946d4f788ed3359fef04d55df09090c95e
--- /dev/null
+++ b/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/file.html.dist
@@ -0,0 +1,65 @@
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+  <meta charset="UTF-8">
+  <title>Code Coverage for {{full_path}}</title>
+  <meta name="viewport" content="width=device-width, initial-scale=1.0">
+  <link href="{{path_to_root}}_css/bootstrap.min.css" rel="stylesheet" type="text/css">
+  <link href="{{path_to_root}}_css/octicons.css" rel="stylesheet" type="text/css">
+  <link href="{{path_to_root}}_css/style.css" rel="stylesheet" type="text/css">
+  <link href="{{path_to_root}}_css/custom.css" rel="stylesheet" type="text/css">
+ </head>
+ <body>
+  <header>
+   <div class="container-fluid">
+    <div class="row">
+     <div class="col-md-12">
+      <nav aria-label="breadcrumb">
+       <ol class="breadcrumb">
+{{breadcrumbs}}
+       </ol>
+      </nav>
+     </div>
+    </div>
+   </div>
+  </header>
+  <div class="container-fluid">
+   <div class="table-responsive">
+    <table class="table table-bordered">
+     <thead>
+      <tr>
+       <td>&nbsp;</td>
+       <td colspan="10"><div align="center"><strong>Code Coverage</strong></div></td>
+      </tr>
+      <tr>
+       <td>&nbsp;</td>
+       <td colspan="3"><div align="center"><strong>Classes and Traits</strong></div></td>
+       <td colspan="4"><div align="center"><strong>Functions and Methods</strong></div></td>
+       <td colspan="3"><div align="center"><strong>Lines</strong></div></td>
+      </tr>
+     </thead>
+     <tbody>
+{{items}}
+     </tbody>
+    </table>
+   </div>
+{{lines}}
+{{structure}}
+   <footer>
+    <hr/>
+    <h4>Legend</h4>
+    {{legend}}
+    <p>
+     <small>Generated by <a href="https://github.com/sebastianbergmann/php-code-coverage" target="_top">php-code-coverage {{version}}</a> using {{runtime}}{{generator}} at {{date}}.</small>
+    </p>
+    <a title="Back to the top" id="toplink" href="#">
+        <svg xmlns="http://www.w3.org/2000/svg" width="12" height="16" viewBox="0 0 12 16"><path fill-rule="evenodd" d="M12 11L6 5l-6 6h12z"/></svg>
+    </a>
+   </footer>
+  </div>
+  <script src="{{path_to_root}}_js/jquery.min.js" type="text/javascript"></script>
+  <script src="{{path_to_root}}_js/popper.min.js" type="text/javascript"></script>
+  <script src="{{path_to_root}}_js/bootstrap.min.js" type="text/javascript"></script>
+  <script src="{{path_to_root}}_js/file.js" type="text/javascript"></script>
+ </body>
+</html>
diff --git a/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/file_branch.html.dist b/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/file_branch.html.dist
new file mode 100644
index 0000000000000000000000000000000000000000..ecbe62134124fbe37336db95388e90a74ad1b123
--- /dev/null
+++ b/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/file_branch.html.dist
@@ -0,0 +1,67 @@
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+  <meta charset="UTF-8">
+  <title>Code Coverage for {{full_path}}</title>
+  <meta name="viewport" content="width=device-width, initial-scale=1.0">
+  <link href="{{path_to_root}}_css/bootstrap.min.css" rel="stylesheet" type="text/css">
+  <link href="{{path_to_root}}_css/octicons.css" rel="stylesheet" type="text/css">
+  <link href="{{path_to_root}}_css/style.css" rel="stylesheet" type="text/css">
+  <link href="{{path_to_root}}_css/custom.css" rel="stylesheet" type="text/css">
+ </head>
+ <body>
+  <header>
+   <div class="container-fluid">
+    <div class="row">
+     <div class="col-md-12">
+      <nav aria-label="breadcrumb">
+       <ol class="breadcrumb">
+{{breadcrumbs}}
+       </ol>
+      </nav>
+     </div>
+    </div>
+   </div>
+  </header>
+  <div class="container-fluid">
+   <div class="table-responsive">
+    <table class="table table-bordered">
+     <thead>
+      <tr>
+       <td>&nbsp;</td>
+       <td colspan="16"><div align="center"><strong>Code Coverage</strong></div></td>
+      </tr>
+      <tr>
+       <td>&nbsp;</td>
+       <td colspan="3"><div align="center"><strong>Classes and Traits</strong></div></td>
+       <td colspan="4"><div align="center"><strong>Functions and Methods</strong></div></td>
+       <td colspan="3"><div align="center"><strong>Paths</strong></div></td>
+       <td colspan="3"><div align="center"><strong>Branches</strong></div></td>
+       <td colspan="3"><div align="center"><strong>Lines</strong></div></td>
+      </tr>
+     </thead>
+     <tbody>
+{{items}}
+     </tbody>
+    </table>
+   </div>
+{{lines}}
+{{structure}}
+   <footer>
+    <hr/>
+    <h4>Legend</h4>
+    {{legend}}
+    <p>
+     <small>Generated by <a href="https://github.com/sebastianbergmann/php-code-coverage" target="_top">php-code-coverage {{version}}</a> using {{runtime}}{{generator}} at {{date}}.</small>
+    </p>
+    <a title="Back to the top" id="toplink" href="#">
+        <svg xmlns="http://www.w3.org/2000/svg" width="12" height="16" viewBox="0 0 12 16"><path fill-rule="evenodd" d="M12 11L6 5l-6 6h12z"/></svg>
+    </a>
+   </footer>
+  </div>
+  <script src="{{path_to_root}}_js/jquery.min.js" type="text/javascript"></script>
+  <script src="{{path_to_root}}_js/popper.min.js" type="text/javascript"></script>
+  <script src="{{path_to_root}}_js/bootstrap.min.js" type="text/javascript"></script>
+  <script src="{{path_to_root}}_js/file.js" type="text/javascript"></script>
+ </body>
+</html>
diff --git a/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/file_item.html.dist b/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/file_item.html.dist
new file mode 100644
index 0000000000000000000000000000000000000000..dc754b3c67d87f1f4e39dbfccfb9bad36af0f32a
--- /dev/null
+++ b/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/file_item.html.dist
@@ -0,0 +1,14 @@
+      <tr>
+       <td class="{{classes_level}}">{{name}}</td>
+       <td class="{{classes_level}} big">{{classes_bar}}</td>
+       <td class="{{classes_level}} small"><div align="right">{{classes_tested_percent}}</div></td>
+       <td class="{{classes_level}} small"><div align="right">{{classes_number}}</div></td>
+       <td class="{{methods_level}} big">{{methods_bar}}</td>
+       <td class="{{methods_level}} small"><div align="right">{{methods_tested_percent}}</div></td>
+       <td class="{{methods_level}} small"><div align="right">{{methods_number}}</div></td>
+       <td class="{{methods_level}} small">{{crap}}</td>
+       <td class="{{lines_level}} big">{{lines_bar}}</td>
+       <td class="{{lines_level}} small"><div align="right">{{lines_executed_percent}}</div></td>
+       <td class="{{lines_level}} small"><div align="right">{{lines_number}}</div></td>
+      </tr>
+
diff --git a/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/file_item_branch.html.dist b/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/file_item_branch.html.dist
new file mode 100644
index 0000000000000000000000000000000000000000..d7e479f627cd80d3cec70661c17bc4de0b8d5cac
--- /dev/null
+++ b/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/file_item_branch.html.dist
@@ -0,0 +1,20 @@
+      <tr>
+       <td class="{{classes_level}}">{{name}}</td>
+       <td class="{{classes_level}} big">{{classes_bar}}</td>
+       <td class="{{classes_level}} small"><div align="right">{{classes_tested_percent}}</div></td>
+       <td class="{{classes_level}} small"><div align="right">{{classes_number}}</div></td>
+       <td class="{{methods_level}} big">{{methods_bar}}</td>
+       <td class="{{methods_level}} small"><div align="right">{{methods_tested_percent}}</div></td>
+       <td class="{{methods_level}} small"><div align="right">{{methods_number}}</div></td>
+       <td class="{{methods_level}} small">{{crap}}</td>
+       <td class="{{paths_level}} big">{{paths_bar}}</td>
+       <td class="{{paths_level}} small"><div align="right">{{paths_executed_percent}}</div></td>
+       <td class="{{paths_level}} small"><div align="right">{{paths_number}}</div></td>
+       <td class="{{branches_level}} big">{{branches_bar}}</td>
+       <td class="{{branches_level}} small"><div align="right">{{branches_executed_percent}}</div></td>
+       <td class="{{branches_level}} small"><div align="right">{{branches_number}}</div></td>
+       <td class="{{lines_level}} big">{{lines_bar}}</td>
+       <td class="{{lines_level}} small"><div align="right">{{lines_executed_percent}}</div></td>
+       <td class="{{lines_level}} small"><div align="right">{{lines_number}}</div></td>
+      </tr>
+
diff --git a/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/icons/file-code.svg b/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/icons/file-code.svg
new file mode 100644
index 0000000000000000000000000000000000000000..5b4b199531b02bf91bae663728d620e8767ee731
--- /dev/null
+++ b/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/icons/file-code.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="12" height="16" viewBox="0 0 12 16"><path fill-rule="evenodd" d="M8.5 1H1c-.55 0-1 .45-1 1v12c0 .55.45 1 1 1h10c.55 0 1-.45 1-1V4.5L8.5 1zM11 14H1V2h7l3 3v9zM5 6.98L3.5 8.5 5 10l-.5 1L2 8.5 4.5 6l.5.98zM7.5 6L10 8.5 7.5 11l-.5-.98L8.5 8.5 7 7l.5-1z"/></svg>
\ No newline at end of file
diff --git a/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/icons/file-directory.svg b/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/icons/file-directory.svg
new file mode 100644
index 0000000000000000000000000000000000000000..4bf1f1caa8958105b2e2c7709bca2b55b1db3aec
--- /dev/null
+++ b/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/icons/file-directory.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="14" height="16" viewBox="0 0 14 16"><path fill-rule="evenodd" d="M13 4H7V3c0-.66-.31-1-1-1H1c-.55 0-1 .45-1 1v10c0 .55.45 1 1 1h12c.55 0 1-.45 1-1V5c0-.55-.45-1-1-1zM6 4H1V3h5v1z"/></svg>
\ No newline at end of file
diff --git a/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/js/bootstrap.min.js b/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/js/bootstrap.min.js
new file mode 100644
index 0000000000000000000000000000000000000000..3ecf55f28bd98f8b6f25512d7e9a91bc4a60204e
--- /dev/null
+++ b/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/js/bootstrap.min.js
@@ -0,0 +1,7 @@
+/*!
+  * Bootstrap v4.5.0 (https://getbootstrap.com/)
+  * Copyright 2011-2020 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors)
+  * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+  */
+!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports,require("jquery"),require("popper.js")):"function"==typeof define&&define.amd?define(["exports","jquery","popper.js"],e):e((t=t||self).bootstrap={},t.jQuery,t.Popper)}(this,(function(t,e,n){"use strict";function i(t,e){for(var n=0;n<e.length;n++){var i=e[n];i.enumerable=i.enumerable||!1,i.configurable=!0,"value"in i&&(i.writable=!0),Object.defineProperty(t,i.key,i)}}function o(t,e,n){return e&&i(t.prototype,e),n&&i(t,n),t}function s(t,e,n){return e in t?Object.defineProperty(t,e,{value:n,enumerable:!0,configurable:!0,writable:!0}):t[e]=n,t}function r(t,e){var n=Object.keys(t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(t);e&&(i=i.filter((function(e){return Object.getOwnPropertyDescriptor(t,e).enumerable}))),n.push.apply(n,i)}return n}function a(t){for(var e=1;e<arguments.length;e++){var n=null!=arguments[e]?arguments[e]:{};e%2?r(Object(n),!0).forEach((function(e){s(t,e,n[e])})):Object.getOwnPropertyDescriptors?Object.defineProperties(t,Object.getOwnPropertyDescriptors(n)):r(Object(n)).forEach((function(e){Object.defineProperty(t,e,Object.getOwnPropertyDescriptor(n,e))}))}return t}e=e&&Object.prototype.hasOwnProperty.call(e,"default")?e.default:e,n=n&&Object.prototype.hasOwnProperty.call(n,"default")?n.default:n;function l(t){var n=this,i=!1;return e(this).one(c.TRANSITION_END,(function(){i=!0})),setTimeout((function(){i||c.triggerTransitionEnd(n)}),t),this}var c={TRANSITION_END:"bsTransitionEnd",getUID:function(t){do{t+=~~(1e6*Math.random())}while(document.getElementById(t));return t},getSelectorFromElement:function(t){var e=t.getAttribute("data-target");if(!e||"#"===e){var n=t.getAttribute("href");e=n&&"#"!==n?n.trim():""}try{return document.querySelector(e)?e:null}catch(t){return null}},getTransitionDurationFromElement:function(t){if(!t)return 0;var n=e(t).css("transition-duration"),i=e(t).css("transition-delay"),o=parseFloat(n),s=parseFloat(i);return o||s?(n=n.split(",")[0],i=i.split(",")[0],1e3*(parseFloat(n)+parseFloat(i))):0},reflow:function(t){return t.offsetHeight},triggerTransitionEnd:function(t){e(t).trigger("transitionend")},supportsTransitionEnd:function(){return Boolean("transitionend")},isElement:function(t){return(t[0]||t).nodeType},typeCheckConfig:function(t,e,n){for(var i in n)if(Object.prototype.hasOwnProperty.call(n,i)){var o=n[i],s=e[i],r=s&&c.isElement(s)?"element":null===(a=s)||"undefined"==typeof a?""+a:{}.toString.call(a).match(/\s([a-z]+)/i)[1].toLowerCase();if(!new RegExp(o).test(r))throw new Error(t.toUpperCase()+': Option "'+i+'" provided type "'+r+'" but expected type "'+o+'".')}var a},findShadowRoot:function(t){if(!document.documentElement.attachShadow)return null;if("function"==typeof t.getRootNode){var e=t.getRootNode();return e instanceof ShadowRoot?e:null}return t instanceof ShadowRoot?t:t.parentNode?c.findShadowRoot(t.parentNode):null},jQueryDetection:function(){if("undefined"==typeof e)throw new TypeError("Bootstrap's JavaScript requires jQuery. jQuery must be included before Bootstrap's JavaScript.");var t=e.fn.jquery.split(" ")[0].split(".");if(t[0]<2&&t[1]<9||1===t[0]&&9===t[1]&&t[2]<1||t[0]>=4)throw new Error("Bootstrap's JavaScript requires at least jQuery v1.9.1 but less than v4.0.0")}};c.jQueryDetection(),e.fn.emulateTransitionEnd=l,e.event.special[c.TRANSITION_END]={bindType:"transitionend",delegateType:"transitionend",handle:function(t){if(e(t.target).is(this))return t.handleObj.handler.apply(this,arguments)}};var h="alert",u=e.fn[h],d=function(){function t(t){this._element=t}var n=t.prototype;return n.close=function(t){var e=this._element;t&&(e=this._getRootElement(t)),this._triggerCloseEvent(e).isDefaultPrevented()||this._removeElement(e)},n.dispose=function(){e.removeData(this._element,"bs.alert"),this._element=null},n._getRootElement=function(t){var n=c.getSelectorFromElement(t),i=!1;return n&&(i=document.querySelector(n)),i||(i=e(t).closest(".alert")[0]),i},n._triggerCloseEvent=function(t){var n=e.Event("close.bs.alert");return e(t).trigger(n),n},n._removeElement=function(t){var n=this;if(e(t).removeClass("show"),e(t).hasClass("fade")){var i=c.getTransitionDurationFromElement(t);e(t).one(c.TRANSITION_END,(function(e){return n._destroyElement(t,e)})).emulateTransitionEnd(i)}else this._destroyElement(t)},n._destroyElement=function(t){e(t).detach().trigger("closed.bs.alert").remove()},t._jQueryInterface=function(n){return this.each((function(){var i=e(this),o=i.data("bs.alert");o||(o=new t(this),i.data("bs.alert",o)),"close"===n&&o[n](this)}))},t._handleDismiss=function(t){return function(e){e&&e.preventDefault(),t.close(this)}},o(t,null,[{key:"VERSION",get:function(){return"4.5.0"}}]),t}();e(document).on("click.bs.alert.data-api",'[data-dismiss="alert"]',d._handleDismiss(new d)),e.fn[h]=d._jQueryInterface,e.fn[h].Constructor=d,e.fn[h].noConflict=function(){return e.fn[h]=u,d._jQueryInterface};var f=e.fn.button,g=function(){function t(t){this._element=t}var n=t.prototype;return n.toggle=function(){var t=!0,n=!0,i=e(this._element).closest('[data-toggle="buttons"]')[0];if(i){var o=this._element.querySelector('input:not([type="hidden"])');if(o){if("radio"===o.type)if(o.checked&&this._element.classList.contains("active"))t=!1;else{var s=i.querySelector(".active");s&&e(s).removeClass("active")}t&&("checkbox"!==o.type&&"radio"!==o.type||(o.checked=!this._element.classList.contains("active")),e(o).trigger("change")),o.focus(),n=!1}}this._element.hasAttribute("disabled")||this._element.classList.contains("disabled")||(n&&this._element.setAttribute("aria-pressed",!this._element.classList.contains("active")),t&&e(this._element).toggleClass("active"))},n.dispose=function(){e.removeData(this._element,"bs.button"),this._element=null},t._jQueryInterface=function(n){return this.each((function(){var i=e(this).data("bs.button");i||(i=new t(this),e(this).data("bs.button",i)),"toggle"===n&&i[n]()}))},o(t,null,[{key:"VERSION",get:function(){return"4.5.0"}}]),t}();e(document).on("click.bs.button.data-api",'[data-toggle^="button"]',(function(t){var n=t.target,i=n;if(e(n).hasClass("btn")||(n=e(n).closest(".btn")[0]),!n||n.hasAttribute("disabled")||n.classList.contains("disabled"))t.preventDefault();else{var o=n.querySelector('input:not([type="hidden"])');if(o&&(o.hasAttribute("disabled")||o.classList.contains("disabled")))return void t.preventDefault();"LABEL"===i.tagName&&o&&"checkbox"===o.type&&t.preventDefault(),g._jQueryInterface.call(e(n),"toggle")}})).on("focus.bs.button.data-api blur.bs.button.data-api",'[data-toggle^="button"]',(function(t){var n=e(t.target).closest(".btn")[0];e(n).toggleClass("focus",/^focus(in)?$/.test(t.type))})),e(window).on("load.bs.button.data-api",(function(){for(var t=[].slice.call(document.querySelectorAll('[data-toggle="buttons"] .btn')),e=0,n=t.length;e<n;e++){var i=t[e],o=i.querySelector('input:not([type="hidden"])');o.checked||o.hasAttribute("checked")?i.classList.add("active"):i.classList.remove("active")}for(var s=0,r=(t=[].slice.call(document.querySelectorAll('[data-toggle="button"]'))).length;s<r;s++){var a=t[s];"true"===a.getAttribute("aria-pressed")?a.classList.add("active"):a.classList.remove("active")}})),e.fn.button=g._jQueryInterface,e.fn.button.Constructor=g,e.fn.button.noConflict=function(){return e.fn.button=f,g._jQueryInterface};var m="carousel",p=".bs.carousel",_=e.fn[m],v={interval:5e3,keyboard:!0,slide:!1,pause:"hover",wrap:!0,touch:!0},b={interval:"(number|boolean)",keyboard:"boolean",slide:"(boolean|string)",pause:"(string|boolean)",wrap:"boolean",touch:"boolean"},y={TOUCH:"touch",PEN:"pen"},E=function(){function t(t,e){this._items=null,this._interval=null,this._activeElement=null,this._isPaused=!1,this._isSliding=!1,this.touchTimeout=null,this.touchStartX=0,this.touchDeltaX=0,this._config=this._getConfig(e),this._element=t,this._indicatorsElement=this._element.querySelector(".carousel-indicators"),this._touchSupported="ontouchstart"in document.documentElement||navigator.maxTouchPoints>0,this._pointerEvent=Boolean(window.PointerEvent||window.MSPointerEvent),this._addEventListeners()}var n=t.prototype;return n.next=function(){this._isSliding||this._slide("next")},n.nextWhenVisible=function(){!document.hidden&&e(this._element).is(":visible")&&"hidden"!==e(this._element).css("visibility")&&this.next()},n.prev=function(){this._isSliding||this._slide("prev")},n.pause=function(t){t||(this._isPaused=!0),this._element.querySelector(".carousel-item-next, .carousel-item-prev")&&(c.triggerTransitionEnd(this._element),this.cycle(!0)),clearInterval(this._interval),this._interval=null},n.cycle=function(t){t||(this._isPaused=!1),this._interval&&(clearInterval(this._interval),this._interval=null),this._config.interval&&!this._isPaused&&(this._interval=setInterval((document.visibilityState?this.nextWhenVisible:this.next).bind(this),this._config.interval))},n.to=function(t){var n=this;this._activeElement=this._element.querySelector(".active.carousel-item");var i=this._getItemIndex(this._activeElement);if(!(t>this._items.length-1||t<0))if(this._isSliding)e(this._element).one("slid.bs.carousel",(function(){return n.to(t)}));else{if(i===t)return this.pause(),void this.cycle();var o=t>i?"next":"prev";this._slide(o,this._items[t])}},n.dispose=function(){e(this._element).off(p),e.removeData(this._element,"bs.carousel"),this._items=null,this._config=null,this._element=null,this._interval=null,this._isPaused=null,this._isSliding=null,this._activeElement=null,this._indicatorsElement=null},n._getConfig=function(t){return t=a(a({},v),t),c.typeCheckConfig(m,t,b),t},n._handleSwipe=function(){var t=Math.abs(this.touchDeltaX);if(!(t<=40)){var e=t/this.touchDeltaX;this.touchDeltaX=0,e>0&&this.prev(),e<0&&this.next()}},n._addEventListeners=function(){var t=this;this._config.keyboard&&e(this._element).on("keydown.bs.carousel",(function(e){return t._keydown(e)})),"hover"===this._config.pause&&e(this._element).on("mouseenter.bs.carousel",(function(e){return t.pause(e)})).on("mouseleave.bs.carousel",(function(e){return t.cycle(e)})),this._config.touch&&this._addTouchEventListeners()},n._addTouchEventListeners=function(){var t=this;if(this._touchSupported){var n=function(e){t._pointerEvent&&y[e.originalEvent.pointerType.toUpperCase()]?t.touchStartX=e.originalEvent.clientX:t._pointerEvent||(t.touchStartX=e.originalEvent.touches[0].clientX)},i=function(e){t._pointerEvent&&y[e.originalEvent.pointerType.toUpperCase()]&&(t.touchDeltaX=e.originalEvent.clientX-t.touchStartX),t._handleSwipe(),"hover"===t._config.pause&&(t.pause(),t.touchTimeout&&clearTimeout(t.touchTimeout),t.touchTimeout=setTimeout((function(e){return t.cycle(e)}),500+t._config.interval))};e(this._element.querySelectorAll(".carousel-item img")).on("dragstart.bs.carousel",(function(t){return t.preventDefault()})),this._pointerEvent?(e(this._element).on("pointerdown.bs.carousel",(function(t){return n(t)})),e(this._element).on("pointerup.bs.carousel",(function(t){return i(t)})),this._element.classList.add("pointer-event")):(e(this._element).on("touchstart.bs.carousel",(function(t){return n(t)})),e(this._element).on("touchmove.bs.carousel",(function(e){return function(e){e.originalEvent.touches&&e.originalEvent.touches.length>1?t.touchDeltaX=0:t.touchDeltaX=e.originalEvent.touches[0].clientX-t.touchStartX}(e)})),e(this._element).on("touchend.bs.carousel",(function(t){return i(t)})))}},n._keydown=function(t){if(!/input|textarea/i.test(t.target.tagName))switch(t.which){case 37:t.preventDefault(),this.prev();break;case 39:t.preventDefault(),this.next()}},n._getItemIndex=function(t){return this._items=t&&t.parentNode?[].slice.call(t.parentNode.querySelectorAll(".carousel-item")):[],this._items.indexOf(t)},n._getItemByDirection=function(t,e){var n="next"===t,i="prev"===t,o=this._getItemIndex(e),s=this._items.length-1;if((i&&0===o||n&&o===s)&&!this._config.wrap)return e;var r=(o+("prev"===t?-1:1))%this._items.length;return-1===r?this._items[this._items.length-1]:this._items[r]},n._triggerSlideEvent=function(t,n){var i=this._getItemIndex(t),o=this._getItemIndex(this._element.querySelector(".active.carousel-item")),s=e.Event("slide.bs.carousel",{relatedTarget:t,direction:n,from:o,to:i});return e(this._element).trigger(s),s},n._setActiveIndicatorElement=function(t){if(this._indicatorsElement){var n=[].slice.call(this._indicatorsElement.querySelectorAll(".active"));e(n).removeClass("active");var i=this._indicatorsElement.children[this._getItemIndex(t)];i&&e(i).addClass("active")}},n._slide=function(t,n){var i,o,s,r=this,a=this._element.querySelector(".active.carousel-item"),l=this._getItemIndex(a),h=n||a&&this._getItemByDirection(t,a),u=this._getItemIndex(h),d=Boolean(this._interval);if("next"===t?(i="carousel-item-left",o="carousel-item-next",s="left"):(i="carousel-item-right",o="carousel-item-prev",s="right"),h&&e(h).hasClass("active"))this._isSliding=!1;else if(!this._triggerSlideEvent(h,s).isDefaultPrevented()&&a&&h){this._isSliding=!0,d&&this.pause(),this._setActiveIndicatorElement(h);var f=e.Event("slid.bs.carousel",{relatedTarget:h,direction:s,from:l,to:u});if(e(this._element).hasClass("slide")){e(h).addClass(o),c.reflow(h),e(a).addClass(i),e(h).addClass(i);var g=parseInt(h.getAttribute("data-interval"),10);g?(this._config.defaultInterval=this._config.defaultInterval||this._config.interval,this._config.interval=g):this._config.interval=this._config.defaultInterval||this._config.interval;var m=c.getTransitionDurationFromElement(a);e(a).one(c.TRANSITION_END,(function(){e(h).removeClass(i+" "+o).addClass("active"),e(a).removeClass("active "+o+" "+i),r._isSliding=!1,setTimeout((function(){return e(r._element).trigger(f)}),0)})).emulateTransitionEnd(m)}else e(a).removeClass("active"),e(h).addClass("active"),this._isSliding=!1,e(this._element).trigger(f);d&&this.cycle()}},t._jQueryInterface=function(n){return this.each((function(){var i=e(this).data("bs.carousel"),o=a(a({},v),e(this).data());"object"==typeof n&&(o=a(a({},o),n));var s="string"==typeof n?n:o.slide;if(i||(i=new t(this,o),e(this).data("bs.carousel",i)),"number"==typeof n)i.to(n);else if("string"==typeof s){if("undefined"==typeof i[s])throw new TypeError('No method named "'+s+'"');i[s]()}else o.interval&&o.ride&&(i.pause(),i.cycle())}))},t._dataApiClickHandler=function(n){var i=c.getSelectorFromElement(this);if(i){var o=e(i)[0];if(o&&e(o).hasClass("carousel")){var s=a(a({},e(o).data()),e(this).data()),r=this.getAttribute("data-slide-to");r&&(s.interval=!1),t._jQueryInterface.call(e(o),s),r&&e(o).data("bs.carousel").to(r),n.preventDefault()}}},o(t,null,[{key:"VERSION",get:function(){return"4.5.0"}},{key:"Default",get:function(){return v}}]),t}();e(document).on("click.bs.carousel.data-api","[data-slide], [data-slide-to]",E._dataApiClickHandler),e(window).on("load.bs.carousel.data-api",(function(){for(var t=[].slice.call(document.querySelectorAll('[data-ride="carousel"]')),n=0,i=t.length;n<i;n++){var o=e(t[n]);E._jQueryInterface.call(o,o.data())}})),e.fn[m]=E._jQueryInterface,e.fn[m].Constructor=E,e.fn[m].noConflict=function(){return e.fn[m]=_,E._jQueryInterface};var w="collapse",T=e.fn[w],C={toggle:!0,parent:""},S={toggle:"boolean",parent:"(string|element)"},D=function(){function t(t,e){this._isTransitioning=!1,this._element=t,this._config=this._getConfig(e),this._triggerArray=[].slice.call(document.querySelectorAll('[data-toggle="collapse"][href="#'+t.id+'"],[data-toggle="collapse"][data-target="#'+t.id+'"]'));for(var n=[].slice.call(document.querySelectorAll('[data-toggle="collapse"]')),i=0,o=n.length;i<o;i++){var s=n[i],r=c.getSelectorFromElement(s),a=[].slice.call(document.querySelectorAll(r)).filter((function(e){return e===t}));null!==r&&a.length>0&&(this._selector=r,this._triggerArray.push(s))}this._parent=this._config.parent?this._getParent():null,this._config.parent||this._addAriaAndCollapsedClass(this._element,this._triggerArray),this._config.toggle&&this.toggle()}var n=t.prototype;return n.toggle=function(){e(this._element).hasClass("show")?this.hide():this.show()},n.show=function(){var n,i,o=this;if(!this._isTransitioning&&!e(this._element).hasClass("show")&&(this._parent&&0===(n=[].slice.call(this._parent.querySelectorAll(".show, .collapsing")).filter((function(t){return"string"==typeof o._config.parent?t.getAttribute("data-parent")===o._config.parent:t.classList.contains("collapse")}))).length&&(n=null),!(n&&(i=e(n).not(this._selector).data("bs.collapse"))&&i._isTransitioning))){var s=e.Event("show.bs.collapse");if(e(this._element).trigger(s),!s.isDefaultPrevented()){n&&(t._jQueryInterface.call(e(n).not(this._selector),"hide"),i||e(n).data("bs.collapse",null));var r=this._getDimension();e(this._element).removeClass("collapse").addClass("collapsing"),this._element.style[r]=0,this._triggerArray.length&&e(this._triggerArray).removeClass("collapsed").attr("aria-expanded",!0),this.setTransitioning(!0);var a="scroll"+(r[0].toUpperCase()+r.slice(1)),l=c.getTransitionDurationFromElement(this._element);e(this._element).one(c.TRANSITION_END,(function(){e(o._element).removeClass("collapsing").addClass("collapse show"),o._element.style[r]="",o.setTransitioning(!1),e(o._element).trigger("shown.bs.collapse")})).emulateTransitionEnd(l),this._element.style[r]=this._element[a]+"px"}}},n.hide=function(){var t=this;if(!this._isTransitioning&&e(this._element).hasClass("show")){var n=e.Event("hide.bs.collapse");if(e(this._element).trigger(n),!n.isDefaultPrevented()){var i=this._getDimension();this._element.style[i]=this._element.getBoundingClientRect()[i]+"px",c.reflow(this._element),e(this._element).addClass("collapsing").removeClass("collapse show");var o=this._triggerArray.length;if(o>0)for(var s=0;s<o;s++){var r=this._triggerArray[s],a=c.getSelectorFromElement(r);if(null!==a)e([].slice.call(document.querySelectorAll(a))).hasClass("show")||e(r).addClass("collapsed").attr("aria-expanded",!1)}this.setTransitioning(!0);this._element.style[i]="";var l=c.getTransitionDurationFromElement(this._element);e(this._element).one(c.TRANSITION_END,(function(){t.setTransitioning(!1),e(t._element).removeClass("collapsing").addClass("collapse").trigger("hidden.bs.collapse")})).emulateTransitionEnd(l)}}},n.setTransitioning=function(t){this._isTransitioning=t},n.dispose=function(){e.removeData(this._element,"bs.collapse"),this._config=null,this._parent=null,this._element=null,this._triggerArray=null,this._isTransitioning=null},n._getConfig=function(t){return(t=a(a({},C),t)).toggle=Boolean(t.toggle),c.typeCheckConfig(w,t,S),t},n._getDimension=function(){return e(this._element).hasClass("width")?"width":"height"},n._getParent=function(){var n,i=this;c.isElement(this._config.parent)?(n=this._config.parent,"undefined"!=typeof this._config.parent.jquery&&(n=this._config.parent[0])):n=document.querySelector(this._config.parent);var o='[data-toggle="collapse"][data-parent="'+this._config.parent+'"]',s=[].slice.call(n.querySelectorAll(o));return e(s).each((function(e,n){i._addAriaAndCollapsedClass(t._getTargetFromElement(n),[n])})),n},n._addAriaAndCollapsedClass=function(t,n){var i=e(t).hasClass("show");n.length&&e(n).toggleClass("collapsed",!i).attr("aria-expanded",i)},t._getTargetFromElement=function(t){var e=c.getSelectorFromElement(t);return e?document.querySelector(e):null},t._jQueryInterface=function(n){return this.each((function(){var i=e(this),o=i.data("bs.collapse"),s=a(a(a({},C),i.data()),"object"==typeof n&&n?n:{});if(!o&&s.toggle&&"string"==typeof n&&/show|hide/.test(n)&&(s.toggle=!1),o||(o=new t(this,s),i.data("bs.collapse",o)),"string"==typeof n){if("undefined"==typeof o[n])throw new TypeError('No method named "'+n+'"');o[n]()}}))},o(t,null,[{key:"VERSION",get:function(){return"4.5.0"}},{key:"Default",get:function(){return C}}]),t}();e(document).on("click.bs.collapse.data-api",'[data-toggle="collapse"]',(function(t){"A"===t.currentTarget.tagName&&t.preventDefault();var n=e(this),i=c.getSelectorFromElement(this),o=[].slice.call(document.querySelectorAll(i));e(o).each((function(){var t=e(this),i=t.data("bs.collapse")?"toggle":n.data();D._jQueryInterface.call(t,i)}))})),e.fn[w]=D._jQueryInterface,e.fn[w].Constructor=D,e.fn[w].noConflict=function(){return e.fn[w]=T,D._jQueryInterface};var k="dropdown",N=e.fn[k],A=new RegExp("38|40|27"),I={offset:0,flip:!0,boundary:"scrollParent",reference:"toggle",display:"dynamic",popperConfig:null},O={offset:"(number|string|function)",flip:"boolean",boundary:"(string|element)",reference:"(string|element)",display:"string",popperConfig:"(null|object)"},j=function(){function t(t,e){this._element=t,this._popper=null,this._config=this._getConfig(e),this._menu=this._getMenuElement(),this._inNavbar=this._detectNavbar(),this._addEventListeners()}var i=t.prototype;return i.toggle=function(){if(!this._element.disabled&&!e(this._element).hasClass("disabled")){var n=e(this._menu).hasClass("show");t._clearMenus(),n||this.show(!0)}},i.show=function(i){if(void 0===i&&(i=!1),!(this._element.disabled||e(this._element).hasClass("disabled")||e(this._menu).hasClass("show"))){var o={relatedTarget:this._element},s=e.Event("show.bs.dropdown",o),r=t._getParentFromElement(this._element);if(e(r).trigger(s),!s.isDefaultPrevented()){if(!this._inNavbar&&i){if("undefined"==typeof n)throw new TypeError("Bootstrap's dropdowns require Popper.js (https://popper.js.org/)");var a=this._element;"parent"===this._config.reference?a=r:c.isElement(this._config.reference)&&(a=this._config.reference,"undefined"!=typeof this._config.reference.jquery&&(a=this._config.reference[0])),"scrollParent"!==this._config.boundary&&e(r).addClass("position-static"),this._popper=new n(a,this._menu,this._getPopperConfig())}"ontouchstart"in document.documentElement&&0===e(r).closest(".navbar-nav").length&&e(document.body).children().on("mouseover",null,e.noop),this._element.focus(),this._element.setAttribute("aria-expanded",!0),e(this._menu).toggleClass("show"),e(r).toggleClass("show").trigger(e.Event("shown.bs.dropdown",o))}}},i.hide=function(){if(!this._element.disabled&&!e(this._element).hasClass("disabled")&&e(this._menu).hasClass("show")){var n={relatedTarget:this._element},i=e.Event("hide.bs.dropdown",n),o=t._getParentFromElement(this._element);e(o).trigger(i),i.isDefaultPrevented()||(this._popper&&this._popper.destroy(),e(this._menu).toggleClass("show"),e(o).toggleClass("show").trigger(e.Event("hidden.bs.dropdown",n)))}},i.dispose=function(){e.removeData(this._element,"bs.dropdown"),e(this._element).off(".bs.dropdown"),this._element=null,this._menu=null,null!==this._popper&&(this._popper.destroy(),this._popper=null)},i.update=function(){this._inNavbar=this._detectNavbar(),null!==this._popper&&this._popper.scheduleUpdate()},i._addEventListeners=function(){var t=this;e(this._element).on("click.bs.dropdown",(function(e){e.preventDefault(),e.stopPropagation(),t.toggle()}))},i._getConfig=function(t){return t=a(a(a({},this.constructor.Default),e(this._element).data()),t),c.typeCheckConfig(k,t,this.constructor.DefaultType),t},i._getMenuElement=function(){if(!this._menu){var e=t._getParentFromElement(this._element);e&&(this._menu=e.querySelector(".dropdown-menu"))}return this._menu},i._getPlacement=function(){var t=e(this._element.parentNode),n="bottom-start";return t.hasClass("dropup")?n=e(this._menu).hasClass("dropdown-menu-right")?"top-end":"top-start":t.hasClass("dropright")?n="right-start":t.hasClass("dropleft")?n="left-start":e(this._menu).hasClass("dropdown-menu-right")&&(n="bottom-end"),n},i._detectNavbar=function(){return e(this._element).closest(".navbar").length>0},i._getOffset=function(){var t=this,e={};return"function"==typeof this._config.offset?e.fn=function(e){return e.offsets=a(a({},e.offsets),t._config.offset(e.offsets,t._element)||{}),e}:e.offset=this._config.offset,e},i._getPopperConfig=function(){var t={placement:this._getPlacement(),modifiers:{offset:this._getOffset(),flip:{enabled:this._config.flip},preventOverflow:{boundariesElement:this._config.boundary}}};return"static"===this._config.display&&(t.modifiers.applyStyle={enabled:!1}),a(a({},t),this._config.popperConfig)},t._jQueryInterface=function(n){return this.each((function(){var i=e(this).data("bs.dropdown");if(i||(i=new t(this,"object"==typeof n?n:null),e(this).data("bs.dropdown",i)),"string"==typeof n){if("undefined"==typeof i[n])throw new TypeError('No method named "'+n+'"');i[n]()}}))},t._clearMenus=function(n){if(!n||3!==n.which&&("keyup"!==n.type||9===n.which))for(var i=[].slice.call(document.querySelectorAll('[data-toggle="dropdown"]')),o=0,s=i.length;o<s;o++){var r=t._getParentFromElement(i[o]),a=e(i[o]).data("bs.dropdown"),l={relatedTarget:i[o]};if(n&&"click"===n.type&&(l.clickEvent=n),a){var c=a._menu;if(e(r).hasClass("show")&&!(n&&("click"===n.type&&/input|textarea/i.test(n.target.tagName)||"keyup"===n.type&&9===n.which)&&e.contains(r,n.target))){var h=e.Event("hide.bs.dropdown",l);e(r).trigger(h),h.isDefaultPrevented()||("ontouchstart"in document.documentElement&&e(document.body).children().off("mouseover",null,e.noop),i[o].setAttribute("aria-expanded","false"),a._popper&&a._popper.destroy(),e(c).removeClass("show"),e(r).removeClass("show").trigger(e.Event("hidden.bs.dropdown",l)))}}}},t._getParentFromElement=function(t){var e,n=c.getSelectorFromElement(t);return n&&(e=document.querySelector(n)),e||t.parentNode},t._dataApiKeydownHandler=function(n){if(!(/input|textarea/i.test(n.target.tagName)?32===n.which||27!==n.which&&(40!==n.which&&38!==n.which||e(n.target).closest(".dropdown-menu").length):!A.test(n.which))&&!this.disabled&&!e(this).hasClass("disabled")){var i=t._getParentFromElement(this),o=e(i).hasClass("show");if(o||27!==n.which){if(n.preventDefault(),n.stopPropagation(),!o||o&&(27===n.which||32===n.which))return 27===n.which&&e(i.querySelector('[data-toggle="dropdown"]')).trigger("focus"),void e(this).trigger("click");var s=[].slice.call(i.querySelectorAll(".dropdown-menu .dropdown-item:not(.disabled):not(:disabled)")).filter((function(t){return e(t).is(":visible")}));if(0!==s.length){var r=s.indexOf(n.target);38===n.which&&r>0&&r--,40===n.which&&r<s.length-1&&r++,r<0&&(r=0),s[r].focus()}}}},o(t,null,[{key:"VERSION",get:function(){return"4.5.0"}},{key:"Default",get:function(){return I}},{key:"DefaultType",get:function(){return O}}]),t}();e(document).on("keydown.bs.dropdown.data-api",'[data-toggle="dropdown"]',j._dataApiKeydownHandler).on("keydown.bs.dropdown.data-api",".dropdown-menu",j._dataApiKeydownHandler).on("click.bs.dropdown.data-api keyup.bs.dropdown.data-api",j._clearMenus).on("click.bs.dropdown.data-api",'[data-toggle="dropdown"]',(function(t){t.preventDefault(),t.stopPropagation(),j._jQueryInterface.call(e(this),"toggle")})).on("click.bs.dropdown.data-api",".dropdown form",(function(t){t.stopPropagation()})),e.fn[k]=j._jQueryInterface,e.fn[k].Constructor=j,e.fn[k].noConflict=function(){return e.fn[k]=N,j._jQueryInterface};var P=e.fn.modal,x={backdrop:!0,keyboard:!0,focus:!0,show:!0},L={backdrop:"(boolean|string)",keyboard:"boolean",focus:"boolean",show:"boolean"},R=function(){function t(t,e){this._config=this._getConfig(e),this._element=t,this._dialog=t.querySelector(".modal-dialog"),this._backdrop=null,this._isShown=!1,this._isBodyOverflowing=!1,this._ignoreBackdropClick=!1,this._isTransitioning=!1,this._scrollbarWidth=0}var n=t.prototype;return n.toggle=function(t){return this._isShown?this.hide():this.show(t)},n.show=function(t){var n=this;if(!this._isShown&&!this._isTransitioning){e(this._element).hasClass("fade")&&(this._isTransitioning=!0);var i=e.Event("show.bs.modal",{relatedTarget:t});e(this._element).trigger(i),this._isShown||i.isDefaultPrevented()||(this._isShown=!0,this._checkScrollbar(),this._setScrollbar(),this._adjustDialog(),this._setEscapeEvent(),this._setResizeEvent(),e(this._element).on("click.dismiss.bs.modal",'[data-dismiss="modal"]',(function(t){return n.hide(t)})),e(this._dialog).on("mousedown.dismiss.bs.modal",(function(){e(n._element).one("mouseup.dismiss.bs.modal",(function(t){e(t.target).is(n._element)&&(n._ignoreBackdropClick=!0)}))})),this._showBackdrop((function(){return n._showElement(t)})))}},n.hide=function(t){var n=this;if(t&&t.preventDefault(),this._isShown&&!this._isTransitioning){var i=e.Event("hide.bs.modal");if(e(this._element).trigger(i),this._isShown&&!i.isDefaultPrevented()){this._isShown=!1;var o=e(this._element).hasClass("fade");if(o&&(this._isTransitioning=!0),this._setEscapeEvent(),this._setResizeEvent(),e(document).off("focusin.bs.modal"),e(this._element).removeClass("show"),e(this._element).off("click.dismiss.bs.modal"),e(this._dialog).off("mousedown.dismiss.bs.modal"),o){var s=c.getTransitionDurationFromElement(this._element);e(this._element).one(c.TRANSITION_END,(function(t){return n._hideModal(t)})).emulateTransitionEnd(s)}else this._hideModal()}}},n.dispose=function(){[window,this._element,this._dialog].forEach((function(t){return e(t).off(".bs.modal")})),e(document).off("focusin.bs.modal"),e.removeData(this._element,"bs.modal"),this._config=null,this._element=null,this._dialog=null,this._backdrop=null,this._isShown=null,this._isBodyOverflowing=null,this._ignoreBackdropClick=null,this._isTransitioning=null,this._scrollbarWidth=null},n.handleUpdate=function(){this._adjustDialog()},n._getConfig=function(t){return t=a(a({},x),t),c.typeCheckConfig("modal",t,L),t},n._triggerBackdropTransition=function(){var t=this;if("static"===this._config.backdrop){var n=e.Event("hidePrevented.bs.modal");if(e(this._element).trigger(n),n.defaultPrevented)return;this._element.classList.add("modal-static");var i=c.getTransitionDurationFromElement(this._element);e(this._element).one(c.TRANSITION_END,(function(){t._element.classList.remove("modal-static")})).emulateTransitionEnd(i),this._element.focus()}else this.hide()},n._showElement=function(t){var n=this,i=e(this._element).hasClass("fade"),o=this._dialog?this._dialog.querySelector(".modal-body"):null;this._element.parentNode&&this._element.parentNode.nodeType===Node.ELEMENT_NODE||document.body.appendChild(this._element),this._element.style.display="block",this._element.removeAttribute("aria-hidden"),this._element.setAttribute("aria-modal",!0),e(this._dialog).hasClass("modal-dialog-scrollable")&&o?o.scrollTop=0:this._element.scrollTop=0,i&&c.reflow(this._element),e(this._element).addClass("show"),this._config.focus&&this._enforceFocus();var s=e.Event("shown.bs.modal",{relatedTarget:t}),r=function(){n._config.focus&&n._element.focus(),n._isTransitioning=!1,e(n._element).trigger(s)};if(i){var a=c.getTransitionDurationFromElement(this._dialog);e(this._dialog).one(c.TRANSITION_END,r).emulateTransitionEnd(a)}else r()},n._enforceFocus=function(){var t=this;e(document).off("focusin.bs.modal").on("focusin.bs.modal",(function(n){document!==n.target&&t._element!==n.target&&0===e(t._element).has(n.target).length&&t._element.focus()}))},n._setEscapeEvent=function(){var t=this;this._isShown?e(this._element).on("keydown.dismiss.bs.modal",(function(e){t._config.keyboard&&27===e.which?(e.preventDefault(),t.hide()):t._config.keyboard||27!==e.which||t._triggerBackdropTransition()})):this._isShown||e(this._element).off("keydown.dismiss.bs.modal")},n._setResizeEvent=function(){var t=this;this._isShown?e(window).on("resize.bs.modal",(function(e){return t.handleUpdate(e)})):e(window).off("resize.bs.modal")},n._hideModal=function(){var t=this;this._element.style.display="none",this._element.setAttribute("aria-hidden",!0),this._element.removeAttribute("aria-modal"),this._isTransitioning=!1,this._showBackdrop((function(){e(document.body).removeClass("modal-open"),t._resetAdjustments(),t._resetScrollbar(),e(t._element).trigger("hidden.bs.modal")}))},n._removeBackdrop=function(){this._backdrop&&(e(this._backdrop).remove(),this._backdrop=null)},n._showBackdrop=function(t){var n=this,i=e(this._element).hasClass("fade")?"fade":"";if(this._isShown&&this._config.backdrop){if(this._backdrop=document.createElement("div"),this._backdrop.className="modal-backdrop",i&&this._backdrop.classList.add(i),e(this._backdrop).appendTo(document.body),e(this._element).on("click.dismiss.bs.modal",(function(t){n._ignoreBackdropClick?n._ignoreBackdropClick=!1:t.target===t.currentTarget&&n._triggerBackdropTransition()})),i&&c.reflow(this._backdrop),e(this._backdrop).addClass("show"),!t)return;if(!i)return void t();var o=c.getTransitionDurationFromElement(this._backdrop);e(this._backdrop).one(c.TRANSITION_END,t).emulateTransitionEnd(o)}else if(!this._isShown&&this._backdrop){e(this._backdrop).removeClass("show");var s=function(){n._removeBackdrop(),t&&t()};if(e(this._element).hasClass("fade")){var r=c.getTransitionDurationFromElement(this._backdrop);e(this._backdrop).one(c.TRANSITION_END,s).emulateTransitionEnd(r)}else s()}else t&&t()},n._adjustDialog=function(){var t=this._element.scrollHeight>document.documentElement.clientHeight;!this._isBodyOverflowing&&t&&(this._element.style.paddingLeft=this._scrollbarWidth+"px"),this._isBodyOverflowing&&!t&&(this._element.style.paddingRight=this._scrollbarWidth+"px")},n._resetAdjustments=function(){this._element.style.paddingLeft="",this._element.style.paddingRight=""},n._checkScrollbar=function(){var t=document.body.getBoundingClientRect();this._isBodyOverflowing=Math.round(t.left+t.right)<window.innerWidth,this._scrollbarWidth=this._getScrollbarWidth()},n._setScrollbar=function(){var t=this;if(this._isBodyOverflowing){var n=[].slice.call(document.querySelectorAll(".fixed-top, .fixed-bottom, .is-fixed, .sticky-top")),i=[].slice.call(document.querySelectorAll(".sticky-top"));e(n).each((function(n,i){var o=i.style.paddingRight,s=e(i).css("padding-right");e(i).data("padding-right",o).css("padding-right",parseFloat(s)+t._scrollbarWidth+"px")})),e(i).each((function(n,i){var o=i.style.marginRight,s=e(i).css("margin-right");e(i).data("margin-right",o).css("margin-right",parseFloat(s)-t._scrollbarWidth+"px")}));var o=document.body.style.paddingRight,s=e(document.body).css("padding-right");e(document.body).data("padding-right",o).css("padding-right",parseFloat(s)+this._scrollbarWidth+"px")}e(document.body).addClass("modal-open")},n._resetScrollbar=function(){var t=[].slice.call(document.querySelectorAll(".fixed-top, .fixed-bottom, .is-fixed, .sticky-top"));e(t).each((function(t,n){var i=e(n).data("padding-right");e(n).removeData("padding-right"),n.style.paddingRight=i||""}));var n=[].slice.call(document.querySelectorAll(".sticky-top"));e(n).each((function(t,n){var i=e(n).data("margin-right");"undefined"!=typeof i&&e(n).css("margin-right",i).removeData("margin-right")}));var i=e(document.body).data("padding-right");e(document.body).removeData("padding-right"),document.body.style.paddingRight=i||""},n._getScrollbarWidth=function(){var t=document.createElement("div");t.className="modal-scrollbar-measure",document.body.appendChild(t);var e=t.getBoundingClientRect().width-t.clientWidth;return document.body.removeChild(t),e},t._jQueryInterface=function(n,i){return this.each((function(){var o=e(this).data("bs.modal"),s=a(a(a({},x),e(this).data()),"object"==typeof n&&n?n:{});if(o||(o=new t(this,s),e(this).data("bs.modal",o)),"string"==typeof n){if("undefined"==typeof o[n])throw new TypeError('No method named "'+n+'"');o[n](i)}else s.show&&o.show(i)}))},o(t,null,[{key:"VERSION",get:function(){return"4.5.0"}},{key:"Default",get:function(){return x}}]),t}();e(document).on("click.bs.modal.data-api",'[data-toggle="modal"]',(function(t){var n,i=this,o=c.getSelectorFromElement(this);o&&(n=document.querySelector(o));var s=e(n).data("bs.modal")?"toggle":a(a({},e(n).data()),e(this).data());"A"!==this.tagName&&"AREA"!==this.tagName||t.preventDefault();var r=e(n).one("show.bs.modal",(function(t){t.isDefaultPrevented()||r.one("hidden.bs.modal",(function(){e(i).is(":visible")&&i.focus()}))}));R._jQueryInterface.call(e(n),s,this)})),e.fn.modal=R._jQueryInterface,e.fn.modal.Constructor=R,e.fn.modal.noConflict=function(){return e.fn.modal=P,R._jQueryInterface};var q=["background","cite","href","itemtype","longdesc","poster","src","xlink:href"],F={"*":["class","dir","id","lang","role",/^aria-[\w-]*$/i],a:["target","href","title","rel"],area:[],b:[],br:[],col:[],code:[],div:[],em:[],hr:[],h1:[],h2:[],h3:[],h4:[],h5:[],h6:[],i:[],img:["src","srcset","alt","title","width","height"],li:[],ol:[],p:[],pre:[],s:[],small:[],span:[],sub:[],sup:[],strong:[],u:[],ul:[]},Q=/^(?:(?:https?|mailto|ftp|tel|file):|[^#&/:?]*(?:[#/?]|$))/gi,B=/^data:(?:image\/(?:bmp|gif|jpeg|jpg|png|tiff|webp)|video\/(?:mpeg|mp4|ogg|webm)|audio\/(?:mp3|oga|ogg|opus));base64,[\d+/a-z]+=*$/i;function H(t,e,n){if(0===t.length)return t;if(n&&"function"==typeof n)return n(t);for(var i=(new window.DOMParser).parseFromString(t,"text/html"),o=Object.keys(e),s=[].slice.call(i.body.querySelectorAll("*")),r=function(t,n){var i=s[t],r=i.nodeName.toLowerCase();if(-1===o.indexOf(i.nodeName.toLowerCase()))return i.parentNode.removeChild(i),"continue";var a=[].slice.call(i.attributes),l=[].concat(e["*"]||[],e[r]||[]);a.forEach((function(t){(function(t,e){var n=t.nodeName.toLowerCase();if(-1!==e.indexOf(n))return-1===q.indexOf(n)||Boolean(t.nodeValue.match(Q)||t.nodeValue.match(B));for(var i=e.filter((function(t){return t instanceof RegExp})),o=0,s=i.length;o<s;o++)if(n.match(i[o]))return!0;return!1})(t,l)||i.removeAttribute(t.nodeName)}))},a=0,l=s.length;a<l;a++)r(a);return i.body.innerHTML}var U="tooltip",M=e.fn[U],W=new RegExp("(^|\\s)bs-tooltip\\S+","g"),V=["sanitize","whiteList","sanitizeFn"],z={animation:"boolean",template:"string",title:"(string|element|function)",trigger:"string",delay:"(number|object)",html:"boolean",selector:"(string|boolean)",placement:"(string|function)",offset:"(number|string|function)",container:"(string|element|boolean)",fallbackPlacement:"(string|array)",boundary:"(string|element)",sanitize:"boolean",sanitizeFn:"(null|function)",whiteList:"object",popperConfig:"(null|object)"},K={AUTO:"auto",TOP:"top",RIGHT:"right",BOTTOM:"bottom",LEFT:"left"},X={animation:!0,template:'<div class="tooltip" role="tooltip"><div class="arrow"></div><div class="tooltip-inner"></div></div>',trigger:"hover focus",title:"",delay:0,html:!1,selector:!1,placement:"top",offset:0,container:!1,fallbackPlacement:"flip",boundary:"scrollParent",sanitize:!0,sanitizeFn:null,whiteList:F,popperConfig:null},Y={HIDE:"hide.bs.tooltip",HIDDEN:"hidden.bs.tooltip",SHOW:"show.bs.tooltip",SHOWN:"shown.bs.tooltip",INSERTED:"inserted.bs.tooltip",CLICK:"click.bs.tooltip",FOCUSIN:"focusin.bs.tooltip",FOCUSOUT:"focusout.bs.tooltip",MOUSEENTER:"mouseenter.bs.tooltip",MOUSELEAVE:"mouseleave.bs.tooltip"},$=function(){function t(t,e){if("undefined"==typeof n)throw new TypeError("Bootstrap's tooltips require Popper.js (https://popper.js.org/)");this._isEnabled=!0,this._timeout=0,this._hoverState="",this._activeTrigger={},this._popper=null,this.element=t,this.config=this._getConfig(e),this.tip=null,this._setListeners()}var i=t.prototype;return i.enable=function(){this._isEnabled=!0},i.disable=function(){this._isEnabled=!1},i.toggleEnabled=function(){this._isEnabled=!this._isEnabled},i.toggle=function(t){if(this._isEnabled)if(t){var n=this.constructor.DATA_KEY,i=e(t.currentTarget).data(n);i||(i=new this.constructor(t.currentTarget,this._getDelegateConfig()),e(t.currentTarget).data(n,i)),i._activeTrigger.click=!i._activeTrigger.click,i._isWithActiveTrigger()?i._enter(null,i):i._leave(null,i)}else{if(e(this.getTipElement()).hasClass("show"))return void this._leave(null,this);this._enter(null,this)}},i.dispose=function(){clearTimeout(this._timeout),e.removeData(this.element,this.constructor.DATA_KEY),e(this.element).off(this.constructor.EVENT_KEY),e(this.element).closest(".modal").off("hide.bs.modal",this._hideModalHandler),this.tip&&e(this.tip).remove(),this._isEnabled=null,this._timeout=null,this._hoverState=null,this._activeTrigger=null,this._popper&&this._popper.destroy(),this._popper=null,this.element=null,this.config=null,this.tip=null},i.show=function(){var t=this;if("none"===e(this.element).css("display"))throw new Error("Please use show on visible elements");var i=e.Event(this.constructor.Event.SHOW);if(this.isWithContent()&&this._isEnabled){e(this.element).trigger(i);var o=c.findShadowRoot(this.element),s=e.contains(null!==o?o:this.element.ownerDocument.documentElement,this.element);if(i.isDefaultPrevented()||!s)return;var r=this.getTipElement(),a=c.getUID(this.constructor.NAME);r.setAttribute("id",a),this.element.setAttribute("aria-describedby",a),this.setContent(),this.config.animation&&e(r).addClass("fade");var l="function"==typeof this.config.placement?this.config.placement.call(this,r,this.element):this.config.placement,h=this._getAttachment(l);this.addAttachmentClass(h);var u=this._getContainer();e(r).data(this.constructor.DATA_KEY,this),e.contains(this.element.ownerDocument.documentElement,this.tip)||e(r).appendTo(u),e(this.element).trigger(this.constructor.Event.INSERTED),this._popper=new n(this.element,r,this._getPopperConfig(h)),e(r).addClass("show"),"ontouchstart"in document.documentElement&&e(document.body).children().on("mouseover",null,e.noop);var d=function(){t.config.animation&&t._fixTransition();var n=t._hoverState;t._hoverState=null,e(t.element).trigger(t.constructor.Event.SHOWN),"out"===n&&t._leave(null,t)};if(e(this.tip).hasClass("fade")){var f=c.getTransitionDurationFromElement(this.tip);e(this.tip).one(c.TRANSITION_END,d).emulateTransitionEnd(f)}else d()}},i.hide=function(t){var n=this,i=this.getTipElement(),o=e.Event(this.constructor.Event.HIDE),s=function(){"show"!==n._hoverState&&i.parentNode&&i.parentNode.removeChild(i),n._cleanTipClass(),n.element.removeAttribute("aria-describedby"),e(n.element).trigger(n.constructor.Event.HIDDEN),null!==n._popper&&n._popper.destroy(),t&&t()};if(e(this.element).trigger(o),!o.isDefaultPrevented()){if(e(i).removeClass("show"),"ontouchstart"in document.documentElement&&e(document.body).children().off("mouseover",null,e.noop),this._activeTrigger.click=!1,this._activeTrigger.focus=!1,this._activeTrigger.hover=!1,e(this.tip).hasClass("fade")){var r=c.getTransitionDurationFromElement(i);e(i).one(c.TRANSITION_END,s).emulateTransitionEnd(r)}else s();this._hoverState=""}},i.update=function(){null!==this._popper&&this._popper.scheduleUpdate()},i.isWithContent=function(){return Boolean(this.getTitle())},i.addAttachmentClass=function(t){e(this.getTipElement()).addClass("bs-tooltip-"+t)},i.getTipElement=function(){return this.tip=this.tip||e(this.config.template)[0],this.tip},i.setContent=function(){var t=this.getTipElement();this.setElementContent(e(t.querySelectorAll(".tooltip-inner")),this.getTitle()),e(t).removeClass("fade show")},i.setElementContent=function(t,n){"object"!=typeof n||!n.nodeType&&!n.jquery?this.config.html?(this.config.sanitize&&(n=H(n,this.config.whiteList,this.config.sanitizeFn)),t.html(n)):t.text(n):this.config.html?e(n).parent().is(t)||t.empty().append(n):t.text(e(n).text())},i.getTitle=function(){var t=this.element.getAttribute("data-original-title");return t||(t="function"==typeof this.config.title?this.config.title.call(this.element):this.config.title),t},i._getPopperConfig=function(t){var e=this;return a(a({},{placement:t,modifiers:{offset:this._getOffset(),flip:{behavior:this.config.fallbackPlacement},arrow:{element:".arrow"},preventOverflow:{boundariesElement:this.config.boundary}},onCreate:function(t){t.originalPlacement!==t.placement&&e._handlePopperPlacementChange(t)},onUpdate:function(t){return e._handlePopperPlacementChange(t)}}),this.config.popperConfig)},i._getOffset=function(){var t=this,e={};return"function"==typeof this.config.offset?e.fn=function(e){return e.offsets=a(a({},e.offsets),t.config.offset(e.offsets,t.element)||{}),e}:e.offset=this.config.offset,e},i._getContainer=function(){return!1===this.config.container?document.body:c.isElement(this.config.container)?e(this.config.container):e(document).find(this.config.container)},i._getAttachment=function(t){return K[t.toUpperCase()]},i._setListeners=function(){var t=this;this.config.trigger.split(" ").forEach((function(n){if("click"===n)e(t.element).on(t.constructor.Event.CLICK,t.config.selector,(function(e){return t.toggle(e)}));else if("manual"!==n){var i="hover"===n?t.constructor.Event.MOUSEENTER:t.constructor.Event.FOCUSIN,o="hover"===n?t.constructor.Event.MOUSELEAVE:t.constructor.Event.FOCUSOUT;e(t.element).on(i,t.config.selector,(function(e){return t._enter(e)})).on(o,t.config.selector,(function(e){return t._leave(e)}))}})),this._hideModalHandler=function(){t.element&&t.hide()},e(this.element).closest(".modal").on("hide.bs.modal",this._hideModalHandler),this.config.selector?this.config=a(a({},this.config),{},{trigger:"manual",selector:""}):this._fixTitle()},i._fixTitle=function(){var t=typeof this.element.getAttribute("data-original-title");(this.element.getAttribute("title")||"string"!==t)&&(this.element.setAttribute("data-original-title",this.element.getAttribute("title")||""),this.element.setAttribute("title",""))},i._enter=function(t,n){var i=this.constructor.DATA_KEY;(n=n||e(t.currentTarget).data(i))||(n=new this.constructor(t.currentTarget,this._getDelegateConfig()),e(t.currentTarget).data(i,n)),t&&(n._activeTrigger["focusin"===t.type?"focus":"hover"]=!0),e(n.getTipElement()).hasClass("show")||"show"===n._hoverState?n._hoverState="show":(clearTimeout(n._timeout),n._hoverState="show",n.config.delay&&n.config.delay.show?n._timeout=setTimeout((function(){"show"===n._hoverState&&n.show()}),n.config.delay.show):n.show())},i._leave=function(t,n){var i=this.constructor.DATA_KEY;(n=n||e(t.currentTarget).data(i))||(n=new this.constructor(t.currentTarget,this._getDelegateConfig()),e(t.currentTarget).data(i,n)),t&&(n._activeTrigger["focusout"===t.type?"focus":"hover"]=!1),n._isWithActiveTrigger()||(clearTimeout(n._timeout),n._hoverState="out",n.config.delay&&n.config.delay.hide?n._timeout=setTimeout((function(){"out"===n._hoverState&&n.hide()}),n.config.delay.hide):n.hide())},i._isWithActiveTrigger=function(){for(var t in this._activeTrigger)if(this._activeTrigger[t])return!0;return!1},i._getConfig=function(t){var n=e(this.element).data();return Object.keys(n).forEach((function(t){-1!==V.indexOf(t)&&delete n[t]})),"number"==typeof(t=a(a(a({},this.constructor.Default),n),"object"==typeof t&&t?t:{})).delay&&(t.delay={show:t.delay,hide:t.delay}),"number"==typeof t.title&&(t.title=t.title.toString()),"number"==typeof t.content&&(t.content=t.content.toString()),c.typeCheckConfig(U,t,this.constructor.DefaultType),t.sanitize&&(t.template=H(t.template,t.whiteList,t.sanitizeFn)),t},i._getDelegateConfig=function(){var t={};if(this.config)for(var e in this.config)this.constructor.Default[e]!==this.config[e]&&(t[e]=this.config[e]);return t},i._cleanTipClass=function(){var t=e(this.getTipElement()),n=t.attr("class").match(W);null!==n&&n.length&&t.removeClass(n.join(""))},i._handlePopperPlacementChange=function(t){this.tip=t.instance.popper,this._cleanTipClass(),this.addAttachmentClass(this._getAttachment(t.placement))},i._fixTransition=function(){var t=this.getTipElement(),n=this.config.animation;null===t.getAttribute("x-placement")&&(e(t).removeClass("fade"),this.config.animation=!1,this.hide(),this.show(),this.config.animation=n)},t._jQueryInterface=function(n){return this.each((function(){var i=e(this).data("bs.tooltip"),o="object"==typeof n&&n;if((i||!/dispose|hide/.test(n))&&(i||(i=new t(this,o),e(this).data("bs.tooltip",i)),"string"==typeof n)){if("undefined"==typeof i[n])throw new TypeError('No method named "'+n+'"');i[n]()}}))},o(t,null,[{key:"VERSION",get:function(){return"4.5.0"}},{key:"Default",get:function(){return X}},{key:"NAME",get:function(){return U}},{key:"DATA_KEY",get:function(){return"bs.tooltip"}},{key:"Event",get:function(){return Y}},{key:"EVENT_KEY",get:function(){return".bs.tooltip"}},{key:"DefaultType",get:function(){return z}}]),t}();e.fn[U]=$._jQueryInterface,e.fn[U].Constructor=$,e.fn[U].noConflict=function(){return e.fn[U]=M,$._jQueryInterface};var J="popover",G=e.fn[J],Z=new RegExp("(^|\\s)bs-popover\\S+","g"),tt=a(a({},$.Default),{},{placement:"right",trigger:"click",content:"",template:'<div class="popover" role="tooltip"><div class="arrow"></div><h3 class="popover-header"></h3><div class="popover-body"></div></div>'}),et=a(a({},$.DefaultType),{},{content:"(string|element|function)"}),nt={HIDE:"hide.bs.popover",HIDDEN:"hidden.bs.popover",SHOW:"show.bs.popover",SHOWN:"shown.bs.popover",INSERTED:"inserted.bs.popover",CLICK:"click.bs.popover",FOCUSIN:"focusin.bs.popover",FOCUSOUT:"focusout.bs.popover",MOUSEENTER:"mouseenter.bs.popover",MOUSELEAVE:"mouseleave.bs.popover"},it=function(t){var n,i;function s(){return t.apply(this,arguments)||this}i=t,(n=s).prototype=Object.create(i.prototype),n.prototype.constructor=n,n.__proto__=i;var r=s.prototype;return r.isWithContent=function(){return this.getTitle()||this._getContent()},r.addAttachmentClass=function(t){e(this.getTipElement()).addClass("bs-popover-"+t)},r.getTipElement=function(){return this.tip=this.tip||e(this.config.template)[0],this.tip},r.setContent=function(){var t=e(this.getTipElement());this.setElementContent(t.find(".popover-header"),this.getTitle());var n=this._getContent();"function"==typeof n&&(n=n.call(this.element)),this.setElementContent(t.find(".popover-body"),n),t.removeClass("fade show")},r._getContent=function(){return this.element.getAttribute("data-content")||this.config.content},r._cleanTipClass=function(){var t=e(this.getTipElement()),n=t.attr("class").match(Z);null!==n&&n.length>0&&t.removeClass(n.join(""))},s._jQueryInterface=function(t){return this.each((function(){var n=e(this).data("bs.popover"),i="object"==typeof t?t:null;if((n||!/dispose|hide/.test(t))&&(n||(n=new s(this,i),e(this).data("bs.popover",n)),"string"==typeof t)){if("undefined"==typeof n[t])throw new TypeError('No method named "'+t+'"');n[t]()}}))},o(s,null,[{key:"VERSION",get:function(){return"4.5.0"}},{key:"Default",get:function(){return tt}},{key:"NAME",get:function(){return J}},{key:"DATA_KEY",get:function(){return"bs.popover"}},{key:"Event",get:function(){return nt}},{key:"EVENT_KEY",get:function(){return".bs.popover"}},{key:"DefaultType",get:function(){return et}}]),s}($);e.fn[J]=it._jQueryInterface,e.fn[J].Constructor=it,e.fn[J].noConflict=function(){return e.fn[J]=G,it._jQueryInterface};var ot="scrollspy",st=e.fn[ot],rt={offset:10,method:"auto",target:""},at={offset:"number",method:"string",target:"(string|element)"},lt=function(){function t(t,n){var i=this;this._element=t,this._scrollElement="BODY"===t.tagName?window:t,this._config=this._getConfig(n),this._selector=this._config.target+" .nav-link,"+this._config.target+" .list-group-item,"+this._config.target+" .dropdown-item",this._offsets=[],this._targets=[],this._activeTarget=null,this._scrollHeight=0,e(this._scrollElement).on("scroll.bs.scrollspy",(function(t){return i._process(t)})),this.refresh(),this._process()}var n=t.prototype;return n.refresh=function(){var t=this,n=this._scrollElement===this._scrollElement.window?"offset":"position",i="auto"===this._config.method?n:this._config.method,o="position"===i?this._getScrollTop():0;this._offsets=[],this._targets=[],this._scrollHeight=this._getScrollHeight(),[].slice.call(document.querySelectorAll(this._selector)).map((function(t){var n,s=c.getSelectorFromElement(t);if(s&&(n=document.querySelector(s)),n){var r=n.getBoundingClientRect();if(r.width||r.height)return[e(n)[i]().top+o,s]}return null})).filter((function(t){return t})).sort((function(t,e){return t[0]-e[0]})).forEach((function(e){t._offsets.push(e[0]),t._targets.push(e[1])}))},n.dispose=function(){e.removeData(this._element,"bs.scrollspy"),e(this._scrollElement).off(".bs.scrollspy"),this._element=null,this._scrollElement=null,this._config=null,this._selector=null,this._offsets=null,this._targets=null,this._activeTarget=null,this._scrollHeight=null},n._getConfig=function(t){if("string"!=typeof(t=a(a({},rt),"object"==typeof t&&t?t:{})).target&&c.isElement(t.target)){var n=e(t.target).attr("id");n||(n=c.getUID(ot),e(t.target).attr("id",n)),t.target="#"+n}return c.typeCheckConfig(ot,t,at),t},n._getScrollTop=function(){return this._scrollElement===window?this._scrollElement.pageYOffset:this._scrollElement.scrollTop},n._getScrollHeight=function(){return this._scrollElement.scrollHeight||Math.max(document.body.scrollHeight,document.documentElement.scrollHeight)},n._getOffsetHeight=function(){return this._scrollElement===window?window.innerHeight:this._scrollElement.getBoundingClientRect().height},n._process=function(){var t=this._getScrollTop()+this._config.offset,e=this._getScrollHeight(),n=this._config.offset+e-this._getOffsetHeight();if(this._scrollHeight!==e&&this.refresh(),t>=n){var i=this._targets[this._targets.length-1];this._activeTarget!==i&&this._activate(i)}else{if(this._activeTarget&&t<this._offsets[0]&&this._offsets[0]>0)return this._activeTarget=null,void this._clear();for(var o=this._offsets.length;o--;){this._activeTarget!==this._targets[o]&&t>=this._offsets[o]&&("undefined"==typeof this._offsets[o+1]||t<this._offsets[o+1])&&this._activate(this._targets[o])}}},n._activate=function(t){this._activeTarget=t,this._clear();var n=this._selector.split(",").map((function(e){return e+'[data-target="'+t+'"],'+e+'[href="'+t+'"]'})),i=e([].slice.call(document.querySelectorAll(n.join(","))));i.hasClass("dropdown-item")?(i.closest(".dropdown").find(".dropdown-toggle").addClass("active"),i.addClass("active")):(i.addClass("active"),i.parents(".nav, .list-group").prev(".nav-link, .list-group-item").addClass("active"),i.parents(".nav, .list-group").prev(".nav-item").children(".nav-link").addClass("active")),e(this._scrollElement).trigger("activate.bs.scrollspy",{relatedTarget:t})},n._clear=function(){[].slice.call(document.querySelectorAll(this._selector)).filter((function(t){return t.classList.contains("active")})).forEach((function(t){return t.classList.remove("active")}))},t._jQueryInterface=function(n){return this.each((function(){var i=e(this).data("bs.scrollspy");if(i||(i=new t(this,"object"==typeof n&&n),e(this).data("bs.scrollspy",i)),"string"==typeof n){if("undefined"==typeof i[n])throw new TypeError('No method named "'+n+'"');i[n]()}}))},o(t,null,[{key:"VERSION",get:function(){return"4.5.0"}},{key:"Default",get:function(){return rt}}]),t}();e(window).on("load.bs.scrollspy.data-api",(function(){for(var t=[].slice.call(document.querySelectorAll('[data-spy="scroll"]')),n=t.length;n--;){var i=e(t[n]);lt._jQueryInterface.call(i,i.data())}})),e.fn[ot]=lt._jQueryInterface,e.fn[ot].Constructor=lt,e.fn[ot].noConflict=function(){return e.fn[ot]=st,lt._jQueryInterface};var ct=e.fn.tab,ht=function(){function t(t){this._element=t}var n=t.prototype;return n.show=function(){var t=this;if(!(this._element.parentNode&&this._element.parentNode.nodeType===Node.ELEMENT_NODE&&e(this._element).hasClass("active")||e(this._element).hasClass("disabled"))){var n,i,o=e(this._element).closest(".nav, .list-group")[0],s=c.getSelectorFromElement(this._element);if(o){var r="UL"===o.nodeName||"OL"===o.nodeName?"> li > .active":".active";i=(i=e.makeArray(e(o).find(r)))[i.length-1]}var a=e.Event("hide.bs.tab",{relatedTarget:this._element}),l=e.Event("show.bs.tab",{relatedTarget:i});if(i&&e(i).trigger(a),e(this._element).trigger(l),!l.isDefaultPrevented()&&!a.isDefaultPrevented()){s&&(n=document.querySelector(s)),this._activate(this._element,o);var h=function(){var n=e.Event("hidden.bs.tab",{relatedTarget:t._element}),o=e.Event("shown.bs.tab",{relatedTarget:i});e(i).trigger(n),e(t._element).trigger(o)};n?this._activate(n,n.parentNode,h):h()}}},n.dispose=function(){e.removeData(this._element,"bs.tab"),this._element=null},n._activate=function(t,n,i){var o=this,s=(!n||"UL"!==n.nodeName&&"OL"!==n.nodeName?e(n).children(".active"):e(n).find("> li > .active"))[0],r=i&&s&&e(s).hasClass("fade"),a=function(){return o._transitionComplete(t,s,i)};if(s&&r){var l=c.getTransitionDurationFromElement(s);e(s).removeClass("show").one(c.TRANSITION_END,a).emulateTransitionEnd(l)}else a()},n._transitionComplete=function(t,n,i){if(n){e(n).removeClass("active");var o=e(n.parentNode).find("> .dropdown-menu .active")[0];o&&e(o).removeClass("active"),"tab"===n.getAttribute("role")&&n.setAttribute("aria-selected",!1)}if(e(t).addClass("active"),"tab"===t.getAttribute("role")&&t.setAttribute("aria-selected",!0),c.reflow(t),t.classList.contains("fade")&&t.classList.add("show"),t.parentNode&&e(t.parentNode).hasClass("dropdown-menu")){var s=e(t).closest(".dropdown")[0];if(s){var r=[].slice.call(s.querySelectorAll(".dropdown-toggle"));e(r).addClass("active")}t.setAttribute("aria-expanded",!0)}i&&i()},t._jQueryInterface=function(n){return this.each((function(){var i=e(this),o=i.data("bs.tab");if(o||(o=new t(this),i.data("bs.tab",o)),"string"==typeof n){if("undefined"==typeof o[n])throw new TypeError('No method named "'+n+'"');o[n]()}}))},o(t,null,[{key:"VERSION",get:function(){return"4.5.0"}}]),t}();e(document).on("click.bs.tab.data-api",'[data-toggle="tab"], [data-toggle="pill"], [data-toggle="list"]',(function(t){t.preventDefault(),ht._jQueryInterface.call(e(this),"show")})),e.fn.tab=ht._jQueryInterface,e.fn.tab.Constructor=ht,e.fn.tab.noConflict=function(){return e.fn.tab=ct,ht._jQueryInterface};var ut=e.fn.toast,dt={animation:"boolean",autohide:"boolean",delay:"number"},ft={animation:!0,autohide:!0,delay:500},gt=function(){function t(t,e){this._element=t,this._config=this._getConfig(e),this._timeout=null,this._setListeners()}var n=t.prototype;return n.show=function(){var t=this,n=e.Event("show.bs.toast");if(e(this._element).trigger(n),!n.isDefaultPrevented()){this._config.animation&&this._element.classList.add("fade");var i=function(){t._element.classList.remove("showing"),t._element.classList.add("show"),e(t._element).trigger("shown.bs.toast"),t._config.autohide&&(t._timeout=setTimeout((function(){t.hide()}),t._config.delay))};if(this._element.classList.remove("hide"),c.reflow(this._element),this._element.classList.add("showing"),this._config.animation){var o=c.getTransitionDurationFromElement(this._element);e(this._element).one(c.TRANSITION_END,i).emulateTransitionEnd(o)}else i()}},n.hide=function(){if(this._element.classList.contains("show")){var t=e.Event("hide.bs.toast");e(this._element).trigger(t),t.isDefaultPrevented()||this._close()}},n.dispose=function(){clearTimeout(this._timeout),this._timeout=null,this._element.classList.contains("show")&&this._element.classList.remove("show"),e(this._element).off("click.dismiss.bs.toast"),e.removeData(this._element,"bs.toast"),this._element=null,this._config=null},n._getConfig=function(t){return t=a(a(a({},ft),e(this._element).data()),"object"==typeof t&&t?t:{}),c.typeCheckConfig("toast",t,this.constructor.DefaultType),t},n._setListeners=function(){var t=this;e(this._element).on("click.dismiss.bs.toast",'[data-dismiss="toast"]',(function(){return t.hide()}))},n._close=function(){var t=this,n=function(){t._element.classList.add("hide"),e(t._element).trigger("hidden.bs.toast")};if(this._element.classList.remove("show"),this._config.animation){var i=c.getTransitionDurationFromElement(this._element);e(this._element).one(c.TRANSITION_END,n).emulateTransitionEnd(i)}else n()},t._jQueryInterface=function(n){return this.each((function(){var i=e(this),o=i.data("bs.toast");if(o||(o=new t(this,"object"==typeof n&&n),i.data("bs.toast",o)),"string"==typeof n){if("undefined"==typeof o[n])throw new TypeError('No method named "'+n+'"');o[n](this)}}))},o(t,null,[{key:"VERSION",get:function(){return"4.5.0"}},{key:"DefaultType",get:function(){return dt}},{key:"Default",get:function(){return ft}}]),t}();e.fn.toast=gt._jQueryInterface,e.fn.toast.Constructor=gt,e.fn.toast.noConflict=function(){return e.fn.toast=ut,gt._jQueryInterface},t.Alert=d,t.Button=g,t.Carousel=E,t.Collapse=D,t.Dropdown=j,t.Modal=R,t.Popover=it,t.Scrollspy=lt,t.Tab=ht,t.Toast=gt,t.Tooltip=$,t.Util=c,Object.defineProperty(t,"__esModule",{value:!0})}));
+//# sourceMappingURL=bootstrap.min.js.map
\ No newline at end of file
diff --git a/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/js/d3.min.js b/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/js/d3.min.js
new file mode 100644
index 0000000000000000000000000000000000000000..166487309a774a196d29b52ad29f14d8a16f9509
--- /dev/null
+++ b/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/js/d3.min.js
@@ -0,0 +1,5 @@
+!function(){function n(n){return n&&(n.ownerDocument||n.document||n).documentElement}function t(n){return n&&(n.ownerDocument&&n.ownerDocument.defaultView||n.document&&n||n.defaultView)}function e(n,t){return t>n?-1:n>t?1:n>=t?0:NaN}function r(n){return null===n?NaN:+n}function i(n){return!isNaN(n)}function u(n){return{left:function(t,e,r,i){for(arguments.length<3&&(r=0),arguments.length<4&&(i=t.length);i>r;){var u=r+i>>>1;n(t[u],e)<0?r=u+1:i=u}return r},right:function(t,e,r,i){for(arguments.length<3&&(r=0),arguments.length<4&&(i=t.length);i>r;){var u=r+i>>>1;n(t[u],e)>0?i=u:r=u+1}return r}}}function o(n){return n.length}function a(n){for(var t=1;n*t%1;)t*=10;return t}function l(n,t){for(var e in t)Object.defineProperty(n.prototype,e,{value:t[e],enumerable:!1})}function c(){this._=Object.create(null)}function f(n){return(n+="")===bo||n[0]===_o?_o+n:n}function s(n){return(n+="")[0]===_o?n.slice(1):n}function h(n){return f(n)in this._}function p(n){return(n=f(n))in this._&&delete this._[n]}function g(){var n=[];for(var t in this._)n.push(s(t));return n}function v(){var n=0;for(var t in this._)++n;return n}function d(){for(var n in this._)return!1;return!0}function y(){this._=Object.create(null)}function m(n){return n}function M(n,t,e){return function(){var r=e.apply(t,arguments);return r===t?n:r}}function x(n,t){if(t in n)return t;t=t.charAt(0).toUpperCase()+t.slice(1);for(var e=0,r=wo.length;r>e;++e){var i=wo[e]+t;if(i in n)return i}}function b(){}function _(){}function w(n){function t(){for(var t,r=e,i=-1,u=r.length;++i<u;)(t=r[i].on)&&t.apply(this,arguments);return n}var e=[],r=new c;return t.on=function(t,i){var u,o=r.get(t);return arguments.length<2?o&&o.on:(o&&(o.on=null,e=e.slice(0,u=e.indexOf(o)).concat(e.slice(u+1)),r.remove(t)),i&&e.push(r.set(t,{on:i})),n)},t}function S(){ao.event.preventDefault()}function k(){for(var n,t=ao.event;n=t.sourceEvent;)t=n;return t}function N(n){for(var t=new _,e=0,r=arguments.length;++e<r;)t[arguments[e]]=w(t);return t.of=function(e,r){return function(i){try{var u=i.sourceEvent=ao.event;i.target=n,ao.event=i,t[i.type].apply(e,r)}finally{ao.event=u}}},t}function E(n){return ko(n,Co),n}function A(n){return"function"==typeof n?n:function(){return No(n,this)}}function C(n){return"function"==typeof n?n:function(){return Eo(n,this)}}function z(n,t){function e(){this.removeAttribute(n)}function r(){this.removeAttributeNS(n.space,n.local)}function i(){this.setAttribute(n,t)}function u(){this.setAttributeNS(n.space,n.local,t)}function o(){var e=t.apply(this,arguments);null==e?this.removeAttribute(n):this.setAttribute(n,e)}function a(){var e=t.apply(this,arguments);null==e?this.removeAttributeNS(n.space,n.local):this.setAttributeNS(n.space,n.local,e)}return n=ao.ns.qualify(n),null==t?n.local?r:e:"function"==typeof t?n.local?a:o:n.local?u:i}function L(n){return n.trim().replace(/\s+/g," ")}function q(n){return new RegExp("(?:^|\\s+)"+ao.requote(n)+"(?:\\s+|$)","g")}function T(n){return(n+"").trim().split(/^|\s+/)}function R(n,t){function e(){for(var e=-1;++e<i;)n[e](this,t)}function r(){for(var e=-1,r=t.apply(this,arguments);++e<i;)n[e](this,r)}n=T(n).map(D);var i=n.length;return"function"==typeof t?r:e}function D(n){var t=q(n);return function(e,r){if(i=e.classList)return r?i.add(n):i.remove(n);var i=e.getAttribute("class")||"";r?(t.lastIndex=0,t.test(i)||e.setAttribute("class",L(i+" "+n))):e.setAttribute("class",L(i.replace(t," ")))}}function P(n,t,e){function r(){this.style.removeProperty(n)}function i(){this.style.setProperty(n,t,e)}function u(){var r=t.apply(this,arguments);null==r?this.style.removeProperty(n):this.style.setProperty(n,r,e)}return null==t?r:"function"==typeof t?u:i}function U(n,t){function e(){delete this[n]}function r(){this[n]=t}function i(){var e=t.apply(this,arguments);null==e?delete this[n]:this[n]=e}return null==t?e:"function"==typeof t?i:r}function j(n){function t(){var t=this.ownerDocument,e=this.namespaceURI;return e===zo&&t.documentElement.namespaceURI===zo?t.createElement(n):t.createElementNS(e,n)}function e(){return this.ownerDocument.createElementNS(n.space,n.local)}return"function"==typeof n?n:(n=ao.ns.qualify(n)).local?e:t}function F(){var n=this.parentNode;n&&n.removeChild(this)}function H(n){return{__data__:n}}function O(n){return function(){return Ao(this,n)}}function I(n){return arguments.length||(n=e),function(t,e){return t&&e?n(t.__data__,e.__data__):!t-!e}}function Y(n,t){for(var e=0,r=n.length;r>e;e++)for(var i,u=n[e],o=0,a=u.length;a>o;o++)(i=u[o])&&t(i,o,e);return n}function Z(n){return ko(n,qo),n}function V(n){var t,e;return function(r,i,u){var o,a=n[u].update,l=a.length;for(u!=e&&(e=u,t=0),i>=t&&(t=i+1);!(o=a[t])&&++t<l;);return o}}function X(n,t,e){function r(){var t=this[o];t&&(this.removeEventListener(n,t,t.$),delete this[o])}function i(){var i=l(t,co(arguments));r.call(this),this.addEventListener(n,this[o]=i,i.$=e),i._=t}function u(){var t,e=new RegExp("^__on([^.]+)"+ao.requote(n)+"$");for(var r in this)if(t=r.match(e)){var i=this[r];this.removeEventListener(t[1],i,i.$),delete this[r]}}var o="__on"+n,a=n.indexOf("."),l=$;a>0&&(n=n.slice(0,a));var c=To.get(n);return c&&(n=c,l=B),a?t?i:r:t?b:u}function $(n,t){return function(e){var r=ao.event;ao.event=e,t[0]=this.__data__;try{n.apply(this,t)}finally{ao.event=r}}}function B(n,t){var e=$(n,t);return function(n){var t=this,r=n.relatedTarget;r&&(r===t||8&r.compareDocumentPosition(t))||e.call(t,n)}}function W(e){var r=".dragsuppress-"+ ++Do,i="click"+r,u=ao.select(t(e)).on("touchmove"+r,S).on("dragstart"+r,S).on("selectstart"+r,S);if(null==Ro&&(Ro="onselectstart"in e?!1:x(e.style,"userSelect")),Ro){var o=n(e).style,a=o[Ro];o[Ro]="none"}return function(n){if(u.on(r,null),Ro&&(o[Ro]=a),n){var t=function(){u.on(i,null)};u.on(i,function(){S(),t()},!0),setTimeout(t,0)}}}function J(n,e){e.changedTouches&&(e=e.changedTouches[0]);var r=n.ownerSVGElement||n;if(r.createSVGPoint){var i=r.createSVGPoint();if(0>Po){var u=t(n);if(u.scrollX||u.scrollY){r=ao.select("body").append("svg").style({position:"absolute",top:0,left:0,margin:0,padding:0,border:"none"},"important");var o=r[0][0].getScreenCTM();Po=!(o.f||o.e),r.remove()}}return Po?(i.x=e.pageX,i.y=e.pageY):(i.x=e.clientX,i.y=e.clientY),i=i.matrixTransform(n.getScreenCTM().inverse()),[i.x,i.y]}var a=n.getBoundingClientRect();return[e.clientX-a.left-n.clientLeft,e.clientY-a.top-n.clientTop]}function G(){return ao.event.changedTouches[0].identifier}function K(n){return n>0?1:0>n?-1:0}function Q(n,t,e){return(t[0]-n[0])*(e[1]-n[1])-(t[1]-n[1])*(e[0]-n[0])}function nn(n){return n>1?0:-1>n?Fo:Math.acos(n)}function tn(n){return n>1?Io:-1>n?-Io:Math.asin(n)}function en(n){return((n=Math.exp(n))-1/n)/2}function rn(n){return((n=Math.exp(n))+1/n)/2}function un(n){return((n=Math.exp(2*n))-1)/(n+1)}function on(n){return(n=Math.sin(n/2))*n}function an(){}function ln(n,t,e){return this instanceof ln?(this.h=+n,this.s=+t,void(this.l=+e)):arguments.length<2?n instanceof ln?new ln(n.h,n.s,n.l):_n(""+n,wn,ln):new ln(n,t,e)}function cn(n,t,e){function r(n){return n>360?n-=360:0>n&&(n+=360),60>n?u+(o-u)*n/60:180>n?o:240>n?u+(o-u)*(240-n)/60:u}function i(n){return Math.round(255*r(n))}var u,o;return n=isNaN(n)?0:(n%=360)<0?n+360:n,t=isNaN(t)?0:0>t?0:t>1?1:t,e=0>e?0:e>1?1:e,o=.5>=e?e*(1+t):e+t-e*t,u=2*e-o,new mn(i(n+120),i(n),i(n-120))}function fn(n,t,e){return this instanceof fn?(this.h=+n,this.c=+t,void(this.l=+e)):arguments.length<2?n instanceof fn?new fn(n.h,n.c,n.l):n instanceof hn?gn(n.l,n.a,n.b):gn((n=Sn((n=ao.rgb(n)).r,n.g,n.b)).l,n.a,n.b):new fn(n,t,e)}function sn(n,t,e){return isNaN(n)&&(n=0),isNaN(t)&&(t=0),new hn(e,Math.cos(n*=Yo)*t,Math.sin(n)*t)}function hn(n,t,e){return this instanceof hn?(this.l=+n,this.a=+t,void(this.b=+e)):arguments.length<2?n instanceof hn?new hn(n.l,n.a,n.b):n instanceof fn?sn(n.h,n.c,n.l):Sn((n=mn(n)).r,n.g,n.b):new hn(n,t,e)}function pn(n,t,e){var r=(n+16)/116,i=r+t/500,u=r-e/200;return i=vn(i)*na,r=vn(r)*ta,u=vn(u)*ea,new mn(yn(3.2404542*i-1.5371385*r-.4985314*u),yn(-.969266*i+1.8760108*r+.041556*u),yn(.0556434*i-.2040259*r+1.0572252*u))}function gn(n,t,e){return n>0?new fn(Math.atan2(e,t)*Zo,Math.sqrt(t*t+e*e),n):new fn(NaN,NaN,n)}function vn(n){return n>.206893034?n*n*n:(n-4/29)/7.787037}function dn(n){return n>.008856?Math.pow(n,1/3):7.787037*n+4/29}function yn(n){return Math.round(255*(.00304>=n?12.92*n:1.055*Math.pow(n,1/2.4)-.055))}function mn(n,t,e){return this instanceof mn?(this.r=~~n,this.g=~~t,void(this.b=~~e)):arguments.length<2?n instanceof mn?new mn(n.r,n.g,n.b):_n(""+n,mn,cn):new mn(n,t,e)}function Mn(n){return new mn(n>>16,n>>8&255,255&n)}function xn(n){return Mn(n)+""}function bn(n){return 16>n?"0"+Math.max(0,n).toString(16):Math.min(255,n).toString(16)}function _n(n,t,e){var r,i,u,o=0,a=0,l=0;if(r=/([a-z]+)\((.*)\)/.exec(n=n.toLowerCase()))switch(i=r[2].split(","),r[1]){case"hsl":return e(parseFloat(i[0]),parseFloat(i[1])/100,parseFloat(i[2])/100);case"rgb":return t(Nn(i[0]),Nn(i[1]),Nn(i[2]))}return(u=ua.get(n))?t(u.r,u.g,u.b):(null==n||"#"!==n.charAt(0)||isNaN(u=parseInt(n.slice(1),16))||(4===n.length?(o=(3840&u)>>4,o=o>>4|o,a=240&u,a=a>>4|a,l=15&u,l=l<<4|l):7===n.length&&(o=(16711680&u)>>16,a=(65280&u)>>8,l=255&u)),t(o,a,l))}function wn(n,t,e){var r,i,u=Math.min(n/=255,t/=255,e/=255),o=Math.max(n,t,e),a=o-u,l=(o+u)/2;return a?(i=.5>l?a/(o+u):a/(2-o-u),r=n==o?(t-e)/a+(e>t?6:0):t==o?(e-n)/a+2:(n-t)/a+4,r*=60):(r=NaN,i=l>0&&1>l?0:r),new ln(r,i,l)}function Sn(n,t,e){n=kn(n),t=kn(t),e=kn(e);var r=dn((.4124564*n+.3575761*t+.1804375*e)/na),i=dn((.2126729*n+.7151522*t+.072175*e)/ta),u=dn((.0193339*n+.119192*t+.9503041*e)/ea);return hn(116*i-16,500*(r-i),200*(i-u))}function kn(n){return(n/=255)<=.04045?n/12.92:Math.pow((n+.055)/1.055,2.4)}function Nn(n){var t=parseFloat(n);return"%"===n.charAt(n.length-1)?Math.round(2.55*t):t}function En(n){return"function"==typeof n?n:function(){return n}}function An(n){return function(t,e,r){return 2===arguments.length&&"function"==typeof e&&(r=e,e=null),Cn(t,e,n,r)}}function Cn(n,t,e,r){function i(){var n,t=l.status;if(!t&&Ln(l)||t>=200&&300>t||304===t){try{n=e.call(u,l)}catch(r){return void o.error.call(u,r)}o.load.call(u,n)}else o.error.call(u,l)}var u={},o=ao.dispatch("beforesend","progress","load","error"),a={},l=new XMLHttpRequest,c=null;return!this.XDomainRequest||"withCredentials"in l||!/^(http(s)?:)?\/\//.test(n)||(l=new XDomainRequest),"onload"in l?l.onload=l.onerror=i:l.onreadystatechange=function(){l.readyState>3&&i()},l.onprogress=function(n){var t=ao.event;ao.event=n;try{o.progress.call(u,l)}finally{ao.event=t}},u.header=function(n,t){return n=(n+"").toLowerCase(),arguments.length<2?a[n]:(null==t?delete a[n]:a[n]=t+"",u)},u.mimeType=function(n){return arguments.length?(t=null==n?null:n+"",u):t},u.responseType=function(n){return arguments.length?(c=n,u):c},u.response=function(n){return e=n,u},["get","post"].forEach(function(n){u[n]=function(){return u.send.apply(u,[n].concat(co(arguments)))}}),u.send=function(e,r,i){if(2===arguments.length&&"function"==typeof r&&(i=r,r=null),l.open(e,n,!0),null==t||"accept"in a||(a.accept=t+",*/*"),l.setRequestHeader)for(var f in a)l.setRequestHeader(f,a[f]);return null!=t&&l.overrideMimeType&&l.overrideMimeType(t),null!=c&&(l.responseType=c),null!=i&&u.on("error",i).on("load",function(n){i(null,n)}),o.beforesend.call(u,l),l.send(null==r?null:r),u},u.abort=function(){return l.abort(),u},ao.rebind(u,o,"on"),null==r?u:u.get(zn(r))}function zn(n){return 1===n.length?function(t,e){n(null==t?e:null)}:n}function Ln(n){var t=n.responseType;return t&&"text"!==t?n.response:n.responseText}function qn(n,t,e){var r=arguments.length;2>r&&(t=0),3>r&&(e=Date.now());var i=e+t,u={c:n,t:i,n:null};return aa?aa.n=u:oa=u,aa=u,la||(ca=clearTimeout(ca),la=1,fa(Tn)),u}function Tn(){var n=Rn(),t=Dn()-n;t>24?(isFinite(t)&&(clearTimeout(ca),ca=setTimeout(Tn,t)),la=0):(la=1,fa(Tn))}function Rn(){for(var n=Date.now(),t=oa;t;)n>=t.t&&t.c(n-t.t)&&(t.c=null),t=t.n;return n}function Dn(){for(var n,t=oa,e=1/0;t;)t.c?(t.t<e&&(e=t.t),t=(n=t).n):t=n?n.n=t.n:oa=t.n;return aa=n,e}function Pn(n,t){return t-(n?Math.ceil(Math.log(n)/Math.LN10):1)}function Un(n,t){var e=Math.pow(10,3*xo(8-t));return{scale:t>8?function(n){return n/e}:function(n){return n*e},symbol:n}}function jn(n){var t=n.decimal,e=n.thousands,r=n.grouping,i=n.currency,u=r&&e?function(n,t){for(var i=n.length,u=[],o=0,a=r[0],l=0;i>0&&a>0&&(l+a+1>t&&(a=Math.max(1,t-l)),u.push(n.substring(i-=a,i+a)),!((l+=a+1)>t));)a=r[o=(o+1)%r.length];return u.reverse().join(e)}:m;return function(n){var e=ha.exec(n),r=e[1]||" ",o=e[2]||">",a=e[3]||"-",l=e[4]||"",c=e[5],f=+e[6],s=e[7],h=e[8],p=e[9],g=1,v="",d="",y=!1,m=!0;switch(h&&(h=+h.substring(1)),(c||"0"===r&&"="===o)&&(c=r="0",o="="),p){case"n":s=!0,p="g";break;case"%":g=100,d="%",p="f";break;case"p":g=100,d="%",p="r";break;case"b":case"o":case"x":case"X":"#"===l&&(v="0"+p.toLowerCase());case"c":m=!1;case"d":y=!0,h=0;break;case"s":g=-1,p="r"}"$"===l&&(v=i[0],d=i[1]),"r"!=p||h||(p="g"),null!=h&&("g"==p?h=Math.max(1,Math.min(21,h)):"e"!=p&&"f"!=p||(h=Math.max(0,Math.min(20,h)))),p=pa.get(p)||Fn;var M=c&&s;return function(n){var e=d;if(y&&n%1)return"";var i=0>n||0===n&&0>1/n?(n=-n,"-"):"-"===a?"":a;if(0>g){var l=ao.formatPrefix(n,h);n=l.scale(n),e=l.symbol+d}else n*=g;n=p(n,h);var x,b,_=n.lastIndexOf(".");if(0>_){var w=m?n.lastIndexOf("e"):-1;0>w?(x=n,b=""):(x=n.substring(0,w),b=n.substring(w))}else x=n.substring(0,_),b=t+n.substring(_+1);!c&&s&&(x=u(x,1/0));var S=v.length+x.length+b.length+(M?0:i.length),k=f>S?new Array(S=f-S+1).join(r):"";return M&&(x=u(k+x,k.length?f-b.length:1/0)),i+=v,n=x+b,("<"===o?i+n+k:">"===o?k+i+n:"^"===o?k.substring(0,S>>=1)+i+n+k.substring(S):i+(M?n:k+n))+e}}}function Fn(n){return n+""}function Hn(){this._=new Date(arguments.length>1?Date.UTC.apply(this,arguments):arguments[0])}function On(n,t,e){function r(t){var e=n(t),r=u(e,1);return r-t>t-e?e:r}function i(e){return t(e=n(new va(e-1)),1),e}function u(n,e){return t(n=new va(+n),e),n}function o(n,r,u){var o=i(n),a=[];if(u>1)for(;r>o;)e(o)%u||a.push(new Date(+o)),t(o,1);else for(;r>o;)a.push(new Date(+o)),t(o,1);return a}function a(n,t,e){try{va=Hn;var r=new Hn;return r._=n,o(r,t,e)}finally{va=Date}}n.floor=n,n.round=r,n.ceil=i,n.offset=u,n.range=o;var l=n.utc=In(n);return l.floor=l,l.round=In(r),l.ceil=In(i),l.offset=In(u),l.range=a,n}function In(n){return function(t,e){try{va=Hn;var r=new Hn;return r._=t,n(r,e)._}finally{va=Date}}}function Yn(n){function t(n){function t(t){for(var e,i,u,o=[],a=-1,l=0;++a<r;)37===n.charCodeAt(a)&&(o.push(n.slice(l,a)),null!=(i=ya[e=n.charAt(++a)])&&(e=n.charAt(++a)),(u=A[e])&&(e=u(t,null==i?"e"===e?" ":"0":i)),o.push(e),l=a+1);return o.push(n.slice(l,a)),o.join("")}var r=n.length;return t.parse=function(t){var r={y:1900,m:0,d:1,H:0,M:0,S:0,L:0,Z:null},i=e(r,n,t,0);if(i!=t.length)return null;"p"in r&&(r.H=r.H%12+12*r.p);var u=null!=r.Z&&va!==Hn,o=new(u?Hn:va);return"j"in r?o.setFullYear(r.y,0,r.j):"W"in r||"U"in r?("w"in r||(r.w="W"in r?1:0),o.setFullYear(r.y,0,1),o.setFullYear(r.y,0,"W"in r?(r.w+6)%7+7*r.W-(o.getDay()+5)%7:r.w+7*r.U-(o.getDay()+6)%7)):o.setFullYear(r.y,r.m,r.d),o.setHours(r.H+(r.Z/100|0),r.M+r.Z%100,r.S,r.L),u?o._:o},t.toString=function(){return n},t}function e(n,t,e,r){for(var i,u,o,a=0,l=t.length,c=e.length;l>a;){if(r>=c)return-1;if(i=t.charCodeAt(a++),37===i){if(o=t.charAt(a++),u=C[o in ya?t.charAt(a++):o],!u||(r=u(n,e,r))<0)return-1}else if(i!=e.charCodeAt(r++))return-1}return r}function r(n,t,e){_.lastIndex=0;var r=_.exec(t.slice(e));return r?(n.w=w.get(r[0].toLowerCase()),e+r[0].length):-1}function i(n,t,e){x.lastIndex=0;var r=x.exec(t.slice(e));return r?(n.w=b.get(r[0].toLowerCase()),e+r[0].length):-1}function u(n,t,e){N.lastIndex=0;var r=N.exec(t.slice(e));return r?(n.m=E.get(r[0].toLowerCase()),e+r[0].length):-1}function o(n,t,e){S.lastIndex=0;var r=S.exec(t.slice(e));return r?(n.m=k.get(r[0].toLowerCase()),e+r[0].length):-1}function a(n,t,r){return e(n,A.c.toString(),t,r)}function l(n,t,r){return e(n,A.x.toString(),t,r)}function c(n,t,r){return e(n,A.X.toString(),t,r)}function f(n,t,e){var r=M.get(t.slice(e,e+=2).toLowerCase());return null==r?-1:(n.p=r,e)}var s=n.dateTime,h=n.date,p=n.time,g=n.periods,v=n.days,d=n.shortDays,y=n.months,m=n.shortMonths;t.utc=function(n){function e(n){try{va=Hn;var t=new va;return t._=n,r(t)}finally{va=Date}}var r=t(n);return e.parse=function(n){try{va=Hn;var t=r.parse(n);return t&&t._}finally{va=Date}},e.toString=r.toString,e},t.multi=t.utc.multi=ct;var M=ao.map(),x=Vn(v),b=Xn(v),_=Vn(d),w=Xn(d),S=Vn(y),k=Xn(y),N=Vn(m),E=Xn(m);g.forEach(function(n,t){M.set(n.toLowerCase(),t)});var A={a:function(n){return d[n.getDay()]},A:function(n){return v[n.getDay()]},b:function(n){return m[n.getMonth()]},B:function(n){return y[n.getMonth()]},c:t(s),d:function(n,t){return Zn(n.getDate(),t,2)},e:function(n,t){return Zn(n.getDate(),t,2)},H:function(n,t){return Zn(n.getHours(),t,2)},I:function(n,t){return Zn(n.getHours()%12||12,t,2)},j:function(n,t){return Zn(1+ga.dayOfYear(n),t,3)},L:function(n,t){return Zn(n.getMilliseconds(),t,3)},m:function(n,t){return Zn(n.getMonth()+1,t,2)},M:function(n,t){return Zn(n.getMinutes(),t,2)},p:function(n){return g[+(n.getHours()>=12)]},S:function(n,t){return Zn(n.getSeconds(),t,2)},U:function(n,t){return Zn(ga.sundayOfYear(n),t,2)},w:function(n){return n.getDay()},W:function(n,t){return Zn(ga.mondayOfYear(n),t,2)},x:t(h),X:t(p),y:function(n,t){return Zn(n.getFullYear()%100,t,2)},Y:function(n,t){return Zn(n.getFullYear()%1e4,t,4)},Z:at,"%":function(){return"%"}},C={a:r,A:i,b:u,B:o,c:a,d:tt,e:tt,H:rt,I:rt,j:et,L:ot,m:nt,M:it,p:f,S:ut,U:Bn,w:$n,W:Wn,x:l,X:c,y:Gn,Y:Jn,Z:Kn,"%":lt};return t}function Zn(n,t,e){var r=0>n?"-":"",i=(r?-n:n)+"",u=i.length;return r+(e>u?new Array(e-u+1).join(t)+i:i)}function Vn(n){return new RegExp("^(?:"+n.map(ao.requote).join("|")+")","i")}function Xn(n){for(var t=new c,e=-1,r=n.length;++e<r;)t.set(n[e].toLowerCase(),e);return t}function $n(n,t,e){ma.lastIndex=0;var r=ma.exec(t.slice(e,e+1));return r?(n.w=+r[0],e+r[0].length):-1}function Bn(n,t,e){ma.lastIndex=0;var r=ma.exec(t.slice(e));return r?(n.U=+r[0],e+r[0].length):-1}function Wn(n,t,e){ma.lastIndex=0;var r=ma.exec(t.slice(e));return r?(n.W=+r[0],e+r[0].length):-1}function Jn(n,t,e){ma.lastIndex=0;var r=ma.exec(t.slice(e,e+4));return r?(n.y=+r[0],e+r[0].length):-1}function Gn(n,t,e){ma.lastIndex=0;var r=ma.exec(t.slice(e,e+2));return r?(n.y=Qn(+r[0]),e+r[0].length):-1}function Kn(n,t,e){return/^[+-]\d{4}$/.test(t=t.slice(e,e+5))?(n.Z=-t,e+5):-1}function Qn(n){return n+(n>68?1900:2e3)}function nt(n,t,e){ma.lastIndex=0;var r=ma.exec(t.slice(e,e+2));return r?(n.m=r[0]-1,e+r[0].length):-1}function tt(n,t,e){ma.lastIndex=0;var r=ma.exec(t.slice(e,e+2));return r?(n.d=+r[0],e+r[0].length):-1}function et(n,t,e){ma.lastIndex=0;var r=ma.exec(t.slice(e,e+3));return r?(n.j=+r[0],e+r[0].length):-1}function rt(n,t,e){ma.lastIndex=0;var r=ma.exec(t.slice(e,e+2));return r?(n.H=+r[0],e+r[0].length):-1}function it(n,t,e){ma.lastIndex=0;var r=ma.exec(t.slice(e,e+2));return r?(n.M=+r[0],e+r[0].length):-1}function ut(n,t,e){ma.lastIndex=0;var r=ma.exec(t.slice(e,e+2));return r?(n.S=+r[0],e+r[0].length):-1}function ot(n,t,e){ma.lastIndex=0;var r=ma.exec(t.slice(e,e+3));return r?(n.L=+r[0],e+r[0].length):-1}function at(n){var t=n.getTimezoneOffset(),e=t>0?"-":"+",r=xo(t)/60|0,i=xo(t)%60;return e+Zn(r,"0",2)+Zn(i,"0",2)}function lt(n,t,e){Ma.lastIndex=0;var r=Ma.exec(t.slice(e,e+1));return r?e+r[0].length:-1}function ct(n){for(var t=n.length,e=-1;++e<t;)n[e][0]=this(n[e][0]);return function(t){for(var e=0,r=n[e];!r[1](t);)r=n[++e];return r[0](t)}}function ft(){}function st(n,t,e){var r=e.s=n+t,i=r-n,u=r-i;e.t=n-u+(t-i)}function ht(n,t){n&&wa.hasOwnProperty(n.type)&&wa[n.type](n,t)}function pt(n,t,e){var r,i=-1,u=n.length-e;for(t.lineStart();++i<u;)r=n[i],t.point(r[0],r[1],r[2]);t.lineEnd()}function gt(n,t){var e=-1,r=n.length;for(t.polygonStart();++e<r;)pt(n[e],t,1);t.polygonEnd()}function vt(){function n(n,t){n*=Yo,t=t*Yo/2+Fo/4;var e=n-r,o=e>=0?1:-1,a=o*e,l=Math.cos(t),c=Math.sin(t),f=u*c,s=i*l+f*Math.cos(a),h=f*o*Math.sin(a);ka.add(Math.atan2(h,s)),r=n,i=l,u=c}var t,e,r,i,u;Na.point=function(o,a){Na.point=n,r=(t=o)*Yo,i=Math.cos(a=(e=a)*Yo/2+Fo/4),u=Math.sin(a)},Na.lineEnd=function(){n(t,e)}}function dt(n){var t=n[0],e=n[1],r=Math.cos(e);return[r*Math.cos(t),r*Math.sin(t),Math.sin(e)]}function yt(n,t){return n[0]*t[0]+n[1]*t[1]+n[2]*t[2]}function mt(n,t){return[n[1]*t[2]-n[2]*t[1],n[2]*t[0]-n[0]*t[2],n[0]*t[1]-n[1]*t[0]]}function Mt(n,t){n[0]+=t[0],n[1]+=t[1],n[2]+=t[2]}function xt(n,t){return[n[0]*t,n[1]*t,n[2]*t]}function bt(n){var t=Math.sqrt(n[0]*n[0]+n[1]*n[1]+n[2]*n[2]);n[0]/=t,n[1]/=t,n[2]/=t}function _t(n){return[Math.atan2(n[1],n[0]),tn(n[2])]}function wt(n,t){return xo(n[0]-t[0])<Uo&&xo(n[1]-t[1])<Uo}function St(n,t){n*=Yo;var e=Math.cos(t*=Yo);kt(e*Math.cos(n),e*Math.sin(n),Math.sin(t))}function kt(n,t,e){++Ea,Ca+=(n-Ca)/Ea,za+=(t-za)/Ea,La+=(e-La)/Ea}function Nt(){function n(n,i){n*=Yo;var u=Math.cos(i*=Yo),o=u*Math.cos(n),a=u*Math.sin(n),l=Math.sin(i),c=Math.atan2(Math.sqrt((c=e*l-r*a)*c+(c=r*o-t*l)*c+(c=t*a-e*o)*c),t*o+e*a+r*l);Aa+=c,qa+=c*(t+(t=o)),Ta+=c*(e+(e=a)),Ra+=c*(r+(r=l)),kt(t,e,r)}var t,e,r;ja.point=function(i,u){i*=Yo;var o=Math.cos(u*=Yo);t=o*Math.cos(i),e=o*Math.sin(i),r=Math.sin(u),ja.point=n,kt(t,e,r)}}function Et(){ja.point=St}function At(){function n(n,t){n*=Yo;var e=Math.cos(t*=Yo),o=e*Math.cos(n),a=e*Math.sin(n),l=Math.sin(t),c=i*l-u*a,f=u*o-r*l,s=r*a-i*o,h=Math.sqrt(c*c+f*f+s*s),p=r*o+i*a+u*l,g=h&&-nn(p)/h,v=Math.atan2(h,p);Da+=g*c,Pa+=g*f,Ua+=g*s,Aa+=v,qa+=v*(r+(r=o)),Ta+=v*(i+(i=a)),Ra+=v*(u+(u=l)),kt(r,i,u)}var t,e,r,i,u;ja.point=function(o,a){t=o,e=a,ja.point=n,o*=Yo;var l=Math.cos(a*=Yo);r=l*Math.cos(o),i=l*Math.sin(o),u=Math.sin(a),kt(r,i,u)},ja.lineEnd=function(){n(t,e),ja.lineEnd=Et,ja.point=St}}function Ct(n,t){function e(e,r){return e=n(e,r),t(e[0],e[1])}return n.invert&&t.invert&&(e.invert=function(e,r){return e=t.invert(e,r),e&&n.invert(e[0],e[1])}),e}function zt(){return!0}function Lt(n,t,e,r,i){var u=[],o=[];if(n.forEach(function(n){if(!((t=n.length-1)<=0)){var t,e=n[0],r=n[t];if(wt(e,r)){i.lineStart();for(var a=0;t>a;++a)i.point((e=n[a])[0],e[1]);return void i.lineEnd()}var l=new Tt(e,n,null,!0),c=new Tt(e,null,l,!1);l.o=c,u.push(l),o.push(c),l=new Tt(r,n,null,!1),c=new Tt(r,null,l,!0),l.o=c,u.push(l),o.push(c)}}),o.sort(t),qt(u),qt(o),u.length){for(var a=0,l=e,c=o.length;c>a;++a)o[a].e=l=!l;for(var f,s,h=u[0];;){for(var p=h,g=!0;p.v;)if((p=p.n)===h)return;f=p.z,i.lineStart();do{if(p.v=p.o.v=!0,p.e){if(g)for(var a=0,c=f.length;c>a;++a)i.point((s=f[a])[0],s[1]);else r(p.x,p.n.x,1,i);p=p.n}else{if(g){f=p.p.z;for(var a=f.length-1;a>=0;--a)i.point((s=f[a])[0],s[1])}else r(p.x,p.p.x,-1,i);p=p.p}p=p.o,f=p.z,g=!g}while(!p.v);i.lineEnd()}}}function qt(n){if(t=n.length){for(var t,e,r=0,i=n[0];++r<t;)i.n=e=n[r],e.p=i,i=e;i.n=e=n[0],e.p=i}}function Tt(n,t,e,r){this.x=n,this.z=t,this.o=e,this.e=r,this.v=!1,this.n=this.p=null}function Rt(n,t,e,r){return function(i,u){function o(t,e){var r=i(t,e);n(t=r[0],e=r[1])&&u.point(t,e)}function a(n,t){var e=i(n,t);d.point(e[0],e[1])}function l(){m.point=a,d.lineStart()}function c(){m.point=o,d.lineEnd()}function f(n,t){v.push([n,t]);var e=i(n,t);x.point(e[0],e[1])}function s(){x.lineStart(),v=[]}function h(){f(v[0][0],v[0][1]),x.lineEnd();var n,t=x.clean(),e=M.buffer(),r=e.length;if(v.pop(),g.push(v),v=null,r)if(1&t){n=e[0];var i,r=n.length-1,o=-1;if(r>0){for(b||(u.polygonStart(),b=!0),u.lineStart();++o<r;)u.point((i=n[o])[0],i[1]);u.lineEnd()}}else r>1&&2&t&&e.push(e.pop().concat(e.shift())),p.push(e.filter(Dt))}var p,g,v,d=t(u),y=i.invert(r[0],r[1]),m={point:o,lineStart:l,lineEnd:c,polygonStart:function(){m.point=f,m.lineStart=s,m.lineEnd=h,p=[],g=[]},polygonEnd:function(){m.point=o,m.lineStart=l,m.lineEnd=c,p=ao.merge(p);var n=Ot(y,g);p.length?(b||(u.polygonStart(),b=!0),Lt(p,Ut,n,e,u)):n&&(b||(u.polygonStart(),b=!0),u.lineStart(),e(null,null,1,u),u.lineEnd()),b&&(u.polygonEnd(),b=!1),p=g=null},sphere:function(){u.polygonStart(),u.lineStart(),e(null,null,1,u),u.lineEnd(),u.polygonEnd()}},M=Pt(),x=t(M),b=!1;return m}}function Dt(n){return n.length>1}function Pt(){var n,t=[];return{lineStart:function(){t.push(n=[])},point:function(t,e){n.push([t,e])},lineEnd:b,buffer:function(){var e=t;return t=[],n=null,e},rejoin:function(){t.length>1&&t.push(t.pop().concat(t.shift()))}}}function Ut(n,t){return((n=n.x)[0]<0?n[1]-Io-Uo:Io-n[1])-((t=t.x)[0]<0?t[1]-Io-Uo:Io-t[1])}function jt(n){var t,e=NaN,r=NaN,i=NaN;return{lineStart:function(){n.lineStart(),t=1},point:function(u,o){var a=u>0?Fo:-Fo,l=xo(u-e);xo(l-Fo)<Uo?(n.point(e,r=(r+o)/2>0?Io:-Io),n.point(i,r),n.lineEnd(),n.lineStart(),n.point(a,r),n.point(u,r),t=0):i!==a&&l>=Fo&&(xo(e-i)<Uo&&(e-=i*Uo),xo(u-a)<Uo&&(u-=a*Uo),r=Ft(e,r,u,o),n.point(i,r),n.lineEnd(),n.lineStart(),n.point(a,r),t=0),n.point(e=u,r=o),i=a},lineEnd:function(){n.lineEnd(),e=r=NaN},clean:function(){return 2-t}}}function Ft(n,t,e,r){var i,u,o=Math.sin(n-e);return xo(o)>Uo?Math.atan((Math.sin(t)*(u=Math.cos(r))*Math.sin(e)-Math.sin(r)*(i=Math.cos(t))*Math.sin(n))/(i*u*o)):(t+r)/2}function Ht(n,t,e,r){var i;if(null==n)i=e*Io,r.point(-Fo,i),r.point(0,i),r.point(Fo,i),r.point(Fo,0),r.point(Fo,-i),r.point(0,-i),r.point(-Fo,-i),r.point(-Fo,0),r.point(-Fo,i);else if(xo(n[0]-t[0])>Uo){var u=n[0]<t[0]?Fo:-Fo;i=e*u/2,r.point(-u,i),r.point(0,i),r.point(u,i)}else r.point(t[0],t[1])}function Ot(n,t){var e=n[0],r=n[1],i=[Math.sin(e),-Math.cos(e),0],u=0,o=0;ka.reset();for(var a=0,l=t.length;l>a;++a){var c=t[a],f=c.length;if(f)for(var s=c[0],h=s[0],p=s[1]/2+Fo/4,g=Math.sin(p),v=Math.cos(p),d=1;;){d===f&&(d=0),n=c[d];var y=n[0],m=n[1]/2+Fo/4,M=Math.sin(m),x=Math.cos(m),b=y-h,_=b>=0?1:-1,w=_*b,S=w>Fo,k=g*M;if(ka.add(Math.atan2(k*_*Math.sin(w),v*x+k*Math.cos(w))),u+=S?b+_*Ho:b,S^h>=e^y>=e){var N=mt(dt(s),dt(n));bt(N);var E=mt(i,N);bt(E);var A=(S^b>=0?-1:1)*tn(E[2]);(r>A||r===A&&(N[0]||N[1]))&&(o+=S^b>=0?1:-1)}if(!d++)break;h=y,g=M,v=x,s=n}}return(-Uo>u||Uo>u&&-Uo>ka)^1&o}function It(n){function t(n,t){return Math.cos(n)*Math.cos(t)>u}function e(n){var e,u,l,c,f;return{lineStart:function(){c=l=!1,f=1},point:function(s,h){var p,g=[s,h],v=t(s,h),d=o?v?0:i(s,h):v?i(s+(0>s?Fo:-Fo),h):0;if(!e&&(c=l=v)&&n.lineStart(),v!==l&&(p=r(e,g),(wt(e,p)||wt(g,p))&&(g[0]+=Uo,g[1]+=Uo,v=t(g[0],g[1]))),v!==l)f=0,v?(n.lineStart(),p=r(g,e),n.point(p[0],p[1])):(p=r(e,g),n.point(p[0],p[1]),n.lineEnd()),e=p;else if(a&&e&&o^v){var y;d&u||!(y=r(g,e,!0))||(f=0,o?(n.lineStart(),n.point(y[0][0],y[0][1]),n.point(y[1][0],y[1][1]),n.lineEnd()):(n.point(y[1][0],y[1][1]),n.lineEnd(),n.lineStart(),n.point(y[0][0],y[0][1])))}!v||e&&wt(e,g)||n.point(g[0],g[1]),e=g,l=v,u=d},lineEnd:function(){l&&n.lineEnd(),e=null},clean:function(){return f|(c&&l)<<1}}}function r(n,t,e){var r=dt(n),i=dt(t),o=[1,0,0],a=mt(r,i),l=yt(a,a),c=a[0],f=l-c*c;if(!f)return!e&&n;var s=u*l/f,h=-u*c/f,p=mt(o,a),g=xt(o,s),v=xt(a,h);Mt(g,v);var d=p,y=yt(g,d),m=yt(d,d),M=y*y-m*(yt(g,g)-1);if(!(0>M)){var x=Math.sqrt(M),b=xt(d,(-y-x)/m);if(Mt(b,g),b=_t(b),!e)return b;var _,w=n[0],S=t[0],k=n[1],N=t[1];w>S&&(_=w,w=S,S=_);var E=S-w,A=xo(E-Fo)<Uo,C=A||Uo>E;if(!A&&k>N&&(_=k,k=N,N=_),C?A?k+N>0^b[1]<(xo(b[0]-w)<Uo?k:N):k<=b[1]&&b[1]<=N:E>Fo^(w<=b[0]&&b[0]<=S)){var z=xt(d,(-y+x)/m);return Mt(z,g),[b,_t(z)]}}}function i(t,e){var r=o?n:Fo-n,i=0;return-r>t?i|=1:t>r&&(i|=2),-r>e?i|=4:e>r&&(i|=8),i}var u=Math.cos(n),o=u>0,a=xo(u)>Uo,l=ve(n,6*Yo);return Rt(t,e,l,o?[0,-n]:[-Fo,n-Fo])}function Yt(n,t,e,r){return function(i){var u,o=i.a,a=i.b,l=o.x,c=o.y,f=a.x,s=a.y,h=0,p=1,g=f-l,v=s-c;if(u=n-l,g||!(u>0)){if(u/=g,0>g){if(h>u)return;p>u&&(p=u)}else if(g>0){if(u>p)return;u>h&&(h=u)}if(u=e-l,g||!(0>u)){if(u/=g,0>g){if(u>p)return;u>h&&(h=u)}else if(g>0){if(h>u)return;p>u&&(p=u)}if(u=t-c,v||!(u>0)){if(u/=v,0>v){if(h>u)return;p>u&&(p=u)}else if(v>0){if(u>p)return;u>h&&(h=u)}if(u=r-c,v||!(0>u)){if(u/=v,0>v){if(u>p)return;u>h&&(h=u)}else if(v>0){if(h>u)return;p>u&&(p=u)}return h>0&&(i.a={x:l+h*g,y:c+h*v}),1>p&&(i.b={x:l+p*g,y:c+p*v}),i}}}}}}function Zt(n,t,e,r){function i(r,i){return xo(r[0]-n)<Uo?i>0?0:3:xo(r[0]-e)<Uo?i>0?2:1:xo(r[1]-t)<Uo?i>0?1:0:i>0?3:2}function u(n,t){return o(n.x,t.x)}function o(n,t){var e=i(n,1),r=i(t,1);return e!==r?e-r:0===e?t[1]-n[1]:1===e?n[0]-t[0]:2===e?n[1]-t[1]:t[0]-n[0]}return function(a){function l(n){for(var t=0,e=d.length,r=n[1],i=0;e>i;++i)for(var u,o=1,a=d[i],l=a.length,c=a[0];l>o;++o)u=a[o],c[1]<=r?u[1]>r&&Q(c,u,n)>0&&++t:u[1]<=r&&Q(c,u,n)<0&&--t,c=u;return 0!==t}function c(u,a,l,c){var f=0,s=0;if(null==u||(f=i(u,l))!==(s=i(a,l))||o(u,a)<0^l>0){do c.point(0===f||3===f?n:e,f>1?r:t);while((f=(f+l+4)%4)!==s)}else c.point(a[0],a[1])}function f(i,u){return i>=n&&e>=i&&u>=t&&r>=u}function s(n,t){f(n,t)&&a.point(n,t)}function h(){C.point=g,d&&d.push(y=[]),S=!0,w=!1,b=_=NaN}function p(){v&&(g(m,M),x&&w&&E.rejoin(),v.push(E.buffer())),C.point=s,w&&a.lineEnd()}function g(n,t){n=Math.max(-Ha,Math.min(Ha,n)),t=Math.max(-Ha,Math.min(Ha,t));var e=f(n,t);if(d&&y.push([n,t]),S)m=n,M=t,x=e,S=!1,e&&(a.lineStart(),a.point(n,t));else if(e&&w)a.point(n,t);else{var r={a:{x:b,y:_},b:{x:n,y:t}};A(r)?(w||(a.lineStart(),a.point(r.a.x,r.a.y)),a.point(r.b.x,r.b.y),e||a.lineEnd(),k=!1):e&&(a.lineStart(),a.point(n,t),k=!1)}b=n,_=t,w=e}var v,d,y,m,M,x,b,_,w,S,k,N=a,E=Pt(),A=Yt(n,t,e,r),C={point:s,lineStart:h,lineEnd:p,polygonStart:function(){a=E,v=[],d=[],k=!0},polygonEnd:function(){a=N,v=ao.merge(v);var t=l([n,r]),e=k&&t,i=v.length;(e||i)&&(a.polygonStart(),e&&(a.lineStart(),c(null,null,1,a),a.lineEnd()),i&&Lt(v,u,t,c,a),a.polygonEnd()),v=d=y=null}};return C}}function Vt(n){var t=0,e=Fo/3,r=ae(n),i=r(t,e);return i.parallels=function(n){return arguments.length?r(t=n[0]*Fo/180,e=n[1]*Fo/180):[t/Fo*180,e/Fo*180]},i}function Xt(n,t){function e(n,t){var e=Math.sqrt(u-2*i*Math.sin(t))/i;return[e*Math.sin(n*=i),o-e*Math.cos(n)]}var r=Math.sin(n),i=(r+Math.sin(t))/2,u=1+r*(2*i-r),o=Math.sqrt(u)/i;return e.invert=function(n,t){var e=o-t;return[Math.atan2(n,e)/i,tn((u-(n*n+e*e)*i*i)/(2*i))]},e}function $t(){function n(n,t){Ia+=i*n-r*t,r=n,i=t}var t,e,r,i;$a.point=function(u,o){$a.point=n,t=r=u,e=i=o},$a.lineEnd=function(){n(t,e)}}function Bt(n,t){Ya>n&&(Ya=n),n>Va&&(Va=n),Za>t&&(Za=t),t>Xa&&(Xa=t)}function Wt(){function n(n,t){o.push("M",n,",",t,u)}function t(n,t){o.push("M",n,",",t),a.point=e}function e(n,t){o.push("L",n,",",t)}function r(){a.point=n}function i(){o.push("Z")}var u=Jt(4.5),o=[],a={point:n,lineStart:function(){a.point=t},lineEnd:r,polygonStart:function(){a.lineEnd=i},polygonEnd:function(){a.lineEnd=r,a.point=n},pointRadius:function(n){return u=Jt(n),a},result:function(){if(o.length){var n=o.join("");return o=[],n}}};return a}function Jt(n){return"m0,"+n+"a"+n+","+n+" 0 1,1 0,"+-2*n+"a"+n+","+n+" 0 1,1 0,"+2*n+"z"}function Gt(n,t){Ca+=n,za+=t,++La}function Kt(){function n(n,r){var i=n-t,u=r-e,o=Math.sqrt(i*i+u*u);qa+=o*(t+n)/2,Ta+=o*(e+r)/2,Ra+=o,Gt(t=n,e=r)}var t,e;Wa.point=function(r,i){Wa.point=n,Gt(t=r,e=i)}}function Qt(){Wa.point=Gt}function ne(){function n(n,t){var e=n-r,u=t-i,o=Math.sqrt(e*e+u*u);qa+=o*(r+n)/2,Ta+=o*(i+t)/2,Ra+=o,o=i*n-r*t,Da+=o*(r+n),Pa+=o*(i+t),Ua+=3*o,Gt(r=n,i=t)}var t,e,r,i;Wa.point=function(u,o){Wa.point=n,Gt(t=r=u,e=i=o)},Wa.lineEnd=function(){n(t,e)}}function te(n){function t(t,e){n.moveTo(t+o,e),n.arc(t,e,o,0,Ho)}function e(t,e){n.moveTo(t,e),a.point=r}function r(t,e){n.lineTo(t,e)}function i(){a.point=t}function u(){n.closePath()}var o=4.5,a={point:t,lineStart:function(){a.point=e},lineEnd:i,polygonStart:function(){a.lineEnd=u},polygonEnd:function(){a.lineEnd=i,a.point=t},pointRadius:function(n){return o=n,a},result:b};return a}function ee(n){function t(n){return(a?r:e)(n)}function e(t){return ue(t,function(e,r){e=n(e,r),t.point(e[0],e[1])})}function r(t){function e(e,r){e=n(e,r),t.point(e[0],e[1])}function r(){M=NaN,S.point=u,t.lineStart()}function u(e,r){var u=dt([e,r]),o=n(e,r);i(M,x,m,b,_,w,M=o[0],x=o[1],m=e,b=u[0],_=u[1],w=u[2],a,t),t.point(M,x)}function o(){S.point=e,t.lineEnd()}function l(){
+r(),S.point=c,S.lineEnd=f}function c(n,t){u(s=n,h=t),p=M,g=x,v=b,d=_,y=w,S.point=u}function f(){i(M,x,m,b,_,w,p,g,s,v,d,y,a,t),S.lineEnd=o,o()}var s,h,p,g,v,d,y,m,M,x,b,_,w,S={point:e,lineStart:r,lineEnd:o,polygonStart:function(){t.polygonStart(),S.lineStart=l},polygonEnd:function(){t.polygonEnd(),S.lineStart=r}};return S}function i(t,e,r,a,l,c,f,s,h,p,g,v,d,y){var m=f-t,M=s-e,x=m*m+M*M;if(x>4*u&&d--){var b=a+p,_=l+g,w=c+v,S=Math.sqrt(b*b+_*_+w*w),k=Math.asin(w/=S),N=xo(xo(w)-1)<Uo||xo(r-h)<Uo?(r+h)/2:Math.atan2(_,b),E=n(N,k),A=E[0],C=E[1],z=A-t,L=C-e,q=M*z-m*L;(q*q/x>u||xo((m*z+M*L)/x-.5)>.3||o>a*p+l*g+c*v)&&(i(t,e,r,a,l,c,A,C,N,b/=S,_/=S,w,d,y),y.point(A,C),i(A,C,N,b,_,w,f,s,h,p,g,v,d,y))}}var u=.5,o=Math.cos(30*Yo),a=16;return t.precision=function(n){return arguments.length?(a=(u=n*n)>0&&16,t):Math.sqrt(u)},t}function re(n){var t=ee(function(t,e){return n([t*Zo,e*Zo])});return function(n){return le(t(n))}}function ie(n){this.stream=n}function ue(n,t){return{point:t,sphere:function(){n.sphere()},lineStart:function(){n.lineStart()},lineEnd:function(){n.lineEnd()},polygonStart:function(){n.polygonStart()},polygonEnd:function(){n.polygonEnd()}}}function oe(n){return ae(function(){return n})()}function ae(n){function t(n){return n=a(n[0]*Yo,n[1]*Yo),[n[0]*h+l,c-n[1]*h]}function e(n){return n=a.invert((n[0]-l)/h,(c-n[1])/h),n&&[n[0]*Zo,n[1]*Zo]}function r(){a=Ct(o=se(y,M,x),u);var n=u(v,d);return l=p-n[0]*h,c=g+n[1]*h,i()}function i(){return f&&(f.valid=!1,f=null),t}var u,o,a,l,c,f,s=ee(function(n,t){return n=u(n,t),[n[0]*h+l,c-n[1]*h]}),h=150,p=480,g=250,v=0,d=0,y=0,M=0,x=0,b=Fa,_=m,w=null,S=null;return t.stream=function(n){return f&&(f.valid=!1),f=le(b(o,s(_(n)))),f.valid=!0,f},t.clipAngle=function(n){return arguments.length?(b=null==n?(w=n,Fa):It((w=+n)*Yo),i()):w},t.clipExtent=function(n){return arguments.length?(S=n,_=n?Zt(n[0][0],n[0][1],n[1][0],n[1][1]):m,i()):S},t.scale=function(n){return arguments.length?(h=+n,r()):h},t.translate=function(n){return arguments.length?(p=+n[0],g=+n[1],r()):[p,g]},t.center=function(n){return arguments.length?(v=n[0]%360*Yo,d=n[1]%360*Yo,r()):[v*Zo,d*Zo]},t.rotate=function(n){return arguments.length?(y=n[0]%360*Yo,M=n[1]%360*Yo,x=n.length>2?n[2]%360*Yo:0,r()):[y*Zo,M*Zo,x*Zo]},ao.rebind(t,s,"precision"),function(){return u=n.apply(this,arguments),t.invert=u.invert&&e,r()}}function le(n){return ue(n,function(t,e){n.point(t*Yo,e*Yo)})}function ce(n,t){return[n,t]}function fe(n,t){return[n>Fo?n-Ho:-Fo>n?n+Ho:n,t]}function se(n,t,e){return n?t||e?Ct(pe(n),ge(t,e)):pe(n):t||e?ge(t,e):fe}function he(n){return function(t,e){return t+=n,[t>Fo?t-Ho:-Fo>t?t+Ho:t,e]}}function pe(n){var t=he(n);return t.invert=he(-n),t}function ge(n,t){function e(n,t){var e=Math.cos(t),a=Math.cos(n)*e,l=Math.sin(n)*e,c=Math.sin(t),f=c*r+a*i;return[Math.atan2(l*u-f*o,a*r-c*i),tn(f*u+l*o)]}var r=Math.cos(n),i=Math.sin(n),u=Math.cos(t),o=Math.sin(t);return e.invert=function(n,t){var e=Math.cos(t),a=Math.cos(n)*e,l=Math.sin(n)*e,c=Math.sin(t),f=c*u-l*o;return[Math.atan2(l*u+c*o,a*r+f*i),tn(f*r-a*i)]},e}function ve(n,t){var e=Math.cos(n),r=Math.sin(n);return function(i,u,o,a){var l=o*t;null!=i?(i=de(e,i),u=de(e,u),(o>0?u>i:i>u)&&(i+=o*Ho)):(i=n+o*Ho,u=n-.5*l);for(var c,f=i;o>0?f>u:u>f;f-=l)a.point((c=_t([e,-r*Math.cos(f),-r*Math.sin(f)]))[0],c[1])}}function de(n,t){var e=dt(t);e[0]-=n,bt(e);var r=nn(-e[1]);return((-e[2]<0?-r:r)+2*Math.PI-Uo)%(2*Math.PI)}function ye(n,t,e){var r=ao.range(n,t-Uo,e).concat(t);return function(n){return r.map(function(t){return[n,t]})}}function me(n,t,e){var r=ao.range(n,t-Uo,e).concat(t);return function(n){return r.map(function(t){return[t,n]})}}function Me(n){return n.source}function xe(n){return n.target}function be(n,t,e,r){var i=Math.cos(t),u=Math.sin(t),o=Math.cos(r),a=Math.sin(r),l=i*Math.cos(n),c=i*Math.sin(n),f=o*Math.cos(e),s=o*Math.sin(e),h=2*Math.asin(Math.sqrt(on(r-t)+i*o*on(e-n))),p=1/Math.sin(h),g=h?function(n){var t=Math.sin(n*=h)*p,e=Math.sin(h-n)*p,r=e*l+t*f,i=e*c+t*s,o=e*u+t*a;return[Math.atan2(i,r)*Zo,Math.atan2(o,Math.sqrt(r*r+i*i))*Zo]}:function(){return[n*Zo,t*Zo]};return g.distance=h,g}function _e(){function n(n,i){var u=Math.sin(i*=Yo),o=Math.cos(i),a=xo((n*=Yo)-t),l=Math.cos(a);Ja+=Math.atan2(Math.sqrt((a=o*Math.sin(a))*a+(a=r*u-e*o*l)*a),e*u+r*o*l),t=n,e=u,r=o}var t,e,r;Ga.point=function(i,u){t=i*Yo,e=Math.sin(u*=Yo),r=Math.cos(u),Ga.point=n},Ga.lineEnd=function(){Ga.point=Ga.lineEnd=b}}function we(n,t){function e(t,e){var r=Math.cos(t),i=Math.cos(e),u=n(r*i);return[u*i*Math.sin(t),u*Math.sin(e)]}return e.invert=function(n,e){var r=Math.sqrt(n*n+e*e),i=t(r),u=Math.sin(i),o=Math.cos(i);return[Math.atan2(n*u,r*o),Math.asin(r&&e*u/r)]},e}function Se(n,t){function e(n,t){o>0?-Io+Uo>t&&(t=-Io+Uo):t>Io-Uo&&(t=Io-Uo);var e=o/Math.pow(i(t),u);return[e*Math.sin(u*n),o-e*Math.cos(u*n)]}var r=Math.cos(n),i=function(n){return Math.tan(Fo/4+n/2)},u=n===t?Math.sin(n):Math.log(r/Math.cos(t))/Math.log(i(t)/i(n)),o=r*Math.pow(i(n),u)/u;return u?(e.invert=function(n,t){var e=o-t,r=K(u)*Math.sqrt(n*n+e*e);return[Math.atan2(n,e)/u,2*Math.atan(Math.pow(o/r,1/u))-Io]},e):Ne}function ke(n,t){function e(n,t){var e=u-t;return[e*Math.sin(i*n),u-e*Math.cos(i*n)]}var r=Math.cos(n),i=n===t?Math.sin(n):(r-Math.cos(t))/(t-n),u=r/i+n;return xo(i)<Uo?ce:(e.invert=function(n,t){var e=u-t;return[Math.atan2(n,e)/i,u-K(i)*Math.sqrt(n*n+e*e)]},e)}function Ne(n,t){return[n,Math.log(Math.tan(Fo/4+t/2))]}function Ee(n){var t,e=oe(n),r=e.scale,i=e.translate,u=e.clipExtent;return e.scale=function(){var n=r.apply(e,arguments);return n===e?t?e.clipExtent(null):e:n},e.translate=function(){var n=i.apply(e,arguments);return n===e?t?e.clipExtent(null):e:n},e.clipExtent=function(n){var o=u.apply(e,arguments);if(o===e){if(t=null==n){var a=Fo*r(),l=i();u([[l[0]-a,l[1]-a],[l[0]+a,l[1]+a]])}}else t&&(o=null);return o},e.clipExtent(null)}function Ae(n,t){return[Math.log(Math.tan(Fo/4+t/2)),-n]}function Ce(n){return n[0]}function ze(n){return n[1]}function Le(n){for(var t=n.length,e=[0,1],r=2,i=2;t>i;i++){for(;r>1&&Q(n[e[r-2]],n[e[r-1]],n[i])<=0;)--r;e[r++]=i}return e.slice(0,r)}function qe(n,t){return n[0]-t[0]||n[1]-t[1]}function Te(n,t,e){return(e[0]-t[0])*(n[1]-t[1])<(e[1]-t[1])*(n[0]-t[0])}function Re(n,t,e,r){var i=n[0],u=e[0],o=t[0]-i,a=r[0]-u,l=n[1],c=e[1],f=t[1]-l,s=r[1]-c,h=(a*(l-c)-s*(i-u))/(s*o-a*f);return[i+h*o,l+h*f]}function De(n){var t=n[0],e=n[n.length-1];return!(t[0]-e[0]||t[1]-e[1])}function Pe(){rr(this),this.edge=this.site=this.circle=null}function Ue(n){var t=cl.pop()||new Pe;return t.site=n,t}function je(n){Be(n),ol.remove(n),cl.push(n),rr(n)}function Fe(n){var t=n.circle,e=t.x,r=t.cy,i={x:e,y:r},u=n.P,o=n.N,a=[n];je(n);for(var l=u;l.circle&&xo(e-l.circle.x)<Uo&&xo(r-l.circle.cy)<Uo;)u=l.P,a.unshift(l),je(l),l=u;a.unshift(l),Be(l);for(var c=o;c.circle&&xo(e-c.circle.x)<Uo&&xo(r-c.circle.cy)<Uo;)o=c.N,a.push(c),je(c),c=o;a.push(c),Be(c);var f,s=a.length;for(f=1;s>f;++f)c=a[f],l=a[f-1],nr(c.edge,l.site,c.site,i);l=a[0],c=a[s-1],c.edge=Ke(l.site,c.site,null,i),$e(l),$e(c)}function He(n){for(var t,e,r,i,u=n.x,o=n.y,a=ol._;a;)if(r=Oe(a,o)-u,r>Uo)a=a.L;else{if(i=u-Ie(a,o),!(i>Uo)){r>-Uo?(t=a.P,e=a):i>-Uo?(t=a,e=a.N):t=e=a;break}if(!a.R){t=a;break}a=a.R}var l=Ue(n);if(ol.insert(t,l),t||e){if(t===e)return Be(t),e=Ue(t.site),ol.insert(l,e),l.edge=e.edge=Ke(t.site,l.site),$e(t),void $e(e);if(!e)return void(l.edge=Ke(t.site,l.site));Be(t),Be(e);var c=t.site,f=c.x,s=c.y,h=n.x-f,p=n.y-s,g=e.site,v=g.x-f,d=g.y-s,y=2*(h*d-p*v),m=h*h+p*p,M=v*v+d*d,x={x:(d*m-p*M)/y+f,y:(h*M-v*m)/y+s};nr(e.edge,c,g,x),l.edge=Ke(c,n,null,x),e.edge=Ke(n,g,null,x),$e(t),$e(e)}}function Oe(n,t){var e=n.site,r=e.x,i=e.y,u=i-t;if(!u)return r;var o=n.P;if(!o)return-(1/0);e=o.site;var a=e.x,l=e.y,c=l-t;if(!c)return a;var f=a-r,s=1/u-1/c,h=f/c;return s?(-h+Math.sqrt(h*h-2*s*(f*f/(-2*c)-l+c/2+i-u/2)))/s+r:(r+a)/2}function Ie(n,t){var e=n.N;if(e)return Oe(e,t);var r=n.site;return r.y===t?r.x:1/0}function Ye(n){this.site=n,this.edges=[]}function Ze(n){for(var t,e,r,i,u,o,a,l,c,f,s=n[0][0],h=n[1][0],p=n[0][1],g=n[1][1],v=ul,d=v.length;d--;)if(u=v[d],u&&u.prepare())for(a=u.edges,l=a.length,o=0;l>o;)f=a[o].end(),r=f.x,i=f.y,c=a[++o%l].start(),t=c.x,e=c.y,(xo(r-t)>Uo||xo(i-e)>Uo)&&(a.splice(o,0,new tr(Qe(u.site,f,xo(r-s)<Uo&&g-i>Uo?{x:s,y:xo(t-s)<Uo?e:g}:xo(i-g)<Uo&&h-r>Uo?{x:xo(e-g)<Uo?t:h,y:g}:xo(r-h)<Uo&&i-p>Uo?{x:h,y:xo(t-h)<Uo?e:p}:xo(i-p)<Uo&&r-s>Uo?{x:xo(e-p)<Uo?t:s,y:p}:null),u.site,null)),++l)}function Ve(n,t){return t.angle-n.angle}function Xe(){rr(this),this.x=this.y=this.arc=this.site=this.cy=null}function $e(n){var t=n.P,e=n.N;if(t&&e){var r=t.site,i=n.site,u=e.site;if(r!==u){var o=i.x,a=i.y,l=r.x-o,c=r.y-a,f=u.x-o,s=u.y-a,h=2*(l*s-c*f);if(!(h>=-jo)){var p=l*l+c*c,g=f*f+s*s,v=(s*p-c*g)/h,d=(l*g-f*p)/h,s=d+a,y=fl.pop()||new Xe;y.arc=n,y.site=i,y.x=v+o,y.y=s+Math.sqrt(v*v+d*d),y.cy=s,n.circle=y;for(var m=null,M=ll._;M;)if(y.y<M.y||y.y===M.y&&y.x<=M.x){if(!M.L){m=M.P;break}M=M.L}else{if(!M.R){m=M;break}M=M.R}ll.insert(m,y),m||(al=y)}}}}function Be(n){var t=n.circle;t&&(t.P||(al=t.N),ll.remove(t),fl.push(t),rr(t),n.circle=null)}function We(n){for(var t,e=il,r=Yt(n[0][0],n[0][1],n[1][0],n[1][1]),i=e.length;i--;)t=e[i],(!Je(t,n)||!r(t)||xo(t.a.x-t.b.x)<Uo&&xo(t.a.y-t.b.y)<Uo)&&(t.a=t.b=null,e.splice(i,1))}function Je(n,t){var e=n.b;if(e)return!0;var r,i,u=n.a,o=t[0][0],a=t[1][0],l=t[0][1],c=t[1][1],f=n.l,s=n.r,h=f.x,p=f.y,g=s.x,v=s.y,d=(h+g)/2,y=(p+v)/2;if(v===p){if(o>d||d>=a)return;if(h>g){if(u){if(u.y>=c)return}else u={x:d,y:l};e={x:d,y:c}}else{if(u){if(u.y<l)return}else u={x:d,y:c};e={x:d,y:l}}}else if(r=(h-g)/(v-p),i=y-r*d,-1>r||r>1)if(h>g){if(u){if(u.y>=c)return}else u={x:(l-i)/r,y:l};e={x:(c-i)/r,y:c}}else{if(u){if(u.y<l)return}else u={x:(c-i)/r,y:c};e={x:(l-i)/r,y:l}}else if(v>p){if(u){if(u.x>=a)return}else u={x:o,y:r*o+i};e={x:a,y:r*a+i}}else{if(u){if(u.x<o)return}else u={x:a,y:r*a+i};e={x:o,y:r*o+i}}return n.a=u,n.b=e,!0}function Ge(n,t){this.l=n,this.r=t,this.a=this.b=null}function Ke(n,t,e,r){var i=new Ge(n,t);return il.push(i),e&&nr(i,n,t,e),r&&nr(i,t,n,r),ul[n.i].edges.push(new tr(i,n,t)),ul[t.i].edges.push(new tr(i,t,n)),i}function Qe(n,t,e){var r=new Ge(n,null);return r.a=t,r.b=e,il.push(r),r}function nr(n,t,e,r){n.a||n.b?n.l===e?n.b=r:n.a=r:(n.a=r,n.l=t,n.r=e)}function tr(n,t,e){var r=n.a,i=n.b;this.edge=n,this.site=t,this.angle=e?Math.atan2(e.y-t.y,e.x-t.x):n.l===t?Math.atan2(i.x-r.x,r.y-i.y):Math.atan2(r.x-i.x,i.y-r.y)}function er(){this._=null}function rr(n){n.U=n.C=n.L=n.R=n.P=n.N=null}function ir(n,t){var e=t,r=t.R,i=e.U;i?i.L===e?i.L=r:i.R=r:n._=r,r.U=i,e.U=r,e.R=r.L,e.R&&(e.R.U=e),r.L=e}function ur(n,t){var e=t,r=t.L,i=e.U;i?i.L===e?i.L=r:i.R=r:n._=r,r.U=i,e.U=r,e.L=r.R,e.L&&(e.L.U=e),r.R=e}function or(n){for(;n.L;)n=n.L;return n}function ar(n,t){var e,r,i,u=n.sort(lr).pop();for(il=[],ul=new Array(n.length),ol=new er,ll=new er;;)if(i=al,u&&(!i||u.y<i.y||u.y===i.y&&u.x<i.x))u.x===e&&u.y===r||(ul[u.i]=new Ye(u),He(u),e=u.x,r=u.y),u=n.pop();else{if(!i)break;Fe(i.arc)}t&&(We(t),Ze(t));var o={cells:ul,edges:il};return ol=ll=il=ul=null,o}function lr(n,t){return t.y-n.y||t.x-n.x}function cr(n,t,e){return(n.x-e.x)*(t.y-n.y)-(n.x-t.x)*(e.y-n.y)}function fr(n){return n.x}function sr(n){return n.y}function hr(){return{leaf:!0,nodes:[],point:null,x:null,y:null}}function pr(n,t,e,r,i,u){if(!n(t,e,r,i,u)){var o=.5*(e+i),a=.5*(r+u),l=t.nodes;l[0]&&pr(n,l[0],e,r,o,a),l[1]&&pr(n,l[1],o,r,i,a),l[2]&&pr(n,l[2],e,a,o,u),l[3]&&pr(n,l[3],o,a,i,u)}}function gr(n,t,e,r,i,u,o){var a,l=1/0;return function c(n,f,s,h,p){if(!(f>u||s>o||r>h||i>p)){if(g=n.point){var g,v=t-n.x,d=e-n.y,y=v*v+d*d;if(l>y){var m=Math.sqrt(l=y);r=t-m,i=e-m,u=t+m,o=e+m,a=g}}for(var M=n.nodes,x=.5*(f+h),b=.5*(s+p),_=t>=x,w=e>=b,S=w<<1|_,k=S+4;k>S;++S)if(n=M[3&S])switch(3&S){case 0:c(n,f,s,x,b);break;case 1:c(n,x,s,h,b);break;case 2:c(n,f,b,x,p);break;case 3:c(n,x,b,h,p)}}}(n,r,i,u,o),a}function vr(n,t){n=ao.rgb(n),t=ao.rgb(t);var e=n.r,r=n.g,i=n.b,u=t.r-e,o=t.g-r,a=t.b-i;return function(n){return"#"+bn(Math.round(e+u*n))+bn(Math.round(r+o*n))+bn(Math.round(i+a*n))}}function dr(n,t){var e,r={},i={};for(e in n)e in t?r[e]=Mr(n[e],t[e]):i[e]=n[e];for(e in t)e in n||(i[e]=t[e]);return function(n){for(e in r)i[e]=r[e](n);return i}}function yr(n,t){return n=+n,t=+t,function(e){return n*(1-e)+t*e}}function mr(n,t){var e,r,i,u=hl.lastIndex=pl.lastIndex=0,o=-1,a=[],l=[];for(n+="",t+="";(e=hl.exec(n))&&(r=pl.exec(t));)(i=r.index)>u&&(i=t.slice(u,i),a[o]?a[o]+=i:a[++o]=i),(e=e[0])===(r=r[0])?a[o]?a[o]+=r:a[++o]=r:(a[++o]=null,l.push({i:o,x:yr(e,r)})),u=pl.lastIndex;return u<t.length&&(i=t.slice(u),a[o]?a[o]+=i:a[++o]=i),a.length<2?l[0]?(t=l[0].x,function(n){return t(n)+""}):function(){return t}:(t=l.length,function(n){for(var e,r=0;t>r;++r)a[(e=l[r]).i]=e.x(n);return a.join("")})}function Mr(n,t){for(var e,r=ao.interpolators.length;--r>=0&&!(e=ao.interpolators[r](n,t)););return e}function xr(n,t){var e,r=[],i=[],u=n.length,o=t.length,a=Math.min(n.length,t.length);for(e=0;a>e;++e)r.push(Mr(n[e],t[e]));for(;u>e;++e)i[e]=n[e];for(;o>e;++e)i[e]=t[e];return function(n){for(e=0;a>e;++e)i[e]=r[e](n);return i}}function br(n){return function(t){return 0>=t?0:t>=1?1:n(t)}}function _r(n){return function(t){return 1-n(1-t)}}function wr(n){return function(t){return.5*(.5>t?n(2*t):2-n(2-2*t))}}function Sr(n){return n*n}function kr(n){return n*n*n}function Nr(n){if(0>=n)return 0;if(n>=1)return 1;var t=n*n,e=t*n;return 4*(.5>n?e:3*(n-t)+e-.75)}function Er(n){return function(t){return Math.pow(t,n)}}function Ar(n){return 1-Math.cos(n*Io)}function Cr(n){return Math.pow(2,10*(n-1))}function zr(n){return 1-Math.sqrt(1-n*n)}function Lr(n,t){var e;return arguments.length<2&&(t=.45),arguments.length?e=t/Ho*Math.asin(1/n):(n=1,e=t/4),function(r){return 1+n*Math.pow(2,-10*r)*Math.sin((r-e)*Ho/t)}}function qr(n){return n||(n=1.70158),function(t){return t*t*((n+1)*t-n)}}function Tr(n){return 1/2.75>n?7.5625*n*n:2/2.75>n?7.5625*(n-=1.5/2.75)*n+.75:2.5/2.75>n?7.5625*(n-=2.25/2.75)*n+.9375:7.5625*(n-=2.625/2.75)*n+.984375}function Rr(n,t){n=ao.hcl(n),t=ao.hcl(t);var e=n.h,r=n.c,i=n.l,u=t.h-e,o=t.c-r,a=t.l-i;return isNaN(o)&&(o=0,r=isNaN(r)?t.c:r),isNaN(u)?(u=0,e=isNaN(e)?t.h:e):u>180?u-=360:-180>u&&(u+=360),function(n){return sn(e+u*n,r+o*n,i+a*n)+""}}function Dr(n,t){n=ao.hsl(n),t=ao.hsl(t);var e=n.h,r=n.s,i=n.l,u=t.h-e,o=t.s-r,a=t.l-i;return isNaN(o)&&(o=0,r=isNaN(r)?t.s:r),isNaN(u)?(u=0,e=isNaN(e)?t.h:e):u>180?u-=360:-180>u&&(u+=360),function(n){return cn(e+u*n,r+o*n,i+a*n)+""}}function Pr(n,t){n=ao.lab(n),t=ao.lab(t);var e=n.l,r=n.a,i=n.b,u=t.l-e,o=t.a-r,a=t.b-i;return function(n){return pn(e+u*n,r+o*n,i+a*n)+""}}function Ur(n,t){return t-=n,function(e){return Math.round(n+t*e)}}function jr(n){var t=[n.a,n.b],e=[n.c,n.d],r=Hr(t),i=Fr(t,e),u=Hr(Or(e,t,-i))||0;t[0]*e[1]<e[0]*t[1]&&(t[0]*=-1,t[1]*=-1,r*=-1,i*=-1),this.rotate=(r?Math.atan2(t[1],t[0]):Math.atan2(-e[0],e[1]))*Zo,this.translate=[n.e,n.f],this.scale=[r,u],this.skew=u?Math.atan2(i,u)*Zo:0}function Fr(n,t){return n[0]*t[0]+n[1]*t[1]}function Hr(n){var t=Math.sqrt(Fr(n,n));return t&&(n[0]/=t,n[1]/=t),t}function Or(n,t,e){return n[0]+=e*t[0],n[1]+=e*t[1],n}function Ir(n){return n.length?n.pop()+",":""}function Yr(n,t,e,r){if(n[0]!==t[0]||n[1]!==t[1]){var i=e.push("translate(",null,",",null,")");r.push({i:i-4,x:yr(n[0],t[0])},{i:i-2,x:yr(n[1],t[1])})}else(t[0]||t[1])&&e.push("translate("+t+")")}function Zr(n,t,e,r){n!==t?(n-t>180?t+=360:t-n>180&&(n+=360),r.push({i:e.push(Ir(e)+"rotate(",null,")")-2,x:yr(n,t)})):t&&e.push(Ir(e)+"rotate("+t+")")}function Vr(n,t,e,r){n!==t?r.push({i:e.push(Ir(e)+"skewX(",null,")")-2,x:yr(n,t)}):t&&e.push(Ir(e)+"skewX("+t+")")}function Xr(n,t,e,r){if(n[0]!==t[0]||n[1]!==t[1]){var i=e.push(Ir(e)+"scale(",null,",",null,")");r.push({i:i-4,x:yr(n[0],t[0])},{i:i-2,x:yr(n[1],t[1])})}else 1===t[0]&&1===t[1]||e.push(Ir(e)+"scale("+t+")")}function $r(n,t){var e=[],r=[];return n=ao.transform(n),t=ao.transform(t),Yr(n.translate,t.translate,e,r),Zr(n.rotate,t.rotate,e,r),Vr(n.skew,t.skew,e,r),Xr(n.scale,t.scale,e,r),n=t=null,function(n){for(var t,i=-1,u=r.length;++i<u;)e[(t=r[i]).i]=t.x(n);return e.join("")}}function Br(n,t){return t=(t-=n=+n)||1/t,function(e){return(e-n)/t}}function Wr(n,t){return t=(t-=n=+n)||1/t,function(e){return Math.max(0,Math.min(1,(e-n)/t))}}function Jr(n){for(var t=n.source,e=n.target,r=Kr(t,e),i=[t];t!==r;)t=t.parent,i.push(t);for(var u=i.length;e!==r;)i.splice(u,0,e),e=e.parent;return i}function Gr(n){for(var t=[],e=n.parent;null!=e;)t.push(n),n=e,e=e.parent;return t.push(n),t}function Kr(n,t){if(n===t)return n;for(var e=Gr(n),r=Gr(t),i=e.pop(),u=r.pop(),o=null;i===u;)o=i,i=e.pop(),u=r.pop();return o}function Qr(n){n.fixed|=2}function ni(n){n.fixed&=-7}function ti(n){n.fixed|=4,n.px=n.x,n.py=n.y}function ei(n){n.fixed&=-5}function ri(n,t,e){var r=0,i=0;if(n.charge=0,!n.leaf)for(var u,o=n.nodes,a=o.length,l=-1;++l<a;)u=o[l],null!=u&&(ri(u,t,e),n.charge+=u.charge,r+=u.charge*u.cx,i+=u.charge*u.cy);if(n.point){n.leaf||(n.point.x+=Math.random()-.5,n.point.y+=Math.random()-.5);var c=t*e[n.point.index];n.charge+=n.pointCharge=c,r+=c*n.point.x,i+=c*n.point.y}n.cx=r/n.charge,n.cy=i/n.charge}function ii(n,t){return ao.rebind(n,t,"sort","children","value"),n.nodes=n,n.links=fi,n}function ui(n,t){for(var e=[n];null!=(n=e.pop());)if(t(n),(i=n.children)&&(r=i.length))for(var r,i;--r>=0;)e.push(i[r])}function oi(n,t){for(var e=[n],r=[];null!=(n=e.pop());)if(r.push(n),(u=n.children)&&(i=u.length))for(var i,u,o=-1;++o<i;)e.push(u[o]);for(;null!=(n=r.pop());)t(n)}function ai(n){return n.children}function li(n){return n.value}function ci(n,t){return t.value-n.value}function fi(n){return ao.merge(n.map(function(n){return(n.children||[]).map(function(t){return{source:n,target:t}})}))}function si(n){return n.x}function hi(n){return n.y}function pi(n,t,e){n.y0=t,n.y=e}function gi(n){return ao.range(n.length)}function vi(n){for(var t=-1,e=n[0].length,r=[];++t<e;)r[t]=0;return r}function di(n){for(var t,e=1,r=0,i=n[0][1],u=n.length;u>e;++e)(t=n[e][1])>i&&(r=e,i=t);return r}function yi(n){return n.reduce(mi,0)}function mi(n,t){return n+t[1]}function Mi(n,t){return xi(n,Math.ceil(Math.log(t.length)/Math.LN2+1))}function xi(n,t){for(var e=-1,r=+n[0],i=(n[1]-r)/t,u=[];++e<=t;)u[e]=i*e+r;return u}function bi(n){return[ao.min(n),ao.max(n)]}function _i(n,t){return n.value-t.value}function wi(n,t){var e=n._pack_next;n._pack_next=t,t._pack_prev=n,t._pack_next=e,e._pack_prev=t}function Si(n,t){n._pack_next=t,t._pack_prev=n}function ki(n,t){var e=t.x-n.x,r=t.y-n.y,i=n.r+t.r;return.999*i*i>e*e+r*r}function Ni(n){function t(n){f=Math.min(n.x-n.r,f),s=Math.max(n.x+n.r,s),h=Math.min(n.y-n.r,h),p=Math.max(n.y+n.r,p)}if((e=n.children)&&(c=e.length)){var e,r,i,u,o,a,l,c,f=1/0,s=-(1/0),h=1/0,p=-(1/0);if(e.forEach(Ei),r=e[0],r.x=-r.r,r.y=0,t(r),c>1&&(i=e[1],i.x=i.r,i.y=0,t(i),c>2))for(u=e[2],zi(r,i,u),t(u),wi(r,u),r._pack_prev=u,wi(u,i),i=r._pack_next,o=3;c>o;o++){zi(r,i,u=e[o]);var g=0,v=1,d=1;for(a=i._pack_next;a!==i;a=a._pack_next,v++)if(ki(a,u)){g=1;break}if(1==g)for(l=r._pack_prev;l!==a._pack_prev&&!ki(l,u);l=l._pack_prev,d++);g?(d>v||v==d&&i.r<r.r?Si(r,i=a):Si(r=l,i),o--):(wi(r,u),i=u,t(u))}var y=(f+s)/2,m=(h+p)/2,M=0;for(o=0;c>o;o++)u=e[o],u.x-=y,u.y-=m,M=Math.max(M,u.r+Math.sqrt(u.x*u.x+u.y*u.y));n.r=M,e.forEach(Ai)}}function Ei(n){n._pack_next=n._pack_prev=n}function Ai(n){delete n._pack_next,delete n._pack_prev}function Ci(n,t,e,r){var i=n.children;if(n.x=t+=r*n.x,n.y=e+=r*n.y,n.r*=r,i)for(var u=-1,o=i.length;++u<o;)Ci(i[u],t,e,r)}function zi(n,t,e){var r=n.r+e.r,i=t.x-n.x,u=t.y-n.y;if(r&&(i||u)){var o=t.r+e.r,a=i*i+u*u;o*=o,r*=r;var l=.5+(r-o)/(2*a),c=Math.sqrt(Math.max(0,2*o*(r+a)-(r-=a)*r-o*o))/(2*a);e.x=n.x+l*i+c*u,e.y=n.y+l*u-c*i}else e.x=n.x+r,e.y=n.y}function Li(n,t){return n.parent==t.parent?1:2}function qi(n){var t=n.children;return t.length?t[0]:n.t}function Ti(n){var t,e=n.children;return(t=e.length)?e[t-1]:n.t}function Ri(n,t,e){var r=e/(t.i-n.i);t.c-=r,t.s+=e,n.c+=r,t.z+=e,t.m+=e}function Di(n){for(var t,e=0,r=0,i=n.children,u=i.length;--u>=0;)t=i[u],t.z+=e,t.m+=e,e+=t.s+(r+=t.c)}function Pi(n,t,e){return n.a.parent===t.parent?n.a:e}function Ui(n){return 1+ao.max(n,function(n){return n.y})}function ji(n){return n.reduce(function(n,t){return n+t.x},0)/n.length}function Fi(n){var t=n.children;return t&&t.length?Fi(t[0]):n}function Hi(n){var t,e=n.children;return e&&(t=e.length)?Hi(e[t-1]):n}function Oi(n){return{x:n.x,y:n.y,dx:n.dx,dy:n.dy}}function Ii(n,t){var e=n.x+t[3],r=n.y+t[0],i=n.dx-t[1]-t[3],u=n.dy-t[0]-t[2];return 0>i&&(e+=i/2,i=0),0>u&&(r+=u/2,u=0),{x:e,y:r,dx:i,dy:u}}function Yi(n){var t=n[0],e=n[n.length-1];return e>t?[t,e]:[e,t]}function Zi(n){return n.rangeExtent?n.rangeExtent():Yi(n.range())}function Vi(n,t,e,r){var i=e(n[0],n[1]),u=r(t[0],t[1]);return function(n){return u(i(n))}}function Xi(n,t){var e,r=0,i=n.length-1,u=n[r],o=n[i];return u>o&&(e=r,r=i,i=e,e=u,u=o,o=e),n[r]=t.floor(u),n[i]=t.ceil(o),n}function $i(n){return n?{floor:function(t){return Math.floor(t/n)*n},ceil:function(t){return Math.ceil(t/n)*n}}:Sl}function Bi(n,t,e,r){var i=[],u=[],o=0,a=Math.min(n.length,t.length)-1;for(n[a]<n[0]&&(n=n.slice().reverse(),t=t.slice().reverse());++o<=a;)i.push(e(n[o-1],n[o])),u.push(r(t[o-1],t[o]));return function(t){var e=ao.bisect(n,t,1,a)-1;return u[e](i[e](t))}}function Wi(n,t,e,r){function i(){var i=Math.min(n.length,t.length)>2?Bi:Vi,l=r?Wr:Br;return o=i(n,t,l,e),a=i(t,n,l,Mr),u}function u(n){return o(n)}var o,a;return u.invert=function(n){return a(n)},u.domain=function(t){return arguments.length?(n=t.map(Number),i()):n},u.range=function(n){return arguments.length?(t=n,i()):t},u.rangeRound=function(n){return u.range(n).interpolate(Ur)},u.clamp=function(n){return arguments.length?(r=n,i()):r},u.interpolate=function(n){return arguments.length?(e=n,i()):e},u.ticks=function(t){return Qi(n,t)},u.tickFormat=function(t,e){return nu(n,t,e)},u.nice=function(t){return Gi(n,t),i()},u.copy=function(){return Wi(n,t,e,r)},i()}function Ji(n,t){return ao.rebind(n,t,"range","rangeRound","interpolate","clamp")}function Gi(n,t){return Xi(n,$i(Ki(n,t)[2])),Xi(n,$i(Ki(n,t)[2])),n}function Ki(n,t){null==t&&(t=10);var e=Yi(n),r=e[1]-e[0],i=Math.pow(10,Math.floor(Math.log(r/t)/Math.LN10)),u=t/r*i;return.15>=u?i*=10:.35>=u?i*=5:.75>=u&&(i*=2),e[0]=Math.ceil(e[0]/i)*i,e[1]=Math.floor(e[1]/i)*i+.5*i,e[2]=i,e}function Qi(n,t){return ao.range.apply(ao,Ki(n,t))}function nu(n,t,e){var r=Ki(n,t);if(e){var i=ha.exec(e);if(i.shift(),"s"===i[8]){var u=ao.formatPrefix(Math.max(xo(r[0]),xo(r[1])));return i[7]||(i[7]="."+tu(u.scale(r[2]))),i[8]="f",e=ao.format(i.join("")),function(n){return e(u.scale(n))+u.symbol}}i[7]||(i[7]="."+eu(i[8],r)),e=i.join("")}else e=",."+tu(r[2])+"f";return ao.format(e)}function tu(n){return-Math.floor(Math.log(n)/Math.LN10+.01)}function eu(n,t){var e=tu(t[2]);return n in kl?Math.abs(e-tu(Math.max(xo(t[0]),xo(t[1]))))+ +("e"!==n):e-2*("%"===n)}function ru(n,t,e,r){function i(n){return(e?Math.log(0>n?0:n):-Math.log(n>0?0:-n))/Math.log(t)}function u(n){return e?Math.pow(t,n):-Math.pow(t,-n)}function o(t){return n(i(t))}return o.invert=function(t){return u(n.invert(t))},o.domain=function(t){return arguments.length?(e=t[0]>=0,n.domain((r=t.map(Number)).map(i)),o):r},o.base=function(e){return arguments.length?(t=+e,n.domain(r.map(i)),o):t},o.nice=function(){var t=Xi(r.map(i),e?Math:El);return n.domain(t),r=t.map(u),o},o.ticks=function(){var n=Yi(r),o=[],a=n[0],l=n[1],c=Math.floor(i(a)),f=Math.ceil(i(l)),s=t%1?2:t;if(isFinite(f-c)){if(e){for(;f>c;c++)for(var h=1;s>h;h++)o.push(u(c)*h);o.push(u(c))}else for(o.push(u(c));c++<f;)for(var h=s-1;h>0;h--)o.push(u(c)*h);for(c=0;o[c]<a;c++);for(f=o.length;o[f-1]>l;f--);o=o.slice(c,f)}return o},o.tickFormat=function(n,e){if(!arguments.length)return Nl;arguments.length<2?e=Nl:"function"!=typeof e&&(e=ao.format(e));var r=Math.max(1,t*n/o.ticks().length);return function(n){var o=n/u(Math.round(i(n)));return t-.5>o*t&&(o*=t),r>=o?e(n):""}},o.copy=function(){return ru(n.copy(),t,e,r)},Ji(o,n)}function iu(n,t,e){function r(t){return n(i(t))}var i=uu(t),u=uu(1/t);return r.invert=function(t){return u(n.invert(t))},r.domain=function(t){return arguments.length?(n.domain((e=t.map(Number)).map(i)),r):e},r.ticks=function(n){return Qi(e,n)},r.tickFormat=function(n,t){return nu(e,n,t)},r.nice=function(n){return r.domain(Gi(e,n))},r.exponent=function(o){return arguments.length?(i=uu(t=o),u=uu(1/t),n.domain(e.map(i)),r):t},r.copy=function(){return iu(n.copy(),t,e)},Ji(r,n)}function uu(n){return function(t){return 0>t?-Math.pow(-t,n):Math.pow(t,n)}}function ou(n,t){function e(e){return u[((i.get(e)||("range"===t.t?i.set(e,n.push(e)):NaN))-1)%u.length]}function r(t,e){return ao.range(n.length).map(function(n){return t+e*n})}var i,u,o;return e.domain=function(r){if(!arguments.length)return n;n=[],i=new c;for(var u,o=-1,a=r.length;++o<a;)i.has(u=r[o])||i.set(u,n.push(u));return e[t.t].apply(e,t.a)},e.range=function(n){return arguments.length?(u=n,o=0,t={t:"range",a:arguments},e):u},e.rangePoints=function(i,a){arguments.length<2&&(a=0);var l=i[0],c=i[1],f=n.length<2?(l=(l+c)/2,0):(c-l)/(n.length-1+a);return u=r(l+f*a/2,f),o=0,t={t:"rangePoints",a:arguments},e},e.rangeRoundPoints=function(i,a){arguments.length<2&&(a=0);var l=i[0],c=i[1],f=n.length<2?(l=c=Math.round((l+c)/2),0):(c-l)/(n.length-1+a)|0;return u=r(l+Math.round(f*a/2+(c-l-(n.length-1+a)*f)/2),f),o=0,t={t:"rangeRoundPoints",a:arguments},e},e.rangeBands=function(i,a,l){arguments.length<2&&(a=0),arguments.length<3&&(l=a);var c=i[1]<i[0],f=i[c-0],s=i[1-c],h=(s-f)/(n.length-a+2*l);return u=r(f+h*l,h),c&&u.reverse(),o=h*(1-a),t={t:"rangeBands",a:arguments},e},e.rangeRoundBands=function(i,a,l){arguments.length<2&&(a=0),arguments.length<3&&(l=a);var c=i[1]<i[0],f=i[c-0],s=i[1-c],h=Math.floor((s-f)/(n.length-a+2*l));return u=r(f+Math.round((s-f-(n.length-a)*h)/2),h),c&&u.reverse(),o=Math.round(h*(1-a)),t={t:"rangeRoundBands",a:arguments},e},e.rangeBand=function(){return o},e.rangeExtent=function(){return Yi(t.a[0])},e.copy=function(){return ou(n,t)},e.domain(n)}function au(n,t){function u(){var e=0,r=t.length;for(a=[];++e<r;)a[e-1]=ao.quantile(n,e/r);return o}function o(n){return isNaN(n=+n)?void 0:t[ao.bisect(a,n)]}var a;return o.domain=function(t){return arguments.length?(n=t.map(r).filter(i).sort(e),u()):n},o.range=function(n){return arguments.length?(t=n,u()):t},o.quantiles=function(){return a},o.invertExtent=function(e){return e=t.indexOf(e),0>e?[NaN,NaN]:[e>0?a[e-1]:n[0],e<a.length?a[e]:n[n.length-1]]},o.copy=function(){return au(n,t)},u()}function lu(n,t,e){function r(t){return e[Math.max(0,Math.min(o,Math.floor(u*(t-n))))]}function i(){return u=e.length/(t-n),o=e.length-1,r}var u,o;return r.domain=function(e){return arguments.length?(n=+e[0],t=+e[e.length-1],i()):[n,t]},r.range=function(n){return arguments.length?(e=n,i()):e},r.invertExtent=function(t){return t=e.indexOf(t),t=0>t?NaN:t/u+n,[t,t+1/u]},r.copy=function(){return lu(n,t,e)},i()}function cu(n,t){function e(e){return e>=e?t[ao.bisect(n,e)]:void 0}return e.domain=function(t){return arguments.length?(n=t,e):n},e.range=function(n){return arguments.length?(t=n,e):t},e.invertExtent=function(e){return e=t.indexOf(e),[n[e-1],n[e]]},e.copy=function(){return cu(n,t)},e}function fu(n){function t(n){return+n}return t.invert=t,t.domain=t.range=function(e){return arguments.length?(n=e.map(t),t):n},t.ticks=function(t){return Qi(n,t)},t.tickFormat=function(t,e){return nu(n,t,e)},t.copy=function(){return fu(n)},t}function su(){return 0}function hu(n){return n.innerRadius}function pu(n){return n.outerRadius}function gu(n){return n.startAngle}function vu(n){return n.endAngle}function du(n){return n&&n.padAngle}function yu(n,t,e,r){return(n-e)*t-(t-r)*n>0?0:1}function mu(n,t,e,r,i){var u=n[0]-t[0],o=n[1]-t[1],a=(i?r:-r)/Math.sqrt(u*u+o*o),l=a*o,c=-a*u,f=n[0]+l,s=n[1]+c,h=t[0]+l,p=t[1]+c,g=(f+h)/2,v=(s+p)/2,d=h-f,y=p-s,m=d*d+y*y,M=e-r,x=f*p-h*s,b=(0>y?-1:1)*Math.sqrt(Math.max(0,M*M*m-x*x)),_=(x*y-d*b)/m,w=(-x*d-y*b)/m,S=(x*y+d*b)/m,k=(-x*d+y*b)/m,N=_-g,E=w-v,A=S-g,C=k-v;return N*N+E*E>A*A+C*C&&(_=S,w=k),[[_-l,w-c],[_*e/M,w*e/M]]}function Mu(n){function t(t){function o(){c.push("M",u(n(f),a))}for(var l,c=[],f=[],s=-1,h=t.length,p=En(e),g=En(r);++s<h;)i.call(this,l=t[s],s)?f.push([+p.call(this,l,s),+g.call(this,l,s)]):f.length&&(o(),f=[]);return f.length&&o(),c.length?c.join(""):null}var e=Ce,r=ze,i=zt,u=xu,o=u.key,a=.7;return t.x=function(n){return arguments.length?(e=n,t):e},t.y=function(n){return arguments.length?(r=n,t):r},t.defined=function(n){return arguments.length?(i=n,t):i},t.interpolate=function(n){return arguments.length?(o="function"==typeof n?u=n:(u=Tl.get(n)||xu).key,t):o},t.tension=function(n){return arguments.length?(a=n,t):a},t}function xu(n){return n.length>1?n.join("L"):n+"Z"}function bu(n){return n.join("L")+"Z"}function _u(n){for(var t=0,e=n.length,r=n[0],i=[r[0],",",r[1]];++t<e;)i.push("H",(r[0]+(r=n[t])[0])/2,"V",r[1]);return e>1&&i.push("H",r[0]),i.join("")}function wu(n){for(var t=0,e=n.length,r=n[0],i=[r[0],",",r[1]];++t<e;)i.push("V",(r=n[t])[1],"H",r[0]);return i.join("")}function Su(n){for(var t=0,e=n.length,r=n[0],i=[r[0],",",r[1]];++t<e;)i.push("H",(r=n[t])[0],"V",r[1]);return i.join("")}function ku(n,t){return n.length<4?xu(n):n[1]+Au(n.slice(1,-1),Cu(n,t))}function Nu(n,t){return n.length<3?bu(n):n[0]+Au((n.push(n[0]),n),Cu([n[n.length-2]].concat(n,[n[1]]),t))}function Eu(n,t){return n.length<3?xu(n):n[0]+Au(n,Cu(n,t))}function Au(n,t){if(t.length<1||n.length!=t.length&&n.length!=t.length+2)return xu(n);var e=n.length!=t.length,r="",i=n[0],u=n[1],o=t[0],a=o,l=1;if(e&&(r+="Q"+(u[0]-2*o[0]/3)+","+(u[1]-2*o[1]/3)+","+u[0]+","+u[1],i=n[1],l=2),t.length>1){a=t[1],u=n[l],l++,r+="C"+(i[0]+o[0])+","+(i[1]+o[1])+","+(u[0]-a[0])+","+(u[1]-a[1])+","+u[0]+","+u[1];for(var c=2;c<t.length;c++,l++)u=n[l],a=t[c],r+="S"+(u[0]-a[0])+","+(u[1]-a[1])+","+u[0]+","+u[1]}if(e){var f=n[l];r+="Q"+(u[0]+2*a[0]/3)+","+(u[1]+2*a[1]/3)+","+f[0]+","+f[1]}return r}function Cu(n,t){for(var e,r=[],i=(1-t)/2,u=n[0],o=n[1],a=1,l=n.length;++a<l;)e=u,u=o,o=n[a],r.push([i*(o[0]-e[0]),i*(o[1]-e[1])]);return r}function zu(n){if(n.length<3)return xu(n);var t=1,e=n.length,r=n[0],i=r[0],u=r[1],o=[i,i,i,(r=n[1])[0]],a=[u,u,u,r[1]],l=[i,",",u,"L",Ru(Pl,o),",",Ru(Pl,a)];for(n.push(n[e-1]);++t<=e;)r=n[t],o.shift(),o.push(r[0]),a.shift(),a.push(r[1]),Du(l,o,a);return n.pop(),l.push("L",r),l.join("")}function Lu(n){if(n.length<4)return xu(n);for(var t,e=[],r=-1,i=n.length,u=[0],o=[0];++r<3;)t=n[r],u.push(t[0]),o.push(t[1]);for(e.push(Ru(Pl,u)+","+Ru(Pl,o)),--r;++r<i;)t=n[r],u.shift(),u.push(t[0]),o.shift(),o.push(t[1]),Du(e,u,o);return e.join("")}function qu(n){for(var t,e,r=-1,i=n.length,u=i+4,o=[],a=[];++r<4;)e=n[r%i],o.push(e[0]),a.push(e[1]);for(t=[Ru(Pl,o),",",Ru(Pl,a)],--r;++r<u;)e=n[r%i],o.shift(),o.push(e[0]),a.shift(),a.push(e[1]),Du(t,o,a);return t.join("")}function Tu(n,t){var e=n.length-1;if(e)for(var r,i,u=n[0][0],o=n[0][1],a=n[e][0]-u,l=n[e][1]-o,c=-1;++c<=e;)r=n[c],i=c/e,r[0]=t*r[0]+(1-t)*(u+i*a),r[1]=t*r[1]+(1-t)*(o+i*l);return zu(n)}function Ru(n,t){return n[0]*t[0]+n[1]*t[1]+n[2]*t[2]+n[3]*t[3]}function Du(n,t,e){n.push("C",Ru(Rl,t),",",Ru(Rl,e),",",Ru(Dl,t),",",Ru(Dl,e),",",Ru(Pl,t),",",Ru(Pl,e))}function Pu(n,t){return(t[1]-n[1])/(t[0]-n[0])}function Uu(n){for(var t=0,e=n.length-1,r=[],i=n[0],u=n[1],o=r[0]=Pu(i,u);++t<e;)r[t]=(o+(o=Pu(i=u,u=n[t+1])))/2;return r[t]=o,r}function ju(n){for(var t,e,r,i,u=[],o=Uu(n),a=-1,l=n.length-1;++a<l;)t=Pu(n[a],n[a+1]),xo(t)<Uo?o[a]=o[a+1]=0:(e=o[a]/t,r=o[a+1]/t,i=e*e+r*r,i>9&&(i=3*t/Math.sqrt(i),o[a]=i*e,o[a+1]=i*r));for(a=-1;++a<=l;)i=(n[Math.min(l,a+1)][0]-n[Math.max(0,a-1)][0])/(6*(1+o[a]*o[a])),u.push([i||0,o[a]*i||0]);return u}function Fu(n){return n.length<3?xu(n):n[0]+Au(n,ju(n))}function Hu(n){for(var t,e,r,i=-1,u=n.length;++i<u;)t=n[i],e=t[0],r=t[1]-Io,t[0]=e*Math.cos(r),t[1]=e*Math.sin(r);return n}function Ou(n){function t(t){function l(){v.push("M",a(n(y),s),f,c(n(d.reverse()),s),"Z")}for(var h,p,g,v=[],d=[],y=[],m=-1,M=t.length,x=En(e),b=En(i),_=e===r?function(){
+return p}:En(r),w=i===u?function(){return g}:En(u);++m<M;)o.call(this,h=t[m],m)?(d.push([p=+x.call(this,h,m),g=+b.call(this,h,m)]),y.push([+_.call(this,h,m),+w.call(this,h,m)])):d.length&&(l(),d=[],y=[]);return d.length&&l(),v.length?v.join(""):null}var e=Ce,r=Ce,i=0,u=ze,o=zt,a=xu,l=a.key,c=a,f="L",s=.7;return t.x=function(n){return arguments.length?(e=r=n,t):r},t.x0=function(n){return arguments.length?(e=n,t):e},t.x1=function(n){return arguments.length?(r=n,t):r},t.y=function(n){return arguments.length?(i=u=n,t):u},t.y0=function(n){return arguments.length?(i=n,t):i},t.y1=function(n){return arguments.length?(u=n,t):u},t.defined=function(n){return arguments.length?(o=n,t):o},t.interpolate=function(n){return arguments.length?(l="function"==typeof n?a=n:(a=Tl.get(n)||xu).key,c=a.reverse||a,f=a.closed?"M":"L",t):l},t.tension=function(n){return arguments.length?(s=n,t):s},t}function Iu(n){return n.radius}function Yu(n){return[n.x,n.y]}function Zu(n){return function(){var t=n.apply(this,arguments),e=t[0],r=t[1]-Io;return[e*Math.cos(r),e*Math.sin(r)]}}function Vu(){return 64}function Xu(){return"circle"}function $u(n){var t=Math.sqrt(n/Fo);return"M0,"+t+"A"+t+","+t+" 0 1,1 0,"+-t+"A"+t+","+t+" 0 1,1 0,"+t+"Z"}function Bu(n){return function(){var t,e,r;(t=this[n])&&(r=t[e=t.active])&&(r.timer.c=null,r.timer.t=NaN,--t.count?delete t[e]:delete this[n],t.active+=.5,r.event&&r.event.interrupt.call(this,this.__data__,r.index))}}function Wu(n,t,e){return ko(n,Yl),n.namespace=t,n.id=e,n}function Ju(n,t,e,r){var i=n.id,u=n.namespace;return Y(n,"function"==typeof e?function(n,o,a){n[u][i].tween.set(t,r(e.call(n,n.__data__,o,a)))}:(e=r(e),function(n){n[u][i].tween.set(t,e)}))}function Gu(n){return null==n&&(n=""),function(){this.textContent=n}}function Ku(n){return null==n?"__transition__":"__transition_"+n+"__"}function Qu(n,t,e,r,i){function u(n){var t=v.delay;return f.t=t+l,n>=t?o(n-t):void(f.c=o)}function o(e){var i=g.active,u=g[i];u&&(u.timer.c=null,u.timer.t=NaN,--g.count,delete g[i],u.event&&u.event.interrupt.call(n,n.__data__,u.index));for(var o in g)if(r>+o){var c=g[o];c.timer.c=null,c.timer.t=NaN,--g.count,delete g[o]}f.c=a,qn(function(){return f.c&&a(e||1)&&(f.c=null,f.t=NaN),1},0,l),g.active=r,v.event&&v.event.start.call(n,n.__data__,t),p=[],v.tween.forEach(function(e,r){(r=r.call(n,n.__data__,t))&&p.push(r)}),h=v.ease,s=v.duration}function a(i){for(var u=i/s,o=h(u),a=p.length;a>0;)p[--a].call(n,o);return u>=1?(v.event&&v.event.end.call(n,n.__data__,t),--g.count?delete g[r]:delete n[e],1):void 0}var l,f,s,h,p,g=n[e]||(n[e]={active:0,count:0}),v=g[r];v||(l=i.time,f=qn(u,0,l),v=g[r]={tween:new c,time:l,timer:f,delay:i.delay,duration:i.duration,ease:i.ease,index:t},i=null,++g.count)}function no(n,t,e){n.attr("transform",function(n){var r=t(n);return"translate("+(isFinite(r)?r:e(n))+",0)"})}function to(n,t,e){n.attr("transform",function(n){var r=t(n);return"translate(0,"+(isFinite(r)?r:e(n))+")"})}function eo(n){return n.toISOString()}function ro(n,t,e){function r(t){return n(t)}function i(n,e){var r=n[1]-n[0],i=r/e,u=ao.bisect(Kl,i);return u==Kl.length?[t.year,Ki(n.map(function(n){return n/31536e6}),e)[2]]:u?t[i/Kl[u-1]<Kl[u]/i?u-1:u]:[tc,Ki(n,e)[2]]}return r.invert=function(t){return io(n.invert(t))},r.domain=function(t){return arguments.length?(n.domain(t),r):n.domain().map(io)},r.nice=function(n,t){function e(e){return!isNaN(e)&&!n.range(e,io(+e+1),t).length}var u=r.domain(),o=Yi(u),a=null==n?i(o,10):"number"==typeof n&&i(o,n);return a&&(n=a[0],t=a[1]),r.domain(Xi(u,t>1?{floor:function(t){for(;e(t=n.floor(t));)t=io(t-1);return t},ceil:function(t){for(;e(t=n.ceil(t));)t=io(+t+1);return t}}:n))},r.ticks=function(n,t){var e=Yi(r.domain()),u=null==n?i(e,10):"number"==typeof n?i(e,n):!n.range&&[{range:n},t];return u&&(n=u[0],t=u[1]),n.range(e[0],io(+e[1]+1),1>t?1:t)},r.tickFormat=function(){return e},r.copy=function(){return ro(n.copy(),t,e)},Ji(r,n)}function io(n){return new Date(n)}function uo(n){return JSON.parse(n.responseText)}function oo(n){var t=fo.createRange();return t.selectNode(fo.body),t.createContextualFragment(n.responseText)}var ao={version:"3.5.17"},lo=[].slice,co=function(n){return lo.call(n)},fo=this.document;if(fo)try{co(fo.documentElement.childNodes)[0].nodeType}catch(so){co=function(n){for(var t=n.length,e=new Array(t);t--;)e[t]=n[t];return e}}if(Date.now||(Date.now=function(){return+new Date}),fo)try{fo.createElement("DIV").style.setProperty("opacity",0,"")}catch(ho){var po=this.Element.prototype,go=po.setAttribute,vo=po.setAttributeNS,yo=this.CSSStyleDeclaration.prototype,mo=yo.setProperty;po.setAttribute=function(n,t){go.call(this,n,t+"")},po.setAttributeNS=function(n,t,e){vo.call(this,n,t,e+"")},yo.setProperty=function(n,t,e){mo.call(this,n,t+"",e)}}ao.ascending=e,ao.descending=function(n,t){return n>t?-1:t>n?1:t>=n?0:NaN},ao.min=function(n,t){var e,r,i=-1,u=n.length;if(1===arguments.length){for(;++i<u;)if(null!=(r=n[i])&&r>=r){e=r;break}for(;++i<u;)null!=(r=n[i])&&e>r&&(e=r)}else{for(;++i<u;)if(null!=(r=t.call(n,n[i],i))&&r>=r){e=r;break}for(;++i<u;)null!=(r=t.call(n,n[i],i))&&e>r&&(e=r)}return e},ao.max=function(n,t){var e,r,i=-1,u=n.length;if(1===arguments.length){for(;++i<u;)if(null!=(r=n[i])&&r>=r){e=r;break}for(;++i<u;)null!=(r=n[i])&&r>e&&(e=r)}else{for(;++i<u;)if(null!=(r=t.call(n,n[i],i))&&r>=r){e=r;break}for(;++i<u;)null!=(r=t.call(n,n[i],i))&&r>e&&(e=r)}return e},ao.extent=function(n,t){var e,r,i,u=-1,o=n.length;if(1===arguments.length){for(;++u<o;)if(null!=(r=n[u])&&r>=r){e=i=r;break}for(;++u<o;)null!=(r=n[u])&&(e>r&&(e=r),r>i&&(i=r))}else{for(;++u<o;)if(null!=(r=t.call(n,n[u],u))&&r>=r){e=i=r;break}for(;++u<o;)null!=(r=t.call(n,n[u],u))&&(e>r&&(e=r),r>i&&(i=r))}return[e,i]},ao.sum=function(n,t){var e,r=0,u=n.length,o=-1;if(1===arguments.length)for(;++o<u;)i(e=+n[o])&&(r+=e);else for(;++o<u;)i(e=+t.call(n,n[o],o))&&(r+=e);return r},ao.mean=function(n,t){var e,u=0,o=n.length,a=-1,l=o;if(1===arguments.length)for(;++a<o;)i(e=r(n[a]))?u+=e:--l;else for(;++a<o;)i(e=r(t.call(n,n[a],a)))?u+=e:--l;return l?u/l:void 0},ao.quantile=function(n,t){var e=(n.length-1)*t+1,r=Math.floor(e),i=+n[r-1],u=e-r;return u?i+u*(n[r]-i):i},ao.median=function(n,t){var u,o=[],a=n.length,l=-1;if(1===arguments.length)for(;++l<a;)i(u=r(n[l]))&&o.push(u);else for(;++l<a;)i(u=r(t.call(n,n[l],l)))&&o.push(u);return o.length?ao.quantile(o.sort(e),.5):void 0},ao.variance=function(n,t){var e,u,o=n.length,a=0,l=0,c=-1,f=0;if(1===arguments.length)for(;++c<o;)i(e=r(n[c]))&&(u=e-a,a+=u/++f,l+=u*(e-a));else for(;++c<o;)i(e=r(t.call(n,n[c],c)))&&(u=e-a,a+=u/++f,l+=u*(e-a));return f>1?l/(f-1):void 0},ao.deviation=function(){var n=ao.variance.apply(this,arguments);return n?Math.sqrt(n):n};var Mo=u(e);ao.bisectLeft=Mo.left,ao.bisect=ao.bisectRight=Mo.right,ao.bisector=function(n){return u(1===n.length?function(t,r){return e(n(t),r)}:n)},ao.shuffle=function(n,t,e){(u=arguments.length)<3&&(e=n.length,2>u&&(t=0));for(var r,i,u=e-t;u;)i=Math.random()*u--|0,r=n[u+t],n[u+t]=n[i+t],n[i+t]=r;return n},ao.permute=function(n,t){for(var e=t.length,r=new Array(e);e--;)r[e]=n[t[e]];return r},ao.pairs=function(n){for(var t,e=0,r=n.length-1,i=n[0],u=new Array(0>r?0:r);r>e;)u[e]=[t=i,i=n[++e]];return u},ao.transpose=function(n){if(!(i=n.length))return[];for(var t=-1,e=ao.min(n,o),r=new Array(e);++t<e;)for(var i,u=-1,a=r[t]=new Array(i);++u<i;)a[u]=n[u][t];return r},ao.zip=function(){return ao.transpose(arguments)},ao.keys=function(n){var t=[];for(var e in n)t.push(e);return t},ao.values=function(n){var t=[];for(var e in n)t.push(n[e]);return t},ao.entries=function(n){var t=[];for(var e in n)t.push({key:e,value:n[e]});return t},ao.merge=function(n){for(var t,e,r,i=n.length,u=-1,o=0;++u<i;)o+=n[u].length;for(e=new Array(o);--i>=0;)for(r=n[i],t=r.length;--t>=0;)e[--o]=r[t];return e};var xo=Math.abs;ao.range=function(n,t,e){if(arguments.length<3&&(e=1,arguments.length<2&&(t=n,n=0)),(t-n)/e===1/0)throw new Error("infinite range");var r,i=[],u=a(xo(e)),o=-1;if(n*=u,t*=u,e*=u,0>e)for(;(r=n+e*++o)>t;)i.push(r/u);else for(;(r=n+e*++o)<t;)i.push(r/u);return i},ao.map=function(n,t){var e=new c;if(n instanceof c)n.forEach(function(n,t){e.set(n,t)});else if(Array.isArray(n)){var r,i=-1,u=n.length;if(1===arguments.length)for(;++i<u;)e.set(i,n[i]);else for(;++i<u;)e.set(t.call(n,r=n[i],i),r)}else for(var o in n)e.set(o,n[o]);return e};var bo="__proto__",_o="\x00";l(c,{has:h,get:function(n){return this._[f(n)]},set:function(n,t){return this._[f(n)]=t},remove:p,keys:g,values:function(){var n=[];for(var t in this._)n.push(this._[t]);return n},entries:function(){var n=[];for(var t in this._)n.push({key:s(t),value:this._[t]});return n},size:v,empty:d,forEach:function(n){for(var t in this._)n.call(this,s(t),this._[t])}}),ao.nest=function(){function n(t,o,a){if(a>=u.length)return r?r.call(i,o):e?o.sort(e):o;for(var l,f,s,h,p=-1,g=o.length,v=u[a++],d=new c;++p<g;)(h=d.get(l=v(f=o[p])))?h.push(f):d.set(l,[f]);return t?(f=t(),s=function(e,r){f.set(e,n(t,r,a))}):(f={},s=function(e,r){f[e]=n(t,r,a)}),d.forEach(s),f}function t(n,e){if(e>=u.length)return n;var r=[],i=o[e++];return n.forEach(function(n,i){r.push({key:n,values:t(i,e)})}),i?r.sort(function(n,t){return i(n.key,t.key)}):r}var e,r,i={},u=[],o=[];return i.map=function(t,e){return n(e,t,0)},i.entries=function(e){return t(n(ao.map,e,0),0)},i.key=function(n){return u.push(n),i},i.sortKeys=function(n){return o[u.length-1]=n,i},i.sortValues=function(n){return e=n,i},i.rollup=function(n){return r=n,i},i},ao.set=function(n){var t=new y;if(n)for(var e=0,r=n.length;r>e;++e)t.add(n[e]);return t},l(y,{has:h,add:function(n){return this._[f(n+="")]=!0,n},remove:p,values:g,size:v,empty:d,forEach:function(n){for(var t in this._)n.call(this,s(t))}}),ao.behavior={},ao.rebind=function(n,t){for(var e,r=1,i=arguments.length;++r<i;)n[e=arguments[r]]=M(n,t,t[e]);return n};var wo=["webkit","ms","moz","Moz","o","O"];ao.dispatch=function(){for(var n=new _,t=-1,e=arguments.length;++t<e;)n[arguments[t]]=w(n);return n},_.prototype.on=function(n,t){var e=n.indexOf("."),r="";if(e>=0&&(r=n.slice(e+1),n=n.slice(0,e)),n)return arguments.length<2?this[n].on(r):this[n].on(r,t);if(2===arguments.length){if(null==t)for(n in this)this.hasOwnProperty(n)&&this[n].on(r,null);return this}},ao.event=null,ao.requote=function(n){return n.replace(So,"\\$&")};var So=/[\\\^\$\*\+\?\|\[\]\(\)\.\{\}]/g,ko={}.__proto__?function(n,t){n.__proto__=t}:function(n,t){for(var e in t)n[e]=t[e]},No=function(n,t){return t.querySelector(n)},Eo=function(n,t){return t.querySelectorAll(n)},Ao=function(n,t){var e=n.matches||n[x(n,"matchesSelector")];return(Ao=function(n,t){return e.call(n,t)})(n,t)};"function"==typeof Sizzle&&(No=function(n,t){return Sizzle(n,t)[0]||null},Eo=Sizzle,Ao=Sizzle.matchesSelector),ao.selection=function(){return ao.select(fo.documentElement)};var Co=ao.selection.prototype=[];Co.select=function(n){var t,e,r,i,u=[];n=A(n);for(var o=-1,a=this.length;++o<a;){u.push(t=[]),t.parentNode=(r=this[o]).parentNode;for(var l=-1,c=r.length;++l<c;)(i=r[l])?(t.push(e=n.call(i,i.__data__,l,o)),e&&"__data__"in i&&(e.__data__=i.__data__)):t.push(null)}return E(u)},Co.selectAll=function(n){var t,e,r=[];n=C(n);for(var i=-1,u=this.length;++i<u;)for(var o=this[i],a=-1,l=o.length;++a<l;)(e=o[a])&&(r.push(t=co(n.call(e,e.__data__,a,i))),t.parentNode=e);return E(r)};var zo="http://www.w3.org/1999/xhtml",Lo={svg:"http://www.w3.org/2000/svg",xhtml:zo,xlink:"http://www.w3.org/1999/xlink",xml:"http://www.w3.org/XML/1998/namespace",xmlns:"http://www.w3.org/2000/xmlns/"};ao.ns={prefix:Lo,qualify:function(n){var t=n.indexOf(":"),e=n;return t>=0&&"xmlns"!==(e=n.slice(0,t))&&(n=n.slice(t+1)),Lo.hasOwnProperty(e)?{space:Lo[e],local:n}:n}},Co.attr=function(n,t){if(arguments.length<2){if("string"==typeof n){var e=this.node();return n=ao.ns.qualify(n),n.local?e.getAttributeNS(n.space,n.local):e.getAttribute(n)}for(t in n)this.each(z(t,n[t]));return this}return this.each(z(n,t))},Co.classed=function(n,t){if(arguments.length<2){if("string"==typeof n){var e=this.node(),r=(n=T(n)).length,i=-1;if(t=e.classList){for(;++i<r;)if(!t.contains(n[i]))return!1}else for(t=e.getAttribute("class");++i<r;)if(!q(n[i]).test(t))return!1;return!0}for(t in n)this.each(R(t,n[t]));return this}return this.each(R(n,t))},Co.style=function(n,e,r){var i=arguments.length;if(3>i){if("string"!=typeof n){2>i&&(e="");for(r in n)this.each(P(r,n[r],e));return this}if(2>i){var u=this.node();return t(u).getComputedStyle(u,null).getPropertyValue(n)}r=""}return this.each(P(n,e,r))},Co.property=function(n,t){if(arguments.length<2){if("string"==typeof n)return this.node()[n];for(t in n)this.each(U(t,n[t]));return this}return this.each(U(n,t))},Co.text=function(n){return arguments.length?this.each("function"==typeof n?function(){var t=n.apply(this,arguments);this.textContent=null==t?"":t}:null==n?function(){this.textContent=""}:function(){this.textContent=n}):this.node().textContent},Co.html=function(n){return arguments.length?this.each("function"==typeof n?function(){var t=n.apply(this,arguments);this.innerHTML=null==t?"":t}:null==n?function(){this.innerHTML=""}:function(){this.innerHTML=n}):this.node().innerHTML},Co.append=function(n){return n=j(n),this.select(function(){return this.appendChild(n.apply(this,arguments))})},Co.insert=function(n,t){return n=j(n),t=A(t),this.select(function(){return this.insertBefore(n.apply(this,arguments),t.apply(this,arguments)||null)})},Co.remove=function(){return this.each(F)},Co.data=function(n,t){function e(n,e){var r,i,u,o=n.length,s=e.length,h=Math.min(o,s),p=new Array(s),g=new Array(s),v=new Array(o);if(t){var d,y=new c,m=new Array(o);for(r=-1;++r<o;)(i=n[r])&&(y.has(d=t.call(i,i.__data__,r))?v[r]=i:y.set(d,i),m[r]=d);for(r=-1;++r<s;)(i=y.get(d=t.call(e,u=e[r],r)))?i!==!0&&(p[r]=i,i.__data__=u):g[r]=H(u),y.set(d,!0);for(r=-1;++r<o;)r in m&&y.get(m[r])!==!0&&(v[r]=n[r])}else{for(r=-1;++r<h;)i=n[r],u=e[r],i?(i.__data__=u,p[r]=i):g[r]=H(u);for(;s>r;++r)g[r]=H(e[r]);for(;o>r;++r)v[r]=n[r]}g.update=p,g.parentNode=p.parentNode=v.parentNode=n.parentNode,a.push(g),l.push(p),f.push(v)}var r,i,u=-1,o=this.length;if(!arguments.length){for(n=new Array(o=(r=this[0]).length);++u<o;)(i=r[u])&&(n[u]=i.__data__);return n}var a=Z([]),l=E([]),f=E([]);if("function"==typeof n)for(;++u<o;)e(r=this[u],n.call(r,r.parentNode.__data__,u));else for(;++u<o;)e(r=this[u],n);return l.enter=function(){return a},l.exit=function(){return f},l},Co.datum=function(n){return arguments.length?this.property("__data__",n):this.property("__data__")},Co.filter=function(n){var t,e,r,i=[];"function"!=typeof n&&(n=O(n));for(var u=0,o=this.length;o>u;u++){i.push(t=[]),t.parentNode=(e=this[u]).parentNode;for(var a=0,l=e.length;l>a;a++)(r=e[a])&&n.call(r,r.__data__,a,u)&&t.push(r)}return E(i)},Co.order=function(){for(var n=-1,t=this.length;++n<t;)for(var e,r=this[n],i=r.length-1,u=r[i];--i>=0;)(e=r[i])&&(u&&u!==e.nextSibling&&u.parentNode.insertBefore(e,u),u=e);return this},Co.sort=function(n){n=I.apply(this,arguments);for(var t=-1,e=this.length;++t<e;)this[t].sort(n);return this.order()},Co.each=function(n){return Y(this,function(t,e,r){n.call(t,t.__data__,e,r)})},Co.call=function(n){var t=co(arguments);return n.apply(t[0]=this,t),this},Co.empty=function(){return!this.node()},Co.node=function(){for(var n=0,t=this.length;t>n;n++)for(var e=this[n],r=0,i=e.length;i>r;r++){var u=e[r];if(u)return u}return null},Co.size=function(){var n=0;return Y(this,function(){++n}),n};var qo=[];ao.selection.enter=Z,ao.selection.enter.prototype=qo,qo.append=Co.append,qo.empty=Co.empty,qo.node=Co.node,qo.call=Co.call,qo.size=Co.size,qo.select=function(n){for(var t,e,r,i,u,o=[],a=-1,l=this.length;++a<l;){r=(i=this[a]).update,o.push(t=[]),t.parentNode=i.parentNode;for(var c=-1,f=i.length;++c<f;)(u=i[c])?(t.push(r[c]=e=n.call(i.parentNode,u.__data__,c,a)),e.__data__=u.__data__):t.push(null)}return E(o)},qo.insert=function(n,t){return arguments.length<2&&(t=V(this)),Co.insert.call(this,n,t)},ao.select=function(t){var e;return"string"==typeof t?(e=[No(t,fo)],e.parentNode=fo.documentElement):(e=[t],e.parentNode=n(t)),E([e])},ao.selectAll=function(n){var t;return"string"==typeof n?(t=co(Eo(n,fo)),t.parentNode=fo.documentElement):(t=co(n),t.parentNode=null),E([t])},Co.on=function(n,t,e){var r=arguments.length;if(3>r){if("string"!=typeof n){2>r&&(t=!1);for(e in n)this.each(X(e,n[e],t));return this}if(2>r)return(r=this.node()["__on"+n])&&r._;e=!1}return this.each(X(n,t,e))};var To=ao.map({mouseenter:"mouseover",mouseleave:"mouseout"});fo&&To.forEach(function(n){"on"+n in fo&&To.remove(n)});var Ro,Do=0;ao.mouse=function(n){return J(n,k())};var Po=this.navigator&&/WebKit/.test(this.navigator.userAgent)?-1:0;ao.touch=function(n,t,e){if(arguments.length<3&&(e=t,t=k().changedTouches),t)for(var r,i=0,u=t.length;u>i;++i)if((r=t[i]).identifier===e)return J(n,r)},ao.behavior.drag=function(){function n(){this.on("mousedown.drag",u).on("touchstart.drag",o)}function e(n,t,e,u,o){return function(){function a(){var n,e,r=t(h,v);r&&(n=r[0]-M[0],e=r[1]-M[1],g|=n|e,M=r,p({type:"drag",x:r[0]+c[0],y:r[1]+c[1],dx:n,dy:e}))}function l(){t(h,v)&&(y.on(u+d,null).on(o+d,null),m(g),p({type:"dragend"}))}var c,f=this,s=ao.event.target.correspondingElement||ao.event.target,h=f.parentNode,p=r.of(f,arguments),g=0,v=n(),d=".drag"+(null==v?"":"-"+v),y=ao.select(e(s)).on(u+d,a).on(o+d,l),m=W(s),M=t(h,v);i?(c=i.apply(f,arguments),c=[c.x-M[0],c.y-M[1]]):c=[0,0],p({type:"dragstart"})}}var r=N(n,"drag","dragstart","dragend"),i=null,u=e(b,ao.mouse,t,"mousemove","mouseup"),o=e(G,ao.touch,m,"touchmove","touchend");return n.origin=function(t){return arguments.length?(i=t,n):i},ao.rebind(n,r,"on")},ao.touches=function(n,t){return arguments.length<2&&(t=k().touches),t?co(t).map(function(t){var e=J(n,t);return e.identifier=t.identifier,e}):[]};var Uo=1e-6,jo=Uo*Uo,Fo=Math.PI,Ho=2*Fo,Oo=Ho-Uo,Io=Fo/2,Yo=Fo/180,Zo=180/Fo,Vo=Math.SQRT2,Xo=2,$o=4;ao.interpolateZoom=function(n,t){var e,r,i=n[0],u=n[1],o=n[2],a=t[0],l=t[1],c=t[2],f=a-i,s=l-u,h=f*f+s*s;if(jo>h)r=Math.log(c/o)/Vo,e=function(n){return[i+n*f,u+n*s,o*Math.exp(Vo*n*r)]};else{var p=Math.sqrt(h),g=(c*c-o*o+$o*h)/(2*o*Xo*p),v=(c*c-o*o-$o*h)/(2*c*Xo*p),d=Math.log(Math.sqrt(g*g+1)-g),y=Math.log(Math.sqrt(v*v+1)-v);r=(y-d)/Vo,e=function(n){var t=n*r,e=rn(d),a=o/(Xo*p)*(e*un(Vo*t+d)-en(d));return[i+a*f,u+a*s,o*e/rn(Vo*t+d)]}}return e.duration=1e3*r,e},ao.behavior.zoom=function(){function n(n){n.on(L,s).on(Wo+".zoom",p).on("dblclick.zoom",g).on(R,h)}function e(n){return[(n[0]-k.x)/k.k,(n[1]-k.y)/k.k]}function r(n){return[n[0]*k.k+k.x,n[1]*k.k+k.y]}function i(n){k.k=Math.max(A[0],Math.min(A[1],n))}function u(n,t){t=r(t),k.x+=n[0]-t[0],k.y+=n[1]-t[1]}function o(t,e,r,o){t.__chart__={x:k.x,y:k.y,k:k.k},i(Math.pow(2,o)),u(d=e,r),t=ao.select(t),C>0&&(t=t.transition().duration(C)),t.call(n.event)}function a(){b&&b.domain(x.range().map(function(n){return(n-k.x)/k.k}).map(x.invert)),w&&w.domain(_.range().map(function(n){return(n-k.y)/k.k}).map(_.invert))}function l(n){z++||n({type:"zoomstart"})}function c(n){a(),n({type:"zoom",scale:k.k,translate:[k.x,k.y]})}function f(n){--z||(n({type:"zoomend"}),d=null)}function s(){function n(){a=1,u(ao.mouse(i),h),c(o)}function r(){s.on(q,null).on(T,null),p(a),f(o)}var i=this,o=D.of(i,arguments),a=0,s=ao.select(t(i)).on(q,n).on(T,r),h=e(ao.mouse(i)),p=W(i);Il.call(i),l(o)}function h(){function n(){var n=ao.touches(g);return p=k.k,n.forEach(function(n){n.identifier in d&&(d[n.identifier]=e(n))}),n}function t(){var t=ao.event.target;ao.select(t).on(x,r).on(b,a),_.push(t);for(var e=ao.event.changedTouches,i=0,u=e.length;u>i;++i)d[e[i].identifier]=null;var l=n(),c=Date.now();if(1===l.length){if(500>c-M){var f=l[0];o(g,f,d[f.identifier],Math.floor(Math.log(k.k)/Math.LN2)+1),S()}M=c}else if(l.length>1){var f=l[0],s=l[1],h=f[0]-s[0],p=f[1]-s[1];y=h*h+p*p}}function r(){var n,t,e,r,o=ao.touches(g);Il.call(g);for(var a=0,l=o.length;l>a;++a,r=null)if(e=o[a],r=d[e.identifier]){if(t)break;n=e,t=r}if(r){var f=(f=e[0]-n[0])*f+(f=e[1]-n[1])*f,s=y&&Math.sqrt(f/y);n=[(n[0]+e[0])/2,(n[1]+e[1])/2],t=[(t[0]+r[0])/2,(t[1]+r[1])/2],i(s*p)}M=null,u(n,t),c(v)}function a(){if(ao.event.touches.length){for(var t=ao.event.changedTouches,e=0,r=t.length;r>e;++e)delete d[t[e].identifier];for(var i in d)return void n()}ao.selectAll(_).on(m,null),w.on(L,s).on(R,h),N(),f(v)}var p,g=this,v=D.of(g,arguments),d={},y=0,m=".zoom-"+ao.event.changedTouches[0].identifier,x="touchmove"+m,b="touchend"+m,_=[],w=ao.select(g),N=W(g);t(),l(v),w.on(L,null).on(R,t)}function p(){var n=D.of(this,arguments);m?clearTimeout(m):(Il.call(this),v=e(d=y||ao.mouse(this)),l(n)),m=setTimeout(function(){m=null,f(n)},50),S(),i(Math.pow(2,.002*Bo())*k.k),u(d,v),c(n)}function g(){var n=ao.mouse(this),t=Math.log(k.k)/Math.LN2;o(this,n,e(n),ao.event.shiftKey?Math.ceil(t)-1:Math.floor(t)+1)}var v,d,y,m,M,x,b,_,w,k={x:0,y:0,k:1},E=[960,500],A=Jo,C=250,z=0,L="mousedown.zoom",q="mousemove.zoom",T="mouseup.zoom",R="touchstart.zoom",D=N(n,"zoomstart","zoom","zoomend");return Wo||(Wo="onwheel"in fo?(Bo=function(){return-ao.event.deltaY*(ao.event.deltaMode?120:1)},"wheel"):"onmousewheel"in fo?(Bo=function(){return ao.event.wheelDelta},"mousewheel"):(Bo=function(){return-ao.event.detail},"MozMousePixelScroll")),n.event=function(n){n.each(function(){var n=D.of(this,arguments),t=k;Hl?ao.select(this).transition().each("start.zoom",function(){k=this.__chart__||{x:0,y:0,k:1},l(n)}).tween("zoom:zoom",function(){var e=E[0],r=E[1],i=d?d[0]:e/2,u=d?d[1]:r/2,o=ao.interpolateZoom([(i-k.x)/k.k,(u-k.y)/k.k,e/k.k],[(i-t.x)/t.k,(u-t.y)/t.k,e/t.k]);return function(t){var r=o(t),a=e/r[2];this.__chart__=k={x:i-r[0]*a,y:u-r[1]*a,k:a},c(n)}}).each("interrupt.zoom",function(){f(n)}).each("end.zoom",function(){f(n)}):(this.__chart__=k,l(n),c(n),f(n))})},n.translate=function(t){return arguments.length?(k={x:+t[0],y:+t[1],k:k.k},a(),n):[k.x,k.y]},n.scale=function(t){return arguments.length?(k={x:k.x,y:k.y,k:null},i(+t),a(),n):k.k},n.scaleExtent=function(t){return arguments.length?(A=null==t?Jo:[+t[0],+t[1]],n):A},n.center=function(t){return arguments.length?(y=t&&[+t[0],+t[1]],n):y},n.size=function(t){return arguments.length?(E=t&&[+t[0],+t[1]],n):E},n.duration=function(t){return arguments.length?(C=+t,n):C},n.x=function(t){return arguments.length?(b=t,x=t.copy(),k={x:0,y:0,k:1},n):b},n.y=function(t){return arguments.length?(w=t,_=t.copy(),k={x:0,y:0,k:1},n):w},ao.rebind(n,D,"on")};var Bo,Wo,Jo=[0,1/0];ao.color=an,an.prototype.toString=function(){return this.rgb()+""},ao.hsl=ln;var Go=ln.prototype=new an;Go.brighter=function(n){return n=Math.pow(.7,arguments.length?n:1),new ln(this.h,this.s,this.l/n)},Go.darker=function(n){return n=Math.pow(.7,arguments.length?n:1),new ln(this.h,this.s,n*this.l)},Go.rgb=function(){return cn(this.h,this.s,this.l)},ao.hcl=fn;var Ko=fn.prototype=new an;Ko.brighter=function(n){return new fn(this.h,this.c,Math.min(100,this.l+Qo*(arguments.length?n:1)))},Ko.darker=function(n){return new fn(this.h,this.c,Math.max(0,this.l-Qo*(arguments.length?n:1)))},Ko.rgb=function(){return sn(this.h,this.c,this.l).rgb()},ao.lab=hn;var Qo=18,na=.95047,ta=1,ea=1.08883,ra=hn.prototype=new an;ra.brighter=function(n){return new hn(Math.min(100,this.l+Qo*(arguments.length?n:1)),this.a,this.b)},ra.darker=function(n){return new hn(Math.max(0,this.l-Qo*(arguments.length?n:1)),this.a,this.b)},ra.rgb=function(){return pn(this.l,this.a,this.b)},ao.rgb=mn;var ia=mn.prototype=new an;ia.brighter=function(n){n=Math.pow(.7,arguments.length?n:1);var t=this.r,e=this.g,r=this.b,i=30;return t||e||r?(t&&i>t&&(t=i),e&&i>e&&(e=i),r&&i>r&&(r=i),new mn(Math.min(255,t/n),Math.min(255,e/n),Math.min(255,r/n))):new mn(i,i,i)},ia.darker=function(n){return n=Math.pow(.7,arguments.length?n:1),new mn(n*this.r,n*this.g,n*this.b)},ia.hsl=function(){return wn(this.r,this.g,this.b)},ia.toString=function(){return"#"+bn(this.r)+bn(this.g)+bn(this.b)};var ua=ao.map({aliceblue:15792383,antiquewhite:16444375,aqua:65535,aquamarine:8388564,azure:15794175,beige:16119260,bisque:16770244,black:0,blanchedalmond:16772045,blue:255,blueviolet:9055202,brown:10824234,burlywood:14596231,cadetblue:6266528,chartreuse:8388352,chocolate:13789470,coral:16744272,cornflowerblue:6591981,cornsilk:16775388,crimson:14423100,cyan:65535,darkblue:139,darkcyan:35723,darkgoldenrod:12092939,darkgray:11119017,darkgreen:25600,darkgrey:11119017,darkkhaki:12433259,darkmagenta:9109643,darkolivegreen:5597999,darkorange:16747520,darkorchid:10040012,darkred:9109504,darksalmon:15308410,darkseagreen:9419919,darkslateblue:4734347,darkslategray:3100495,darkslategrey:3100495,darkturquoise:52945,darkviolet:9699539,deeppink:16716947,deepskyblue:49151,dimgray:6908265,dimgrey:6908265,dodgerblue:2003199,firebrick:11674146,floralwhite:16775920,forestgreen:2263842,fuchsia:16711935,gainsboro:14474460,ghostwhite:16316671,gold:16766720,goldenrod:14329120,gray:8421504,green:32768,greenyellow:11403055,grey:8421504,honeydew:15794160,hotpink:16738740,indianred:13458524,indigo:4915330,ivory:16777200,khaki:15787660,lavender:15132410,lavenderblush:16773365,lawngreen:8190976,lemonchiffon:16775885,lightblue:11393254,lightcoral:15761536,lightcyan:14745599,lightgoldenrodyellow:16448210,lightgray:13882323,lightgreen:9498256,lightgrey:13882323,lightpink:16758465,lightsalmon:16752762,lightseagreen:2142890,lightskyblue:8900346,lightslategray:7833753,lightslategrey:7833753,lightsteelblue:11584734,lightyellow:16777184,lime:65280,limegreen:3329330,linen:16445670,magenta:16711935,maroon:8388608,mediumaquamarine:6737322,mediumblue:205,mediumorchid:12211667,mediumpurple:9662683,mediumseagreen:3978097,mediumslateblue:8087790,mediumspringgreen:64154,mediumturquoise:4772300,mediumvioletred:13047173,midnightblue:1644912,mintcream:16121850,mistyrose:16770273,moccasin:16770229,navajowhite:16768685,navy:128,oldlace:16643558,olive:8421376,olivedrab:7048739,orange:16753920,orangered:16729344,orchid:14315734,palegoldenrod:15657130,palegreen:10025880,paleturquoise:11529966,palevioletred:14381203,papayawhip:16773077,peachpuff:16767673,peru:13468991,pink:16761035,plum:14524637,powderblue:11591910,purple:8388736,rebeccapurple:6697881,red:16711680,rosybrown:12357519,royalblue:4286945,saddlebrown:9127187,salmon:16416882,sandybrown:16032864,seagreen:3050327,seashell:16774638,sienna:10506797,silver:12632256,skyblue:8900331,slateblue:6970061,slategray:7372944,slategrey:7372944,snow:16775930,springgreen:65407,steelblue:4620980,tan:13808780,teal:32896,thistle:14204888,tomato:16737095,turquoise:4251856,violet:15631086,wheat:16113331,white:16777215,whitesmoke:16119285,yellow:16776960,yellowgreen:10145074});ua.forEach(function(n,t){ua.set(n,Mn(t))}),ao.functor=En,ao.xhr=An(m),ao.dsv=function(n,t){function e(n,e,u){arguments.length<3&&(u=e,e=null);var o=Cn(n,t,null==e?r:i(e),u);return o.row=function(n){return arguments.length?o.response(null==(e=n)?r:i(n)):e},o}function r(n){return e.parse(n.responseText)}function i(n){return function(t){return e.parse(t.responseText,n)}}function u(t){return t.map(o).join(n)}function o(n){return a.test(n)?'"'+n.replace(/\"/g,'""')+'"':n}var a=new RegExp('["'+n+"\n]"),l=n.charCodeAt(0);return e.parse=function(n,t){var r;return e.parseRows(n,function(n,e){if(r)return r(n,e-1);var i=new Function("d","return {"+n.map(function(n,t){return JSON.stringify(n)+": d["+t+"]"}).join(",")+"}");r=t?function(n,e){return t(i(n),e)}:i})},e.parseRows=function(n,t){function e(){if(f>=c)return o;if(i)return i=!1,u;var t=f;if(34===n.charCodeAt(t)){for(var e=t;e++<c;)if(34===n.charCodeAt(e)){if(34!==n.charCodeAt(e+1))break;++e}f=e+2;var r=n.charCodeAt(e+1);return 13===r?(i=!0,10===n.charCodeAt(e+2)&&++f):10===r&&(i=!0),n.slice(t+1,e).replace(/""/g,'"')}for(;c>f;){var r=n.charCodeAt(f++),a=1;if(10===r)i=!0;else if(13===r)i=!0,10===n.charCodeAt(f)&&(++f,++a);else if(r!==l)continue;return n.slice(t,f-a)}return n.slice(t)}for(var r,i,u={},o={},a=[],c=n.length,f=0,s=0;(r=e())!==o;){for(var h=[];r!==u&&r!==o;)h.push(r),r=e();t&&null==(h=t(h,s++))||a.push(h)}return a},e.format=function(t){if(Array.isArray(t[0]))return e.formatRows(t);var r=new y,i=[];return t.forEach(function(n){for(var t in n)r.has(t)||i.push(r.add(t))}),[i.map(o).join(n)].concat(t.map(function(t){return i.map(function(n){return o(t[n])}).join(n)})).join("\n")},e.formatRows=function(n){return n.map(u).join("\n")},e},ao.csv=ao.dsv(",","text/csv"),ao.tsv=ao.dsv("	","text/tab-separated-values");var oa,aa,la,ca,fa=this[x(this,"requestAnimationFrame")]||function(n){setTimeout(n,17)};ao.timer=function(){qn.apply(this,arguments)},ao.timer.flush=function(){Rn(),Dn()},ao.round=function(n,t){return t?Math.round(n*(t=Math.pow(10,t)))/t:Math.round(n)};var sa=["y","z","a","f","p","n","\xb5","m","","k","M","G","T","P","E","Z","Y"].map(Un);ao.formatPrefix=function(n,t){var e=0;return(n=+n)&&(0>n&&(n*=-1),t&&(n=ao.round(n,Pn(n,t))),e=1+Math.floor(1e-12+Math.log(n)/Math.LN10),e=Math.max(-24,Math.min(24,3*Math.floor((e-1)/3)))),sa[8+e/3]};var ha=/(?:([^{])?([<>=^]))?([+\- ])?([$#])?(0)?(\d+)?(,)?(\.-?\d+)?([a-z%])?/i,pa=ao.map({b:function(n){return n.toString(2)},c:function(n){return String.fromCharCode(n)},o:function(n){return n.toString(8)},x:function(n){return n.toString(16)},X:function(n){return n.toString(16).toUpperCase()},g:function(n,t){return n.toPrecision(t)},e:function(n,t){return n.toExponential(t)},f:function(n,t){return n.toFixed(t)},r:function(n,t){return(n=ao.round(n,Pn(n,t))).toFixed(Math.max(0,Math.min(20,Pn(n*(1+1e-15),t))))}}),ga=ao.time={},va=Date;Hn.prototype={getDate:function(){return this._.getUTCDate()},getDay:function(){return this._.getUTCDay()},getFullYear:function(){return this._.getUTCFullYear()},getHours:function(){return this._.getUTCHours()},getMilliseconds:function(){return this._.getUTCMilliseconds()},getMinutes:function(){return this._.getUTCMinutes()},getMonth:function(){return this._.getUTCMonth()},getSeconds:function(){return this._.getUTCSeconds()},getTime:function(){return this._.getTime()},getTimezoneOffset:function(){return 0},valueOf:function(){return this._.valueOf()},setDate:function(){da.setUTCDate.apply(this._,arguments)},setDay:function(){da.setUTCDay.apply(this._,arguments)},setFullYear:function(){da.setUTCFullYear.apply(this._,arguments)},setHours:function(){da.setUTCHours.apply(this._,arguments)},setMilliseconds:function(){da.setUTCMilliseconds.apply(this._,arguments)},setMinutes:function(){da.setUTCMinutes.apply(this._,arguments)},setMonth:function(){da.setUTCMonth.apply(this._,arguments)},setSeconds:function(){da.setUTCSeconds.apply(this._,arguments)},setTime:function(){da.setTime.apply(this._,arguments)}};var da=Date.prototype;ga.year=On(function(n){return n=ga.day(n),n.setMonth(0,1),n},function(n,t){n.setFullYear(n.getFullYear()+t)},function(n){return n.getFullYear()}),ga.years=ga.year.range,ga.years.utc=ga.year.utc.range,ga.day=On(function(n){var t=new va(2e3,0);return t.setFullYear(n.getFullYear(),n.getMonth(),n.getDate()),t},function(n,t){n.setDate(n.getDate()+t)},function(n){return n.getDate()-1}),ga.days=ga.day.range,ga.days.utc=ga.day.utc.range,ga.dayOfYear=function(n){var t=ga.year(n);return Math.floor((n-t-6e4*(n.getTimezoneOffset()-t.getTimezoneOffset()))/864e5)},["sunday","monday","tuesday","wednesday","thursday","friday","saturday"].forEach(function(n,t){t=7-t;var e=ga[n]=On(function(n){return(n=ga.day(n)).setDate(n.getDate()-(n.getDay()+t)%7),n},function(n,t){n.setDate(n.getDate()+7*Math.floor(t))},function(n){var e=ga.year(n).getDay();return Math.floor((ga.dayOfYear(n)+(e+t)%7)/7)-(e!==t)});ga[n+"s"]=e.range,ga[n+"s"].utc=e.utc.range,ga[n+"OfYear"]=function(n){var e=ga.year(n).getDay();return Math.floor((ga.dayOfYear(n)+(e+t)%7)/7)}}),ga.week=ga.sunday,ga.weeks=ga.sunday.range,ga.weeks.utc=ga.sunday.utc.range,ga.weekOfYear=ga.sundayOfYear;var ya={"-":"",_:" ",0:"0"},ma=/^\s*\d+/,Ma=/^%/;ao.locale=function(n){return{numberFormat:jn(n),timeFormat:Yn(n)}};var xa=ao.locale({decimal:".",thousands:",",grouping:[3],currency:["$",""],dateTime:"%a %b %e %X %Y",date:"%m/%d/%Y",time:"%H:%M:%S",periods:["AM","PM"],days:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],
+shortDays:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],months:["January","February","March","April","May","June","July","August","September","October","November","December"],shortMonths:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"]});ao.format=xa.numberFormat,ao.geo={},ft.prototype={s:0,t:0,add:function(n){st(n,this.t,ba),st(ba.s,this.s,this),this.s?this.t+=ba.t:this.s=ba.t},reset:function(){this.s=this.t=0},valueOf:function(){return this.s}};var ba=new ft;ao.geo.stream=function(n,t){n&&_a.hasOwnProperty(n.type)?_a[n.type](n,t):ht(n,t)};var _a={Feature:function(n,t){ht(n.geometry,t)},FeatureCollection:function(n,t){for(var e=n.features,r=-1,i=e.length;++r<i;)ht(e[r].geometry,t)}},wa={Sphere:function(n,t){t.sphere()},Point:function(n,t){n=n.coordinates,t.point(n[0],n[1],n[2])},MultiPoint:function(n,t){for(var e=n.coordinates,r=-1,i=e.length;++r<i;)n=e[r],t.point(n[0],n[1],n[2])},LineString:function(n,t){pt(n.coordinates,t,0)},MultiLineString:function(n,t){for(var e=n.coordinates,r=-1,i=e.length;++r<i;)pt(e[r],t,0)},Polygon:function(n,t){gt(n.coordinates,t)},MultiPolygon:function(n,t){for(var e=n.coordinates,r=-1,i=e.length;++r<i;)gt(e[r],t)},GeometryCollection:function(n,t){for(var e=n.geometries,r=-1,i=e.length;++r<i;)ht(e[r],t)}};ao.geo.area=function(n){return Sa=0,ao.geo.stream(n,Na),Sa};var Sa,ka=new ft,Na={sphere:function(){Sa+=4*Fo},point:b,lineStart:b,lineEnd:b,polygonStart:function(){ka.reset(),Na.lineStart=vt},polygonEnd:function(){var n=2*ka;Sa+=0>n?4*Fo+n:n,Na.lineStart=Na.lineEnd=Na.point=b}};ao.geo.bounds=function(){function n(n,t){M.push(x=[f=n,h=n]),s>t&&(s=t),t>p&&(p=t)}function t(t,e){var r=dt([t*Yo,e*Yo]);if(y){var i=mt(y,r),u=[i[1],-i[0],0],o=mt(u,i);bt(o),o=_t(o);var l=t-g,c=l>0?1:-1,v=o[0]*Zo*c,d=xo(l)>180;if(d^(v>c*g&&c*t>v)){var m=o[1]*Zo;m>p&&(p=m)}else if(v=(v+360)%360-180,d^(v>c*g&&c*t>v)){var m=-o[1]*Zo;s>m&&(s=m)}else s>e&&(s=e),e>p&&(p=e);d?g>t?a(f,t)>a(f,h)&&(h=t):a(t,h)>a(f,h)&&(f=t):h>=f?(f>t&&(f=t),t>h&&(h=t)):t>g?a(f,t)>a(f,h)&&(h=t):a(t,h)>a(f,h)&&(f=t)}else n(t,e);y=r,g=t}function e(){b.point=t}function r(){x[0]=f,x[1]=h,b.point=n,y=null}function i(n,e){if(y){var r=n-g;m+=xo(r)>180?r+(r>0?360:-360):r}else v=n,d=e;Na.point(n,e),t(n,e)}function u(){Na.lineStart()}function o(){i(v,d),Na.lineEnd(),xo(m)>Uo&&(f=-(h=180)),x[0]=f,x[1]=h,y=null}function a(n,t){return(t-=n)<0?t+360:t}function l(n,t){return n[0]-t[0]}function c(n,t){return t[0]<=t[1]?t[0]<=n&&n<=t[1]:n<t[0]||t[1]<n}var f,s,h,p,g,v,d,y,m,M,x,b={point:n,lineStart:e,lineEnd:r,polygonStart:function(){b.point=i,b.lineStart=u,b.lineEnd=o,m=0,Na.polygonStart()},polygonEnd:function(){Na.polygonEnd(),b.point=n,b.lineStart=e,b.lineEnd=r,0>ka?(f=-(h=180),s=-(p=90)):m>Uo?p=90:-Uo>m&&(s=-90),x[0]=f,x[1]=h}};return function(n){p=h=-(f=s=1/0),M=[],ao.geo.stream(n,b);var t=M.length;if(t){M.sort(l);for(var e,r=1,i=M[0],u=[i];t>r;++r)e=M[r],c(e[0],i)||c(e[1],i)?(a(i[0],e[1])>a(i[0],i[1])&&(i[1]=e[1]),a(e[0],i[1])>a(i[0],i[1])&&(i[0]=e[0])):u.push(i=e);for(var o,e,g=-(1/0),t=u.length-1,r=0,i=u[t];t>=r;i=e,++r)e=u[r],(o=a(i[1],e[0]))>g&&(g=o,f=e[0],h=i[1])}return M=x=null,f===1/0||s===1/0?[[NaN,NaN],[NaN,NaN]]:[[f,s],[h,p]]}}(),ao.geo.centroid=function(n){Ea=Aa=Ca=za=La=qa=Ta=Ra=Da=Pa=Ua=0,ao.geo.stream(n,ja);var t=Da,e=Pa,r=Ua,i=t*t+e*e+r*r;return jo>i&&(t=qa,e=Ta,r=Ra,Uo>Aa&&(t=Ca,e=za,r=La),i=t*t+e*e+r*r,jo>i)?[NaN,NaN]:[Math.atan2(e,t)*Zo,tn(r/Math.sqrt(i))*Zo]};var Ea,Aa,Ca,za,La,qa,Ta,Ra,Da,Pa,Ua,ja={sphere:b,point:St,lineStart:Nt,lineEnd:Et,polygonStart:function(){ja.lineStart=At},polygonEnd:function(){ja.lineStart=Nt}},Fa=Rt(zt,jt,Ht,[-Fo,-Fo/2]),Ha=1e9;ao.geo.clipExtent=function(){var n,t,e,r,i,u,o={stream:function(n){return i&&(i.valid=!1),i=u(n),i.valid=!0,i},extent:function(a){return arguments.length?(u=Zt(n=+a[0][0],t=+a[0][1],e=+a[1][0],r=+a[1][1]),i&&(i.valid=!1,i=null),o):[[n,t],[e,r]]}};return o.extent([[0,0],[960,500]])},(ao.geo.conicEqualArea=function(){return Vt(Xt)}).raw=Xt,ao.geo.albers=function(){return ao.geo.conicEqualArea().rotate([96,0]).center([-.6,38.7]).parallels([29.5,45.5]).scale(1070)},ao.geo.albersUsa=function(){function n(n){var u=n[0],o=n[1];return t=null,e(u,o),t||(r(u,o),t)||i(u,o),t}var t,e,r,i,u=ao.geo.albers(),o=ao.geo.conicEqualArea().rotate([154,0]).center([-2,58.5]).parallels([55,65]),a=ao.geo.conicEqualArea().rotate([157,0]).center([-3,19.9]).parallels([8,18]),l={point:function(n,e){t=[n,e]}};return n.invert=function(n){var t=u.scale(),e=u.translate(),r=(n[0]-e[0])/t,i=(n[1]-e[1])/t;return(i>=.12&&.234>i&&r>=-.425&&-.214>r?o:i>=.166&&.234>i&&r>=-.214&&-.115>r?a:u).invert(n)},n.stream=function(n){var t=u.stream(n),e=o.stream(n),r=a.stream(n);return{point:function(n,i){t.point(n,i),e.point(n,i),r.point(n,i)},sphere:function(){t.sphere(),e.sphere(),r.sphere()},lineStart:function(){t.lineStart(),e.lineStart(),r.lineStart()},lineEnd:function(){t.lineEnd(),e.lineEnd(),r.lineEnd()},polygonStart:function(){t.polygonStart(),e.polygonStart(),r.polygonStart()},polygonEnd:function(){t.polygonEnd(),e.polygonEnd(),r.polygonEnd()}}},n.precision=function(t){return arguments.length?(u.precision(t),o.precision(t),a.precision(t),n):u.precision()},n.scale=function(t){return arguments.length?(u.scale(t),o.scale(.35*t),a.scale(t),n.translate(u.translate())):u.scale()},n.translate=function(t){if(!arguments.length)return u.translate();var c=u.scale(),f=+t[0],s=+t[1];return e=u.translate(t).clipExtent([[f-.455*c,s-.238*c],[f+.455*c,s+.238*c]]).stream(l).point,r=o.translate([f-.307*c,s+.201*c]).clipExtent([[f-.425*c+Uo,s+.12*c+Uo],[f-.214*c-Uo,s+.234*c-Uo]]).stream(l).point,i=a.translate([f-.205*c,s+.212*c]).clipExtent([[f-.214*c+Uo,s+.166*c+Uo],[f-.115*c-Uo,s+.234*c-Uo]]).stream(l).point,n},n.scale(1070)};var Oa,Ia,Ya,Za,Va,Xa,$a={point:b,lineStart:b,lineEnd:b,polygonStart:function(){Ia=0,$a.lineStart=$t},polygonEnd:function(){$a.lineStart=$a.lineEnd=$a.point=b,Oa+=xo(Ia/2)}},Ba={point:Bt,lineStart:b,lineEnd:b,polygonStart:b,polygonEnd:b},Wa={point:Gt,lineStart:Kt,lineEnd:Qt,polygonStart:function(){Wa.lineStart=ne},polygonEnd:function(){Wa.point=Gt,Wa.lineStart=Kt,Wa.lineEnd=Qt}};ao.geo.path=function(){function n(n){return n&&("function"==typeof a&&u.pointRadius(+a.apply(this,arguments)),o&&o.valid||(o=i(u)),ao.geo.stream(n,o)),u.result()}function t(){return o=null,n}var e,r,i,u,o,a=4.5;return n.area=function(n){return Oa=0,ao.geo.stream(n,i($a)),Oa},n.centroid=function(n){return Ca=za=La=qa=Ta=Ra=Da=Pa=Ua=0,ao.geo.stream(n,i(Wa)),Ua?[Da/Ua,Pa/Ua]:Ra?[qa/Ra,Ta/Ra]:La?[Ca/La,za/La]:[NaN,NaN]},n.bounds=function(n){return Va=Xa=-(Ya=Za=1/0),ao.geo.stream(n,i(Ba)),[[Ya,Za],[Va,Xa]]},n.projection=function(n){return arguments.length?(i=(e=n)?n.stream||re(n):m,t()):e},n.context=function(n){return arguments.length?(u=null==(r=n)?new Wt:new te(n),"function"!=typeof a&&u.pointRadius(a),t()):r},n.pointRadius=function(t){return arguments.length?(a="function"==typeof t?t:(u.pointRadius(+t),+t),n):a},n.projection(ao.geo.albersUsa()).context(null)},ao.geo.transform=function(n){return{stream:function(t){var e=new ie(t);for(var r in n)e[r]=n[r];return e}}},ie.prototype={point:function(n,t){this.stream.point(n,t)},sphere:function(){this.stream.sphere()},lineStart:function(){this.stream.lineStart()},lineEnd:function(){this.stream.lineEnd()},polygonStart:function(){this.stream.polygonStart()},polygonEnd:function(){this.stream.polygonEnd()}},ao.geo.projection=oe,ao.geo.projectionMutator=ae,(ao.geo.equirectangular=function(){return oe(ce)}).raw=ce.invert=ce,ao.geo.rotation=function(n){function t(t){return t=n(t[0]*Yo,t[1]*Yo),t[0]*=Zo,t[1]*=Zo,t}return n=se(n[0]%360*Yo,n[1]*Yo,n.length>2?n[2]*Yo:0),t.invert=function(t){return t=n.invert(t[0]*Yo,t[1]*Yo),t[0]*=Zo,t[1]*=Zo,t},t},fe.invert=ce,ao.geo.circle=function(){function n(){var n="function"==typeof r?r.apply(this,arguments):r,t=se(-n[0]*Yo,-n[1]*Yo,0).invert,i=[];return e(null,null,1,{point:function(n,e){i.push(n=t(n,e)),n[0]*=Zo,n[1]*=Zo}}),{type:"Polygon",coordinates:[i]}}var t,e,r=[0,0],i=6;return n.origin=function(t){return arguments.length?(r=t,n):r},n.angle=function(r){return arguments.length?(e=ve((t=+r)*Yo,i*Yo),n):t},n.precision=function(r){return arguments.length?(e=ve(t*Yo,(i=+r)*Yo),n):i},n.angle(90)},ao.geo.distance=function(n,t){var e,r=(t[0]-n[0])*Yo,i=n[1]*Yo,u=t[1]*Yo,o=Math.sin(r),a=Math.cos(r),l=Math.sin(i),c=Math.cos(i),f=Math.sin(u),s=Math.cos(u);return Math.atan2(Math.sqrt((e=s*o)*e+(e=c*f-l*s*a)*e),l*f+c*s*a)},ao.geo.graticule=function(){function n(){return{type:"MultiLineString",coordinates:t()}}function t(){return ao.range(Math.ceil(u/d)*d,i,d).map(h).concat(ao.range(Math.ceil(c/y)*y,l,y).map(p)).concat(ao.range(Math.ceil(r/g)*g,e,g).filter(function(n){return xo(n%d)>Uo}).map(f)).concat(ao.range(Math.ceil(a/v)*v,o,v).filter(function(n){return xo(n%y)>Uo}).map(s))}var e,r,i,u,o,a,l,c,f,s,h,p,g=10,v=g,d=90,y=360,m=2.5;return n.lines=function(){return t().map(function(n){return{type:"LineString",coordinates:n}})},n.outline=function(){return{type:"Polygon",coordinates:[h(u).concat(p(l).slice(1),h(i).reverse().slice(1),p(c).reverse().slice(1))]}},n.extent=function(t){return arguments.length?n.majorExtent(t).minorExtent(t):n.minorExtent()},n.majorExtent=function(t){return arguments.length?(u=+t[0][0],i=+t[1][0],c=+t[0][1],l=+t[1][1],u>i&&(t=u,u=i,i=t),c>l&&(t=c,c=l,l=t),n.precision(m)):[[u,c],[i,l]]},n.minorExtent=function(t){return arguments.length?(r=+t[0][0],e=+t[1][0],a=+t[0][1],o=+t[1][1],r>e&&(t=r,r=e,e=t),a>o&&(t=a,a=o,o=t),n.precision(m)):[[r,a],[e,o]]},n.step=function(t){return arguments.length?n.majorStep(t).minorStep(t):n.minorStep()},n.majorStep=function(t){return arguments.length?(d=+t[0],y=+t[1],n):[d,y]},n.minorStep=function(t){return arguments.length?(g=+t[0],v=+t[1],n):[g,v]},n.precision=function(t){return arguments.length?(m=+t,f=ye(a,o,90),s=me(r,e,m),h=ye(c,l,90),p=me(u,i,m),n):m},n.majorExtent([[-180,-90+Uo],[180,90-Uo]]).minorExtent([[-180,-80-Uo],[180,80+Uo]])},ao.geo.greatArc=function(){function n(){return{type:"LineString",coordinates:[t||r.apply(this,arguments),e||i.apply(this,arguments)]}}var t,e,r=Me,i=xe;return n.distance=function(){return ao.geo.distance(t||r.apply(this,arguments),e||i.apply(this,arguments))},n.source=function(e){return arguments.length?(r=e,t="function"==typeof e?null:e,n):r},n.target=function(t){return arguments.length?(i=t,e="function"==typeof t?null:t,n):i},n.precision=function(){return arguments.length?n:0},n},ao.geo.interpolate=function(n,t){return be(n[0]*Yo,n[1]*Yo,t[0]*Yo,t[1]*Yo)},ao.geo.length=function(n){return Ja=0,ao.geo.stream(n,Ga),Ja};var Ja,Ga={sphere:b,point:b,lineStart:_e,lineEnd:b,polygonStart:b,polygonEnd:b},Ka=we(function(n){return Math.sqrt(2/(1+n))},function(n){return 2*Math.asin(n/2)});(ao.geo.azimuthalEqualArea=function(){return oe(Ka)}).raw=Ka;var Qa=we(function(n){var t=Math.acos(n);return t&&t/Math.sin(t)},m);(ao.geo.azimuthalEquidistant=function(){return oe(Qa)}).raw=Qa,(ao.geo.conicConformal=function(){return Vt(Se)}).raw=Se,(ao.geo.conicEquidistant=function(){return Vt(ke)}).raw=ke;var nl=we(function(n){return 1/n},Math.atan);(ao.geo.gnomonic=function(){return oe(nl)}).raw=nl,Ne.invert=function(n,t){return[n,2*Math.atan(Math.exp(t))-Io]},(ao.geo.mercator=function(){return Ee(Ne)}).raw=Ne;var tl=we(function(){return 1},Math.asin);(ao.geo.orthographic=function(){return oe(tl)}).raw=tl;var el=we(function(n){return 1/(1+n)},function(n){return 2*Math.atan(n)});(ao.geo.stereographic=function(){return oe(el)}).raw=el,Ae.invert=function(n,t){return[-t,2*Math.atan(Math.exp(n))-Io]},(ao.geo.transverseMercator=function(){var n=Ee(Ae),t=n.center,e=n.rotate;return n.center=function(n){return n?t([-n[1],n[0]]):(n=t(),[n[1],-n[0]])},n.rotate=function(n){return n?e([n[0],n[1],n.length>2?n[2]+90:90]):(n=e(),[n[0],n[1],n[2]-90])},e([0,0,90])}).raw=Ae,ao.geom={},ao.geom.hull=function(n){function t(n){if(n.length<3)return[];var t,i=En(e),u=En(r),o=n.length,a=[],l=[];for(t=0;o>t;t++)a.push([+i.call(this,n[t],t),+u.call(this,n[t],t),t]);for(a.sort(qe),t=0;o>t;t++)l.push([a[t][0],-a[t][1]]);var c=Le(a),f=Le(l),s=f[0]===c[0],h=f[f.length-1]===c[c.length-1],p=[];for(t=c.length-1;t>=0;--t)p.push(n[a[c[t]][2]]);for(t=+s;t<f.length-h;++t)p.push(n[a[f[t]][2]]);return p}var e=Ce,r=ze;return arguments.length?t(n):(t.x=function(n){return arguments.length?(e=n,t):e},t.y=function(n){return arguments.length?(r=n,t):r},t)},ao.geom.polygon=function(n){return ko(n,rl),n};var rl=ao.geom.polygon.prototype=[];rl.area=function(){for(var n,t=-1,e=this.length,r=this[e-1],i=0;++t<e;)n=r,r=this[t],i+=n[1]*r[0]-n[0]*r[1];return.5*i},rl.centroid=function(n){var t,e,r=-1,i=this.length,u=0,o=0,a=this[i-1];for(arguments.length||(n=-1/(6*this.area()));++r<i;)t=a,a=this[r],e=t[0]*a[1]-a[0]*t[1],u+=(t[0]+a[0])*e,o+=(t[1]+a[1])*e;return[u*n,o*n]},rl.clip=function(n){for(var t,e,r,i,u,o,a=De(n),l=-1,c=this.length-De(this),f=this[c-1];++l<c;){for(t=n.slice(),n.length=0,i=this[l],u=t[(r=t.length-a)-1],e=-1;++e<r;)o=t[e],Te(o,f,i)?(Te(u,f,i)||n.push(Re(u,o,f,i)),n.push(o)):Te(u,f,i)&&n.push(Re(u,o,f,i)),u=o;a&&n.push(n[0]),f=i}return n};var il,ul,ol,al,ll,cl=[],fl=[];Ye.prototype.prepare=function(){for(var n,t=this.edges,e=t.length;e--;)n=t[e].edge,n.b&&n.a||t.splice(e,1);return t.sort(Ve),t.length},tr.prototype={start:function(){return this.edge.l===this.site?this.edge.a:this.edge.b},end:function(){return this.edge.l===this.site?this.edge.b:this.edge.a}},er.prototype={insert:function(n,t){var e,r,i;if(n){if(t.P=n,t.N=n.N,n.N&&(n.N.P=t),n.N=t,n.R){for(n=n.R;n.L;)n=n.L;n.L=t}else n.R=t;e=n}else this._?(n=or(this._),t.P=null,t.N=n,n.P=n.L=t,e=n):(t.P=t.N=null,this._=t,e=null);for(t.L=t.R=null,t.U=e,t.C=!0,n=t;e&&e.C;)r=e.U,e===r.L?(i=r.R,i&&i.C?(e.C=i.C=!1,r.C=!0,n=r):(n===e.R&&(ir(this,e),n=e,e=n.U),e.C=!1,r.C=!0,ur(this,r))):(i=r.L,i&&i.C?(e.C=i.C=!1,r.C=!0,n=r):(n===e.L&&(ur(this,e),n=e,e=n.U),e.C=!1,r.C=!0,ir(this,r))),e=n.U;this._.C=!1},remove:function(n){n.N&&(n.N.P=n.P),n.P&&(n.P.N=n.N),n.N=n.P=null;var t,e,r,i=n.U,u=n.L,o=n.R;if(e=u?o?or(o):u:o,i?i.L===n?i.L=e:i.R=e:this._=e,u&&o?(r=e.C,e.C=n.C,e.L=u,u.U=e,e!==o?(i=e.U,e.U=n.U,n=e.R,i.L=n,e.R=o,o.U=e):(e.U=i,i=e,n=e.R)):(r=n.C,n=e),n&&(n.U=i),!r){if(n&&n.C)return void(n.C=!1);do{if(n===this._)break;if(n===i.L){if(t=i.R,t.C&&(t.C=!1,i.C=!0,ir(this,i),t=i.R),t.L&&t.L.C||t.R&&t.R.C){t.R&&t.R.C||(t.L.C=!1,t.C=!0,ur(this,t),t=i.R),t.C=i.C,i.C=t.R.C=!1,ir(this,i),n=this._;break}}else if(t=i.L,t.C&&(t.C=!1,i.C=!0,ur(this,i),t=i.L),t.L&&t.L.C||t.R&&t.R.C){t.L&&t.L.C||(t.R.C=!1,t.C=!0,ir(this,t),t=i.L),t.C=i.C,i.C=t.L.C=!1,ur(this,i),n=this._;break}t.C=!0,n=i,i=i.U}while(!n.C);n&&(n.C=!1)}}},ao.geom.voronoi=function(n){function t(n){var t=new Array(n.length),r=a[0][0],i=a[0][1],u=a[1][0],o=a[1][1];return ar(e(n),a).cells.forEach(function(e,a){var l=e.edges,c=e.site,f=t[a]=l.length?l.map(function(n){var t=n.start();return[t.x,t.y]}):c.x>=r&&c.x<=u&&c.y>=i&&c.y<=o?[[r,o],[u,o],[u,i],[r,i]]:[];f.point=n[a]}),t}function e(n){return n.map(function(n,t){return{x:Math.round(u(n,t)/Uo)*Uo,y:Math.round(o(n,t)/Uo)*Uo,i:t}})}var r=Ce,i=ze,u=r,o=i,a=sl;return n?t(n):(t.links=function(n){return ar(e(n)).edges.filter(function(n){return n.l&&n.r}).map(function(t){return{source:n[t.l.i],target:n[t.r.i]}})},t.triangles=function(n){var t=[];return ar(e(n)).cells.forEach(function(e,r){for(var i,u,o=e.site,a=e.edges.sort(Ve),l=-1,c=a.length,f=a[c-1].edge,s=f.l===o?f.r:f.l;++l<c;)i=f,u=s,f=a[l].edge,s=f.l===o?f.r:f.l,r<u.i&&r<s.i&&cr(o,u,s)<0&&t.push([n[r],n[u.i],n[s.i]])}),t},t.x=function(n){return arguments.length?(u=En(r=n),t):r},t.y=function(n){return arguments.length?(o=En(i=n),t):i},t.clipExtent=function(n){return arguments.length?(a=null==n?sl:n,t):a===sl?null:a},t.size=function(n){return arguments.length?t.clipExtent(n&&[[0,0],n]):a===sl?null:a&&a[1]},t)};var sl=[[-1e6,-1e6],[1e6,1e6]];ao.geom.delaunay=function(n){return ao.geom.voronoi().triangles(n)},ao.geom.quadtree=function(n,t,e,r,i){function u(n){function u(n,t,e,r,i,u,o,a){if(!isNaN(e)&&!isNaN(r))if(n.leaf){var l=n.x,f=n.y;if(null!=l)if(xo(l-e)+xo(f-r)<.01)c(n,t,e,r,i,u,o,a);else{var s=n.point;n.x=n.y=n.point=null,c(n,s,l,f,i,u,o,a),c(n,t,e,r,i,u,o,a)}else n.x=e,n.y=r,n.point=t}else c(n,t,e,r,i,u,o,a)}function c(n,t,e,r,i,o,a,l){var c=.5*(i+a),f=.5*(o+l),s=e>=c,h=r>=f,p=h<<1|s;n.leaf=!1,n=n.nodes[p]||(n.nodes[p]=hr()),s?i=c:a=c,h?o=f:l=f,u(n,t,e,r,i,o,a,l)}var f,s,h,p,g,v,d,y,m,M=En(a),x=En(l);if(null!=t)v=t,d=e,y=r,m=i;else if(y=m=-(v=d=1/0),s=[],h=[],g=n.length,o)for(p=0;g>p;++p)f=n[p],f.x<v&&(v=f.x),f.y<d&&(d=f.y),f.x>y&&(y=f.x),f.y>m&&(m=f.y),s.push(f.x),h.push(f.y);else for(p=0;g>p;++p){var b=+M(f=n[p],p),_=+x(f,p);v>b&&(v=b),d>_&&(d=_),b>y&&(y=b),_>m&&(m=_),s.push(b),h.push(_)}var w=y-v,S=m-d;w>S?m=d+w:y=v+S;var k=hr();if(k.add=function(n){u(k,n,+M(n,++p),+x(n,p),v,d,y,m)},k.visit=function(n){pr(n,k,v,d,y,m)},k.find=function(n){return gr(k,n[0],n[1],v,d,y,m)},p=-1,null==t){for(;++p<g;)u(k,n[p],s[p],h[p],v,d,y,m);--p}else n.forEach(k.add);return s=h=n=f=null,k}var o,a=Ce,l=ze;return(o=arguments.length)?(a=fr,l=sr,3===o&&(i=e,r=t,e=t=0),u(n)):(u.x=function(n){return arguments.length?(a=n,u):a},u.y=function(n){return arguments.length?(l=n,u):l},u.extent=function(n){return arguments.length?(null==n?t=e=r=i=null:(t=+n[0][0],e=+n[0][1],r=+n[1][0],i=+n[1][1]),u):null==t?null:[[t,e],[r,i]]},u.size=function(n){return arguments.length?(null==n?t=e=r=i=null:(t=e=0,r=+n[0],i=+n[1]),u):null==t?null:[r-t,i-e]},u)},ao.interpolateRgb=vr,ao.interpolateObject=dr,ao.interpolateNumber=yr,ao.interpolateString=mr;var hl=/[-+]?(?:\d+\.?\d*|\.?\d+)(?:[eE][-+]?\d+)?/g,pl=new RegExp(hl.source,"g");ao.interpolate=Mr,ao.interpolators=[function(n,t){var e=typeof t;return("string"===e?ua.has(t.toLowerCase())||/^(#|rgb\(|hsl\()/i.test(t)?vr:mr:t instanceof an?vr:Array.isArray(t)?xr:"object"===e&&isNaN(t)?dr:yr)(n,t)}],ao.interpolateArray=xr;var gl=function(){return m},vl=ao.map({linear:gl,poly:Er,quad:function(){return Sr},cubic:function(){return kr},sin:function(){return Ar},exp:function(){return Cr},circle:function(){return zr},elastic:Lr,back:qr,bounce:function(){return Tr}}),dl=ao.map({"in":m,out:_r,"in-out":wr,"out-in":function(n){return wr(_r(n))}});ao.ease=function(n){var t=n.indexOf("-"),e=t>=0?n.slice(0,t):n,r=t>=0?n.slice(t+1):"in";return e=vl.get(e)||gl,r=dl.get(r)||m,br(r(e.apply(null,lo.call(arguments,1))))},ao.interpolateHcl=Rr,ao.interpolateHsl=Dr,ao.interpolateLab=Pr,ao.interpolateRound=Ur,ao.transform=function(n){var t=fo.createElementNS(ao.ns.prefix.svg,"g");return(ao.transform=function(n){if(null!=n){t.setAttribute("transform",n);var e=t.transform.baseVal.consolidate()}return new jr(e?e.matrix:yl)})(n)},jr.prototype.toString=function(){return"translate("+this.translate+")rotate("+this.rotate+")skewX("+this.skew+")scale("+this.scale+")"};var yl={a:1,b:0,c:0,d:1,e:0,f:0};ao.interpolateTransform=$r,ao.layout={},ao.layout.bundle=function(){return function(n){for(var t=[],e=-1,r=n.length;++e<r;)t.push(Jr(n[e]));return t}},ao.layout.chord=function(){function n(){var n,c,s,h,p,g={},v=[],d=ao.range(u),y=[];for(e=[],r=[],n=0,h=-1;++h<u;){for(c=0,p=-1;++p<u;)c+=i[h][p];v.push(c),y.push(ao.range(u)),n+=c}for(o&&d.sort(function(n,t){return o(v[n],v[t])}),a&&y.forEach(function(n,t){n.sort(function(n,e){return a(i[t][n],i[t][e])})}),n=(Ho-f*u)/n,c=0,h=-1;++h<u;){for(s=c,p=-1;++p<u;){var m=d[h],M=y[m][p],x=i[m][M],b=c,_=c+=x*n;g[m+"-"+M]={index:m,subindex:M,startAngle:b,endAngle:_,value:x}}r[m]={index:m,startAngle:s,endAngle:c,value:v[m]},c+=f}for(h=-1;++h<u;)for(p=h-1;++p<u;){var w=g[h+"-"+p],S=g[p+"-"+h];(w.value||S.value)&&e.push(w.value<S.value?{source:S,target:w}:{source:w,target:S})}l&&t()}function t(){e.sort(function(n,t){return l((n.source.value+n.target.value)/2,(t.source.value+t.target.value)/2)})}var e,r,i,u,o,a,l,c={},f=0;return c.matrix=function(n){return arguments.length?(u=(i=n)&&i.length,e=r=null,c):i},c.padding=function(n){return arguments.length?(f=n,e=r=null,c):f},c.sortGroups=function(n){return arguments.length?(o=n,e=r=null,c):o},c.sortSubgroups=function(n){return arguments.length?(a=n,e=null,c):a},c.sortChords=function(n){return arguments.length?(l=n,e&&t(),c):l},c.chords=function(){return e||n(),e},c.groups=function(){return r||n(),r},c},ao.layout.force=function(){function n(n){return function(t,e,r,i){if(t.point!==n){var u=t.cx-n.x,o=t.cy-n.y,a=i-e,l=u*u+o*o;if(l>a*a/y){if(v>l){var c=t.charge/l;n.px-=u*c,n.py-=o*c}return!0}if(t.point&&l&&v>l){var c=t.pointCharge/l;n.px-=u*c,n.py-=o*c}}return!t.charge}}function t(n){n.px=ao.event.x,n.py=ao.event.y,l.resume()}var e,r,i,u,o,a,l={},c=ao.dispatch("start","tick","end"),f=[1,1],s=.9,h=ml,p=Ml,g=-30,v=xl,d=.1,y=.64,M=[],x=[];return l.tick=function(){if((i*=.99)<.005)return e=null,c.end({type:"end",alpha:i=0}),!0;var t,r,l,h,p,v,y,m,b,_=M.length,w=x.length;for(r=0;w>r;++r)l=x[r],h=l.source,p=l.target,m=p.x-h.x,b=p.y-h.y,(v=m*m+b*b)&&(v=i*o[r]*((v=Math.sqrt(v))-u[r])/v,m*=v,b*=v,p.x-=m*(y=h.weight+p.weight?h.weight/(h.weight+p.weight):.5),p.y-=b*y,h.x+=m*(y=1-y),h.y+=b*y);if((y=i*d)&&(m=f[0]/2,b=f[1]/2,r=-1,y))for(;++r<_;)l=M[r],l.x+=(m-l.x)*y,l.y+=(b-l.y)*y;if(g)for(ri(t=ao.geom.quadtree(M),i,a),r=-1;++r<_;)(l=M[r]).fixed||t.visit(n(l));for(r=-1;++r<_;)l=M[r],l.fixed?(l.x=l.px,l.y=l.py):(l.x-=(l.px-(l.px=l.x))*s,l.y-=(l.py-(l.py=l.y))*s);c.tick({type:"tick",alpha:i})},l.nodes=function(n){return arguments.length?(M=n,l):M},l.links=function(n){return arguments.length?(x=n,l):x},l.size=function(n){return arguments.length?(f=n,l):f},l.linkDistance=function(n){return arguments.length?(h="function"==typeof n?n:+n,l):h},l.distance=l.linkDistance,l.linkStrength=function(n){return arguments.length?(p="function"==typeof n?n:+n,l):p},l.friction=function(n){return arguments.length?(s=+n,l):s},l.charge=function(n){return arguments.length?(g="function"==typeof n?n:+n,l):g},l.chargeDistance=function(n){return arguments.length?(v=n*n,l):Math.sqrt(v)},l.gravity=function(n){return arguments.length?(d=+n,l):d},l.theta=function(n){return arguments.length?(y=n*n,l):Math.sqrt(y)},l.alpha=function(n){return arguments.length?(n=+n,i?n>0?i=n:(e.c=null,e.t=NaN,e=null,c.end({type:"end",alpha:i=0})):n>0&&(c.start({type:"start",alpha:i=n}),e=qn(l.tick)),l):i},l.start=function(){function n(n,r){if(!e){for(e=new Array(i),l=0;i>l;++l)e[l]=[];for(l=0;c>l;++l){var u=x[l];e[u.source.index].push(u.target),e[u.target.index].push(u.source)}}for(var o,a=e[t],l=-1,f=a.length;++l<f;)if(!isNaN(o=a[l][n]))return o;return Math.random()*r}var t,e,r,i=M.length,c=x.length,s=f[0],v=f[1];for(t=0;i>t;++t)(r=M[t]).index=t,r.weight=0;for(t=0;c>t;++t)r=x[t],"number"==typeof r.source&&(r.source=M[r.source]),"number"==typeof r.target&&(r.target=M[r.target]),++r.source.weight,++r.target.weight;for(t=0;i>t;++t)r=M[t],isNaN(r.x)&&(r.x=n("x",s)),isNaN(r.y)&&(r.y=n("y",v)),isNaN(r.px)&&(r.px=r.x),isNaN(r.py)&&(r.py=r.y);if(u=[],"function"==typeof h)for(t=0;c>t;++t)u[t]=+h.call(this,x[t],t);else for(t=0;c>t;++t)u[t]=h;if(o=[],"function"==typeof p)for(t=0;c>t;++t)o[t]=+p.call(this,x[t],t);else for(t=0;c>t;++t)o[t]=p;if(a=[],"function"==typeof g)for(t=0;i>t;++t)a[t]=+g.call(this,M[t],t);else for(t=0;i>t;++t)a[t]=g;return l.resume()},l.resume=function(){return l.alpha(.1)},l.stop=function(){return l.alpha(0)},l.drag=function(){return r||(r=ao.behavior.drag().origin(m).on("dragstart.force",Qr).on("drag.force",t).on("dragend.force",ni)),arguments.length?void this.on("mouseover.force",ti).on("mouseout.force",ei).call(r):r},ao.rebind(l,c,"on")};var ml=20,Ml=1,xl=1/0;ao.layout.hierarchy=function(){function n(i){var u,o=[i],a=[];for(i.depth=0;null!=(u=o.pop());)if(a.push(u),(c=e.call(n,u,u.depth))&&(l=c.length)){for(var l,c,f;--l>=0;)o.push(f=c[l]),f.parent=u,f.depth=u.depth+1;r&&(u.value=0),u.children=c}else r&&(u.value=+r.call(n,u,u.depth)||0),delete u.children;return oi(i,function(n){var e,i;t&&(e=n.children)&&e.sort(t),r&&(i=n.parent)&&(i.value+=n.value)}),a}var t=ci,e=ai,r=li;return n.sort=function(e){return arguments.length?(t=e,n):t},n.children=function(t){return arguments.length?(e=t,n):e},n.value=function(t){return arguments.length?(r=t,n):r},n.revalue=function(t){return r&&(ui(t,function(n){n.children&&(n.value=0)}),oi(t,function(t){var e;t.children||(t.value=+r.call(n,t,t.depth)||0),(e=t.parent)&&(e.value+=t.value)})),t},n},ao.layout.partition=function(){function n(t,e,r,i){var u=t.children;if(t.x=e,t.y=t.depth*i,t.dx=r,t.dy=i,u&&(o=u.length)){var o,a,l,c=-1;for(r=t.value?r/t.value:0;++c<o;)n(a=u[c],e,l=a.value*r,i),e+=l}}function t(n){var e=n.children,r=0;if(e&&(i=e.length))for(var i,u=-1;++u<i;)r=Math.max(r,t(e[u]));return 1+r}function e(e,u){var o=r.call(this,e,u);return n(o[0],0,i[0],i[1]/t(o[0])),o}var r=ao.layout.hierarchy(),i=[1,1];return e.size=function(n){return arguments.length?(i=n,e):i},ii(e,r)},ao.layout.pie=function(){function n(o){var a,l=o.length,c=o.map(function(e,r){return+t.call(n,e,r)}),f=+("function"==typeof r?r.apply(this,arguments):r),s=("function"==typeof i?i.apply(this,arguments):i)-f,h=Math.min(Math.abs(s)/l,+("function"==typeof u?u.apply(this,arguments):u)),p=h*(0>s?-1:1),g=ao.sum(c),v=g?(s-l*p)/g:0,d=ao.range(l),y=[];return null!=e&&d.sort(e===bl?function(n,t){return c[t]-c[n]}:function(n,t){return e(o[n],o[t])}),d.forEach(function(n){y[n]={data:o[n],value:a=c[n],startAngle:f,endAngle:f+=a*v+p,padAngle:h}}),y}var t=Number,e=bl,r=0,i=Ho,u=0;return n.value=function(e){return arguments.length?(t=e,n):t},n.sort=function(t){return arguments.length?(e=t,n):e},n.startAngle=function(t){return arguments.length?(r=t,n):r},n.endAngle=function(t){return arguments.length?(i=t,n):i},n.padAngle=function(t){return arguments.length?(u=t,n):u},n};var bl={};ao.layout.stack=function(){function n(a,l){if(!(h=a.length))return a;var c=a.map(function(e,r){return t.call(n,e,r)}),f=c.map(function(t){return t.map(function(t,e){return[u.call(n,t,e),o.call(n,t,e)]})}),s=e.call(n,f,l);c=ao.permute(c,s),f=ao.permute(f,s);var h,p,g,v,d=r.call(n,f,l),y=c[0].length;for(g=0;y>g;++g)for(i.call(n,c[0][g],v=d[g],f[0][g][1]),p=1;h>p;++p)i.call(n,c[p][g],v+=f[p-1][g][1],f[p][g][1]);return a}var t=m,e=gi,r=vi,i=pi,u=si,o=hi;return n.values=function(e){return arguments.length?(t=e,n):t},n.order=function(t){return arguments.length?(e="function"==typeof t?t:_l.get(t)||gi,n):e},n.offset=function(t){return arguments.length?(r="function"==typeof t?t:wl.get(t)||vi,n):r},n.x=function(t){return arguments.length?(u=t,n):u},n.y=function(t){return arguments.length?(o=t,n):o},n.out=function(t){return arguments.length?(i=t,n):i},n};var _l=ao.map({"inside-out":function(n){var t,e,r=n.length,i=n.map(di),u=n.map(yi),o=ao.range(r).sort(function(n,t){return i[n]-i[t]}),a=0,l=0,c=[],f=[];for(t=0;r>t;++t)e=o[t],l>a?(a+=u[e],c.push(e)):(l+=u[e],f.push(e));return f.reverse().concat(c)},reverse:function(n){return ao.range(n.length).reverse()},"default":gi}),wl=ao.map({silhouette:function(n){var t,e,r,i=n.length,u=n[0].length,o=[],a=0,l=[];for(e=0;u>e;++e){for(t=0,r=0;i>t;t++)r+=n[t][e][1];r>a&&(a=r),o.push(r)}for(e=0;u>e;++e)l[e]=(a-o[e])/2;return l},wiggle:function(n){var t,e,r,i,u,o,a,l,c,f=n.length,s=n[0],h=s.length,p=[];for(p[0]=l=c=0,e=1;h>e;++e){for(t=0,i=0;f>t;++t)i+=n[t][e][1];for(t=0,u=0,a=s[e][0]-s[e-1][0];f>t;++t){for(r=0,o=(n[t][e][1]-n[t][e-1][1])/(2*a);t>r;++r)o+=(n[r][e][1]-n[r][e-1][1])/a;u+=o*n[t][e][1]}p[e]=l-=i?u/i*a:0,c>l&&(c=l)}for(e=0;h>e;++e)p[e]-=c;return p},expand:function(n){var t,e,r,i=n.length,u=n[0].length,o=1/i,a=[];for(e=0;u>e;++e){for(t=0,r=0;i>t;t++)r+=n[t][e][1];if(r)for(t=0;i>t;t++)n[t][e][1]/=r;else for(t=0;i>t;t++)n[t][e][1]=o}for(e=0;u>e;++e)a[e]=0;return a},zero:vi});ao.layout.histogram=function(){function n(n,u){for(var o,a,l=[],c=n.map(e,this),f=r.call(this,c,u),s=i.call(this,f,c,u),u=-1,h=c.length,p=s.length-1,g=t?1:1/h;++u<p;)o=l[u]=[],o.dx=s[u+1]-(o.x=s[u]),o.y=0;if(p>0)for(u=-1;++u<h;)a=c[u],a>=f[0]&&a<=f[1]&&(o=l[ao.bisect(s,a,1,p)-1],o.y+=g,o.push(n[u]));return l}var t=!0,e=Number,r=bi,i=Mi;return n.value=function(t){return arguments.length?(e=t,n):e},n.range=function(t){return arguments.length?(r=En(t),n):r},n.bins=function(t){return arguments.length?(i="number"==typeof t?function(n){return xi(n,t)}:En(t),n):i},n.frequency=function(e){return arguments.length?(t=!!e,n):t},n},ao.layout.pack=function(){function n(n,u){var o=e.call(this,n,u),a=o[0],l=i[0],c=i[1],f=null==t?Math.sqrt:"function"==typeof t?t:function(){return t};if(a.x=a.y=0,oi(a,function(n){n.r=+f(n.value)}),oi(a,Ni),r){var s=r*(t?1:Math.max(2*a.r/l,2*a.r/c))/2;oi(a,function(n){n.r+=s}),oi(a,Ni),oi(a,function(n){n.r-=s})}return Ci(a,l/2,c/2,t?1:1/Math.max(2*a.r/l,2*a.r/c)),o}var t,e=ao.layout.hierarchy().sort(_i),r=0,i=[1,1];return n.size=function(t){return arguments.length?(i=t,n):i},n.radius=function(e){return arguments.length?(t=null==e||"function"==typeof e?e:+e,n):t},n.padding=function(t){return arguments.length?(r=+t,n):r},ii(n,e)},ao.layout.tree=function(){function n(n,i){var f=o.call(this,n,i),s=f[0],h=t(s);if(oi(h,e),h.parent.m=-h.z,ui(h,r),c)ui(s,u);else{var p=s,g=s,v=s;ui(s,function(n){n.x<p.x&&(p=n),n.x>g.x&&(g=n),n.depth>v.depth&&(v=n)});var d=a(p,g)/2-p.x,y=l[0]/(g.x+a(g,p)/2+d),m=l[1]/(v.depth||1);ui(s,function(n){n.x=(n.x+d)*y,n.y=n.depth*m})}return f}function t(n){for(var t,e={A:null,children:[n]},r=[e];null!=(t=r.pop());)for(var i,u=t.children,o=0,a=u.length;a>o;++o)r.push((u[o]=i={_:u[o],parent:t,children:(i=u[o].children)&&i.slice()||[],A:null,a:null,z:0,m:0,c:0,s:0,t:null,i:o}).a=i);return e.children[0]}function e(n){var t=n.children,e=n.parent.children,r=n.i?e[n.i-1]:null;if(t.length){Di(n);var u=(t[0].z+t[t.length-1].z)/2;r?(n.z=r.z+a(n._,r._),n.m=n.z-u):n.z=u}else r&&(n.z=r.z+a(n._,r._));n.parent.A=i(n,r,n.parent.A||e[0])}function r(n){n._.x=n.z+n.parent.m,n.m+=n.parent.m}function i(n,t,e){if(t){for(var r,i=n,u=n,o=t,l=i.parent.children[0],c=i.m,f=u.m,s=o.m,h=l.m;o=Ti(o),i=qi(i),o&&i;)l=qi(l),u=Ti(u),u.a=n,r=o.z+s-i.z-c+a(o._,i._),r>0&&(Ri(Pi(o,n,e),n,r),c+=r,f+=r),s+=o.m,c+=i.m,h+=l.m,f+=u.m;o&&!Ti(u)&&(u.t=o,u.m+=s-f),i&&!qi(l)&&(l.t=i,l.m+=c-h,e=n)}return e}function u(n){n.x*=l[0],n.y=n.depth*l[1]}var o=ao.layout.hierarchy().sort(null).value(null),a=Li,l=[1,1],c=null;return n.separation=function(t){return arguments.length?(a=t,n):a},n.size=function(t){return arguments.length?(c=null==(l=t)?u:null,n):c?null:l},n.nodeSize=function(t){return arguments.length?(c=null==(l=t)?null:u,n):c?l:null},ii(n,o)},ao.layout.cluster=function(){function n(n,u){var o,a=t.call(this,n,u),l=a[0],c=0;oi(l,function(n){var t=n.children;t&&t.length?(n.x=ji(t),n.y=Ui(t)):(n.x=o?c+=e(n,o):0,n.y=0,o=n)});var f=Fi(l),s=Hi(l),h=f.x-e(f,s)/2,p=s.x+e(s,f)/2;return oi(l,i?function(n){n.x=(n.x-l.x)*r[0],n.y=(l.y-n.y)*r[1]}:function(n){n.x=(n.x-h)/(p-h)*r[0],n.y=(1-(l.y?n.y/l.y:1))*r[1]}),a}var t=ao.layout.hierarchy().sort(null).value(null),e=Li,r=[1,1],i=!1;return n.separation=function(t){return arguments.length?(e=t,n):e},n.size=function(t){return arguments.length?(i=null==(r=t),n):i?null:r},n.nodeSize=function(t){return arguments.length?(i=null!=(r=t),n):i?r:null},ii(n,t)},ao.layout.treemap=function(){function n(n,t){for(var e,r,i=-1,u=n.length;++i<u;)r=(e=n[i]).value*(0>t?0:t),e.area=isNaN(r)||0>=r?0:r}function t(e){var u=e.children;if(u&&u.length){var o,a,l,c=s(e),f=[],h=u.slice(),g=1/0,v="slice"===p?c.dx:"dice"===p?c.dy:"slice-dice"===p?1&e.depth?c.dy:c.dx:Math.min(c.dx,c.dy);for(n(h,c.dx*c.dy/e.value),f.area=0;(l=h.length)>0;)f.push(o=h[l-1]),f.area+=o.area,"squarify"!==p||(a=r(f,v))<=g?(h.pop(),g=a):(f.area-=f.pop().area,i(f,v,c,!1),v=Math.min(c.dx,c.dy),f.length=f.area=0,g=1/0);f.length&&(i(f,v,c,!0),f.length=f.area=0),u.forEach(t)}}function e(t){var r=t.children;if(r&&r.length){var u,o=s(t),a=r.slice(),l=[];for(n(a,o.dx*o.dy/t.value),l.area=0;u=a.pop();)l.push(u),l.area+=u.area,null!=u.z&&(i(l,u.z?o.dx:o.dy,o,!a.length),l.length=l.area=0);r.forEach(e)}}function r(n,t){for(var e,r=n.area,i=0,u=1/0,o=-1,a=n.length;++o<a;)(e=n[o].area)&&(u>e&&(u=e),e>i&&(i=e));return r*=r,t*=t,r?Math.max(t*i*g/r,r/(t*u*g)):1/0}function i(n,t,e,r){var i,u=-1,o=n.length,a=e.x,c=e.y,f=t?l(n.area/t):0;
+if(t==e.dx){for((r||f>e.dy)&&(f=e.dy);++u<o;)i=n[u],i.x=a,i.y=c,i.dy=f,a+=i.dx=Math.min(e.x+e.dx-a,f?l(i.area/f):0);i.z=!0,i.dx+=e.x+e.dx-a,e.y+=f,e.dy-=f}else{for((r||f>e.dx)&&(f=e.dx);++u<o;)i=n[u],i.x=a,i.y=c,i.dx=f,c+=i.dy=Math.min(e.y+e.dy-c,f?l(i.area/f):0);i.z=!1,i.dy+=e.y+e.dy-c,e.x+=f,e.dx-=f}}function u(r){var i=o||a(r),u=i[0];return u.x=u.y=0,u.value?(u.dx=c[0],u.dy=c[1]):u.dx=u.dy=0,o&&a.revalue(u),n([u],u.dx*u.dy/u.value),(o?e:t)(u),h&&(o=i),i}var o,a=ao.layout.hierarchy(),l=Math.round,c=[1,1],f=null,s=Oi,h=!1,p="squarify",g=.5*(1+Math.sqrt(5));return u.size=function(n){return arguments.length?(c=n,u):c},u.padding=function(n){function t(t){var e=n.call(u,t,t.depth);return null==e?Oi(t):Ii(t,"number"==typeof e?[e,e,e,e]:e)}function e(t){return Ii(t,n)}if(!arguments.length)return f;var r;return s=null==(f=n)?Oi:"function"==(r=typeof n)?t:"number"===r?(n=[n,n,n,n],e):e,u},u.round=function(n){return arguments.length?(l=n?Math.round:Number,u):l!=Number},u.sticky=function(n){return arguments.length?(h=n,o=null,u):h},u.ratio=function(n){return arguments.length?(g=n,u):g},u.mode=function(n){return arguments.length?(p=n+"",u):p},ii(u,a)},ao.random={normal:function(n,t){var e=arguments.length;return 2>e&&(t=1),1>e&&(n=0),function(){var e,r,i;do e=2*Math.random()-1,r=2*Math.random()-1,i=e*e+r*r;while(!i||i>1);return n+t*e*Math.sqrt(-2*Math.log(i)/i)}},logNormal:function(){var n=ao.random.normal.apply(ao,arguments);return function(){return Math.exp(n())}},bates:function(n){var t=ao.random.irwinHall(n);return function(){return t()/n}},irwinHall:function(n){return function(){for(var t=0,e=0;n>e;e++)t+=Math.random();return t}}},ao.scale={};var Sl={floor:m,ceil:m};ao.scale.linear=function(){return Wi([0,1],[0,1],Mr,!1)};var kl={s:1,g:1,p:1,r:1,e:1};ao.scale.log=function(){return ru(ao.scale.linear().domain([0,1]),10,!0,[1,10])};var Nl=ao.format(".0e"),El={floor:function(n){return-Math.ceil(-n)},ceil:function(n){return-Math.floor(-n)}};ao.scale.pow=function(){return iu(ao.scale.linear(),1,[0,1])},ao.scale.sqrt=function(){return ao.scale.pow().exponent(.5)},ao.scale.ordinal=function(){return ou([],{t:"range",a:[[]]})},ao.scale.category10=function(){return ao.scale.ordinal().range(Al)},ao.scale.category20=function(){return ao.scale.ordinal().range(Cl)},ao.scale.category20b=function(){return ao.scale.ordinal().range(zl)},ao.scale.category20c=function(){return ao.scale.ordinal().range(Ll)};var Al=[2062260,16744206,2924588,14034728,9725885,9197131,14907330,8355711,12369186,1556175].map(xn),Cl=[2062260,11454440,16744206,16759672,2924588,10018698,14034728,16750742,9725885,12955861,9197131,12885140,14907330,16234194,8355711,13092807,12369186,14408589,1556175,10410725].map(xn),zl=[3750777,5395619,7040719,10264286,6519097,9216594,11915115,13556636,9202993,12426809,15186514,15190932,8666169,11356490,14049643,15177372,8077683,10834324,13528509,14589654].map(xn),Ll=[3244733,7057110,10406625,13032431,15095053,16616764,16625259,16634018,3253076,7652470,10607003,13101504,7695281,10394312,12369372,14342891,6513507,9868950,12434877,14277081].map(xn);ao.scale.quantile=function(){return au([],[])},ao.scale.quantize=function(){return lu(0,1,[0,1])},ao.scale.threshold=function(){return cu([.5],[0,1])},ao.scale.identity=function(){return fu([0,1])},ao.svg={},ao.svg.arc=function(){function n(){var n=Math.max(0,+e.apply(this,arguments)),c=Math.max(0,+r.apply(this,arguments)),f=o.apply(this,arguments)-Io,s=a.apply(this,arguments)-Io,h=Math.abs(s-f),p=f>s?0:1;if(n>c&&(g=c,c=n,n=g),h>=Oo)return t(c,p)+(n?t(n,1-p):"")+"Z";var g,v,d,y,m,M,x,b,_,w,S,k,N=0,E=0,A=[];if((y=(+l.apply(this,arguments)||0)/2)&&(d=u===ql?Math.sqrt(n*n+c*c):+u.apply(this,arguments),p||(E*=-1),c&&(E=tn(d/c*Math.sin(y))),n&&(N=tn(d/n*Math.sin(y)))),c){m=c*Math.cos(f+E),M=c*Math.sin(f+E),x=c*Math.cos(s-E),b=c*Math.sin(s-E);var C=Math.abs(s-f-2*E)<=Fo?0:1;if(E&&yu(m,M,x,b)===p^C){var z=(f+s)/2;m=c*Math.cos(z),M=c*Math.sin(z),x=b=null}}else m=M=0;if(n){_=n*Math.cos(s-N),w=n*Math.sin(s-N),S=n*Math.cos(f+N),k=n*Math.sin(f+N);var L=Math.abs(f-s+2*N)<=Fo?0:1;if(N&&yu(_,w,S,k)===1-p^L){var q=(f+s)/2;_=n*Math.cos(q),w=n*Math.sin(q),S=k=null}}else _=w=0;if(h>Uo&&(g=Math.min(Math.abs(c-n)/2,+i.apply(this,arguments)))>.001){v=c>n^p?0:1;var T=g,R=g;if(Fo>h){var D=null==S?[_,w]:null==x?[m,M]:Re([m,M],[S,k],[x,b],[_,w]),P=m-D[0],U=M-D[1],j=x-D[0],F=b-D[1],H=1/Math.sin(Math.acos((P*j+U*F)/(Math.sqrt(P*P+U*U)*Math.sqrt(j*j+F*F)))/2),O=Math.sqrt(D[0]*D[0]+D[1]*D[1]);R=Math.min(g,(n-O)/(H-1)),T=Math.min(g,(c-O)/(H+1))}if(null!=x){var I=mu(null==S?[_,w]:[S,k],[m,M],c,T,p),Y=mu([x,b],[_,w],c,T,p);g===T?A.push("M",I[0],"A",T,",",T," 0 0,",v," ",I[1],"A",c,",",c," 0 ",1-p^yu(I[1][0],I[1][1],Y[1][0],Y[1][1]),",",p," ",Y[1],"A",T,",",T," 0 0,",v," ",Y[0]):A.push("M",I[0],"A",T,",",T," 0 1,",v," ",Y[0])}else A.push("M",m,",",M);if(null!=S){var Z=mu([m,M],[S,k],n,-R,p),V=mu([_,w],null==x?[m,M]:[x,b],n,-R,p);g===R?A.push("L",V[0],"A",R,",",R," 0 0,",v," ",V[1],"A",n,",",n," 0 ",p^yu(V[1][0],V[1][1],Z[1][0],Z[1][1]),",",1-p," ",Z[1],"A",R,",",R," 0 0,",v," ",Z[0]):A.push("L",V[0],"A",R,",",R," 0 0,",v," ",Z[0])}else A.push("L",_,",",w)}else A.push("M",m,",",M),null!=x&&A.push("A",c,",",c," 0 ",C,",",p," ",x,",",b),A.push("L",_,",",w),null!=S&&A.push("A",n,",",n," 0 ",L,",",1-p," ",S,",",k);return A.push("Z"),A.join("")}function t(n,t){return"M0,"+n+"A"+n+","+n+" 0 1,"+t+" 0,"+-n+"A"+n+","+n+" 0 1,"+t+" 0,"+n}var e=hu,r=pu,i=su,u=ql,o=gu,a=vu,l=du;return n.innerRadius=function(t){return arguments.length?(e=En(t),n):e},n.outerRadius=function(t){return arguments.length?(r=En(t),n):r},n.cornerRadius=function(t){return arguments.length?(i=En(t),n):i},n.padRadius=function(t){return arguments.length?(u=t==ql?ql:En(t),n):u},n.startAngle=function(t){return arguments.length?(o=En(t),n):o},n.endAngle=function(t){return arguments.length?(a=En(t),n):a},n.padAngle=function(t){return arguments.length?(l=En(t),n):l},n.centroid=function(){var n=(+e.apply(this,arguments)+ +r.apply(this,arguments))/2,t=(+o.apply(this,arguments)+ +a.apply(this,arguments))/2-Io;return[Math.cos(t)*n,Math.sin(t)*n]},n};var ql="auto";ao.svg.line=function(){return Mu(m)};var Tl=ao.map({linear:xu,"linear-closed":bu,step:_u,"step-before":wu,"step-after":Su,basis:zu,"basis-open":Lu,"basis-closed":qu,bundle:Tu,cardinal:Eu,"cardinal-open":ku,"cardinal-closed":Nu,monotone:Fu});Tl.forEach(function(n,t){t.key=n,t.closed=/-closed$/.test(n)});var Rl=[0,2/3,1/3,0],Dl=[0,1/3,2/3,0],Pl=[0,1/6,2/3,1/6];ao.svg.line.radial=function(){var n=Mu(Hu);return n.radius=n.x,delete n.x,n.angle=n.y,delete n.y,n},wu.reverse=Su,Su.reverse=wu,ao.svg.area=function(){return Ou(m)},ao.svg.area.radial=function(){var n=Ou(Hu);return n.radius=n.x,delete n.x,n.innerRadius=n.x0,delete n.x0,n.outerRadius=n.x1,delete n.x1,n.angle=n.y,delete n.y,n.startAngle=n.y0,delete n.y0,n.endAngle=n.y1,delete n.y1,n},ao.svg.chord=function(){function n(n,a){var l=t(this,u,n,a),c=t(this,o,n,a);return"M"+l.p0+r(l.r,l.p1,l.a1-l.a0)+(e(l,c)?i(l.r,l.p1,l.r,l.p0):i(l.r,l.p1,c.r,c.p0)+r(c.r,c.p1,c.a1-c.a0)+i(c.r,c.p1,l.r,l.p0))+"Z"}function t(n,t,e,r){var i=t.call(n,e,r),u=a.call(n,i,r),o=l.call(n,i,r)-Io,f=c.call(n,i,r)-Io;return{r:u,a0:o,a1:f,p0:[u*Math.cos(o),u*Math.sin(o)],p1:[u*Math.cos(f),u*Math.sin(f)]}}function e(n,t){return n.a0==t.a0&&n.a1==t.a1}function r(n,t,e){return"A"+n+","+n+" 0 "+ +(e>Fo)+",1 "+t}function i(n,t,e,r){return"Q 0,0 "+r}var u=Me,o=xe,a=Iu,l=gu,c=vu;return n.radius=function(t){return arguments.length?(a=En(t),n):a},n.source=function(t){return arguments.length?(u=En(t),n):u},n.target=function(t){return arguments.length?(o=En(t),n):o},n.startAngle=function(t){return arguments.length?(l=En(t),n):l},n.endAngle=function(t){return arguments.length?(c=En(t),n):c},n},ao.svg.diagonal=function(){function n(n,i){var u=t.call(this,n,i),o=e.call(this,n,i),a=(u.y+o.y)/2,l=[u,{x:u.x,y:a},{x:o.x,y:a},o];return l=l.map(r),"M"+l[0]+"C"+l[1]+" "+l[2]+" "+l[3]}var t=Me,e=xe,r=Yu;return n.source=function(e){return arguments.length?(t=En(e),n):t},n.target=function(t){return arguments.length?(e=En(t),n):e},n.projection=function(t){return arguments.length?(r=t,n):r},n},ao.svg.diagonal.radial=function(){var n=ao.svg.diagonal(),t=Yu,e=n.projection;return n.projection=function(n){return arguments.length?e(Zu(t=n)):t},n},ao.svg.symbol=function(){function n(n,r){return(Ul.get(t.call(this,n,r))||$u)(e.call(this,n,r))}var t=Xu,e=Vu;return n.type=function(e){return arguments.length?(t=En(e),n):t},n.size=function(t){return arguments.length?(e=En(t),n):e},n};var Ul=ao.map({circle:$u,cross:function(n){var t=Math.sqrt(n/5)/2;return"M"+-3*t+","+-t+"H"+-t+"V"+-3*t+"H"+t+"V"+-t+"H"+3*t+"V"+t+"H"+t+"V"+3*t+"H"+-t+"V"+t+"H"+-3*t+"Z"},diamond:function(n){var t=Math.sqrt(n/(2*Fl)),e=t*Fl;return"M0,"+-t+"L"+e+",0 0,"+t+" "+-e+",0Z"},square:function(n){var t=Math.sqrt(n)/2;return"M"+-t+","+-t+"L"+t+","+-t+" "+t+","+t+" "+-t+","+t+"Z"},"triangle-down":function(n){var t=Math.sqrt(n/jl),e=t*jl/2;return"M0,"+e+"L"+t+","+-e+" "+-t+","+-e+"Z"},"triangle-up":function(n){var t=Math.sqrt(n/jl),e=t*jl/2;return"M0,"+-e+"L"+t+","+e+" "+-t+","+e+"Z"}});ao.svg.symbolTypes=Ul.keys();var jl=Math.sqrt(3),Fl=Math.tan(30*Yo);Co.transition=function(n){for(var t,e,r=Hl||++Zl,i=Ku(n),u=[],o=Ol||{time:Date.now(),ease:Nr,delay:0,duration:250},a=-1,l=this.length;++a<l;){u.push(t=[]);for(var c=this[a],f=-1,s=c.length;++f<s;)(e=c[f])&&Qu(e,f,i,r,o),t.push(e)}return Wu(u,i,r)},Co.interrupt=function(n){return this.each(null==n?Il:Bu(Ku(n)))};var Hl,Ol,Il=Bu(Ku()),Yl=[],Zl=0;Yl.call=Co.call,Yl.empty=Co.empty,Yl.node=Co.node,Yl.size=Co.size,ao.transition=function(n,t){return n&&n.transition?Hl?n.transition(t):n:ao.selection().transition(n)},ao.transition.prototype=Yl,Yl.select=function(n){var t,e,r,i=this.id,u=this.namespace,o=[];n=A(n);for(var a=-1,l=this.length;++a<l;){o.push(t=[]);for(var c=this[a],f=-1,s=c.length;++f<s;)(r=c[f])&&(e=n.call(r,r.__data__,f,a))?("__data__"in r&&(e.__data__=r.__data__),Qu(e,f,u,i,r[u][i]),t.push(e)):t.push(null)}return Wu(o,u,i)},Yl.selectAll=function(n){var t,e,r,i,u,o=this.id,a=this.namespace,l=[];n=C(n);for(var c=-1,f=this.length;++c<f;)for(var s=this[c],h=-1,p=s.length;++h<p;)if(r=s[h]){u=r[a][o],e=n.call(r,r.__data__,h,c),l.push(t=[]);for(var g=-1,v=e.length;++g<v;)(i=e[g])&&Qu(i,g,a,o,u),t.push(i)}return Wu(l,a,o)},Yl.filter=function(n){var t,e,r,i=[];"function"!=typeof n&&(n=O(n));for(var u=0,o=this.length;o>u;u++){i.push(t=[]);for(var e=this[u],a=0,l=e.length;l>a;a++)(r=e[a])&&n.call(r,r.__data__,a,u)&&t.push(r)}return Wu(i,this.namespace,this.id)},Yl.tween=function(n,t){var e=this.id,r=this.namespace;return arguments.length<2?this.node()[r][e].tween.get(n):Y(this,null==t?function(t){t[r][e].tween.remove(n)}:function(i){i[r][e].tween.set(n,t)})},Yl.attr=function(n,t){function e(){this.removeAttribute(a)}function r(){this.removeAttributeNS(a.space,a.local)}function i(n){return null==n?e:(n+="",function(){var t,e=this.getAttribute(a);return e!==n&&(t=o(e,n),function(n){this.setAttribute(a,t(n))})})}function u(n){return null==n?r:(n+="",function(){var t,e=this.getAttributeNS(a.space,a.local);return e!==n&&(t=o(e,n),function(n){this.setAttributeNS(a.space,a.local,t(n))})})}if(arguments.length<2){for(t in n)this.attr(t,n[t]);return this}var o="transform"==n?$r:Mr,a=ao.ns.qualify(n);return Ju(this,"attr."+n,t,a.local?u:i)},Yl.attrTween=function(n,t){function e(n,e){var r=t.call(this,n,e,this.getAttribute(i));return r&&function(n){this.setAttribute(i,r(n))}}function r(n,e){var r=t.call(this,n,e,this.getAttributeNS(i.space,i.local));return r&&function(n){this.setAttributeNS(i.space,i.local,r(n))}}var i=ao.ns.qualify(n);return this.tween("attr."+n,i.local?r:e)},Yl.style=function(n,e,r){function i(){this.style.removeProperty(n)}function u(e){return null==e?i:(e+="",function(){var i,u=t(this).getComputedStyle(this,null).getPropertyValue(n);return u!==e&&(i=Mr(u,e),function(t){this.style.setProperty(n,i(t),r)})})}var o=arguments.length;if(3>o){if("string"!=typeof n){2>o&&(e="");for(r in n)this.style(r,n[r],e);return this}r=""}return Ju(this,"style."+n,e,u)},Yl.styleTween=function(n,e,r){function i(i,u){var o=e.call(this,i,u,t(this).getComputedStyle(this,null).getPropertyValue(n));return o&&function(t){this.style.setProperty(n,o(t),r)}}return arguments.length<3&&(r=""),this.tween("style."+n,i)},Yl.text=function(n){return Ju(this,"text",n,Gu)},Yl.remove=function(){var n=this.namespace;return this.each("end.transition",function(){var t;this[n].count<2&&(t=this.parentNode)&&t.removeChild(this)})},Yl.ease=function(n){var t=this.id,e=this.namespace;return arguments.length<1?this.node()[e][t].ease:("function"!=typeof n&&(n=ao.ease.apply(ao,arguments)),Y(this,function(r){r[e][t].ease=n}))},Yl.delay=function(n){var t=this.id,e=this.namespace;return arguments.length<1?this.node()[e][t].delay:Y(this,"function"==typeof n?function(r,i,u){r[e][t].delay=+n.call(r,r.__data__,i,u)}:(n=+n,function(r){r[e][t].delay=n}))},Yl.duration=function(n){var t=this.id,e=this.namespace;return arguments.length<1?this.node()[e][t].duration:Y(this,"function"==typeof n?function(r,i,u){r[e][t].duration=Math.max(1,n.call(r,r.__data__,i,u))}:(n=Math.max(1,n),function(r){r[e][t].duration=n}))},Yl.each=function(n,t){var e=this.id,r=this.namespace;if(arguments.length<2){var i=Ol,u=Hl;try{Hl=e,Y(this,function(t,i,u){Ol=t[r][e],n.call(t,t.__data__,i,u)})}finally{Ol=i,Hl=u}}else Y(this,function(i){var u=i[r][e];(u.event||(u.event=ao.dispatch("start","end","interrupt"))).on(n,t)});return this},Yl.transition=function(){for(var n,t,e,r,i=this.id,u=++Zl,o=this.namespace,a=[],l=0,c=this.length;c>l;l++){a.push(n=[]);for(var t=this[l],f=0,s=t.length;s>f;f++)(e=t[f])&&(r=e[o][i],Qu(e,f,o,u,{time:r.time,ease:r.ease,delay:r.delay+r.duration,duration:r.duration})),n.push(e)}return Wu(a,o,u)},ao.svg.axis=function(){function n(n){n.each(function(){var n,c=ao.select(this),f=this.__chart__||e,s=this.__chart__=e.copy(),h=null==l?s.ticks?s.ticks.apply(s,a):s.domain():l,p=null==t?s.tickFormat?s.tickFormat.apply(s,a):m:t,g=c.selectAll(".tick").data(h,s),v=g.enter().insert("g",".domain").attr("class","tick").style("opacity",Uo),d=ao.transition(g.exit()).style("opacity",Uo).remove(),y=ao.transition(g.order()).style("opacity",1),M=Math.max(i,0)+o,x=Zi(s),b=c.selectAll(".domain").data([0]),_=(b.enter().append("path").attr("class","domain"),ao.transition(b));v.append("line"),v.append("text");var w,S,k,N,E=v.select("line"),A=y.select("line"),C=g.select("text").text(p),z=v.select("text"),L=y.select("text"),q="top"===r||"left"===r?-1:1;if("bottom"===r||"top"===r?(n=no,w="x",k="y",S="x2",N="y2",C.attr("dy",0>q?"0em":".71em").style("text-anchor","middle"),_.attr("d","M"+x[0]+","+q*u+"V0H"+x[1]+"V"+q*u)):(n=to,w="y",k="x",S="y2",N="x2",C.attr("dy",".32em").style("text-anchor",0>q?"end":"start"),_.attr("d","M"+q*u+","+x[0]+"H0V"+x[1]+"H"+q*u)),E.attr(N,q*i),z.attr(k,q*M),A.attr(S,0).attr(N,q*i),L.attr(w,0).attr(k,q*M),s.rangeBand){var T=s,R=T.rangeBand()/2;f=s=function(n){return T(n)+R}}else f.rangeBand?f=s:d.call(n,s,f);v.call(n,f,s),y.call(n,s,s)})}var t,e=ao.scale.linear(),r=Vl,i=6,u=6,o=3,a=[10],l=null;return n.scale=function(t){return arguments.length?(e=t,n):e},n.orient=function(t){return arguments.length?(r=t in Xl?t+"":Vl,n):r},n.ticks=function(){return arguments.length?(a=co(arguments),n):a},n.tickValues=function(t){return arguments.length?(l=t,n):l},n.tickFormat=function(e){return arguments.length?(t=e,n):t},n.tickSize=function(t){var e=arguments.length;return e?(i=+t,u=+arguments[e-1],n):i},n.innerTickSize=function(t){return arguments.length?(i=+t,n):i},n.outerTickSize=function(t){return arguments.length?(u=+t,n):u},n.tickPadding=function(t){return arguments.length?(o=+t,n):o},n.tickSubdivide=function(){return arguments.length&&n},n};var Vl="bottom",Xl={top:1,right:1,bottom:1,left:1};ao.svg.brush=function(){function n(t){t.each(function(){var t=ao.select(this).style("pointer-events","all").style("-webkit-tap-highlight-color","rgba(0,0,0,0)").on("mousedown.brush",u).on("touchstart.brush",u),o=t.selectAll(".background").data([0]);o.enter().append("rect").attr("class","background").style("visibility","hidden").style("cursor","crosshair"),t.selectAll(".extent").data([0]).enter().append("rect").attr("class","extent").style("cursor","move");var a=t.selectAll(".resize").data(v,m);a.exit().remove(),a.enter().append("g").attr("class",function(n){return"resize "+n}).style("cursor",function(n){return $l[n]}).append("rect").attr("x",function(n){return/[ew]$/.test(n)?-3:null}).attr("y",function(n){return/^[ns]/.test(n)?-3:null}).attr("width",6).attr("height",6).style("visibility","hidden"),a.style("display",n.empty()?"none":null);var l,s=ao.transition(t),h=ao.transition(o);c&&(l=Zi(c),h.attr("x",l[0]).attr("width",l[1]-l[0]),r(s)),f&&(l=Zi(f),h.attr("y",l[0]).attr("height",l[1]-l[0]),i(s)),e(s)})}function e(n){n.selectAll(".resize").attr("transform",function(n){return"translate("+s[+/e$/.test(n)]+","+h[+/^s/.test(n)]+")"})}function r(n){n.select(".extent").attr("x",s[0]),n.selectAll(".extent,.n>rect,.s>rect").attr("width",s[1]-s[0])}function i(n){n.select(".extent").attr("y",h[0]),n.selectAll(".extent,.e>rect,.w>rect").attr("height",h[1]-h[0])}function u(){function u(){32==ao.event.keyCode&&(C||(M=null,L[0]-=s[1],L[1]-=h[1],C=2),S())}function v(){32==ao.event.keyCode&&2==C&&(L[0]+=s[1],L[1]+=h[1],C=0,S())}function d(){var n=ao.mouse(b),t=!1;x&&(n[0]+=x[0],n[1]+=x[1]),C||(ao.event.altKey?(M||(M=[(s[0]+s[1])/2,(h[0]+h[1])/2]),L[0]=s[+(n[0]<M[0])],L[1]=h[+(n[1]<M[1])]):M=null),E&&y(n,c,0)&&(r(k),t=!0),A&&y(n,f,1)&&(i(k),t=!0),t&&(e(k),w({type:"brush",mode:C?"move":"resize"}))}function y(n,t,e){var r,i,u=Zi(t),l=u[0],c=u[1],f=L[e],v=e?h:s,d=v[1]-v[0];return C&&(l-=f,c-=d+f),r=(e?g:p)?Math.max(l,Math.min(c,n[e])):n[e],C?i=(r+=f)+d:(M&&(f=Math.max(l,Math.min(c,2*M[e]-r))),r>f?(i=r,r=f):i=f),v[0]!=r||v[1]!=i?(e?a=null:o=null,v[0]=r,v[1]=i,!0):void 0}function m(){d(),k.style("pointer-events","all").selectAll(".resize").style("display",n.empty()?"none":null),ao.select("body").style("cursor",null),q.on("mousemove.brush",null).on("mouseup.brush",null).on("touchmove.brush",null).on("touchend.brush",null).on("keydown.brush",null).on("keyup.brush",null),z(),w({type:"brushend"})}var M,x,b=this,_=ao.select(ao.event.target),w=l.of(b,arguments),k=ao.select(b),N=_.datum(),E=!/^(n|s)$/.test(N)&&c,A=!/^(e|w)$/.test(N)&&f,C=_.classed("extent"),z=W(b),L=ao.mouse(b),q=ao.select(t(b)).on("keydown.brush",u).on("keyup.brush",v);if(ao.event.changedTouches?q.on("touchmove.brush",d).on("touchend.brush",m):q.on("mousemove.brush",d).on("mouseup.brush",m),k.interrupt().selectAll("*").interrupt(),C)L[0]=s[0]-L[0],L[1]=h[0]-L[1];else if(N){var T=+/w$/.test(N),R=+/^n/.test(N);x=[s[1-T]-L[0],h[1-R]-L[1]],L[0]=s[T],L[1]=h[R]}else ao.event.altKey&&(M=L.slice());k.style("pointer-events","none").selectAll(".resize").style("display",null),ao.select("body").style("cursor",_.style("cursor")),w({type:"brushstart"}),d()}var o,a,l=N(n,"brushstart","brush","brushend"),c=null,f=null,s=[0,0],h=[0,0],p=!0,g=!0,v=Bl[0];return n.event=function(n){n.each(function(){var n=l.of(this,arguments),t={x:s,y:h,i:o,j:a},e=this.__chart__||t;this.__chart__=t,Hl?ao.select(this).transition().each("start.brush",function(){o=e.i,a=e.j,s=e.x,h=e.y,n({type:"brushstart"})}).tween("brush:brush",function(){var e=xr(s,t.x),r=xr(h,t.y);return o=a=null,function(i){s=t.x=e(i),h=t.y=r(i),n({type:"brush",mode:"resize"})}}).each("end.brush",function(){o=t.i,a=t.j,n({type:"brush",mode:"resize"}),n({type:"brushend"})}):(n({type:"brushstart"}),n({type:"brush",mode:"resize"}),n({type:"brushend"}))})},n.x=function(t){return arguments.length?(c=t,v=Bl[!c<<1|!f],n):c},n.y=function(t){return arguments.length?(f=t,v=Bl[!c<<1|!f],n):f},n.clamp=function(t){return arguments.length?(c&&f?(p=!!t[0],g=!!t[1]):c?p=!!t:f&&(g=!!t),n):c&&f?[p,g]:c?p:f?g:null},n.extent=function(t){var e,r,i,u,l;return arguments.length?(c&&(e=t[0],r=t[1],f&&(e=e[0],r=r[0]),o=[e,r],c.invert&&(e=c(e),r=c(r)),e>r&&(l=e,e=r,r=l),e==s[0]&&r==s[1]||(s=[e,r])),f&&(i=t[0],u=t[1],c&&(i=i[1],u=u[1]),a=[i,u],f.invert&&(i=f(i),u=f(u)),i>u&&(l=i,i=u,u=l),i==h[0]&&u==h[1]||(h=[i,u])),n):(c&&(o?(e=o[0],r=o[1]):(e=s[0],r=s[1],c.invert&&(e=c.invert(e),r=c.invert(r)),e>r&&(l=e,e=r,r=l))),f&&(a?(i=a[0],u=a[1]):(i=h[0],u=h[1],f.invert&&(i=f.invert(i),u=f.invert(u)),i>u&&(l=i,i=u,u=l))),c&&f?[[e,i],[r,u]]:c?[e,r]:f&&[i,u])},n.clear=function(){return n.empty()||(s=[0,0],h=[0,0],o=a=null),n},n.empty=function(){return!!c&&s[0]==s[1]||!!f&&h[0]==h[1]},ao.rebind(n,l,"on")};var $l={n:"ns-resize",e:"ew-resize",s:"ns-resize",w:"ew-resize",nw:"nwse-resize",ne:"nesw-resize",se:"nwse-resize",sw:"nesw-resize"},Bl=[["n","e","s","w","nw","ne","se","sw"],["e","w"],["n","s"],[]],Wl=ga.format=xa.timeFormat,Jl=Wl.utc,Gl=Jl("%Y-%m-%dT%H:%M:%S.%LZ");Wl.iso=Date.prototype.toISOString&&+new Date("2000-01-01T00:00:00.000Z")?eo:Gl,eo.parse=function(n){var t=new Date(n);return isNaN(t)?null:t},eo.toString=Gl.toString,ga.second=On(function(n){return new va(1e3*Math.floor(n/1e3))},function(n,t){n.setTime(n.getTime()+1e3*Math.floor(t))},function(n){return n.getSeconds()}),ga.seconds=ga.second.range,ga.seconds.utc=ga.second.utc.range,ga.minute=On(function(n){return new va(6e4*Math.floor(n/6e4))},function(n,t){n.setTime(n.getTime()+6e4*Math.floor(t))},function(n){return n.getMinutes()}),ga.minutes=ga.minute.range,ga.minutes.utc=ga.minute.utc.range,ga.hour=On(function(n){var t=n.getTimezoneOffset()/60;return new va(36e5*(Math.floor(n/36e5-t)+t))},function(n,t){n.setTime(n.getTime()+36e5*Math.floor(t))},function(n){return n.getHours()}),ga.hours=ga.hour.range,ga.hours.utc=ga.hour.utc.range,ga.month=On(function(n){return n=ga.day(n),n.setDate(1),n},function(n,t){n.setMonth(n.getMonth()+t)},function(n){return n.getMonth()}),ga.months=ga.month.range,ga.months.utc=ga.month.utc.range;var Kl=[1e3,5e3,15e3,3e4,6e4,3e5,9e5,18e5,36e5,108e5,216e5,432e5,864e5,1728e5,6048e5,2592e6,7776e6,31536e6],Ql=[[ga.second,1],[ga.second,5],[ga.second,15],[ga.second,30],[ga.minute,1],[ga.minute,5],[ga.minute,15],[ga.minute,30],[ga.hour,1],[ga.hour,3],[ga.hour,6],[ga.hour,12],[ga.day,1],[ga.day,2],[ga.week,1],[ga.month,1],[ga.month,3],[ga.year,1]],nc=Wl.multi([[".%L",function(n){return n.getMilliseconds()}],[":%S",function(n){return n.getSeconds()}],["%I:%M",function(n){return n.getMinutes()}],["%I %p",function(n){return n.getHours()}],["%a %d",function(n){return n.getDay()&&1!=n.getDate()}],["%b %d",function(n){return 1!=n.getDate()}],["%B",function(n){return n.getMonth()}],["%Y",zt]]),tc={range:function(n,t,e){return ao.range(Math.ceil(n/e)*e,+t,e).map(io)},floor:m,ceil:m};Ql.year=ga.year,ga.scale=function(){return ro(ao.scale.linear(),Ql,nc)};var ec=Ql.map(function(n){return[n[0].utc,n[1]]}),rc=Jl.multi([[".%L",function(n){return n.getUTCMilliseconds()}],[":%S",function(n){return n.getUTCSeconds()}],["%I:%M",function(n){return n.getUTCMinutes()}],["%I %p",function(n){return n.getUTCHours()}],["%a %d",function(n){return n.getUTCDay()&&1!=n.getUTCDate()}],["%b %d",function(n){return 1!=n.getUTCDate()}],["%B",function(n){return n.getUTCMonth()}],["%Y",zt]]);ec.year=ga.year.utc,ga.scale.utc=function(){return ro(ao.scale.linear(),ec,rc)},ao.text=An(function(n){return n.responseText}),ao.json=function(n,t){return Cn(n,"application/json",uo,t)},ao.html=function(n,t){return Cn(n,"text/html",oo,t)},ao.xml=An(function(n){return n.responseXML}),"function"==typeof define&&define.amd?(this.d3=ao,define(ao)):"object"==typeof module&&module.exports?module.exports=ao:this.d3=ao}();
\ No newline at end of file
diff --git a/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/js/file.js b/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/js/file.js
new file mode 100644
index 0000000000000000000000000000000000000000..29cacd4d1d1df3456c23e7a3d7f8047da3e65c80
--- /dev/null
+++ b/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/js/file.js
@@ -0,0 +1,62 @@
+  $(function() {
+   var $window     = $(window)
+     , $top_link   = $('#toplink')
+     , $body       = $('body, html')
+     , offset      = $('#code').offset().top
+     , hidePopover = function ($target) {
+        $target.data('popover-hover', false);
+
+        setTimeout(function () {
+         if (!$target.data('popover-hover')) {
+          $target.popover('hide');
+         }
+        }, 300);
+     };
+
+   $top_link.hide().click(function(event) {
+    event.preventDefault();
+    $body.animate({scrollTop:0}, 800);
+   });
+
+   $window.scroll(function() {
+    if($window.scrollTop() > offset) {
+     $top_link.fadeIn();
+    } else {
+     $top_link.fadeOut();
+    }
+   }).scroll();
+
+   $('.popin')
+    .popover({trigger: 'manual'})
+    .on({
+     'mouseenter.popover': function () {
+      var $target = $(this);
+      var $container = $target.children().first();
+
+      $target.data('popover-hover', true);
+
+      // popover already displayed
+      if ($target.next('.popover').length) {
+       return;
+      }
+
+      // show the popover
+      $container.popover('show');
+
+      // register mouse events on the popover
+      $target.next('.popover:not(.popover-initialized)')
+       .on({
+        'mouseenter': function () {
+         $target.data('popover-hover', true);
+        },
+        'mouseleave': function () {
+         hidePopover($container);
+        }
+       })
+       .addClass('popover-initialized');
+     },
+     'mouseleave.popover': function () {
+      hidePopover($(this).children().first());
+     }
+    });
+  });
diff --git a/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/js/jquery.min.js b/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/js/jquery.min.js
new file mode 100644
index 0000000000000000000000000000000000000000..b0614034ad3a95e4ae9f53c2b015eeb3e8d68bde
--- /dev/null
+++ b/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/js/jquery.min.js
@@ -0,0 +1,2 @@
+/*! jQuery v3.5.1 | (c) JS Foundation and other contributors | jquery.org/license */
+!function(e,t){"use strict";"object"==typeof module&&"object"==typeof module.exports?module.exports=e.document?t(e,!0):function(e){if(!e.document)throw new Error("jQuery requires a window with a document");return t(e)}:t(e)}("undefined"!=typeof window?window:this,function(C,e){"use strict";var t=[],r=Object.getPrototypeOf,s=t.slice,g=t.flat?function(e){return t.flat.call(e)}:function(e){return t.concat.apply([],e)},u=t.push,i=t.indexOf,n={},o=n.toString,v=n.hasOwnProperty,a=v.toString,l=a.call(Object),y={},m=function(e){return"function"==typeof e&&"number"!=typeof e.nodeType},x=function(e){return null!=e&&e===e.window},E=C.document,c={type:!0,src:!0,nonce:!0,noModule:!0};function b(e,t,n){var r,i,o=(n=n||E).createElement("script");if(o.text=e,t)for(r in c)(i=t[r]||t.getAttribute&&t.getAttribute(r))&&o.setAttribute(r,i);n.head.appendChild(o).parentNode.removeChild(o)}function w(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?n[o.call(e)]||"object":typeof e}var f="3.5.1",S=function(e,t){return new S.fn.init(e,t)};function p(e){var t=!!e&&"length"in e&&e.length,n=w(e);return!m(e)&&!x(e)&&("array"===n||0===t||"number"==typeof t&&0<t&&t-1 in e)}S.fn=S.prototype={jquery:f,constructor:S,length:0,toArray:function(){return s.call(this)},get:function(e){return null==e?s.call(this):e<0?this[e+this.length]:this[e]},pushStack:function(e){var t=S.merge(this.constructor(),e);return t.prevObject=this,t},each:function(e){return S.each(this,e)},map:function(n){return this.pushStack(S.map(this,function(e,t){return n.call(e,t,e)}))},slice:function(){return this.pushStack(s.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},even:function(){return this.pushStack(S.grep(this,function(e,t){return(t+1)%2}))},odd:function(){return this.pushStack(S.grep(this,function(e,t){return t%2}))},eq:function(e){var t=this.length,n=+e+(e<0?t:0);return this.pushStack(0<=n&&n<t?[this[n]]:[])},end:function(){return this.prevObject||this.constructor()},push:u,sort:t.sort,splice:t.splice},S.extend=S.fn.extend=function(){var e,t,n,r,i,o,a=arguments[0]||{},s=1,u=arguments.length,l=!1;for("boolean"==typeof a&&(l=a,a=arguments[s]||{},s++),"object"==typeof a||m(a)||(a={}),s===u&&(a=this,s--);s<u;s++)if(null!=(e=arguments[s]))for(t in e)r=e[t],"__proto__"!==t&&a!==r&&(l&&r&&(S.isPlainObject(r)||(i=Array.isArray(r)))?(n=a[t],o=i&&!Array.isArray(n)?[]:i||S.isPlainObject(n)?n:{},i=!1,a[t]=S.extend(l,o,r)):void 0!==r&&(a[t]=r));return a},S.extend({expando:"jQuery"+(f+Math.random()).replace(/\D/g,""),isReady:!0,error:function(e){throw new Error(e)},noop:function(){},isPlainObject:function(e){var t,n;return!(!e||"[object Object]"!==o.call(e))&&(!(t=r(e))||"function"==typeof(n=v.call(t,"constructor")&&t.constructor)&&a.call(n)===l)},isEmptyObject:function(e){var t;for(t in e)return!1;return!0},globalEval:function(e,t,n){b(e,{nonce:t&&t.nonce},n)},each:function(e,t){var n,r=0;if(p(e)){for(n=e.length;r<n;r++)if(!1===t.call(e[r],r,e[r]))break}else for(r in e)if(!1===t.call(e[r],r,e[r]))break;return e},makeArray:function(e,t){var n=t||[];return null!=e&&(p(Object(e))?S.merge(n,"string"==typeof e?[e]:e):u.call(n,e)),n},inArray:function(e,t,n){return null==t?-1:i.call(t,e,n)},merge:function(e,t){for(var n=+t.length,r=0,i=e.length;r<n;r++)e[i++]=t[r];return e.length=i,e},grep:function(e,t,n){for(var r=[],i=0,o=e.length,a=!n;i<o;i++)!t(e[i],i)!==a&&r.push(e[i]);return r},map:function(e,t,n){var r,i,o=0,a=[];if(p(e))for(r=e.length;o<r;o++)null!=(i=t(e[o],o,n))&&a.push(i);else for(o in e)null!=(i=t(e[o],o,n))&&a.push(i);return g(a)},guid:1,support:y}),"function"==typeof Symbol&&(S.fn[Symbol.iterator]=t[Symbol.iterator]),S.each("Boolean Number String Function Array Date RegExp Object Error Symbol".split(" "),function(e,t){n["[object "+t+"]"]=t.toLowerCase()});var d=function(n){var e,d,b,o,i,h,f,g,w,u,l,T,C,a,E,v,s,c,y,S="sizzle"+1*new Date,p=n.document,k=0,r=0,m=ue(),x=ue(),A=ue(),N=ue(),D=function(e,t){return e===t&&(l=!0),0},j={}.hasOwnProperty,t=[],q=t.pop,L=t.push,H=t.push,O=t.slice,P=function(e,t){for(var n=0,r=e.length;n<r;n++)if(e[n]===t)return n;return-1},R="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",M="[\\x20\\t\\r\\n\\f]",I="(?:\\\\[\\da-fA-F]{1,6}"+M+"?|\\\\[^\\r\\n\\f]|[\\w-]|[^\0-\\x7f])+",W="\\["+M+"*("+I+")(?:"+M+"*([*^$|!~]?=)"+M+"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|("+I+"))|)"+M+"*\\]",F=":("+I+")(?:\\((('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|((?:\\\\.|[^\\\\()[\\]]|"+W+")*)|.*)\\)|)",B=new RegExp(M+"+","g"),$=new RegExp("^"+M+"+|((?:^|[^\\\\])(?:\\\\.)*)"+M+"+$","g"),_=new RegExp("^"+M+"*,"+M+"*"),z=new RegExp("^"+M+"*([>+~]|"+M+")"+M+"*"),U=new RegExp(M+"|>"),X=new RegExp(F),V=new RegExp("^"+I+"$"),G={ID:new RegExp("^#("+I+")"),CLASS:new RegExp("^\\.("+I+")"),TAG:new RegExp("^("+I+"|[*])"),ATTR:new RegExp("^"+W),PSEUDO:new RegExp("^"+F),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+M+"*(even|odd|(([+-]|)(\\d*)n|)"+M+"*(?:([+-]|)"+M+"*(\\d+)|))"+M+"*\\)|)","i"),bool:new RegExp("^(?:"+R+")$","i"),needsContext:new RegExp("^"+M+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+M+"*((?:-\\d)?\\d*)"+M+"*\\)|)(?=[^-]|$)","i")},Y=/HTML$/i,Q=/^(?:input|select|textarea|button)$/i,J=/^h\d$/i,K=/^[^{]+\{\s*\[native \w/,Z=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,ee=/[+~]/,te=new RegExp("\\\\[\\da-fA-F]{1,6}"+M+"?|\\\\([^\\r\\n\\f])","g"),ne=function(e,t){var n="0x"+e.slice(1)-65536;return t||(n<0?String.fromCharCode(n+65536):String.fromCharCode(n>>10|55296,1023&n|56320))},re=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g,ie=function(e,t){return t?"\0"===e?"\ufffd":e.slice(0,-1)+"\\"+e.charCodeAt(e.length-1).toString(16)+" ":"\\"+e},oe=function(){T()},ae=be(function(e){return!0===e.disabled&&"fieldset"===e.nodeName.toLowerCase()},{dir:"parentNode",next:"legend"});try{H.apply(t=O.call(p.childNodes),p.childNodes),t[p.childNodes.length].nodeType}catch(e){H={apply:t.length?function(e,t){L.apply(e,O.call(t))}:function(e,t){var n=e.length,r=0;while(e[n++]=t[r++]);e.length=n-1}}}function se(t,e,n,r){var i,o,a,s,u,l,c,f=e&&e.ownerDocument,p=e?e.nodeType:9;if(n=n||[],"string"!=typeof t||!t||1!==p&&9!==p&&11!==p)return n;if(!r&&(T(e),e=e||C,E)){if(11!==p&&(u=Z.exec(t)))if(i=u[1]){if(9===p){if(!(a=e.getElementById(i)))return n;if(a.id===i)return n.push(a),n}else if(f&&(a=f.getElementById(i))&&y(e,a)&&a.id===i)return n.push(a),n}else{if(u[2])return H.apply(n,e.getElementsByTagName(t)),n;if((i=u[3])&&d.getElementsByClassName&&e.getElementsByClassName)return H.apply(n,e.getElementsByClassName(i)),n}if(d.qsa&&!N[t+" "]&&(!v||!v.test(t))&&(1!==p||"object"!==e.nodeName.toLowerCase())){if(c=t,f=e,1===p&&(U.test(t)||z.test(t))){(f=ee.test(t)&&ye(e.parentNode)||e)===e&&d.scope||((s=e.getAttribute("id"))?s=s.replace(re,ie):e.setAttribute("id",s=S)),o=(l=h(t)).length;while(o--)l[o]=(s?"#"+s:":scope")+" "+xe(l[o]);c=l.join(",")}try{return H.apply(n,f.querySelectorAll(c)),n}catch(e){N(t,!0)}finally{s===S&&e.removeAttribute("id")}}}return g(t.replace($,"$1"),e,n,r)}function ue(){var r=[];return function e(t,n){return r.push(t+" ")>b.cacheLength&&delete e[r.shift()],e[t+" "]=n}}function le(e){return e[S]=!0,e}function ce(e){var t=C.createElement("fieldset");try{return!!e(t)}catch(e){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function fe(e,t){var n=e.split("|"),r=n.length;while(r--)b.attrHandle[n[r]]=t}function pe(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&e.sourceIndex-t.sourceIndex;if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function de(t){return function(e){return"input"===e.nodeName.toLowerCase()&&e.type===t}}function he(n){return function(e){var t=e.nodeName.toLowerCase();return("input"===t||"button"===t)&&e.type===n}}function ge(t){return function(e){return"form"in e?e.parentNode&&!1===e.disabled?"label"in e?"label"in e.parentNode?e.parentNode.disabled===t:e.disabled===t:e.isDisabled===t||e.isDisabled!==!t&&ae(e)===t:e.disabled===t:"label"in e&&e.disabled===t}}function ve(a){return le(function(o){return o=+o,le(function(e,t){var n,r=a([],e.length,o),i=r.length;while(i--)e[n=r[i]]&&(e[n]=!(t[n]=e[n]))})})}function ye(e){return e&&"undefined"!=typeof e.getElementsByTagName&&e}for(e in d=se.support={},i=se.isXML=function(e){var t=e.namespaceURI,n=(e.ownerDocument||e).documentElement;return!Y.test(t||n&&n.nodeName||"HTML")},T=se.setDocument=function(e){var t,n,r=e?e.ownerDocument||e:p;return r!=C&&9===r.nodeType&&r.documentElement&&(a=(C=r).documentElement,E=!i(C),p!=C&&(n=C.defaultView)&&n.top!==n&&(n.addEventListener?n.addEventListener("unload",oe,!1):n.attachEvent&&n.attachEvent("onunload",oe)),d.scope=ce(function(e){return a.appendChild(e).appendChild(C.createElement("div")),"undefined"!=typeof e.querySelectorAll&&!e.querySelectorAll(":scope fieldset div").length}),d.attributes=ce(function(e){return e.className="i",!e.getAttribute("className")}),d.getElementsByTagName=ce(function(e){return e.appendChild(C.createComment("")),!e.getElementsByTagName("*").length}),d.getElementsByClassName=K.test(C.getElementsByClassName),d.getById=ce(function(e){return a.appendChild(e).id=S,!C.getElementsByName||!C.getElementsByName(S).length}),d.getById?(b.filter.ID=function(e){var t=e.replace(te,ne);return function(e){return e.getAttribute("id")===t}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n=t.getElementById(e);return n?[n]:[]}}):(b.filter.ID=function(e){var n=e.replace(te,ne);return function(e){var t="undefined"!=typeof e.getAttributeNode&&e.getAttributeNode("id");return t&&t.value===n}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n,r,i,o=t.getElementById(e);if(o){if((n=o.getAttributeNode("id"))&&n.value===e)return[o];i=t.getElementsByName(e),r=0;while(o=i[r++])if((n=o.getAttributeNode("id"))&&n.value===e)return[o]}return[]}}),b.find.TAG=d.getElementsByTagName?function(e,t){return"undefined"!=typeof t.getElementsByTagName?t.getElementsByTagName(e):d.qsa?t.querySelectorAll(e):void 0}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},b.find.CLASS=d.getElementsByClassName&&function(e,t){if("undefined"!=typeof t.getElementsByClassName&&E)return t.getElementsByClassName(e)},s=[],v=[],(d.qsa=K.test(C.querySelectorAll))&&(ce(function(e){var t;a.appendChild(e).innerHTML="<a id='"+S+"'></a><select id='"+S+"-\r\\' msallowcapture=''><option selected=''></option></select>",e.querySelectorAll("[msallowcapture^='']").length&&v.push("[*^$]="+M+"*(?:''|\"\")"),e.querySelectorAll("[selected]").length||v.push("\\["+M+"*(?:value|"+R+")"),e.querySelectorAll("[id~="+S+"-]").length||v.push("~="),(t=C.createElement("input")).setAttribute("name",""),e.appendChild(t),e.querySelectorAll("[name='']").length||v.push("\\["+M+"*name"+M+"*="+M+"*(?:''|\"\")"),e.querySelectorAll(":checked").length||v.push(":checked"),e.querySelectorAll("a#"+S+"+*").length||v.push(".#.+[+~]"),e.querySelectorAll("\\\f"),v.push("[\\r\\n\\f]")}),ce(function(e){e.innerHTML="<a href='' disabled='disabled'></a><select disabled='disabled'><option/></select>";var t=C.createElement("input");t.setAttribute("type","hidden"),e.appendChild(t).setAttribute("name","D"),e.querySelectorAll("[name=d]").length&&v.push("name"+M+"*[*^$|!~]?="),2!==e.querySelectorAll(":enabled").length&&v.push(":enabled",":disabled"),a.appendChild(e).disabled=!0,2!==e.querySelectorAll(":disabled").length&&v.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),v.push(",.*:")})),(d.matchesSelector=K.test(c=a.matches||a.webkitMatchesSelector||a.mozMatchesSelector||a.oMatchesSelector||a.msMatchesSelector))&&ce(function(e){d.disconnectedMatch=c.call(e,"*"),c.call(e,"[s!='']:x"),s.push("!=",F)}),v=v.length&&new RegExp(v.join("|")),s=s.length&&new RegExp(s.join("|")),t=K.test(a.compareDocumentPosition),y=t||K.test(a.contains)?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},D=t?function(e,t){if(e===t)return l=!0,0;var n=!e.compareDocumentPosition-!t.compareDocumentPosition;return n||(1&(n=(e.ownerDocument||e)==(t.ownerDocument||t)?e.compareDocumentPosition(t):1)||!d.sortDetached&&t.compareDocumentPosition(e)===n?e==C||e.ownerDocument==p&&y(p,e)?-1:t==C||t.ownerDocument==p&&y(p,t)?1:u?P(u,e)-P(u,t):0:4&n?-1:1)}:function(e,t){if(e===t)return l=!0,0;var n,r=0,i=e.parentNode,o=t.parentNode,a=[e],s=[t];if(!i||!o)return e==C?-1:t==C?1:i?-1:o?1:u?P(u,e)-P(u,t):0;if(i===o)return pe(e,t);n=e;while(n=n.parentNode)a.unshift(n);n=t;while(n=n.parentNode)s.unshift(n);while(a[r]===s[r])r++;return r?pe(a[r],s[r]):a[r]==p?-1:s[r]==p?1:0}),C},se.matches=function(e,t){return se(e,null,null,t)},se.matchesSelector=function(e,t){if(T(e),d.matchesSelector&&E&&!N[t+" "]&&(!s||!s.test(t))&&(!v||!v.test(t)))try{var n=c.call(e,t);if(n||d.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(e){N(t,!0)}return 0<se(t,C,null,[e]).length},se.contains=function(e,t){return(e.ownerDocument||e)!=C&&T(e),y(e,t)},se.attr=function(e,t){(e.ownerDocument||e)!=C&&T(e);var n=b.attrHandle[t.toLowerCase()],r=n&&j.call(b.attrHandle,t.toLowerCase())?n(e,t,!E):void 0;return void 0!==r?r:d.attributes||!E?e.getAttribute(t):(r=e.getAttributeNode(t))&&r.specified?r.value:null},se.escape=function(e){return(e+"").replace(re,ie)},se.error=function(e){throw new Error("Syntax error, unrecognized expression: "+e)},se.uniqueSort=function(e){var t,n=[],r=0,i=0;if(l=!d.detectDuplicates,u=!d.sortStable&&e.slice(0),e.sort(D),l){while(t=e[i++])t===e[i]&&(r=n.push(i));while(r--)e.splice(n[r],1)}return u=null,e},o=se.getText=function(e){var t,n="",r=0,i=e.nodeType;if(i){if(1===i||9===i||11===i){if("string"==typeof e.textContent)return e.textContent;for(e=e.firstChild;e;e=e.nextSibling)n+=o(e)}else if(3===i||4===i)return e.nodeValue}else while(t=e[r++])n+=o(t);return n},(b=se.selectors={cacheLength:50,createPseudo:le,match:G,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(te,ne),e[3]=(e[3]||e[4]||e[5]||"").replace(te,ne),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||se.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&se.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return G.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||"":n&&X.test(n)&&(t=h(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(te,ne).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=m[e+" "];return t||(t=new RegExp("(^|"+M+")"+e+"("+M+"|$)"))&&m(e,function(e){return t.test("string"==typeof e.className&&e.className||"undefined"!=typeof e.getAttribute&&e.getAttribute("class")||"")})},ATTR:function(n,r,i){return function(e){var t=se.attr(e,n);return null==t?"!="===r:!r||(t+="","="===r?t===i:"!="===r?t!==i:"^="===r?i&&0===t.indexOf(i):"*="===r?i&&-1<t.indexOf(i):"$="===r?i&&t.slice(-i.length)===i:"~="===r?-1<(" "+t.replace(B," ")+" ").indexOf(i):"|="===r&&(t===i||t.slice(0,i.length+1)===i+"-"))}},CHILD:function(h,e,t,g,v){var y="nth"!==h.slice(0,3),m="last"!==h.slice(-4),x="of-type"===e;return 1===g&&0===v?function(e){return!!e.parentNode}:function(e,t,n){var r,i,o,a,s,u,l=y!==m?"nextSibling":"previousSibling",c=e.parentNode,f=x&&e.nodeName.toLowerCase(),p=!n&&!x,d=!1;if(c){if(y){while(l){a=e;while(a=a[l])if(x?a.nodeName.toLowerCase()===f:1===a.nodeType)return!1;u=l="only"===h&&!u&&"nextSibling"}return!0}if(u=[m?c.firstChild:c.lastChild],m&&p){d=(s=(r=(i=(o=(a=c)[S]||(a[S]={}))[a.uniqueID]||(o[a.uniqueID]={}))[h]||[])[0]===k&&r[1])&&r[2],a=s&&c.childNodes[s];while(a=++s&&a&&a[l]||(d=s=0)||u.pop())if(1===a.nodeType&&++d&&a===e){i[h]=[k,s,d];break}}else if(p&&(d=s=(r=(i=(o=(a=e)[S]||(a[S]={}))[a.uniqueID]||(o[a.uniqueID]={}))[h]||[])[0]===k&&r[1]),!1===d)while(a=++s&&a&&a[l]||(d=s=0)||u.pop())if((x?a.nodeName.toLowerCase()===f:1===a.nodeType)&&++d&&(p&&((i=(o=a[S]||(a[S]={}))[a.uniqueID]||(o[a.uniqueID]={}))[h]=[k,d]),a===e))break;return(d-=v)===g||d%g==0&&0<=d/g}}},PSEUDO:function(e,o){var t,a=b.pseudos[e]||b.setFilters[e.toLowerCase()]||se.error("unsupported pseudo: "+e);return a[S]?a(o):1<a.length?(t=[e,e,"",o],b.setFilters.hasOwnProperty(e.toLowerCase())?le(function(e,t){var n,r=a(e,o),i=r.length;while(i--)e[n=P(e,r[i])]=!(t[n]=r[i])}):function(e){return a(e,0,t)}):a}},pseudos:{not:le(function(e){var r=[],i=[],s=f(e.replace($,"$1"));return s[S]?le(function(e,t,n,r){var i,o=s(e,null,r,[]),a=e.length;while(a--)(i=o[a])&&(e[a]=!(t[a]=i))}):function(e,t,n){return r[0]=e,s(r,null,n,i),r[0]=null,!i.pop()}}),has:le(function(t){return function(e){return 0<se(t,e).length}}),contains:le(function(t){return t=t.replace(te,ne),function(e){return-1<(e.textContent||o(e)).indexOf(t)}}),lang:le(function(n){return V.test(n||"")||se.error("unsupported lang: "+n),n=n.replace(te,ne).toLowerCase(),function(e){var t;do{if(t=E?e.lang:e.getAttribute("xml:lang")||e.getAttribute("lang"))return(t=t.toLowerCase())===n||0===t.indexOf(n+"-")}while((e=e.parentNode)&&1===e.nodeType);return!1}}),target:function(e){var t=n.location&&n.location.hash;return t&&t.slice(1)===e.id},root:function(e){return e===a},focus:function(e){return e===C.activeElement&&(!C.hasFocus||C.hasFocus())&&!!(e.type||e.href||~e.tabIndex)},enabled:ge(!1),disabled:ge(!0),checked:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&!!e.checked||"option"===t&&!!e.selected},selected:function(e){return e.parentNode&&e.parentNode.selectedIndex,!0===e.selected},empty:function(e){for(e=e.firstChild;e;e=e.nextSibling)if(e.nodeType<6)return!1;return!0},parent:function(e){return!b.pseudos.empty(e)},header:function(e){return J.test(e.nodeName)},input:function(e){return Q.test(e.nodeName)},button:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&"button"===e.type||"button"===t},text:function(e){var t;return"input"===e.nodeName.toLowerCase()&&"text"===e.type&&(null==(t=e.getAttribute("type"))||"text"===t.toLowerCase())},first:ve(function(){return[0]}),last:ve(function(e,t){return[t-1]}),eq:ve(function(e,t,n){return[n<0?n+t:n]}),even:ve(function(e,t){for(var n=0;n<t;n+=2)e.push(n);return e}),odd:ve(function(e,t){for(var n=1;n<t;n+=2)e.push(n);return e}),lt:ve(function(e,t,n){for(var r=n<0?n+t:t<n?t:n;0<=--r;)e.push(r);return e}),gt:ve(function(e,t,n){for(var r=n<0?n+t:n;++r<t;)e.push(r);return e})}}).pseudos.nth=b.pseudos.eq,{radio:!0,checkbox:!0,file:!0,password:!0,image:!0})b.pseudos[e]=de(e);for(e in{submit:!0,reset:!0})b.pseudos[e]=he(e);function me(){}function xe(e){for(var t=0,n=e.length,r="";t<n;t++)r+=e[t].value;return r}function be(s,e,t){var u=e.dir,l=e.next,c=l||u,f=t&&"parentNode"===c,p=r++;return e.first?function(e,t,n){while(e=e[u])if(1===e.nodeType||f)return s(e,t,n);return!1}:function(e,t,n){var r,i,o,a=[k,p];if(n){while(e=e[u])if((1===e.nodeType||f)&&s(e,t,n))return!0}else while(e=e[u])if(1===e.nodeType||f)if(i=(o=e[S]||(e[S]={}))[e.uniqueID]||(o[e.uniqueID]={}),l&&l===e.nodeName.toLowerCase())e=e[u]||e;else{if((r=i[c])&&r[0]===k&&r[1]===p)return a[2]=r[2];if((i[c]=a)[2]=s(e,t,n))return!0}return!1}}function we(i){return 1<i.length?function(e,t,n){var r=i.length;while(r--)if(!i[r](e,t,n))return!1;return!0}:i[0]}function Te(e,t,n,r,i){for(var o,a=[],s=0,u=e.length,l=null!=t;s<u;s++)(o=e[s])&&(n&&!n(o,r,i)||(a.push(o),l&&t.push(s)));return a}function Ce(d,h,g,v,y,e){return v&&!v[S]&&(v=Ce(v)),y&&!y[S]&&(y=Ce(y,e)),le(function(e,t,n,r){var i,o,a,s=[],u=[],l=t.length,c=e||function(e,t,n){for(var r=0,i=t.length;r<i;r++)se(e,t[r],n);return n}(h||"*",n.nodeType?[n]:n,[]),f=!d||!e&&h?c:Te(c,s,d,n,r),p=g?y||(e?d:l||v)?[]:t:f;if(g&&g(f,p,n,r),v){i=Te(p,u),v(i,[],n,r),o=i.length;while(o--)(a=i[o])&&(p[u[o]]=!(f[u[o]]=a))}if(e){if(y||d){if(y){i=[],o=p.length;while(o--)(a=p[o])&&i.push(f[o]=a);y(null,p=[],i,r)}o=p.length;while(o--)(a=p[o])&&-1<(i=y?P(e,a):s[o])&&(e[i]=!(t[i]=a))}}else p=Te(p===t?p.splice(l,p.length):p),y?y(null,t,p,r):H.apply(t,p)})}function Ee(e){for(var i,t,n,r=e.length,o=b.relative[e[0].type],a=o||b.relative[" "],s=o?1:0,u=be(function(e){return e===i},a,!0),l=be(function(e){return-1<P(i,e)},a,!0),c=[function(e,t,n){var r=!o&&(n||t!==w)||((i=t).nodeType?u(e,t,n):l(e,t,n));return i=null,r}];s<r;s++)if(t=b.relative[e[s].type])c=[be(we(c),t)];else{if((t=b.filter[e[s].type].apply(null,e[s].matches))[S]){for(n=++s;n<r;n++)if(b.relative[e[n].type])break;return Ce(1<s&&we(c),1<s&&xe(e.slice(0,s-1).concat({value:" "===e[s-2].type?"*":""})).replace($,"$1"),t,s<n&&Ee(e.slice(s,n)),n<r&&Ee(e=e.slice(n)),n<r&&xe(e))}c.push(t)}return we(c)}return me.prototype=b.filters=b.pseudos,b.setFilters=new me,h=se.tokenize=function(e,t){var n,r,i,o,a,s,u,l=x[e+" "];if(l)return t?0:l.slice(0);a=e,s=[],u=b.preFilter;while(a){for(o in n&&!(r=_.exec(a))||(r&&(a=a.slice(r[0].length)||a),s.push(i=[])),n=!1,(r=z.exec(a))&&(n=r.shift(),i.push({value:n,type:r[0].replace($," ")}),a=a.slice(n.length)),b.filter)!(r=G[o].exec(a))||u[o]&&!(r=u[o](r))||(n=r.shift(),i.push({value:n,type:o,matches:r}),a=a.slice(n.length));if(!n)break}return t?a.length:a?se.error(e):x(e,s).slice(0)},f=se.compile=function(e,t){var n,v,y,m,x,r,i=[],o=[],a=A[e+" "];if(!a){t||(t=h(e)),n=t.length;while(n--)(a=Ee(t[n]))[S]?i.push(a):o.push(a);(a=A(e,(v=o,m=0<(y=i).length,x=0<v.length,r=function(e,t,n,r,i){var o,a,s,u=0,l="0",c=e&&[],f=[],p=w,d=e||x&&b.find.TAG("*",i),h=k+=null==p?1:Math.random()||.1,g=d.length;for(i&&(w=t==C||t||i);l!==g&&null!=(o=d[l]);l++){if(x&&o){a=0,t||o.ownerDocument==C||(T(o),n=!E);while(s=v[a++])if(s(o,t||C,n)){r.push(o);break}i&&(k=h)}m&&((o=!s&&o)&&u--,e&&c.push(o))}if(u+=l,m&&l!==u){a=0;while(s=y[a++])s(c,f,t,n);if(e){if(0<u)while(l--)c[l]||f[l]||(f[l]=q.call(r));f=Te(f)}H.apply(r,f),i&&!e&&0<f.length&&1<u+y.length&&se.uniqueSort(r)}return i&&(k=h,w=p),c},m?le(r):r))).selector=e}return a},g=se.select=function(e,t,n,r){var i,o,a,s,u,l="function"==typeof e&&e,c=!r&&h(e=l.selector||e);if(n=n||[],1===c.length){if(2<(o=c[0]=c[0].slice(0)).length&&"ID"===(a=o[0]).type&&9===t.nodeType&&E&&b.relative[o[1].type]){if(!(t=(b.find.ID(a.matches[0].replace(te,ne),t)||[])[0]))return n;l&&(t=t.parentNode),e=e.slice(o.shift().value.length)}i=G.needsContext.test(e)?0:o.length;while(i--){if(a=o[i],b.relative[s=a.type])break;if((u=b.find[s])&&(r=u(a.matches[0].replace(te,ne),ee.test(o[0].type)&&ye(t.parentNode)||t))){if(o.splice(i,1),!(e=r.length&&xe(o)))return H.apply(n,r),n;break}}}return(l||f(e,c))(r,t,!E,n,!t||ee.test(e)&&ye(t.parentNode)||t),n},d.sortStable=S.split("").sort(D).join("")===S,d.detectDuplicates=!!l,T(),d.sortDetached=ce(function(e){return 1&e.compareDocumentPosition(C.createElement("fieldset"))}),ce(function(e){return e.innerHTML="<a href='#'></a>","#"===e.firstChild.getAttribute("href")})||fe("type|href|height|width",function(e,t,n){if(!n)return e.getAttribute(t,"type"===t.toLowerCase()?1:2)}),d.attributes&&ce(function(e){return e.innerHTML="<input/>",e.firstChild.setAttribute("value",""),""===e.firstChild.getAttribute("value")})||fe("value",function(e,t,n){if(!n&&"input"===e.nodeName.toLowerCase())return e.defaultValue}),ce(function(e){return null==e.getAttribute("disabled")})||fe(R,function(e,t,n){var r;if(!n)return!0===e[t]?t.toLowerCase():(r=e.getAttributeNode(t))&&r.specified?r.value:null}),se}(C);S.find=d,S.expr=d.selectors,S.expr[":"]=S.expr.pseudos,S.uniqueSort=S.unique=d.uniqueSort,S.text=d.getText,S.isXMLDoc=d.isXML,S.contains=d.contains,S.escapeSelector=d.escape;var h=function(e,t,n){var r=[],i=void 0!==n;while((e=e[t])&&9!==e.nodeType)if(1===e.nodeType){if(i&&S(e).is(n))break;r.push(e)}return r},T=function(e,t){for(var n=[];e;e=e.nextSibling)1===e.nodeType&&e!==t&&n.push(e);return n},k=S.expr.match.needsContext;function A(e,t){return e.nodeName&&e.nodeName.toLowerCase()===t.toLowerCase()}var N=/^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i;function D(e,n,r){return m(n)?S.grep(e,function(e,t){return!!n.call(e,t,e)!==r}):n.nodeType?S.grep(e,function(e){return e===n!==r}):"string"!=typeof n?S.grep(e,function(e){return-1<i.call(n,e)!==r}):S.filter(n,e,r)}S.filter=function(e,t,n){var r=t[0];return n&&(e=":not("+e+")"),1===t.length&&1===r.nodeType?S.find.matchesSelector(r,e)?[r]:[]:S.find.matches(e,S.grep(t,function(e){return 1===e.nodeType}))},S.fn.extend({find:function(e){var t,n,r=this.length,i=this;if("string"!=typeof e)return this.pushStack(S(e).filter(function(){for(t=0;t<r;t++)if(S.contains(i[t],this))return!0}));for(n=this.pushStack([]),t=0;t<r;t++)S.find(e,i[t],n);return 1<r?S.uniqueSort(n):n},filter:function(e){return this.pushStack(D(this,e||[],!1))},not:function(e){return this.pushStack(D(this,e||[],!0))},is:function(e){return!!D(this,"string"==typeof e&&k.test(e)?S(e):e||[],!1).length}});var j,q=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]+))$/;(S.fn.init=function(e,t,n){var r,i;if(!e)return this;if(n=n||j,"string"==typeof e){if(!(r="<"===e[0]&&">"===e[e.length-1]&&3<=e.length?[null,e,null]:q.exec(e))||!r[1]&&t)return!t||t.jquery?(t||n).find(e):this.constructor(t).find(e);if(r[1]){if(t=t instanceof S?t[0]:t,S.merge(this,S.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:E,!0)),N.test(r[1])&&S.isPlainObject(t))for(r in t)m(this[r])?this[r](t[r]):this.attr(r,t[r]);return this}return(i=E.getElementById(r[2]))&&(this[0]=i,this.length=1),this}return e.nodeType?(this[0]=e,this.length=1,this):m(e)?void 0!==n.ready?n.ready(e):e(S):S.makeArray(e,this)}).prototype=S.fn,j=S(E);var L=/^(?:parents|prev(?:Until|All))/,H={children:!0,contents:!0,next:!0,prev:!0};function O(e,t){while((e=e[t])&&1!==e.nodeType);return e}S.fn.extend({has:function(e){var t=S(e,this),n=t.length;return this.filter(function(){for(var e=0;e<n;e++)if(S.contains(this,t[e]))return!0})},closest:function(e,t){var n,r=0,i=this.length,o=[],a="string"!=typeof e&&S(e);if(!k.test(e))for(;r<i;r++)for(n=this[r];n&&n!==t;n=n.parentNode)if(n.nodeType<11&&(a?-1<a.index(n):1===n.nodeType&&S.find.matchesSelector(n,e))){o.push(n);break}return this.pushStack(1<o.length?S.uniqueSort(o):o)},index:function(e){return e?"string"==typeof e?i.call(S(e),this[0]):i.call(this,e.jquery?e[0]:e):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(e,t){return this.pushStack(S.uniqueSort(S.merge(this.get(),S(e,t))))},addBack:function(e){return this.add(null==e?this.prevObject:this.prevObject.filter(e))}}),S.each({parent:function(e){var t=e.parentNode;return t&&11!==t.nodeType?t:null},parents:function(e){return h(e,"parentNode")},parentsUntil:function(e,t,n){return h(e,"parentNode",n)},next:function(e){return O(e,"nextSibling")},prev:function(e){return O(e,"previousSibling")},nextAll:function(e){return h(e,"nextSibling")},prevAll:function(e){return h(e,"previousSibling")},nextUntil:function(e,t,n){return h(e,"nextSibling",n)},prevUntil:function(e,t,n){return h(e,"previousSibling",n)},siblings:function(e){return T((e.parentNode||{}).firstChild,e)},children:function(e){return T(e.firstChild)},contents:function(e){return null!=e.contentDocument&&r(e.contentDocument)?e.contentDocument:(A(e,"template")&&(e=e.content||e),S.merge([],e.childNodes))}},function(r,i){S.fn[r]=function(e,t){var n=S.map(this,i,e);return"Until"!==r.slice(-5)&&(t=e),t&&"string"==typeof t&&(n=S.filter(t,n)),1<this.length&&(H[r]||S.uniqueSort(n),L.test(r)&&n.reverse()),this.pushStack(n)}});var P=/[^\x20\t\r\n\f]+/g;function R(e){return e}function M(e){throw e}function I(e,t,n,r){var i;try{e&&m(i=e.promise)?i.call(e).done(t).fail(n):e&&m(i=e.then)?i.call(e,t,n):t.apply(void 0,[e].slice(r))}catch(e){n.apply(void 0,[e])}}S.Callbacks=function(r){var e,n;r="string"==typeof r?(e=r,n={},S.each(e.match(P)||[],function(e,t){n[t]=!0}),n):S.extend({},r);var i,t,o,a,s=[],u=[],l=-1,c=function(){for(a=a||r.once,o=i=!0;u.length;l=-1){t=u.shift();while(++l<s.length)!1===s[l].apply(t[0],t[1])&&r.stopOnFalse&&(l=s.length,t=!1)}r.memory||(t=!1),i=!1,a&&(s=t?[]:"")},f={add:function(){return s&&(t&&!i&&(l=s.length-1,u.push(t)),function n(e){S.each(e,function(e,t){m(t)?r.unique&&f.has(t)||s.push(t):t&&t.length&&"string"!==w(t)&&n(t)})}(arguments),t&&!i&&c()),this},remove:function(){return S.each(arguments,function(e,t){var n;while(-1<(n=S.inArray(t,s,n)))s.splice(n,1),n<=l&&l--}),this},has:function(e){return e?-1<S.inArray(e,s):0<s.length},empty:function(){return s&&(s=[]),this},disable:function(){return a=u=[],s=t="",this},disabled:function(){return!s},lock:function(){return a=u=[],t||i||(s=t=""),this},locked:function(){return!!a},fireWith:function(e,t){return a||(t=[e,(t=t||[]).slice?t.slice():t],u.push(t),i||c()),this},fire:function(){return f.fireWith(this,arguments),this},fired:function(){return!!o}};return f},S.extend({Deferred:function(e){var o=[["notify","progress",S.Callbacks("memory"),S.Callbacks("memory"),2],["resolve","done",S.Callbacks("once memory"),S.Callbacks("once memory"),0,"resolved"],["reject","fail",S.Callbacks("once memory"),S.Callbacks("once memory"),1,"rejected"]],i="pending",a={state:function(){return i},always:function(){return s.done(arguments).fail(arguments),this},"catch":function(e){return a.then(null,e)},pipe:function(){var i=arguments;return S.Deferred(function(r){S.each(o,function(e,t){var n=m(i[t[4]])&&i[t[4]];s[t[1]](function(){var e=n&&n.apply(this,arguments);e&&m(e.promise)?e.promise().progress(r.notify).done(r.resolve).fail(r.reject):r[t[0]+"With"](this,n?[e]:arguments)})}),i=null}).promise()},then:function(t,n,r){var u=0;function l(i,o,a,s){return function(){var n=this,r=arguments,e=function(){var e,t;if(!(i<u)){if((e=a.apply(n,r))===o.promise())throw new TypeError("Thenable self-resolution");t=e&&("object"==typeof e||"function"==typeof e)&&e.then,m(t)?s?t.call(e,l(u,o,R,s),l(u,o,M,s)):(u++,t.call(e,l(u,o,R,s),l(u,o,M,s),l(u,o,R,o.notifyWith))):(a!==R&&(n=void 0,r=[e]),(s||o.resolveWith)(n,r))}},t=s?e:function(){try{e()}catch(e){S.Deferred.exceptionHook&&S.Deferred.exceptionHook(e,t.stackTrace),u<=i+1&&(a!==M&&(n=void 0,r=[e]),o.rejectWith(n,r))}};i?t():(S.Deferred.getStackHook&&(t.stackTrace=S.Deferred.getStackHook()),C.setTimeout(t))}}return S.Deferred(function(e){o[0][3].add(l(0,e,m(r)?r:R,e.notifyWith)),o[1][3].add(l(0,e,m(t)?t:R)),o[2][3].add(l(0,e,m(n)?n:M))}).promise()},promise:function(e){return null!=e?S.extend(e,a):a}},s={};return S.each(o,function(e,t){var n=t[2],r=t[5];a[t[1]]=n.add,r&&n.add(function(){i=r},o[3-e][2].disable,o[3-e][3].disable,o[0][2].lock,o[0][3].lock),n.add(t[3].fire),s[t[0]]=function(){return s[t[0]+"With"](this===s?void 0:this,arguments),this},s[t[0]+"With"]=n.fireWith}),a.promise(s),e&&e.call(s,s),s},when:function(e){var n=arguments.length,t=n,r=Array(t),i=s.call(arguments),o=S.Deferred(),a=function(t){return function(e){r[t]=this,i[t]=1<arguments.length?s.call(arguments):e,--n||o.resolveWith(r,i)}};if(n<=1&&(I(e,o.done(a(t)).resolve,o.reject,!n),"pending"===o.state()||m(i[t]&&i[t].then)))return o.then();while(t--)I(i[t],a(t),o.reject);return o.promise()}});var W=/^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/;S.Deferred.exceptionHook=function(e,t){C.console&&C.console.warn&&e&&W.test(e.name)&&C.console.warn("jQuery.Deferred exception: "+e.message,e.stack,t)},S.readyException=function(e){C.setTimeout(function(){throw e})};var F=S.Deferred();function B(){E.removeEventListener("DOMContentLoaded",B),C.removeEventListener("load",B),S.ready()}S.fn.ready=function(e){return F.then(e)["catch"](function(e){S.readyException(e)}),this},S.extend({isReady:!1,readyWait:1,ready:function(e){(!0===e?--S.readyWait:S.isReady)||(S.isReady=!0)!==e&&0<--S.readyWait||F.resolveWith(E,[S])}}),S.ready.then=F.then,"complete"===E.readyState||"loading"!==E.readyState&&!E.documentElement.doScroll?C.setTimeout(S.ready):(E.addEventListener("DOMContentLoaded",B),C.addEventListener("load",B));var $=function(e,t,n,r,i,o,a){var s=0,u=e.length,l=null==n;if("object"===w(n))for(s in i=!0,n)$(e,t,s,n[s],!0,o,a);else if(void 0!==r&&(i=!0,m(r)||(a=!0),l&&(a?(t.call(e,r),t=null):(l=t,t=function(e,t,n){return l.call(S(e),n)})),t))for(;s<u;s++)t(e[s],n,a?r:r.call(e[s],s,t(e[s],n)));return i?e:l?t.call(e):u?t(e[0],n):o},_=/^-ms-/,z=/-([a-z])/g;function U(e,t){return t.toUpperCase()}function X(e){return e.replace(_,"ms-").replace(z,U)}var V=function(e){return 1===e.nodeType||9===e.nodeType||!+e.nodeType};function G(){this.expando=S.expando+G.uid++}G.uid=1,G.prototype={cache:function(e){var t=e[this.expando];return t||(t={},V(e)&&(e.nodeType?e[this.expando]=t:Object.defineProperty(e,this.expando,{value:t,configurable:!0}))),t},set:function(e,t,n){var r,i=this.cache(e);if("string"==typeof t)i[X(t)]=n;else for(r in t)i[X(r)]=t[r];return i},get:function(e,t){return void 0===t?this.cache(e):e[this.expando]&&e[this.expando][X(t)]},access:function(e,t,n){return void 0===t||t&&"string"==typeof t&&void 0===n?this.get(e,t):(this.set(e,t,n),void 0!==n?n:t)},remove:function(e,t){var n,r=e[this.expando];if(void 0!==r){if(void 0!==t){n=(t=Array.isArray(t)?t.map(X):(t=X(t))in r?[t]:t.match(P)||[]).length;while(n--)delete r[t[n]]}(void 0===t||S.isEmptyObject(r))&&(e.nodeType?e[this.expando]=void 0:delete e[this.expando])}},hasData:function(e){var t=e[this.expando];return void 0!==t&&!S.isEmptyObject(t)}};var Y=new G,Q=new G,J=/^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,K=/[A-Z]/g;function Z(e,t,n){var r,i;if(void 0===n&&1===e.nodeType)if(r="data-"+t.replace(K,"-$&").toLowerCase(),"string"==typeof(n=e.getAttribute(r))){try{n="true"===(i=n)||"false"!==i&&("null"===i?null:i===+i+""?+i:J.test(i)?JSON.parse(i):i)}catch(e){}Q.set(e,t,n)}else n=void 0;return n}S.extend({hasData:function(e){return Q.hasData(e)||Y.hasData(e)},data:function(e,t,n){return Q.access(e,t,n)},removeData:function(e,t){Q.remove(e,t)},_data:function(e,t,n){return Y.access(e,t,n)},_removeData:function(e,t){Y.remove(e,t)}}),S.fn.extend({data:function(n,e){var t,r,i,o=this[0],a=o&&o.attributes;if(void 0===n){if(this.length&&(i=Q.get(o),1===o.nodeType&&!Y.get(o,"hasDataAttrs"))){t=a.length;while(t--)a[t]&&0===(r=a[t].name).indexOf("data-")&&(r=X(r.slice(5)),Z(o,r,i[r]));Y.set(o,"hasDataAttrs",!0)}return i}return"object"==typeof n?this.each(function(){Q.set(this,n)}):$(this,function(e){var t;if(o&&void 0===e)return void 0!==(t=Q.get(o,n))?t:void 0!==(t=Z(o,n))?t:void 0;this.each(function(){Q.set(this,n,e)})},null,e,1<arguments.length,null,!0)},removeData:function(e){return this.each(function(){Q.remove(this,e)})}}),S.extend({queue:function(e,t,n){var r;if(e)return t=(t||"fx")+"queue",r=Y.get(e,t),n&&(!r||Array.isArray(n)?r=Y.access(e,t,S.makeArray(n)):r.push(n)),r||[]},dequeue:function(e,t){t=t||"fx";var n=S.queue(e,t),r=n.length,i=n.shift(),o=S._queueHooks(e,t);"inprogress"===i&&(i=n.shift(),r--),i&&("fx"===t&&n.unshift("inprogress"),delete o.stop,i.call(e,function(){S.dequeue(e,t)},o)),!r&&o&&o.empty.fire()},_queueHooks:function(e,t){var n=t+"queueHooks";return Y.get(e,n)||Y.access(e,n,{empty:S.Callbacks("once memory").add(function(){Y.remove(e,[t+"queue",n])})})}}),S.fn.extend({queue:function(t,n){var e=2;return"string"!=typeof t&&(n=t,t="fx",e--),arguments.length<e?S.queue(this[0],t):void 0===n?this:this.each(function(){var e=S.queue(this,t,n);S._queueHooks(this,t),"fx"===t&&"inprogress"!==e[0]&&S.dequeue(this,t)})},dequeue:function(e){return this.each(function(){S.dequeue(this,e)})},clearQueue:function(e){return this.queue(e||"fx",[])},promise:function(e,t){var n,r=1,i=S.Deferred(),o=this,a=this.length,s=function(){--r||i.resolveWith(o,[o])};"string"!=typeof e&&(t=e,e=void 0),e=e||"fx";while(a--)(n=Y.get(o[a],e+"queueHooks"))&&n.empty&&(r++,n.empty.add(s));return s(),i.promise(t)}});var ee=/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source,te=new RegExp("^(?:([+-])=|)("+ee+")([a-z%]*)$","i"),ne=["Top","Right","Bottom","Left"],re=E.documentElement,ie=function(e){return S.contains(e.ownerDocument,e)},oe={composed:!0};re.getRootNode&&(ie=function(e){return S.contains(e.ownerDocument,e)||e.getRootNode(oe)===e.ownerDocument});var ae=function(e,t){return"none"===(e=t||e).style.display||""===e.style.display&&ie(e)&&"none"===S.css(e,"display")};function se(e,t,n,r){var i,o,a=20,s=r?function(){return r.cur()}:function(){return S.css(e,t,"")},u=s(),l=n&&n[3]||(S.cssNumber[t]?"":"px"),c=e.nodeType&&(S.cssNumber[t]||"px"!==l&&+u)&&te.exec(S.css(e,t));if(c&&c[3]!==l){u/=2,l=l||c[3],c=+u||1;while(a--)S.style(e,t,c+l),(1-o)*(1-(o=s()/u||.5))<=0&&(a=0),c/=o;c*=2,S.style(e,t,c+l),n=n||[]}return n&&(c=+c||+u||0,i=n[1]?c+(n[1]+1)*n[2]:+n[2],r&&(r.unit=l,r.start=c,r.end=i)),i}var ue={};function le(e,t){for(var n,r,i,o,a,s,u,l=[],c=0,f=e.length;c<f;c++)(r=e[c]).style&&(n=r.style.display,t?("none"===n&&(l[c]=Y.get(r,"display")||null,l[c]||(r.style.display="")),""===r.style.display&&ae(r)&&(l[c]=(u=a=o=void 0,a=(i=r).ownerDocument,s=i.nodeName,(u=ue[s])||(o=a.body.appendChild(a.createElement(s)),u=S.css(o,"display"),o.parentNode.removeChild(o),"none"===u&&(u="block"),ue[s]=u)))):"none"!==n&&(l[c]="none",Y.set(r,"display",n)));for(c=0;c<f;c++)null!=l[c]&&(e[c].style.display=l[c]);return e}S.fn.extend({show:function(){return le(this,!0)},hide:function(){return le(this)},toggle:function(e){return"boolean"==typeof e?e?this.show():this.hide():this.each(function(){ae(this)?S(this).show():S(this).hide()})}});var ce,fe,pe=/^(?:checkbox|radio)$/i,de=/<([a-z][^\/\0>\x20\t\r\n\f]*)/i,he=/^$|^module$|\/(?:java|ecma)script/i;ce=E.createDocumentFragment().appendChild(E.createElement("div")),(fe=E.createElement("input")).setAttribute("type","radio"),fe.setAttribute("checked","checked"),fe.setAttribute("name","t"),ce.appendChild(fe),y.checkClone=ce.cloneNode(!0).cloneNode(!0).lastChild.checked,ce.innerHTML="<textarea>x</textarea>",y.noCloneChecked=!!ce.cloneNode(!0).lastChild.defaultValue,ce.innerHTML="<option></option>",y.option=!!ce.lastChild;var ge={thead:[1,"<table>","</table>"],col:[2,"<table><colgroup>","</colgroup></table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],_default:[0,"",""]};function ve(e,t){var n;return n="undefined"!=typeof e.getElementsByTagName?e.getElementsByTagName(t||"*"):"undefined"!=typeof e.querySelectorAll?e.querySelectorAll(t||"*"):[],void 0===t||t&&A(e,t)?S.merge([e],n):n}function ye(e,t){for(var n=0,r=e.length;n<r;n++)Y.set(e[n],"globalEval",!t||Y.get(t[n],"globalEval"))}ge.tbody=ge.tfoot=ge.colgroup=ge.caption=ge.thead,ge.th=ge.td,y.option||(ge.optgroup=ge.option=[1,"<select multiple='multiple'>","</select>"]);var me=/<|&#?\w+;/;function xe(e,t,n,r,i){for(var o,a,s,u,l,c,f=t.createDocumentFragment(),p=[],d=0,h=e.length;d<h;d++)if((o=e[d])||0===o)if("object"===w(o))S.merge(p,o.nodeType?[o]:o);else if(me.test(o)){a=a||f.appendChild(t.createElement("div")),s=(de.exec(o)||["",""])[1].toLowerCase(),u=ge[s]||ge._default,a.innerHTML=u[1]+S.htmlPrefilter(o)+u[2],c=u[0];while(c--)a=a.lastChild;S.merge(p,a.childNodes),(a=f.firstChild).textContent=""}else p.push(t.createTextNode(o));f.textContent="",d=0;while(o=p[d++])if(r&&-1<S.inArray(o,r))i&&i.push(o);else if(l=ie(o),a=ve(f.appendChild(o),"script"),l&&ye(a),n){c=0;while(o=a[c++])he.test(o.type||"")&&n.push(o)}return f}var be=/^key/,we=/^(?:mouse|pointer|contextmenu|drag|drop)|click/,Te=/^([^.]*)(?:\.(.+)|)/;function Ce(){return!0}function Ee(){return!1}function Se(e,t){return e===function(){try{return E.activeElement}catch(e){}}()==("focus"===t)}function ke(e,t,n,r,i,o){var a,s;if("object"==typeof t){for(s in"string"!=typeof n&&(r=r||n,n=void 0),t)ke(e,s,n,r,t[s],o);return e}if(null==r&&null==i?(i=n,r=n=void 0):null==i&&("string"==typeof n?(i=r,r=void 0):(i=r,r=n,n=void 0)),!1===i)i=Ee;else if(!i)return e;return 1===o&&(a=i,(i=function(e){return S().off(e),a.apply(this,arguments)}).guid=a.guid||(a.guid=S.guid++)),e.each(function(){S.event.add(this,t,i,r,n)})}function Ae(e,i,o){o?(Y.set(e,i,!1),S.event.add(e,i,{namespace:!1,handler:function(e){var t,n,r=Y.get(this,i);if(1&e.isTrigger&&this[i]){if(r.length)(S.event.special[i]||{}).delegateType&&e.stopPropagation();else if(r=s.call(arguments),Y.set(this,i,r),t=o(this,i),this[i](),r!==(n=Y.get(this,i))||t?Y.set(this,i,!1):n={},r!==n)return e.stopImmediatePropagation(),e.preventDefault(),n.value}else r.length&&(Y.set(this,i,{value:S.event.trigger(S.extend(r[0],S.Event.prototype),r.slice(1),this)}),e.stopImmediatePropagation())}})):void 0===Y.get(e,i)&&S.event.add(e,i,Ce)}S.event={global:{},add:function(t,e,n,r,i){var o,a,s,u,l,c,f,p,d,h,g,v=Y.get(t);if(V(t)){n.handler&&(n=(o=n).handler,i=o.selector),i&&S.find.matchesSelector(re,i),n.guid||(n.guid=S.guid++),(u=v.events)||(u=v.events=Object.create(null)),(a=v.handle)||(a=v.handle=function(e){return"undefined"!=typeof S&&S.event.triggered!==e.type?S.event.dispatch.apply(t,arguments):void 0}),l=(e=(e||"").match(P)||[""]).length;while(l--)d=g=(s=Te.exec(e[l])||[])[1],h=(s[2]||"").split(".").sort(),d&&(f=S.event.special[d]||{},d=(i?f.delegateType:f.bindType)||d,f=S.event.special[d]||{},c=S.extend({type:d,origType:g,data:r,handler:n,guid:n.guid,selector:i,needsContext:i&&S.expr.match.needsContext.test(i),namespace:h.join(".")},o),(p=u[d])||((p=u[d]=[]).delegateCount=0,f.setup&&!1!==f.setup.call(t,r,h,a)||t.addEventListener&&t.addEventListener(d,a)),f.add&&(f.add.call(t,c),c.handler.guid||(c.handler.guid=n.guid)),i?p.splice(p.delegateCount++,0,c):p.push(c),S.event.global[d]=!0)}},remove:function(e,t,n,r,i){var o,a,s,u,l,c,f,p,d,h,g,v=Y.hasData(e)&&Y.get(e);if(v&&(u=v.events)){l=(t=(t||"").match(P)||[""]).length;while(l--)if(d=g=(s=Te.exec(t[l])||[])[1],h=(s[2]||"").split(".").sort(),d){f=S.event.special[d]||{},p=u[d=(r?f.delegateType:f.bindType)||d]||[],s=s[2]&&new RegExp("(^|\\.)"+h.join("\\.(?:.*\\.|)")+"(\\.|$)"),a=o=p.length;while(o--)c=p[o],!i&&g!==c.origType||n&&n.guid!==c.guid||s&&!s.test(c.namespace)||r&&r!==c.selector&&("**"!==r||!c.selector)||(p.splice(o,1),c.selector&&p.delegateCount--,f.remove&&f.remove.call(e,c));a&&!p.length&&(f.teardown&&!1!==f.teardown.call(e,h,v.handle)||S.removeEvent(e,d,v.handle),delete u[d])}else for(d in u)S.event.remove(e,d+t[l],n,r,!0);S.isEmptyObject(u)&&Y.remove(e,"handle events")}},dispatch:function(e){var t,n,r,i,o,a,s=new Array(arguments.length),u=S.event.fix(e),l=(Y.get(this,"events")||Object.create(null))[u.type]||[],c=S.event.special[u.type]||{};for(s[0]=u,t=1;t<arguments.length;t++)s[t]=arguments[t];if(u.delegateTarget=this,!c.preDispatch||!1!==c.preDispatch.call(this,u)){a=S.event.handlers.call(this,u,l),t=0;while((i=a[t++])&&!u.isPropagationStopped()){u.currentTarget=i.elem,n=0;while((o=i.handlers[n++])&&!u.isImmediatePropagationStopped())u.rnamespace&&!1!==o.namespace&&!u.rnamespace.test(o.namespace)||(u.handleObj=o,u.data=o.data,void 0!==(r=((S.event.special[o.origType]||{}).handle||o.handler).apply(i.elem,s))&&!1===(u.result=r)&&(u.preventDefault(),u.stopPropagation()))}return c.postDispatch&&c.postDispatch.call(this,u),u.result}},handlers:function(e,t){var n,r,i,o,a,s=[],u=t.delegateCount,l=e.target;if(u&&l.nodeType&&!("click"===e.type&&1<=e.button))for(;l!==this;l=l.parentNode||this)if(1===l.nodeType&&("click"!==e.type||!0!==l.disabled)){for(o=[],a={},n=0;n<u;n++)void 0===a[i=(r=t[n]).selector+" "]&&(a[i]=r.needsContext?-1<S(i,this).index(l):S.find(i,this,null,[l]).length),a[i]&&o.push(r);o.length&&s.push({elem:l,handlers:o})}return l=this,u<t.length&&s.push({elem:l,handlers:t.slice(u)}),s},addProp:function(t,e){Object.defineProperty(S.Event.prototype,t,{enumerable:!0,configurable:!0,get:m(e)?function(){if(this.originalEvent)return e(this.originalEvent)}:function(){if(this.originalEvent)return this.originalEvent[t]},set:function(e){Object.defineProperty(this,t,{enumerable:!0,configurable:!0,writable:!0,value:e})}})},fix:function(e){return e[S.expando]?e:new S.Event(e)},special:{load:{noBubble:!0},click:{setup:function(e){var t=this||e;return pe.test(t.type)&&t.click&&A(t,"input")&&Ae(t,"click",Ce),!1},trigger:function(e){var t=this||e;return pe.test(t.type)&&t.click&&A(t,"input")&&Ae(t,"click"),!0},_default:function(e){var t=e.target;return pe.test(t.type)&&t.click&&A(t,"input")&&Y.get(t,"click")||A(t,"a")}},beforeunload:{postDispatch:function(e){void 0!==e.result&&e.originalEvent&&(e.originalEvent.returnValue=e.result)}}}},S.removeEvent=function(e,t,n){e.removeEventListener&&e.removeEventListener(t,n)},S.Event=function(e,t){if(!(this instanceof S.Event))return new S.Event(e,t);e&&e.type?(this.originalEvent=e,this.type=e.type,this.isDefaultPrevented=e.defaultPrevented||void 0===e.defaultPrevented&&!1===e.returnValue?Ce:Ee,this.target=e.target&&3===e.target.nodeType?e.target.parentNode:e.target,this.currentTarget=e.currentTarget,this.relatedTarget=e.relatedTarget):this.type=e,t&&S.extend(this,t),this.timeStamp=e&&e.timeStamp||Date.now(),this[S.expando]=!0},S.Event.prototype={constructor:S.Event,isDefaultPrevented:Ee,isPropagationStopped:Ee,isImmediatePropagationStopped:Ee,isSimulated:!1,preventDefault:function(){var e=this.originalEvent;this.isDefaultPrevented=Ce,e&&!this.isSimulated&&e.preventDefault()},stopPropagation:function(){var e=this.originalEvent;this.isPropagationStopped=Ce,e&&!this.isSimulated&&e.stopPropagation()},stopImmediatePropagation:function(){var e=this.originalEvent;this.isImmediatePropagationStopped=Ce,e&&!this.isSimulated&&e.stopImmediatePropagation(),this.stopPropagation()}},S.each({altKey:!0,bubbles:!0,cancelable:!0,changedTouches:!0,ctrlKey:!0,detail:!0,eventPhase:!0,metaKey:!0,pageX:!0,pageY:!0,shiftKey:!0,view:!0,"char":!0,code:!0,charCode:!0,key:!0,keyCode:!0,button:!0,buttons:!0,clientX:!0,clientY:!0,offsetX:!0,offsetY:!0,pointerId:!0,pointerType:!0,screenX:!0,screenY:!0,targetTouches:!0,toElement:!0,touches:!0,which:function(e){var t=e.button;return null==e.which&&be.test(e.type)?null!=e.charCode?e.charCode:e.keyCode:!e.which&&void 0!==t&&we.test(e.type)?1&t?1:2&t?3:4&t?2:0:e.which}},S.event.addProp),S.each({focus:"focusin",blur:"focusout"},function(e,t){S.event.special[e]={setup:function(){return Ae(this,e,Se),!1},trigger:function(){return Ae(this,e),!0},delegateType:t}}),S.each({mouseenter:"mouseover",mouseleave:"mouseout",pointerenter:"pointerover",pointerleave:"pointerout"},function(e,i){S.event.special[e]={delegateType:i,bindType:i,handle:function(e){var t,n=e.relatedTarget,r=e.handleObj;return n&&(n===this||S.contains(this,n))||(e.type=r.origType,t=r.handler.apply(this,arguments),e.type=i),t}}}),S.fn.extend({on:function(e,t,n,r){return ke(this,e,t,n,r)},one:function(e,t,n,r){return ke(this,e,t,n,r,1)},off:function(e,t,n){var r,i;if(e&&e.preventDefault&&e.handleObj)return r=e.handleObj,S(e.delegateTarget).off(r.namespace?r.origType+"."+r.namespace:r.origType,r.selector,r.handler),this;if("object"==typeof e){for(i in e)this.off(i,t,e[i]);return this}return!1!==t&&"function"!=typeof t||(n=t,t=void 0),!1===n&&(n=Ee),this.each(function(){S.event.remove(this,e,n,t)})}});var Ne=/<script|<style|<link/i,De=/checked\s*(?:[^=]|=\s*.checked.)/i,je=/^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g;function qe(e,t){return A(e,"table")&&A(11!==t.nodeType?t:t.firstChild,"tr")&&S(e).children("tbody")[0]||e}function Le(e){return e.type=(null!==e.getAttribute("type"))+"/"+e.type,e}function He(e){return"true/"===(e.type||"").slice(0,5)?e.type=e.type.slice(5):e.removeAttribute("type"),e}function Oe(e,t){var n,r,i,o,a,s;if(1===t.nodeType){if(Y.hasData(e)&&(s=Y.get(e).events))for(i in Y.remove(t,"handle events"),s)for(n=0,r=s[i].length;n<r;n++)S.event.add(t,i,s[i][n]);Q.hasData(e)&&(o=Q.access(e),a=S.extend({},o),Q.set(t,a))}}function Pe(n,r,i,o){r=g(r);var e,t,a,s,u,l,c=0,f=n.length,p=f-1,d=r[0],h=m(d);if(h||1<f&&"string"==typeof d&&!y.checkClone&&De.test(d))return n.each(function(e){var t=n.eq(e);h&&(r[0]=d.call(this,e,t.html())),Pe(t,r,i,o)});if(f&&(t=(e=xe(r,n[0].ownerDocument,!1,n,o)).firstChild,1===e.childNodes.length&&(e=t),t||o)){for(s=(a=S.map(ve(e,"script"),Le)).length;c<f;c++)u=e,c!==p&&(u=S.clone(u,!0,!0),s&&S.merge(a,ve(u,"script"))),i.call(n[c],u,c);if(s)for(l=a[a.length-1].ownerDocument,S.map(a,He),c=0;c<s;c++)u=a[c],he.test(u.type||"")&&!Y.access(u,"globalEval")&&S.contains(l,u)&&(u.src&&"module"!==(u.type||"").toLowerCase()?S._evalUrl&&!u.noModule&&S._evalUrl(u.src,{nonce:u.nonce||u.getAttribute("nonce")},l):b(u.textContent.replace(je,""),u,l))}return n}function Re(e,t,n){for(var r,i=t?S.filter(t,e):e,o=0;null!=(r=i[o]);o++)n||1!==r.nodeType||S.cleanData(ve(r)),r.parentNode&&(n&&ie(r)&&ye(ve(r,"script")),r.parentNode.removeChild(r));return e}S.extend({htmlPrefilter:function(e){return e},clone:function(e,t,n){var r,i,o,a,s,u,l,c=e.cloneNode(!0),f=ie(e);if(!(y.noCloneChecked||1!==e.nodeType&&11!==e.nodeType||S.isXMLDoc(e)))for(a=ve(c),r=0,i=(o=ve(e)).length;r<i;r++)s=o[r],u=a[r],void 0,"input"===(l=u.nodeName.toLowerCase())&&pe.test(s.type)?u.checked=s.checked:"input"!==l&&"textarea"!==l||(u.defaultValue=s.defaultValue);if(t)if(n)for(o=o||ve(e),a=a||ve(c),r=0,i=o.length;r<i;r++)Oe(o[r],a[r]);else Oe(e,c);return 0<(a=ve(c,"script")).length&&ye(a,!f&&ve(e,"script")),c},cleanData:function(e){for(var t,n,r,i=S.event.special,o=0;void 0!==(n=e[o]);o++)if(V(n)){if(t=n[Y.expando]){if(t.events)for(r in t.events)i[r]?S.event.remove(n,r):S.removeEvent(n,r,t.handle);n[Y.expando]=void 0}n[Q.expando]&&(n[Q.expando]=void 0)}}}),S.fn.extend({detach:function(e){return Re(this,e,!0)},remove:function(e){return Re(this,e)},text:function(e){return $(this,function(e){return void 0===e?S.text(this):this.empty().each(function(){1!==this.nodeType&&11!==this.nodeType&&9!==this.nodeType||(this.textContent=e)})},null,e,arguments.length)},append:function(){return Pe(this,arguments,function(e){1!==this.nodeType&&11!==this.nodeType&&9!==this.nodeType||qe(this,e).appendChild(e)})},prepend:function(){return Pe(this,arguments,function(e){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var t=qe(this,e);t.insertBefore(e,t.firstChild)}})},before:function(){return Pe(this,arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this)})},after:function(){return Pe(this,arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this.nextSibling)})},empty:function(){for(var e,t=0;null!=(e=this[t]);t++)1===e.nodeType&&(S.cleanData(ve(e,!1)),e.textContent="");return this},clone:function(e,t){return e=null!=e&&e,t=null==t?e:t,this.map(function(){return S.clone(this,e,t)})},html:function(e){return $(this,function(e){var t=this[0]||{},n=0,r=this.length;if(void 0===e&&1===t.nodeType)return t.innerHTML;if("string"==typeof e&&!Ne.test(e)&&!ge[(de.exec(e)||["",""])[1].toLowerCase()]){e=S.htmlPrefilter(e);try{for(;n<r;n++)1===(t=this[n]||{}).nodeType&&(S.cleanData(ve(t,!1)),t.innerHTML=e);t=0}catch(e){}}t&&this.empty().append(e)},null,e,arguments.length)},replaceWith:function(){var n=[];return Pe(this,arguments,function(e){var t=this.parentNode;S.inArray(this,n)<0&&(S.cleanData(ve(this)),t&&t.replaceChild(e,this))},n)}}),S.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(e,a){S.fn[e]=function(e){for(var t,n=[],r=S(e),i=r.length-1,o=0;o<=i;o++)t=o===i?this:this.clone(!0),S(r[o])[a](t),u.apply(n,t.get());return this.pushStack(n)}});var Me=new RegExp("^("+ee+")(?!px)[a-z%]+$","i"),Ie=function(e){var t=e.ownerDocument.defaultView;return t&&t.opener||(t=C),t.getComputedStyle(e)},We=function(e,t,n){var r,i,o={};for(i in t)o[i]=e.style[i],e.style[i]=t[i];for(i in r=n.call(e),t)e.style[i]=o[i];return r},Fe=new RegExp(ne.join("|"),"i");function Be(e,t,n){var r,i,o,a,s=e.style;return(n=n||Ie(e))&&(""!==(a=n.getPropertyValue(t)||n[t])||ie(e)||(a=S.style(e,t)),!y.pixelBoxStyles()&&Me.test(a)&&Fe.test(t)&&(r=s.width,i=s.minWidth,o=s.maxWidth,s.minWidth=s.maxWidth=s.width=a,a=n.width,s.width=r,s.minWidth=i,s.maxWidth=o)),void 0!==a?a+"":a}function $e(e,t){return{get:function(){if(!e())return(this.get=t).apply(this,arguments);delete this.get}}}!function(){function e(){if(l){u.style.cssText="position:absolute;left:-11111px;width:60px;margin-top:1px;padding:0;border:0",l.style.cssText="position:relative;display:block;box-sizing:border-box;overflow:scroll;margin:auto;border:1px;padding:1px;width:60%;top:1%",re.appendChild(u).appendChild(l);var e=C.getComputedStyle(l);n="1%"!==e.top,s=12===t(e.marginLeft),l.style.right="60%",o=36===t(e.right),r=36===t(e.width),l.style.position="absolute",i=12===t(l.offsetWidth/3),re.removeChild(u),l=null}}function t(e){return Math.round(parseFloat(e))}var n,r,i,o,a,s,u=E.createElement("div"),l=E.createElement("div");l.style&&(l.style.backgroundClip="content-box",l.cloneNode(!0).style.backgroundClip="",y.clearCloneStyle="content-box"===l.style.backgroundClip,S.extend(y,{boxSizingReliable:function(){return e(),r},pixelBoxStyles:function(){return e(),o},pixelPosition:function(){return e(),n},reliableMarginLeft:function(){return e(),s},scrollboxSize:function(){return e(),i},reliableTrDimensions:function(){var e,t,n,r;return null==a&&(e=E.createElement("table"),t=E.createElement("tr"),n=E.createElement("div"),e.style.cssText="position:absolute;left:-11111px",t.style.height="1px",n.style.height="9px",re.appendChild(e).appendChild(t).appendChild(n),r=C.getComputedStyle(t),a=3<parseInt(r.height),re.removeChild(e)),a}}))}();var _e=["Webkit","Moz","ms"],ze=E.createElement("div").style,Ue={};function Xe(e){var t=S.cssProps[e]||Ue[e];return t||(e in ze?e:Ue[e]=function(e){var t=e[0].toUpperCase()+e.slice(1),n=_e.length;while(n--)if((e=_e[n]+t)in ze)return e}(e)||e)}var Ve=/^(none|table(?!-c[ea]).+)/,Ge=/^--/,Ye={position:"absolute",visibility:"hidden",display:"block"},Qe={letterSpacing:"0",fontWeight:"400"};function Je(e,t,n){var r=te.exec(t);return r?Math.max(0,r[2]-(n||0))+(r[3]||"px"):t}function Ke(e,t,n,r,i,o){var a="width"===t?1:0,s=0,u=0;if(n===(r?"border":"content"))return 0;for(;a<4;a+=2)"margin"===n&&(u+=S.css(e,n+ne[a],!0,i)),r?("content"===n&&(u-=S.css(e,"padding"+ne[a],!0,i)),"margin"!==n&&(u-=S.css(e,"border"+ne[a]+"Width",!0,i))):(u+=S.css(e,"padding"+ne[a],!0,i),"padding"!==n?u+=S.css(e,"border"+ne[a]+"Width",!0,i):s+=S.css(e,"border"+ne[a]+"Width",!0,i));return!r&&0<=o&&(u+=Math.max(0,Math.ceil(e["offset"+t[0].toUpperCase()+t.slice(1)]-o-u-s-.5))||0),u}function Ze(e,t,n){var r=Ie(e),i=(!y.boxSizingReliable()||n)&&"border-box"===S.css(e,"boxSizing",!1,r),o=i,a=Be(e,t,r),s="offset"+t[0].toUpperCase()+t.slice(1);if(Me.test(a)){if(!n)return a;a="auto"}return(!y.boxSizingReliable()&&i||!y.reliableTrDimensions()&&A(e,"tr")||"auto"===a||!parseFloat(a)&&"inline"===S.css(e,"display",!1,r))&&e.getClientRects().length&&(i="border-box"===S.css(e,"boxSizing",!1,r),(o=s in e)&&(a=e[s])),(a=parseFloat(a)||0)+Ke(e,t,n||(i?"border":"content"),o,r,a)+"px"}function et(e,t,n,r,i){return new et.prototype.init(e,t,n,r,i)}S.extend({cssHooks:{opacity:{get:function(e,t){if(t){var n=Be(e,"opacity");return""===n?"1":n}}}},cssNumber:{animationIterationCount:!0,columnCount:!0,fillOpacity:!0,flexGrow:!0,flexShrink:!0,fontWeight:!0,gridArea:!0,gridColumn:!0,gridColumnEnd:!0,gridColumnStart:!0,gridRow:!0,gridRowEnd:!0,gridRowStart:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{},style:function(e,t,n,r){if(e&&3!==e.nodeType&&8!==e.nodeType&&e.style){var i,o,a,s=X(t),u=Ge.test(t),l=e.style;if(u||(t=Xe(s)),a=S.cssHooks[t]||S.cssHooks[s],void 0===n)return a&&"get"in a&&void 0!==(i=a.get(e,!1,r))?i:l[t];"string"===(o=typeof n)&&(i=te.exec(n))&&i[1]&&(n=se(e,t,i),o="number"),null!=n&&n==n&&("number"!==o||u||(n+=i&&i[3]||(S.cssNumber[s]?"":"px")),y.clearCloneStyle||""!==n||0!==t.indexOf("background")||(l[t]="inherit"),a&&"set"in a&&void 0===(n=a.set(e,n,r))||(u?l.setProperty(t,n):l[t]=n))}},css:function(e,t,n,r){var i,o,a,s=X(t);return Ge.test(t)||(t=Xe(s)),(a=S.cssHooks[t]||S.cssHooks[s])&&"get"in a&&(i=a.get(e,!0,n)),void 0===i&&(i=Be(e,t,r)),"normal"===i&&t in Qe&&(i=Qe[t]),""===n||n?(o=parseFloat(i),!0===n||isFinite(o)?o||0:i):i}}),S.each(["height","width"],function(e,u){S.cssHooks[u]={get:function(e,t,n){if(t)return!Ve.test(S.css(e,"display"))||e.getClientRects().length&&e.getBoundingClientRect().width?Ze(e,u,n):We(e,Ye,function(){return Ze(e,u,n)})},set:function(e,t,n){var r,i=Ie(e),o=!y.scrollboxSize()&&"absolute"===i.position,a=(o||n)&&"border-box"===S.css(e,"boxSizing",!1,i),s=n?Ke(e,u,n,a,i):0;return a&&o&&(s-=Math.ceil(e["offset"+u[0].toUpperCase()+u.slice(1)]-parseFloat(i[u])-Ke(e,u,"border",!1,i)-.5)),s&&(r=te.exec(t))&&"px"!==(r[3]||"px")&&(e.style[u]=t,t=S.css(e,u)),Je(0,t,s)}}}),S.cssHooks.marginLeft=$e(y.reliableMarginLeft,function(e,t){if(t)return(parseFloat(Be(e,"marginLeft"))||e.getBoundingClientRect().left-We(e,{marginLeft:0},function(){return e.getBoundingClientRect().left}))+"px"}),S.each({margin:"",padding:"",border:"Width"},function(i,o){S.cssHooks[i+o]={expand:function(e){for(var t=0,n={},r="string"==typeof e?e.split(" "):[e];t<4;t++)n[i+ne[t]+o]=r[t]||r[t-2]||r[0];return n}},"margin"!==i&&(S.cssHooks[i+o].set=Je)}),S.fn.extend({css:function(e,t){return $(this,function(e,t,n){var r,i,o={},a=0;if(Array.isArray(t)){for(r=Ie(e),i=t.length;a<i;a++)o[t[a]]=S.css(e,t[a],!1,r);return o}return void 0!==n?S.style(e,t,n):S.css(e,t)},e,t,1<arguments.length)}}),((S.Tween=et).prototype={constructor:et,init:function(e,t,n,r,i,o){this.elem=e,this.prop=n,this.easing=i||S.easing._default,this.options=t,this.start=this.now=this.cur(),this.end=r,this.unit=o||(S.cssNumber[n]?"":"px")},cur:function(){var e=et.propHooks[this.prop];return e&&e.get?e.get(this):et.propHooks._default.get(this)},run:function(e){var t,n=et.propHooks[this.prop];return this.options.duration?this.pos=t=S.easing[this.easing](e,this.options.duration*e,0,1,this.options.duration):this.pos=t=e,this.now=(this.end-this.start)*t+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),n&&n.set?n.set(this):et.propHooks._default.set(this),this}}).init.prototype=et.prototype,(et.propHooks={_default:{get:function(e){var t;return 1!==e.elem.nodeType||null!=e.elem[e.prop]&&null==e.elem.style[e.prop]?e.elem[e.prop]:(t=S.css(e.elem,e.prop,""))&&"auto"!==t?t:0},set:function(e){S.fx.step[e.prop]?S.fx.step[e.prop](e):1!==e.elem.nodeType||!S.cssHooks[e.prop]&&null==e.elem.style[Xe(e.prop)]?e.elem[e.prop]=e.now:S.style(e.elem,e.prop,e.now+e.unit)}}}).scrollTop=et.propHooks.scrollLeft={set:function(e){e.elem.nodeType&&e.elem.parentNode&&(e.elem[e.prop]=e.now)}},S.easing={linear:function(e){return e},swing:function(e){return.5-Math.cos(e*Math.PI)/2},_default:"swing"},S.fx=et.prototype.init,S.fx.step={};var tt,nt,rt,it,ot=/^(?:toggle|show|hide)$/,at=/queueHooks$/;function st(){nt&&(!1===E.hidden&&C.requestAnimationFrame?C.requestAnimationFrame(st):C.setTimeout(st,S.fx.interval),S.fx.tick())}function ut(){return C.setTimeout(function(){tt=void 0}),tt=Date.now()}function lt(e,t){var n,r=0,i={height:e};for(t=t?1:0;r<4;r+=2-t)i["margin"+(n=ne[r])]=i["padding"+n]=e;return t&&(i.opacity=i.width=e),i}function ct(e,t,n){for(var r,i=(ft.tweeners[t]||[]).concat(ft.tweeners["*"]),o=0,a=i.length;o<a;o++)if(r=i[o].call(n,t,e))return r}function ft(o,e,t){var n,a,r=0,i=ft.prefilters.length,s=S.Deferred().always(function(){delete u.elem}),u=function(){if(a)return!1;for(var e=tt||ut(),t=Math.max(0,l.startTime+l.duration-e),n=1-(t/l.duration||0),r=0,i=l.tweens.length;r<i;r++)l.tweens[r].run(n);return s.notifyWith(o,[l,n,t]),n<1&&i?t:(i||s.notifyWith(o,[l,1,0]),s.resolveWith(o,[l]),!1)},l=s.promise({elem:o,props:S.extend({},e),opts:S.extend(!0,{specialEasing:{},easing:S.easing._default},t),originalProperties:e,originalOptions:t,startTime:tt||ut(),duration:t.duration,tweens:[],createTween:function(e,t){var n=S.Tween(o,l.opts,e,t,l.opts.specialEasing[e]||l.opts.easing);return l.tweens.push(n),n},stop:function(e){var t=0,n=e?l.tweens.length:0;if(a)return this;for(a=!0;t<n;t++)l.tweens[t].run(1);return e?(s.notifyWith(o,[l,1,0]),s.resolveWith(o,[l,e])):s.rejectWith(o,[l,e]),this}}),c=l.props;for(!function(e,t){var n,r,i,o,a;for(n in e)if(i=t[r=X(n)],o=e[n],Array.isArray(o)&&(i=o[1],o=e[n]=o[0]),n!==r&&(e[r]=o,delete e[n]),(a=S.cssHooks[r])&&"expand"in a)for(n in o=a.expand(o),delete e[r],o)n in e||(e[n]=o[n],t[n]=i);else t[r]=i}(c,l.opts.specialEasing);r<i;r++)if(n=ft.prefilters[r].call(l,o,c,l.opts))return m(n.stop)&&(S._queueHooks(l.elem,l.opts.queue).stop=n.stop.bind(n)),n;return S.map(c,ct,l),m(l.opts.start)&&l.opts.start.call(o,l),l.progress(l.opts.progress).done(l.opts.done,l.opts.complete).fail(l.opts.fail).always(l.opts.always),S.fx.timer(S.extend(u,{elem:o,anim:l,queue:l.opts.queue})),l}S.Animation=S.extend(ft,{tweeners:{"*":[function(e,t){var n=this.createTween(e,t);return se(n.elem,e,te.exec(t),n),n}]},tweener:function(e,t){m(e)?(t=e,e=["*"]):e=e.match(P);for(var n,r=0,i=e.length;r<i;r++)n=e[r],ft.tweeners[n]=ft.tweeners[n]||[],ft.tweeners[n].unshift(t)},prefilters:[function(e,t,n){var r,i,o,a,s,u,l,c,f="width"in t||"height"in t,p=this,d={},h=e.style,g=e.nodeType&&ae(e),v=Y.get(e,"fxshow");for(r in n.queue||(null==(a=S._queueHooks(e,"fx")).unqueued&&(a.unqueued=0,s=a.empty.fire,a.empty.fire=function(){a.unqueued||s()}),a.unqueued++,p.always(function(){p.always(function(){a.unqueued--,S.queue(e,"fx").length||a.empty.fire()})})),t)if(i=t[r],ot.test(i)){if(delete t[r],o=o||"toggle"===i,i===(g?"hide":"show")){if("show"!==i||!v||void 0===v[r])continue;g=!0}d[r]=v&&v[r]||S.style(e,r)}if((u=!S.isEmptyObject(t))||!S.isEmptyObject(d))for(r in f&&1===e.nodeType&&(n.overflow=[h.overflow,h.overflowX,h.overflowY],null==(l=v&&v.display)&&(l=Y.get(e,"display")),"none"===(c=S.css(e,"display"))&&(l?c=l:(le([e],!0),l=e.style.display||l,c=S.css(e,"display"),le([e]))),("inline"===c||"inline-block"===c&&null!=l)&&"none"===S.css(e,"float")&&(u||(p.done(function(){h.display=l}),null==l&&(c=h.display,l="none"===c?"":c)),h.display="inline-block")),n.overflow&&(h.overflow="hidden",p.always(function(){h.overflow=n.overflow[0],h.overflowX=n.overflow[1],h.overflowY=n.overflow[2]})),u=!1,d)u||(v?"hidden"in v&&(g=v.hidden):v=Y.access(e,"fxshow",{display:l}),o&&(v.hidden=!g),g&&le([e],!0),p.done(function(){for(r in g||le([e]),Y.remove(e,"fxshow"),d)S.style(e,r,d[r])})),u=ct(g?v[r]:0,r,p),r in v||(v[r]=u.start,g&&(u.end=u.start,u.start=0))}],prefilter:function(e,t){t?ft.prefilters.unshift(e):ft.prefilters.push(e)}}),S.speed=function(e,t,n){var r=e&&"object"==typeof e?S.extend({},e):{complete:n||!n&&t||m(e)&&e,duration:e,easing:n&&t||t&&!m(t)&&t};return S.fx.off?r.duration=0:"number"!=typeof r.duration&&(r.duration in S.fx.speeds?r.duration=S.fx.speeds[r.duration]:r.duration=S.fx.speeds._default),null!=r.queue&&!0!==r.queue||(r.queue="fx"),r.old=r.complete,r.complete=function(){m(r.old)&&r.old.call(this),r.queue&&S.dequeue(this,r.queue)},r},S.fn.extend({fadeTo:function(e,t,n,r){return this.filter(ae).css("opacity",0).show().end().animate({opacity:t},e,n,r)},animate:function(t,e,n,r){var i=S.isEmptyObject(t),o=S.speed(e,n,r),a=function(){var e=ft(this,S.extend({},t),o);(i||Y.get(this,"finish"))&&e.stop(!0)};return a.finish=a,i||!1===o.queue?this.each(a):this.queue(o.queue,a)},stop:function(i,e,o){var a=function(e){var t=e.stop;delete e.stop,t(o)};return"string"!=typeof i&&(o=e,e=i,i=void 0),e&&this.queue(i||"fx",[]),this.each(function(){var e=!0,t=null!=i&&i+"queueHooks",n=S.timers,r=Y.get(this);if(t)r[t]&&r[t].stop&&a(r[t]);else for(t in r)r[t]&&r[t].stop&&at.test(t)&&a(r[t]);for(t=n.length;t--;)n[t].elem!==this||null!=i&&n[t].queue!==i||(n[t].anim.stop(o),e=!1,n.splice(t,1));!e&&o||S.dequeue(this,i)})},finish:function(a){return!1!==a&&(a=a||"fx"),this.each(function(){var e,t=Y.get(this),n=t[a+"queue"],r=t[a+"queueHooks"],i=S.timers,o=n?n.length:0;for(t.finish=!0,S.queue(this,a,[]),r&&r.stop&&r.stop.call(this,!0),e=i.length;e--;)i[e].elem===this&&i[e].queue===a&&(i[e].anim.stop(!0),i.splice(e,1));for(e=0;e<o;e++)n[e]&&n[e].finish&&n[e].finish.call(this);delete t.finish})}}),S.each(["toggle","show","hide"],function(e,r){var i=S.fn[r];S.fn[r]=function(e,t,n){return null==e||"boolean"==typeof e?i.apply(this,arguments):this.animate(lt(r,!0),e,t,n)}}),S.each({slideDown:lt("show"),slideUp:lt("hide"),slideToggle:lt("toggle"),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(e,r){S.fn[e]=function(e,t,n){return this.animate(r,e,t,n)}}),S.timers=[],S.fx.tick=function(){var e,t=0,n=S.timers;for(tt=Date.now();t<n.length;t++)(e=n[t])()||n[t]!==e||n.splice(t--,1);n.length||S.fx.stop(),tt=void 0},S.fx.timer=function(e){S.timers.push(e),S.fx.start()},S.fx.interval=13,S.fx.start=function(){nt||(nt=!0,st())},S.fx.stop=function(){nt=null},S.fx.speeds={slow:600,fast:200,_default:400},S.fn.delay=function(r,e){return r=S.fx&&S.fx.speeds[r]||r,e=e||"fx",this.queue(e,function(e,t){var n=C.setTimeout(e,r);t.stop=function(){C.clearTimeout(n)}})},rt=E.createElement("input"),it=E.createElement("select").appendChild(E.createElement("option")),rt.type="checkbox",y.checkOn=""!==rt.value,y.optSelected=it.selected,(rt=E.createElement("input")).value="t",rt.type="radio",y.radioValue="t"===rt.value;var pt,dt=S.expr.attrHandle;S.fn.extend({attr:function(e,t){return $(this,S.attr,e,t,1<arguments.length)},removeAttr:function(e){return this.each(function(){S.removeAttr(this,e)})}}),S.extend({attr:function(e,t,n){var r,i,o=e.nodeType;if(3!==o&&8!==o&&2!==o)return"undefined"==typeof e.getAttribute?S.prop(e,t,n):(1===o&&S.isXMLDoc(e)||(i=S.attrHooks[t.toLowerCase()]||(S.expr.match.bool.test(t)?pt:void 0)),void 0!==n?null===n?void S.removeAttr(e,t):i&&"set"in i&&void 0!==(r=i.set(e,n,t))?r:(e.setAttribute(t,n+""),n):i&&"get"in i&&null!==(r=i.get(e,t))?r:null==(r=S.find.attr(e,t))?void 0:r)},attrHooks:{type:{set:function(e,t){if(!y.radioValue&&"radio"===t&&A(e,"input")){var n=e.value;return e.setAttribute("type",t),n&&(e.value=n),t}}}},removeAttr:function(e,t){var n,r=0,i=t&&t.match(P);if(i&&1===e.nodeType)while(n=i[r++])e.removeAttribute(n)}}),pt={set:function(e,t,n){return!1===t?S.removeAttr(e,n):e.setAttribute(n,n),n}},S.each(S.expr.match.bool.source.match(/\w+/g),function(e,t){var a=dt[t]||S.find.attr;dt[t]=function(e,t,n){var r,i,o=t.toLowerCase();return n||(i=dt[o],dt[o]=r,r=null!=a(e,t,n)?o:null,dt[o]=i),r}});var ht=/^(?:input|select|textarea|button)$/i,gt=/^(?:a|area)$/i;function vt(e){return(e.match(P)||[]).join(" ")}function yt(e){return e.getAttribute&&e.getAttribute("class")||""}function mt(e){return Array.isArray(e)?e:"string"==typeof e&&e.match(P)||[]}S.fn.extend({prop:function(e,t){return $(this,S.prop,e,t,1<arguments.length)},removeProp:function(e){return this.each(function(){delete this[S.propFix[e]||e]})}}),S.extend({prop:function(e,t,n){var r,i,o=e.nodeType;if(3!==o&&8!==o&&2!==o)return 1===o&&S.isXMLDoc(e)||(t=S.propFix[t]||t,i=S.propHooks[t]),void 0!==n?i&&"set"in i&&void 0!==(r=i.set(e,n,t))?r:e[t]=n:i&&"get"in i&&null!==(r=i.get(e,t))?r:e[t]},propHooks:{tabIndex:{get:function(e){var t=S.find.attr(e,"tabindex");return t?parseInt(t,10):ht.test(e.nodeName)||gt.test(e.nodeName)&&e.href?0:-1}}},propFix:{"for":"htmlFor","class":"className"}}),y.optSelected||(S.propHooks.selected={get:function(e){var t=e.parentNode;return t&&t.parentNode&&t.parentNode.selectedIndex,null},set:function(e){var t=e.parentNode;t&&(t.selectedIndex,t.parentNode&&t.parentNode.selectedIndex)}}),S.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],function(){S.propFix[this.toLowerCase()]=this}),S.fn.extend({addClass:function(t){var e,n,r,i,o,a,s,u=0;if(m(t))return this.each(function(e){S(this).addClass(t.call(this,e,yt(this)))});if((e=mt(t)).length)while(n=this[u++])if(i=yt(n),r=1===n.nodeType&&" "+vt(i)+" "){a=0;while(o=e[a++])r.indexOf(" "+o+" ")<0&&(r+=o+" ");i!==(s=vt(r))&&n.setAttribute("class",s)}return this},removeClass:function(t){var e,n,r,i,o,a,s,u=0;if(m(t))return this.each(function(e){S(this).removeClass(t.call(this,e,yt(this)))});if(!arguments.length)return this.attr("class","");if((e=mt(t)).length)while(n=this[u++])if(i=yt(n),r=1===n.nodeType&&" "+vt(i)+" "){a=0;while(o=e[a++])while(-1<r.indexOf(" "+o+" "))r=r.replace(" "+o+" "," ");i!==(s=vt(r))&&n.setAttribute("class",s)}return this},toggleClass:function(i,t){var o=typeof i,a="string"===o||Array.isArray(i);return"boolean"==typeof t&&a?t?this.addClass(i):this.removeClass(i):m(i)?this.each(function(e){S(this).toggleClass(i.call(this,e,yt(this),t),t)}):this.each(function(){var e,t,n,r;if(a){t=0,n=S(this),r=mt(i);while(e=r[t++])n.hasClass(e)?n.removeClass(e):n.addClass(e)}else void 0!==i&&"boolean"!==o||((e=yt(this))&&Y.set(this,"__className__",e),this.setAttribute&&this.setAttribute("class",e||!1===i?"":Y.get(this,"__className__")||""))})},hasClass:function(e){var t,n,r=0;t=" "+e+" ";while(n=this[r++])if(1===n.nodeType&&-1<(" "+vt(yt(n))+" ").indexOf(t))return!0;return!1}});var xt=/\r/g;S.fn.extend({val:function(n){var r,e,i,t=this[0];return arguments.length?(i=m(n),this.each(function(e){var t;1===this.nodeType&&(null==(t=i?n.call(this,e,S(this).val()):n)?t="":"number"==typeof t?t+="":Array.isArray(t)&&(t=S.map(t,function(e){return null==e?"":e+""})),(r=S.valHooks[this.type]||S.valHooks[this.nodeName.toLowerCase()])&&"set"in r&&void 0!==r.set(this,t,"value")||(this.value=t))})):t?(r=S.valHooks[t.type]||S.valHooks[t.nodeName.toLowerCase()])&&"get"in r&&void 0!==(e=r.get(t,"value"))?e:"string"==typeof(e=t.value)?e.replace(xt,""):null==e?"":e:void 0}}),S.extend({valHooks:{option:{get:function(e){var t=S.find.attr(e,"value");return null!=t?t:vt(S.text(e))}},select:{get:function(e){var t,n,r,i=e.options,o=e.selectedIndex,a="select-one"===e.type,s=a?null:[],u=a?o+1:i.length;for(r=o<0?u:a?o:0;r<u;r++)if(((n=i[r]).selected||r===o)&&!n.disabled&&(!n.parentNode.disabled||!A(n.parentNode,"optgroup"))){if(t=S(n).val(),a)return t;s.push(t)}return s},set:function(e,t){var n,r,i=e.options,o=S.makeArray(t),a=i.length;while(a--)((r=i[a]).selected=-1<S.inArray(S.valHooks.option.get(r),o))&&(n=!0);return n||(e.selectedIndex=-1),o}}}}),S.each(["radio","checkbox"],function(){S.valHooks[this]={set:function(e,t){if(Array.isArray(t))return e.checked=-1<S.inArray(S(e).val(),t)}},y.checkOn||(S.valHooks[this].get=function(e){return null===e.getAttribute("value")?"on":e.value})}),y.focusin="onfocusin"in C;var bt=/^(?:focusinfocus|focusoutblur)$/,wt=function(e){e.stopPropagation()};S.extend(S.event,{trigger:function(e,t,n,r){var i,o,a,s,u,l,c,f,p=[n||E],d=v.call(e,"type")?e.type:e,h=v.call(e,"namespace")?e.namespace.split("."):[];if(o=f=a=n=n||E,3!==n.nodeType&&8!==n.nodeType&&!bt.test(d+S.event.triggered)&&(-1<d.indexOf(".")&&(d=(h=d.split(".")).shift(),h.sort()),u=d.indexOf(":")<0&&"on"+d,(e=e[S.expando]?e:new S.Event(d,"object"==typeof e&&e)).isTrigger=r?2:3,e.namespace=h.join("."),e.rnamespace=e.namespace?new RegExp("(^|\\.)"+h.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,e.result=void 0,e.target||(e.target=n),t=null==t?[e]:S.makeArray(t,[e]),c=S.event.special[d]||{},r||!c.trigger||!1!==c.trigger.apply(n,t))){if(!r&&!c.noBubble&&!x(n)){for(s=c.delegateType||d,bt.test(s+d)||(o=o.parentNode);o;o=o.parentNode)p.push(o),a=o;a===(n.ownerDocument||E)&&p.push(a.defaultView||a.parentWindow||C)}i=0;while((o=p[i++])&&!e.isPropagationStopped())f=o,e.type=1<i?s:c.bindType||d,(l=(Y.get(o,"events")||Object.create(null))[e.type]&&Y.get(o,"handle"))&&l.apply(o,t),(l=u&&o[u])&&l.apply&&V(o)&&(e.result=l.apply(o,t),!1===e.result&&e.preventDefault());return e.type=d,r||e.isDefaultPrevented()||c._default&&!1!==c._default.apply(p.pop(),t)||!V(n)||u&&m(n[d])&&!x(n)&&((a=n[u])&&(n[u]=null),S.event.triggered=d,e.isPropagationStopped()&&f.addEventListener(d,wt),n[d](),e.isPropagationStopped()&&f.removeEventListener(d,wt),S.event.triggered=void 0,a&&(n[u]=a)),e.result}},simulate:function(e,t,n){var r=S.extend(new S.Event,n,{type:e,isSimulated:!0});S.event.trigger(r,null,t)}}),S.fn.extend({trigger:function(e,t){return this.each(function(){S.event.trigger(e,t,this)})},triggerHandler:function(e,t){var n=this[0];if(n)return S.event.trigger(e,t,n,!0)}}),y.focusin||S.each({focus:"focusin",blur:"focusout"},function(n,r){var i=function(e){S.event.simulate(r,e.target,S.event.fix(e))};S.event.special[r]={setup:function(){var e=this.ownerDocument||this.document||this,t=Y.access(e,r);t||e.addEventListener(n,i,!0),Y.access(e,r,(t||0)+1)},teardown:function(){var e=this.ownerDocument||this.document||this,t=Y.access(e,r)-1;t?Y.access(e,r,t):(e.removeEventListener(n,i,!0),Y.remove(e,r))}}});var Tt=C.location,Ct={guid:Date.now()},Et=/\?/;S.parseXML=function(e){var t;if(!e||"string"!=typeof e)return null;try{t=(new C.DOMParser).parseFromString(e,"text/xml")}catch(e){t=void 0}return t&&!t.getElementsByTagName("parsererror").length||S.error("Invalid XML: "+e),t};var St=/\[\]$/,kt=/\r?\n/g,At=/^(?:submit|button|image|reset|file)$/i,Nt=/^(?:input|select|textarea|keygen)/i;function Dt(n,e,r,i){var t;if(Array.isArray(e))S.each(e,function(e,t){r||St.test(n)?i(n,t):Dt(n+"["+("object"==typeof t&&null!=t?e:"")+"]",t,r,i)});else if(r||"object"!==w(e))i(n,e);else for(t in e)Dt(n+"["+t+"]",e[t],r,i)}S.param=function(e,t){var n,r=[],i=function(e,t){var n=m(t)?t():t;r[r.length]=encodeURIComponent(e)+"="+encodeURIComponent(null==n?"":n)};if(null==e)return"";if(Array.isArray(e)||e.jquery&&!S.isPlainObject(e))S.each(e,function(){i(this.name,this.value)});else for(n in e)Dt(n,e[n],t,i);return r.join("&")},S.fn.extend({serialize:function(){return S.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var e=S.prop(this,"elements");return e?S.makeArray(e):this}).filter(function(){var e=this.type;return this.name&&!S(this).is(":disabled")&&Nt.test(this.nodeName)&&!At.test(e)&&(this.checked||!pe.test(e))}).map(function(e,t){var n=S(this).val();return null==n?null:Array.isArray(n)?S.map(n,function(e){return{name:t.name,value:e.replace(kt,"\r\n")}}):{name:t.name,value:n.replace(kt,"\r\n")}}).get()}});var jt=/%20/g,qt=/#.*$/,Lt=/([?&])_=[^&]*/,Ht=/^(.*?):[ \t]*([^\r\n]*)$/gm,Ot=/^(?:GET|HEAD)$/,Pt=/^\/\//,Rt={},Mt={},It="*/".concat("*"),Wt=E.createElement("a");function Ft(o){return function(e,t){"string"!=typeof e&&(t=e,e="*");var n,r=0,i=e.toLowerCase().match(P)||[];if(m(t))while(n=i[r++])"+"===n[0]?(n=n.slice(1)||"*",(o[n]=o[n]||[]).unshift(t)):(o[n]=o[n]||[]).push(t)}}function Bt(t,i,o,a){var s={},u=t===Mt;function l(e){var r;return s[e]=!0,S.each(t[e]||[],function(e,t){var n=t(i,o,a);return"string"!=typeof n||u||s[n]?u?!(r=n):void 0:(i.dataTypes.unshift(n),l(n),!1)}),r}return l(i.dataTypes[0])||!s["*"]&&l("*")}function $t(e,t){var n,r,i=S.ajaxSettings.flatOptions||{};for(n in t)void 0!==t[n]&&((i[n]?e:r||(r={}))[n]=t[n]);return r&&S.extend(!0,e,r),e}Wt.href=Tt.href,S.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:Tt.href,type:"GET",isLocal:/^(?:about|app|app-storage|.+-extension|file|res|widget):$/.test(Tt.protocol),global:!0,processData:!0,async:!0,contentType:"application/x-www-form-urlencoded; charset=UTF-8",accepts:{"*":It,text:"text/plain",html:"text/html",xml:"application/xml, text/xml",json:"application/json, text/javascript"},contents:{xml:/\bxml\b/,html:/\bhtml/,json:/\bjson\b/},responseFields:{xml:"responseXML",text:"responseText",json:"responseJSON"},converters:{"* text":String,"text html":!0,"text json":JSON.parse,"text xml":S.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(e,t){return t?$t($t(e,S.ajaxSettings),t):$t(S.ajaxSettings,e)},ajaxPrefilter:Ft(Rt),ajaxTransport:Ft(Mt),ajax:function(e,t){"object"==typeof e&&(t=e,e=void 0),t=t||{};var c,f,p,n,d,r,h,g,i,o,v=S.ajaxSetup({},t),y=v.context||v,m=v.context&&(y.nodeType||y.jquery)?S(y):S.event,x=S.Deferred(),b=S.Callbacks("once memory"),w=v.statusCode||{},a={},s={},u="canceled",T={readyState:0,getResponseHeader:function(e){var t;if(h){if(!n){n={};while(t=Ht.exec(p))n[t[1].toLowerCase()+" "]=(n[t[1].toLowerCase()+" "]||[]).concat(t[2])}t=n[e.toLowerCase()+" "]}return null==t?null:t.join(", ")},getAllResponseHeaders:function(){return h?p:null},setRequestHeader:function(e,t){return null==h&&(e=s[e.toLowerCase()]=s[e.toLowerCase()]||e,a[e]=t),this},overrideMimeType:function(e){return null==h&&(v.mimeType=e),this},statusCode:function(e){var t;if(e)if(h)T.always(e[T.status]);else for(t in e)w[t]=[w[t],e[t]];return this},abort:function(e){var t=e||u;return c&&c.abort(t),l(0,t),this}};if(x.promise(T),v.url=((e||v.url||Tt.href)+"").replace(Pt,Tt.protocol+"//"),v.type=t.method||t.type||v.method||v.type,v.dataTypes=(v.dataType||"*").toLowerCase().match(P)||[""],null==v.crossDomain){r=E.createElement("a");try{r.href=v.url,r.href=r.href,v.crossDomain=Wt.protocol+"//"+Wt.host!=r.protocol+"//"+r.host}catch(e){v.crossDomain=!0}}if(v.data&&v.processData&&"string"!=typeof v.data&&(v.data=S.param(v.data,v.traditional)),Bt(Rt,v,t,T),h)return T;for(i in(g=S.event&&v.global)&&0==S.active++&&S.event.trigger("ajaxStart"),v.type=v.type.toUpperCase(),v.hasContent=!Ot.test(v.type),f=v.url.replace(qt,""),v.hasContent?v.data&&v.processData&&0===(v.contentType||"").indexOf("application/x-www-form-urlencoded")&&(v.data=v.data.replace(jt,"+")):(o=v.url.slice(f.length),v.data&&(v.processData||"string"==typeof v.data)&&(f+=(Et.test(f)?"&":"?")+v.data,delete v.data),!1===v.cache&&(f=f.replace(Lt,"$1"),o=(Et.test(f)?"&":"?")+"_="+Ct.guid+++o),v.url=f+o),v.ifModified&&(S.lastModified[f]&&T.setRequestHeader("If-Modified-Since",S.lastModified[f]),S.etag[f]&&T.setRequestHeader("If-None-Match",S.etag[f])),(v.data&&v.hasContent&&!1!==v.contentType||t.contentType)&&T.setRequestHeader("Content-Type",v.contentType),T.setRequestHeader("Accept",v.dataTypes[0]&&v.accepts[v.dataTypes[0]]?v.accepts[v.dataTypes[0]]+("*"!==v.dataTypes[0]?", "+It+"; q=0.01":""):v.accepts["*"]),v.headers)T.setRequestHeader(i,v.headers[i]);if(v.beforeSend&&(!1===v.beforeSend.call(y,T,v)||h))return T.abort();if(u="abort",b.add(v.complete),T.done(v.success),T.fail(v.error),c=Bt(Mt,v,t,T)){if(T.readyState=1,g&&m.trigger("ajaxSend",[T,v]),h)return T;v.async&&0<v.timeout&&(d=C.setTimeout(function(){T.abort("timeout")},v.timeout));try{h=!1,c.send(a,l)}catch(e){if(h)throw e;l(-1,e)}}else l(-1,"No Transport");function l(e,t,n,r){var i,o,a,s,u,l=t;h||(h=!0,d&&C.clearTimeout(d),c=void 0,p=r||"",T.readyState=0<e?4:0,i=200<=e&&e<300||304===e,n&&(s=function(e,t,n){var r,i,o,a,s=e.contents,u=e.dataTypes;while("*"===u[0])u.shift(),void 0===r&&(r=e.mimeType||t.getResponseHeader("Content-Type"));if(r)for(i in s)if(s[i]&&s[i].test(r)){u.unshift(i);break}if(u[0]in n)o=u[0];else{for(i in n){if(!u[0]||e.converters[i+" "+u[0]]){o=i;break}a||(a=i)}o=o||a}if(o)return o!==u[0]&&u.unshift(o),n[o]}(v,T,n)),!i&&-1<S.inArray("script",v.dataTypes)&&(v.converters["text script"]=function(){}),s=function(e,t,n,r){var i,o,a,s,u,l={},c=e.dataTypes.slice();if(c[1])for(a in e.converters)l[a.toLowerCase()]=e.converters[a];o=c.shift();while(o)if(e.responseFields[o]&&(n[e.responseFields[o]]=t),!u&&r&&e.dataFilter&&(t=e.dataFilter(t,e.dataType)),u=o,o=c.shift())if("*"===o)o=u;else if("*"!==u&&u!==o){if(!(a=l[u+" "+o]||l["* "+o]))for(i in l)if((s=i.split(" "))[1]===o&&(a=l[u+" "+s[0]]||l["* "+s[0]])){!0===a?a=l[i]:!0!==l[i]&&(o=s[0],c.unshift(s[1]));break}if(!0!==a)if(a&&e["throws"])t=a(t);else try{t=a(t)}catch(e){return{state:"parsererror",error:a?e:"No conversion from "+u+" to "+o}}}return{state:"success",data:t}}(v,s,T,i),i?(v.ifModified&&((u=T.getResponseHeader("Last-Modified"))&&(S.lastModified[f]=u),(u=T.getResponseHeader("etag"))&&(S.etag[f]=u)),204===e||"HEAD"===v.type?l="nocontent":304===e?l="notmodified":(l=s.state,o=s.data,i=!(a=s.error))):(a=l,!e&&l||(l="error",e<0&&(e=0))),T.status=e,T.statusText=(t||l)+"",i?x.resolveWith(y,[o,l,T]):x.rejectWith(y,[T,l,a]),T.statusCode(w),w=void 0,g&&m.trigger(i?"ajaxSuccess":"ajaxError",[T,v,i?o:a]),b.fireWith(y,[T,l]),g&&(m.trigger("ajaxComplete",[T,v]),--S.active||S.event.trigger("ajaxStop")))}return T},getJSON:function(e,t,n){return S.get(e,t,n,"json")},getScript:function(e,t){return S.get(e,void 0,t,"script")}}),S.each(["get","post"],function(e,i){S[i]=function(e,t,n,r){return m(t)&&(r=r||n,n=t,t=void 0),S.ajax(S.extend({url:e,type:i,dataType:r,data:t,success:n},S.isPlainObject(e)&&e))}}),S.ajaxPrefilter(function(e){var t;for(t in e.headers)"content-type"===t.toLowerCase()&&(e.contentType=e.headers[t]||"")}),S._evalUrl=function(e,t,n){return S.ajax({url:e,type:"GET",dataType:"script",cache:!0,async:!1,global:!1,converters:{"text script":function(){}},dataFilter:function(e){S.globalEval(e,t,n)}})},S.fn.extend({wrapAll:function(e){var t;return this[0]&&(m(e)&&(e=e.call(this[0])),t=S(e,this[0].ownerDocument).eq(0).clone(!0),this[0].parentNode&&t.insertBefore(this[0]),t.map(function(){var e=this;while(e.firstElementChild)e=e.firstElementChild;return e}).append(this)),this},wrapInner:function(n){return m(n)?this.each(function(e){S(this).wrapInner(n.call(this,e))}):this.each(function(){var e=S(this),t=e.contents();t.length?t.wrapAll(n):e.append(n)})},wrap:function(t){var n=m(t);return this.each(function(e){S(this).wrapAll(n?t.call(this,e):t)})},unwrap:function(e){return this.parent(e).not("body").each(function(){S(this).replaceWith(this.childNodes)}),this}}),S.expr.pseudos.hidden=function(e){return!S.expr.pseudos.visible(e)},S.expr.pseudos.visible=function(e){return!!(e.offsetWidth||e.offsetHeight||e.getClientRects().length)},S.ajaxSettings.xhr=function(){try{return new C.XMLHttpRequest}catch(e){}};var _t={0:200,1223:204},zt=S.ajaxSettings.xhr();y.cors=!!zt&&"withCredentials"in zt,y.ajax=zt=!!zt,S.ajaxTransport(function(i){var o,a;if(y.cors||zt&&!i.crossDomain)return{send:function(e,t){var n,r=i.xhr();if(r.open(i.type,i.url,i.async,i.username,i.password),i.xhrFields)for(n in i.xhrFields)r[n]=i.xhrFields[n];for(n in i.mimeType&&r.overrideMimeType&&r.overrideMimeType(i.mimeType),i.crossDomain||e["X-Requested-With"]||(e["X-Requested-With"]="XMLHttpRequest"),e)r.setRequestHeader(n,e[n]);o=function(e){return function(){o&&(o=a=r.onload=r.onerror=r.onabort=r.ontimeout=r.onreadystatechange=null,"abort"===e?r.abort():"error"===e?"number"!=typeof r.status?t(0,"error"):t(r.status,r.statusText):t(_t[r.status]||r.status,r.statusText,"text"!==(r.responseType||"text")||"string"!=typeof r.responseText?{binary:r.response}:{text:r.responseText},r.getAllResponseHeaders()))}},r.onload=o(),a=r.onerror=r.ontimeout=o("error"),void 0!==r.onabort?r.onabort=a:r.onreadystatechange=function(){4===r.readyState&&C.setTimeout(function(){o&&a()})},o=o("abort");try{r.send(i.hasContent&&i.data||null)}catch(e){if(o)throw e}},abort:function(){o&&o()}}}),S.ajaxPrefilter(function(e){e.crossDomain&&(e.contents.script=!1)}),S.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/\b(?:java|ecma)script\b/},converters:{"text script":function(e){return S.globalEval(e),e}}}),S.ajaxPrefilter("script",function(e){void 0===e.cache&&(e.cache=!1),e.crossDomain&&(e.type="GET")}),S.ajaxTransport("script",function(n){var r,i;if(n.crossDomain||n.scriptAttrs)return{send:function(e,t){r=S("<script>").attr(n.scriptAttrs||{}).prop({charset:n.scriptCharset,src:n.url}).on("load error",i=function(e){r.remove(),i=null,e&&t("error"===e.type?404:200,e.type)}),E.head.appendChild(r[0])},abort:function(){i&&i()}}});var Ut,Xt=[],Vt=/(=)\?(?=&|$)|\?\?/;S.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=Xt.pop()||S.expando+"_"+Ct.guid++;return this[e]=!0,e}}),S.ajaxPrefilter("json jsonp",function(e,t,n){var r,i,o,a=!1!==e.jsonp&&(Vt.test(e.url)?"url":"string"==typeof e.data&&0===(e.contentType||"").indexOf("application/x-www-form-urlencoded")&&Vt.test(e.data)&&"data");if(a||"jsonp"===e.dataTypes[0])return r=e.jsonpCallback=m(e.jsonpCallback)?e.jsonpCallback():e.jsonpCallback,a?e[a]=e[a].replace(Vt,"$1"+r):!1!==e.jsonp&&(e.url+=(Et.test(e.url)?"&":"?")+e.jsonp+"="+r),e.converters["script json"]=function(){return o||S.error(r+" was not called"),o[0]},e.dataTypes[0]="json",i=C[r],C[r]=function(){o=arguments},n.always(function(){void 0===i?S(C).removeProp(r):C[r]=i,e[r]&&(e.jsonpCallback=t.jsonpCallback,Xt.push(r)),o&&m(i)&&i(o[0]),o=i=void 0}),"script"}),y.createHTMLDocument=((Ut=E.implementation.createHTMLDocument("").body).innerHTML="<form></form><form></form>",2===Ut.childNodes.length),S.parseHTML=function(e,t,n){return"string"!=typeof e?[]:("boolean"==typeof t&&(n=t,t=!1),t||(y.createHTMLDocument?((r=(t=E.implementation.createHTMLDocument("")).createElement("base")).href=E.location.href,t.head.appendChild(r)):t=E),o=!n&&[],(i=N.exec(e))?[t.createElement(i[1])]:(i=xe([e],t,o),o&&o.length&&S(o).remove(),S.merge([],i.childNodes)));var r,i,o},S.fn.load=function(e,t,n){var r,i,o,a=this,s=e.indexOf(" ");return-1<s&&(r=vt(e.slice(s)),e=e.slice(0,s)),m(t)?(n=t,t=void 0):t&&"object"==typeof t&&(i="POST"),0<a.length&&S.ajax({url:e,type:i||"GET",dataType:"html",data:t}).done(function(e){o=arguments,a.html(r?S("<div>").append(S.parseHTML(e)).find(r):e)}).always(n&&function(e,t){a.each(function(){n.apply(this,o||[e.responseText,t,e])})}),this},S.expr.pseudos.animated=function(t){return S.grep(S.timers,function(e){return t===e.elem}).length},S.offset={setOffset:function(e,t,n){var r,i,o,a,s,u,l=S.css(e,"position"),c=S(e),f={};"static"===l&&(e.style.position="relative"),s=c.offset(),o=S.css(e,"top"),u=S.css(e,"left"),("absolute"===l||"fixed"===l)&&-1<(o+u).indexOf("auto")?(a=(r=c.position()).top,i=r.left):(a=parseFloat(o)||0,i=parseFloat(u)||0),m(t)&&(t=t.call(e,n,S.extend({},s))),null!=t.top&&(f.top=t.top-s.top+a),null!=t.left&&(f.left=t.left-s.left+i),"using"in t?t.using.call(e,f):("number"==typeof f.top&&(f.top+="px"),"number"==typeof f.left&&(f.left+="px"),c.css(f))}},S.fn.extend({offset:function(t){if(arguments.length)return void 0===t?this:this.each(function(e){S.offset.setOffset(this,t,e)});var e,n,r=this[0];return r?r.getClientRects().length?(e=r.getBoundingClientRect(),n=r.ownerDocument.defaultView,{top:e.top+n.pageYOffset,left:e.left+n.pageXOffset}):{top:0,left:0}:void 0},position:function(){if(this[0]){var e,t,n,r=this[0],i={top:0,left:0};if("fixed"===S.css(r,"position"))t=r.getBoundingClientRect();else{t=this.offset(),n=r.ownerDocument,e=r.offsetParent||n.documentElement;while(e&&(e===n.body||e===n.documentElement)&&"static"===S.css(e,"position"))e=e.parentNode;e&&e!==r&&1===e.nodeType&&((i=S(e).offset()).top+=S.css(e,"borderTopWidth",!0),i.left+=S.css(e,"borderLeftWidth",!0))}return{top:t.top-i.top-S.css(r,"marginTop",!0),left:t.left-i.left-S.css(r,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var e=this.offsetParent;while(e&&"static"===S.css(e,"position"))e=e.offsetParent;return e||re})}}),S.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(t,i){var o="pageYOffset"===i;S.fn[t]=function(e){return $(this,function(e,t,n){var r;if(x(e)?r=e:9===e.nodeType&&(r=e.defaultView),void 0===n)return r?r[i]:e[t];r?r.scrollTo(o?r.pageXOffset:n,o?n:r.pageYOffset):e[t]=n},t,e,arguments.length)}}),S.each(["top","left"],function(e,n){S.cssHooks[n]=$e(y.pixelPosition,function(e,t){if(t)return t=Be(e,n),Me.test(t)?S(e).position()[n]+"px":t})}),S.each({Height:"height",Width:"width"},function(a,s){S.each({padding:"inner"+a,content:s,"":"outer"+a},function(r,o){S.fn[o]=function(e,t){var n=arguments.length&&(r||"boolean"!=typeof e),i=r||(!0===e||!0===t?"margin":"border");return $(this,function(e,t,n){var r;return x(e)?0===o.indexOf("outer")?e["inner"+a]:e.document.documentElement["client"+a]:9===e.nodeType?(r=e.documentElement,Math.max(e.body["scroll"+a],r["scroll"+a],e.body["offset"+a],r["offset"+a],r["client"+a])):void 0===n?S.css(e,t,i):S.style(e,t,n,i)},s,n?e:void 0,n)}})}),S.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(e,t){S.fn[t]=function(e){return this.on(t,e)}}),S.fn.extend({bind:function(e,t,n){return this.on(e,null,t,n)},unbind:function(e,t){return this.off(e,null,t)},delegate:function(e,t,n,r){return this.on(t,e,n,r)},undelegate:function(e,t,n){return 1===arguments.length?this.off(e,"**"):this.off(t,e||"**",n)},hover:function(e,t){return this.mouseenter(e).mouseleave(t||e)}}),S.each("blur focus focusin focusout resize scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup contextmenu".split(" "),function(e,n){S.fn[n]=function(e,t){return 0<arguments.length?this.on(n,null,e,t):this.trigger(n)}});var Gt=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g;S.proxy=function(e,t){var n,r,i;if("string"==typeof t&&(n=e[t],t=e,e=n),m(e))return r=s.call(arguments,2),(i=function(){return e.apply(t||this,r.concat(s.call(arguments)))}).guid=e.guid=e.guid||S.guid++,i},S.holdReady=function(e){e?S.readyWait++:S.ready(!0)},S.isArray=Array.isArray,S.parseJSON=JSON.parse,S.nodeName=A,S.isFunction=m,S.isWindow=x,S.camelCase=X,S.type=w,S.now=Date.now,S.isNumeric=function(e){var t=S.type(e);return("number"===t||"string"===t)&&!isNaN(e-parseFloat(e))},S.trim=function(e){return null==e?"":(e+"").replace(Gt,"")},"function"==typeof define&&define.amd&&define("jquery",[],function(){return S});var Yt=C.jQuery,Qt=C.$;return S.noConflict=function(e){return C.$===S&&(C.$=Qt),e&&C.jQuery===S&&(C.jQuery=Yt),S},"undefined"==typeof e&&(C.jQuery=C.$=S),S});
diff --git a/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/js/nv.d3.min.js b/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/js/nv.d3.min.js
new file mode 100644
index 0000000000000000000000000000000000000000..801e721d3c0e8934fb5a630326679f7c2f5fbb98
--- /dev/null
+++ b/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/js/nv.d3.min.js
@@ -0,0 +1,8 @@
+/* nvd3 version 1.8.1 (https://github.com/novus/nvd3) 2015-06-15 */
+!function(){var a={};a.dev=!1,a.tooltip=a.tooltip||{},a.utils=a.utils||{},a.models=a.models||{},a.charts={},a.logs={},a.dom={},a.dispatch=d3.dispatch("render_start","render_end"),Function.prototype.bind||(Function.prototype.bind=function(a){if("function"!=typeof this)throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable");var b=Array.prototype.slice.call(arguments,1),c=this,d=function(){},e=function(){return c.apply(this instanceof d&&a?this:a,b.concat(Array.prototype.slice.call(arguments)))};return d.prototype=this.prototype,e.prototype=new d,e}),a.dev&&(a.dispatch.on("render_start",function(){a.logs.startTime=+new Date}),a.dispatch.on("render_end",function(){a.logs.endTime=+new Date,a.logs.totalTime=a.logs.endTime-a.logs.startTime,a.log("total",a.logs.totalTime)})),a.log=function(){if(a.dev&&window.console&&console.log&&console.log.apply)console.log.apply(console,arguments);else if(a.dev&&window.console&&"function"==typeof console.log&&Function.prototype.bind){var b=Function.prototype.bind.call(console.log,console);b.apply(console,arguments)}return arguments[arguments.length-1]},a.deprecated=function(a,b){console&&console.warn&&console.warn("nvd3 warning: `"+a+"` has been deprecated. ",b||"")},a.render=function(b){b=b||1,a.render.active=!0,a.dispatch.render_start();var c=function(){for(var d,e,f=0;b>f&&(e=a.render.queue[f]);f++)d=e.generate(),typeof e.callback==typeof Function&&e.callback(d);a.render.queue.splice(0,f),a.render.queue.length?setTimeout(c):(a.dispatch.render_end(),a.render.active=!1)};setTimeout(c)},a.render.active=!1,a.render.queue=[],a.addGraph=function(b){typeof arguments[0]==typeof Function&&(b={generate:arguments[0],callback:arguments[1]}),a.render.queue.push(b),a.render.active||a.render()},"undefined"!=typeof module&&"undefined"!=typeof exports&&(module.exports=a),"undefined"!=typeof window&&(window.nv=a),a.dom.write=function(a){return void 0!==window.fastdom?fastdom.write(a):a()},a.dom.read=function(a){return void 0!==window.fastdom?fastdom.read(a):a()},a.interactiveGuideline=function(){"use strict";function b(l){l.each(function(l){function m(){var a=d3.mouse(this),d=a[0],e=a[1],i=!0,j=!1;if(k&&(d=d3.event.offsetX,e=d3.event.offsetY,"svg"!==d3.event.target.tagName&&(i=!1),d3.event.target.className.baseVal.match("nv-legend")&&(j=!0)),i&&(d-=f.left,e-=f.top),0>d||0>e||d>o||e>p||d3.event.relatedTarget&&void 0===d3.event.relatedTarget.ownerSVGElement||j){if(k&&d3.event.relatedTarget&&void 0===d3.event.relatedTarget.ownerSVGElement&&(void 0===d3.event.relatedTarget.className||d3.event.relatedTarget.className.match(c.nvPointerEventsClass)))return;return h.elementMouseout({mouseX:d,mouseY:e}),b.renderGuideLine(null),void c.hidden(!0)}c.hidden(!1);var l=g.invert(d);h.elementMousemove({mouseX:d,mouseY:e,pointXValue:l}),"dblclick"===d3.event.type&&h.elementDblclick({mouseX:d,mouseY:e,pointXValue:l}),"click"===d3.event.type&&h.elementClick({mouseX:d,mouseY:e,pointXValue:l})}var n=d3.select(this),o=d||960,p=e||400,q=n.selectAll("g.nv-wrap.nv-interactiveLineLayer").data([l]),r=q.enter().append("g").attr("class"," nv-wrap nv-interactiveLineLayer");r.append("g").attr("class","nv-interactiveGuideLine"),j&&(j.on("touchmove",m).on("mousemove",m,!0).on("mouseout",m,!0).on("dblclick",m).on("click",m),b.guideLine=null,b.renderGuideLine=function(c){i&&(b.guideLine&&b.guideLine.attr("x1")===c||a.dom.write(function(){var b=q.select(".nv-interactiveGuideLine").selectAll("line").data(null!=c?[a.utils.NaNtoZero(c)]:[],String);b.enter().append("line").attr("class","nv-guideline").attr("x1",function(a){return a}).attr("x2",function(a){return a}).attr("y1",p).attr("y2",0),b.exit().remove()}))})})}var c=a.models.tooltip();c.duration(0).hideDelay(0)._isInteractiveLayer(!0).hidden(!1);var d=null,e=null,f={left:0,top:0},g=d3.scale.linear(),h=d3.dispatch("elementMousemove","elementMouseout","elementClick","elementDblclick"),i=!0,j=null,k="ActiveXObject"in window;return b.dispatch=h,b.tooltip=c,b.margin=function(a){return arguments.length?(f.top="undefined"!=typeof a.top?a.top:f.top,f.left="undefined"!=typeof a.left?a.left:f.left,b):f},b.width=function(a){return arguments.length?(d=a,b):d},b.height=function(a){return arguments.length?(e=a,b):e},b.xScale=function(a){return arguments.length?(g=a,b):g},b.showGuideLine=function(a){return arguments.length?(i=a,b):i},b.svgContainer=function(a){return arguments.length?(j=a,b):j},b},a.interactiveBisect=function(a,b,c){"use strict";if(!(a instanceof Array))return null;var d;d="function"!=typeof c?function(a){return a.x}:c;var e=function(a,b){return d(a)-b},f=d3.bisector(e).left,g=d3.max([0,f(a,b)-1]),h=d(a[g]);if("undefined"==typeof h&&(h=g),h===b)return g;var i=d3.min([g+1,a.length-1]),j=d(a[i]);return"undefined"==typeof j&&(j=i),Math.abs(j-b)>=Math.abs(h-b)?g:i},a.nearestValueIndex=function(a,b,c){"use strict";var d=1/0,e=null;return a.forEach(function(a,f){var g=Math.abs(b-a);null!=a&&d>=g&&c>g&&(d=g,e=f)}),e},function(){"use strict";a.models.tooltip=function(){function b(){if(k){var a=d3.select(k);"svg"!==a.node().tagName&&(a=a.select("svg"));var b=a.node()?a.attr("viewBox"):null;if(b){b=b.split(" ");var c=parseInt(a.style("width"),10)/b[2];p.left=p.left*c,p.top=p.top*c}}}function c(){if(!n){var a;a=k?k:document.body,n=d3.select(a).append("div").attr("class","nvtooltip "+(j?j:"xy-tooltip")).attr("id",v),n.style("top",0).style("left",0),n.style("opacity",0),n.selectAll("div, table, td, tr").classed(w,!0),n.classed(w,!0),o=n.node()}}function d(){if(r&&B(e)){b();var f=p.left,g=null!==i?i:p.top;return a.dom.write(function(){c();var b=A(e);b&&(o.innerHTML=b),k&&u?a.dom.read(function(){var a=k.getElementsByTagName("svg")[0],b={left:0,top:0};if(a){var c=a.getBoundingClientRect(),d=k.getBoundingClientRect(),e=c.top;if(0>e){var i=k.getBoundingClientRect();e=Math.abs(e)>i.height?0:e}b.top=Math.abs(e-d.top),b.left=Math.abs(c.left-d.left)}f+=k.offsetLeft+b.left-2*k.scrollLeft,g+=k.offsetTop+b.top-2*k.scrollTop,h&&h>0&&(g=Math.floor(g/h)*h),C([f,g])}):C([f,g])}),d}}var e=null,f="w",g=25,h=0,i=null,j=null,k=null,l=!0,m=400,n=null,o=null,p={left:null,top:null},q={left:0,top:0},r=!0,s=100,t=!0,u=!1,v="nvtooltip-"+Math.floor(1e5*Math.random()),w="nv-pointer-events-none",x=function(a){return a},y=function(a){return a},z=function(a){return a},A=function(a){if(null===a)return"";var b=d3.select(document.createElement("table"));if(t){var c=b.selectAll("thead").data([a]).enter().append("thead");c.append("tr").append("td").attr("colspan",3).append("strong").classed("x-value",!0).html(y(a.value))}var d=b.selectAll("tbody").data([a]).enter().append("tbody"),e=d.selectAll("tr").data(function(a){return a.series}).enter().append("tr").classed("highlight",function(a){return a.highlight});e.append("td").classed("legend-color-guide",!0).append("div").style("background-color",function(a){return a.color}),e.append("td").classed("key",!0).html(function(a,b){return z(a.key,b)}),e.append("td").classed("value",!0).html(function(a,b){return x(a.value,b)}),e.selectAll("td").each(function(a){if(a.highlight){var b=d3.scale.linear().domain([0,1]).range(["#fff",a.color]),c=.6;d3.select(this).style("border-bottom-color",b(c)).style("border-top-color",b(c))}});var f=b.node().outerHTML;return void 0!==a.footer&&(f+="<div class='footer'>"+a.footer+"</div>"),f},B=function(a){if(a&&a.series){if(a.series instanceof Array)return!!a.series.length;if(a.series instanceof Object)return a.series=[a.series],!0}return!1},C=function(b){o&&a.dom.read(function(){var c,d,e=parseInt(o.offsetHeight,10),h=parseInt(o.offsetWidth,10),i=a.utils.windowSize().width,j=a.utils.windowSize().height,k=window.pageYOffset,p=window.pageXOffset;j=window.innerWidth>=document.body.scrollWidth?j:j-16,i=window.innerHeight>=document.body.scrollHeight?i:i-16;var r,t,u=function(a){var b=d;do isNaN(a.offsetTop)||(b+=a.offsetTop),a=a.offsetParent;while(a);return b},v=function(a){var b=c;do isNaN(a.offsetLeft)||(b+=a.offsetLeft),a=a.offsetParent;while(a);return b};switch(f){case"e":c=b[0]-h-g,d=b[1]-e/2,r=v(o),t=u(o),p>r&&(c=b[0]+g>p?b[0]+g:p-r+c),k>t&&(d=k-t+d),t+e>k+j&&(d=k+j-t+d-e);break;case"w":c=b[0]+g,d=b[1]-e/2,r=v(o),t=u(o),r+h>i&&(c=b[0]-h-g),k>t&&(d=k+5),t+e>k+j&&(d=k+j-t+d-e);break;case"n":c=b[0]-h/2-5,d=b[1]+g,r=v(o),t=u(o),p>r&&(c=p+5),r+h>i&&(c=c-h/2+5),t+e>k+j&&(d=k+j-t+d-e);break;case"s":c=b[0]-h/2,d=b[1]-e-g,r=v(o),t=u(o),p>r&&(c=p+5),r+h>i&&(c=c-h/2+5),k>t&&(d=k);break;case"none":c=b[0],d=b[1]-g,r=v(o),t=u(o)}c-=q.left,d-=q.top;var w=o.getBoundingClientRect(),k=window.pageYOffset||document.documentElement.scrollTop,p=window.pageXOffset||document.documentElement.scrollLeft,x="translate("+(w.left+p)+"px, "+(w.top+k)+"px)",y="translate("+c+"px, "+d+"px)",z=d3.interpolateString(x,y),A=n.style("opacity")<.1;l?n.transition().delay(m).duration(0).style("opacity",0):n.interrupt().transition().duration(A?0:s).styleTween("transform",function(){return z},"important").style("-webkit-transform",y).style("opacity",1)})};return d.nvPointerEventsClass=w,d.options=a.utils.optionsFunc.bind(d),d._options=Object.create({},{duration:{get:function(){return s},set:function(a){s=a}},gravity:{get:function(){return f},set:function(a){f=a}},distance:{get:function(){return g},set:function(a){g=a}},snapDistance:{get:function(){return h},set:function(a){h=a}},classes:{get:function(){return j},set:function(a){j=a}},chartContainer:{get:function(){return k},set:function(a){k=a}},fixedTop:{get:function(){return i},set:function(a){i=a}},enabled:{get:function(){return r},set:function(a){r=a}},hideDelay:{get:function(){return m},set:function(a){m=a}},contentGenerator:{get:function(){return A},set:function(a){A=a}},valueFormatter:{get:function(){return x},set:function(a){x=a}},headerFormatter:{get:function(){return y},set:function(a){y=a}},keyFormatter:{get:function(){return z},set:function(a){z=a}},headerEnabled:{get:function(){return t},set:function(a){t=a}},_isInteractiveLayer:{get:function(){return u},set:function(a){u=!!a}},position:{get:function(){return p},set:function(a){p.left=void 0!==a.left?a.left:p.left,p.top=void 0!==a.top?a.top:p.top}},offset:{get:function(){return q},set:function(a){q.left=void 0!==a.left?a.left:q.left,q.top=void 0!==a.top?a.top:q.top}},hidden:{get:function(){return l},set:function(a){l!=a&&(l=!!a,d())}},data:{get:function(){return e},set:function(a){a.point&&(a.value=a.point.x,a.series=a.series||{},a.series.value=a.point.y,a.series.color=a.point.color||a.series.color),e=a}},tooltipElem:{get:function(){return o},set:function(){}},id:{get:function(){return v},set:function(){}}}),a.utils.initOptions(d),d}}(),a.utils.windowSize=function(){var a={width:640,height:480};return window.innerWidth&&window.innerHeight?(a.width=window.innerWidth,a.height=window.innerHeight,a):"CSS1Compat"==document.compatMode&&document.documentElement&&document.documentElement.offsetWidth?(a.width=document.documentElement.offsetWidth,a.height=document.documentElement.offsetHeight,a):document.body&&document.body.offsetWidth?(a.width=document.body.offsetWidth,a.height=document.body.offsetHeight,a):a},a.utils.windowResize=function(b){return window.addEventListener?window.addEventListener("resize",b):a.log("ERROR: Failed to bind to window.resize with: ",b),{callback:b,clear:function(){window.removeEventListener("resize",b)}}},a.utils.getColor=function(b){if(void 0===b)return a.utils.defaultColor();if(Array.isArray(b)){var c=d3.scale.ordinal().range(b);return function(a,b){var d=void 0===b?a:b;return a.color||c(d)}}return b},a.utils.defaultColor=function(){return a.utils.getColor(d3.scale.category20().range())},a.utils.customTheme=function(a,b,c){b=b||function(a){return a.key},c=c||d3.scale.category20().range();var d=c.length;return function(e){var f=b(e);return"function"==typeof a[f]?a[f]():void 0!==a[f]?a[f]:(d||(d=c.length),d-=1,c[d])}},a.utils.pjax=function(b,c){var d=function(d){d3.html(d,function(d){var e=d3.select(c).node();e.parentNode.replaceChild(d3.select(d).select(c).node(),e),a.utils.pjax(b,c)})};d3.selectAll(b).on("click",function(){history.pushState(this.href,this.textContent,this.href),d(this.href),d3.event.preventDefault()}),d3.select(window).on("popstate",function(){d3.event.state&&d(d3.event.state)})},a.utils.calcApproxTextWidth=function(a){if("function"==typeof a.style&&"function"==typeof a.text){var b=parseInt(a.style("font-size").replace("px",""),10),c=a.text().length;return c*b*.5}return 0},a.utils.NaNtoZero=function(a){return"number"!=typeof a||isNaN(a)||null===a||1/0===a||a===-1/0?0:a},d3.selection.prototype.watchTransition=function(a){var b=[this].concat([].slice.call(arguments,1));return a.transition.apply(a,b)},a.utils.renderWatch=function(b,c){if(!(this instanceof a.utils.renderWatch))return new a.utils.renderWatch(b,c);var d=void 0!==c?c:250,e=[],f=this;this.models=function(a){return a=[].slice.call(arguments,0),a.forEach(function(a){a.__rendered=!1,function(a){a.dispatch.on("renderEnd",function(){a.__rendered=!0,f.renderEnd("model")})}(a),e.indexOf(a)<0&&e.push(a)}),this},this.reset=function(a){void 0!==a&&(d=a),e=[]},this.transition=function(a,b,c){if(b=arguments.length>1?[].slice.call(arguments,1):[],c=b.length>1?b.pop():void 0!==d?d:250,a.__rendered=!1,e.indexOf(a)<0&&e.push(a),0===c)return a.__rendered=!0,a.delay=function(){return this},a.duration=function(){return this},a;a.__rendered=0===a.length?!0:a.every(function(a){return!a.length})?!0:!1;var g=0;return a.transition().duration(c).each(function(){++g}).each("end",function(){0===--g&&(a.__rendered=!0,f.renderEnd.apply(this,b))})},this.renderEnd=function(){e.every(function(a){return a.__rendered})&&(e.forEach(function(a){a.__rendered=!1}),b.renderEnd.apply(this,arguments))}},a.utils.deepExtend=function(b){var c=arguments.length>1?[].slice.call(arguments,1):[];c.forEach(function(c){for(var d in c){var e=b[d]instanceof Array,f="object"==typeof b[d],g="object"==typeof c[d];f&&!e&&g?a.utils.deepExtend(b[d],c[d]):b[d]=c[d]}})},a.utils.state=function(){if(!(this instanceof a.utils.state))return new a.utils.state;var b={},c=function(){},d=function(){return{}},e=null,f=null;this.dispatch=d3.dispatch("change","set"),this.dispatch.on("set",function(a){c(a,!0)}),this.getter=function(a){return d=a,this},this.setter=function(a,b){return b||(b=function(){}),c=function(c,d){a(c),d&&b()},this},this.init=function(b){e=e||{},a.utils.deepExtend(e,b)};var g=function(){var a=d();if(JSON.stringify(a)===JSON.stringify(b))return!1;for(var c in a)void 0===b[c]&&(b[c]={}),b[c]=a[c],f=!0;return!0};this.update=function(){e&&(c(e,!1),e=null),g.call(this)&&this.dispatch.change(b)}},a.utils.optionsFunc=function(a){return a&&d3.map(a).forEach(function(a,b){"function"==typeof this[a]&&this[a](b)}.bind(this)),this},a.utils.calcTicksX=function(b,c){var d=1,e=0;for(e;e<c.length;e+=1){var f=c[e]&&c[e].values?c[e].values.length:0;d=f>d?f:d}return a.log("Requested number of ticks: ",b),a.log("Calculated max values to be: ",d),b=b>d?b=d-1:b,b=1>b?1:b,b=Math.floor(b),a.log("Calculating tick count as: ",b),b},a.utils.calcTicksY=function(b,c){return a.utils.calcTicksX(b,c)},a.utils.initOption=function(a,b){a._calls&&a._calls[b]?a[b]=a._calls[b]:(a[b]=function(c){return arguments.length?(a._overrides[b]=!0,a._options[b]=c,a):a._options[b]},a["_"+b]=function(c){return arguments.length?(a._overrides[b]||(a._options[b]=c),a):a._options[b]})},a.utils.initOptions=function(b){b._overrides=b._overrides||{};var c=Object.getOwnPropertyNames(b._options||{}),d=Object.getOwnPropertyNames(b._calls||{});c=c.concat(d);for(var e in c)a.utils.initOption(b,c[e])},a.utils.inheritOptionsD3=function(a,b,c){a._d3options=c.concat(a._d3options||[]),c.unshift(b),c.unshift(a),d3.rebind.apply(this,c)},a.utils.arrayUnique=function(a){return a.sort().filter(function(b,c){return!c||b!=a[c-1]})},a.utils.symbolMap=d3.map(),a.utils.symbol=function(){function b(b,e){var f=c.call(this,b,e),g=d.call(this,b,e);return-1!==d3.svg.symbolTypes.indexOf(f)?d3.svg.symbol().type(f).size(g)():a.utils.symbolMap.get(f)(g)}var c,d=64;return b.type=function(a){return arguments.length?(c=d3.functor(a),b):c},b.size=function(a){return arguments.length?(d=d3.functor(a),b):d},b},a.utils.inheritOptions=function(b,c){var d=Object.getOwnPropertyNames(c._options||{}),e=Object.getOwnPropertyNames(c._calls||{}),f=c._inherited||[],g=c._d3options||[],h=d.concat(e).concat(f).concat(g);h.unshift(c),h.unshift(b),d3.rebind.apply(this,h),b._inherited=a.utils.arrayUnique(d.concat(e).concat(f).concat(d).concat(b._inherited||[])),b._d3options=a.utils.arrayUnique(g.concat(b._d3options||[]))},a.utils.initSVG=function(a){a.classed({"nvd3-svg":!0})},a.utils.sanitizeHeight=function(a,b){return a||parseInt(b.style("height"),10)||400},a.utils.sanitizeWidth=function(a,b){return a||parseInt(b.style("width"),10)||960},a.utils.availableHeight=function(b,c,d){return a.utils.sanitizeHeight(b,c)-d.top-d.bottom},a.utils.availableWidth=function(b,c,d){return a.utils.sanitizeWidth(b,c)-d.left-d.right},a.utils.noData=function(b,c){var d=b.options(),e=d.margin(),f=d.noData(),g=null==f?["No Data Available."]:[f],h=a.utils.availableHeight(d.height(),c,e),i=a.utils.availableWidth(d.width(),c,e),j=e.left+i/2,k=e.top+h/2;c.selectAll("g").remove();var l=c.selectAll(".nv-noData").data(g);l.enter().append("text").attr("class","nvd3 nv-noData").attr("dy","-.7em").style("text-anchor","middle"),l.attr("x",j).attr("y",k).text(function(a){return a})},a.models.axis=function(){"use strict";function b(g){return s.reset(),g.each(function(b){var g=d3.select(this);a.utils.initSVG(g);var p=g.selectAll("g.nv-wrap.nv-axis").data([b]),q=p.enter().append("g").attr("class","nvd3 nv-wrap nv-axis"),t=(q.append("g"),p.select("g"));null!==n?c.ticks(n):("top"==c.orient()||"bottom"==c.orient())&&c.ticks(Math.abs(d.range()[1]-d.range()[0])/100),t.watchTransition(s,"axis").call(c),r=r||c.scale();var u=c.tickFormat();null==u&&(u=r.tickFormat());var v=t.selectAll("text.nv-axislabel").data([h||null]);v.exit().remove();var w,x,y;switch(c.orient()){case"top":v.enter().append("text").attr("class","nv-axislabel"),y=d.range().length<2?0:2===d.range().length?d.range()[1]:d.range()[d.range().length-1]+(d.range()[1]-d.range()[0]),v.attr("text-anchor","middle").attr("y",0).attr("x",y/2),i&&(x=p.selectAll("g.nv-axisMaxMin").data(d.domain()),x.enter().append("g").attr("class",function(a,b){return["nv-axisMaxMin","nv-axisMaxMin-x",0==b?"nv-axisMin-x":"nv-axisMax-x"].join(" ")}).append("text"),x.exit().remove(),x.attr("transform",function(b){return"translate("+a.utils.NaNtoZero(d(b))+",0)"}).select("text").attr("dy","-0.5em").attr("y",-c.tickPadding()).attr("text-anchor","middle").text(function(a){var b=u(a);return(""+b).match("NaN")?"":b}),x.watchTransition(s,"min-max top").attr("transform",function(b,c){return"translate("+a.utils.NaNtoZero(d.range()[c])+",0)"}));break;case"bottom":w=o+36;var z=30,A=0,B=t.selectAll("g").select("text"),C="";if(j%360){B.each(function(){var a=this.getBoundingClientRect(),b=a.width;A=a.height,b>z&&(z=b)}),C="rotate("+j+" 0,"+(A/2+c.tickPadding())+")";var D=Math.abs(Math.sin(j*Math.PI/180));w=(D?D*z:z)+30,B.attr("transform",C).style("text-anchor",j%360>0?"start":"end")}v.enter().append("text").attr("class","nv-axislabel"),y=d.range().length<2?0:2===d.range().length?d.range()[1]:d.range()[d.range().length-1]+(d.range()[1]-d.range()[0]),v.attr("text-anchor","middle").attr("y",w).attr("x",y/2),i&&(x=p.selectAll("g.nv-axisMaxMin").data([d.domain()[0],d.domain()[d.domain().length-1]]),x.enter().append("g").attr("class",function(a,b){return["nv-axisMaxMin","nv-axisMaxMin-x",0==b?"nv-axisMin-x":"nv-axisMax-x"].join(" ")}).append("text"),x.exit().remove(),x.attr("transform",function(b){return"translate("+a.utils.NaNtoZero(d(b)+(m?d.rangeBand()/2:0))+",0)"}).select("text").attr("dy",".71em").attr("y",c.tickPadding()).attr("transform",C).style("text-anchor",j?j%360>0?"start":"end":"middle").text(function(a){var b=u(a);return(""+b).match("NaN")?"":b}),x.watchTransition(s,"min-max bottom").attr("transform",function(b){return"translate("+a.utils.NaNtoZero(d(b)+(m?d.rangeBand()/2:0))+",0)"})),l&&B.attr("transform",function(a,b){return"translate(0,"+(b%2==0?"0":"12")+")"});break;case"right":v.enter().append("text").attr("class","nv-axislabel"),v.style("text-anchor",k?"middle":"begin").attr("transform",k?"rotate(90)":"").attr("y",k?-Math.max(e.right,f)+12:-10).attr("x",k?d3.max(d.range())/2:c.tickPadding()),i&&(x=p.selectAll("g.nv-axisMaxMin").data(d.domain()),x.enter().append("g").attr("class",function(a,b){return["nv-axisMaxMin","nv-axisMaxMin-y",0==b?"nv-axisMin-y":"nv-axisMax-y"].join(" ")}).append("text").style("opacity",0),x.exit().remove(),x.attr("transform",function(b){return"translate(0,"+a.utils.NaNtoZero(d(b))+")"}).select("text").attr("dy",".32em").attr("y",0).attr("x",c.tickPadding()).style("text-anchor","start").text(function(a){var b=u(a);return(""+b).match("NaN")?"":b}),x.watchTransition(s,"min-max right").attr("transform",function(b,c){return"translate(0,"+a.utils.NaNtoZero(d.range()[c])+")"}).select("text").style("opacity",1));break;case"left":v.enter().append("text").attr("class","nv-axislabel"),v.style("text-anchor",k?"middle":"end").attr("transform",k?"rotate(-90)":"").attr("y",k?-Math.max(e.left,f)+25-(o||0):-10).attr("x",k?-d3.max(d.range())/2:-c.tickPadding()),i&&(x=p.selectAll("g.nv-axisMaxMin").data(d.domain()),x.enter().append("g").attr("class",function(a,b){return["nv-axisMaxMin","nv-axisMaxMin-y",0==b?"nv-axisMin-y":"nv-axisMax-y"].join(" ")}).append("text").style("opacity",0),x.exit().remove(),x.attr("transform",function(b){return"translate(0,"+a.utils.NaNtoZero(r(b))+")"}).select("text").attr("dy",".32em").attr("y",0).attr("x",-c.tickPadding()).attr("text-anchor","end").text(function(a){var b=u(a);return(""+b).match("NaN")?"":b}),x.watchTransition(s,"min-max right").attr("transform",function(b,c){return"translate(0,"+a.utils.NaNtoZero(d.range()[c])+")"}).select("text").style("opacity",1))}if(v.text(function(a){return a}),!i||"left"!==c.orient()&&"right"!==c.orient()||(t.selectAll("g").each(function(a){d3.select(this).select("text").attr("opacity",1),(d(a)<d.range()[1]+10||d(a)>d.range()[0]-10)&&((a>1e-10||-1e-10>a)&&d3.select(this).attr("opacity",0),d3.select(this).select("text").attr("opacity",0))}),d.domain()[0]==d.domain()[1]&&0==d.domain()[0]&&p.selectAll("g.nv-axisMaxMin").style("opacity",function(a,b){return b?0:1})),i&&("top"===c.orient()||"bottom"===c.orient())){var E=[];p.selectAll("g.nv-axisMaxMin").each(function(a,b){try{E.push(b?d(a)-this.getBoundingClientRect().width-4:d(a)+this.getBoundingClientRect().width+4)}catch(c){E.push(b?d(a)-4:d(a)+4)}}),t.selectAll("g").each(function(a){(d(a)<E[0]||d(a)>E[1])&&(a>1e-10||-1e-10>a?d3.select(this).remove():d3.select(this).select("text").remove())})}t.selectAll(".tick").filter(function(a){return!parseFloat(Math.round(1e5*a)/1e6)&&void 0!==a}).classed("zero",!0),r=d.copy()}),s.renderEnd("axis immediate"),b}var c=d3.svg.axis(),d=d3.scale.linear(),e={top:0,right:0,bottom:0,left:0},f=75,g=60,h=null,i=!0,j=0,k=!0,l=!1,m=!1,n=null,o=0,p=250,q=d3.dispatch("renderEnd");c.scale(d).orient("bottom").tickFormat(function(a){return a});var r,s=a.utils.renderWatch(q,p);return b.axis=c,b.dispatch=q,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{axisLabelDistance:{get:function(){return o},set:function(a){o=a}},staggerLabels:{get:function(){return l},set:function(a){l=a}},rotateLabels:{get:function(){return j},set:function(a){j=a}},rotateYLabel:{get:function(){return k},set:function(a){k=a}},showMaxMin:{get:function(){return i},set:function(a){i=a}},axisLabel:{get:function(){return h},set:function(a){h=a}},height:{get:function(){return g},set:function(a){g=a}},ticks:{get:function(){return n},set:function(a){n=a}},width:{get:function(){return f},set:function(a){f=a}},margin:{get:function(){return e},set:function(a){e.top=void 0!==a.top?a.top:e.top,e.right=void 0!==a.right?a.right:e.right,e.bottom=void 0!==a.bottom?a.bottom:e.bottom,e.left=void 0!==a.left?a.left:e.left}},duration:{get:function(){return p},set:function(a){p=a,s.reset(p)}},scale:{get:function(){return d},set:function(e){d=e,c.scale(d),m="function"==typeof d.rangeBands,a.utils.inheritOptionsD3(b,d,["domain","range","rangeBand","rangeBands"])}}}),a.utils.initOptions(b),a.utils.inheritOptionsD3(b,c,["orient","tickValues","tickSubdivide","tickSize","tickPadding","tickFormat"]),a.utils.inheritOptionsD3(b,d,["domain","range","rangeBand","rangeBands"]),b},a.models.boxPlot=function(){"use strict";function b(l){return v.reset(),l.each(function(b){var l=j-i.left-i.right,p=k-i.top-i.bottom;r=d3.select(this),a.utils.initSVG(r),m.domain(c||b.map(function(a,b){return o(a,b)})).rangeBands(e||[0,l],.1);var w=[];if(!d){var x=d3.min(b.map(function(a){var b=[];return b.push(a.values.Q1),a.values.hasOwnProperty("whisker_low")&&null!==a.values.whisker_low&&b.push(a.values.whisker_low),a.values.hasOwnProperty("outliers")&&null!==a.values.outliers&&(b=b.concat(a.values.outliers)),d3.min(b)})),y=d3.max(b.map(function(a){var b=[];return b.push(a.values.Q3),a.values.hasOwnProperty("whisker_high")&&null!==a.values.whisker_high&&b.push(a.values.whisker_high),a.values.hasOwnProperty("outliers")&&null!==a.values.outliers&&(b=b.concat(a.values.outliers)),d3.max(b)}));w=[x,y]}n.domain(d||w),n.range(f||[p,0]),g=g||m,h=h||n.copy().range([n(0),n(0)]);{var z=r.selectAll("g.nv-wrap").data([b]);z.enter().append("g").attr("class","nvd3 nv-wrap")}z.attr("transform","translate("+i.left+","+i.top+")");var A=z.selectAll(".nv-boxplot").data(function(a){return a}),B=A.enter().append("g").style("stroke-opacity",1e-6).style("fill-opacity",1e-6);A.attr("class","nv-boxplot").attr("transform",function(a,b){return"translate("+(m(o(a,b))+.05*m.rangeBand())+", 0)"}).classed("hover",function(a){return a.hover}),A.watchTransition(v,"nv-boxplot: boxplots").style("stroke-opacity",1).style("fill-opacity",.75).delay(function(a,c){return c*t/b.length}).attr("transform",function(a,b){return"translate("+(m(o(a,b))+.05*m.rangeBand())+", 0)"}),A.exit().remove(),B.each(function(a,b){var c=d3.select(this);["low","high"].forEach(function(d){a.values.hasOwnProperty("whisker_"+d)&&null!==a.values["whisker_"+d]&&(c.append("line").style("stroke",a.color?a.color:q(a,b)).attr("class","nv-boxplot-whisker nv-boxplot-"+d),c.append("line").style("stroke",a.color?a.color:q(a,b)).attr("class","nv-boxplot-tick nv-boxplot-"+d))})});var C=A.selectAll(".nv-boxplot-outlier").data(function(a){return a.values.hasOwnProperty("outliers")&&null!==a.values.outliers?a.values.outliers:[]});C.enter().append("circle").style("fill",function(a,b,c){return q(a,c)}).style("stroke",function(a,b,c){return q(a,c)}).on("mouseover",function(a,b,c){d3.select(this).classed("hover",!0),s.elementMouseover({series:{key:a,color:q(a,c)},e:d3.event})}).on("mouseout",function(a,b,c){d3.select(this).classed("hover",!1),s.elementMouseout({series:{key:a,color:q(a,c)},e:d3.event})}).on("mousemove",function(){s.elementMousemove({e:d3.event})}),C.attr("class","nv-boxplot-outlier"),C.watchTransition(v,"nv-boxplot: nv-boxplot-outlier").attr("cx",.45*m.rangeBand()).attr("cy",function(a){return n(a)}).attr("r","3"),C.exit().remove();var D=function(){return null===u?.9*m.rangeBand():Math.min(75,.9*m.rangeBand())},E=function(){return.45*m.rangeBand()-D()/2},F=function(){return.45*m.rangeBand()+D()/2};["low","high"].forEach(function(a){var b="low"===a?"Q1":"Q3";A.select("line.nv-boxplot-whisker.nv-boxplot-"+a).watchTransition(v,"nv-boxplot: boxplots").attr("x1",.45*m.rangeBand()).attr("y1",function(b){return n(b.values["whisker_"+a])}).attr("x2",.45*m.rangeBand()).attr("y2",function(a){return n(a.values[b])}),A.select("line.nv-boxplot-tick.nv-boxplot-"+a).watchTransition(v,"nv-boxplot: boxplots").attr("x1",E).attr("y1",function(b){return n(b.values["whisker_"+a])}).attr("x2",F).attr("y2",function(b){return n(b.values["whisker_"+a])})}),["low","high"].forEach(function(a){B.selectAll(".nv-boxplot-"+a).on("mouseover",function(b,c,d){d3.select(this).classed("hover",!0),s.elementMouseover({series:{key:b.values["whisker_"+a],color:q(b,d)},e:d3.event})}).on("mouseout",function(b,c,d){d3.select(this).classed("hover",!1),s.elementMouseout({series:{key:b.values["whisker_"+a],color:q(b,d)},e:d3.event})}).on("mousemove",function(){s.elementMousemove({e:d3.event})})}),B.append("rect").attr("class","nv-boxplot-box").on("mouseover",function(a,b){d3.select(this).classed("hover",!0),s.elementMouseover({key:a.label,value:a.label,series:[{key:"Q3",value:a.values.Q3,color:a.color||q(a,b)},{key:"Q2",value:a.values.Q2,color:a.color||q(a,b)},{key:"Q1",value:a.values.Q1,color:a.color||q(a,b)}],data:a,index:b,e:d3.event})}).on("mouseout",function(a,b){d3.select(this).classed("hover",!1),s.elementMouseout({key:a.label,value:a.label,series:[{key:"Q3",value:a.values.Q3,color:a.color||q(a,b)},{key:"Q2",value:a.values.Q2,color:a.color||q(a,b)},{key:"Q1",value:a.values.Q1,color:a.color||q(a,b)}],data:a,index:b,e:d3.event})}).on("mousemove",function(){s.elementMousemove({e:d3.event})}),A.select("rect.nv-boxplot-box").watchTransition(v,"nv-boxplot: boxes").attr("y",function(a){return n(a.values.Q3)}).attr("width",D).attr("x",E).attr("height",function(a){return Math.abs(n(a.values.Q3)-n(a.values.Q1))||1}).style("fill",function(a,b){return a.color||q(a,b)}).style("stroke",function(a,b){return a.color||q(a,b)}),B.append("line").attr("class","nv-boxplot-median"),A.select("line.nv-boxplot-median").watchTransition(v,"nv-boxplot: boxplots line").attr("x1",E).attr("y1",function(a){return n(a.values.Q2)}).attr("x2",F).attr("y2",function(a){return n(a.values.Q2)}),g=m.copy(),h=n.copy()}),v.renderEnd("nv-boxplot immediate"),b}var c,d,e,f,g,h,i={top:0,right:0,bottom:0,left:0},j=960,k=500,l=Math.floor(1e4*Math.random()),m=d3.scale.ordinal(),n=d3.scale.linear(),o=function(a){return a.x},p=function(a){return a.y},q=a.utils.defaultColor(),r=null,s=d3.dispatch("elementMouseover","elementMouseout","elementMousemove","renderEnd"),t=250,u=null,v=a.utils.renderWatch(s,t);return b.dispatch=s,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return j},set:function(a){j=a}},height:{get:function(){return k},set:function(a){k=a}},maxBoxWidth:{get:function(){return u},set:function(a){u=a}},x:{get:function(){return o},set:function(a){o=a}},y:{get:function(){return p},set:function(a){p=a}},xScale:{get:function(){return m},set:function(a){m=a}},yScale:{get:function(){return n},set:function(a){n=a}},xDomain:{get:function(){return c},set:function(a){c=a}},yDomain:{get:function(){return d},set:function(a){d=a}},xRange:{get:function(){return e},set:function(a){e=a}},yRange:{get:function(){return f},set:function(a){f=a}},id:{get:function(){return l},set:function(a){l=a}},margin:{get:function(){return i},set:function(a){i.top=void 0!==a.top?a.top:i.top,i.right=void 0!==a.right?a.right:i.right,i.bottom=void 0!==a.bottom?a.bottom:i.bottom,i.left=void 0!==a.left?a.left:i.left}},color:{get:function(){return q},set:function(b){q=a.utils.getColor(b)}},duration:{get:function(){return t},set:function(a){t=a,v.reset(t)}}}),a.utils.initOptions(b),b},a.models.boxPlotChart=function(){"use strict";function b(k){return t.reset(),t.models(e),l&&t.models(f),m&&t.models(g),k.each(function(k){var p=d3.select(this);a.utils.initSVG(p);var t=(i||parseInt(p.style("width"))||960)-h.left-h.right,u=(j||parseInt(p.style("height"))||400)-h.top-h.bottom;if(b.update=function(){r.beforeUpdate(),p.transition().duration(s).call(b)},b.container=this,!(k&&k.length&&k.filter(function(a){return a.values.hasOwnProperty("Q1")&&a.values.hasOwnProperty("Q2")&&a.values.hasOwnProperty("Q3")}).length)){var v=p.selectAll(".nv-noData").data([q]);return v.enter().append("text").attr("class","nvd3 nv-noData").attr("dy","-.7em").style("text-anchor","middle"),v.attr("x",h.left+t/2).attr("y",h.top+u/2).text(function(a){return a}),b}p.selectAll(".nv-noData").remove(),c=e.xScale(),d=e.yScale().clamp(!0);var w=p.selectAll("g.nv-wrap.nv-boxPlotWithAxes").data([k]),x=w.enter().append("g").attr("class","nvd3 nv-wrap nv-boxPlotWithAxes").append("g"),y=x.append("defs"),z=w.select("g");
+x.append("g").attr("class","nv-x nv-axis"),x.append("g").attr("class","nv-y nv-axis").append("g").attr("class","nv-zeroLine").append("line"),x.append("g").attr("class","nv-barsWrap"),z.attr("transform","translate("+h.left+","+h.top+")"),n&&z.select(".nv-y.nv-axis").attr("transform","translate("+t+",0)"),e.width(t).height(u);var A=z.select(".nv-barsWrap").datum(k.filter(function(a){return!a.disabled}));if(A.transition().call(e),y.append("clipPath").attr("id","nv-x-label-clip-"+e.id()).append("rect"),z.select("#nv-x-label-clip-"+e.id()+" rect").attr("width",c.rangeBand()*(o?2:1)).attr("height",16).attr("x",-c.rangeBand()/(o?1:2)),l){f.scale(c).ticks(a.utils.calcTicksX(t/100,k)).tickSize(-u,0),z.select(".nv-x.nv-axis").attr("transform","translate(0,"+d.range()[0]+")"),z.select(".nv-x.nv-axis").call(f);var B=z.select(".nv-x.nv-axis").selectAll("g");o&&B.selectAll("text").attr("transform",function(a,b,c){return"translate(0,"+(c%2==0?"5":"17")+")"})}m&&(g.scale(d).ticks(Math.floor(u/36)).tickSize(-t,0),z.select(".nv-y.nv-axis").call(g)),z.select(".nv-zeroLine line").attr("x1",0).attr("x2",t).attr("y1",d(0)).attr("y2",d(0))}),t.renderEnd("nv-boxplot chart immediate"),b}var c,d,e=a.models.boxPlot(),f=a.models.axis(),g=a.models.axis(),h={top:15,right:10,bottom:50,left:60},i=null,j=null,k=a.utils.getColor(),l=!0,m=!0,n=!1,o=!1,p=a.models.tooltip(),q="No Data Available.",r=d3.dispatch("tooltipShow","tooltipHide","beforeUpdate","renderEnd"),s=250;f.orient("bottom").showMaxMin(!1).tickFormat(function(a){return a}),g.orient(n?"right":"left").tickFormat(d3.format(",.1f")),p.duration(0);var t=a.utils.renderWatch(r,s);return e.dispatch.on("elementMouseover.tooltip",function(a){p.data(a).hidden(!1)}),e.dispatch.on("elementMouseout.tooltip",function(a){p.data(a).hidden(!0)}),e.dispatch.on("elementMousemove.tooltip",function(){p.position({top:d3.event.pageY,left:d3.event.pageX})()}),b.dispatch=r,b.boxplot=e,b.xAxis=f,b.yAxis=g,b.tooltip=p,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return i},set:function(a){i=a}},height:{get:function(){return j},set:function(a){j=a}},staggerLabels:{get:function(){return o},set:function(a){o=a}},showXAxis:{get:function(){return l},set:function(a){l=a}},showYAxis:{get:function(){return m},set:function(a){m=a}},tooltips:{get:function(){return tooltips},set:function(a){tooltips=a}},tooltipContent:{get:function(){return p},set:function(a){p=a}},noData:{get:function(){return q},set:function(a){q=a}},margin:{get:function(){return h},set:function(a){h.top=void 0!==a.top?a.top:h.top,h.right=void 0!==a.right?a.right:h.right,h.bottom=void 0!==a.bottom?a.bottom:h.bottom,h.left=void 0!==a.left?a.left:h.left}},duration:{get:function(){return s},set:function(a){s=a,t.reset(s),e.duration(s),f.duration(s),g.duration(s)}},color:{get:function(){return k},set:function(b){k=a.utils.getColor(b),e.color(k)}},rightAlignYAxis:{get:function(){return n},set:function(a){n=a,g.orient(a?"right":"left")}}}),a.utils.inheritOptions(b,e),a.utils.initOptions(b),b},a.models.bullet=function(){"use strict";function b(d){return d.each(function(b,d){var p=m-c.left-c.right,s=n-c.top-c.bottom;o=d3.select(this),a.utils.initSVG(o);{var t=f.call(this,b,d).slice().sort(d3.descending),u=g.call(this,b,d).slice().sort(d3.descending),v=h.call(this,b,d).slice().sort(d3.descending),w=i.call(this,b,d).slice(),x=j.call(this,b,d).slice(),y=k.call(this,b,d).slice(),z=d3.scale.linear().domain(d3.extent(d3.merge([l,t]))).range(e?[p,0]:[0,p]);this.__chart__||d3.scale.linear().domain([0,1/0]).range(z.range())}this.__chart__=z;var A=d3.min(t),B=d3.max(t),C=t[1],D=o.selectAll("g.nv-wrap.nv-bullet").data([b]),E=D.enter().append("g").attr("class","nvd3 nv-wrap nv-bullet"),F=E.append("g"),G=D.select("g");F.append("rect").attr("class","nv-range nv-rangeMax"),F.append("rect").attr("class","nv-range nv-rangeAvg"),F.append("rect").attr("class","nv-range nv-rangeMin"),F.append("rect").attr("class","nv-measure"),D.attr("transform","translate("+c.left+","+c.top+")");var H=function(a){return Math.abs(z(a)-z(0))},I=function(a){return z(0>a?a:0)};G.select("rect.nv-rangeMax").attr("height",s).attr("width",H(B>0?B:A)).attr("x",I(B>0?B:A)).datum(B>0?B:A),G.select("rect.nv-rangeAvg").attr("height",s).attr("width",H(C)).attr("x",I(C)).datum(C),G.select("rect.nv-rangeMin").attr("height",s).attr("width",H(B)).attr("x",I(B)).attr("width",H(B>0?A:B)).attr("x",I(B>0?A:B)).datum(B>0?A:B),G.select("rect.nv-measure").style("fill",q).attr("height",s/3).attr("y",s/3).attr("width",0>v?z(0)-z(v[0]):z(v[0])-z(0)).attr("x",I(v)).on("mouseover",function(){r.elementMouseover({value:v[0],label:y[0]||"Current",color:d3.select(this).style("fill")})}).on("mousemove",function(){r.elementMousemove({value:v[0],label:y[0]||"Current",color:d3.select(this).style("fill")})}).on("mouseout",function(){r.elementMouseout({value:v[0],label:y[0]||"Current",color:d3.select(this).style("fill")})});var J=s/6,K=u.map(function(a,b){return{value:a,label:x[b]}});F.selectAll("path.nv-markerTriangle").data(K).enter().append("path").attr("class","nv-markerTriangle").attr("transform",function(a){return"translate("+z(a.value)+","+s/2+")"}).attr("d","M0,"+J+"L"+J+","+-J+" "+-J+","+-J+"Z").on("mouseover",function(a){r.elementMouseover({value:a.value,label:a.label||"Previous",color:d3.select(this).style("fill"),pos:[z(a.value),s/2]})}).on("mousemove",function(a){r.elementMousemove({value:a.value,label:a.label||"Previous",color:d3.select(this).style("fill")})}).on("mouseout",function(a){r.elementMouseout({value:a.value,label:a.label||"Previous",color:d3.select(this).style("fill")})}),D.selectAll(".nv-range").on("mouseover",function(a,b){var c=w[b]||(b?1==b?"Mean":"Minimum":"Maximum");r.elementMouseover({value:a,label:c,color:d3.select(this).style("fill")})}).on("mousemove",function(){r.elementMousemove({value:v[0],label:y[0]||"Previous",color:d3.select(this).style("fill")})}).on("mouseout",function(a,b){var c=w[b]||(b?1==b?"Mean":"Minimum":"Maximum");r.elementMouseout({value:a,label:c,color:d3.select(this).style("fill")})})}),b}var c={top:0,right:0,bottom:0,left:0},d="left",e=!1,f=function(a){return a.ranges},g=function(a){return a.markers?a.markers:[0]},h=function(a){return a.measures},i=function(a){return a.rangeLabels?a.rangeLabels:[]},j=function(a){return a.markerLabels?a.markerLabels:[]},k=function(a){return a.measureLabels?a.measureLabels:[]},l=[0],m=380,n=30,o=null,p=null,q=a.utils.getColor(["#1f77b4"]),r=d3.dispatch("elementMouseover","elementMouseout","elementMousemove");return b.dispatch=r,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{ranges:{get:function(){return f},set:function(a){f=a}},markers:{get:function(){return g},set:function(a){g=a}},measures:{get:function(){return h},set:function(a){h=a}},forceX:{get:function(){return l},set:function(a){l=a}},width:{get:function(){return m},set:function(a){m=a}},height:{get:function(){return n},set:function(a){n=a}},tickFormat:{get:function(){return p},set:function(a){p=a}},margin:{get:function(){return c},set:function(a){c.top=void 0!==a.top?a.top:c.top,c.right=void 0!==a.right?a.right:c.right,c.bottom=void 0!==a.bottom?a.bottom:c.bottom,c.left=void 0!==a.left?a.left:c.left}},orient:{get:function(){return d},set:function(a){d=a,e="right"==d||"bottom"==d}},color:{get:function(){return q},set:function(b){q=a.utils.getColor(b)}}}),a.utils.initOptions(b),b},a.models.bulletChart=function(){"use strict";function b(d){return d.each(function(e,o){var p=d3.select(this);a.utils.initSVG(p);var q=a.utils.availableWidth(k,p,g),r=l-g.top-g.bottom;if(b.update=function(){b(d)},b.container=this,!e||!h.call(this,e,o))return a.utils.noData(b,p),b;p.selectAll(".nv-noData").remove();var s=h.call(this,e,o).slice().sort(d3.descending),t=i.call(this,e,o).slice().sort(d3.descending),u=j.call(this,e,o).slice().sort(d3.descending),v=p.selectAll("g.nv-wrap.nv-bulletChart").data([e]),w=v.enter().append("g").attr("class","nvd3 nv-wrap nv-bulletChart"),x=w.append("g"),y=v.select("g");x.append("g").attr("class","nv-bulletWrap"),x.append("g").attr("class","nv-titles"),v.attr("transform","translate("+g.left+","+g.top+")");var z=d3.scale.linear().domain([0,Math.max(s[0],t[0],u[0])]).range(f?[q,0]:[0,q]),A=this.__chart__||d3.scale.linear().domain([0,1/0]).range(z.range());this.__chart__=z;var B=x.select(".nv-titles").append("g").attr("text-anchor","end").attr("transform","translate(-6,"+(l-g.top-g.bottom)/2+")");B.append("text").attr("class","nv-title").text(function(a){return a.title}),B.append("text").attr("class","nv-subtitle").attr("dy","1em").text(function(a){return a.subtitle}),c.width(q).height(r);var C=y.select(".nv-bulletWrap");d3.transition(C).call(c);var D=m||z.tickFormat(q/100),E=y.selectAll("g.nv-tick").data(z.ticks(n?n:q/50),function(a){return this.textContent||D(a)}),F=E.enter().append("g").attr("class","nv-tick").attr("transform",function(a){return"translate("+A(a)+",0)"}).style("opacity",1e-6);F.append("line").attr("y1",r).attr("y2",7*r/6),F.append("text").attr("text-anchor","middle").attr("dy","1em").attr("y",7*r/6).text(D);var G=d3.transition(E).attr("transform",function(a){return"translate("+z(a)+",0)"}).style("opacity",1);G.select("line").attr("y1",r).attr("y2",7*r/6),G.select("text").attr("y",7*r/6),d3.transition(E.exit()).attr("transform",function(a){return"translate("+z(a)+",0)"}).style("opacity",1e-6).remove()}),d3.timer.flush(),b}var c=a.models.bullet(),d=a.models.tooltip(),e="left",f=!1,g={top:5,right:40,bottom:20,left:120},h=function(a){return a.ranges},i=function(a){return a.markers?a.markers:[0]},j=function(a){return a.measures},k=null,l=55,m=null,n=null,o=null,p=d3.dispatch("tooltipShow","tooltipHide");return d.duration(0).headerEnabled(!1),c.dispatch.on("elementMouseover.tooltip",function(a){a.series={key:a.label,value:a.value,color:a.color},d.data(a).hidden(!1)}),c.dispatch.on("elementMouseout.tooltip",function(){d.hidden(!0)}),c.dispatch.on("elementMousemove.tooltip",function(){d.position({top:d3.event.pageY,left:d3.event.pageX})()}),b.bullet=c,b.dispatch=p,b.tooltip=d,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{ranges:{get:function(){return h},set:function(a){h=a}},markers:{get:function(){return i},set:function(a){i=a}},measures:{get:function(){return j},set:function(a){j=a}},width:{get:function(){return k},set:function(a){k=a}},height:{get:function(){return l},set:function(a){l=a}},tickFormat:{get:function(){return m},set:function(a){m=a}},ticks:{get:function(){return n},set:function(a){n=a}},noData:{get:function(){return o},set:function(a){o=a}},tooltips:{get:function(){return d.enabled()},set:function(b){a.deprecated("tooltips","use chart.tooltip.enabled() instead"),d.enabled(!!b)}},tooltipContent:{get:function(){return d.contentGenerator()},set:function(b){a.deprecated("tooltipContent","use chart.tooltip.contentGenerator() instead"),d.contentGenerator(b)}},margin:{get:function(){return g},set:function(a){g.top=void 0!==a.top?a.top:g.top,g.right=void 0!==a.right?a.right:g.right,g.bottom=void 0!==a.bottom?a.bottom:g.bottom,g.left=void 0!==a.left?a.left:g.left}},orient:{get:function(){return e},set:function(a){e=a,f="right"==e||"bottom"==e}}}),a.utils.inheritOptions(b,c),a.utils.initOptions(b),b},a.models.candlestickBar=function(){"use strict";function b(x){return x.each(function(b){c=d3.select(this);var x=a.utils.availableWidth(i,c,h),y=a.utils.availableHeight(j,c,h);a.utils.initSVG(c);var A=x/b[0].values.length*.45;l.domain(d||d3.extent(b[0].values.map(n).concat(t))),l.range(v?f||[.5*x/b[0].values.length,x*(b[0].values.length-.5)/b[0].values.length]:f||[5+A/2,x-A/2-5]),m.domain(e||[d3.min(b[0].values.map(s).concat(u)),d3.max(b[0].values.map(r).concat(u))]).range(g||[y,0]),l.domain()[0]===l.domain()[1]&&l.domain(l.domain()[0]?[l.domain()[0]-.01*l.domain()[0],l.domain()[1]+.01*l.domain()[1]]:[-1,1]),m.domain()[0]===m.domain()[1]&&m.domain(m.domain()[0]?[m.domain()[0]+.01*m.domain()[0],m.domain()[1]-.01*m.domain()[1]]:[-1,1]);var B=d3.select(this).selectAll("g.nv-wrap.nv-candlestickBar").data([b[0].values]),C=B.enter().append("g").attr("class","nvd3 nv-wrap nv-candlestickBar"),D=C.append("defs"),E=C.append("g"),F=B.select("g");E.append("g").attr("class","nv-ticks"),B.attr("transform","translate("+h.left+","+h.top+")"),c.on("click",function(a,b){z.chartClick({data:a,index:b,pos:d3.event,id:k})}),D.append("clipPath").attr("id","nv-chart-clip-path-"+k).append("rect"),B.select("#nv-chart-clip-path-"+k+" rect").attr("width",x).attr("height",y),F.attr("clip-path",w?"url(#nv-chart-clip-path-"+k+")":"");var G=B.select(".nv-ticks").selectAll(".nv-tick").data(function(a){return a});G.exit().remove();{var H=G.enter().append("g").attr("class",function(a,b,c){return(p(a,b)>q(a,b)?"nv-tick negative":"nv-tick positive")+" nv-tick-"+c+"-"+b});H.append("line").attr("class","nv-candlestick-lines").attr("transform",function(a,b){return"translate("+l(n(a,b))+",0)"}).attr("x1",0).attr("y1",function(a,b){return m(r(a,b))}).attr("x2",0).attr("y2",function(a,b){return m(s(a,b))}),H.append("rect").attr("class","nv-candlestick-rects nv-bars").attr("transform",function(a,b){return"translate("+(l(n(a,b))-A/2)+","+(m(o(a,b))-(p(a,b)>q(a,b)?m(q(a,b))-m(p(a,b)):0))+")"}).attr("x",0).attr("y",0).attr("width",A).attr("height",function(a,b){var c=p(a,b),d=q(a,b);return c>d?m(d)-m(c):m(c)-m(d)})}c.selectAll(".nv-candlestick-lines").transition().attr("transform",function(a,b){return"translate("+l(n(a,b))+",0)"}).attr("x1",0).attr("y1",function(a,b){return m(r(a,b))}).attr("x2",0).attr("y2",function(a,b){return m(s(a,b))}),c.selectAll(".nv-candlestick-rects").transition().attr("transform",function(a,b){return"translate("+(l(n(a,b))-A/2)+","+(m(o(a,b))-(p(a,b)>q(a,b)?m(q(a,b))-m(p(a,b)):0))+")"}).attr("x",0).attr("y",0).attr("width",A).attr("height",function(a,b){var c=p(a,b),d=q(a,b);return c>d?m(d)-m(c):m(c)-m(d)})}),b}var c,d,e,f,g,h={top:0,right:0,bottom:0,left:0},i=null,j=null,k=Math.floor(1e4*Math.random()),l=d3.scale.linear(),m=d3.scale.linear(),n=function(a){return a.x},o=function(a){return a.y},p=function(a){return a.open},q=function(a){return a.close},r=function(a){return a.high},s=function(a){return a.low},t=[],u=[],v=!1,w=!0,x=a.utils.defaultColor(),y=!1,z=d3.dispatch("tooltipShow","tooltipHide","stateChange","changeState","renderEnd","chartClick","elementClick","elementDblClick","elementMouseover","elementMouseout","elementMousemove");return b.highlightPoint=function(a,d){b.clearHighlights(),c.select(".nv-candlestickBar .nv-tick-0-"+a).classed("hover",d)},b.clearHighlights=function(){c.select(".nv-candlestickBar .nv-tick.hover").classed("hover",!1)},b.dispatch=z,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return i},set:function(a){i=a}},height:{get:function(){return j},set:function(a){j=a}},xScale:{get:function(){return l},set:function(a){l=a}},yScale:{get:function(){return m},set:function(a){m=a}},xDomain:{get:function(){return d},set:function(a){d=a}},yDomain:{get:function(){return e},set:function(a){e=a}},xRange:{get:function(){return f},set:function(a){f=a}},yRange:{get:function(){return g},set:function(a){g=a}},forceX:{get:function(){return t},set:function(a){t=a}},forceY:{get:function(){return u},set:function(a){u=a}},padData:{get:function(){return v},set:function(a){v=a}},clipEdge:{get:function(){return w},set:function(a){w=a}},id:{get:function(){return k},set:function(a){k=a}},interactive:{get:function(){return y},set:function(a){y=a}},x:{get:function(){return n},set:function(a){n=a}},y:{get:function(){return o},set:function(a){o=a}},open:{get:function(){return p()},set:function(a){p=a}},close:{get:function(){return q()},set:function(a){q=a}},high:{get:function(){return r},set:function(a){r=a}},low:{get:function(){return s},set:function(a){s=a}},margin:{get:function(){return h},set:function(a){h.top=void 0!=a.top?a.top:h.top,h.right=void 0!=a.right?a.right:h.right,h.bottom=void 0!=a.bottom?a.bottom:h.bottom,h.left=void 0!=a.left?a.left:h.left}},color:{get:function(){return x},set:function(b){x=a.utils.getColor(b)}}}),a.utils.initOptions(b),b},a.models.cumulativeLineChart=function(){"use strict";function b(l){return H.reset(),H.models(f),r&&H.models(g),s&&H.models(h),l.each(function(l){function A(){d3.select(b.container).style("cursor","ew-resize")}function E(){G.x=d3.event.x,G.i=Math.round(F.invert(G.x)),K()}function H(){d3.select(b.container).style("cursor","auto"),y.index=G.i,C.stateChange(y)}function K(){bb.data([G]);var a=b.duration();b.duration(0),b.update(),b.duration(a)}var L=d3.select(this);a.utils.initSVG(L),L.classed("nv-chart-"+x,!0);var M=this,N=a.utils.availableWidth(o,L,m),O=a.utils.availableHeight(p,L,m);if(b.update=function(){0===D?L.call(b):L.transition().duration(D).call(b)},b.container=this,y.setter(J(l),b.update).getter(I(l)).update(),y.disabled=l.map(function(a){return!!a.disabled}),!z){var P;z={};for(P in y)z[P]=y[P]instanceof Array?y[P].slice(0):y[P]}var Q=d3.behavior.drag().on("dragstart",A).on("drag",E).on("dragend",H);if(!(l&&l.length&&l.filter(function(a){return a.values.length}).length))return a.utils.noData(b,L),b;if(L.selectAll(".nv-noData").remove(),d=f.xScale(),e=f.yScale(),w)f.yDomain(null);else{var R=l.filter(function(a){return!a.disabled}).map(function(a){var b=d3.extent(a.values,f.y());return b[0]<-.95&&(b[0]=-.95),[(b[0]-b[1])/(1+b[1]),(b[1]-b[0])/(1+b[0])]}),S=[d3.min(R,function(a){return a[0]}),d3.max(R,function(a){return a[1]})];f.yDomain(S)}F.domain([0,l[0].values.length-1]).range([0,N]).clamp(!0);var l=c(G.i,l),T=v?"none":"all",U=L.selectAll("g.nv-wrap.nv-cumulativeLine").data([l]),V=U.enter().append("g").attr("class","nvd3 nv-wrap nv-cumulativeLine").append("g"),W=U.select("g");if(V.append("g").attr("class","nv-interactive"),V.append("g").attr("class","nv-x nv-axis").style("pointer-events","none"),V.append("g").attr("class","nv-y nv-axis"),V.append("g").attr("class","nv-background"),V.append("g").attr("class","nv-linesWrap").style("pointer-events",T),V.append("g").attr("class","nv-avgLinesWrap").style("pointer-events","none"),V.append("g").attr("class","nv-legendWrap"),V.append("g").attr("class","nv-controlsWrap"),q&&(i.width(N),W.select(".nv-legendWrap").datum(l).call(i),m.top!=i.height()&&(m.top=i.height(),O=a.utils.availableHeight(p,L,m)),W.select(".nv-legendWrap").attr("transform","translate(0,"+-m.top+")")),u){var X=[{key:"Re-scale y-axis",disabled:!w}];j.width(140).color(["#444","#444","#444"]).rightAlign(!1).margin({top:5,right:0,bottom:5,left:20}),W.select(".nv-controlsWrap").datum(X).attr("transform","translate(0,"+-m.top+")").call(j)}U.attr("transform","translate("+m.left+","+m.top+")"),t&&W.select(".nv-y.nv-axis").attr("transform","translate("+N+",0)");var Y=l.filter(function(a){return a.tempDisabled});U.select(".tempDisabled").remove(),Y.length&&U.append("text").attr("class","tempDisabled").attr("x",N/2).attr("y","-.71em").style("text-anchor","end").text(Y.map(function(a){return a.key}).join(", ")+" values cannot be calculated for this time period."),v&&(k.width(N).height(O).margin({left:m.left,top:m.top}).svgContainer(L).xScale(d),U.select(".nv-interactive").call(k)),V.select(".nv-background").append("rect"),W.select(".nv-background rect").attr("width",N).attr("height",O),f.y(function(a){return a.display.y}).width(N).height(O).color(l.map(function(a,b){return a.color||n(a,b)}).filter(function(a,b){return!l[b].disabled&&!l[b].tempDisabled}));var Z=W.select(".nv-linesWrap").datum(l.filter(function(a){return!a.disabled&&!a.tempDisabled}));Z.call(f),l.forEach(function(a,b){a.seriesIndex=b});var $=l.filter(function(a){return!a.disabled&&!!B(a)}),_=W.select(".nv-avgLinesWrap").selectAll("line").data($,function(a){return a.key}),ab=function(a){var b=e(B(a));return 0>b?0:b>O?O:b};_.enter().append("line").style("stroke-width",2).style("stroke-dasharray","10,10").style("stroke",function(a){return f.color()(a,a.seriesIndex)}).attr("x1",0).attr("x2",N).attr("y1",ab).attr("y2",ab),_.style("stroke-opacity",function(a){var b=e(B(a));return 0>b||b>O?0:1}).attr("x1",0).attr("x2",N).attr("y1",ab).attr("y2",ab),_.exit().remove();var bb=Z.selectAll(".nv-indexLine").data([G]);bb.enter().append("rect").attr("class","nv-indexLine").attr("width",3).attr("x",-2).attr("fill","red").attr("fill-opacity",.5).style("pointer-events","all").call(Q),bb.attr("transform",function(a){return"translate("+F(a.i)+",0)"}).attr("height",O),r&&(g.scale(d)._ticks(a.utils.calcTicksX(N/70,l)).tickSize(-O,0),W.select(".nv-x.nv-axis").attr("transform","translate(0,"+e.range()[0]+")"),W.select(".nv-x.nv-axis").call(g)),s&&(h.scale(e)._ticks(a.utils.calcTicksY(O/36,l)).tickSize(-N,0),W.select(".nv-y.nv-axis").call(h)),W.select(".nv-background rect").on("click",function(){G.x=d3.mouse(this)[0],G.i=Math.round(F.invert(G.x)),y.index=G.i,C.stateChange(y),K()}),f.dispatch.on("elementClick",function(a){G.i=a.pointIndex,G.x=F(G.i),y.index=G.i,C.stateChange(y),K()}),j.dispatch.on("legendClick",function(a){a.disabled=!a.disabled,w=!a.disabled,y.rescaleY=w,C.stateChange(y),b.update()}),i.dispatch.on("stateChange",function(a){for(var c in a)y[c]=a[c];C.stateChange(y),b.update()}),k.dispatch.on("elementMousemove",function(c){f.clearHighlights();var d,e,i,j=[];if(l.filter(function(a,b){return a.seriesIndex=b,!a.disabled}).forEach(function(g,h){e=a.interactiveBisect(g.values,c.pointXValue,b.x()),f.highlightPoint(h,e,!0);var k=g.values[e];"undefined"!=typeof k&&("undefined"==typeof d&&(d=k),"undefined"==typeof i&&(i=b.xScale()(b.x()(k,e))),j.push({key:g.key,value:b.y()(k,e),color:n(g,g.seriesIndex)}))}),j.length>2){var o=b.yScale().invert(c.mouseY),p=Math.abs(b.yScale().domain()[0]-b.yScale().domain()[1]),q=.03*p,r=a.nearestValueIndex(j.map(function(a){return a.value}),o,q);null!==r&&(j[r].highlight=!0)}var s=g.tickFormat()(b.x()(d,e),e);k.tooltip.position({left:i+m.left,top:c.mouseY+m.top}).chartContainer(M.parentNode).valueFormatter(function(a){return h.tickFormat()(a)}).data({value:s,series:j})(),k.renderGuideLine(i)}),k.dispatch.on("elementMouseout",function(){f.clearHighlights()}),C.on("changeState",function(a){"undefined"!=typeof a.disabled&&(l.forEach(function(b,c){b.disabled=a.disabled[c]}),y.disabled=a.disabled),"undefined"!=typeof a.index&&(G.i=a.index,G.x=F(G.i),y.index=a.index,bb.data([G])),"undefined"!=typeof a.rescaleY&&(w=a.rescaleY),b.update()})}),H.renderEnd("cumulativeLineChart immediate"),b}function c(a,b){return K||(K=f.y()),b.map(function(b){if(!b.values)return b;var c=b.values[a];if(null==c)return b;var d=K(c,a);return-.95>d&&!E?(b.tempDisabled=!0,b):(b.tempDisabled=!1,b.values=b.values.map(function(a,b){return a.display={y:(K(a,b)-d)/(1+d)},a}),b)})}var d,e,f=a.models.line(),g=a.models.axis(),h=a.models.axis(),i=a.models.legend(),j=a.models.legend(),k=a.interactiveGuideline(),l=a.models.tooltip(),m={top:30,right:30,bottom:50,left:60},n=a.utils.defaultColor(),o=null,p=null,q=!0,r=!0,s=!0,t=!1,u=!0,v=!1,w=!0,x=f.id(),y=a.utils.state(),z=null,A=null,B=function(a){return a.average},C=d3.dispatch("stateChange","changeState","renderEnd"),D=250,E=!1;y.index=0,y.rescaleY=w,g.orient("bottom").tickPadding(7),h.orient(t?"right":"left"),l.valueFormatter(function(a,b){return h.tickFormat()(a,b)}).headerFormatter(function(a,b){return g.tickFormat()(a,b)}),j.updateState(!1);var F=d3.scale.linear(),G={i:0,x:0},H=a.utils.renderWatch(C,D),I=function(a){return function(){return{active:a.map(function(a){return!a.disabled}),index:G.i,rescaleY:w}}},J=function(a){return function(b){void 0!==b.index&&(G.i=b.index),void 0!==b.rescaleY&&(w=b.rescaleY),void 0!==b.active&&a.forEach(function(a,c){a.disabled=!b.active[c]})}};f.dispatch.on("elementMouseover.tooltip",function(a){var c={x:b.x()(a.point),y:b.y()(a.point),color:a.point.color};a.point=c,l.data(a).position(a.pos).hidden(!1)}),f.dispatch.on("elementMouseout.tooltip",function(){l.hidden(!0)});var K=null;return b.dispatch=C,b.lines=f,b.legend=i,b.controls=j,b.xAxis=g,b.yAxis=h,b.interactiveLayer=k,b.state=y,b.tooltip=l,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return o},set:function(a){o=a}},height:{get:function(){return p},set:function(a){p=a}},rescaleY:{get:function(){return w},set:function(a){w=a}},showControls:{get:function(){return u},set:function(a){u=a}},showLegend:{get:function(){return q},set:function(a){q=a}},average:{get:function(){return B},set:function(a){B=a}},defaultState:{get:function(){return z},set:function(a){z=a}},noData:{get:function(){return A},set:function(a){A=a}},showXAxis:{get:function(){return r},set:function(a){r=a}},showYAxis:{get:function(){return s},set:function(a){s=a}},noErrorCheck:{get:function(){return E},set:function(a){E=a}},tooltips:{get:function(){return l.enabled()},set:function(b){a.deprecated("tooltips","use chart.tooltip.enabled() instead"),l.enabled(!!b)}},tooltipContent:{get:function(){return l.contentGenerator()},set:function(b){a.deprecated("tooltipContent","use chart.tooltip.contentGenerator() instead"),l.contentGenerator(b)}},margin:{get:function(){return m},set:function(a){m.top=void 0!==a.top?a.top:m.top,m.right=void 0!==a.right?a.right:m.right,m.bottom=void 0!==a.bottom?a.bottom:m.bottom,m.left=void 0!==a.left?a.left:m.left}},color:{get:function(){return n},set:function(b){n=a.utils.getColor(b),i.color(n)}},useInteractiveGuideline:{get:function(){return v},set:function(a){v=a,a===!0&&(b.interactive(!1),b.useVoronoi(!1))}},rightAlignYAxis:{get:function(){return t},set:function(a){t=a,h.orient(a?"right":"left")}},duration:{get:function(){return D},set:function(a){D=a,f.duration(D),g.duration(D),h.duration(D),H.reset(D)}}}),a.utils.inheritOptions(b,f),a.utils.initOptions(b),b},a.models.discreteBar=function(){"use strict";function b(m){return y.reset(),m.each(function(b){var m=k-j.left-j.right,x=l-j.top-j.bottom;c=d3.select(this),a.utils.initSVG(c),b.forEach(function(a,b){a.values.forEach(function(a){a.series=b})});var z=d&&e?[]:b.map(function(a){return a.values.map(function(a,b){return{x:p(a,b),y:q(a,b),y0:a.y0}})});n.domain(d||d3.merge(z).map(function(a){return a.x})).rangeBands(f||[0,m],.1),o.domain(e||d3.extent(d3.merge(z).map(function(a){return a.y}).concat(r))),o.range(t?g||[x-(o.domain()[0]<0?12:0),o.domain()[1]>0?12:0]:g||[x,0]),h=h||n,i=i||o.copy().range([o(0),o(0)]);{var A=c.selectAll("g.nv-wrap.nv-discretebar").data([b]),B=A.enter().append("g").attr("class","nvd3 nv-wrap nv-discretebar"),C=B.append("g");A.select("g")}C.append("g").attr("class","nv-groups"),A.attr("transform","translate("+j.left+","+j.top+")");var D=A.select(".nv-groups").selectAll(".nv-group").data(function(a){return a},function(a){return a.key});D.enter().append("g").style("stroke-opacity",1e-6).style("fill-opacity",1e-6),D.exit().watchTransition(y,"discreteBar: exit groups").style("stroke-opacity",1e-6).style("fill-opacity",1e-6).remove(),D.attr("class",function(a,b){return"nv-group nv-series-"+b}).classed("hover",function(a){return a.hover}),D.watchTransition(y,"discreteBar: groups").style("stroke-opacity",1).style("fill-opacity",.75);var E=D.selectAll("g.nv-bar").data(function(a){return a.values});E.exit().remove();var F=E.enter().append("g").attr("transform",function(a,b){return"translate("+(n(p(a,b))+.05*n.rangeBand())+", "+o(0)+")"}).on("mouseover",function(a,b){d3.select(this).classed("hover",!0),v.elementMouseover({data:a,index:b,color:d3.select(this).style("fill")})}).on("mouseout",function(a,b){d3.select(this).classed("hover",!1),v.elementMouseout({data:a,index:b,color:d3.select(this).style("fill")})}).on("mousemove",function(a,b){v.elementMousemove({data:a,index:b,color:d3.select(this).style("fill")})}).on("click",function(a,b){v.elementClick({data:a,index:b,color:d3.select(this).style("fill")}),d3.event.stopPropagation()}).on("dblclick",function(a,b){v.elementDblClick({data:a,index:b,color:d3.select(this).style("fill")}),d3.event.stopPropagation()});F.append("rect").attr("height",0).attr("width",.9*n.rangeBand()/b.length),t?(F.append("text").attr("text-anchor","middle"),E.select("text").text(function(a,b){return u(q(a,b))}).watchTransition(y,"discreteBar: bars text").attr("x",.9*n.rangeBand()/2).attr("y",function(a,b){return q(a,b)<0?o(q(a,b))-o(0)+12:-4})):E.selectAll("text").remove(),E.attr("class",function(a,b){return q(a,b)<0?"nv-bar negative":"nv-bar positive"}).style("fill",function(a,b){return a.color||s(a,b)}).style("stroke",function(a,b){return a.color||s(a,b)}).select("rect").attr("class",w).watchTransition(y,"discreteBar: bars rect").attr("width",.9*n.rangeBand()/b.length),E.watchTransition(y,"discreteBar: bars").attr("transform",function(a,b){var c=n(p(a,b))+.05*n.rangeBand(),d=q(a,b)<0?o(0):o(0)-o(q(a,b))<1?o(0)-1:o(q(a,b));return"translate("+c+", "+d+")"}).select("rect").attr("height",function(a,b){return Math.max(Math.abs(o(q(a,b))-o(e&&e[0]||0))||1)}),h=n.copy(),i=o.copy()}),y.renderEnd("discreteBar immediate"),b}var c,d,e,f,g,h,i,j={top:0,right:0,bottom:0,left:0},k=960,l=500,m=Math.floor(1e4*Math.random()),n=d3.scale.ordinal(),o=d3.scale.linear(),p=function(a){return a.x},q=function(a){return a.y},r=[0],s=a.utils.defaultColor(),t=!1,u=d3.format(",.2f"),v=d3.dispatch("chartClick","elementClick","elementDblClick","elementMouseover","elementMouseout","elementMousemove","renderEnd"),w="discreteBar",x=250,y=a.utils.renderWatch(v,x);return b.dispatch=v,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return k},set:function(a){k=a}},height:{get:function(){return l},set:function(a){l=a}},forceY:{get:function(){return r},set:function(a){r=a}},showValues:{get:function(){return t},set:function(a){t=a}},x:{get:function(){return p},set:function(a){p=a}},y:{get:function(){return q},set:function(a){q=a}},xScale:{get:function(){return n},set:function(a){n=a}},yScale:{get:function(){return o},set:function(a){o=a}},xDomain:{get:function(){return d},set:function(a){d=a}},yDomain:{get:function(){return e},set:function(a){e=a}},xRange:{get:function(){return f},set:function(a){f=a}},yRange:{get:function(){return g},set:function(a){g=a}},valueFormat:{get:function(){return u},set:function(a){u=a}},id:{get:function(){return m},set:function(a){m=a}},rectClass:{get:function(){return w},set:function(a){w=a}},margin:{get:function(){return j},set:function(a){j.top=void 0!==a.top?a.top:j.top,j.right=void 0!==a.right?a.right:j.right,j.bottom=void 0!==a.bottom?a.bottom:j.bottom,j.left=void 0!==a.left?a.left:j.left}},color:{get:function(){return s},set:function(b){s=a.utils.getColor(b)}},duration:{get:function(){return x},set:function(a){x=a,y.reset(x)}}}),a.utils.initOptions(b),b},a.models.discreteBarChart=function(){"use strict";function b(h){return t.reset(),t.models(e),m&&t.models(f),n&&t.models(g),h.each(function(h){var l=d3.select(this);a.utils.initSVG(l);var q=a.utils.availableWidth(j,l,i),t=a.utils.availableHeight(k,l,i);if(b.update=function(){r.beforeUpdate(),l.transition().duration(s).call(b)},b.container=this,!(h&&h.length&&h.filter(function(a){return a.values.length}).length))return a.utils.noData(b,l),b;l.selectAll(".nv-noData").remove(),c=e.xScale(),d=e.yScale().clamp(!0);var u=l.selectAll("g.nv-wrap.nv-discreteBarWithAxes").data([h]),v=u.enter().append("g").attr("class","nvd3 nv-wrap nv-discreteBarWithAxes").append("g"),w=v.append("defs"),x=u.select("g");v.append("g").attr("class","nv-x nv-axis"),v.append("g").attr("class","nv-y nv-axis").append("g").attr("class","nv-zeroLine").append("line"),v.append("g").attr("class","nv-barsWrap"),x.attr("transform","translate("+i.left+","+i.top+")"),o&&x.select(".nv-y.nv-axis").attr("transform","translate("+q+",0)"),e.width(q).height(t);var y=x.select(".nv-barsWrap").datum(h.filter(function(a){return!a.disabled}));if(y.transition().call(e),w.append("clipPath").attr("id","nv-x-label-clip-"+e.id()).append("rect"),x.select("#nv-x-label-clip-"+e.id()+" rect").attr("width",c.rangeBand()*(p?2:1)).attr("height",16).attr("x",-c.rangeBand()/(p?1:2)),m){f.scale(c)._ticks(a.utils.calcTicksX(q/100,h)).tickSize(-t,0),x.select(".nv-x.nv-axis").attr("transform","translate(0,"+(d.range()[0]+(e.showValues()&&d.domain()[0]<0?16:0))+")"),x.select(".nv-x.nv-axis").call(f);
+var z=x.select(".nv-x.nv-axis").selectAll("g");p&&z.selectAll("text").attr("transform",function(a,b,c){return"translate(0,"+(c%2==0?"5":"17")+")"})}n&&(g.scale(d)._ticks(a.utils.calcTicksY(t/36,h)).tickSize(-q,0),x.select(".nv-y.nv-axis").call(g)),x.select(".nv-zeroLine line").attr("x1",0).attr("x2",q).attr("y1",d(0)).attr("y2",d(0))}),t.renderEnd("discreteBar chart immediate"),b}var c,d,e=a.models.discreteBar(),f=a.models.axis(),g=a.models.axis(),h=a.models.tooltip(),i={top:15,right:10,bottom:50,left:60},j=null,k=null,l=a.utils.getColor(),m=!0,n=!0,o=!1,p=!1,q=null,r=d3.dispatch("beforeUpdate","renderEnd"),s=250;f.orient("bottom").showMaxMin(!1).tickFormat(function(a){return a}),g.orient(o?"right":"left").tickFormat(d3.format(",.1f")),h.duration(0).headerEnabled(!1).valueFormatter(function(a,b){return g.tickFormat()(a,b)}).keyFormatter(function(a,b){return f.tickFormat()(a,b)});var t=a.utils.renderWatch(r,s);return e.dispatch.on("elementMouseover.tooltip",function(a){a.series={key:b.x()(a.data),value:b.y()(a.data),color:a.color},h.data(a).hidden(!1)}),e.dispatch.on("elementMouseout.tooltip",function(){h.hidden(!0)}),e.dispatch.on("elementMousemove.tooltip",function(){h.position({top:d3.event.pageY,left:d3.event.pageX})()}),b.dispatch=r,b.discretebar=e,b.xAxis=f,b.yAxis=g,b.tooltip=h,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return j},set:function(a){j=a}},height:{get:function(){return k},set:function(a){k=a}},staggerLabels:{get:function(){return p},set:function(a){p=a}},showXAxis:{get:function(){return m},set:function(a){m=a}},showYAxis:{get:function(){return n},set:function(a){n=a}},noData:{get:function(){return q},set:function(a){q=a}},tooltips:{get:function(){return h.enabled()},set:function(b){a.deprecated("tooltips","use chart.tooltip.enabled() instead"),h.enabled(!!b)}},tooltipContent:{get:function(){return h.contentGenerator()},set:function(b){a.deprecated("tooltipContent","use chart.tooltip.contentGenerator() instead"),h.contentGenerator(b)}},margin:{get:function(){return i},set:function(a){i.top=void 0!==a.top?a.top:i.top,i.right=void 0!==a.right?a.right:i.right,i.bottom=void 0!==a.bottom?a.bottom:i.bottom,i.left=void 0!==a.left?a.left:i.left}},duration:{get:function(){return s},set:function(a){s=a,t.reset(s),e.duration(s),f.duration(s),g.duration(s)}},color:{get:function(){return l},set:function(b){l=a.utils.getColor(b),e.color(l)}},rightAlignYAxis:{get:function(){return o},set:function(a){o=a,g.orient(a?"right":"left")}}}),a.utils.inheritOptions(b,e),a.utils.initOptions(b),b},a.models.distribution=function(){"use strict";function b(k){return m.reset(),k.each(function(b){var k=(e-("x"===g?d.left+d.right:d.top+d.bottom),"x"==g?"y":"x"),l=d3.select(this);a.utils.initSVG(l),c=c||j;var n=l.selectAll("g.nv-distribution").data([b]),o=n.enter().append("g").attr("class","nvd3 nv-distribution"),p=(o.append("g"),n.select("g"));n.attr("transform","translate("+d.left+","+d.top+")");var q=p.selectAll("g.nv-dist").data(function(a){return a},function(a){return a.key});q.enter().append("g"),q.attr("class",function(a,b){return"nv-dist nv-series-"+b}).style("stroke",function(a,b){return i(a,b)});var r=q.selectAll("line.nv-dist"+g).data(function(a){return a.values});r.enter().append("line").attr(g+"1",function(a,b){return c(h(a,b))}).attr(g+"2",function(a,b){return c(h(a,b))}),m.transition(q.exit().selectAll("line.nv-dist"+g),"dist exit").attr(g+"1",function(a,b){return j(h(a,b))}).attr(g+"2",function(a,b){return j(h(a,b))}).style("stroke-opacity",0).remove(),r.attr("class",function(a,b){return"nv-dist"+g+" nv-dist"+g+"-"+b}).attr(k+"1",0).attr(k+"2",f),m.transition(r,"dist").attr(g+"1",function(a,b){return j(h(a,b))}).attr(g+"2",function(a,b){return j(h(a,b))}),c=j.copy()}),m.renderEnd("distribution immediate"),b}var c,d={top:0,right:0,bottom:0,left:0},e=400,f=8,g="x",h=function(a){return a[g]},i=a.utils.defaultColor(),j=d3.scale.linear(),k=250,l=d3.dispatch("renderEnd"),m=a.utils.renderWatch(l,k);return b.options=a.utils.optionsFunc.bind(b),b.dispatch=l,b.margin=function(a){return arguments.length?(d.top="undefined"!=typeof a.top?a.top:d.top,d.right="undefined"!=typeof a.right?a.right:d.right,d.bottom="undefined"!=typeof a.bottom?a.bottom:d.bottom,d.left="undefined"!=typeof a.left?a.left:d.left,b):d},b.width=function(a){return arguments.length?(e=a,b):e},b.axis=function(a){return arguments.length?(g=a,b):g},b.size=function(a){return arguments.length?(f=a,b):f},b.getData=function(a){return arguments.length?(h=d3.functor(a),b):h},b.scale=function(a){return arguments.length?(j=a,b):j},b.color=function(c){return arguments.length?(i=a.utils.getColor(c),b):i},b.duration=function(a){return arguments.length?(k=a,m.reset(k),b):k},b},a.models.furiousLegend=function(){"use strict";function b(p){function q(a,b){return"furious"!=o?"#000":m?a.disengaged?g(a,b):"#fff":m?void 0:a.disabled?g(a,b):"#fff"}function r(a,b){return m&&"furious"==o?a.disengaged?"#fff":g(a,b):a.disabled?"#fff":g(a,b)}return p.each(function(b){var p=d-c.left-c.right,s=d3.select(this);a.utils.initSVG(s);var t=s.selectAll("g.nv-legend").data([b]),u=(t.enter().append("g").attr("class","nvd3 nv-legend").append("g"),t.select("g"));t.attr("transform","translate("+c.left+","+c.top+")");var v,w=u.selectAll(".nv-series").data(function(a){return"furious"!=o?a:a.filter(function(a){return m?!0:!a.disengaged})}),x=w.enter().append("g").attr("class","nv-series");if("classic"==o)x.append("circle").style("stroke-width",2).attr("class","nv-legend-symbol").attr("r",5),v=w.select("circle");else if("furious"==o){x.append("rect").style("stroke-width",2).attr("class","nv-legend-symbol").attr("rx",3).attr("ry",3),v=w.select("rect"),x.append("g").attr("class","nv-check-box").property("innerHTML",'<path d="M0.5,5 L22.5,5 L22.5,26.5 L0.5,26.5 L0.5,5 Z" class="nv-box"></path><path d="M5.5,12.8618467 L11.9185089,19.2803556 L31,0.198864511" class="nv-check"></path>').attr("transform","translate(-10,-8)scale(0.5)");var y=w.select(".nv-check-box");y.each(function(a,b){d3.select(this).selectAll("path").attr("stroke",q(a,b))})}x.append("text").attr("text-anchor","start").attr("class","nv-legend-text").attr("dy",".32em").attr("dx","8");var z=w.select("text.nv-legend-text");w.on("mouseover",function(a,b){n.legendMouseover(a,b)}).on("mouseout",function(a,b){n.legendMouseout(a,b)}).on("click",function(a,b){n.legendClick(a,b);var c=w.data();if(k){if("classic"==o)l?(c.forEach(function(a){a.disabled=!0}),a.disabled=!1):(a.disabled=!a.disabled,c.every(function(a){return a.disabled})&&c.forEach(function(a){a.disabled=!1}));else if("furious"==o)if(m)a.disengaged=!a.disengaged,a.userDisabled=void 0==a.userDisabled?!!a.disabled:a.userDisabled,a.disabled=a.disengaged||a.userDisabled;else if(!m){a.disabled=!a.disabled,a.userDisabled=a.disabled;var d=c.filter(function(a){return!a.disengaged});d.every(function(a){return a.userDisabled})&&c.forEach(function(a){a.disabled=a.userDisabled=!1})}n.stateChange({disabled:c.map(function(a){return!!a.disabled}),disengaged:c.map(function(a){return!!a.disengaged})})}}).on("dblclick",function(a,b){if(("furious"!=o||!m)&&(n.legendDblclick(a,b),k)){var c=w.data();c.forEach(function(a){a.disabled=!0,"furious"==o&&(a.userDisabled=a.disabled)}),a.disabled=!1,"furious"==o&&(a.userDisabled=a.disabled),n.stateChange({disabled:c.map(function(a){return!!a.disabled})})}}),w.classed("nv-disabled",function(a){return a.userDisabled}),w.exit().remove(),z.attr("fill",q).text(f);var A;switch(o){case"furious":A=23;break;case"classic":A=20}if(h){var B=[];w.each(function(){var b,c=d3.select(this).select("text");try{if(b=c.node().getComputedTextLength(),0>=b)throw Error()}catch(d){b=a.utils.calcApproxTextWidth(c)}B.push(b+i)});for(var C=0,D=0,E=[];p>D&&C<B.length;)E[C]=B[C],D+=B[C++];for(0===C&&(C=1);D>p&&C>1;){E=[],C--;for(var F=0;F<B.length;F++)B[F]>(E[F%C]||0)&&(E[F%C]=B[F]);D=E.reduce(function(a,b){return a+b})}for(var G=[],H=0,I=0;C>H;H++)G[H]=I,I+=E[H];w.attr("transform",function(a,b){return"translate("+G[b%C]+","+(5+Math.floor(b/C)*A)+")"}),j?u.attr("transform","translate("+(d-c.right-D)+","+c.top+")"):u.attr("transform","translate(0,"+c.top+")"),e=c.top+c.bottom+Math.ceil(B.length/C)*A}else{var J,K=5,L=5,M=0;w.attr("transform",function(){var a=d3.select(this).select("text").node().getComputedTextLength()+i;return J=L,d<c.left+c.right+J+a&&(L=J=5,K+=A),L+=a,L>M&&(M=L),"translate("+J+","+K+")"}),u.attr("transform","translate("+(d-c.right-M)+","+c.top+")"),e=c.top+c.bottom+K+15}"furious"==o&&v.attr("width",function(a,b){return z[0][b].getComputedTextLength()+27}).attr("height",18).attr("y",-9).attr("x",-15),v.style("fill",r).style("stroke",function(a,b){return a.color||g(a,b)})}),b}var c={top:5,right:0,bottom:5,left:0},d=400,e=20,f=function(a){return a.key},g=a.utils.getColor(),h=!0,i=28,j=!0,k=!0,l=!1,m=!1,n=d3.dispatch("legendClick","legendDblclick","legendMouseover","legendMouseout","stateChange"),o="classic";return b.dispatch=n,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return d},set:function(a){d=a}},height:{get:function(){return e},set:function(a){e=a}},key:{get:function(){return f},set:function(a){f=a}},align:{get:function(){return h},set:function(a){h=a}},rightAlign:{get:function(){return j},set:function(a){j=a}},padding:{get:function(){return i},set:function(a){i=a}},updateState:{get:function(){return k},set:function(a){k=a}},radioButtonMode:{get:function(){return l},set:function(a){l=a}},expanded:{get:function(){return m},set:function(a){m=a}},vers:{get:function(){return o},set:function(a){o=a}},margin:{get:function(){return c},set:function(a){c.top=void 0!==a.top?a.top:c.top,c.right=void 0!==a.right?a.right:c.right,c.bottom=void 0!==a.bottom?a.bottom:c.bottom,c.left=void 0!==a.left?a.left:c.left}},color:{get:function(){return g},set:function(b){g=a.utils.getColor(b)}}}),a.utils.initOptions(b),b},a.models.historicalBar=function(){"use strict";function b(x){return x.each(function(b){w.reset(),k=d3.select(this);var x=a.utils.availableWidth(h,k,g),y=a.utils.availableHeight(i,k,g);a.utils.initSVG(k),l.domain(c||d3.extent(b[0].values.map(n).concat(p))),l.range(r?e||[.5*x/b[0].values.length,x*(b[0].values.length-.5)/b[0].values.length]:e||[0,x]),m.domain(d||d3.extent(b[0].values.map(o).concat(q))).range(f||[y,0]),l.domain()[0]===l.domain()[1]&&l.domain(l.domain()[0]?[l.domain()[0]-.01*l.domain()[0],l.domain()[1]+.01*l.domain()[1]]:[-1,1]),m.domain()[0]===m.domain()[1]&&m.domain(m.domain()[0]?[m.domain()[0]+.01*m.domain()[0],m.domain()[1]-.01*m.domain()[1]]:[-1,1]);var z=k.selectAll("g.nv-wrap.nv-historicalBar-"+j).data([b[0].values]),A=z.enter().append("g").attr("class","nvd3 nv-wrap nv-historicalBar-"+j),B=A.append("defs"),C=A.append("g"),D=z.select("g");C.append("g").attr("class","nv-bars"),z.attr("transform","translate("+g.left+","+g.top+")"),k.on("click",function(a,b){u.chartClick({data:a,index:b,pos:d3.event,id:j})}),B.append("clipPath").attr("id","nv-chart-clip-path-"+j).append("rect"),z.select("#nv-chart-clip-path-"+j+" rect").attr("width",x).attr("height",y),D.attr("clip-path",s?"url(#nv-chart-clip-path-"+j+")":"");var E=z.select(".nv-bars").selectAll(".nv-bar").data(function(a){return a},function(a,b){return n(a,b)});E.exit().remove(),E.enter().append("rect").attr("x",0).attr("y",function(b,c){return a.utils.NaNtoZero(m(Math.max(0,o(b,c))))}).attr("height",function(b,c){return a.utils.NaNtoZero(Math.abs(m(o(b,c))-m(0)))}).attr("transform",function(a,c){return"translate("+(l(n(a,c))-x/b[0].values.length*.45)+",0)"}).on("mouseover",function(a,b){v&&(d3.select(this).classed("hover",!0),u.elementMouseover({data:a,index:b,color:d3.select(this).style("fill")}))}).on("mouseout",function(a,b){v&&(d3.select(this).classed("hover",!1),u.elementMouseout({data:a,index:b,color:d3.select(this).style("fill")}))}).on("mousemove",function(a,b){v&&u.elementMousemove({data:a,index:b,color:d3.select(this).style("fill")})}).on("click",function(a,b){v&&(u.elementClick({data:a,index:b,color:d3.select(this).style("fill")}),d3.event.stopPropagation())}).on("dblclick",function(a,b){v&&(u.elementDblClick({data:a,index:b,color:d3.select(this).style("fill")}),d3.event.stopPropagation())}),E.attr("fill",function(a,b){return t(a,b)}).attr("class",function(a,b,c){return(o(a,b)<0?"nv-bar negative":"nv-bar positive")+" nv-bar-"+c+"-"+b}).watchTransition(w,"bars").attr("transform",function(a,c){return"translate("+(l(n(a,c))-x/b[0].values.length*.45)+",0)"}).attr("width",x/b[0].values.length*.9),E.watchTransition(w,"bars").attr("y",function(b,c){var d=o(b,c)<0?m(0):m(0)-m(o(b,c))<1?m(0)-1:m(o(b,c));return a.utils.NaNtoZero(d)}).attr("height",function(b,c){return a.utils.NaNtoZero(Math.max(Math.abs(m(o(b,c))-m(0)),1))})}),w.renderEnd("historicalBar immediate"),b}var c,d,e,f,g={top:0,right:0,bottom:0,left:0},h=null,i=null,j=Math.floor(1e4*Math.random()),k=null,l=d3.scale.linear(),m=d3.scale.linear(),n=function(a){return a.x},o=function(a){return a.y},p=[],q=[0],r=!1,s=!0,t=a.utils.defaultColor(),u=d3.dispatch("chartClick","elementClick","elementDblClick","elementMouseover","elementMouseout","elementMousemove","renderEnd"),v=!0,w=a.utils.renderWatch(u,0);return b.highlightPoint=function(a,b){k.select(".nv-bars .nv-bar-0-"+a).classed("hover",b)},b.clearHighlights=function(){k.select(".nv-bars .nv-bar.hover").classed("hover",!1)},b.dispatch=u,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return h},set:function(a){h=a}},height:{get:function(){return i},set:function(a){i=a}},forceX:{get:function(){return p},set:function(a){p=a}},forceY:{get:function(){return q},set:function(a){q=a}},padData:{get:function(){return r},set:function(a){r=a}},x:{get:function(){return n},set:function(a){n=a}},y:{get:function(){return o},set:function(a){o=a}},xScale:{get:function(){return l},set:function(a){l=a}},yScale:{get:function(){return m},set:function(a){m=a}},xDomain:{get:function(){return c},set:function(a){c=a}},yDomain:{get:function(){return d},set:function(a){d=a}},xRange:{get:function(){return e},set:function(a){e=a}},yRange:{get:function(){return f},set:function(a){f=a}},clipEdge:{get:function(){return s},set:function(a){s=a}},id:{get:function(){return j},set:function(a){j=a}},interactive:{get:function(){return v},set:function(a){v=a}},margin:{get:function(){return g},set:function(a){g.top=void 0!==a.top?a.top:g.top,g.right=void 0!==a.right?a.right:g.right,g.bottom=void 0!==a.bottom?a.bottom:g.bottom,g.left=void 0!==a.left?a.left:g.left}},color:{get:function(){return t},set:function(b){t=a.utils.getColor(b)}}}),a.utils.initOptions(b),b},a.models.historicalBarChart=function(b){"use strict";function c(b){return b.each(function(k){z.reset(),z.models(f),q&&z.models(g),r&&z.models(h);var w=d3.select(this),A=this;a.utils.initSVG(w);var B=a.utils.availableWidth(n,w,l),C=a.utils.availableHeight(o,w,l);if(c.update=function(){w.transition().duration(y).call(c)},c.container=this,u.disabled=k.map(function(a){return!!a.disabled}),!v){var D;v={};for(D in u)v[D]=u[D]instanceof Array?u[D].slice(0):u[D]}if(!(k&&k.length&&k.filter(function(a){return a.values.length}).length))return a.utils.noData(c,w),c;w.selectAll(".nv-noData").remove(),d=f.xScale(),e=f.yScale();var E=w.selectAll("g.nv-wrap.nv-historicalBarChart").data([k]),F=E.enter().append("g").attr("class","nvd3 nv-wrap nv-historicalBarChart").append("g"),G=E.select("g");F.append("g").attr("class","nv-x nv-axis"),F.append("g").attr("class","nv-y nv-axis"),F.append("g").attr("class","nv-barsWrap"),F.append("g").attr("class","nv-legendWrap"),F.append("g").attr("class","nv-interactive"),p&&(i.width(B),G.select(".nv-legendWrap").datum(k).call(i),l.top!=i.height()&&(l.top=i.height(),C=a.utils.availableHeight(o,w,l)),E.select(".nv-legendWrap").attr("transform","translate(0,"+-l.top+")")),E.attr("transform","translate("+l.left+","+l.top+")"),s&&G.select(".nv-y.nv-axis").attr("transform","translate("+B+",0)"),t&&(j.width(B).height(C).margin({left:l.left,top:l.top}).svgContainer(w).xScale(d),E.select(".nv-interactive").call(j)),f.width(B).height(C).color(k.map(function(a,b){return a.color||m(a,b)}).filter(function(a,b){return!k[b].disabled}));var H=G.select(".nv-barsWrap").datum(k.filter(function(a){return!a.disabled}));H.transition().call(f),q&&(g.scale(d)._ticks(a.utils.calcTicksX(B/100,k)).tickSize(-C,0),G.select(".nv-x.nv-axis").attr("transform","translate(0,"+e.range()[0]+")"),G.select(".nv-x.nv-axis").transition().call(g)),r&&(h.scale(e)._ticks(a.utils.calcTicksY(C/36,k)).tickSize(-B,0),G.select(".nv-y.nv-axis").transition().call(h)),j.dispatch.on("elementMousemove",function(b){f.clearHighlights();var d,e,i,n=[];k.filter(function(a,b){return a.seriesIndex=b,!a.disabled}).forEach(function(g){e=a.interactiveBisect(g.values,b.pointXValue,c.x()),f.highlightPoint(e,!0);var h=g.values[e];void 0!==h&&(void 0===d&&(d=h),void 0===i&&(i=c.xScale()(c.x()(h,e))),n.push({key:g.key,value:c.y()(h,e),color:m(g,g.seriesIndex),data:g.values[e]}))});var o=g.tickFormat()(c.x()(d,e));j.tooltip.position({left:i+l.left,top:b.mouseY+l.top}).chartContainer(A.parentNode).valueFormatter(function(a){return h.tickFormat()(a)}).data({value:o,index:e,series:n})(),j.renderGuideLine(i)}),j.dispatch.on("elementMouseout",function(){x.tooltipHide(),f.clearHighlights()}),i.dispatch.on("legendClick",function(a){a.disabled=!a.disabled,k.filter(function(a){return!a.disabled}).length||k.map(function(a){return a.disabled=!1,E.selectAll(".nv-series").classed("disabled",!1),a}),u.disabled=k.map(function(a){return!!a.disabled}),x.stateChange(u),b.transition().call(c)}),i.dispatch.on("legendDblclick",function(a){k.forEach(function(a){a.disabled=!0}),a.disabled=!1,u.disabled=k.map(function(a){return!!a.disabled}),x.stateChange(u),c.update()}),x.on("changeState",function(a){"undefined"!=typeof a.disabled&&(k.forEach(function(b,c){b.disabled=a.disabled[c]}),u.disabled=a.disabled),c.update()})}),z.renderEnd("historicalBarChart immediate"),c}var d,e,f=b||a.models.historicalBar(),g=a.models.axis(),h=a.models.axis(),i=a.models.legend(),j=a.interactiveGuideline(),k=a.models.tooltip(),l={top:30,right:90,bottom:50,left:90},m=a.utils.defaultColor(),n=null,o=null,p=!1,q=!0,r=!0,s=!1,t=!1,u={},v=null,w=null,x=d3.dispatch("tooltipHide","stateChange","changeState","renderEnd"),y=250;g.orient("bottom").tickPadding(7),h.orient(s?"right":"left"),k.duration(0).headerEnabled(!1).valueFormatter(function(a,b){return h.tickFormat()(a,b)}).headerFormatter(function(a,b){return g.tickFormat()(a,b)});var z=a.utils.renderWatch(x,0);return f.dispatch.on("elementMouseover.tooltip",function(a){a.series={key:c.x()(a.data),value:c.y()(a.data),color:a.color},k.data(a).hidden(!1)}),f.dispatch.on("elementMouseout.tooltip",function(){k.hidden(!0)}),f.dispatch.on("elementMousemove.tooltip",function(){k.position({top:d3.event.pageY,left:d3.event.pageX})()}),c.dispatch=x,c.bars=f,c.legend=i,c.xAxis=g,c.yAxis=h,c.interactiveLayer=j,c.tooltip=k,c.options=a.utils.optionsFunc.bind(c),c._options=Object.create({},{width:{get:function(){return n},set:function(a){n=a}},height:{get:function(){return o},set:function(a){o=a}},showLegend:{get:function(){return p},set:function(a){p=a}},showXAxis:{get:function(){return q},set:function(a){q=a}},showYAxis:{get:function(){return r},set:function(a){r=a}},defaultState:{get:function(){return v},set:function(a){v=a}},noData:{get:function(){return w},set:function(a){w=a}},tooltips:{get:function(){return k.enabled()},set:function(b){a.deprecated("tooltips","use chart.tooltip.enabled() instead"),k.enabled(!!b)}},tooltipContent:{get:function(){return k.contentGenerator()},set:function(b){a.deprecated("tooltipContent","use chart.tooltip.contentGenerator() instead"),k.contentGenerator(b)}},margin:{get:function(){return l},set:function(a){l.top=void 0!==a.top?a.top:l.top,l.right=void 0!==a.right?a.right:l.right,l.bottom=void 0!==a.bottom?a.bottom:l.bottom,l.left=void 0!==a.left?a.left:l.left}},color:{get:function(){return m},set:function(b){m=a.utils.getColor(b),i.color(m),f.color(m)}},duration:{get:function(){return y},set:function(a){y=a,z.reset(y),h.duration(y),g.duration(y)}},rightAlignYAxis:{get:function(){return s},set:function(a){s=a,h.orient(a?"right":"left")}},useInteractiveGuideline:{get:function(){return t},set:function(a){t=a,a===!0&&c.interactive(!1)}}}),a.utils.inheritOptions(c,f),a.utils.initOptions(c),c},a.models.ohlcBarChart=function(){var b=a.models.historicalBarChart(a.models.ohlcBar());return b.useInteractiveGuideline(!0),b.interactiveLayer.tooltip.contentGenerator(function(a){var c=a.series[0].data,d=c.open<c.close?"2ca02c":"d62728";return'<h3 style="color: #'+d+'">'+a.value+"</h3><table><tr><td>open:</td><td>"+b.yAxis.tickFormat()(c.open)+"</td></tr><tr><td>close:</td><td>"+b.yAxis.tickFormat()(c.close)+"</td></tr><tr><td>high</td><td>"+b.yAxis.tickFormat()(c.high)+"</td></tr><tr><td>low:</td><td>"+b.yAxis.tickFormat()(c.low)+"</td></tr></table>"}),b},a.models.candlestickBarChart=function(){var b=a.models.historicalBarChart(a.models.candlestickBar());return b.useInteractiveGuideline(!0),b.interactiveLayer.tooltip.contentGenerator(function(a){var c=a.series[0].data,d=c.open<c.close?"2ca02c":"d62728";return'<h3 style="color: #'+d+'">'+a.value+"</h3><table><tr><td>open:</td><td>"+b.yAxis.tickFormat()(c.open)+"</td></tr><tr><td>close:</td><td>"+b.yAxis.tickFormat()(c.close)+"</td></tr><tr><td>high</td><td>"+b.yAxis.tickFormat()(c.high)+"</td></tr><tr><td>low:</td><td>"+b.yAxis.tickFormat()(c.low)+"</td></tr></table>"}),b},a.models.legend=function(){"use strict";function b(p){function q(a,b){return"furious"!=o?"#000":m?a.disengaged?"#000":"#fff":m?void 0:(a.color||(a.color=g(a,b)),a.disabled?a.color:"#fff")}function r(a,b){return m&&"furious"==o&&a.disengaged?"#eee":a.color||g(a,b)}function s(a){return m&&"furious"==o?1:a.disabled?0:1}return p.each(function(b){var g=d-c.left-c.right,p=d3.select(this);a.utils.initSVG(p);var t=p.selectAll("g.nv-legend").data([b]),u=t.enter().append("g").attr("class","nvd3 nv-legend").append("g"),v=t.select("g");t.attr("transform","translate("+c.left+","+c.top+")");var w,x,y=v.selectAll(".nv-series").data(function(a){return"furious"!=o?a:a.filter(function(a){return m?!0:!a.disengaged})}),z=y.enter().append("g").attr("class","nv-series");switch(o){case"furious":x=23;break;case"classic":x=20}if("classic"==o)z.append("circle").style("stroke-width",2).attr("class","nv-legend-symbol").attr("r",5),w=y.select("circle");else if("furious"==o){z.append("rect").style("stroke-width",2).attr("class","nv-legend-symbol").attr("rx",3).attr("ry",3),w=y.select(".nv-legend-symbol"),z.append("g").attr("class","nv-check-box").property("innerHTML",'<path d="M0.5,5 L22.5,5 L22.5,26.5 L0.5,26.5 L0.5,5 Z" class="nv-box"></path><path d="M5.5,12.8618467 L11.9185089,19.2803556 L31,0.198864511" class="nv-check"></path>').attr("transform","translate(-10,-8)scale(0.5)");var A=y.select(".nv-check-box");A.each(function(a,b){d3.select(this).selectAll("path").attr("stroke",q(a,b))})}z.append("text").attr("text-anchor","start").attr("class","nv-legend-text").attr("dy",".32em").attr("dx","8");var B=y.select("text.nv-legend-text");y.on("mouseover",function(a,b){n.legendMouseover(a,b)}).on("mouseout",function(a,b){n.legendMouseout(a,b)}).on("click",function(a,b){n.legendClick(a,b);var c=y.data();if(k){if("classic"==o)l?(c.forEach(function(a){a.disabled=!0}),a.disabled=!1):(a.disabled=!a.disabled,c.every(function(a){return a.disabled})&&c.forEach(function(a){a.disabled=!1}));else if("furious"==o)if(m)a.disengaged=!a.disengaged,a.userDisabled=void 0==a.userDisabled?!!a.disabled:a.userDisabled,a.disabled=a.disengaged||a.userDisabled;else if(!m){a.disabled=!a.disabled,a.userDisabled=a.disabled;var d=c.filter(function(a){return!a.disengaged});d.every(function(a){return a.userDisabled})&&c.forEach(function(a){a.disabled=a.userDisabled=!1})}n.stateChange({disabled:c.map(function(a){return!!a.disabled}),disengaged:c.map(function(a){return!!a.disengaged})})}}).on("dblclick",function(a,b){if(("furious"!=o||!m)&&(n.legendDblclick(a,b),k)){var c=y.data();c.forEach(function(a){a.disabled=!0,"furious"==o&&(a.userDisabled=a.disabled)}),a.disabled=!1,"furious"==o&&(a.userDisabled=a.disabled),n.stateChange({disabled:c.map(function(a){return!!a.disabled})})}}),y.classed("nv-disabled",function(a){return a.userDisabled}),y.exit().remove(),B.attr("fill",q).text(f);var C=0;if(h){var D=[];y.each(function(){var b,c=d3.select(this).select("text");try{if(b=c.node().getComputedTextLength(),0>=b)throw Error()}catch(d){b=a.utils.calcApproxTextWidth(c)}D.push(b+i)});var E=0,F=[];for(C=0;g>C&&E<D.length;)F[E]=D[E],C+=D[E++];for(0===E&&(E=1);C>g&&E>1;){F=[],E--;for(var G=0;G<D.length;G++)D[G]>(F[G%E]||0)&&(F[G%E]=D[G]);C=F.reduce(function(a,b){return a+b})}for(var H=[],I=0,J=0;E>I;I++)H[I]=J,J+=F[I];y.attr("transform",function(a,b){return"translate("+H[b%E]+","+(5+Math.floor(b/E)*x)+")"}),j?v.attr("transform","translate("+(d-c.right-C)+","+c.top+")"):v.attr("transform","translate(0,"+c.top+")"),e=c.top+c.bottom+Math.ceil(D.length/E)*x}else{var K,L=5,M=5,N=0;y.attr("transform",function(){var a=d3.select(this).select("text").node().getComputedTextLength()+i;return K=M,d<c.left+c.right+K+a&&(M=K=5,L+=x),M+=a,M>N&&(N=M),K+N>C&&(C=K+N),"translate("+K+","+L+")"}),v.attr("transform","translate("+(d-c.right-N)+","+c.top+")"),e=c.top+c.bottom+L+15}if("furious"==o){w.attr("width",function(a,b){return B[0][b].getComputedTextLength()+27}).attr("height",18).attr("y",-9).attr("x",-15),u.insert("rect",":first-child").attr("class","nv-legend-bg").attr("fill","#eee").attr("opacity",0);var O=v.select(".nv-legend-bg");O.transition().duration(300).attr("x",-x).attr("width",C+x-12).attr("height",e+10).attr("y",-c.top-10).attr("opacity",m?1:0)}w.style("fill",r).style("fill-opacity",s).style("stroke",r)}),b}var c={top:5,right:0,bottom:5,left:0},d=400,e=20,f=function(a){return a.key},g=a.utils.getColor(),h=!0,i=32,j=!0,k=!0,l=!1,m=!1,n=d3.dispatch("legendClick","legendDblclick","legendMouseover","legendMouseout","stateChange"),o="classic";return b.dispatch=n,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return d},set:function(a){d=a}},height:{get:function(){return e},set:function(a){e=a}},key:{get:function(){return f},set:function(a){f=a}},align:{get:function(){return h},set:function(a){h=a}},rightAlign:{get:function(){return j},set:function(a){j=a}},padding:{get:function(){return i},set:function(a){i=a}},updateState:{get:function(){return k},set:function(a){k=a}},radioButtonMode:{get:function(){return l},set:function(a){l=a}},expanded:{get:function(){return m},set:function(a){m=a}},vers:{get:function(){return o},set:function(a){o=a}},margin:{get:function(){return c},set:function(a){c.top=void 0!==a.top?a.top:c.top,c.right=void 0!==a.right?a.right:c.right,c.bottom=void 0!==a.bottom?a.bottom:c.bottom,c.left=void 0!==a.left?a.left:c.left}},color:{get:function(){return g},set:function(b){g=a.utils.getColor(b)}}}),a.utils.initOptions(b),b},a.models.line=function(){"use strict";function b(r){return v.reset(),v.models(e),r.each(function(b){i=d3.select(this);var r=a.utils.availableWidth(g,i,f),s=a.utils.availableHeight(h,i,f);a.utils.initSVG(i),c=e.xScale(),d=e.yScale(),t=t||c,u=u||d;var w=i.selectAll("g.nv-wrap.nv-line").data([b]),x=w.enter().append("g").attr("class","nvd3 nv-wrap nv-line"),y=x.append("defs"),z=x.append("g"),A=w.select("g");z.append("g").attr("class","nv-groups"),z.append("g").attr("class","nv-scatterWrap"),w.attr("transform","translate("+f.left+","+f.top+")"),e.width(r).height(s);var B=w.select(".nv-scatterWrap");B.call(e),y.append("clipPath").attr("id","nv-edge-clip-"+e.id()).append("rect"),w.select("#nv-edge-clip-"+e.id()+" rect").attr("width",r).attr("height",s>0?s:0),A.attr("clip-path",p?"url(#nv-edge-clip-"+e.id()+")":""),B.attr("clip-path",p?"url(#nv-edge-clip-"+e.id()+")":"");var C=w.select(".nv-groups").selectAll(".nv-group").data(function(a){return a},function(a){return a.key});C.enter().append("g").style("stroke-opacity",1e-6).style("stroke-width",function(a){return a.strokeWidth||j}).style("fill-opacity",1e-6),C.exit().remove(),C.attr("class",function(a,b){return(a.classed||"")+" nv-group nv-series-"+b}).classed("hover",function(a){return a.hover}).style("fill",function(a,b){return k(a,b)}).style("stroke",function(a,b){return k(a,b)}),C.watchTransition(v,"line: groups").style("stroke-opacity",1).style("fill-opacity",function(a){return a.fillOpacity||.5});var D=C.selectAll("path.nv-area").data(function(a){return o(a)?[a]:[]});D.enter().append("path").attr("class","nv-area").attr("d",function(b){return d3.svg.area().interpolate(q).defined(n).x(function(b,c){return a.utils.NaNtoZero(t(l(b,c)))}).y0(function(b,c){return a.utils.NaNtoZero(u(m(b,c)))}).y1(function(){return u(d.domain()[0]<=0?d.domain()[1]>=0?0:d.domain()[1]:d.domain()[0])}).apply(this,[b.values])}),C.exit().selectAll("path.nv-area").remove(),D.watchTransition(v,"line: areaPaths").attr("d",function(b){return d3.svg.area().interpolate(q).defined(n).x(function(b,d){return a.utils.NaNtoZero(c(l(b,d)))}).y0(function(b,c){return a.utils.NaNtoZero(d(m(b,c)))}).y1(function(){return d(d.domain()[0]<=0?d.domain()[1]>=0?0:d.domain()[1]:d.domain()[0])}).apply(this,[b.values])});var E=C.selectAll("path.nv-line").data(function(a){return[a.values]});E.enter().append("path").attr("class","nv-line").attr("d",d3.svg.line().interpolate(q).defined(n).x(function(b,c){return a.utils.NaNtoZero(t(l(b,c)))}).y(function(b,c){return a.utils.NaNtoZero(u(m(b,c)))})),E.watchTransition(v,"line: linePaths").attr("d",d3.svg.line().interpolate(q).defined(n).x(function(b,d){return a.utils.NaNtoZero(c(l(b,d)))}).y(function(b,c){return a.utils.NaNtoZero(d(m(b,c)))})),t=c.copy(),u=d.copy()}),v.renderEnd("line immediate"),b}var c,d,e=a.models.scatter(),f={top:0,right:0,bottom:0,left:0},g=960,h=500,i=null,j=1.5,k=a.utils.defaultColor(),l=function(a){return a.x},m=function(a){return a.y},n=function(a,b){return!isNaN(m(a,b))&&null!==m(a,b)},o=function(a){return a.area},p=!1,q="linear",r=250,s=d3.dispatch("elementClick","elementMouseover","elementMouseout","renderEnd");e.pointSize(16).pointDomain([16,256]);var t,u,v=a.utils.renderWatch(s,r);return b.dispatch=s,b.scatter=e,e.dispatch.on("elementClick",function(){s.elementClick.apply(this,arguments)}),e.dispatch.on("elementMouseover",function(){s.elementMouseover.apply(this,arguments)}),e.dispatch.on("elementMouseout",function(){s.elementMouseout.apply(this,arguments)}),b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return g},set:function(a){g=a}},height:{get:function(){return h},set:function(a){h=a}},defined:{get:function(){return n},set:function(a){n=a}},interpolate:{get:function(){return q},set:function(a){q=a}},clipEdge:{get:function(){return p},set:function(a){p=a}},margin:{get:function(){return f},set:function(a){f.top=void 0!==a.top?a.top:f.top,f.right=void 0!==a.right?a.right:f.right,f.bottom=void 0!==a.bottom?a.bottom:f.bottom,f.left=void 0!==a.left?a.left:f.left}},duration:{get:function(){return r},set:function(a){r=a,v.reset(r),e.duration(r)}},isArea:{get:function(){return o},set:function(a){o=d3.functor(a)}},x:{get:function(){return l},set:function(a){l=a,e.x(a)}},y:{get:function(){return m},set:function(a){m=a,e.y(a)}},color:{get:function(){return k},set:function(b){k=a.utils.getColor(b),e.color(k)}}}),a.utils.inheritOptions(b,e),a.utils.initOptions(b),b},a.models.lineChart=function(){"use strict";function b(j){return y.reset(),y.models(e),p&&y.models(f),q&&y.models(g),j.each(function(j){var v=d3.select(this),y=this;a.utils.initSVG(v);var B=a.utils.availableWidth(m,v,k),C=a.utils.availableHeight(n,v,k);if(b.update=function(){0===x?v.call(b):v.transition().duration(x).call(b)},b.container=this,t.setter(A(j),b.update).getter(z(j)).update(),t.disabled=j.map(function(a){return!!a.disabled}),!u){var D;u={};for(D in t)u[D]=t[D]instanceof Array?t[D].slice(0):t[D]
+}if(!(j&&j.length&&j.filter(function(a){return a.values.length}).length))return a.utils.noData(b,v),b;v.selectAll(".nv-noData").remove(),c=e.xScale(),d=e.yScale();var E=v.selectAll("g.nv-wrap.nv-lineChart").data([j]),F=E.enter().append("g").attr("class","nvd3 nv-wrap nv-lineChart").append("g"),G=E.select("g");F.append("rect").style("opacity",0),F.append("g").attr("class","nv-x nv-axis"),F.append("g").attr("class","nv-y nv-axis"),F.append("g").attr("class","nv-linesWrap"),F.append("g").attr("class","nv-legendWrap"),F.append("g").attr("class","nv-interactive"),G.select("rect").attr("width",B).attr("height",C>0?C:0),o&&(h.width(B),G.select(".nv-legendWrap").datum(j).call(h),k.top!=h.height()&&(k.top=h.height(),C=a.utils.availableHeight(n,v,k)),E.select(".nv-legendWrap").attr("transform","translate(0,"+-k.top+")")),E.attr("transform","translate("+k.left+","+k.top+")"),r&&G.select(".nv-y.nv-axis").attr("transform","translate("+B+",0)"),s&&(i.width(B).height(C).margin({left:k.left,top:k.top}).svgContainer(v).xScale(c),E.select(".nv-interactive").call(i)),e.width(B).height(C).color(j.map(function(a,b){return a.color||l(a,b)}).filter(function(a,b){return!j[b].disabled}));var H=G.select(".nv-linesWrap").datum(j.filter(function(a){return!a.disabled}));H.call(e),p&&(f.scale(c)._ticks(a.utils.calcTicksX(B/100,j)).tickSize(-C,0),G.select(".nv-x.nv-axis").attr("transform","translate(0,"+d.range()[0]+")"),G.select(".nv-x.nv-axis").call(f)),q&&(g.scale(d)._ticks(a.utils.calcTicksY(C/36,j)).tickSize(-B,0),G.select(".nv-y.nv-axis").call(g)),h.dispatch.on("stateChange",function(a){for(var c in a)t[c]=a[c];w.stateChange(t),b.update()}),i.dispatch.on("elementMousemove",function(c){e.clearHighlights();var d,h,m,n=[];if(j.filter(function(a,b){return a.seriesIndex=b,!a.disabled}).forEach(function(f,g){h=a.interactiveBisect(f.values,c.pointXValue,b.x());var i=f.values[h],j=b.y()(i,h);null!=j&&e.highlightPoint(g,h,!0),void 0!==i&&(void 0===d&&(d=i),void 0===m&&(m=b.xScale()(b.x()(i,h))),n.push({key:f.key,value:j,color:l(f,f.seriesIndex)}))}),n.length>2){var o=b.yScale().invert(c.mouseY),p=Math.abs(b.yScale().domain()[0]-b.yScale().domain()[1]),q=.03*p,r=a.nearestValueIndex(n.map(function(a){return a.value}),o,q);null!==r&&(n[r].highlight=!0)}var s=f.tickFormat()(b.x()(d,h));i.tooltip.position({left:c.mouseX+k.left,top:c.mouseY+k.top}).chartContainer(y.parentNode).valueFormatter(function(a){return null==a?"N/A":g.tickFormat()(a)}).data({value:s,index:h,series:n})(),i.renderGuideLine(m)}),i.dispatch.on("elementClick",function(c){var d,f=[];j.filter(function(a,b){return a.seriesIndex=b,!a.disabled}).forEach(function(e){var g=a.interactiveBisect(e.values,c.pointXValue,b.x()),h=e.values[g];if("undefined"!=typeof h){"undefined"==typeof d&&(d=b.xScale()(b.x()(h,g)));var i=b.yScale()(b.y()(h,g));f.push({point:h,pointIndex:g,pos:[d,i],seriesIndex:e.seriesIndex,series:e})}}),e.dispatch.elementClick(f)}),i.dispatch.on("elementMouseout",function(){e.clearHighlights()}),w.on("changeState",function(a){"undefined"!=typeof a.disabled&&j.length===a.disabled.length&&(j.forEach(function(b,c){b.disabled=a.disabled[c]}),t.disabled=a.disabled),b.update()})}),y.renderEnd("lineChart immediate"),b}var c,d,e=a.models.line(),f=a.models.axis(),g=a.models.axis(),h=a.models.legend(),i=a.interactiveGuideline(),j=a.models.tooltip(),k={top:30,right:20,bottom:50,left:60},l=a.utils.defaultColor(),m=null,n=null,o=!0,p=!0,q=!0,r=!1,s=!1,t=a.utils.state(),u=null,v=null,w=d3.dispatch("tooltipShow","tooltipHide","stateChange","changeState","renderEnd"),x=250;f.orient("bottom").tickPadding(7),g.orient(r?"right":"left"),j.valueFormatter(function(a,b){return g.tickFormat()(a,b)}).headerFormatter(function(a,b){return f.tickFormat()(a,b)});var y=a.utils.renderWatch(w,x),z=function(a){return function(){return{active:a.map(function(a){return!a.disabled})}}},A=function(a){return function(b){void 0!==b.active&&a.forEach(function(a,c){a.disabled=!b.active[c]})}};return e.dispatch.on("elementMouseover.tooltip",function(a){j.data(a).position(a.pos).hidden(!1)}),e.dispatch.on("elementMouseout.tooltip",function(){j.hidden(!0)}),b.dispatch=w,b.lines=e,b.legend=h,b.xAxis=f,b.yAxis=g,b.interactiveLayer=i,b.tooltip=j,b.dispatch=w,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return m},set:function(a){m=a}},height:{get:function(){return n},set:function(a){n=a}},showLegend:{get:function(){return o},set:function(a){o=a}},showXAxis:{get:function(){return p},set:function(a){p=a}},showYAxis:{get:function(){return q},set:function(a){q=a}},defaultState:{get:function(){return u},set:function(a){u=a}},noData:{get:function(){return v},set:function(a){v=a}},tooltips:{get:function(){return j.enabled()},set:function(b){a.deprecated("tooltips","use chart.tooltip.enabled() instead"),j.enabled(!!b)}},tooltipContent:{get:function(){return j.contentGenerator()},set:function(b){a.deprecated("tooltipContent","use chart.tooltip.contentGenerator() instead"),j.contentGenerator(b)}},margin:{get:function(){return k},set:function(a){k.top=void 0!==a.top?a.top:k.top,k.right=void 0!==a.right?a.right:k.right,k.bottom=void 0!==a.bottom?a.bottom:k.bottom,k.left=void 0!==a.left?a.left:k.left}},duration:{get:function(){return x},set:function(a){x=a,y.reset(x),e.duration(x),f.duration(x),g.duration(x)}},color:{get:function(){return l},set:function(b){l=a.utils.getColor(b),h.color(l),e.color(l)}},rightAlignYAxis:{get:function(){return r},set:function(a){r=a,g.orient(r?"right":"left")}},useInteractiveGuideline:{get:function(){return s},set:function(a){s=a,s&&(e.interactive(!1),e.useVoronoi(!1))}}}),a.utils.inheritOptions(b,e),a.utils.initOptions(b),b},a.models.linePlusBarChart=function(){"use strict";function b(v){return v.each(function(v){function J(a){var b=+("e"==a),c=b?1:-1,d=X/3;return"M"+.5*c+","+d+"A6,6 0 0 "+b+" "+6.5*c+","+(d+6)+"V"+(2*d-6)+"A6,6 0 0 "+b+" "+.5*c+","+2*d+"ZM"+2.5*c+","+(d+8)+"V"+(2*d-8)+"M"+4.5*c+","+(d+8)+"V"+(2*d-8)}function S(){u.empty()||u.extent(I),kb.data([u.empty()?e.domain():I]).each(function(a){var b=e(a[0])-e.range()[0],c=e.range()[1]-e(a[1]);d3.select(this).select(".left").attr("width",0>b?0:b),d3.select(this).select(".right").attr("x",e(a[1])).attr("width",0>c?0:c)})}function T(){I=u.empty()?null:u.extent(),c=u.empty()?e.domain():u.extent(),K.brush({extent:c,brush:u}),S(),l.width(V).height(W).color(v.map(function(a,b){return a.color||C(a,b)}).filter(function(a,b){return!v[b].disabled&&v[b].bar})),j.width(V).height(W).color(v.map(function(a,b){return a.color||C(a,b)}).filter(function(a,b){return!v[b].disabled&&!v[b].bar}));var b=db.select(".nv-focus .nv-barsWrap").datum(Z.length?Z.map(function(a){return{key:a.key,values:a.values.filter(function(a,b){return l.x()(a,b)>=c[0]&&l.x()(a,b)<=c[1]})}}):[{values:[]}]),h=db.select(".nv-focus .nv-linesWrap").datum($[0].disabled?[{values:[]}]:$.map(function(a){return{area:a.area,fillOpacity:a.fillOpacity,key:a.key,values:a.values.filter(function(a,b){return j.x()(a,b)>=c[0]&&j.x()(a,b)<=c[1]})}}));d=Z.length?l.xScale():j.xScale(),n.scale(d)._ticks(a.utils.calcTicksX(V/100,v)).tickSize(-W,0),n.domain([Math.ceil(c[0]),Math.floor(c[1])]),db.select(".nv-x.nv-axis").transition().duration(L).call(n),b.transition().duration(L).call(l),h.transition().duration(L).call(j),db.select(".nv-focus .nv-x.nv-axis").attr("transform","translate(0,"+f.range()[0]+")"),p.scale(f)._ticks(a.utils.calcTicksY(W/36,v)).tickSize(-V,0),q.scale(g)._ticks(a.utils.calcTicksY(W/36,v)).tickSize(Z.length?0:-V,0),db.select(".nv-focus .nv-y1.nv-axis").style("opacity",Z.length?1:0),db.select(".nv-focus .nv-y2.nv-axis").style("opacity",$.length&&!$[0].disabled?1:0).attr("transform","translate("+d.range()[1]+",0)"),db.select(".nv-focus .nv-y1.nv-axis").transition().duration(L).call(p),db.select(".nv-focus .nv-y2.nv-axis").transition().duration(L).call(q)}var U=d3.select(this);a.utils.initSVG(U);var V=a.utils.availableWidth(y,U,w),W=a.utils.availableHeight(z,U,w)-(E?H:0),X=H-x.top-x.bottom;if(b.update=function(){U.transition().duration(L).call(b)},b.container=this,M.setter(R(v),b.update).getter(Q(v)).update(),M.disabled=v.map(function(a){return!!a.disabled}),!N){var Y;N={};for(Y in M)N[Y]=M[Y]instanceof Array?M[Y].slice(0):M[Y]}if(!(v&&v.length&&v.filter(function(a){return a.values.length}).length))return a.utils.noData(b,U),b;U.selectAll(".nv-noData").remove();var Z=v.filter(function(a){return!a.disabled&&a.bar}),$=v.filter(function(a){return!a.bar});d=l.xScale(),e=o.scale(),f=l.yScale(),g=j.yScale(),h=m.yScale(),i=k.yScale();var _=v.filter(function(a){return!a.disabled&&a.bar}).map(function(a){return a.values.map(function(a,b){return{x:A(a,b),y:B(a,b)}})}),ab=v.filter(function(a){return!a.disabled&&!a.bar}).map(function(a){return a.values.map(function(a,b){return{x:A(a,b),y:B(a,b)}})});d.range([0,V]),e.domain(d3.extent(d3.merge(_.concat(ab)),function(a){return a.x})).range([0,V]);var bb=U.selectAll("g.nv-wrap.nv-linePlusBar").data([v]),cb=bb.enter().append("g").attr("class","nvd3 nv-wrap nv-linePlusBar").append("g"),db=bb.select("g");cb.append("g").attr("class","nv-legendWrap");var eb=cb.append("g").attr("class","nv-focus");eb.append("g").attr("class","nv-x nv-axis"),eb.append("g").attr("class","nv-y1 nv-axis"),eb.append("g").attr("class","nv-y2 nv-axis"),eb.append("g").attr("class","nv-barsWrap"),eb.append("g").attr("class","nv-linesWrap");var fb=cb.append("g").attr("class","nv-context");if(fb.append("g").attr("class","nv-x nv-axis"),fb.append("g").attr("class","nv-y1 nv-axis"),fb.append("g").attr("class","nv-y2 nv-axis"),fb.append("g").attr("class","nv-barsWrap"),fb.append("g").attr("class","nv-linesWrap"),fb.append("g").attr("class","nv-brushBackground"),fb.append("g").attr("class","nv-x nv-brush"),D){var gb=t.align()?V/2:V,hb=t.align()?gb:0;t.width(gb),db.select(".nv-legendWrap").datum(v.map(function(a){return a.originalKey=void 0===a.originalKey?a.key:a.originalKey,a.key=a.originalKey+(a.bar?O:P),a})).call(t),w.top!=t.height()&&(w.top=t.height(),W=a.utils.availableHeight(z,U,w)-H),db.select(".nv-legendWrap").attr("transform","translate("+hb+","+-w.top+")")}bb.attr("transform","translate("+w.left+","+w.top+")"),db.select(".nv-context").style("display",E?"initial":"none"),m.width(V).height(X).color(v.map(function(a,b){return a.color||C(a,b)}).filter(function(a,b){return!v[b].disabled&&v[b].bar})),k.width(V).height(X).color(v.map(function(a,b){return a.color||C(a,b)}).filter(function(a,b){return!v[b].disabled&&!v[b].bar}));var ib=db.select(".nv-context .nv-barsWrap").datum(Z.length?Z:[{values:[]}]),jb=db.select(".nv-context .nv-linesWrap").datum($[0].disabled?[{values:[]}]:$);db.select(".nv-context").attr("transform","translate(0,"+(W+w.bottom+x.top)+")"),ib.transition().call(m),jb.transition().call(k),G&&(o._ticks(a.utils.calcTicksX(V/100,v)).tickSize(-X,0),db.select(".nv-context .nv-x.nv-axis").attr("transform","translate(0,"+h.range()[0]+")"),db.select(".nv-context .nv-x.nv-axis").transition().call(o)),F&&(r.scale(h)._ticks(X/36).tickSize(-V,0),s.scale(i)._ticks(X/36).tickSize(Z.length?0:-V,0),db.select(".nv-context .nv-y3.nv-axis").style("opacity",Z.length?1:0).attr("transform","translate(0,"+e.range()[0]+")"),db.select(".nv-context .nv-y2.nv-axis").style("opacity",$.length?1:0).attr("transform","translate("+e.range()[1]+",0)"),db.select(".nv-context .nv-y1.nv-axis").transition().call(r),db.select(".nv-context .nv-y2.nv-axis").transition().call(s)),u.x(e).on("brush",T),I&&u.extent(I);var kb=db.select(".nv-brushBackground").selectAll("g").data([I||u.extent()]),lb=kb.enter().append("g");lb.append("rect").attr("class","left").attr("x",0).attr("y",0).attr("height",X),lb.append("rect").attr("class","right").attr("x",0).attr("y",0).attr("height",X);var mb=db.select(".nv-x.nv-brush").call(u);mb.selectAll("rect").attr("height",X),mb.selectAll(".resize").append("path").attr("d",J),t.dispatch.on("stateChange",function(a){for(var c in a)M[c]=a[c];K.stateChange(M),b.update()}),K.on("changeState",function(a){"undefined"!=typeof a.disabled&&(v.forEach(function(b,c){b.disabled=a.disabled[c]}),M.disabled=a.disabled),b.update()}),T()}),b}var c,d,e,f,g,h,i,j=a.models.line(),k=a.models.line(),l=a.models.historicalBar(),m=a.models.historicalBar(),n=a.models.axis(),o=a.models.axis(),p=a.models.axis(),q=a.models.axis(),r=a.models.axis(),s=a.models.axis(),t=a.models.legend(),u=d3.svg.brush(),v=a.models.tooltip(),w={top:30,right:30,bottom:30,left:60},x={top:0,right:30,bottom:20,left:60},y=null,z=null,A=function(a){return a.x},B=function(a){return a.y},C=a.utils.defaultColor(),D=!0,E=!0,F=!1,G=!0,H=50,I=null,J=null,K=d3.dispatch("brush","stateChange","changeState"),L=0,M=a.utils.state(),N=null,O=" (left axis)",P=" (right axis)";j.clipEdge(!0),k.interactive(!1),n.orient("bottom").tickPadding(5),p.orient("left"),q.orient("right"),o.orient("bottom").tickPadding(5),r.orient("left"),s.orient("right"),v.headerEnabled(!0).headerFormatter(function(a,b){return n.tickFormat()(a,b)});var Q=function(a){return function(){return{active:a.map(function(a){return!a.disabled})}}},R=function(a){return function(b){void 0!==b.active&&a.forEach(function(a,c){a.disabled=!b.active[c]})}};return j.dispatch.on("elementMouseover.tooltip",function(a){v.duration(100).valueFormatter(function(a,b){return q.tickFormat()(a,b)}).data(a).position(a.pos).hidden(!1)}),j.dispatch.on("elementMouseout.tooltip",function(){v.hidden(!0)}),l.dispatch.on("elementMouseover.tooltip",function(a){a.value=b.x()(a.data),a.series={value:b.y()(a.data),color:a.color},v.duration(0).valueFormatter(function(a,b){return p.tickFormat()(a,b)}).data(a).hidden(!1)}),l.dispatch.on("elementMouseout.tooltip",function(){v.hidden(!0)}),l.dispatch.on("elementMousemove.tooltip",function(){v.position({top:d3.event.pageY,left:d3.event.pageX})()}),b.dispatch=K,b.legend=t,b.lines=j,b.lines2=k,b.bars=l,b.bars2=m,b.xAxis=n,b.x2Axis=o,b.y1Axis=p,b.y2Axis=q,b.y3Axis=r,b.y4Axis=s,b.tooltip=v,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return y},set:function(a){y=a}},height:{get:function(){return z},set:function(a){z=a}},showLegend:{get:function(){return D},set:function(a){D=a}},brushExtent:{get:function(){return I},set:function(a){I=a}},noData:{get:function(){return J},set:function(a){J=a}},focusEnable:{get:function(){return E},set:function(a){E=a}},focusHeight:{get:function(){return H},set:function(a){H=a}},focusShowAxisX:{get:function(){return G},set:function(a){G=a}},focusShowAxisY:{get:function(){return F},set:function(a){F=a}},legendLeftAxisHint:{get:function(){return O},set:function(a){O=a}},legendRightAxisHint:{get:function(){return P},set:function(a){P=a}},tooltips:{get:function(){return v.enabled()},set:function(b){a.deprecated("tooltips","use chart.tooltip.enabled() instead"),v.enabled(!!b)}},tooltipContent:{get:function(){return v.contentGenerator()},set:function(b){a.deprecated("tooltipContent","use chart.tooltip.contentGenerator() instead"),v.contentGenerator(b)}},margin:{get:function(){return w},set:function(a){w.top=void 0!==a.top?a.top:w.top,w.right=void 0!==a.right?a.right:w.right,w.bottom=void 0!==a.bottom?a.bottom:w.bottom,w.left=void 0!==a.left?a.left:w.left}},duration:{get:function(){return L},set:function(a){L=a}},color:{get:function(){return C},set:function(b){C=a.utils.getColor(b),t.color(C)}},x:{get:function(){return A},set:function(a){A=a,j.x(a),k.x(a),l.x(a),m.x(a)}},y:{get:function(){return B},set:function(a){B=a,j.y(a),k.y(a),l.y(a),m.y(a)}}}),a.utils.inheritOptions(b,j),a.utils.initOptions(b),b},a.models.lineWithFocusChart=function(){"use strict";function b(o){return o.each(function(o){function z(a){var b=+("e"==a),c=b?1:-1,d=M/3;return"M"+.5*c+","+d+"A6,6 0 0 "+b+" "+6.5*c+","+(d+6)+"V"+(2*d-6)+"A6,6 0 0 "+b+" "+.5*c+","+2*d+"ZM"+2.5*c+","+(d+8)+"V"+(2*d-8)+"M"+4.5*c+","+(d+8)+"V"+(2*d-8)}function G(){n.empty()||n.extent(y),U.data([n.empty()?e.domain():y]).each(function(a){var b=e(a[0])-c.range()[0],d=K-e(a[1]);d3.select(this).select(".left").attr("width",0>b?0:b),d3.select(this).select(".right").attr("x",e(a[1])).attr("width",0>d?0:d)})}function H(){y=n.empty()?null:n.extent();var a=n.empty()?e.domain():n.extent();if(!(Math.abs(a[0]-a[1])<=1)){A.brush({extent:a,brush:n}),G();var b=Q.select(".nv-focus .nv-linesWrap").datum(o.filter(function(a){return!a.disabled}).map(function(b){return{key:b.key,area:b.area,values:b.values.filter(function(b,c){return g.x()(b,c)>=a[0]&&g.x()(b,c)<=a[1]})}}));b.transition().duration(B).call(g),Q.select(".nv-focus .nv-x.nv-axis").transition().duration(B).call(i),Q.select(".nv-focus .nv-y.nv-axis").transition().duration(B).call(j)}}var I=d3.select(this),J=this;a.utils.initSVG(I);var K=a.utils.availableWidth(t,I,q),L=a.utils.availableHeight(u,I,q)-v,M=v-r.top-r.bottom;if(b.update=function(){I.transition().duration(B).call(b)},b.container=this,C.setter(F(o),b.update).getter(E(o)).update(),C.disabled=o.map(function(a){return!!a.disabled}),!D){var N;D={};for(N in C)D[N]=C[N]instanceof Array?C[N].slice(0):C[N]}if(!(o&&o.length&&o.filter(function(a){return a.values.length}).length))return a.utils.noData(b,I),b;I.selectAll(".nv-noData").remove(),c=g.xScale(),d=g.yScale(),e=h.xScale(),f=h.yScale();var O=I.selectAll("g.nv-wrap.nv-lineWithFocusChart").data([o]),P=O.enter().append("g").attr("class","nvd3 nv-wrap nv-lineWithFocusChart").append("g"),Q=O.select("g");P.append("g").attr("class","nv-legendWrap");var R=P.append("g").attr("class","nv-focus");R.append("g").attr("class","nv-x nv-axis"),R.append("g").attr("class","nv-y nv-axis"),R.append("g").attr("class","nv-linesWrap"),R.append("g").attr("class","nv-interactive");var S=P.append("g").attr("class","nv-context");S.append("g").attr("class","nv-x nv-axis"),S.append("g").attr("class","nv-y nv-axis"),S.append("g").attr("class","nv-linesWrap"),S.append("g").attr("class","nv-brushBackground"),S.append("g").attr("class","nv-x nv-brush"),x&&(m.width(K),Q.select(".nv-legendWrap").datum(o).call(m),q.top!=m.height()&&(q.top=m.height(),L=a.utils.availableHeight(u,I,q)-v),Q.select(".nv-legendWrap").attr("transform","translate(0,"+-q.top+")")),O.attr("transform","translate("+q.left+","+q.top+")"),w&&(p.width(K).height(L).margin({left:q.left,top:q.top}).svgContainer(I).xScale(c),O.select(".nv-interactive").call(p)),g.width(K).height(L).color(o.map(function(a,b){return a.color||s(a,b)}).filter(function(a,b){return!o[b].disabled})),h.defined(g.defined()).width(K).height(M).color(o.map(function(a,b){return a.color||s(a,b)}).filter(function(a,b){return!o[b].disabled})),Q.select(".nv-context").attr("transform","translate(0,"+(L+q.bottom+r.top)+")");var T=Q.select(".nv-context .nv-linesWrap").datum(o.filter(function(a){return!a.disabled}));d3.transition(T).call(h),i.scale(c)._ticks(a.utils.calcTicksX(K/100,o)).tickSize(-L,0),j.scale(d)._ticks(a.utils.calcTicksY(L/36,o)).tickSize(-K,0),Q.select(".nv-focus .nv-x.nv-axis").attr("transform","translate(0,"+L+")"),n.x(e).on("brush",function(){H()}),y&&n.extent(y);var U=Q.select(".nv-brushBackground").selectAll("g").data([y||n.extent()]),V=U.enter().append("g");V.append("rect").attr("class","left").attr("x",0).attr("y",0).attr("height",M),V.append("rect").attr("class","right").attr("x",0).attr("y",0).attr("height",M);var W=Q.select(".nv-x.nv-brush").call(n);W.selectAll("rect").attr("height",M),W.selectAll(".resize").append("path").attr("d",z),H(),k.scale(e)._ticks(a.utils.calcTicksX(K/100,o)).tickSize(-M,0),Q.select(".nv-context .nv-x.nv-axis").attr("transform","translate(0,"+f.range()[0]+")"),d3.transition(Q.select(".nv-context .nv-x.nv-axis")).call(k),l.scale(f)._ticks(a.utils.calcTicksY(M/36,o)).tickSize(-K,0),d3.transition(Q.select(".nv-context .nv-y.nv-axis")).call(l),Q.select(".nv-context .nv-x.nv-axis").attr("transform","translate(0,"+f.range()[0]+")"),m.dispatch.on("stateChange",function(a){for(var c in a)C[c]=a[c];A.stateChange(C),b.update()}),p.dispatch.on("elementMousemove",function(c){g.clearHighlights();var d,f,h,k=[];if(o.filter(function(a,b){return a.seriesIndex=b,!a.disabled}).forEach(function(i,j){var l=n.empty()?e.domain():n.extent(),m=i.values.filter(function(a,b){return g.x()(a,b)>=l[0]&&g.x()(a,b)<=l[1]});f=a.interactiveBisect(m,c.pointXValue,g.x());var o=m[f],p=b.y()(o,f);null!=p&&g.highlightPoint(j,f,!0),void 0!==o&&(void 0===d&&(d=o),void 0===h&&(h=b.xScale()(b.x()(o,f))),k.push({key:i.key,value:b.y()(o,f),color:s(i,i.seriesIndex)}))}),k.length>2){var l=b.yScale().invert(c.mouseY),m=Math.abs(b.yScale().domain()[0]-b.yScale().domain()[1]),r=.03*m,t=a.nearestValueIndex(k.map(function(a){return a.value}),l,r);null!==t&&(k[t].highlight=!0)}var u=i.tickFormat()(b.x()(d,f));p.tooltip.position({left:c.mouseX+q.left,top:c.mouseY+q.top}).chartContainer(J.parentNode).valueFormatter(function(a){return null==a?"N/A":j.tickFormat()(a)}).data({value:u,index:f,series:k})(),p.renderGuideLine(h)}),p.dispatch.on("elementMouseout",function(){g.clearHighlights()}),A.on("changeState",function(a){"undefined"!=typeof a.disabled&&o.forEach(function(b,c){b.disabled=a.disabled[c]}),b.update()})}),b}var c,d,e,f,g=a.models.line(),h=a.models.line(),i=a.models.axis(),j=a.models.axis(),k=a.models.axis(),l=a.models.axis(),m=a.models.legend(),n=d3.svg.brush(),o=a.models.tooltip(),p=a.interactiveGuideline(),q={top:30,right:30,bottom:30,left:60},r={top:0,right:30,bottom:20,left:60},s=a.utils.defaultColor(),t=null,u=null,v=50,w=!1,x=!0,y=null,z=null,A=d3.dispatch("brush","stateChange","changeState"),B=250,C=a.utils.state(),D=null;g.clipEdge(!0).duration(0),h.interactive(!1),i.orient("bottom").tickPadding(5),j.orient("left"),k.orient("bottom").tickPadding(5),l.orient("left"),o.valueFormatter(function(a,b){return j.tickFormat()(a,b)}).headerFormatter(function(a,b){return i.tickFormat()(a,b)});var E=function(a){return function(){return{active:a.map(function(a){return!a.disabled})}}},F=function(a){return function(b){void 0!==b.active&&a.forEach(function(a,c){a.disabled=!b.active[c]})}};return g.dispatch.on("elementMouseover.tooltip",function(a){o.data(a).position(a.pos).hidden(!1)}),g.dispatch.on("elementMouseout.tooltip",function(){o.hidden(!0)}),b.dispatch=A,b.legend=m,b.lines=g,b.lines2=h,b.xAxis=i,b.yAxis=j,b.x2Axis=k,b.y2Axis=l,b.interactiveLayer=p,b.tooltip=o,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return t},set:function(a){t=a}},height:{get:function(){return u},set:function(a){u=a}},focusHeight:{get:function(){return v},set:function(a){v=a}},showLegend:{get:function(){return x},set:function(a){x=a}},brushExtent:{get:function(){return y},set:function(a){y=a}},defaultState:{get:function(){return D},set:function(a){D=a}},noData:{get:function(){return z},set:function(a){z=a}},tooltips:{get:function(){return o.enabled()},set:function(b){a.deprecated("tooltips","use chart.tooltip.enabled() instead"),o.enabled(!!b)}},tooltipContent:{get:function(){return o.contentGenerator()},set:function(b){a.deprecated("tooltipContent","use chart.tooltip.contentGenerator() instead"),o.contentGenerator(b)}},margin:{get:function(){return q},set:function(a){q.top=void 0!==a.top?a.top:q.top,q.right=void 0!==a.right?a.right:q.right,q.bottom=void 0!==a.bottom?a.bottom:q.bottom,q.left=void 0!==a.left?a.left:q.left}},color:{get:function(){return s},set:function(b){s=a.utils.getColor(b),m.color(s)}},interpolate:{get:function(){return g.interpolate()},set:function(a){g.interpolate(a),h.interpolate(a)}},xTickFormat:{get:function(){return i.tickFormat()},set:function(a){i.tickFormat(a),k.tickFormat(a)}},yTickFormat:{get:function(){return j.tickFormat()},set:function(a){j.tickFormat(a),l.tickFormat(a)}},duration:{get:function(){return B},set:function(a){B=a,j.duration(B),l.duration(B),i.duration(B),k.duration(B)}},x:{get:function(){return g.x()},set:function(a){g.x(a),h.x(a)}},y:{get:function(){return g.y()},set:function(a){g.y(a),h.y(a)}},useInteractiveGuideline:{get:function(){return w},set:function(a){w=a,w&&(g.interactive(!1),g.useVoronoi(!1))}}}),a.utils.inheritOptions(b,g),a.utils.initOptions(b),b},a.models.multiBar=function(){"use strict";function b(E){return C.reset(),E.each(function(b){var E=k-j.left-j.right,F=l-j.top-j.bottom;p=d3.select(this),a.utils.initSVG(p);var G=0;if(x&&b.length&&(x=[{values:b[0].values.map(function(a){return{x:a.x,y:0,series:a.series,size:.01}})}]),u){var H=d3.layout.stack().offset(v).values(function(a){return a.values}).y(r)(!b.length&&x?x:b);H.forEach(function(a,c){a.nonStackable?(b[c].nonStackableSeries=G++,H[c]=b[c]):c>0&&H[c-1].nonStackable&&H[c].values.map(function(a,b){a.y0-=H[c-1].values[b].y,a.y1=a.y0+a.y})}),b=H}b.forEach(function(a,b){a.values.forEach(function(c){c.series=b,c.key=a.key})}),u&&b[0].values.map(function(a,c){var d=0,e=0;b.map(function(a,f){if(!b[f].nonStackable){var g=a.values[c];g.size=Math.abs(g.y),g.y<0?(g.y1=e,e-=g.size):(g.y1=g.size+d,d+=g.size)}})});var I=d&&e?[]:b.map(function(a,b){return a.values.map(function(a,c){return{x:q(a,c),y:r(a,c),y0:a.y0,y1:a.y1,idx:b}})});m.domain(d||d3.merge(I).map(function(a){return a.x})).rangeBands(f||[0,E],A),n.domain(e||d3.extent(d3.merge(I).map(function(a){var c=a.y;return u&&!b[a.idx].nonStackable&&(c=a.y>0?a.y1:a.y1+a.y),c}).concat(s))).range(g||[F,0]),m.domain()[0]===m.domain()[1]&&m.domain(m.domain()[0]?[m.domain()[0]-.01*m.domain()[0],m.domain()[1]+.01*m.domain()[1]]:[-1,1]),n.domain()[0]===n.domain()[1]&&n.domain(n.domain()[0]?[n.domain()[0]+.01*n.domain()[0],n.domain()[1]-.01*n.domain()[1]]:[-1,1]),h=h||m,i=i||n;var J=p.selectAll("g.nv-wrap.nv-multibar").data([b]),K=J.enter().append("g").attr("class","nvd3 nv-wrap nv-multibar"),L=K.append("defs"),M=K.append("g"),N=J.select("g");M.append("g").attr("class","nv-groups"),J.attr("transform","translate("+j.left+","+j.top+")"),L.append("clipPath").attr("id","nv-edge-clip-"+o).append("rect"),J.select("#nv-edge-clip-"+o+" rect").attr("width",E).attr("height",F),N.attr("clip-path",t?"url(#nv-edge-clip-"+o+")":"");var O=J.select(".nv-groups").selectAll(".nv-group").data(function(a){return a},function(a,b){return b});O.enter().append("g").style("stroke-opacity",1e-6).style("fill-opacity",1e-6);var P=C.transition(O.exit().selectAll("rect.nv-bar"),"multibarExit",Math.min(100,z)).attr("y",function(a){var c=i(0)||0;return u&&b[a.series]&&!b[a.series].nonStackable&&(c=i(a.y0)),c}).attr("height",0).remove();P.delay&&P.delay(function(a,b){var c=b*(z/(D+1))-b;return c}),O.attr("class",function(a,b){return"nv-group nv-series-"+b}).classed("hover",function(a){return a.hover}).style("fill",function(a,b){return w(a,b)}).style("stroke",function(a,b){return w(a,b)}),O.style("stroke-opacity",1).style("fill-opacity",.75);var Q=O.selectAll("rect.nv-bar").data(function(a){return x&&!b.length?x.values:a.values});Q.exit().remove();Q.enter().append("rect").attr("class",function(a,b){return r(a,b)<0?"nv-bar negative":"nv-bar positive"}).attr("x",function(a,c,d){return u&&!b[d].nonStackable?0:d*m.rangeBand()/b.length}).attr("y",function(a,c,d){return i(u&&!b[d].nonStackable?a.y0:0)||0}).attr("height",0).attr("width",function(a,c,d){return m.rangeBand()/(u&&!b[d].nonStackable?1:b.length)}).attr("transform",function(a,b){return"translate("+m(q(a,b))+",0)"});Q.style("fill",function(a,b,c){return w(a,c,b)}).style("stroke",function(a,b,c){return w(a,c,b)}).on("mouseover",function(a,b){d3.select(this).classed("hover",!0),B.elementMouseover({data:a,index:b,color:d3.select(this).style("fill")})}).on("mouseout",function(a,b){d3.select(this).classed("hover",!1),B.elementMouseout({data:a,index:b,color:d3.select(this).style("fill")})}).on("mousemove",function(a,b){B.elementMousemove({data:a,index:b,color:d3.select(this).style("fill")})}).on("click",function(a,b){B.elementClick({data:a,index:b,color:d3.select(this).style("fill")}),d3.event.stopPropagation()}).on("dblclick",function(a,b){B.elementDblClick({data:a,index:b,color:d3.select(this).style("fill")}),d3.event.stopPropagation()}),Q.attr("class",function(a,b){return r(a,b)<0?"nv-bar negative":"nv-bar positive"}).attr("transform",function(a,b){return"translate("+m(q(a,b))+",0)"}),y&&(c||(c=b.map(function(){return!0})),Q.style("fill",function(a,b,d){return d3.rgb(y(a,b)).darker(c.map(function(a,b){return b}).filter(function(a,b){return!c[b]})[d]).toString()}).style("stroke",function(a,b,d){return d3.rgb(y(a,b)).darker(c.map(function(a,b){return b}).filter(function(a,b){return!c[b]})[d]).toString()}));var R=Q.watchTransition(C,"multibar",Math.min(250,z)).delay(function(a,c){return c*z/b[0].values.length});u?R.attr("y",function(a,c,d){var e=0;return e=b[d].nonStackable?r(a,c)<0?n(0):n(0)-n(r(a,c))<-1?n(0)-1:n(r(a,c))||0:n(a.y1)}).attr("height",function(a,c,d){return b[d].nonStackable?Math.max(Math.abs(n(r(a,c))-n(0)),1)||0:Math.max(Math.abs(n(a.y+a.y0)-n(a.y0)),1)}).attr("x",function(a,c,d){var e=0;return b[d].nonStackable&&(e=a.series*m.rangeBand()/b.length,b.length!==G&&(e=b[d].nonStackableSeries*m.rangeBand()/(2*G))),e}).attr("width",function(a,c,d){if(b[d].nonStackable){var e=m.rangeBand()/G;return b.length!==G&&(e=m.rangeBand()/(2*G)),e}return m.rangeBand()}):R.attr("x",function(a){return a.series*m.rangeBand()/b.length}).attr("width",m.rangeBand()/b.length).attr("y",function(a,b){return r(a,b)<0?n(0):n(0)-n(r(a,b))<1?n(0)-1:n(r(a,b))||0}).attr("height",function(a,b){return Math.max(Math.abs(n(r(a,b))-n(0)),1)||0}),h=m.copy(),i=n.copy(),b[0]&&b[0].values&&(D=b[0].values.length)}),C.renderEnd("multibar immediate"),b}var c,d,e,f,g,h,i,j={top:0,right:0,bottom:0,left:0},k=960,l=500,m=d3.scale.ordinal(),n=d3.scale.linear(),o=Math.floor(1e4*Math.random()),p=null,q=function(a){return a.x},r=function(a){return a.y},s=[0],t=!0,u=!1,v="zero",w=a.utils.defaultColor(),x=!1,y=null,z=500,A=.1,B=d3.dispatch("chartClick","elementClick","elementDblClick","elementMouseover","elementMouseout","elementMousemove","renderEnd"),C=a.utils.renderWatch(B,z),D=0;return b.dispatch=B,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return k},set:function(a){k=a}},height:{get:function(){return l},set:function(a){l=a}},x:{get:function(){return q},set:function(a){q=a}},y:{get:function(){return r},set:function(a){r=a}},xScale:{get:function(){return m},set:function(a){m=a}},yScale:{get:function(){return n},set:function(a){n=a}},xDomain:{get:function(){return d},set:function(a){d=a}},yDomain:{get:function(){return e},set:function(a){e=a}},xRange:{get:function(){return f},set:function(a){f=a}},yRange:{get:function(){return g},set:function(a){g=a}},forceY:{get:function(){return s},set:function(a){s=a}},stacked:{get:function(){return u},set:function(a){u=a}},stackOffset:{get:function(){return v},set:function(a){v=a}},clipEdge:{get:function(){return t},set:function(a){t=a}},disabled:{get:function(){return c},set:function(a){c=a}},id:{get:function(){return o},set:function(a){o=a}},hideable:{get:function(){return x},set:function(a){x=a}},groupSpacing:{get:function(){return A},set:function(a){A=a}},margin:{get:function(){return j},set:function(a){j.top=void 0!==a.top?a.top:j.top,j.right=void 0!==a.right?a.right:j.right,j.bottom=void 0!==a.bottom?a.bottom:j.bottom,j.left=void 0!==a.left?a.left:j.left}},duration:{get:function(){return z},set:function(a){z=a,C.reset(z)}},color:{get:function(){return w},set:function(b){w=a.utils.getColor(b)}},barColor:{get:function(){return y},set:function(b){y=b?a.utils.getColor(b):null}}}),a.utils.initOptions(b),b},a.models.multiBarChart=function(){"use strict";function b(j){return D.reset(),D.models(e),r&&D.models(f),s&&D.models(g),j.each(function(j){var z=d3.select(this);a.utils.initSVG(z);var D=a.utils.availableWidth(l,z,k),H=a.utils.availableHeight(m,z,k);if(b.update=function(){0===C?z.call(b):z.transition().duration(C).call(b)},b.container=this,x.setter(G(j),b.update).getter(F(j)).update(),x.disabled=j.map(function(a){return!!a.disabled}),!y){var I;y={};for(I in x)y[I]=x[I]instanceof Array?x[I].slice(0):x[I]}if(!(j&&j.length&&j.filter(function(a){return a.values.length}).length))return a.utils.noData(b,z),b;z.selectAll(".nv-noData").remove(),c=e.xScale(),d=e.yScale();
+var J=z.selectAll("g.nv-wrap.nv-multiBarWithLegend").data([j]),K=J.enter().append("g").attr("class","nvd3 nv-wrap nv-multiBarWithLegend").append("g"),L=J.select("g");if(K.append("g").attr("class","nv-x nv-axis"),K.append("g").attr("class","nv-y nv-axis"),K.append("g").attr("class","nv-barsWrap"),K.append("g").attr("class","nv-legendWrap"),K.append("g").attr("class","nv-controlsWrap"),q&&(h.width(D-B()),L.select(".nv-legendWrap").datum(j).call(h),k.top!=h.height()&&(k.top=h.height(),H=a.utils.availableHeight(m,z,k)),L.select(".nv-legendWrap").attr("transform","translate("+B()+","+-k.top+")")),o){var M=[{key:p.grouped||"Grouped",disabled:e.stacked()},{key:p.stacked||"Stacked",disabled:!e.stacked()}];i.width(B()).color(["#444","#444","#444"]),L.select(".nv-controlsWrap").datum(M).attr("transform","translate(0,"+-k.top+")").call(i)}J.attr("transform","translate("+k.left+","+k.top+")"),t&&L.select(".nv-y.nv-axis").attr("transform","translate("+D+",0)"),e.disabled(j.map(function(a){return a.disabled})).width(D).height(H).color(j.map(function(a,b){return a.color||n(a,b)}).filter(function(a,b){return!j[b].disabled}));var N=L.select(".nv-barsWrap").datum(j.filter(function(a){return!a.disabled}));if(N.call(e),r){f.scale(c)._ticks(a.utils.calcTicksX(D/100,j)).tickSize(-H,0),L.select(".nv-x.nv-axis").attr("transform","translate(0,"+d.range()[0]+")"),L.select(".nv-x.nv-axis").call(f);var O=L.select(".nv-x.nv-axis > g").selectAll("g");if(O.selectAll("line, text").style("opacity",1),v){var P=function(a,b){return"translate("+a+","+b+")"},Q=5,R=17;O.selectAll("text").attr("transform",function(a,b,c){return P(0,c%2==0?Q:R)});var S=d3.selectAll(".nv-x.nv-axis .nv-wrap g g text")[0].length;L.selectAll(".nv-x.nv-axis .nv-axisMaxMin text").attr("transform",function(a,b){return P(0,0===b||S%2!==0?R:Q)})}u&&O.filter(function(a,b){return b%Math.ceil(j[0].values.length/(D/100))!==0}).selectAll("text, line").style("opacity",0),w&&O.selectAll(".tick text").attr("transform","rotate("+w+" 0,0)").style("text-anchor",w>0?"start":"end"),L.select(".nv-x.nv-axis").selectAll("g.nv-axisMaxMin text").style("opacity",1)}s&&(g.scale(d)._ticks(a.utils.calcTicksY(H/36,j)).tickSize(-D,0),L.select(".nv-y.nv-axis").call(g)),h.dispatch.on("stateChange",function(a){for(var c in a)x[c]=a[c];A.stateChange(x),b.update()}),i.dispatch.on("legendClick",function(a){if(a.disabled){switch(M=M.map(function(a){return a.disabled=!0,a}),a.disabled=!1,a.key){case"Grouped":case p.grouped:e.stacked(!1);break;case"Stacked":case p.stacked:e.stacked(!0)}x.stacked=e.stacked(),A.stateChange(x),b.update()}}),A.on("changeState",function(a){"undefined"!=typeof a.disabled&&(j.forEach(function(b,c){b.disabled=a.disabled[c]}),x.disabled=a.disabled),"undefined"!=typeof a.stacked&&(e.stacked(a.stacked),x.stacked=a.stacked,E=a.stacked),b.update()})}),D.renderEnd("multibarchart immediate"),b}var c,d,e=a.models.multiBar(),f=a.models.axis(),g=a.models.axis(),h=a.models.legend(),i=a.models.legend(),j=a.models.tooltip(),k={top:30,right:20,bottom:50,left:60},l=null,m=null,n=a.utils.defaultColor(),o=!0,p={},q=!0,r=!0,s=!0,t=!1,u=!0,v=!1,w=0,x=a.utils.state(),y=null,z=null,A=d3.dispatch("stateChange","changeState","renderEnd"),B=function(){return o?180:0},C=250;x.stacked=!1,e.stacked(!1),f.orient("bottom").tickPadding(7).showMaxMin(!1).tickFormat(function(a){return a}),g.orient(t?"right":"left").tickFormat(d3.format(",.1f")),j.duration(0).valueFormatter(function(a,b){return g.tickFormat()(a,b)}).headerFormatter(function(a,b){return f.tickFormat()(a,b)}),i.updateState(!1);var D=a.utils.renderWatch(A),E=!1,F=function(a){return function(){return{active:a.map(function(a){return!a.disabled}),stacked:E}}},G=function(a){return function(b){void 0!==b.stacked&&(E=b.stacked),void 0!==b.active&&a.forEach(function(a,c){a.disabled=!b.active[c]})}};return e.dispatch.on("elementMouseover.tooltip",function(a){a.value=b.x()(a.data),a.series={key:a.data.key,value:b.y()(a.data),color:a.color},j.data(a).hidden(!1)}),e.dispatch.on("elementMouseout.tooltip",function(){j.hidden(!0)}),e.dispatch.on("elementMousemove.tooltip",function(){j.position({top:d3.event.pageY,left:d3.event.pageX})()}),b.dispatch=A,b.multibar=e,b.legend=h,b.controls=i,b.xAxis=f,b.yAxis=g,b.state=x,b.tooltip=j,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return l},set:function(a){l=a}},height:{get:function(){return m},set:function(a){m=a}},showLegend:{get:function(){return q},set:function(a){q=a}},showControls:{get:function(){return o},set:function(a){o=a}},controlLabels:{get:function(){return p},set:function(a){p=a}},showXAxis:{get:function(){return r},set:function(a){r=a}},showYAxis:{get:function(){return s},set:function(a){s=a}},defaultState:{get:function(){return y},set:function(a){y=a}},noData:{get:function(){return z},set:function(a){z=a}},reduceXTicks:{get:function(){return u},set:function(a){u=a}},rotateLabels:{get:function(){return w},set:function(a){w=a}},staggerLabels:{get:function(){return v},set:function(a){v=a}},tooltips:{get:function(){return j.enabled()},set:function(b){a.deprecated("tooltips","use chart.tooltip.enabled() instead"),j.enabled(!!b)}},tooltipContent:{get:function(){return j.contentGenerator()},set:function(b){a.deprecated("tooltipContent","use chart.tooltip.contentGenerator() instead"),j.contentGenerator(b)}},margin:{get:function(){return k},set:function(a){k.top=void 0!==a.top?a.top:k.top,k.right=void 0!==a.right?a.right:k.right,k.bottom=void 0!==a.bottom?a.bottom:k.bottom,k.left=void 0!==a.left?a.left:k.left}},duration:{get:function(){return C},set:function(a){C=a,e.duration(C),f.duration(C),g.duration(C),D.reset(C)}},color:{get:function(){return n},set:function(b){n=a.utils.getColor(b),h.color(n)}},rightAlignYAxis:{get:function(){return t},set:function(a){t=a,g.orient(t?"right":"left")}},barColor:{get:function(){return e.barColor},set:function(a){e.barColor(a),h.color(function(a,b){return d3.rgb("#ccc").darker(1.5*b).toString()})}}}),a.utils.inheritOptions(b,e),a.utils.initOptions(b),b},a.models.multiBarHorizontal=function(){"use strict";function b(m){return E.reset(),m.each(function(b){var m=k-j.left-j.right,C=l-j.top-j.bottom;n=d3.select(this),a.utils.initSVG(n),w&&(b=d3.layout.stack().offset("zero").values(function(a){return a.values}).y(r)(b)),b.forEach(function(a,b){a.values.forEach(function(c){c.series=b,c.key=a.key})}),w&&b[0].values.map(function(a,c){var d=0,e=0;b.map(function(a){var b=a.values[c];b.size=Math.abs(b.y),b.y<0?(b.y1=e-b.size,e-=b.size):(b.y1=d,d+=b.size)})});var F=d&&e?[]:b.map(function(a){return a.values.map(function(a,b){return{x:q(a,b),y:r(a,b),y0:a.y0,y1:a.y1}})});o.domain(d||d3.merge(F).map(function(a){return a.x})).rangeBands(f||[0,C],A),p.domain(e||d3.extent(d3.merge(F).map(function(a){return w?a.y>0?a.y1+a.y:a.y1:a.y}).concat(t))),p.range(x&&!w?g||[p.domain()[0]<0?z:0,m-(p.domain()[1]>0?z:0)]:g||[0,m]),h=h||o,i=i||d3.scale.linear().domain(p.domain()).range([p(0),p(0)]);{var G=d3.select(this).selectAll("g.nv-wrap.nv-multibarHorizontal").data([b]),H=G.enter().append("g").attr("class","nvd3 nv-wrap nv-multibarHorizontal"),I=(H.append("defs"),H.append("g"));G.select("g")}I.append("g").attr("class","nv-groups"),G.attr("transform","translate("+j.left+","+j.top+")");var J=G.select(".nv-groups").selectAll(".nv-group").data(function(a){return a},function(a,b){return b});J.enter().append("g").style("stroke-opacity",1e-6).style("fill-opacity",1e-6),J.exit().watchTransition(E,"multibarhorizontal: exit groups").style("stroke-opacity",1e-6).style("fill-opacity",1e-6).remove(),J.attr("class",function(a,b){return"nv-group nv-series-"+b}).classed("hover",function(a){return a.hover}).style("fill",function(a,b){return u(a,b)}).style("stroke",function(a,b){return u(a,b)}),J.watchTransition(E,"multibarhorizontal: groups").style("stroke-opacity",1).style("fill-opacity",.75);var K=J.selectAll("g.nv-bar").data(function(a){return a.values});K.exit().remove();var L=K.enter().append("g").attr("transform",function(a,c,d){return"translate("+i(w?a.y0:0)+","+(w?0:d*o.rangeBand()/b.length+o(q(a,c)))+")"});L.append("rect").attr("width",0).attr("height",o.rangeBand()/(w?1:b.length)),K.on("mouseover",function(a,b){d3.select(this).classed("hover",!0),D.elementMouseover({data:a,index:b,color:d3.select(this).style("fill")})}).on("mouseout",function(a,b){d3.select(this).classed("hover",!1),D.elementMouseout({data:a,index:b,color:d3.select(this).style("fill")})}).on("mouseout",function(a,b){D.elementMouseout({data:a,index:b,color:d3.select(this).style("fill")})}).on("mousemove",function(a,b){D.elementMousemove({data:a,index:b,color:d3.select(this).style("fill")})}).on("click",function(a,b){D.elementClick({data:a,index:b,color:d3.select(this).style("fill")}),d3.event.stopPropagation()}).on("dblclick",function(a,b){D.elementDblClick({data:a,index:b,color:d3.select(this).style("fill")}),d3.event.stopPropagation()}),s(b[0],0)&&(L.append("polyline"),K.select("polyline").attr("fill","none").attr("points",function(a,c){var d=s(a,c),e=.8*o.rangeBand()/(2*(w?1:b.length));d=d.length?d:[-Math.abs(d),Math.abs(d)],d=d.map(function(a){return p(a)-p(0)});var f=[[d[0],-e],[d[0],e],[d[0],0],[d[1],0],[d[1],-e],[d[1],e]];return f.map(function(a){return a.join(",")}).join(" ")}).attr("transform",function(a,c){var d=o.rangeBand()/(2*(w?1:b.length));return"translate("+(r(a,c)<0?0:p(r(a,c))-p(0))+", "+d+")"})),L.append("text"),x&&!w?(K.select("text").attr("text-anchor",function(a,b){return r(a,b)<0?"end":"start"}).attr("y",o.rangeBand()/(2*b.length)).attr("dy",".32em").text(function(a,b){var c=B(r(a,b)),d=s(a,b);return void 0===d?c:d.length?c+"+"+B(Math.abs(d[1]))+"-"+B(Math.abs(d[0])):c+"±"+B(Math.abs(d))}),K.watchTransition(E,"multibarhorizontal: bars").select("text").attr("x",function(a,b){return r(a,b)<0?-4:p(r(a,b))-p(0)+4})):K.selectAll("text").text(""),y&&!w?(L.append("text").classed("nv-bar-label",!0),K.select("text.nv-bar-label").attr("text-anchor",function(a,b){return r(a,b)<0?"start":"end"}).attr("y",o.rangeBand()/(2*b.length)).attr("dy",".32em").text(function(a,b){return q(a,b)}),K.watchTransition(E,"multibarhorizontal: bars").select("text.nv-bar-label").attr("x",function(a,b){return r(a,b)<0?p(0)-p(r(a,b))+4:-4})):K.selectAll("text.nv-bar-label").text(""),K.attr("class",function(a,b){return r(a,b)<0?"nv-bar negative":"nv-bar positive"}),v&&(c||(c=b.map(function(){return!0})),K.style("fill",function(a,b,d){return d3.rgb(v(a,b)).darker(c.map(function(a,b){return b}).filter(function(a,b){return!c[b]})[d]).toString()}).style("stroke",function(a,b,d){return d3.rgb(v(a,b)).darker(c.map(function(a,b){return b}).filter(function(a,b){return!c[b]})[d]).toString()})),w?K.watchTransition(E,"multibarhorizontal: bars").attr("transform",function(a,b){return"translate("+p(a.y1)+","+o(q(a,b))+")"}).select("rect").attr("width",function(a,b){return Math.abs(p(r(a,b)+a.y0)-p(a.y0))}).attr("height",o.rangeBand()):K.watchTransition(E,"multibarhorizontal: bars").attr("transform",function(a,c){return"translate("+p(r(a,c)<0?r(a,c):0)+","+(a.series*o.rangeBand()/b.length+o(q(a,c)))+")"}).select("rect").attr("height",o.rangeBand()/b.length).attr("width",function(a,b){return Math.max(Math.abs(p(r(a,b))-p(0)),1)}),h=o.copy(),i=p.copy()}),E.renderEnd("multibarHorizontal immediate"),b}var c,d,e,f,g,h,i,j={top:0,right:0,bottom:0,left:0},k=960,l=500,m=Math.floor(1e4*Math.random()),n=null,o=d3.scale.ordinal(),p=d3.scale.linear(),q=function(a){return a.x},r=function(a){return a.y},s=function(a){return a.yErr},t=[0],u=a.utils.defaultColor(),v=null,w=!1,x=!1,y=!1,z=60,A=.1,B=d3.format(",.2f"),C=250,D=d3.dispatch("chartClick","elementClick","elementDblClick","elementMouseover","elementMouseout","elementMousemove","renderEnd"),E=a.utils.renderWatch(D,C);return b.dispatch=D,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return k},set:function(a){k=a}},height:{get:function(){return l},set:function(a){l=a}},x:{get:function(){return q},set:function(a){q=a}},y:{get:function(){return r},set:function(a){r=a}},yErr:{get:function(){return s},set:function(a){s=a}},xScale:{get:function(){return o},set:function(a){o=a}},yScale:{get:function(){return p},set:function(a){p=a}},xDomain:{get:function(){return d},set:function(a){d=a}},yDomain:{get:function(){return e},set:function(a){e=a}},xRange:{get:function(){return f},set:function(a){f=a}},yRange:{get:function(){return g},set:function(a){g=a}},forceY:{get:function(){return t},set:function(a){t=a}},stacked:{get:function(){return w},set:function(a){w=a}},showValues:{get:function(){return x},set:function(a){x=a}},disabled:{get:function(){return c},set:function(a){c=a}},id:{get:function(){return m},set:function(a){m=a}},valueFormat:{get:function(){return B},set:function(a){B=a}},valuePadding:{get:function(){return z},set:function(a){z=a}},groupSpacing:{get:function(){return A},set:function(a){A=a}},margin:{get:function(){return j},set:function(a){j.top=void 0!==a.top?a.top:j.top,j.right=void 0!==a.right?a.right:j.right,j.bottom=void 0!==a.bottom?a.bottom:j.bottom,j.left=void 0!==a.left?a.left:j.left}},duration:{get:function(){return C},set:function(a){C=a,E.reset(C)}},color:{get:function(){return u},set:function(b){u=a.utils.getColor(b)}},barColor:{get:function(){return v},set:function(b){v=b?a.utils.getColor(b):null}}}),a.utils.initOptions(b),b},a.models.multiBarHorizontalChart=function(){"use strict";function b(j){return C.reset(),C.models(e),r&&C.models(f),s&&C.models(g),j.each(function(j){var w=d3.select(this);a.utils.initSVG(w);var C=a.utils.availableWidth(l,w,k),D=a.utils.availableHeight(m,w,k);if(b.update=function(){w.transition().duration(z).call(b)},b.container=this,t=e.stacked(),u.setter(B(j),b.update).getter(A(j)).update(),u.disabled=j.map(function(a){return!!a.disabled}),!v){var E;v={};for(E in u)v[E]=u[E]instanceof Array?u[E].slice(0):u[E]}if(!(j&&j.length&&j.filter(function(a){return a.values.length}).length))return a.utils.noData(b,w),b;w.selectAll(".nv-noData").remove(),c=e.xScale(),d=e.yScale();var F=w.selectAll("g.nv-wrap.nv-multiBarHorizontalChart").data([j]),G=F.enter().append("g").attr("class","nvd3 nv-wrap nv-multiBarHorizontalChart").append("g"),H=F.select("g");if(G.append("g").attr("class","nv-x nv-axis"),G.append("g").attr("class","nv-y nv-axis").append("g").attr("class","nv-zeroLine").append("line"),G.append("g").attr("class","nv-barsWrap"),G.append("g").attr("class","nv-legendWrap"),G.append("g").attr("class","nv-controlsWrap"),q&&(h.width(C-y()),H.select(".nv-legendWrap").datum(j).call(h),k.top!=h.height()&&(k.top=h.height(),D=a.utils.availableHeight(m,w,k)),H.select(".nv-legendWrap").attr("transform","translate("+y()+","+-k.top+")")),o){var I=[{key:p.grouped||"Grouped",disabled:e.stacked()},{key:p.stacked||"Stacked",disabled:!e.stacked()}];i.width(y()).color(["#444","#444","#444"]),H.select(".nv-controlsWrap").datum(I).attr("transform","translate(0,"+-k.top+")").call(i)}F.attr("transform","translate("+k.left+","+k.top+")"),e.disabled(j.map(function(a){return a.disabled})).width(C).height(D).color(j.map(function(a,b){return a.color||n(a,b)}).filter(function(a,b){return!j[b].disabled}));var J=H.select(".nv-barsWrap").datum(j.filter(function(a){return!a.disabled}));if(J.transition().call(e),r){f.scale(c)._ticks(a.utils.calcTicksY(D/24,j)).tickSize(-C,0),H.select(".nv-x.nv-axis").call(f);var K=H.select(".nv-x.nv-axis").selectAll("g");K.selectAll("line, text")}s&&(g.scale(d)._ticks(a.utils.calcTicksX(C/100,j)).tickSize(-D,0),H.select(".nv-y.nv-axis").attr("transform","translate(0,"+D+")"),H.select(".nv-y.nv-axis").call(g)),H.select(".nv-zeroLine line").attr("x1",d(0)).attr("x2",d(0)).attr("y1",0).attr("y2",-D),h.dispatch.on("stateChange",function(a){for(var c in a)u[c]=a[c];x.stateChange(u),b.update()}),i.dispatch.on("legendClick",function(a){if(a.disabled){switch(I=I.map(function(a){return a.disabled=!0,a}),a.disabled=!1,a.key){case"Grouped":e.stacked(!1);break;case"Stacked":e.stacked(!0)}u.stacked=e.stacked(),x.stateChange(u),t=e.stacked(),b.update()}}),x.on("changeState",function(a){"undefined"!=typeof a.disabled&&(j.forEach(function(b,c){b.disabled=a.disabled[c]}),u.disabled=a.disabled),"undefined"!=typeof a.stacked&&(e.stacked(a.stacked),u.stacked=a.stacked,t=a.stacked),b.update()})}),C.renderEnd("multibar horizontal chart immediate"),b}var c,d,e=a.models.multiBarHorizontal(),f=a.models.axis(),g=a.models.axis(),h=a.models.legend().height(30),i=a.models.legend().height(30),j=a.models.tooltip(),k={top:30,right:20,bottom:50,left:60},l=null,m=null,n=a.utils.defaultColor(),o=!0,p={},q=!0,r=!0,s=!0,t=!1,u=a.utils.state(),v=null,w=null,x=d3.dispatch("stateChange","changeState","renderEnd"),y=function(){return o?180:0},z=250;u.stacked=!1,e.stacked(t),f.orient("left").tickPadding(5).showMaxMin(!1).tickFormat(function(a){return a}),g.orient("bottom").tickFormat(d3.format(",.1f")),j.duration(0).valueFormatter(function(a,b){return g.tickFormat()(a,b)}).headerFormatter(function(a,b){return f.tickFormat()(a,b)}),i.updateState(!1);var A=function(a){return function(){return{active:a.map(function(a){return!a.disabled}),stacked:t}}},B=function(a){return function(b){void 0!==b.stacked&&(t=b.stacked),void 0!==b.active&&a.forEach(function(a,c){a.disabled=!b.active[c]})}},C=a.utils.renderWatch(x,z);return e.dispatch.on("elementMouseover.tooltip",function(a){a.value=b.x()(a.data),a.series={key:a.data.key,value:b.y()(a.data),color:a.color},j.data(a).hidden(!1)}),e.dispatch.on("elementMouseout.tooltip",function(){j.hidden(!0)}),e.dispatch.on("elementMousemove.tooltip",function(){j.position({top:d3.event.pageY,left:d3.event.pageX})()}),b.dispatch=x,b.multibar=e,b.legend=h,b.controls=i,b.xAxis=f,b.yAxis=g,b.state=u,b.tooltip=j,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return l},set:function(a){l=a}},height:{get:function(){return m},set:function(a){m=a}},showLegend:{get:function(){return q},set:function(a){q=a}},showControls:{get:function(){return o},set:function(a){o=a}},controlLabels:{get:function(){return p},set:function(a){p=a}},showXAxis:{get:function(){return r},set:function(a){r=a}},showYAxis:{get:function(){return s},set:function(a){s=a}},defaultState:{get:function(){return v},set:function(a){v=a}},noData:{get:function(){return w},set:function(a){w=a}},tooltips:{get:function(){return j.enabled()},set:function(b){a.deprecated("tooltips","use chart.tooltip.enabled() instead"),j.enabled(!!b)}},tooltipContent:{get:function(){return j.contentGenerator()},set:function(b){a.deprecated("tooltipContent","use chart.tooltip.contentGenerator() instead"),j.contentGenerator(b)}},margin:{get:function(){return k},set:function(a){k.top=void 0!==a.top?a.top:k.top,k.right=void 0!==a.right?a.right:k.right,k.bottom=void 0!==a.bottom?a.bottom:k.bottom,k.left=void 0!==a.left?a.left:k.left}},duration:{get:function(){return z},set:function(a){z=a,C.reset(z),e.duration(z),f.duration(z),g.duration(z)}},color:{get:function(){return n},set:function(b){n=a.utils.getColor(b),h.color(n)}},barColor:{get:function(){return e.barColor},set:function(a){e.barColor(a),h.color(function(a,b){return d3.rgb("#ccc").darker(1.5*b).toString()})}}}),a.utils.inheritOptions(b,e),a.utils.initOptions(b),b},a.models.multiChart=function(){"use strict";function b(j){return j.each(function(j){function k(a){var b=2===j[a.seriesIndex].yAxis?z:y;a.value=a.point.x,a.series={value:a.point.y,color:a.point.color},B.duration(100).valueFormatter(function(a,c){return b.tickFormat()(a,c)}).data(a).position(a.pos).hidden(!1)}function l(a){var b=2===j[a.seriesIndex].yAxis?z:y;a.point.x=v.x()(a.point),a.point.y=v.y()(a.point),B.duration(100).valueFormatter(function(a,c){return b.tickFormat()(a,c)}).data(a).position(a.pos).hidden(!1)}function n(a){var b=2===j[a.data.series].yAxis?z:y;a.value=t.x()(a.data),a.series={value:t.y()(a.data),color:a.color},B.duration(0).valueFormatter(function(a,c){return b.tickFormat()(a,c)}).data(a).hidden(!1)}var C=d3.select(this);a.utils.initSVG(C),b.update=function(){C.transition().call(b)},b.container=this;var D=a.utils.availableWidth(g,C,e),E=a.utils.availableHeight(h,C,e),F=j.filter(function(a){return"line"==a.type&&1==a.yAxis}),G=j.filter(function(a){return"line"==a.type&&2==a.yAxis}),H=j.filter(function(a){return"bar"==a.type&&1==a.yAxis}),I=j.filter(function(a){return"bar"==a.type&&2==a.yAxis}),J=j.filter(function(a){return"area"==a.type&&1==a.yAxis}),K=j.filter(function(a){return"area"==a.type&&2==a.yAxis});if(!(j&&j.length&&j.filter(function(a){return a.values.length}).length))return a.utils.noData(b,C),b;C.selectAll(".nv-noData").remove();var L=j.filter(function(a){return!a.disabled&&1==a.yAxis}).map(function(a){return a.values.map(function(a){return{x:a.x,y:a.y}})}),M=j.filter(function(a){return!a.disabled&&2==a.yAxis}).map(function(a){return a.values.map(function(a){return{x:a.x,y:a.y}})});o.domain(d3.extent(d3.merge(L.concat(M)),function(a){return a.x})).range([0,D]);var N=C.selectAll("g.wrap.multiChart").data([j]),O=N.enter().append("g").attr("class","wrap nvd3 multiChart").append("g");O.append("g").attr("class","nv-x nv-axis"),O.append("g").attr("class","nv-y1 nv-axis"),O.append("g").attr("class","nv-y2 nv-axis"),O.append("g").attr("class","lines1Wrap"),O.append("g").attr("class","lines2Wrap"),O.append("g").attr("class","bars1Wrap"),O.append("g").attr("class","bars2Wrap"),O.append("g").attr("class","stack1Wrap"),O.append("g").attr("class","stack2Wrap"),O.append("g").attr("class","legendWrap");var P=N.select("g"),Q=j.map(function(a,b){return j[b].color||f(a,b)});if(i){var R=A.align()?D/2:D,S=A.align()?R:0;A.width(R),A.color(Q),P.select(".legendWrap").datum(j.map(function(a){return a.originalKey=void 0===a.originalKey?a.key:a.originalKey,a.key=a.originalKey+(1==a.yAxis?"":" (right axis)"),a})).call(A),e.top!=A.height()&&(e.top=A.height(),E=a.utils.availableHeight(h,C,e)),P.select(".legendWrap").attr("transform","translate("+S+","+-e.top+")")}r.width(D).height(E).interpolate(m).color(Q.filter(function(a,b){return!j[b].disabled&&1==j[b].yAxis&&"line"==j[b].type})),s.width(D).height(E).interpolate(m).color(Q.filter(function(a,b){return!j[b].disabled&&2==j[b].yAxis&&"line"==j[b].type})),t.width(D).height(E).color(Q.filter(function(a,b){return!j[b].disabled&&1==j[b].yAxis&&"bar"==j[b].type})),u.width(D).height(E).color(Q.filter(function(a,b){return!j[b].disabled&&2==j[b].yAxis&&"bar"==j[b].type})),v.width(D).height(E).color(Q.filter(function(a,b){return!j[b].disabled&&1==j[b].yAxis&&"area"==j[b].type})),w.width(D).height(E).color(Q.filter(function(a,b){return!j[b].disabled&&2==j[b].yAxis&&"area"==j[b].type})),P.attr("transform","translate("+e.left+","+e.top+")");var T=P.select(".lines1Wrap").datum(F.filter(function(a){return!a.disabled})),U=P.select(".bars1Wrap").datum(H.filter(function(a){return!a.disabled})),V=P.select(".stack1Wrap").datum(J.filter(function(a){return!a.disabled})),W=P.select(".lines2Wrap").datum(G.filter(function(a){return!a.disabled})),X=P.select(".bars2Wrap").datum(I.filter(function(a){return!a.disabled})),Y=P.select(".stack2Wrap").datum(K.filter(function(a){return!a.disabled})),Z=J.length?J.map(function(a){return a.values}).reduce(function(a,b){return a.map(function(a,c){return{x:a.x,y:a.y+b[c].y}})}).concat([{x:0,y:0}]):[],$=K.length?K.map(function(a){return a.values}).reduce(function(a,b){return a.map(function(a,c){return{x:a.x,y:a.y+b[c].y}})}).concat([{x:0,y:0}]):[];p.domain(c||d3.extent(d3.merge(L).concat(Z),function(a){return a.y})).range([0,E]),q.domain(d||d3.extent(d3.merge(M).concat($),function(a){return a.y})).range([0,E]),r.yDomain(p.domain()),t.yDomain(p.domain()),v.yDomain(p.domain()),s.yDomain(q.domain()),u.yDomain(q.domain()),w.yDomain(q.domain()),J.length&&d3.transition(V).call(v),K.length&&d3.transition(Y).call(w),H.length&&d3.transition(U).call(t),I.length&&d3.transition(X).call(u),F.length&&d3.transition(T).call(r),G.length&&d3.transition(W).call(s),x._ticks(a.utils.calcTicksX(D/100,j)).tickSize(-E,0),P.select(".nv-x.nv-axis").attr("transform","translate(0,"+E+")"),d3.transition(P.select(".nv-x.nv-axis")).call(x),y._ticks(a.utils.calcTicksY(E/36,j)).tickSize(-D,0),d3.transition(P.select(".nv-y1.nv-axis")).call(y),z._ticks(a.utils.calcTicksY(E/36,j)).tickSize(-D,0),d3.transition(P.select(".nv-y2.nv-axis")).call(z),P.select(".nv-y1.nv-axis").classed("nv-disabled",L.length?!1:!0).attr("transform","translate("+o.range()[0]+",0)"),P.select(".nv-y2.nv-axis").classed("nv-disabled",M.length?!1:!0).attr("transform","translate("+o.range()[1]+",0)"),A.dispatch.on("stateChange",function(){b.update()}),r.dispatch.on("elementMouseover.tooltip",k),s.dispatch.on("elementMouseover.tooltip",k),r.dispatch.on("elementMouseout.tooltip",function(){B.hidden(!0)}),s.dispatch.on("elementMouseout.tooltip",function(){B.hidden(!0)}),v.dispatch.on("elementMouseover.tooltip",l),w.dispatch.on("elementMouseover.tooltip",l),v.dispatch.on("elementMouseout.tooltip",function(){B.hidden(!0)}),w.dispatch.on("elementMouseout.tooltip",function(){B.hidden(!0)}),t.dispatch.on("elementMouseover.tooltip",n),u.dispatch.on("elementMouseover.tooltip",n),t.dispatch.on("elementMouseout.tooltip",function(){B.hidden(!0)}),u.dispatch.on("elementMouseout.tooltip",function(){B.hidden(!0)}),t.dispatch.on("elementMousemove.tooltip",function(){B.position({top:d3.event.pageY,left:d3.event.pageX})()}),u.dispatch.on("elementMousemove.tooltip",function(){B.position({top:d3.event.pageY,left:d3.event.pageX})()})}),b}var c,d,e={top:30,right:20,bottom:50,left:60},f=a.utils.defaultColor(),g=null,h=null,i=!0,j=null,k=function(a){return a.x},l=function(a){return a.y},m="monotone",n=!0,o=d3.scale.linear(),p=d3.scale.linear(),q=d3.scale.linear(),r=a.models.line().yScale(p),s=a.models.line().yScale(q),t=a.models.multiBar().stacked(!1).yScale(p),u=a.models.multiBar().stacked(!1).yScale(q),v=a.models.stackedArea().yScale(p),w=a.models.stackedArea().yScale(q),x=a.models.axis().scale(o).orient("bottom").tickPadding(5),y=a.models.axis().scale(p).orient("left"),z=a.models.axis().scale(q).orient("right"),A=a.models.legend().height(30),B=a.models.tooltip(),C=d3.dispatch();return b.dispatch=C,b.lines1=r,b.lines2=s,b.bars1=t,b.bars2=u,b.stack1=v,b.stack2=w,b.xAxis=x,b.yAxis1=y,b.yAxis2=z,b.tooltip=B,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return g},set:function(a){g=a}},height:{get:function(){return h},set:function(a){h=a}},showLegend:{get:function(){return i},set:function(a){i=a}},yDomain1:{get:function(){return c},set:function(a){c=a}},yDomain2:{get:function(){return d},set:function(a){d=a}},noData:{get:function(){return j},set:function(a){j=a}},interpolate:{get:function(){return m},set:function(a){m=a}},tooltips:{get:function(){return B.enabled()},set:function(b){a.deprecated("tooltips","use chart.tooltip.enabled() instead"),B.enabled(!!b)}},tooltipContent:{get:function(){return B.contentGenerator()},set:function(b){a.deprecated("tooltipContent","use chart.tooltip.contentGenerator() instead"),B.contentGenerator(b)}},margin:{get:function(){return e},set:function(a){e.top=void 0!==a.top?a.top:e.top,e.right=void 0!==a.right?a.right:e.right,e.bottom=void 0!==a.bottom?a.bottom:e.bottom,e.left=void 0!==a.left?a.left:e.left}},color:{get:function(){return f},set:function(b){f=a.utils.getColor(b)}},x:{get:function(){return k},set:function(a){k=a,r.x(a),s.x(a),t.x(a),u.x(a),v.x(a),w.x(a)}},y:{get:function(){return l},set:function(a){l=a,r.y(a),s.y(a),v.y(a),w.y(a),t.y(a),u.y(a)}},useVoronoi:{get:function(){return n},set:function(a){n=a,r.useVoronoi(a),s.useVoronoi(a),v.useVoronoi(a),w.useVoronoi(a)}}}),a.utils.initOptions(b),b},a.models.ohlcBar=function(){"use strict";function b(y){return y.each(function(b){k=d3.select(this);var y=a.utils.availableWidth(h,k,g),A=a.utils.availableHeight(i,k,g);a.utils.initSVG(k);var B=y/b[0].values.length*.9;l.domain(c||d3.extent(b[0].values.map(n).concat(t))),l.range(v?e||[.5*y/b[0].values.length,y*(b[0].values.length-.5)/b[0].values.length]:e||[5+B/2,y-B/2-5]),m.domain(d||[d3.min(b[0].values.map(s).concat(u)),d3.max(b[0].values.map(r).concat(u))]).range(f||[A,0]),l.domain()[0]===l.domain()[1]&&l.domain(l.domain()[0]?[l.domain()[0]-.01*l.domain()[0],l.domain()[1]+.01*l.domain()[1]]:[-1,1]),m.domain()[0]===m.domain()[1]&&m.domain(m.domain()[0]?[m.domain()[0]+.01*m.domain()[0],m.domain()[1]-.01*m.domain()[1]]:[-1,1]);var C=d3.select(this).selectAll("g.nv-wrap.nv-ohlcBar").data([b[0].values]),D=C.enter().append("g").attr("class","nvd3 nv-wrap nv-ohlcBar"),E=D.append("defs"),F=D.append("g"),G=C.select("g");F.append("g").attr("class","nv-ticks"),C.attr("transform","translate("+g.left+","+g.top+")"),k.on("click",function(a,b){z.chartClick({data:a,index:b,pos:d3.event,id:j})}),E.append("clipPath").attr("id","nv-chart-clip-path-"+j).append("rect"),C.select("#nv-chart-clip-path-"+j+" rect").attr("width",y).attr("height",A),G.attr("clip-path",w?"url(#nv-chart-clip-path-"+j+")":"");var H=C.select(".nv-ticks").selectAll(".nv-tick").data(function(a){return a});H.exit().remove(),H.enter().append("path").attr("class",function(a,b,c){return(p(a,b)>q(a,b)?"nv-tick negative":"nv-tick positive")+" nv-tick-"+c+"-"+b}).attr("d",function(a,b){return"m0,0l0,"+(m(p(a,b))-m(r(a,b)))+"l"+-B/2+",0l"+B/2+",0l0,"+(m(s(a,b))-m(p(a,b)))+"l0,"+(m(q(a,b))-m(s(a,b)))+"l"+B/2+",0l"+-B/2+",0z"}).attr("transform",function(a,b){return"translate("+l(n(a,b))+","+m(r(a,b))+")"}).attr("fill",function(){return x[0]}).attr("stroke",function(){return x[0]}).attr("x",0).attr("y",function(a,b){return m(Math.max(0,o(a,b)))}).attr("height",function(a,b){return Math.abs(m(o(a,b))-m(0))}),H.attr("class",function(a,b,c){return(p(a,b)>q(a,b)?"nv-tick negative":"nv-tick positive")+" nv-tick-"+c+"-"+b}),d3.transition(H).attr("transform",function(a,b){return"translate("+l(n(a,b))+","+m(r(a,b))+")"}).attr("d",function(a,c){var d=y/b[0].values.length*.9;return"m0,0l0,"+(m(p(a,c))-m(r(a,c)))+"l"+-d/2+",0l"+d/2+",0l0,"+(m(s(a,c))-m(p(a,c)))+"l0,"+(m(q(a,c))-m(s(a,c)))+"l"+d/2+",0l"+-d/2+",0z"})}),b}var c,d,e,f,g={top:0,right:0,bottom:0,left:0},h=null,i=null,j=Math.floor(1e4*Math.random()),k=null,l=d3.scale.linear(),m=d3.scale.linear(),n=function(a){return a.x},o=function(a){return a.y},p=function(a){return a.open},q=function(a){return a.close},r=function(a){return a.high},s=function(a){return a.low},t=[],u=[],v=!1,w=!0,x=a.utils.defaultColor(),y=!1,z=d3.dispatch("tooltipShow","tooltipHide","stateChange","changeState","renderEnd","chartClick","elementClick","elementDblClick","elementMouseover","elementMouseout","elementMousemove");return b.highlightPoint=function(a,c){b.clearHighlights(),k.select(".nv-ohlcBar .nv-tick-0-"+a).classed("hover",c)},b.clearHighlights=function(){k.select(".nv-ohlcBar .nv-tick.hover").classed("hover",!1)},b.dispatch=z,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return h},set:function(a){h=a}},height:{get:function(){return i},set:function(a){i=a}},xScale:{get:function(){return l},set:function(a){l=a}},yScale:{get:function(){return m},set:function(a){m=a}},xDomain:{get:function(){return c},set:function(a){c=a}},yDomain:{get:function(){return d},set:function(a){d=a}},xRange:{get:function(){return e},set:function(a){e=a}},yRange:{get:function(){return f},set:function(a){f=a}},forceX:{get:function(){return t},set:function(a){t=a}},forceY:{get:function(){return u},set:function(a){u=a}},padData:{get:function(){return v},set:function(a){v=a}},clipEdge:{get:function(){return w},set:function(a){w=a}},id:{get:function(){return j},set:function(a){j=a}},interactive:{get:function(){return y},set:function(a){y=a}},x:{get:function(){return n},set:function(a){n=a}},y:{get:function(){return o},set:function(a){o=a}},open:{get:function(){return p()},set:function(a){p=a}},close:{get:function(){return q()},set:function(a){q=a}},high:{get:function(){return r},set:function(a){r=a}},low:{get:function(){return s},set:function(a){s=a}},margin:{get:function(){return g},set:function(a){g.top=void 0!=a.top?a.top:g.top,g.right=void 0!=a.right?a.right:g.right,g.bottom=void 0!=a.bottom?a.bottom:g.bottom,g.left=void 0!=a.left?a.left:g.left
+}},color:{get:function(){return x},set:function(b){x=a.utils.getColor(b)}}}),a.utils.initOptions(b),b},a.models.parallelCoordinates=function(){"use strict";function b(p){return p.each(function(b){function p(a){return F(h.map(function(b){if(isNaN(a[b])||isNaN(parseFloat(a[b]))){var c=g[b].domain(),d=g[b].range(),e=c[0]-(c[1]-c[0])/9;if(J.indexOf(b)<0){var h=d3.scale.linear().domain([e,c[1]]).range([x-12,d[1]]);g[b].brush.y(h),J.push(b)}return[f(b),g[b](e)]}return J.length>0?(D.style("display","inline"),E.style("display","inline")):(D.style("display","none"),E.style("display","none")),[f(b),g[b](a[b])]}))}function q(){var a=h.filter(function(a){return!g[a].brush.empty()}),b=a.map(function(a){return g[a].brush.extent()});k=[],a.forEach(function(a,c){k[c]={dimension:a,extent:b[c]}}),l=[],M.style("display",function(c){var d=a.every(function(a,d){return isNaN(c[a])&&b[d][0]==g[a].brush.y().domain()[0]?!0:b[d][0]<=c[a]&&c[a]<=b[d][1]});return d&&l.push(c),d?null:"none"}),o.brush({filters:k,active:l})}function r(a){m[a]=this.parentNode.__origin__=f(a),L.attr("visibility","hidden")}function s(a){m[a]=Math.min(w,Math.max(0,this.parentNode.__origin__+=d3.event.x)),M.attr("d",p),h.sort(function(a,b){return u(a)-u(b)}),f.domain(h),N.attr("transform",function(a){return"translate("+u(a)+")"})}function t(a){delete this.parentNode.__origin__,delete m[a],d3.select(this.parentNode).attr("transform","translate("+f(a)+")"),M.attr("d",p),L.attr("d",p).attr("visibility",null)}function u(a){var b=m[a];return null==b?f(a):b}var v=d3.select(this),w=a.utils.availableWidth(d,v,c),x=a.utils.availableHeight(e,v,c);a.utils.initSVG(v),l=b,f.rangePoints([0,w],1).domain(h);var y={};h.forEach(function(a){var c=d3.extent(b,function(b){return+b[a]});return y[a]=!1,void 0===c[0]&&(y[a]=!0,c[0]=0,c[1]=0),c[0]===c[1]&&(c[0]=c[0]-1,c[1]=c[1]+1),g[a]=d3.scale.linear().domain(c).range([.9*(x-12),0]),g[a].brush=d3.svg.brush().y(g[a]).on("brush",q),"name"!=a});var z=v.selectAll("g.nv-wrap.nv-parallelCoordinates").data([b]),A=z.enter().append("g").attr("class","nvd3 nv-wrap nv-parallelCoordinates"),B=A.append("g"),C=z.select("g");B.append("g").attr("class","nv-parallelCoordinates background"),B.append("g").attr("class","nv-parallelCoordinates foreground"),B.append("g").attr("class","nv-parallelCoordinates missingValuesline"),z.attr("transform","translate("+c.left+","+c.top+")");var D,E,F=d3.svg.line().interpolate("cardinal").tension(n),G=d3.svg.axis().orient("left"),H=d3.behavior.drag().on("dragstart",r).on("drag",s).on("dragend",t),I=f.range()[1]-f.range()[0],J=[],K=[0+I/2,x-12,w-I/2,x-12];D=z.select(".missingValuesline").selectAll("line").data([K]),D.enter().append("line"),D.exit().remove(),D.attr("x1",function(a){return a[0]}).attr("y1",function(a){return a[1]}).attr("x2",function(a){return a[2]}).attr("y2",function(a){return a[3]}),E=z.select(".missingValuesline").selectAll("text").data(["undefined values"]),E.append("text").data(["undefined values"]),E.enter().append("text"),E.exit().remove(),E.attr("y",x).attr("x",w-92-I/2).text(function(a){return a});var L=z.select(".background").selectAll("path").data(b);L.enter().append("path"),L.exit().remove(),L.attr("d",p);var M=z.select(".foreground").selectAll("path").data(b);M.enter().append("path"),M.exit().remove(),M.attr("d",p).attr("stroke",j),M.on("mouseover",function(a,b){d3.select(this).classed("hover",!0),o.elementMouseover({label:a.name,data:a.data,index:b,pos:[d3.mouse(this.parentNode)[0],d3.mouse(this.parentNode)[1]]})}),M.on("mouseout",function(a,b){d3.select(this).classed("hover",!1),o.elementMouseout({label:a.name,data:a.data,index:b})});var N=C.selectAll(".dimension").data(h),O=N.enter().append("g").attr("class","nv-parallelCoordinates dimension");O.append("g").attr("class","nv-parallelCoordinates nv-axis"),O.append("g").attr("class","nv-parallelCoordinates-brush"),O.append("text").attr("class","nv-parallelCoordinates nv-label"),N.attr("transform",function(a){return"translate("+f(a)+",0)"}),N.exit().remove(),N.select(".nv-label").style("cursor","move").attr("dy","-1em").attr("text-anchor","middle").text(String).on("mouseover",function(a){o.elementMouseover({dim:a,pos:[d3.mouse(this.parentNode.parentNode)[0],d3.mouse(this.parentNode.parentNode)[1]]})}).on("mouseout",function(a){o.elementMouseout({dim:a})}).call(H),N.select(".nv-axis").each(function(a,b){d3.select(this).call(G.scale(g[a]).tickFormat(d3.format(i[b])))}),N.select(".nv-parallelCoordinates-brush").each(function(a){d3.select(this).call(g[a].brush)}).selectAll("rect").attr("x",-8).attr("width",16)}),b}var c={top:30,right:0,bottom:10,left:0},d=null,e=null,f=d3.scale.ordinal(),g={},h=[],i=[],j=a.utils.defaultColor(),k=[],l=[],m=[],n=1,o=d3.dispatch("brush","elementMouseover","elementMouseout");return b.dispatch=o,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return d},set:function(a){d=a}},height:{get:function(){return e},set:function(a){e=a}},dimensionNames:{get:function(){return h},set:function(a){h=a}},dimensionFormats:{get:function(){return i},set:function(a){i=a}},lineTension:{get:function(){return n},set:function(a){n=a}},dimensions:{get:function(){return h},set:function(b){a.deprecated("dimensions","use dimensionNames instead"),h=b}},margin:{get:function(){return c},set:function(a){c.top=void 0!==a.top?a.top:c.top,c.right=void 0!==a.right?a.right:c.right,c.bottom=void 0!==a.bottom?a.bottom:c.bottom,c.left=void 0!==a.left?a.left:c.left}},color:{get:function(){return j},set:function(b){j=a.utils.getColor(b)}}}),a.utils.initOptions(b),b},a.models.pie=function(){"use strict";function b(E){return D.reset(),E.each(function(b){function E(a,b){a.endAngle=isNaN(a.endAngle)?0:a.endAngle,a.startAngle=isNaN(a.startAngle)?0:a.startAngle,p||(a.innerRadius=0);var c=d3.interpolate(this._current,a);return this._current=c(0),function(a){return B[b](c(a))}}var F=d-c.left-c.right,G=e-c.top-c.bottom,H=Math.min(F,G)/2,I=[],J=[];if(i=d3.select(this),0===z.length)for(var K=H-H/5,L=y*H,M=0;M<b[0].length;M++)I.push(K),J.push(L);else I=z.map(function(a){return(a.outer-a.outer/5)*H}),J=z.map(function(a){return(a.inner-a.inner/5)*H}),y=d3.min(z.map(function(a){return a.inner-a.inner/5}));a.utils.initSVG(i);var N=i.selectAll(".nv-wrap.nv-pie").data(b),O=N.enter().append("g").attr("class","nvd3 nv-wrap nv-pie nv-chart-"+h),P=O.append("g"),Q=N.select("g"),R=P.append("g").attr("class","nv-pie");P.append("g").attr("class","nv-pieLabels"),N.attr("transform","translate("+c.left+","+c.top+")"),Q.select(".nv-pie").attr("transform","translate("+F/2+","+G/2+")"),Q.select(".nv-pieLabels").attr("transform","translate("+F/2+","+G/2+")"),i.on("click",function(a,b){A.chartClick({data:a,index:b,pos:d3.event,id:h})}),B=[],C=[];for(var M=0;M<b[0].length;M++){var S=d3.svg.arc().outerRadius(I[M]),T=d3.svg.arc().outerRadius(I[M]+5);u!==!1&&(S.startAngle(u),T.startAngle(u)),w!==!1&&(S.endAngle(w),T.endAngle(w)),p&&(S.innerRadius(J[M]),T.innerRadius(J[M])),S.cornerRadius&&x&&(S.cornerRadius(x),T.cornerRadius(x)),B.push(S),C.push(T)}var U=d3.layout.pie().sort(null).value(function(a){return a.disabled?0:g(a)});U.padAngle&&v&&U.padAngle(v),p&&q&&(R.append("text").attr("class","nv-pie-title"),N.select(".nv-pie-title").style("text-anchor","middle").text(function(){return q}).style("font-size",Math.min(F,G)*y*2/(q.length+2)+"px").attr("dy","0.35em").attr("transform",function(){return"translate(0, "+s+")"}));var V=N.select(".nv-pie").selectAll(".nv-slice").data(U),W=N.select(".nv-pieLabels").selectAll(".nv-label").data(U);V.exit().remove(),W.exit().remove();var X=V.enter().append("g");X.attr("class","nv-slice"),X.on("mouseover",function(a,b){d3.select(this).classed("hover",!0),r&&d3.select(this).select("path").transition().duration(70).attr("d",C[b]),A.elementMouseover({data:a.data,index:b,color:d3.select(this).style("fill")})}),X.on("mouseout",function(a,b){d3.select(this).classed("hover",!1),r&&d3.select(this).select("path").transition().duration(50).attr("d",B[b]),A.elementMouseout({data:a.data,index:b})}),X.on("mousemove",function(a,b){A.elementMousemove({data:a.data,index:b})}),X.on("click",function(a,b){A.elementClick({data:a.data,index:b,color:d3.select(this).style("fill")})}),X.on("dblclick",function(a,b){A.elementDblClick({data:a.data,index:b,color:d3.select(this).style("fill")})}),V.attr("fill",function(a,b){return j(a.data,b)}),V.attr("stroke",function(a,b){return j(a.data,b)});X.append("path").each(function(a){this._current=a});if(V.select("path").transition().attr("d",function(a,b){return B[b](a)}).attrTween("d",E),l){for(var Y=[],M=0;M<b[0].length;M++)Y.push(B[M]),m?p&&(Y[M]=d3.svg.arc().outerRadius(B[M].outerRadius()),u!==!1&&Y[M].startAngle(u),w!==!1&&Y[M].endAngle(w)):p||Y[M].innerRadius(0);W.enter().append("g").classed("nv-label",!0).each(function(a){var b=d3.select(this);b.attr("transform",function(a,b){if(t){a.outerRadius=I[b]+10,a.innerRadius=I[b]+15;var c=(a.startAngle+a.endAngle)/2*(180/Math.PI);return(a.startAngle+a.endAngle)/2<Math.PI?c-=90:c+=90,"translate("+Y[b].centroid(a)+") rotate("+c+")"}return a.outerRadius=H+10,a.innerRadius=H+15,"translate("+Y[b].centroid(a)+")"}),b.append("rect").style("stroke","#fff").style("fill","#fff").attr("rx",3).attr("ry",3),b.append("text").style("text-anchor",t?(a.startAngle+a.endAngle)/2<Math.PI?"start":"end":"middle").style("fill","#000")});var Z={},$=14,_=140,ab=function(a){return Math.floor(a[0]/_)*_+","+Math.floor(a[1]/$)*$};W.watchTransition(D,"pie labels").attr("transform",function(a,b){if(t){a.outerRadius=I[b]+10,a.innerRadius=I[b]+15;var c=(a.startAngle+a.endAngle)/2*(180/Math.PI);return(a.startAngle+a.endAngle)/2<Math.PI?c-=90:c+=90,"translate("+Y[b].centroid(a)+") rotate("+c+")"}a.outerRadius=H+10,a.innerRadius=H+15;var d=Y[b].centroid(a);if(a.value){var e=ab(d);Z[e]&&(d[1]-=$),Z[ab(d)]=!0}return"translate("+d+")"}),W.select(".nv-label text").style("text-anchor",function(a){return t?(a.startAngle+a.endAngle)/2<Math.PI?"start":"end":"middle"}).text(function(a,b){var c=(a.endAngle-a.startAngle)/(2*Math.PI),d="";if(!a.value||o>c)return"";if("function"==typeof n)d=n(a,b,{key:f(a.data),value:g(a.data),percent:k(c)});else switch(n){case"key":d=f(a.data);break;case"value":d=k(g(a.data));break;case"percent":d=d3.format("%")(c)}return d})}}),D.renderEnd("pie immediate"),b}var c={top:0,right:0,bottom:0,left:0},d=500,e=500,f=function(a){return a.x},g=function(a){return a.y},h=Math.floor(1e4*Math.random()),i=null,j=a.utils.defaultColor(),k=d3.format(",.2f"),l=!0,m=!1,n="key",o=.02,p=!1,q=!1,r=!0,s=0,t=!1,u=!1,v=!1,w=!1,x=0,y=.5,z=[],A=d3.dispatch("chartClick","elementClick","elementDblClick","elementMouseover","elementMouseout","elementMousemove","renderEnd"),B=[],C=[],D=a.utils.renderWatch(A);return b.dispatch=A,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{arcsRadius:{get:function(){return z},set:function(a){z=a}},width:{get:function(){return d},set:function(a){d=a}},height:{get:function(){return e},set:function(a){e=a}},showLabels:{get:function(){return l},set:function(a){l=a}},title:{get:function(){return q},set:function(a){q=a}},titleOffset:{get:function(){return s},set:function(a){s=a}},labelThreshold:{get:function(){return o},set:function(a){o=a}},valueFormat:{get:function(){return k},set:function(a){k=a}},x:{get:function(){return f},set:function(a){f=a}},id:{get:function(){return h},set:function(a){h=a}},endAngle:{get:function(){return w},set:function(a){w=a}},startAngle:{get:function(){return u},set:function(a){u=a}},padAngle:{get:function(){return v},set:function(a){v=a}},cornerRadius:{get:function(){return x},set:function(a){x=a}},donutRatio:{get:function(){return y},set:function(a){y=a}},labelsOutside:{get:function(){return m},set:function(a){m=a}},labelSunbeamLayout:{get:function(){return t},set:function(a){t=a}},donut:{get:function(){return p},set:function(a){p=a}},growOnHover:{get:function(){return r},set:function(a){r=a}},pieLabelsOutside:{get:function(){return m},set:function(b){m=b,a.deprecated("pieLabelsOutside","use labelsOutside instead")}},donutLabelsOutside:{get:function(){return m},set:function(b){m=b,a.deprecated("donutLabelsOutside","use labelsOutside instead")}},labelFormat:{get:function(){return k},set:function(b){k=b,a.deprecated("labelFormat","use valueFormat instead")}},margin:{get:function(){return c},set:function(a){c.top="undefined"!=typeof a.top?a.top:c.top,c.right="undefined"!=typeof a.right?a.right:c.right,c.bottom="undefined"!=typeof a.bottom?a.bottom:c.bottom,c.left="undefined"!=typeof a.left?a.left:c.left}},y:{get:function(){return g},set:function(a){g=d3.functor(a)}},color:{get:function(){return j},set:function(b){j=a.utils.getColor(b)}},labelType:{get:function(){return n},set:function(a){n=a||"key"}}}),a.utils.initOptions(b),b},a.models.pieChart=function(){"use strict";function b(e){return q.reset(),q.models(c),e.each(function(e){var k=d3.select(this);a.utils.initSVG(k);var n=a.utils.availableWidth(g,k,f),o=a.utils.availableHeight(h,k,f);if(b.update=function(){k.transition().call(b)},b.container=this,l.setter(s(e),b.update).getter(r(e)).update(),l.disabled=e.map(function(a){return!!a.disabled}),!m){var q;m={};for(q in l)m[q]=l[q]instanceof Array?l[q].slice(0):l[q]}if(!e||!e.length)return a.utils.noData(b,k),b;k.selectAll(".nv-noData").remove();var t=k.selectAll("g.nv-wrap.nv-pieChart").data([e]),u=t.enter().append("g").attr("class","nvd3 nv-wrap nv-pieChart").append("g"),v=t.select("g");if(u.append("g").attr("class","nv-pieWrap"),u.append("g").attr("class","nv-legendWrap"),i)if("top"===j)d.width(n).key(c.x()),t.select(".nv-legendWrap").datum(e).call(d),f.top!=d.height()&&(f.top=d.height(),o=a.utils.availableHeight(h,k,f)),t.select(".nv-legendWrap").attr("transform","translate(0,"+-f.top+")");else if("right"===j){var w=a.models.legend().width();w>n/2&&(w=n/2),d.height(o).key(c.x()),d.width(w),n-=d.width(),t.select(".nv-legendWrap").datum(e).call(d).attr("transform","translate("+n+",0)")}t.attr("transform","translate("+f.left+","+f.top+")"),c.width(n).height(o);var x=v.select(".nv-pieWrap").datum([e]);d3.transition(x).call(c),d.dispatch.on("stateChange",function(a){for(var c in a)l[c]=a[c];p.stateChange(l),b.update()}),p.on("changeState",function(a){"undefined"!=typeof a.disabled&&(e.forEach(function(b,c){b.disabled=a.disabled[c]}),l.disabled=a.disabled),b.update()})}),q.renderEnd("pieChart immediate"),b}var c=a.models.pie(),d=a.models.legend(),e=a.models.tooltip(),f={top:30,right:20,bottom:20,left:20},g=null,h=null,i=!0,j="top",k=a.utils.defaultColor(),l=a.utils.state(),m=null,n=null,o=250,p=d3.dispatch("tooltipShow","tooltipHide","stateChange","changeState","renderEnd");e.headerEnabled(!1).duration(0).valueFormatter(function(a,b){return c.valueFormat()(a,b)});var q=a.utils.renderWatch(p),r=function(a){return function(){return{active:a.map(function(a){return!a.disabled})}}},s=function(a){return function(b){void 0!==b.active&&a.forEach(function(a,c){a.disabled=!b.active[c]})}};return c.dispatch.on("elementMouseover.tooltip",function(a){a.series={key:b.x()(a.data),value:b.y()(a.data),color:a.color},e.data(a).hidden(!1)}),c.dispatch.on("elementMouseout.tooltip",function(){e.hidden(!0)}),c.dispatch.on("elementMousemove.tooltip",function(){e.position({top:d3.event.pageY,left:d3.event.pageX})()}),b.legend=d,b.dispatch=p,b.pie=c,b.tooltip=e,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{noData:{get:function(){return n},set:function(a){n=a}},showLegend:{get:function(){return i},set:function(a){i=a}},legendPosition:{get:function(){return j},set:function(a){j=a}},defaultState:{get:function(){return m},set:function(a){m=a}},tooltips:{get:function(){return e.enabled()},set:function(b){a.deprecated("tooltips","use chart.tooltip.enabled() instead"),e.enabled(!!b)}},tooltipContent:{get:function(){return e.contentGenerator()},set:function(b){a.deprecated("tooltipContent","use chart.tooltip.contentGenerator() instead"),e.contentGenerator(b)}},color:{get:function(){return k},set:function(a){k=a,d.color(k),c.color(k)}},duration:{get:function(){return o},set:function(a){o=a,q.reset(o)}},margin:{get:function(){return f},set:function(a){f.top=void 0!==a.top?a.top:f.top,f.right=void 0!==a.right?a.right:f.right,f.bottom=void 0!==a.bottom?a.bottom:f.bottom,f.left=void 0!==a.left?a.left:f.left}}}),a.utils.inheritOptions(b,c),a.utils.initOptions(b),b},a.models.scatter=function(){"use strict";function b(N){return P.reset(),N.each(function(b){function N(){if(O=!1,!w)return!1;if(M===!0){var a=d3.merge(b.map(function(a,b){return a.values.map(function(a,c){var d=p(a,c),e=q(a,c);return[m(d)+1e-4*Math.random(),n(e)+1e-4*Math.random(),b,c,a]}).filter(function(a,b){return x(a[4],b)})}));if(0==a.length)return!1;a.length<3&&(a.push([m.range()[0]-20,n.range()[0]-20,null,null]),a.push([m.range()[1]+20,n.range()[1]+20,null,null]),a.push([m.range()[0]-20,n.range()[0]+20,null,null]),a.push([m.range()[1]+20,n.range()[1]-20,null,null]));var c=d3.geom.polygon([[-10,-10],[-10,i+10],[h+10,i+10],[h+10,-10]]),d=d3.geom.voronoi(a).map(function(b,d){return{data:c.clip(b),series:a[d][2],point:a[d][3]}});U.select(".nv-point-paths").selectAll("path").remove();var e=U.select(".nv-point-paths").selectAll("path").data(d),f=e.enter().append("svg:path").attr("d",function(a){return a&&a.data&&0!==a.data.length?"M"+a.data.join(",")+"Z":"M 0 0"}).attr("id",function(a,b){return"nv-path-"+b}).attr("clip-path",function(a,b){return"url(#nv-clip-"+b+")"});C&&f.style("fill",d3.rgb(230,230,230)).style("fill-opacity",.4).style("stroke-opacity",1).style("stroke",d3.rgb(200,200,200)),B&&(U.select(".nv-point-clips").selectAll("clipPath").remove(),U.select(".nv-point-clips").selectAll("clipPath").data(a).enter().append("svg:clipPath").attr("id",function(a,b){return"nv-clip-"+b}).append("svg:circle").attr("cx",function(a){return a[0]}).attr("cy",function(a){return a[1]}).attr("r",D));var k=function(a,c){if(O)return 0;var d=b[a.series];if(void 0!==d){var e=d.values[a.point];e.color=j(d,a.series),e.x=p(e),e.y=q(e);var f=l.node().getBoundingClientRect(),h=window.pageYOffset||document.documentElement.scrollTop,i=window.pageXOffset||document.documentElement.scrollLeft,k={left:m(p(e,a.point))+f.left+i+g.left+10,top:n(q(e,a.point))+f.top+h+g.top+10};c({point:e,series:d,pos:k,seriesIndex:a.series,pointIndex:a.point})}};e.on("click",function(a){k(a,L.elementClick)}).on("dblclick",function(a){k(a,L.elementDblClick)}).on("mouseover",function(a){k(a,L.elementMouseover)}).on("mouseout",function(a){k(a,L.elementMouseout)})}else U.select(".nv-groups").selectAll(".nv-group").selectAll(".nv-point").on("click",function(a,c){if(O||!b[a.series])return 0;var d=b[a.series],e=d.values[c];L.elementClick({point:e,series:d,pos:[m(p(e,c))+g.left,n(q(e,c))+g.top],seriesIndex:a.series,pointIndex:c})}).on("dblclick",function(a,c){if(O||!b[a.series])return 0;var d=b[a.series],e=d.values[c];L.elementDblClick({point:e,series:d,pos:[m(p(e,c))+g.left,n(q(e,c))+g.top],seriesIndex:a.series,pointIndex:c})}).on("mouseover",function(a,c){if(O||!b[a.series])return 0;var d=b[a.series],e=d.values[c];L.elementMouseover({point:e,series:d,pos:[m(p(e,c))+g.left,n(q(e,c))+g.top],seriesIndex:a.series,pointIndex:c,color:j(a,c)})}).on("mouseout",function(a,c){if(O||!b[a.series])return 0;var d=b[a.series],e=d.values[c];L.elementMouseout({point:e,series:d,seriesIndex:a.series,pointIndex:c,color:j(a,c)})})}l=d3.select(this);var R=a.utils.availableWidth(h,l,g),S=a.utils.availableHeight(i,l,g);a.utils.initSVG(l),b.forEach(function(a,b){a.values.forEach(function(a){a.series=b})});var T=E&&F&&I?[]:d3.merge(b.map(function(a){return a.values.map(function(a,b){return{x:p(a,b),y:q(a,b),size:r(a,b)}})}));m.domain(E||d3.extent(T.map(function(a){return a.x}).concat(t))),m.range(y&&b[0]?G||[(R*z+R)/(2*b[0].values.length),R-R*(1+z)/(2*b[0].values.length)]:G||[0,R]),n.domain(F||d3.extent(T.map(function(a){return a.y}).concat(u))).range(H||[S,0]),o.domain(I||d3.extent(T.map(function(a){return a.size}).concat(v))).range(J||Q),K=m.domain()[0]===m.domain()[1]||n.domain()[0]===n.domain()[1],m.domain()[0]===m.domain()[1]&&m.domain(m.domain()[0]?[m.domain()[0]-.01*m.domain()[0],m.domain()[1]+.01*m.domain()[1]]:[-1,1]),n.domain()[0]===n.domain()[1]&&n.domain(n.domain()[0]?[n.domain()[0]-.01*n.domain()[0],n.domain()[1]+.01*n.domain()[1]]:[-1,1]),isNaN(m.domain()[0])&&m.domain([-1,1]),isNaN(n.domain()[0])&&n.domain([-1,1]),c=c||m,d=d||n,e=e||o;var U=l.selectAll("g.nv-wrap.nv-scatter").data([b]),V=U.enter().append("g").attr("class","nvd3 nv-wrap nv-scatter nv-chart-"+k),W=V.append("defs"),X=V.append("g"),Y=U.select("g");U.classed("nv-single-point",K),X.append("g").attr("class","nv-groups"),X.append("g").attr("class","nv-point-paths"),V.append("g").attr("class","nv-point-clips"),U.attr("transform","translate("+g.left+","+g.top+")"),W.append("clipPath").attr("id","nv-edge-clip-"+k).append("rect"),U.select("#nv-edge-clip-"+k+" rect").attr("width",R).attr("height",S>0?S:0),Y.attr("clip-path",A?"url(#nv-edge-clip-"+k+")":""),O=!0;var Z=U.select(".nv-groups").selectAll(".nv-group").data(function(a){return a},function(a){return a.key});Z.enter().append("g").style("stroke-opacity",1e-6).style("fill-opacity",1e-6),Z.exit().remove(),Z.attr("class",function(a,b){return"nv-group nv-series-"+b}).classed("hover",function(a){return a.hover}),Z.watchTransition(P,"scatter: groups").style("fill",function(a,b){return j(a,b)}).style("stroke",function(a,b){return j(a,b)}).style("stroke-opacity",1).style("fill-opacity",.5);var $=Z.selectAll("path.nv-point").data(function(a){return a.values.map(function(a,b){return[a,b]}).filter(function(a,b){return x(a[0],b)})});$.enter().append("path").style("fill",function(a){return a.color}).style("stroke",function(a){return a.color}).attr("transform",function(a){return"translate("+c(p(a[0],a[1]))+","+d(q(a[0],a[1]))+")"}).attr("d",a.utils.symbol().type(function(a){return s(a[0])}).size(function(a){return o(r(a[0],a[1]))})),$.exit().remove(),Z.exit().selectAll("path.nv-point").watchTransition(P,"scatter exit").attr("transform",function(a){return"translate("+m(p(a[0],a[1]))+","+n(q(a[0],a[1]))+")"}).remove(),$.each(function(a){d3.select(this).classed("nv-point",!0).classed("nv-point-"+a[1],!0).classed("nv-noninteractive",!w).classed("hover",!1)}),$.watchTransition(P,"scatter points").attr("transform",function(a){return"translate("+m(p(a[0],a[1]))+","+n(q(a[0],a[1]))+")"}).attr("d",a.utils.symbol().type(function(a){return s(a[0])}).size(function(a){return o(r(a[0],a[1]))})),clearTimeout(f),f=setTimeout(N,300),c=m.copy(),d=n.copy(),e=o.copy()}),P.renderEnd("scatter immediate"),b}var c,d,e,f,g={top:0,right:0,bottom:0,left:0},h=null,i=null,j=a.utils.defaultColor(),k=Math.floor(1e5*Math.random()),l=null,m=d3.scale.linear(),n=d3.scale.linear(),o=d3.scale.linear(),p=function(a){return a.x},q=function(a){return a.y},r=function(a){return a.size||1},s=function(a){return a.shape||"circle"},t=[],u=[],v=[],w=!0,x=function(a){return!a.notActive},y=!1,z=.1,A=!1,B=!0,C=!1,D=function(){return 25},E=null,F=null,G=null,H=null,I=null,J=null,K=!1,L=d3.dispatch("elementClick","elementDblClick","elementMouseover","elementMouseout","renderEnd"),M=!0,N=250,O=!1,P=a.utils.renderWatch(L,N),Q=[16,256];return b.dispatch=L,b.options=a.utils.optionsFunc.bind(b),b._calls=new function(){this.clearHighlights=function(){return a.dom.write(function(){l.selectAll(".nv-point.hover").classed("hover",!1)}),null},this.highlightPoint=function(b,c,d){a.dom.write(function(){l.select(" .nv-series-"+b+" .nv-point-"+c).classed("hover",d)})}},L.on("elementMouseover.point",function(a){w&&b._calls.highlightPoint(a.seriesIndex,a.pointIndex,!0)}),L.on("elementMouseout.point",function(a){w&&b._calls.highlightPoint(a.seriesIndex,a.pointIndex,!1)}),b._options=Object.create({},{width:{get:function(){return h},set:function(a){h=a}},height:{get:function(){return i},set:function(a){i=a}},xScale:{get:function(){return m},set:function(a){m=a}},yScale:{get:function(){return n},set:function(a){n=a}},pointScale:{get:function(){return o},set:function(a){o=a}},xDomain:{get:function(){return E},set:function(a){E=a}},yDomain:{get:function(){return F},set:function(a){F=a}},pointDomain:{get:function(){return I},set:function(a){I=a}},xRange:{get:function(){return G},set:function(a){G=a}},yRange:{get:function(){return H},set:function(a){H=a}},pointRange:{get:function(){return J},set:function(a){J=a}},forceX:{get:function(){return t},set:function(a){t=a}},forceY:{get:function(){return u},set:function(a){u=a}},forcePoint:{get:function(){return v},set:function(a){v=a}},interactive:{get:function(){return w},set:function(a){w=a}},pointActive:{get:function(){return x},set:function(a){x=a}},padDataOuter:{get:function(){return z},set:function(a){z=a}},padData:{get:function(){return y},set:function(a){y=a}},clipEdge:{get:function(){return A},set:function(a){A=a}},clipVoronoi:{get:function(){return B},set:function(a){B=a}},clipRadius:{get:function(){return D},set:function(a){D=a}},showVoronoi:{get:function(){return C},set:function(a){C=a}},id:{get:function(){return k},set:function(a){k=a}},x:{get:function(){return p},set:function(a){p=d3.functor(a)}},y:{get:function(){return q},set:function(a){q=d3.functor(a)}},pointSize:{get:function(){return r},set:function(a){r=d3.functor(a)}},pointShape:{get:function(){return s},set:function(a){s=d3.functor(a)}},margin:{get:function(){return g},set:function(a){g.top=void 0!==a.top?a.top:g.top,g.right=void 0!==a.right?a.right:g.right,g.bottom=void 0!==a.bottom?a.bottom:g.bottom,g.left=void 0!==a.left?a.left:g.left}},duration:{get:function(){return N},set:function(a){N=a,P.reset(N)}},color:{get:function(){return j},set:function(b){j=a.utils.getColor(b)}},useVoronoi:{get:function(){return M},set:function(a){M=a,M===!1&&(B=!1)}}}),a.utils.initOptions(b),b},a.models.scatterChart=function(){"use strict";function b(z){return D.reset(),D.models(c),t&&D.models(d),u&&D.models(e),q&&D.models(g),r&&D.models(h),z.each(function(z){m=d3.select(this),a.utils.initSVG(m);var G=a.utils.availableWidth(k,m,j),H=a.utils.availableHeight(l,m,j);if(b.update=function(){0===A?m.call(b):m.transition().duration(A).call(b)},b.container=this,w.setter(F(z),b.update).getter(E(z)).update(),w.disabled=z.map(function(a){return!!a.disabled}),!x){var I;x={};for(I in w)x[I]=w[I]instanceof Array?w[I].slice(0):w[I]}if(!(z&&z.length&&z.filter(function(a){return a.values.length}).length))return a.utils.noData(b,m),D.renderEnd("scatter immediate"),b;m.selectAll(".nv-noData").remove(),o=c.xScale(),p=c.yScale();var J=m.selectAll("g.nv-wrap.nv-scatterChart").data([z]),K=J.enter().append("g").attr("class","nvd3 nv-wrap nv-scatterChart nv-chart-"+c.id()),L=K.append("g"),M=J.select("g");if(L.append("rect").attr("class","nvd3 nv-background").style("pointer-events","none"),L.append("g").attr("class","nv-x nv-axis"),L.append("g").attr("class","nv-y nv-axis"),L.append("g").attr("class","nv-scatterWrap"),L.append("g").attr("class","nv-regressionLinesWrap"),L.append("g").attr("class","nv-distWrap"),L.append("g").attr("class","nv-legendWrap"),v&&M.select(".nv-y.nv-axis").attr("transform","translate("+G+",0)"),s){var N=G;f.width(N),J.select(".nv-legendWrap").datum(z).call(f),j.top!=f.height()&&(j.top=f.height(),H=a.utils.availableHeight(l,m,j)),J.select(".nv-legendWrap").attr("transform","translate(0,"+-j.top+")")}J.attr("transform","translate("+j.left+","+j.top+")"),c.width(G).height(H).color(z.map(function(a,b){return a.color=a.color||n(a,b),a.color}).filter(function(a,b){return!z[b].disabled})),J.select(".nv-scatterWrap").datum(z.filter(function(a){return!a.disabled})).call(c),J.select(".nv-regressionLinesWrap").attr("clip-path","url(#nv-edge-clip-"+c.id()+")");var O=J.select(".nv-regressionLinesWrap").selectAll(".nv-regLines").data(function(a){return a});O.enter().append("g").attr("class","nv-regLines");var P=O.selectAll(".nv-regLine").data(function(a){return[a]});P.enter().append("line").attr("class","nv-regLine").style("stroke-opacity",0),P.filter(function(a){return a.intercept&&a.slope}).watchTransition(D,"scatterPlusLineChart: regline").attr("x1",o.range()[0]).attr("x2",o.range()[1]).attr("y1",function(a){return p(o.domain()[0]*a.slope+a.intercept)}).attr("y2",function(a){return p(o.domain()[1]*a.slope+a.intercept)}).style("stroke",function(a,b,c){return n(a,c)}).style("stroke-opacity",function(a){return a.disabled||"undefined"==typeof a.slope||"undefined"==typeof a.intercept?0:1}),t&&(d.scale(o)._ticks(a.utils.calcTicksX(G/100,z)).tickSize(-H,0),M.select(".nv-x.nv-axis").attr("transform","translate(0,"+p.range()[0]+")").call(d)),u&&(e.scale(p)._ticks(a.utils.calcTicksY(H/36,z)).tickSize(-G,0),M.select(".nv-y.nv-axis").call(e)),q&&(g.getData(c.x()).scale(o).width(G).color(z.map(function(a,b){return a.color||n(a,b)}).filter(function(a,b){return!z[b].disabled})),L.select(".nv-distWrap").append("g").attr("class","nv-distributionX"),M.select(".nv-distributionX").attr("transform","translate(0,"+p.range()[0]+")").datum(z.filter(function(a){return!a.disabled})).call(g)),r&&(h.getData(c.y()).scale(p).width(H).color(z.map(function(a,b){return a.color||n(a,b)}).filter(function(a,b){return!z[b].disabled})),L.select(".nv-distWrap").append("g").attr("class","nv-distributionY"),M.select(".nv-distributionY").attr("transform","translate("+(v?G:-h.size())+",0)").datum(z.filter(function(a){return!a.disabled})).call(h)),f.dispatch.on("stateChange",function(a){for(var c in a)w[c]=a[c];y.stateChange(w),b.update()}),y.on("changeState",function(a){"undefined"!=typeof a.disabled&&(z.forEach(function(b,c){b.disabled=a.disabled[c]}),w.disabled=a.disabled),b.update()}),c.dispatch.on("elementMouseout.tooltip",function(a){i.hidden(!0),m.select(".nv-chart-"+c.id()+" .nv-series-"+a.seriesIndex+" .nv-distx-"+a.pointIndex).attr("y1",0),m.select(".nv-chart-"+c.id()+" .nv-series-"+a.seriesIndex+" .nv-disty-"+a.pointIndex).attr("x2",h.size())}),c.dispatch.on("elementMouseover.tooltip",function(a){m.select(".nv-series-"+a.seriesIndex+" .nv-distx-"+a.pointIndex).attr("y1",a.pos.top-H-j.top),m.select(".nv-series-"+a.seriesIndex+" .nv-disty-"+a.pointIndex).attr("x2",a.pos.left+g.size()-j.left),i.position(a.pos).data(a).hidden(!1)}),B=o.copy(),C=p.copy()}),D.renderEnd("scatter with line immediate"),b}var c=a.models.scatter(),d=a.models.axis(),e=a.models.axis(),f=a.models.legend(),g=a.models.distribution(),h=a.models.distribution(),i=a.models.tooltip(),j={top:30,right:20,bottom:50,left:75},k=null,l=null,m=null,n=a.utils.defaultColor(),o=c.xScale(),p=c.yScale(),q=!1,r=!1,s=!0,t=!0,u=!0,v=!1,w=a.utils.state(),x=null,y=d3.dispatch("stateChange","changeState","renderEnd"),z=null,A=250;c.xScale(o).yScale(p),d.orient("bottom").tickPadding(10),e.orient(v?"right":"left").tickPadding(10),g.axis("x"),h.axis("y"),i.headerFormatter(function(a,b){return d.tickFormat()(a,b)}).valueFormatter(function(a,b){return e.tickFormat()(a,b)});var B,C,D=a.utils.renderWatch(y,A),E=function(a){return function(){return{active:a.map(function(a){return!a.disabled})}}},F=function(a){return function(b){void 0!==b.active&&a.forEach(function(a,c){a.disabled=!b.active[c]})}};return b.dispatch=y,b.scatter=c,b.legend=f,b.xAxis=d,b.yAxis=e,b.distX=g,b.distY=h,b.tooltip=i,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return k},set:function(a){k=a}},height:{get:function(){return l},set:function(a){l=a}},container:{get:function(){return m},set:function(a){m=a}},showDistX:{get:function(){return q},set:function(a){q=a}},showDistY:{get:function(){return r},set:function(a){r=a}},showLegend:{get:function(){return s},set:function(a){s=a}},showXAxis:{get:function(){return t},set:function(a){t=a}},showYAxis:{get:function(){return u},set:function(a){u=a}},defaultState:{get:function(){return x},set:function(a){x=a}},noData:{get:function(){return z},set:function(a){z=a}},duration:{get:function(){return A},set:function(a){A=a}},tooltips:{get:function(){return i.enabled()},set:function(b){a.deprecated("tooltips","use chart.tooltip.enabled() instead"),i.enabled(!!b)
+}},tooltipContent:{get:function(){return i.contentGenerator()},set:function(b){a.deprecated("tooltipContent","use chart.tooltip.contentGenerator() instead"),i.contentGenerator(b)}},tooltipXContent:{get:function(){return i.contentGenerator()},set:function(){a.deprecated("tooltipContent","This option is removed, put values into main tooltip.")}},tooltipYContent:{get:function(){return i.contentGenerator()},set:function(){a.deprecated("tooltipContent","This option is removed, put values into main tooltip.")}},margin:{get:function(){return j},set:function(a){j.top=void 0!==a.top?a.top:j.top,j.right=void 0!==a.right?a.right:j.right,j.bottom=void 0!==a.bottom?a.bottom:j.bottom,j.left=void 0!==a.left?a.left:j.left}},rightAlignYAxis:{get:function(){return v},set:function(a){v=a,e.orient(a?"right":"left")}},color:{get:function(){return n},set:function(b){n=a.utils.getColor(b),f.color(n),g.color(n),h.color(n)}}}),a.utils.inheritOptions(b,c),a.utils.initOptions(b),b},a.models.sparkline=function(){"use strict";function b(k){return k.each(function(b){var k=h-g.left-g.right,q=i-g.top-g.bottom;j=d3.select(this),a.utils.initSVG(j),l.domain(c||d3.extent(b,n)).range(e||[0,k]),m.domain(d||d3.extent(b,o)).range(f||[q,0]);{var r=j.selectAll("g.nv-wrap.nv-sparkline").data([b]),s=r.enter().append("g").attr("class","nvd3 nv-wrap nv-sparkline");s.append("g"),r.select("g")}r.attr("transform","translate("+g.left+","+g.top+")");var t=r.selectAll("path").data(function(a){return[a]});t.enter().append("path"),t.exit().remove(),t.style("stroke",function(a,b){return a.color||p(a,b)}).attr("d",d3.svg.line().x(function(a,b){return l(n(a,b))}).y(function(a,b){return m(o(a,b))}));var u=r.selectAll("circle.nv-point").data(function(a){function b(b){if(-1!=b){var c=a[b];return c.pointIndex=b,c}return null}var c=a.map(function(a,b){return o(a,b)}),d=b(c.lastIndexOf(m.domain()[1])),e=b(c.indexOf(m.domain()[0])),f=b(c.length-1);return[e,d,f].filter(function(a){return null!=a})});u.enter().append("circle"),u.exit().remove(),u.attr("cx",function(a){return l(n(a,a.pointIndex))}).attr("cy",function(a){return m(o(a,a.pointIndex))}).attr("r",2).attr("class",function(a){return n(a,a.pointIndex)==l.domain()[1]?"nv-point nv-currentValue":o(a,a.pointIndex)==m.domain()[0]?"nv-point nv-minValue":"nv-point nv-maxValue"})}),b}var c,d,e,f,g={top:2,right:0,bottom:2,left:0},h=400,i=32,j=null,k=!0,l=d3.scale.linear(),m=d3.scale.linear(),n=function(a){return a.x},o=function(a){return a.y},p=a.utils.getColor(["#000"]);return b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return h},set:function(a){h=a}},height:{get:function(){return i},set:function(a){i=a}},xDomain:{get:function(){return c},set:function(a){c=a}},yDomain:{get:function(){return d},set:function(a){d=a}},xRange:{get:function(){return e},set:function(a){e=a}},yRange:{get:function(){return f},set:function(a){f=a}},xScale:{get:function(){return l},set:function(a){l=a}},yScale:{get:function(){return m},set:function(a){m=a}},animate:{get:function(){return k},set:function(a){k=a}},x:{get:function(){return n},set:function(a){n=d3.functor(a)}},y:{get:function(){return o},set:function(a){o=d3.functor(a)}},margin:{get:function(){return g},set:function(a){g.top=void 0!==a.top?a.top:g.top,g.right=void 0!==a.right?a.right:g.right,g.bottom=void 0!==a.bottom?a.bottom:g.bottom,g.left=void 0!==a.left?a.left:g.left}},color:{get:function(){return p},set:function(b){p=a.utils.getColor(b)}}}),a.utils.initOptions(b),b},a.models.sparklinePlus=function(){"use strict";function b(p){return p.each(function(p){function q(){if(!j){var a=z.selectAll(".nv-hoverValue").data(i),b=a.enter().append("g").attr("class","nv-hoverValue").style("stroke-opacity",0).style("fill-opacity",0);a.exit().transition().duration(250).style("stroke-opacity",0).style("fill-opacity",0).remove(),a.attr("transform",function(a){return"translate("+c(e.x()(p[a],a))+",0)"}).transition().duration(250).style("stroke-opacity",1).style("fill-opacity",1),i.length&&(b.append("line").attr("x1",0).attr("y1",-f.top).attr("x2",0).attr("y2",u),b.append("text").attr("class","nv-xValue").attr("x",-6).attr("y",-f.top).attr("text-anchor","end").attr("dy",".9em"),z.select(".nv-hoverValue .nv-xValue").text(k(e.x()(p[i[0]],i[0]))),b.append("text").attr("class","nv-yValue").attr("x",6).attr("y",-f.top).attr("text-anchor","start").attr("dy",".9em"),z.select(".nv-hoverValue .nv-yValue").text(l(e.y()(p[i[0]],i[0]))))}}function r(){function a(a,b){for(var c=Math.abs(e.x()(a[0],0)-b),d=0,f=0;f<a.length;f++)Math.abs(e.x()(a[f],f)-b)<c&&(c=Math.abs(e.x()(a[f],f)-b),d=f);return d}if(!j){var b=d3.mouse(this)[0]-f.left;i=[a(p,Math.round(c.invert(b)))],q()}}var s=d3.select(this);a.utils.initSVG(s);var t=a.utils.availableWidth(g,s,f),u=a.utils.availableHeight(h,s,f);if(b.update=function(){s.call(b)},b.container=this,!p||!p.length)return a.utils.noData(b,s),b;s.selectAll(".nv-noData").remove();var v=e.y()(p[p.length-1],p.length-1);c=e.xScale(),d=e.yScale();var w=s.selectAll("g.nv-wrap.nv-sparklineplus").data([p]),x=w.enter().append("g").attr("class","nvd3 nv-wrap nv-sparklineplus"),y=x.append("g"),z=w.select("g");y.append("g").attr("class","nv-sparklineWrap"),y.append("g").attr("class","nv-valueWrap"),y.append("g").attr("class","nv-hoverArea"),w.attr("transform","translate("+f.left+","+f.top+")");var A=z.select(".nv-sparklineWrap");if(e.width(t).height(u),A.call(e),m){var B=z.select(".nv-valueWrap"),C=B.selectAll(".nv-currentValue").data([v]);C.enter().append("text").attr("class","nv-currentValue").attr("dx",o?-8:8).attr("dy",".9em").style("text-anchor",o?"end":"start"),C.attr("x",t+(o?f.right:0)).attr("y",n?function(a){return d(a)}:0).style("fill",e.color()(p[p.length-1],p.length-1)).text(l(v))}y.select(".nv-hoverArea").append("rect").on("mousemove",r).on("click",function(){j=!j}).on("mouseout",function(){i=[],q()}),z.select(".nv-hoverArea rect").attr("transform",function(){return"translate("+-f.left+","+-f.top+")"}).attr("width",t+f.left+f.right).attr("height",u+f.top)}),b}var c,d,e=a.models.sparkline(),f={top:15,right:100,bottom:10,left:50},g=null,h=null,i=[],j=!1,k=d3.format(",r"),l=d3.format(",.2f"),m=!0,n=!0,o=!1,p=null;return b.sparkline=e,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return g},set:function(a){g=a}},height:{get:function(){return h},set:function(a){h=a}},xTickFormat:{get:function(){return k},set:function(a){k=a}},yTickFormat:{get:function(){return l},set:function(a){l=a}},showLastValue:{get:function(){return m},set:function(a){m=a}},alignValue:{get:function(){return n},set:function(a){n=a}},rightAlignValue:{get:function(){return o},set:function(a){o=a}},noData:{get:function(){return p},set:function(a){p=a}},margin:{get:function(){return f},set:function(a){f.top=void 0!==a.top?a.top:f.top,f.right=void 0!==a.right?a.right:f.right,f.bottom=void 0!==a.bottom?a.bottom:f.bottom,f.left=void 0!==a.left?a.left:f.left}}}),a.utils.inheritOptions(b,e),a.utils.initOptions(b),b},a.models.stackedArea=function(){"use strict";function b(m){return u.reset(),u.models(r),m.each(function(m){var s=f-e.left-e.right,v=g-e.top-e.bottom;j=d3.select(this),a.utils.initSVG(j),c=r.xScale(),d=r.yScale();var w=m;m.forEach(function(a,b){a.seriesIndex=b,a.values=a.values.map(function(a,c){return a.index=c,a.seriesIndex=b,a})});var x=m.filter(function(a){return!a.disabled});m=d3.layout.stack().order(o).offset(n).values(function(a){return a.values}).x(k).y(l).out(function(a,b,c){a.display={y:c,y0:b}})(x);var y=j.selectAll("g.nv-wrap.nv-stackedarea").data([m]),z=y.enter().append("g").attr("class","nvd3 nv-wrap nv-stackedarea"),A=z.append("defs"),B=z.append("g"),C=y.select("g");B.append("g").attr("class","nv-areaWrap"),B.append("g").attr("class","nv-scatterWrap"),y.attr("transform","translate("+e.left+","+e.top+")"),0==r.forceY().length&&r.forceY().push(0),r.width(s).height(v).x(k).y(function(a){return a.display.y+a.display.y0}).forceY([0]).color(m.map(function(a){return a.color||h(a,a.seriesIndex)}));var D=C.select(".nv-scatterWrap").datum(m);D.call(r),A.append("clipPath").attr("id","nv-edge-clip-"+i).append("rect"),y.select("#nv-edge-clip-"+i+" rect").attr("width",s).attr("height",v),C.attr("clip-path",q?"url(#nv-edge-clip-"+i+")":"");var E=d3.svg.area().x(function(a,b){return c(k(a,b))}).y0(function(a){return d(a.display.y0)}).y1(function(a){return d(a.display.y+a.display.y0)}).interpolate(p),F=d3.svg.area().x(function(a,b){return c(k(a,b))}).y0(function(a){return d(a.display.y0)}).y1(function(a){return d(a.display.y0)}),G=C.select(".nv-areaWrap").selectAll("path.nv-area").data(function(a){return a});G.enter().append("path").attr("class",function(a,b){return"nv-area nv-area-"+b}).attr("d",function(a){return F(a.values,a.seriesIndex)}).on("mouseover",function(a){d3.select(this).classed("hover",!0),t.areaMouseover({point:a,series:a.key,pos:[d3.event.pageX,d3.event.pageY],seriesIndex:a.seriesIndex})}).on("mouseout",function(a){d3.select(this).classed("hover",!1),t.areaMouseout({point:a,series:a.key,pos:[d3.event.pageX,d3.event.pageY],seriesIndex:a.seriesIndex})}).on("click",function(a){d3.select(this).classed("hover",!1),t.areaClick({point:a,series:a.key,pos:[d3.event.pageX,d3.event.pageY],seriesIndex:a.seriesIndex})}),G.exit().remove(),G.style("fill",function(a){return a.color||h(a,a.seriesIndex)}).style("stroke",function(a){return a.color||h(a,a.seriesIndex)}),G.watchTransition(u,"stackedArea path").attr("d",function(a,b){return E(a.values,b)}),r.dispatch.on("elementMouseover.area",function(a){C.select(".nv-chart-"+i+" .nv-area-"+a.seriesIndex).classed("hover",!0)}),r.dispatch.on("elementMouseout.area",function(a){C.select(".nv-chart-"+i+" .nv-area-"+a.seriesIndex).classed("hover",!1)}),b.d3_stackedOffset_stackPercent=function(a){var b,c,d,e=a.length,f=a[0].length,g=[];for(c=0;f>c;++c){for(b=0,d=0;b<w.length;b++)d+=l(w[b].values[c]);if(d)for(b=0;e>b;b++)a[b][c][1]/=d;else for(b=0;e>b;b++)a[b][c][1]=0}for(c=0;f>c;++c)g[c]=0;return g}}),u.renderEnd("stackedArea immediate"),b}var c,d,e={top:0,right:0,bottom:0,left:0},f=960,g=500,h=a.utils.defaultColor(),i=Math.floor(1e5*Math.random()),j=null,k=function(a){return a.x},l=function(a){return a.y},m="stack",n="zero",o="default",p="linear",q=!1,r=a.models.scatter(),s=250,t=d3.dispatch("areaClick","areaMouseover","areaMouseout","renderEnd","elementClick","elementMouseover","elementMouseout");r.pointSize(2.2).pointDomain([2.2,2.2]);var u=a.utils.renderWatch(t,s);return b.dispatch=t,b.scatter=r,r.dispatch.on("elementClick",function(){t.elementClick.apply(this,arguments)}),r.dispatch.on("elementMouseover",function(){t.elementMouseover.apply(this,arguments)}),r.dispatch.on("elementMouseout",function(){t.elementMouseout.apply(this,arguments)}),b.interpolate=function(a){return arguments.length?(p=a,b):p},b.duration=function(a){return arguments.length?(s=a,u.reset(s),r.duration(s),b):s},b.dispatch=t,b.scatter=r,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return f},set:function(a){f=a}},height:{get:function(){return g},set:function(a){g=a}},clipEdge:{get:function(){return q},set:function(a){q=a}},offset:{get:function(){return n},set:function(a){n=a}},order:{get:function(){return o},set:function(a){o=a}},interpolate:{get:function(){return p},set:function(a){p=a}},x:{get:function(){return k},set:function(a){k=d3.functor(a)}},y:{get:function(){return l},set:function(a){l=d3.functor(a)}},margin:{get:function(){return e},set:function(a){e.top=void 0!==a.top?a.top:e.top,e.right=void 0!==a.right?a.right:e.right,e.bottom=void 0!==a.bottom?a.bottom:e.bottom,e.left=void 0!==a.left?a.left:e.left}},color:{get:function(){return h},set:function(b){h=a.utils.getColor(b)}},style:{get:function(){return m},set:function(a){switch(m=a){case"stack":b.offset("zero"),b.order("default");break;case"stream":b.offset("wiggle"),b.order("inside-out");break;case"stream-center":b.offset("silhouette"),b.order("inside-out");break;case"expand":b.offset("expand"),b.order("default");break;case"stack_percent":b.offset(b.d3_stackedOffset_stackPercent),b.order("default")}}},duration:{get:function(){return s},set:function(a){s=a,u.reset(s),r.duration(s)}}}),a.utils.inheritOptions(b,r),a.utils.initOptions(b),b},a.models.stackedAreaChart=function(){"use strict";function b(k){return F.reset(),F.models(e),r&&F.models(f),s&&F.models(g),k.each(function(k){var x=d3.select(this),F=this;a.utils.initSVG(x);var K=a.utils.availableWidth(m,x,l),L=a.utils.availableHeight(n,x,l);if(b.update=function(){x.transition().duration(C).call(b)},b.container=this,v.setter(I(k),b.update).getter(H(k)).update(),v.disabled=k.map(function(a){return!!a.disabled}),!w){var M;w={};for(M in v)w[M]=v[M]instanceof Array?v[M].slice(0):v[M]}if(!(k&&k.length&&k.filter(function(a){return a.values.length}).length))return a.utils.noData(b,x),b;x.selectAll(".nv-noData").remove(),c=e.xScale(),d=e.yScale();var N=x.selectAll("g.nv-wrap.nv-stackedAreaChart").data([k]),O=N.enter().append("g").attr("class","nvd3 nv-wrap nv-stackedAreaChart").append("g"),P=N.select("g");if(O.append("rect").style("opacity",0),O.append("g").attr("class","nv-x nv-axis"),O.append("g").attr("class","nv-y nv-axis"),O.append("g").attr("class","nv-stackedWrap"),O.append("g").attr("class","nv-legendWrap"),O.append("g").attr("class","nv-controlsWrap"),O.append("g").attr("class","nv-interactive"),P.select("rect").attr("width",K).attr("height",L),q){var Q=p?K-z:K;h.width(Q),P.select(".nv-legendWrap").datum(k).call(h),l.top!=h.height()&&(l.top=h.height(),L=a.utils.availableHeight(n,x,l)),P.select(".nv-legendWrap").attr("transform","translate("+(K-Q)+","+-l.top+")")}if(p){var R=[{key:B.stacked||"Stacked",metaKey:"Stacked",disabled:"stack"!=e.style(),style:"stack"},{key:B.stream||"Stream",metaKey:"Stream",disabled:"stream"!=e.style(),style:"stream"},{key:B.expanded||"Expanded",metaKey:"Expanded",disabled:"expand"!=e.style(),style:"expand"},{key:B.stack_percent||"Stack %",metaKey:"Stack_Percent",disabled:"stack_percent"!=e.style(),style:"stack_percent"}];z=A.length/3*260,R=R.filter(function(a){return-1!==A.indexOf(a.metaKey)}),i.width(z).color(["#444","#444","#444"]),P.select(".nv-controlsWrap").datum(R).call(i),l.top!=Math.max(i.height(),h.height())&&(l.top=Math.max(i.height(),h.height()),L=a.utils.availableHeight(n,x,l)),P.select(".nv-controlsWrap").attr("transform","translate(0,"+-l.top+")")}N.attr("transform","translate("+l.left+","+l.top+")"),t&&P.select(".nv-y.nv-axis").attr("transform","translate("+K+",0)"),u&&(j.width(K).height(L).margin({left:l.left,top:l.top}).svgContainer(x).xScale(c),N.select(".nv-interactive").call(j)),e.width(K).height(L);var S=P.select(".nv-stackedWrap").datum(k);if(S.transition().call(e),r&&(f.scale(c)._ticks(a.utils.calcTicksX(K/100,k)).tickSize(-L,0),P.select(".nv-x.nv-axis").attr("transform","translate(0,"+L+")"),P.select(".nv-x.nv-axis").transition().duration(0).call(f)),s){var T;if(T="wiggle"===e.offset()?0:a.utils.calcTicksY(L/36,k),g.scale(d)._ticks(T).tickSize(-K,0),"expand"===e.style()||"stack_percent"===e.style()){var U=g.tickFormat();D&&U===J||(D=U),g.tickFormat(J)}else D&&(g.tickFormat(D),D=null);P.select(".nv-y.nv-axis").transition().duration(0).call(g)}e.dispatch.on("areaClick.toggle",function(a){k.forEach(1===k.filter(function(a){return!a.disabled}).length?function(a){a.disabled=!1}:function(b,c){b.disabled=c!=a.seriesIndex}),v.disabled=k.map(function(a){return!!a.disabled}),y.stateChange(v),b.update()}),h.dispatch.on("stateChange",function(a){for(var c in a)v[c]=a[c];y.stateChange(v),b.update()}),i.dispatch.on("legendClick",function(a){a.disabled&&(R=R.map(function(a){return a.disabled=!0,a}),a.disabled=!1,e.style(a.style),v.style=e.style(),y.stateChange(v),b.update())}),j.dispatch.on("elementMousemove",function(c){e.clearHighlights();var d,g,h,i=[];if(k.filter(function(a,b){return a.seriesIndex=b,!a.disabled}).forEach(function(f,j){g=a.interactiveBisect(f.values,c.pointXValue,b.x());var k=f.values[g],l=b.y()(k,g);if(null!=l&&e.highlightPoint(j,g,!0),"undefined"!=typeof k){"undefined"==typeof d&&(d=k),"undefined"==typeof h&&(h=b.xScale()(b.x()(k,g)));var m="expand"==e.style()?k.display.y:b.y()(k,g);i.push({key:f.key,value:m,color:o(f,f.seriesIndex),stackedValue:k.display})}}),i.reverse(),i.length>2){var m=b.yScale().invert(c.mouseY),n=null;i.forEach(function(a,b){m=Math.abs(m);var c=Math.abs(a.stackedValue.y0),d=Math.abs(a.stackedValue.y);return m>=c&&d+c>=m?void(n=b):void 0}),null!=n&&(i[n].highlight=!0)}var p=f.tickFormat()(b.x()(d,g)),q=j.tooltip.valueFormatter();"expand"===e.style()||"stack_percent"===e.style()?(E||(E=q),q=d3.format(".1%")):E&&(q=E,E=null),j.tooltip.position({left:h+l.left,top:c.mouseY+l.top}).chartContainer(F.parentNode).valueFormatter(q).data({value:p,series:i})(),j.renderGuideLine(h)}),j.dispatch.on("elementMouseout",function(){e.clearHighlights()}),y.on("changeState",function(a){"undefined"!=typeof a.disabled&&k.length===a.disabled.length&&(k.forEach(function(b,c){b.disabled=a.disabled[c]}),v.disabled=a.disabled),"undefined"!=typeof a.style&&(e.style(a.style),G=a.style),b.update()})}),F.renderEnd("stacked Area chart immediate"),b}var c,d,e=a.models.stackedArea(),f=a.models.axis(),g=a.models.axis(),h=a.models.legend(),i=a.models.legend(),j=a.interactiveGuideline(),k=a.models.tooltip(),l={top:30,right:25,bottom:50,left:60},m=null,n=null,o=a.utils.defaultColor(),p=!0,q=!0,r=!0,s=!0,t=!1,u=!1,v=a.utils.state(),w=null,x=null,y=d3.dispatch("stateChange","changeState","renderEnd"),z=250,A=["Stacked","Stream","Expanded"],B={},C=250;v.style=e.style(),f.orient("bottom").tickPadding(7),g.orient(t?"right":"left"),k.headerFormatter(function(a,b){return f.tickFormat()(a,b)}).valueFormatter(function(a,b){return g.tickFormat()(a,b)}),j.tooltip.headerFormatter(function(a,b){return f.tickFormat()(a,b)}).valueFormatter(function(a,b){return g.tickFormat()(a,b)});var D=null,E=null;i.updateState(!1);var F=a.utils.renderWatch(y),G=e.style(),H=function(a){return function(){return{active:a.map(function(a){return!a.disabled}),style:e.style()}}},I=function(a){return function(b){void 0!==b.style&&(G=b.style),void 0!==b.active&&a.forEach(function(a,c){a.disabled=!b.active[c]})}},J=d3.format("%");return e.dispatch.on("elementMouseover.tooltip",function(a){a.point.x=e.x()(a.point),a.point.y=e.y()(a.point),k.data(a).position(a.pos).hidden(!1)}),e.dispatch.on("elementMouseout.tooltip",function(){k.hidden(!0)}),b.dispatch=y,b.stacked=e,b.legend=h,b.controls=i,b.xAxis=f,b.yAxis=g,b.interactiveLayer=j,b.tooltip=k,b.dispatch=y,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return m},set:function(a){m=a}},height:{get:function(){return n},set:function(a){n=a}},showLegend:{get:function(){return q},set:function(a){q=a}},showXAxis:{get:function(){return r},set:function(a){r=a}},showYAxis:{get:function(){return s},set:function(a){s=a}},defaultState:{get:function(){return w},set:function(a){w=a}},noData:{get:function(){return x},set:function(a){x=a}},showControls:{get:function(){return p},set:function(a){p=a}},controlLabels:{get:function(){return B},set:function(a){B=a}},controlOptions:{get:function(){return A},set:function(a){A=a}},tooltips:{get:function(){return k.enabled()},set:function(b){a.deprecated("tooltips","use chart.tooltip.enabled() instead"),k.enabled(!!b)}},tooltipContent:{get:function(){return k.contentGenerator()},set:function(b){a.deprecated("tooltipContent","use chart.tooltip.contentGenerator() instead"),k.contentGenerator(b)}},margin:{get:function(){return l},set:function(a){l.top=void 0!==a.top?a.top:l.top,l.right=void 0!==a.right?a.right:l.right,l.bottom=void 0!==a.bottom?a.bottom:l.bottom,l.left=void 0!==a.left?a.left:l.left}},duration:{get:function(){return C},set:function(a){C=a,F.reset(C),e.duration(C),f.duration(C),g.duration(C)}},color:{get:function(){return o},set:function(b){o=a.utils.getColor(b),h.color(o),e.color(o)}},rightAlignYAxis:{get:function(){return t},set:function(a){t=a,g.orient(t?"right":"left")}},useInteractiveGuideline:{get:function(){return u},set:function(a){u=!!a,b.interactive(!a),b.useVoronoi(!a),e.scatter.interactive(!a)}}}),a.utils.inheritOptions(b,e),a.utils.initOptions(b),b},a.models.sunburst=function(){"use strict";function b(u){return t.reset(),u.each(function(b){function t(a){a.x0=a.x,a.dx0=a.dx}function u(a){var b=d3.interpolate(p.domain(),[a.x,a.x+a.dx]),c=d3.interpolate(q.domain(),[a.y,1]),d=d3.interpolate(q.range(),[a.y?20:0,y]);return function(a,e){return e?function(){return s(a)}:function(e){return p.domain(b(e)),q.domain(c(e)).range(d(e)),s(a)}}}l=d3.select(this);var v,w=a.utils.availableWidth(g,l,f),x=a.utils.availableHeight(h,l,f),y=Math.min(w,x)/2;a.utils.initSVG(l);var z=l.selectAll(".nv-wrap.nv-sunburst").data(b),A=z.enter().append("g").attr("class","nvd3 nv-wrap nv-sunburst nv-chart-"+k),B=A.selectAll("nv-sunburst");z.attr("transform","translate("+w/2+","+x/2+")"),l.on("click",function(a,b){o.chartClick({data:a,index:b,pos:d3.event,id:k})}),q.range([0,y]),c=c||b,e=b[0],r.value(j[i]||j.count),v=B.data(r.nodes).enter().append("path").attr("d",s).style("fill",function(a){return m((a.children?a:a.parent).name)}).style("stroke","#FFF").on("click",function(a){d!==c&&c!==a&&(d=c),c=a,v.transition().duration(n).attrTween("d",u(a))}).each(t).on("dblclick",function(a){d.parent==a&&v.transition().duration(n).attrTween("d",u(e))}).each(t).on("mouseover",function(a){d3.select(this).classed("hover",!0).style("opacity",.8),o.elementMouseover({data:a,color:d3.select(this).style("fill")})}).on("mouseout",function(a){d3.select(this).classed("hover",!1).style("opacity",1),o.elementMouseout({data:a})}).on("mousemove",function(a){o.elementMousemove({data:a})})}),t.renderEnd("sunburst immediate"),b}var c,d,e,f={top:0,right:0,bottom:0,left:0},g=null,h=null,i="count",j={count:function(){return 1},size:function(a){return a.size}},k=Math.floor(1e4*Math.random()),l=null,m=a.utils.defaultColor(),n=500,o=d3.dispatch("chartClick","elementClick","elementDblClick","elementMousemove","elementMouseover","elementMouseout","renderEnd"),p=d3.scale.linear().range([0,2*Math.PI]),q=d3.scale.sqrt(),r=d3.layout.partition().sort(null).value(function(){return 1}),s=d3.svg.arc().startAngle(function(a){return Math.max(0,Math.min(2*Math.PI,p(a.x)))}).endAngle(function(a){return Math.max(0,Math.min(2*Math.PI,p(a.x+a.dx)))}).innerRadius(function(a){return Math.max(0,q(a.y))}).outerRadius(function(a){return Math.max(0,q(a.y+a.dy))}),t=a.utils.renderWatch(o);return b.dispatch=o,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return g},set:function(a){g=a}},height:{get:function(){return h},set:function(a){h=a}},mode:{get:function(){return i},set:function(a){i=a}},id:{get:function(){return k},set:function(a){k=a}},duration:{get:function(){return n},set:function(a){n=a}},margin:{get:function(){return f},set:function(a){f.top=void 0!=a.top?a.top:f.top,f.right=void 0!=a.right?a.right:f.right,f.bottom=void 0!=a.bottom?a.bottom:f.bottom,f.left=void 0!=a.left?a.left:f.left}},color:{get:function(){return m},set:function(b){m=a.utils.getColor(b)}}}),a.utils.initOptions(b),b},a.models.sunburstChart=function(){"use strict";function b(d){return m.reset(),m.models(c),d.each(function(d){var h=d3.select(this);a.utils.initSVG(h);var i=a.utils.availableWidth(f,h,e),j=a.utils.availableHeight(g,h,e);if(b.update=function(){0===k?h.call(b):h.transition().duration(k).call(b)},b.container=this,!d||!d.length)return a.utils.noData(b,h),b;h.selectAll(".nv-noData").remove();var l=h.selectAll("g.nv-wrap.nv-sunburstChart").data(d),m=l.enter().append("g").attr("class","nvd3 nv-wrap nv-sunburstChart").append("g"),n=l.select("g");m.append("g").attr("class","nv-sunburstWrap"),l.attr("transform","translate("+e.left+","+e.top+")"),c.width(i).height(j);var o=n.select(".nv-sunburstWrap").datum(d);d3.transition(o).call(c)}),m.renderEnd("sunburstChart immediate"),b}var c=a.models.sunburst(),d=a.models.tooltip(),e={top:30,right:20,bottom:20,left:20},f=null,g=null,h=a.utils.defaultColor(),i=(Math.round(1e5*Math.random()),null),j=null,k=250,l=d3.dispatch("tooltipShow","tooltipHide","stateChange","changeState","renderEnd"),m=a.utils.renderWatch(l);return d.headerEnabled(!1).duration(0).valueFormatter(function(a){return a}),c.dispatch.on("elementMouseover.tooltip",function(a){a.series={key:a.data.name,value:a.data.size,color:a.color},d.data(a).hidden(!1)}),c.dispatch.on("elementMouseout.tooltip",function(){d.hidden(!0)}),c.dispatch.on("elementMousemove.tooltip",function(){d.position({top:d3.event.pageY,left:d3.event.pageX})()}),b.dispatch=l,b.sunburst=c,b.tooltip=d,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{noData:{get:function(){return j},set:function(a){j=a}},defaultState:{get:function(){return i},set:function(a){i=a}},color:{get:function(){return h},set:function(a){h=a,c.color(h)}},duration:{get:function(){return k},set:function(a){k=a,m.reset(k),c.duration(k)}},margin:{get:function(){return e},set:function(a){e.top=void 0!==a.top?a.top:e.top,e.right=void 0!==a.right?a.right:e.right,e.bottom=void 0!==a.bottom?a.bottom:e.bottom,e.left=void 0!==a.left?a.left:e.left}}}),a.utils.inheritOptions(b,c),a.utils.initOptions(b),b},a.version="1.8.1"}();
\ No newline at end of file
diff --git a/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/js/popper.min.js b/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/js/popper.min.js
new file mode 100644
index 0000000000000000000000000000000000000000..36c2aeb998dae8cb8db32f23f72f33ee836e8e21
--- /dev/null
+++ b/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/js/popper.min.js
@@ -0,0 +1,5 @@
+/*
+ Copyright (C) Federico Zivolo 2019
+ Distributed under the MIT License (license terms are at http://opensource.org/licenses/MIT).
+ */(function(e,t){'object'==typeof exports&&'undefined'!=typeof module?module.exports=t():'function'==typeof define&&define.amd?define(t):e.Popper=t()})(this,function(){'use strict';function e(e){return e&&'[object Function]'==={}.toString.call(e)}function t(e,t){if(1!==e.nodeType)return[];var o=e.ownerDocument.defaultView,n=o.getComputedStyle(e,null);return t?n[t]:n}function o(e){return'HTML'===e.nodeName?e:e.parentNode||e.host}function n(e){if(!e)return document.body;switch(e.nodeName){case'HTML':case'BODY':return e.ownerDocument.body;case'#document':return e.body;}var i=t(e),r=i.overflow,p=i.overflowX,s=i.overflowY;return /(auto|scroll|overlay)/.test(r+s+p)?e:n(o(e))}function r(e){return 11===e?pe:10===e?se:pe||se}function p(e){if(!e)return document.documentElement;for(var o=r(10)?document.body:null,n=e.offsetParent||null;n===o&&e.nextElementSibling;)n=(e=e.nextElementSibling).offsetParent;var i=n&&n.nodeName;return i&&'BODY'!==i&&'HTML'!==i?-1!==['TH','TD','TABLE'].indexOf(n.nodeName)&&'static'===t(n,'position')?p(n):n:e?e.ownerDocument.documentElement:document.documentElement}function s(e){var t=e.nodeName;return'BODY'!==t&&('HTML'===t||p(e.firstElementChild)===e)}function d(e){return null===e.parentNode?e:d(e.parentNode)}function a(e,t){if(!e||!e.nodeType||!t||!t.nodeType)return document.documentElement;var o=e.compareDocumentPosition(t)&Node.DOCUMENT_POSITION_FOLLOWING,n=o?e:t,i=o?t:e,r=document.createRange();r.setStart(n,0),r.setEnd(i,0);var l=r.commonAncestorContainer;if(e!==l&&t!==l||n.contains(i))return s(l)?l:p(l);var f=d(e);return f.host?a(f.host,t):a(e,d(t).host)}function l(e){var t=1<arguments.length&&void 0!==arguments[1]?arguments[1]:'top',o='top'===t?'scrollTop':'scrollLeft',n=e.nodeName;if('BODY'===n||'HTML'===n){var i=e.ownerDocument.documentElement,r=e.ownerDocument.scrollingElement||i;return r[o]}return e[o]}function f(e,t){var o=2<arguments.length&&void 0!==arguments[2]&&arguments[2],n=l(t,'top'),i=l(t,'left'),r=o?-1:1;return e.top+=n*r,e.bottom+=n*r,e.left+=i*r,e.right+=i*r,e}function m(e,t){var o='x'===t?'Left':'Top',n='Left'==o?'Right':'Bottom';return parseFloat(e['border'+o+'Width'],10)+parseFloat(e['border'+n+'Width'],10)}function h(e,t,o,n){return ee(t['offset'+e],t['scroll'+e],o['client'+e],o['offset'+e],o['scroll'+e],r(10)?parseInt(o['offset'+e])+parseInt(n['margin'+('Height'===e?'Top':'Left')])+parseInt(n['margin'+('Height'===e?'Bottom':'Right')]):0)}function c(e){var t=e.body,o=e.documentElement,n=r(10)&&getComputedStyle(o);return{height:h('Height',t,o,n),width:h('Width',t,o,n)}}function g(e){return fe({},e,{right:e.left+e.width,bottom:e.top+e.height})}function u(e){var o={};try{if(r(10)){o=e.getBoundingClientRect();var n=l(e,'top'),i=l(e,'left');o.top+=n,o.left+=i,o.bottom+=n,o.right+=i}else o=e.getBoundingClientRect()}catch(t){}var p={left:o.left,top:o.top,width:o.right-o.left,height:o.bottom-o.top},s='HTML'===e.nodeName?c(e.ownerDocument):{},d=s.width||e.clientWidth||p.right-p.left,a=s.height||e.clientHeight||p.bottom-p.top,f=e.offsetWidth-d,h=e.offsetHeight-a;if(f||h){var u=t(e);f-=m(u,'x'),h-=m(u,'y'),p.width-=f,p.height-=h}return g(p)}function b(e,o){var i=2<arguments.length&&void 0!==arguments[2]&&arguments[2],p=r(10),s='HTML'===o.nodeName,d=u(e),a=u(o),l=n(e),m=t(o),h=parseFloat(m.borderTopWidth,10),c=parseFloat(m.borderLeftWidth,10);i&&s&&(a.top=ee(a.top,0),a.left=ee(a.left,0));var b=g({top:d.top-a.top-h,left:d.left-a.left-c,width:d.width,height:d.height});if(b.marginTop=0,b.marginLeft=0,!p&&s){var w=parseFloat(m.marginTop,10),y=parseFloat(m.marginLeft,10);b.top-=h-w,b.bottom-=h-w,b.left-=c-y,b.right-=c-y,b.marginTop=w,b.marginLeft=y}return(p&&!i?o.contains(l):o===l&&'BODY'!==l.nodeName)&&(b=f(b,o)),b}function w(e){var t=1<arguments.length&&void 0!==arguments[1]&&arguments[1],o=e.ownerDocument.documentElement,n=b(e,o),i=ee(o.clientWidth,window.innerWidth||0),r=ee(o.clientHeight,window.innerHeight||0),p=t?0:l(o),s=t?0:l(o,'left'),d={top:p-n.top+n.marginTop,left:s-n.left+n.marginLeft,width:i,height:r};return g(d)}function y(e){var n=e.nodeName;if('BODY'===n||'HTML'===n)return!1;if('fixed'===t(e,'position'))return!0;var i=o(e);return!!i&&y(i)}function E(e){if(!e||!e.parentElement||r())return document.documentElement;for(var o=e.parentElement;o&&'none'===t(o,'transform');)o=o.parentElement;return o||document.documentElement}function v(e,t,i,r){var p=4<arguments.length&&void 0!==arguments[4]&&arguments[4],s={top:0,left:0},d=p?E(e):a(e,t);if('viewport'===r)s=w(d,p);else{var l;'scrollParent'===r?(l=n(o(t)),'BODY'===l.nodeName&&(l=e.ownerDocument.documentElement)):'window'===r?l=e.ownerDocument.documentElement:l=r;var f=b(l,d,p);if('HTML'===l.nodeName&&!y(d)){var m=c(e.ownerDocument),h=m.height,g=m.width;s.top+=f.top-f.marginTop,s.bottom=h+f.top,s.left+=f.left-f.marginLeft,s.right=g+f.left}else s=f}i=i||0;var u='number'==typeof i;return s.left+=u?i:i.left||0,s.top+=u?i:i.top||0,s.right-=u?i:i.right||0,s.bottom-=u?i:i.bottom||0,s}function x(e){var t=e.width,o=e.height;return t*o}function O(e,t,o,n,i){var r=5<arguments.length&&void 0!==arguments[5]?arguments[5]:0;if(-1===e.indexOf('auto'))return e;var p=v(o,n,r,i),s={top:{width:p.width,height:t.top-p.top},right:{width:p.right-t.right,height:p.height},bottom:{width:p.width,height:p.bottom-t.bottom},left:{width:t.left-p.left,height:p.height}},d=Object.keys(s).map(function(e){return fe({key:e},s[e],{area:x(s[e])})}).sort(function(e,t){return t.area-e.area}),a=d.filter(function(e){var t=e.width,n=e.height;return t>=o.clientWidth&&n>=o.clientHeight}),l=0<a.length?a[0].key:d[0].key,f=e.split('-')[1];return l+(f?'-'+f:'')}function L(e,t,o){var n=3<arguments.length&&void 0!==arguments[3]?arguments[3]:null,i=n?E(t):a(t,o);return b(o,i,n)}function S(e){var t=e.ownerDocument.defaultView,o=t.getComputedStyle(e),n=parseFloat(o.marginTop||0)+parseFloat(o.marginBottom||0),i=parseFloat(o.marginLeft||0)+parseFloat(o.marginRight||0),r={width:e.offsetWidth+i,height:e.offsetHeight+n};return r}function T(e){var t={left:'right',right:'left',bottom:'top',top:'bottom'};return e.replace(/left|right|bottom|top/g,function(e){return t[e]})}function C(e,t,o){o=o.split('-')[0];var n=S(e),i={width:n.width,height:n.height},r=-1!==['right','left'].indexOf(o),p=r?'top':'left',s=r?'left':'top',d=r?'height':'width',a=r?'width':'height';return i[p]=t[p]+t[d]/2-n[d]/2,i[s]=o===s?t[s]-n[a]:t[T(s)],i}function D(e,t){return Array.prototype.find?e.find(t):e.filter(t)[0]}function N(e,t,o){if(Array.prototype.findIndex)return e.findIndex(function(e){return e[t]===o});var n=D(e,function(e){return e[t]===o});return e.indexOf(n)}function P(t,o,n){var i=void 0===n?t:t.slice(0,N(t,'name',n));return i.forEach(function(t){t['function']&&console.warn('`modifier.function` is deprecated, use `modifier.fn`!');var n=t['function']||t.fn;t.enabled&&e(n)&&(o.offsets.popper=g(o.offsets.popper),o.offsets.reference=g(o.offsets.reference),o=n(o,t))}),o}function k(){if(!this.state.isDestroyed){var e={instance:this,styles:{},arrowStyles:{},attributes:{},flipped:!1,offsets:{}};e.offsets.reference=L(this.state,this.popper,this.reference,this.options.positionFixed),e.placement=O(this.options.placement,e.offsets.reference,this.popper,this.reference,this.options.modifiers.flip.boundariesElement,this.options.modifiers.flip.padding),e.originalPlacement=e.placement,e.positionFixed=this.options.positionFixed,e.offsets.popper=C(this.popper,e.offsets.reference,e.placement),e.offsets.popper.position=this.options.positionFixed?'fixed':'absolute',e=P(this.modifiers,e),this.state.isCreated?this.options.onUpdate(e):(this.state.isCreated=!0,this.options.onCreate(e))}}function W(e,t){return e.some(function(e){var o=e.name,n=e.enabled;return n&&o===t})}function B(e){for(var t=[!1,'ms','Webkit','Moz','O'],o=e.charAt(0).toUpperCase()+e.slice(1),n=0;n<t.length;n++){var i=t[n],r=i?''+i+o:e;if('undefined'!=typeof document.body.style[r])return r}return null}function H(){return this.state.isDestroyed=!0,W(this.modifiers,'applyStyle')&&(this.popper.removeAttribute('x-placement'),this.popper.style.position='',this.popper.style.top='',this.popper.style.left='',this.popper.style.right='',this.popper.style.bottom='',this.popper.style.willChange='',this.popper.style[B('transform')]=''),this.disableEventListeners(),this.options.removeOnDestroy&&this.popper.parentNode.removeChild(this.popper),this}function A(e){var t=e.ownerDocument;return t?t.defaultView:window}function M(e,t,o,i){var r='BODY'===e.nodeName,p=r?e.ownerDocument.defaultView:e;p.addEventListener(t,o,{passive:!0}),r||M(n(p.parentNode),t,o,i),i.push(p)}function F(e,t,o,i){o.updateBound=i,A(e).addEventListener('resize',o.updateBound,{passive:!0});var r=n(e);return M(r,'scroll',o.updateBound,o.scrollParents),o.scrollElement=r,o.eventsEnabled=!0,o}function I(){this.state.eventsEnabled||(this.state=F(this.reference,this.options,this.state,this.scheduleUpdate))}function R(e,t){return A(e).removeEventListener('resize',t.updateBound),t.scrollParents.forEach(function(e){e.removeEventListener('scroll',t.updateBound)}),t.updateBound=null,t.scrollParents=[],t.scrollElement=null,t.eventsEnabled=!1,t}function U(){this.state.eventsEnabled&&(cancelAnimationFrame(this.scheduleUpdate),this.state=R(this.reference,this.state))}function Y(e){return''!==e&&!isNaN(parseFloat(e))&&isFinite(e)}function V(e,t){Object.keys(t).forEach(function(o){var n='';-1!==['width','height','top','right','bottom','left'].indexOf(o)&&Y(t[o])&&(n='px'),e.style[o]=t[o]+n})}function j(e,t){Object.keys(t).forEach(function(o){var n=t[o];!1===n?e.removeAttribute(o):e.setAttribute(o,t[o])})}function q(e,t){var o=e.offsets,n=o.popper,i=o.reference,r=$,p=function(e){return e},s=r(i.width),d=r(n.width),a=-1!==['left','right'].indexOf(e.placement),l=-1!==e.placement.indexOf('-'),f=t?a||l||s%2==d%2?r:Z:p,m=t?r:p;return{left:f(1==s%2&&1==d%2&&!l&&t?n.left-1:n.left),top:m(n.top),bottom:m(n.bottom),right:f(n.right)}}function K(e,t,o){var n=D(e,function(e){var o=e.name;return o===t}),i=!!n&&e.some(function(e){return e.name===o&&e.enabled&&e.order<n.order});if(!i){var r='`'+t+'`';console.warn('`'+o+'`'+' modifier is required by '+r+' modifier in order to work, be sure to include it before '+r+'!')}return i}function z(e){return'end'===e?'start':'start'===e?'end':e}function G(e){var t=1<arguments.length&&void 0!==arguments[1]&&arguments[1],o=ce.indexOf(e),n=ce.slice(o+1).concat(ce.slice(0,o));return t?n.reverse():n}function _(e,t,o,n){var i=e.match(/((?:\-|\+)?\d*\.?\d*)(.*)/),r=+i[1],p=i[2];if(!r)return e;if(0===p.indexOf('%')){var s;switch(p){case'%p':s=o;break;case'%':case'%r':default:s=n;}var d=g(s);return d[t]/100*r}if('vh'===p||'vw'===p){var a;return a='vh'===p?ee(document.documentElement.clientHeight,window.innerHeight||0):ee(document.documentElement.clientWidth,window.innerWidth||0),a/100*r}return r}function X(e,t,o,n){var i=[0,0],r=-1!==['right','left'].indexOf(n),p=e.split(/(\+|\-)/).map(function(e){return e.trim()}),s=p.indexOf(D(p,function(e){return-1!==e.search(/,|\s/)}));p[s]&&-1===p[s].indexOf(',')&&console.warn('Offsets separated by white space(s) are deprecated, use a comma (,) instead.');var d=/\s*,\s*|\s+/,a=-1===s?[p]:[p.slice(0,s).concat([p[s].split(d)[0]]),[p[s].split(d)[1]].concat(p.slice(s+1))];return a=a.map(function(e,n){var i=(1===n?!r:r)?'height':'width',p=!1;return e.reduce(function(e,t){return''===e[e.length-1]&&-1!==['+','-'].indexOf(t)?(e[e.length-1]=t,p=!0,e):p?(e[e.length-1]+=t,p=!1,e):e.concat(t)},[]).map(function(e){return _(e,i,t,o)})}),a.forEach(function(e,t){e.forEach(function(o,n){Y(o)&&(i[t]+=o*('-'===e[n-1]?-1:1))})}),i}function J(e,t){var o,n=t.offset,i=e.placement,r=e.offsets,p=r.popper,s=r.reference,d=i.split('-')[0];return o=Y(+n)?[+n,0]:X(n,p,s,d),'left'===d?(p.top+=o[0],p.left-=o[1]):'right'===d?(p.top+=o[0],p.left+=o[1]):'top'===d?(p.left+=o[0],p.top-=o[1]):'bottom'===d&&(p.left+=o[0],p.top+=o[1]),e.popper=p,e}for(var Q=Math.min,Z=Math.floor,$=Math.round,ee=Math.max,te='undefined'!=typeof window&&'undefined'!=typeof document,oe=['Edge','Trident','Firefox'],ne=0,ie=0;ie<oe.length;ie+=1)if(te&&0<=navigator.userAgent.indexOf(oe[ie])){ne=1;break}var i=te&&window.Promise,re=i?function(e){var t=!1;return function(){t||(t=!0,window.Promise.resolve().then(function(){t=!1,e()}))}}:function(e){var t=!1;return function(){t||(t=!0,setTimeout(function(){t=!1,e()},ne))}},pe=te&&!!(window.MSInputMethodContext&&document.documentMode),se=te&&/MSIE 10/.test(navigator.userAgent),de=function(e,t){if(!(e instanceof t))throw new TypeError('Cannot call a class as a function')},ae=function(){function e(e,t){for(var o,n=0;n<t.length;n++)o=t[n],o.enumerable=o.enumerable||!1,o.configurable=!0,'value'in o&&(o.writable=!0),Object.defineProperty(e,o.key,o)}return function(t,o,n){return o&&e(t.prototype,o),n&&e(t,n),t}}(),le=function(e,t,o){return t in e?Object.defineProperty(e,t,{value:o,enumerable:!0,configurable:!0,writable:!0}):e[t]=o,e},fe=Object.assign||function(e){for(var t,o=1;o<arguments.length;o++)for(var n in t=arguments[o],t)Object.prototype.hasOwnProperty.call(t,n)&&(e[n]=t[n]);return e},me=te&&/Firefox/i.test(navigator.userAgent),he=['auto-start','auto','auto-end','top-start','top','top-end','right-start','right','right-end','bottom-end','bottom','bottom-start','left-end','left','left-start'],ce=he.slice(3),ge={FLIP:'flip',CLOCKWISE:'clockwise',COUNTERCLOCKWISE:'counterclockwise'},ue=function(){function t(o,n){var i=this,r=2<arguments.length&&void 0!==arguments[2]?arguments[2]:{};de(this,t),this.scheduleUpdate=function(){return requestAnimationFrame(i.update)},this.update=re(this.update.bind(this)),this.options=fe({},t.Defaults,r),this.state={isDestroyed:!1,isCreated:!1,scrollParents:[]},this.reference=o&&o.jquery?o[0]:o,this.popper=n&&n.jquery?n[0]:n,this.options.modifiers={},Object.keys(fe({},t.Defaults.modifiers,r.modifiers)).forEach(function(e){i.options.modifiers[e]=fe({},t.Defaults.modifiers[e]||{},r.modifiers?r.modifiers[e]:{})}),this.modifiers=Object.keys(this.options.modifiers).map(function(e){return fe({name:e},i.options.modifiers[e])}).sort(function(e,t){return e.order-t.order}),this.modifiers.forEach(function(t){t.enabled&&e(t.onLoad)&&t.onLoad(i.reference,i.popper,i.options,t,i.state)}),this.update();var p=this.options.eventsEnabled;p&&this.enableEventListeners(),this.state.eventsEnabled=p}return ae(t,[{key:'update',value:function(){return k.call(this)}},{key:'destroy',value:function(){return H.call(this)}},{key:'enableEventListeners',value:function(){return I.call(this)}},{key:'disableEventListeners',value:function(){return U.call(this)}}]),t}();return ue.Utils=('undefined'==typeof window?global:window).PopperUtils,ue.placements=he,ue.Defaults={placement:'bottom',positionFixed:!1,eventsEnabled:!0,removeOnDestroy:!1,onCreate:function(){},onUpdate:function(){},modifiers:{shift:{order:100,enabled:!0,fn:function(e){var t=e.placement,o=t.split('-')[0],n=t.split('-')[1];if(n){var i=e.offsets,r=i.reference,p=i.popper,s=-1!==['bottom','top'].indexOf(o),d=s?'left':'top',a=s?'width':'height',l={start:le({},d,r[d]),end:le({},d,r[d]+r[a]-p[a])};e.offsets.popper=fe({},p,l[n])}return e}},offset:{order:200,enabled:!0,fn:J,offset:0},preventOverflow:{order:300,enabled:!0,fn:function(e,t){var o=t.boundariesElement||p(e.instance.popper);e.instance.reference===o&&(o=p(o));var n=B('transform'),i=e.instance.popper.style,r=i.top,s=i.left,d=i[n];i.top='',i.left='',i[n]='';var a=v(e.instance.popper,e.instance.reference,t.padding,o,e.positionFixed);i.top=r,i.left=s,i[n]=d,t.boundaries=a;var l=t.priority,f=e.offsets.popper,m={primary:function(e){var o=f[e];return f[e]<a[e]&&!t.escapeWithReference&&(o=ee(f[e],a[e])),le({},e,o)},secondary:function(e){var o='right'===e?'left':'top',n=f[o];return f[e]>a[e]&&!t.escapeWithReference&&(n=Q(f[o],a[e]-('right'===e?f.width:f.height))),le({},o,n)}};return l.forEach(function(e){var t=-1===['left','top'].indexOf(e)?'secondary':'primary';f=fe({},f,m[t](e))}),e.offsets.popper=f,e},priority:['left','right','top','bottom'],padding:5,boundariesElement:'scrollParent'},keepTogether:{order:400,enabled:!0,fn:function(e){var t=e.offsets,o=t.popper,n=t.reference,i=e.placement.split('-')[0],r=Z,p=-1!==['top','bottom'].indexOf(i),s=p?'right':'bottom',d=p?'left':'top',a=p?'width':'height';return o[s]<r(n[d])&&(e.offsets.popper[d]=r(n[d])-o[a]),o[d]>r(n[s])&&(e.offsets.popper[d]=r(n[s])),e}},arrow:{order:500,enabled:!0,fn:function(e,o){var n;if(!K(e.instance.modifiers,'arrow','keepTogether'))return e;var i=o.element;if('string'==typeof i){if(i=e.instance.popper.querySelector(i),!i)return e;}else if(!e.instance.popper.contains(i))return console.warn('WARNING: `arrow.element` must be child of its popper element!'),e;var r=e.placement.split('-')[0],p=e.offsets,s=p.popper,d=p.reference,a=-1!==['left','right'].indexOf(r),l=a?'height':'width',f=a?'Top':'Left',m=f.toLowerCase(),h=a?'left':'top',c=a?'bottom':'right',u=S(i)[l];d[c]-u<s[m]&&(e.offsets.popper[m]-=s[m]-(d[c]-u)),d[m]+u>s[c]&&(e.offsets.popper[m]+=d[m]+u-s[c]),e.offsets.popper=g(e.offsets.popper);var b=d[m]+d[l]/2-u/2,w=t(e.instance.popper),y=parseFloat(w['margin'+f],10),E=parseFloat(w['border'+f+'Width'],10),v=b-e.offsets.popper[m]-y-E;return v=ee(Q(s[l]-u,v),0),e.arrowElement=i,e.offsets.arrow=(n={},le(n,m,$(v)),le(n,h,''),n),e},element:'[x-arrow]'},flip:{order:600,enabled:!0,fn:function(e,t){if(W(e.instance.modifiers,'inner'))return e;if(e.flipped&&e.placement===e.originalPlacement)return e;var o=v(e.instance.popper,e.instance.reference,t.padding,t.boundariesElement,e.positionFixed),n=e.placement.split('-')[0],i=T(n),r=e.placement.split('-')[1]||'',p=[];switch(t.behavior){case ge.FLIP:p=[n,i];break;case ge.CLOCKWISE:p=G(n);break;case ge.COUNTERCLOCKWISE:p=G(n,!0);break;default:p=t.behavior;}return p.forEach(function(s,d){if(n!==s||p.length===d+1)return e;n=e.placement.split('-')[0],i=T(n);var a=e.offsets.popper,l=e.offsets.reference,f=Z,m='left'===n&&f(a.right)>f(l.left)||'right'===n&&f(a.left)<f(l.right)||'top'===n&&f(a.bottom)>f(l.top)||'bottom'===n&&f(a.top)<f(l.bottom),h=f(a.left)<f(o.left),c=f(a.right)>f(o.right),g=f(a.top)<f(o.top),u=f(a.bottom)>f(o.bottom),b='left'===n&&h||'right'===n&&c||'top'===n&&g||'bottom'===n&&u,w=-1!==['top','bottom'].indexOf(n),y=!!t.flipVariations&&(w&&'start'===r&&h||w&&'end'===r&&c||!w&&'start'===r&&g||!w&&'end'===r&&u),E=!!t.flipVariationsByContent&&(w&&'start'===r&&c||w&&'end'===r&&h||!w&&'start'===r&&u||!w&&'end'===r&&g),v=y||E;(m||b||v)&&(e.flipped=!0,(m||b)&&(n=p[d+1]),v&&(r=z(r)),e.placement=n+(r?'-'+r:''),e.offsets.popper=fe({},e.offsets.popper,C(e.instance.popper,e.offsets.reference,e.placement)),e=P(e.instance.modifiers,e,'flip'))}),e},behavior:'flip',padding:5,boundariesElement:'viewport',flipVariations:!1,flipVariationsByContent:!1},inner:{order:700,enabled:!1,fn:function(e){var t=e.placement,o=t.split('-')[0],n=e.offsets,i=n.popper,r=n.reference,p=-1!==['left','right'].indexOf(o),s=-1===['top','left'].indexOf(o);return i[p?'left':'top']=r[o]-(s?i[p?'width':'height']:0),e.placement=T(t),e.offsets.popper=g(i),e}},hide:{order:800,enabled:!0,fn:function(e){if(!K(e.instance.modifiers,'hide','preventOverflow'))return e;var t=e.offsets.reference,o=D(e.instance.modifiers,function(e){return'preventOverflow'===e.name}).boundaries;if(t.bottom<o.top||t.left>o.right||t.top>o.bottom||t.right<o.left){if(!0===e.hide)return e;e.hide=!0,e.attributes['x-out-of-boundaries']=''}else{if(!1===e.hide)return e;e.hide=!1,e.attributes['x-out-of-boundaries']=!1}return e}},computeStyle:{order:850,enabled:!0,fn:function(e,t){var o=t.x,n=t.y,i=e.offsets.popper,r=D(e.instance.modifiers,function(e){return'applyStyle'===e.name}).gpuAcceleration;void 0!==r&&console.warn('WARNING: `gpuAcceleration` option moved to `computeStyle` modifier and will not be supported in future versions of Popper.js!');var s,d,a=void 0===r?t.gpuAcceleration:r,l=p(e.instance.popper),f=u(l),m={position:i.position},h=q(e,2>window.devicePixelRatio||!me),c='bottom'===o?'top':'bottom',g='right'===n?'left':'right',b=B('transform');if(d='bottom'==c?'HTML'===l.nodeName?-l.clientHeight+h.bottom:-f.height+h.bottom:h.top,s='right'==g?'HTML'===l.nodeName?-l.clientWidth+h.right:-f.width+h.right:h.left,a&&b)m[b]='translate3d('+s+'px, '+d+'px, 0)',m[c]=0,m[g]=0,m.willChange='transform';else{var w='bottom'==c?-1:1,y='right'==g?-1:1;m[c]=d*w,m[g]=s*y,m.willChange=c+', '+g}var E={"x-placement":e.placement};return e.attributes=fe({},E,e.attributes),e.styles=fe({},m,e.styles),e.arrowStyles=fe({},e.offsets.arrow,e.arrowStyles),e},gpuAcceleration:!0,x:'bottom',y:'right'},applyStyle:{order:900,enabled:!0,fn:function(e){return V(e.instance.popper,e.styles),j(e.instance.popper,e.attributes),e.arrowElement&&Object.keys(e.arrowStyles).length&&V(e.arrowElement,e.arrowStyles),e},onLoad:function(e,t,o,n,i){var r=L(i,t,e,o.positionFixed),p=O(o.placement,r,t,e,o.modifiers.flip.boundariesElement,o.modifiers.flip.padding);return t.setAttribute('x-placement',p),V(t,{position:o.positionFixed?'fixed':'absolute'}),o},gpuAcceleration:void 0}}},ue});
+//# sourceMappingURL=popper.min.js.map
diff --git a/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/line.html.dist b/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/line.html.dist
new file mode 100644
index 0000000000000000000000000000000000000000..89810d157bdc96699074ac94d04e6bed1b1c2800
--- /dev/null
+++ b/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/line.html.dist
@@ -0,0 +1 @@
+    <tr class="{{class}} d-flex"><td {{popover}} class="col-1 text-right"><a id="{{lineNumber}}" href="#{{lineNumber}}">{{lineNumber}}</a></td><td class="col-11 codeLine">{{lineContent}}</td></tr>
diff --git a/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/lines.html.dist b/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/lines.html.dist
new file mode 100644
index 0000000000000000000000000000000000000000..add40e4e9b28afcd3d8ccbf555d317aa98c01ca6
--- /dev/null
+++ b/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/lines.html.dist
@@ -0,0 +1,5 @@
+<table id="code" class="table table-borderless table-condensed">
+<tbody>
+{{lines}}
+</tbody>
+</table>
diff --git a/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/method_item.html.dist b/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/method_item.html.dist
new file mode 100644
index 0000000000000000000000000000000000000000..d8890ed279dc9ab3127bcc2d1476089182925b9a
--- /dev/null
+++ b/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/method_item.html.dist
@@ -0,0 +1,11 @@
+      <tr>
+       <td class="{{methods_level}}" colspan="4">{{name}}</td>
+       <td class="{{methods_level}} big">{{methods_bar}}</td>
+       <td class="{{methods_level}} small"><div align="right">{{methods_tested_percent}}</div></td>
+       <td class="{{methods_level}} small"><div align="right">{{methods_number}}</div></td>
+       <td class="{{methods_level}} small">{{crap}}</td>
+       <td class="{{lines_level}} big">{{lines_bar}}</td>
+       <td class="{{lines_level}} small"><div align="right">{{lines_executed_percent}}</div></td>
+       <td class="{{lines_level}} small"><div align="right">{{lines_number}}</div></td>
+      </tr>
+
diff --git a/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/method_item_branch.html.dist b/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/method_item_branch.html.dist
new file mode 100644
index 0000000000000000000000000000000000000000..a6a25f95e76818fef26ba88b5230ac7bebf76a91
--- /dev/null
+++ b/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/method_item_branch.html.dist
@@ -0,0 +1,17 @@
+      <tr>
+       <td class="{{methods_level}}" colspan="4">{{name}}</td>
+       <td class="{{methods_level}} big">{{methods_bar}}</td>
+       <td class="{{methods_level}} small"><div align="right">{{methods_tested_percent}}</div></td>
+       <td class="{{methods_level}} small"><div align="right">{{methods_number}}</div></td>
+       <td class="{{methods_level}} small">{{crap}}</td>
+       <td class="{{paths_level}} big">{{paths_bar}}</td>
+       <td class="{{paths_level}} small"><div align="right">{{paths_executed_percent}}</div></td>
+       <td class="{{paths_level}} small"><div align="right">{{paths_number}}</div></td>
+       <td class="{{branches_level}} big">{{branches_bar}}</td>
+       <td class="{{branches_level}} small"><div align="right">{{branches_executed_percent}}</div></td>
+       <td class="{{branches_level}} small"><div align="right">{{branches_number}}</div></td>
+       <td class="{{lines_level}} big">{{lines_bar}}</td>
+       <td class="{{lines_level}} small"><div align="right">{{lines_executed_percent}}</div></td>
+       <td class="{{lines_level}} small"><div align="right">{{lines_number}}</div></td>
+      </tr>
+
diff --git a/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/paths.html.dist b/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/paths.html.dist
new file mode 100644
index 0000000000000000000000000000000000000000..d14b8ad9d4a9a00348956425c590f9b7dd9a1e31
--- /dev/null
+++ b/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/paths.html.dist
@@ -0,0 +1,9 @@
+<hr/>
+<h4>Paths</h4>
+<p>
+    Below are the source code lines that represent each code path as identified by Xdebug. Please note a path is not
+    necessarily coterminous with a line, a line may contain multiple paths and therefore show up more than once.
+    Please also be aware that some paths may include implicit rather than explicit branches, e.g. an <code>if</code> statement
+    <i>always</i> has an <code>else</code> as part of its logical flow even if you didn't write one.
+</p>
+{{paths}}
diff --git a/vendor/phpunit/php-code-coverage/src/Report/PHP.php b/vendor/phpunit/php-code-coverage/src/Report/PHP.php
new file mode 100644
index 0000000000000000000000000000000000000000..cb6e263e12ad1dcb4f99879cb6c864bda3c19ca4
--- /dev/null
+++ b/vendor/phpunit/php-code-coverage/src/Report/PHP.php
@@ -0,0 +1,41 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of phpunit/php-code-coverage.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\CodeCoverage\Report;
+
+use function addcslashes;
+use function dirname;
+use function file_put_contents;
+use function serialize;
+use function sprintf;
+use SebastianBergmann\CodeCoverage\CodeCoverage;
+use SebastianBergmann\CodeCoverage\Directory;
+use SebastianBergmann\CodeCoverage\Driver\WriteOperationFailedException;
+
+final class PHP
+{
+    public function process(CodeCoverage $coverage, ?string $target = null): string
+    {
+        $buffer = sprintf(
+            '<?php
+return \unserialize(\'%s\');',
+            addcslashes(serialize($coverage), "'")
+        );
+
+        if ($target !== null) {
+            Directory::create(dirname($target));
+
+            if (@file_put_contents($target, $buffer) === false) {
+                throw new WriteOperationFailedException($target);
+            }
+        }
+
+        return $buffer;
+    }
+}
diff --git a/vendor/phpunit/php-code-coverage/src/Report/Text.php b/vendor/phpunit/php-code-coverage/src/Report/Text.php
new file mode 100644
index 0000000000000000000000000000000000000000..b587d36a836d44bf8cccf67ef4fe9fa67872bd54
--- /dev/null
+++ b/vendor/phpunit/php-code-coverage/src/Report/Text.php
@@ -0,0 +1,341 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of phpunit/php-code-coverage.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\CodeCoverage\Report;
+
+use const PHP_EOL;
+use function array_map;
+use function date;
+use function ksort;
+use function max;
+use function sprintf;
+use function str_pad;
+use function strlen;
+use SebastianBergmann\CodeCoverage\CodeCoverage;
+use SebastianBergmann\CodeCoverage\Node\File;
+use SebastianBergmann\CodeCoverage\Percentage;
+
+final class Text
+{
+    /**
+     * @var string
+     */
+    private const COLOR_GREEN = "\x1b[30;42m";
+
+    /**
+     * @var string
+     */
+    private const COLOR_YELLOW = "\x1b[30;43m";
+
+    /**
+     * @var string
+     */
+    private const COLOR_RED = "\x1b[37;41m";
+
+    /**
+     * @var string
+     */
+    private const COLOR_HEADER = "\x1b[1;37;40m";
+
+    /**
+     * @var string
+     */
+    private const COLOR_RESET = "\x1b[0m";
+
+    /**
+     * @var string
+     */
+    private const COLOR_EOL = "\x1b[2K";
+
+    /**
+     * @var int
+     */
+    private $lowUpperBound;
+
+    /**
+     * @var int
+     */
+    private $highLowerBound;
+
+    /**
+     * @var bool
+     */
+    private $showUncoveredFiles;
+
+    /**
+     * @var bool
+     */
+    private $showOnlySummary;
+
+    public function __construct(int $lowUpperBound = 50, int $highLowerBound = 90, bool $showUncoveredFiles = false, bool $showOnlySummary = false)
+    {
+        $this->lowUpperBound      = $lowUpperBound;
+        $this->highLowerBound     = $highLowerBound;
+        $this->showUncoveredFiles = $showUncoveredFiles;
+        $this->showOnlySummary    = $showOnlySummary;
+    }
+
+    public function process(CodeCoverage $coverage, bool $showColors = false): string
+    {
+        $hasBranchCoverage = !empty($coverage->getData(true)->functionCoverage());
+
+        $output = PHP_EOL . PHP_EOL;
+        $report = $coverage->getReport();
+
+        $colors = [
+            'header'   => '',
+            'classes'  => '',
+            'methods'  => '',
+            'lines'    => '',
+            'branches' => '',
+            'paths'    => '',
+            'reset'    => '',
+            'eol'      => '',
+        ];
+
+        if ($showColors) {
+            $colors['classes'] = $this->coverageColor(
+                $report->numberOfTestedClassesAndTraits(),
+                $report->numberOfClassesAndTraits()
+            );
+
+            $colors['methods'] = $this->coverageColor(
+                $report->numberOfTestedMethods(),
+                $report->numberOfMethods()
+            );
+
+            $colors['lines'] = $this->coverageColor(
+                $report->numberOfExecutedLines(),
+                $report->numberOfExecutableLines()
+            );
+
+            $colors['branches'] = $this->coverageColor(
+                $report->numberOfExecutedBranches(),
+                $report->numberOfExecutableBranches()
+            );
+
+            $colors['paths'] = $this->coverageColor(
+                $report->numberOfExecutedPaths(),
+                $report->numberOfExecutablePaths()
+            );
+
+            $colors['reset']  = self::COLOR_RESET;
+            $colors['header'] = self::COLOR_HEADER;
+            $colors['eol']    = self::COLOR_EOL;
+        }
+
+        $classes = sprintf(
+            '  Classes: %6s (%d/%d)',
+            Percentage::fromFractionAndTotal(
+                $report->numberOfTestedClassesAndTraits(),
+                $report->numberOfClassesAndTraits()
+            )->asString(),
+            $report->numberOfTestedClassesAndTraits(),
+            $report->numberOfClassesAndTraits()
+        );
+
+        $methods = sprintf(
+            '  Methods: %6s (%d/%d)',
+            Percentage::fromFractionAndTotal(
+                $report->numberOfTestedMethods(),
+                $report->numberOfMethods(),
+            )->asString(),
+            $report->numberOfTestedMethods(),
+            $report->numberOfMethods()
+        );
+
+        $paths    = '';
+        $branches = '';
+
+        if ($hasBranchCoverage) {
+            $paths = sprintf(
+                '  Paths:   %6s (%d/%d)',
+                Percentage::fromFractionAndTotal(
+                    $report->numberOfExecutedPaths(),
+                    $report->numberOfExecutablePaths(),
+                )->asString(),
+                $report->numberOfExecutedPaths(),
+                $report->numberOfExecutablePaths()
+            );
+
+            $branches = sprintf(
+                '  Branches:   %6s (%d/%d)',
+                Percentage::fromFractionAndTotal(
+                    $report->numberOfExecutedBranches(),
+                    $report->numberOfExecutableBranches(),
+                )->asString(),
+                $report->numberOfExecutedBranches(),
+                $report->numberOfExecutableBranches()
+            );
+        }
+
+        $lines = sprintf(
+            '  Lines:   %6s (%d/%d)',
+            Percentage::fromFractionAndTotal(
+                $report->numberOfExecutedLines(),
+                $report->numberOfExecutableLines(),
+            )->asString(),
+            $report->numberOfExecutedLines(),
+            $report->numberOfExecutableLines()
+        );
+
+        $padding = max(array_map('strlen', [$classes, $methods, $lines]));
+
+        if ($this->showOnlySummary) {
+            $title   = 'Code Coverage Report Summary:';
+            $padding = max($padding, strlen($title));
+
+            $output .= $this->format($colors['header'], $padding, $title);
+        } else {
+            $date  = date('  Y-m-d H:i:s');
+            $title = 'Code Coverage Report:';
+
+            $output .= $this->format($colors['header'], $padding, $title);
+            $output .= $this->format($colors['header'], $padding, $date);
+            $output .= $this->format($colors['header'], $padding, '');
+            $output .= $this->format($colors['header'], $padding, ' Summary:');
+        }
+
+        $output .= $this->format($colors['classes'], $padding, $classes);
+        $output .= $this->format($colors['methods'], $padding, $methods);
+
+        if ($hasBranchCoverage) {
+            $output .= $this->format($colors['paths'], $padding, $paths);
+            $output .= $this->format($colors['branches'], $padding, $branches);
+        }
+        $output .= $this->format($colors['lines'], $padding, $lines);
+
+        if ($this->showOnlySummary) {
+            return $output . PHP_EOL;
+        }
+
+        $classCoverage = [];
+
+        foreach ($report as $item) {
+            if (!$item instanceof File) {
+                continue;
+            }
+
+            $classes = $item->classesAndTraits();
+
+            foreach ($classes as $className => $class) {
+                $classExecutableLines    = 0;
+                $classExecutedLines      = 0;
+                $classExecutableBranches = 0;
+                $classExecutedBranches   = 0;
+                $classExecutablePaths    = 0;
+                $classExecutedPaths      = 0;
+                $coveredMethods          = 0;
+                $classMethods            = 0;
+
+                foreach ($class['methods'] as $method) {
+                    if ($method['executableLines'] == 0) {
+                        continue;
+                    }
+
+                    $classMethods++;
+                    $classExecutableLines += $method['executableLines'];
+                    $classExecutedLines += $method['executedLines'];
+                    $classExecutableBranches += $method['executableBranches'];
+                    $classExecutedBranches += $method['executedBranches'];
+                    $classExecutablePaths += $method['executablePaths'];
+                    $classExecutedPaths += $method['executedPaths'];
+
+                    if ($method['coverage'] == 100) {
+                        $coveredMethods++;
+                    }
+                }
+
+                $classCoverage[$className] = [
+                    'namespace'         => $class['namespace'],
+                    'className'         => $className,
+                    'methodsCovered'    => $coveredMethods,
+                    'methodCount'       => $classMethods,
+                    'statementsCovered' => $classExecutedLines,
+                    'statementCount'    => $classExecutableLines,
+                    'branchesCovered'   => $classExecutedBranches,
+                    'branchesCount'     => $classExecutableBranches,
+                    'pathsCovered'      => $classExecutedPaths,
+                    'pathsCount'        => $classExecutablePaths,
+                ];
+            }
+        }
+
+        ksort($classCoverage);
+
+        $methodColor   = '';
+        $pathsColor    = '';
+        $branchesColor = '';
+        $linesColor    = '';
+        $resetColor    = '';
+
+        foreach ($classCoverage as $fullQualifiedPath => $classInfo) {
+            if ($this->showUncoveredFiles || $classInfo['statementsCovered'] != 0) {
+                if ($showColors) {
+                    $methodColor   = $this->coverageColor($classInfo['methodsCovered'], $classInfo['methodCount']);
+                    $pathsColor    = $this->coverageColor($classInfo['pathsCovered'], $classInfo['pathsCount']);
+                    $branchesColor = $this->coverageColor($classInfo['branchesCovered'], $classInfo['branchesCount']);
+                    $linesColor    = $this->coverageColor($classInfo['statementsCovered'], $classInfo['statementCount']);
+                    $resetColor    = $colors['reset'];
+                }
+
+                $output .= PHP_EOL . $fullQualifiedPath . PHP_EOL
+                    . '  ' . $methodColor . 'Methods: ' . $this->printCoverageCounts($classInfo['methodsCovered'], $classInfo['methodCount'], 2) . $resetColor . ' ';
+
+                if ($hasBranchCoverage) {
+                    $output .= '  ' . $pathsColor . 'Paths: ' . $this->printCoverageCounts($classInfo['pathsCovered'], $classInfo['pathsCount'], 3) . $resetColor . ' '
+                    . '  ' . $branchesColor . 'Branches: ' . $this->printCoverageCounts($classInfo['branchesCovered'], $classInfo['branchesCount'], 3) . $resetColor . ' ';
+                }
+                $output .= '  ' . $linesColor . 'Lines: ' . $this->printCoverageCounts($classInfo['statementsCovered'], $classInfo['statementCount'], 3) . $resetColor;
+            }
+        }
+
+        return $output . PHP_EOL;
+    }
+
+    private function coverageColor(int $numberOfCoveredElements, int $totalNumberOfElements): string
+    {
+        $coverage = Percentage::fromFractionAndTotal(
+            $numberOfCoveredElements,
+            $totalNumberOfElements
+        );
+
+        if ($coverage->asFloat() >= $this->highLowerBound) {
+            return self::COLOR_GREEN;
+        }
+
+        if ($coverage->asFloat() > $this->lowUpperBound) {
+            return self::COLOR_YELLOW;
+        }
+
+        return self::COLOR_RED;
+    }
+
+    private function printCoverageCounts(int $numberOfCoveredElements, int $totalNumberOfElements, int $precision): string
+    {
+        $format = '%' . $precision . 's';
+
+        return Percentage::fromFractionAndTotal(
+            $numberOfCoveredElements,
+            $totalNumberOfElements
+        )->asFixedWidthString() .
+            ' (' . sprintf($format, $numberOfCoveredElements) . '/' .
+        sprintf($format, $totalNumberOfElements) . ')';
+    }
+
+    /**
+     * @param false|string $string
+     */
+    private function format(string $color, int $padding, $string): string
+    {
+        $reset = $color ? self::COLOR_RESET : '';
+
+        return $color . str_pad((string) $string, $padding) . $reset . PHP_EOL;
+    }
+}
diff --git a/vendor/phpunit/php-code-coverage/src/Report/Xml/BuildInformation.php b/vendor/phpunit/php-code-coverage/src/Report/Xml/BuildInformation.php
new file mode 100644
index 0000000000000000000000000000000000000000..ebdbae612c711752afbee053117d35e1a09b17cb
--- /dev/null
+++ b/vendor/phpunit/php-code-coverage/src/Report/Xml/BuildInformation.php
@@ -0,0 +1,88 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of phpunit/php-code-coverage.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\CodeCoverage\Report\Xml;
+
+use function constant;
+use function phpversion;
+use DateTimeImmutable;
+use DOMElement;
+use SebastianBergmann\Environment\Runtime;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage
+ */
+final class BuildInformation
+{
+    /**
+     * @var DOMElement
+     */
+    private $contextNode;
+
+    public function __construct(DOMElement $contextNode)
+    {
+        $this->contextNode = $contextNode;
+    }
+
+    public function setRuntimeInformation(Runtime $runtime): void
+    {
+        $runtimeNode = $this->nodeByName('runtime');
+
+        $runtimeNode->setAttribute('name', $runtime->getName());
+        $runtimeNode->setAttribute('version', $runtime->getVersion());
+        $runtimeNode->setAttribute('url', $runtime->getVendorUrl());
+
+        $driverNode = $this->nodeByName('driver');
+
+        if ($runtime->hasPHPDBGCodeCoverage()) {
+            $driverNode->setAttribute('name', 'phpdbg');
+            $driverNode->setAttribute('version', constant('PHPDBG_VERSION'));
+        }
+
+        if ($runtime->hasXdebug()) {
+            $driverNode->setAttribute('name', 'xdebug');
+            $driverNode->setAttribute('version', phpversion('xdebug'));
+        }
+
+        if ($runtime->hasPCOV()) {
+            $driverNode->setAttribute('name', 'pcov');
+            $driverNode->setAttribute('version', phpversion('pcov'));
+        }
+    }
+
+    public function setBuildTime(DateTimeImmutable $date): void
+    {
+        $this->contextNode->setAttribute('time', $date->format('D M j G:i:s T Y'));
+    }
+
+    public function setGeneratorVersions(string $phpUnitVersion, string $coverageVersion): void
+    {
+        $this->contextNode->setAttribute('phpunit', $phpUnitVersion);
+        $this->contextNode->setAttribute('coverage', $coverageVersion);
+    }
+
+    private function nodeByName(string $name): DOMElement
+    {
+        $node = $this->contextNode->getElementsByTagNameNS(
+            'https://schema.phpunit.de/coverage/1.0',
+            $name
+        )->item(0);
+
+        if (!$node) {
+            $node = $this->contextNode->appendChild(
+                $this->contextNode->ownerDocument->createElementNS(
+                    'https://schema.phpunit.de/coverage/1.0',
+                    $name
+                )
+            );
+        }
+
+        return $node;
+    }
+}
diff --git a/vendor/phpunit/php-code-coverage/src/Report/Xml/Coverage.php b/vendor/phpunit/php-code-coverage/src/Report/Xml/Coverage.php
new file mode 100644
index 0000000000000000000000000000000000000000..215f9b932905af9a903e4c95b3258567b26ba0b5
--- /dev/null
+++ b/vendor/phpunit/php-code-coverage/src/Report/Xml/Coverage.php
@@ -0,0 +1,74 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of phpunit/php-code-coverage.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\CodeCoverage\Report\Xml;
+
+use DOMElement;
+use SebastianBergmann\CodeCoverage\ReportAlreadyFinalizedException;
+use XMLWriter;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage
+ */
+final class Coverage
+{
+    /**
+     * @var XMLWriter
+     */
+    private $writer;
+
+    /**
+     * @var DOMElement
+     */
+    private $contextNode;
+
+    /**
+     * @var bool
+     */
+    private $finalized = false;
+
+    public function __construct(DOMElement $context, string $line)
+    {
+        $this->contextNode = $context;
+
+        $this->writer = new XMLWriter();
+        $this->writer->openMemory();
+        $this->writer->startElementNS(null, $context->nodeName, 'https://schema.phpunit.de/coverage/1.0');
+        $this->writer->writeAttribute('nr', $line);
+    }
+
+    /**
+     * @throws ReportAlreadyFinalizedException
+     */
+    public function addTest(string $test): void
+    {
+        if ($this->finalized) {
+            throw new ReportAlreadyFinalizedException;
+        }
+
+        $this->writer->startElement('covered');
+        $this->writer->writeAttribute('by', $test);
+        $this->writer->endElement();
+    }
+
+    public function finalize(): void
+    {
+        $this->writer->endElement();
+
+        $fragment = $this->contextNode->ownerDocument->createDocumentFragment();
+        $fragment->appendXML($this->writer->outputMemory());
+
+        $this->contextNode->parentNode->replaceChild(
+            $fragment,
+            $this->contextNode
+        );
+
+        $this->finalized = true;
+    }
+}
diff --git a/vendor/phpunit/php-code-coverage/src/Report/Xml/Directory.php b/vendor/phpunit/php-code-coverage/src/Report/Xml/Directory.php
new file mode 100644
index 0000000000000000000000000000000000000000..b712953abbf85cffdecf7f0fec240af35239a108
--- /dev/null
+++ b/vendor/phpunit/php-code-coverage/src/Report/Xml/Directory.php
@@ -0,0 +1,17 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of phpunit/php-code-coverage.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\CodeCoverage\Report\Xml;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage
+ */
+final class Directory extends Node
+{
+}
diff --git a/vendor/phpunit/php-code-coverage/src/Report/Xml/Facade.php b/vendor/phpunit/php-code-coverage/src/Report/Xml/Facade.php
new file mode 100644
index 0000000000000000000000000000000000000000..b4158d33019f616592d8efb74098fdca007b918e
--- /dev/null
+++ b/vendor/phpunit/php-code-coverage/src/Report/Xml/Facade.php
@@ -0,0 +1,315 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of phpunit/php-code-coverage.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\CodeCoverage\Report\Xml;
+
+use const DIRECTORY_SEPARATOR;
+use const PHP_EOL;
+use function count;
+use function dirname;
+use function file_get_contents;
+use function file_put_contents;
+use function is_array;
+use function is_dir;
+use function is_file;
+use function is_writable;
+use function libxml_clear_errors;
+use function libxml_get_errors;
+use function libxml_use_internal_errors;
+use function sprintf;
+use function strlen;
+use function substr;
+use DateTimeImmutable;
+use DOMDocument;
+use SebastianBergmann\CodeCoverage\CodeCoverage;
+use SebastianBergmann\CodeCoverage\Directory as DirectoryUtil;
+use SebastianBergmann\CodeCoverage\Driver\PathExistsButIsNotDirectoryException;
+use SebastianBergmann\CodeCoverage\Driver\WriteOperationFailedException;
+use SebastianBergmann\CodeCoverage\Node\AbstractNode;
+use SebastianBergmann\CodeCoverage\Node\Directory as DirectoryNode;
+use SebastianBergmann\CodeCoverage\Node\File as FileNode;
+use SebastianBergmann\CodeCoverage\Version;
+use SebastianBergmann\CodeCoverage\XmlException;
+use SebastianBergmann\Environment\Runtime;
+
+final class Facade
+{
+    /**
+     * @var string
+     */
+    private $target;
+
+    /**
+     * @var Project
+     */
+    private $project;
+
+    /**
+     * @var string
+     */
+    private $phpUnitVersion;
+
+    public function __construct(string $version)
+    {
+        $this->phpUnitVersion = $version;
+    }
+
+    /**
+     * @throws XmlException
+     */
+    public function process(CodeCoverage $coverage, string $target): void
+    {
+        if (substr($target, -1, 1) !== DIRECTORY_SEPARATOR) {
+            $target .= DIRECTORY_SEPARATOR;
+        }
+
+        $this->target = $target;
+        $this->initTargetDirectory($target);
+
+        $report = $coverage->getReport();
+
+        $this->project = new Project(
+            $coverage->getReport()->name()
+        );
+
+        $this->setBuildInformation();
+        $this->processTests($coverage->getTests());
+        $this->processDirectory($report, $this->project);
+
+        $this->saveDocument($this->project->asDom(), 'index');
+    }
+
+    private function setBuildInformation(): void
+    {
+        $buildNode = $this->project->buildInformation();
+        $buildNode->setRuntimeInformation(new Runtime);
+        $buildNode->setBuildTime(new DateTimeImmutable);
+        $buildNode->setGeneratorVersions($this->phpUnitVersion, Version::id());
+    }
+
+    /**
+     * @throws PathExistsButIsNotDirectoryException
+     * @throws WriteOperationFailedException
+     */
+    private function initTargetDirectory(string $directory): void
+    {
+        if (is_file($directory)) {
+            if (!is_dir($directory)) {
+                throw new PathExistsButIsNotDirectoryException($directory);
+            }
+
+            if (!is_writable($directory)) {
+                throw new WriteOperationFailedException($directory);
+            }
+        }
+
+        DirectoryUtil::create($directory);
+    }
+
+    /**
+     * @throws XmlException
+     */
+    private function processDirectory(DirectoryNode $directory, Node $context): void
+    {
+        $directoryName = $directory->name();
+
+        if ($this->project->projectSourceDirectory() === $directoryName) {
+            $directoryName = '/';
+        }
+
+        $directoryObject = $context->addDirectory($directoryName);
+
+        $this->setTotals($directory, $directoryObject->totals());
+
+        foreach ($directory->directories() as $node) {
+            $this->processDirectory($node, $directoryObject);
+        }
+
+        foreach ($directory->files() as $node) {
+            $this->processFile($node, $directoryObject);
+        }
+    }
+
+    /**
+     * @throws XmlException
+     */
+    private function processFile(FileNode $file, Directory $context): void
+    {
+        $fileObject = $context->addFile(
+            $file->name(),
+            $file->id() . '.xml'
+        );
+
+        $this->setTotals($file, $fileObject->totals());
+
+        $path = substr(
+            $file->pathAsString(),
+            strlen($this->project->projectSourceDirectory())
+        );
+
+        $fileReport = new Report($path);
+
+        $this->setTotals($file, $fileReport->totals());
+
+        foreach ($file->classesAndTraits() as $unit) {
+            $this->processUnit($unit, $fileReport);
+        }
+
+        foreach ($file->functions() as $function) {
+            $this->processFunction($function, $fileReport);
+        }
+
+        foreach ($file->lineCoverageData() as $line => $tests) {
+            if (!is_array($tests) || count($tests) === 0) {
+                continue;
+            }
+
+            $coverage = $fileReport->lineCoverage((string) $line);
+
+            foreach ($tests as $test) {
+                $coverage->addTest($test);
+            }
+
+            $coverage->finalize();
+        }
+
+        $fileReport->source()->setSourceCode(
+            file_get_contents($file->pathAsString())
+        );
+
+        $this->saveDocument($fileReport->asDom(), $file->id());
+    }
+
+    private function processUnit(array $unit, Report $report): void
+    {
+        if (isset($unit['className'])) {
+            $unitObject = $report->classObject($unit['className']);
+        } else {
+            $unitObject = $report->traitObject($unit['traitName']);
+        }
+
+        $unitObject->setLines(
+            $unit['startLine'],
+            $unit['executableLines'],
+            $unit['executedLines']
+        );
+
+        $unitObject->setCrap((float) $unit['crap']);
+        $unitObject->setNamespace($unit['namespace']);
+
+        foreach ($unit['methods'] as $method) {
+            $methodObject = $unitObject->addMethod($method['methodName']);
+            $methodObject->setSignature($method['signature']);
+            $methodObject->setLines((string) $method['startLine'], (string) $method['endLine']);
+            $methodObject->setCrap($method['crap']);
+            $methodObject->setTotals(
+                (string) $method['executableLines'],
+                (string) $method['executedLines'],
+                (string) $method['coverage']
+            );
+        }
+    }
+
+    private function processFunction(array $function, Report $report): void
+    {
+        $functionObject = $report->functionObject($function['functionName']);
+
+        $functionObject->setSignature($function['signature']);
+        $functionObject->setLines((string) $function['startLine']);
+        $functionObject->setCrap($function['crap']);
+        $functionObject->setTotals((string) $function['executableLines'], (string) $function['executedLines'], (string) $function['coverage']);
+    }
+
+    private function processTests(array $tests): void
+    {
+        $testsObject = $this->project->tests();
+
+        foreach ($tests as $test => $result) {
+            $testsObject->addTest($test, $result);
+        }
+    }
+
+    private function setTotals(AbstractNode $node, Totals $totals): void
+    {
+        $loc = $node->linesOfCode();
+
+        $totals->setNumLines(
+            $loc->linesOfCode(),
+            $loc->commentLinesOfCode(),
+            $loc->nonCommentLinesOfCode(),
+            $node->numberOfExecutableLines(),
+            $node->numberOfExecutedLines()
+        );
+
+        $totals->setNumClasses(
+            $node->numberOfClasses(),
+            $node->numberOfTestedClasses()
+        );
+
+        $totals->setNumTraits(
+            $node->numberOfTraits(),
+            $node->numberOfTestedTraits()
+        );
+
+        $totals->setNumMethods(
+            $node->numberOfMethods(),
+            $node->numberOfTestedMethods()
+        );
+
+        $totals->setNumFunctions(
+            $node->numberOfFunctions(),
+            $node->numberOfTestedFunctions()
+        );
+    }
+
+    private function targetDirectory(): string
+    {
+        return $this->target;
+    }
+
+    /**
+     * @throws XmlException
+     */
+    private function saveDocument(DOMDocument $document, string $name): void
+    {
+        $filename = sprintf('%s/%s.xml', $this->targetDirectory(), $name);
+
+        $document->formatOutput       = true;
+        $document->preserveWhiteSpace = false;
+        $this->initTargetDirectory(dirname($filename));
+
+        file_put_contents($filename, $this->documentAsString($document));
+    }
+
+    /**
+     * @throws XmlException
+     *
+     * @see https://bugs.php.net/bug.php?id=79191
+     */
+    private function documentAsString(DOMDocument $document): string
+    {
+        $xmlErrorHandling = libxml_use_internal_errors(true);
+        $xml              = $document->saveXML();
+
+        if ($xml === false) {
+            $message = 'Unable to generate the XML';
+
+            foreach (libxml_get_errors() as $error) {
+                $message .= PHP_EOL . $error->message;
+            }
+
+            throw new XmlException($message);
+        }
+
+        libxml_clear_errors();
+        libxml_use_internal_errors($xmlErrorHandling);
+
+        return $xml;
+    }
+}
diff --git a/vendor/phpunit/php-code-coverage/src/Report/Xml/File.php b/vendor/phpunit/php-code-coverage/src/Report/Xml/File.php
new file mode 100644
index 0000000000000000000000000000000000000000..245c5cee6bd856b252552fbdb7c31128b1489a3b
--- /dev/null
+++ b/vendor/phpunit/php-code-coverage/src/Report/Xml/File.php
@@ -0,0 +1,87 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of phpunit/php-code-coverage.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\CodeCoverage\Report\Xml;
+
+use DOMDocument;
+use DOMElement;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage
+ */
+class File
+{
+    /**
+     * @var DOMDocument
+     */
+    private $dom;
+
+    /**
+     * @var DOMElement
+     */
+    private $contextNode;
+
+    public function __construct(DOMElement $context)
+    {
+        $this->dom         = $context->ownerDocument;
+        $this->contextNode = $context;
+    }
+
+    public function totals(): Totals
+    {
+        $totalsContainer = $this->contextNode->firstChild;
+
+        if (!$totalsContainer) {
+            $totalsContainer = $this->contextNode->appendChild(
+                $this->dom->createElementNS(
+                    'https://schema.phpunit.de/coverage/1.0',
+                    'totals'
+                )
+            );
+        }
+
+        return new Totals($totalsContainer);
+    }
+
+    public function lineCoverage(string $line): Coverage
+    {
+        $coverage = $this->contextNode->getElementsByTagNameNS(
+            'https://schema.phpunit.de/coverage/1.0',
+            'coverage'
+        )->item(0);
+
+        if (!$coverage) {
+            $coverage = $this->contextNode->appendChild(
+                $this->dom->createElementNS(
+                    'https://schema.phpunit.de/coverage/1.0',
+                    'coverage'
+                )
+            );
+        }
+
+        $lineNode = $coverage->appendChild(
+            $this->dom->createElementNS(
+                'https://schema.phpunit.de/coverage/1.0',
+                'line'
+            )
+        );
+
+        return new Coverage($lineNode, $line);
+    }
+
+    protected function contextNode(): DOMElement
+    {
+        return $this->contextNode;
+    }
+
+    protected function dom(): DOMDocument
+    {
+        return $this->dom;
+    }
+}
diff --git a/vendor/phpunit/php-code-coverage/src/Report/Xml/Method.php b/vendor/phpunit/php-code-coverage/src/Report/Xml/Method.php
new file mode 100644
index 0000000000000000000000000000000000000000..7e30099979c4d82d8c177eab5d0e02e9f6332c16
--- /dev/null
+++ b/vendor/phpunit/php-code-coverage/src/Report/Xml/Method.php
@@ -0,0 +1,61 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of phpunit/php-code-coverage.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\CodeCoverage\Report\Xml;
+
+use DOMElement;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage
+ */
+final class Method
+{
+    /**
+     * @var DOMElement
+     */
+    private $contextNode;
+
+    public function __construct(DOMElement $context, string $name)
+    {
+        $this->contextNode = $context;
+
+        $this->setName($name);
+    }
+
+    public function setSignature(string $signature): void
+    {
+        $this->contextNode->setAttribute('signature', $signature);
+    }
+
+    public function setLines(string $start, ?string $end = null): void
+    {
+        $this->contextNode->setAttribute('start', $start);
+
+        if ($end !== null) {
+            $this->contextNode->setAttribute('end', $end);
+        }
+    }
+
+    public function setTotals(string $executable, string $executed, string $coverage): void
+    {
+        $this->contextNode->setAttribute('executable', $executable);
+        $this->contextNode->setAttribute('executed', $executed);
+        $this->contextNode->setAttribute('coverage', $coverage);
+    }
+
+    public function setCrap(string $crap): void
+    {
+        $this->contextNode->setAttribute('crap', $crap);
+    }
+
+    private function setName(string $name): void
+    {
+        $this->contextNode->setAttribute('name', $name);
+    }
+}
diff --git a/vendor/phpunit/php-code-coverage/src/Report/Xml/Node.php b/vendor/phpunit/php-code-coverage/src/Report/Xml/Node.php
new file mode 100644
index 0000000000000000000000000000000000000000..15992309394ca24c1bfd1a5cacb5c26f03e92d80
--- /dev/null
+++ b/vendor/phpunit/php-code-coverage/src/Report/Xml/Node.php
@@ -0,0 +1,93 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of phpunit/php-code-coverage.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\CodeCoverage\Report\Xml;
+
+use DOMDocument;
+use DOMElement;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage
+ */
+abstract class Node
+{
+    /**
+     * @var DOMDocument
+     */
+    private $dom;
+
+    /**
+     * @var DOMElement
+     */
+    private $contextNode;
+
+    public function __construct(DOMElement $context)
+    {
+        $this->setContextNode($context);
+    }
+
+    public function dom(): DOMDocument
+    {
+        return $this->dom;
+    }
+
+    public function totals(): Totals
+    {
+        $totalsContainer = $this->contextNode()->firstChild;
+
+        if (!$totalsContainer) {
+            $totalsContainer = $this->contextNode()->appendChild(
+                $this->dom->createElementNS(
+                    'https://schema.phpunit.de/coverage/1.0',
+                    'totals'
+                )
+            );
+        }
+
+        return new Totals($totalsContainer);
+    }
+
+    public function addDirectory(string $name): Directory
+    {
+        $dirNode = $this->dom()->createElementNS(
+            'https://schema.phpunit.de/coverage/1.0',
+            'directory'
+        );
+
+        $dirNode->setAttribute('name', $name);
+        $this->contextNode()->appendChild($dirNode);
+
+        return new Directory($dirNode);
+    }
+
+    public function addFile(string $name, string $href): File
+    {
+        $fileNode = $this->dom()->createElementNS(
+            'https://schema.phpunit.de/coverage/1.0',
+            'file'
+        );
+
+        $fileNode->setAttribute('name', $name);
+        $fileNode->setAttribute('href', $href);
+        $this->contextNode()->appendChild($fileNode);
+
+        return new File($fileNode);
+    }
+
+    protected function setContextNode(DOMElement $context): void
+    {
+        $this->dom         = $context->ownerDocument;
+        $this->contextNode = $context;
+    }
+
+    protected function contextNode(): DOMElement
+    {
+        return $this->contextNode;
+    }
+}
diff --git a/vendor/phpunit/php-code-coverage/src/Report/Xml/Project.php b/vendor/phpunit/php-code-coverage/src/Report/Xml/Project.php
new file mode 100644
index 0000000000000000000000000000000000000000..b566bce0645dad448ea91e7c00a254202401fc82
--- /dev/null
+++ b/vendor/phpunit/php-code-coverage/src/Report/Xml/Project.php
@@ -0,0 +1,90 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of phpunit/php-code-coverage.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\CodeCoverage\Report\Xml;
+
+use DOMDocument;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage
+ */
+final class Project extends Node
+{
+    public function __construct(string $directory)
+    {
+        $this->init();
+        $this->setProjectSourceDirectory($directory);
+    }
+
+    public function projectSourceDirectory(): string
+    {
+        return $this->contextNode()->getAttribute('source');
+    }
+
+    public function buildInformation(): BuildInformation
+    {
+        $buildNode = $this->dom()->getElementsByTagNameNS(
+            'https://schema.phpunit.de/coverage/1.0',
+            'build'
+        )->item(0);
+
+        if (!$buildNode) {
+            $buildNode = $this->dom()->documentElement->appendChild(
+                $this->dom()->createElementNS(
+                    'https://schema.phpunit.de/coverage/1.0',
+                    'build'
+                )
+            );
+        }
+
+        return new BuildInformation($buildNode);
+    }
+
+    public function tests(): Tests
+    {
+        $testsNode = $this->contextNode()->getElementsByTagNameNS(
+            'https://schema.phpunit.de/coverage/1.0',
+            'tests'
+        )->item(0);
+
+        if (!$testsNode) {
+            $testsNode = $this->contextNode()->appendChild(
+                $this->dom()->createElementNS(
+                    'https://schema.phpunit.de/coverage/1.0',
+                    'tests'
+                )
+            );
+        }
+
+        return new Tests($testsNode);
+    }
+
+    public function asDom(): DOMDocument
+    {
+        return $this->dom();
+    }
+
+    private function init(): void
+    {
+        $dom = new DOMDocument;
+        $dom->loadXML('<?xml version="1.0" ?><phpunit xmlns="https://schema.phpunit.de/coverage/1.0"><build/><project/></phpunit>');
+
+        $this->setContextNode(
+            $dom->getElementsByTagNameNS(
+                'https://schema.phpunit.de/coverage/1.0',
+                'project'
+            )->item(0)
+        );
+    }
+
+    private function setProjectSourceDirectory(string $name): void
+    {
+        $this->contextNode()->setAttribute('source', $name);
+    }
+}
diff --git a/vendor/phpunit/php-code-coverage/src/Report/Xml/Report.php b/vendor/phpunit/php-code-coverage/src/Report/Xml/Report.php
new file mode 100644
index 0000000000000000000000000000000000000000..b53b08c00eefea5ade7c2ea28188536907a7d573
--- /dev/null
+++ b/vendor/phpunit/php-code-coverage/src/Report/Xml/Report.php
@@ -0,0 +1,99 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of phpunit/php-code-coverage.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\CodeCoverage\Report\Xml;
+
+use function basename;
+use function dirname;
+use DOMDocument;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage
+ */
+final class Report extends File
+{
+    public function __construct(string $name)
+    {
+        $dom = new DOMDocument();
+        $dom->loadXML('<?xml version="1.0" ?><phpunit xmlns="https://schema.phpunit.de/coverage/1.0"><file /></phpunit>');
+
+        $contextNode = $dom->getElementsByTagNameNS(
+            'https://schema.phpunit.de/coverage/1.0',
+            'file'
+        )->item(0);
+
+        parent::__construct($contextNode);
+
+        $this->setName($name);
+    }
+
+    public function asDom(): DOMDocument
+    {
+        return $this->dom();
+    }
+
+    public function functionObject($name): Method
+    {
+        $node = $this->contextNode()->appendChild(
+            $this->dom()->createElementNS(
+                'https://schema.phpunit.de/coverage/1.0',
+                'function'
+            )
+        );
+
+        return new Method($node, $name);
+    }
+
+    public function classObject($name): Unit
+    {
+        return $this->unitObject('class', $name);
+    }
+
+    public function traitObject($name): Unit
+    {
+        return $this->unitObject('trait', $name);
+    }
+
+    public function source(): Source
+    {
+        $source = $this->contextNode()->getElementsByTagNameNS(
+            'https://schema.phpunit.de/coverage/1.0',
+            'source'
+        )->item(0);
+
+        if (!$source) {
+            $source = $this->contextNode()->appendChild(
+                $this->dom()->createElementNS(
+                    'https://schema.phpunit.de/coverage/1.0',
+                    'source'
+                )
+            );
+        }
+
+        return new Source($source);
+    }
+
+    private function setName(string $name): void
+    {
+        $this->contextNode()->setAttribute('name', basename($name));
+        $this->contextNode()->setAttribute('path', dirname($name));
+    }
+
+    private function unitObject(string $tagName, $name): Unit
+    {
+        $node = $this->contextNode()->appendChild(
+            $this->dom()->createElementNS(
+                'https://schema.phpunit.de/coverage/1.0',
+                $tagName
+            )
+        );
+
+        return new Unit($node, $name);
+    }
+}
diff --git a/vendor/phpunit/php-code-coverage/src/Report/Xml/Source.php b/vendor/phpunit/php-code-coverage/src/Report/Xml/Source.php
new file mode 100644
index 0000000000000000000000000000000000000000..8fd20f58f3d026a2ed4856b5dda88ec986006c80
--- /dev/null
+++ b/vendor/phpunit/php-code-coverage/src/Report/Xml/Source.php
@@ -0,0 +1,42 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of phpunit/php-code-coverage.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\CodeCoverage\Report\Xml;
+
+use DOMElement;
+use TheSeer\Tokenizer\NamespaceUri;
+use TheSeer\Tokenizer\Tokenizer;
+use TheSeer\Tokenizer\XMLSerializer;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage
+ */
+final class Source
+{
+    /** @var DOMElement */
+    private $context;
+
+    public function __construct(DOMElement $context)
+    {
+        $this->context = $context;
+    }
+
+    public function setSourceCode(string $source): void
+    {
+        $context = $this->context;
+
+        $tokens = (new Tokenizer())->parse($source);
+        $srcDom = (new XMLSerializer(new NamespaceUri($context->namespaceURI)))->toDom($tokens);
+
+        $context->parentNode->replaceChild(
+            $context->ownerDocument->importNode($srcDom->documentElement, true),
+            $context
+        );
+    }
+}
diff --git a/vendor/phpunit/php-code-coverage/src/Report/Xml/Tests.php b/vendor/phpunit/php-code-coverage/src/Report/Xml/Tests.php
new file mode 100644
index 0000000000000000000000000000000000000000..c2e56268cea278a9e7ee4780c99e26fe58f99de4
--- /dev/null
+++ b/vendor/phpunit/php-code-coverage/src/Report/Xml/Tests.php
@@ -0,0 +1,51 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of phpunit/php-code-coverage.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\CodeCoverage\Report\Xml;
+
+use DOMElement;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage
+ */
+final class Tests
+{
+    private $contextNode;
+
+    private $codeMap = [
+        -1 => 'UNKNOWN',    // PHPUnit_Runner_BaseTestRunner::STATUS_UNKNOWN
+        0  => 'PASSED',     // PHPUnit_Runner_BaseTestRunner::STATUS_PASSED
+        1  => 'SKIPPED',    // PHPUnit_Runner_BaseTestRunner::STATUS_SKIPPED
+        2  => 'INCOMPLETE', // PHPUnit_Runner_BaseTestRunner::STATUS_INCOMPLETE
+        3  => 'FAILURE',    // PHPUnit_Runner_BaseTestRunner::STATUS_FAILURE
+        4  => 'ERROR',      // PHPUnit_Runner_BaseTestRunner::STATUS_ERROR
+        5  => 'RISKY',      // PHPUnit_Runner_BaseTestRunner::STATUS_RISKY
+        6  => 'WARNING',     // PHPUnit_Runner_BaseTestRunner::STATUS_WARNING
+    ];
+
+    public function __construct(DOMElement $context)
+    {
+        $this->contextNode = $context;
+    }
+
+    public function addTest(string $test, array $result): void
+    {
+        $node = $this->contextNode->appendChild(
+            $this->contextNode->ownerDocument->createElementNS(
+                'https://schema.phpunit.de/coverage/1.0',
+                'test'
+            )
+        );
+
+        $node->setAttribute('name', $test);
+        $node->setAttribute('size', $result['size']);
+        $node->setAttribute('result', (string) $result['status']);
+        $node->setAttribute('status', $this->codeMap[(int) $result['status']]);
+    }
+}
diff --git a/vendor/phpunit/php-code-coverage/src/Report/Xml/Totals.php b/vendor/phpunit/php-code-coverage/src/Report/Xml/Totals.php
new file mode 100644
index 0000000000000000000000000000000000000000..17a4cb178b0c14d4b6130d0be3aceaf02903f2ee
--- /dev/null
+++ b/vendor/phpunit/php-code-coverage/src/Report/Xml/Totals.php
@@ -0,0 +1,146 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of phpunit/php-code-coverage.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\CodeCoverage\Report\Xml;
+
+use function sprintf;
+use DOMElement;
+use DOMNode;
+use SebastianBergmann\CodeCoverage\Percentage;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage
+ */
+final class Totals
+{
+    /**
+     * @var DOMNode
+     */
+    private $container;
+
+    /**
+     * @var DOMElement
+     */
+    private $linesNode;
+
+    /**
+     * @var DOMElement
+     */
+    private $methodsNode;
+
+    /**
+     * @var DOMElement
+     */
+    private $functionsNode;
+
+    /**
+     * @var DOMElement
+     */
+    private $classesNode;
+
+    /**
+     * @var DOMElement
+     */
+    private $traitsNode;
+
+    public function __construct(DOMElement $container)
+    {
+        $this->container = $container;
+        $dom             = $container->ownerDocument;
+
+        $this->linesNode = $dom->createElementNS(
+            'https://schema.phpunit.de/coverage/1.0',
+            'lines'
+        );
+
+        $this->methodsNode = $dom->createElementNS(
+            'https://schema.phpunit.de/coverage/1.0',
+            'methods'
+        );
+
+        $this->functionsNode = $dom->createElementNS(
+            'https://schema.phpunit.de/coverage/1.0',
+            'functions'
+        );
+
+        $this->classesNode = $dom->createElementNS(
+            'https://schema.phpunit.de/coverage/1.0',
+            'classes'
+        );
+
+        $this->traitsNode = $dom->createElementNS(
+            'https://schema.phpunit.de/coverage/1.0',
+            'traits'
+        );
+
+        $container->appendChild($this->linesNode);
+        $container->appendChild($this->methodsNode);
+        $container->appendChild($this->functionsNode);
+        $container->appendChild($this->classesNode);
+        $container->appendChild($this->traitsNode);
+    }
+
+    public function container(): DOMNode
+    {
+        return $this->container;
+    }
+
+    public function setNumLines(int $loc, int $cloc, int $ncloc, int $executable, int $executed): void
+    {
+        $this->linesNode->setAttribute('total', (string) $loc);
+        $this->linesNode->setAttribute('comments', (string) $cloc);
+        $this->linesNode->setAttribute('code', (string) $ncloc);
+        $this->linesNode->setAttribute('executable', (string) $executable);
+        $this->linesNode->setAttribute('executed', (string) $executed);
+        $this->linesNode->setAttribute(
+            'percent',
+            $executable === 0 ? '0' : sprintf('%01.2F', Percentage::fromFractionAndTotal($executed, $executable)->asFloat())
+        );
+    }
+
+    public function setNumClasses(int $count, int $tested): void
+    {
+        $this->classesNode->setAttribute('count', (string) $count);
+        $this->classesNode->setAttribute('tested', (string) $tested);
+        $this->classesNode->setAttribute(
+            'percent',
+            $count === 0 ? '0' : sprintf('%01.2F', Percentage::fromFractionAndTotal($tested, $count)->asFloat())
+        );
+    }
+
+    public function setNumTraits(int $count, int $tested): void
+    {
+        $this->traitsNode->setAttribute('count', (string) $count);
+        $this->traitsNode->setAttribute('tested', (string) $tested);
+        $this->traitsNode->setAttribute(
+            'percent',
+            $count === 0 ? '0' : sprintf('%01.2F', Percentage::fromFractionAndTotal($tested, $count)->asFloat())
+        );
+    }
+
+    public function setNumMethods(int $count, int $tested): void
+    {
+        $this->methodsNode->setAttribute('count', (string) $count);
+        $this->methodsNode->setAttribute('tested', (string) $tested);
+        $this->methodsNode->setAttribute(
+            'percent',
+            $count === 0 ? '0' : sprintf('%01.2F', Percentage::fromFractionAndTotal($tested, $count)->asFloat())
+        );
+    }
+
+    public function setNumFunctions(int $count, int $tested): void
+    {
+        $this->functionsNode->setAttribute('count', (string) $count);
+        $this->functionsNode->setAttribute('tested', (string) $tested);
+        $this->functionsNode->setAttribute(
+            'percent',
+            $count === 0 ? '0' : sprintf('%01.2F', Percentage::fromFractionAndTotal($tested, $count)->asFloat())
+        );
+    }
+}
diff --git a/vendor/phpunit/php-code-coverage/src/Report/Xml/Unit.php b/vendor/phpunit/php-code-coverage/src/Report/Xml/Unit.php
new file mode 100644
index 0000000000000000000000000000000000000000..d84dc481fe4db5a8befb9e405c913585804499d9
--- /dev/null
+++ b/vendor/phpunit/php-code-coverage/src/Report/Xml/Unit.php
@@ -0,0 +1,78 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of phpunit/php-code-coverage.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\CodeCoverage\Report\Xml;
+
+use DOMElement;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage
+ */
+final class Unit
+{
+    /**
+     * @var DOMElement
+     */
+    private $contextNode;
+
+    public function __construct(DOMElement $context, string $name)
+    {
+        $this->contextNode = $context;
+
+        $this->setName($name);
+    }
+
+    public function setLines(int $start, int $executable, int $executed): void
+    {
+        $this->contextNode->setAttribute('start', (string) $start);
+        $this->contextNode->setAttribute('executable', (string) $executable);
+        $this->contextNode->setAttribute('executed', (string) $executed);
+    }
+
+    public function setCrap(float $crap): void
+    {
+        $this->contextNode->setAttribute('crap', (string) $crap);
+    }
+
+    public function setNamespace(string $namespace): void
+    {
+        $node = $this->contextNode->getElementsByTagNameNS(
+            'https://schema.phpunit.de/coverage/1.0',
+            'namespace'
+        )->item(0);
+
+        if (!$node) {
+            $node = $this->contextNode->appendChild(
+                $this->contextNode->ownerDocument->createElementNS(
+                    'https://schema.phpunit.de/coverage/1.0',
+                    'namespace'
+                )
+            );
+        }
+
+        $node->setAttribute('name', $namespace);
+    }
+
+    public function addMethod(string $name): Method
+    {
+        $node = $this->contextNode->appendChild(
+            $this->contextNode->ownerDocument->createElementNS(
+                'https://schema.phpunit.de/coverage/1.0',
+                'method'
+            )
+        );
+
+        return new Method($node, $name);
+    }
+
+    private function setName(string $name): void
+    {
+        $this->contextNode->setAttribute('name', $name);
+    }
+}
diff --git a/vendor/phpunit/php-code-coverage/src/StaticAnalysis/Cache.php b/vendor/phpunit/php-code-coverage/src/StaticAnalysis/Cache.php
new file mode 100644
index 0000000000000000000000000000000000000000..081a6530ab8ec6d15a89239c06eaa1dec701c6bf
--- /dev/null
+++ b/vendor/phpunit/php-code-coverage/src/StaticAnalysis/Cache.php
@@ -0,0 +1,90 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of phpunit/php-code-coverage.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\CodeCoverage\StaticAnalysis;
+
+use const DIRECTORY_SEPARATOR;
+use function file_get_contents;
+use function file_put_contents;
+use function filemtime;
+use function hash;
+use function is_file;
+use function serialize;
+use function unserialize;
+use SebastianBergmann\CodeCoverage\Directory;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage
+ */
+abstract class Cache
+{
+    /**
+     * @var string
+     */
+    private $directory;
+
+    public function __construct(string $directory)
+    {
+        Directory::create($directory);
+
+        $this->directory = $directory;
+    }
+
+    protected function has(string $filename, string $key): bool
+    {
+        $cacheFile = $this->cacheFile($filename, $key);
+
+        if (!is_file($cacheFile)) {
+            return false;
+        }
+
+        if (filemtime($cacheFile) < filemtime($filename)) {
+            return false;
+        }
+
+        return true;
+    }
+
+    /**
+     * @psalm-param list<class-string> $allowedClasses
+     *
+     * @return mixed
+     */
+    protected function read(string $filename, string $key, array $allowedClasses = [])
+    {
+        $options = ['allowed_classes' => false];
+
+        if (!empty($allowedClasses)) {
+            $options = ['allowed_classes' => $allowedClasses];
+        }
+
+        return unserialize(
+            file_get_contents(
+                $this->cacheFile($filename, $key)
+            ),
+            $options
+        );
+    }
+
+    /**
+     * @param mixed $data
+     */
+    protected function write(string $filename, string $key, $data): void
+    {
+        file_put_contents(
+            $this->cacheFile($filename, $key),
+            serialize($data)
+        );
+    }
+
+    private function cacheFile(string $filename, string $key): string
+    {
+        return $this->directory . DIRECTORY_SEPARATOR . hash('sha256', $filename . $key);
+    }
+}
diff --git a/vendor/phpunit/php-code-coverage/src/StaticAnalysis/CacheWarmer.php b/vendor/phpunit/php-code-coverage/src/StaticAnalysis/CacheWarmer.php
new file mode 100644
index 0000000000000000000000000000000000000000..93b0dbde8791979990399e712c7b10cb324ca393
--- /dev/null
+++ b/vendor/phpunit/php-code-coverage/src/StaticAnalysis/CacheWarmer.php
@@ -0,0 +1,38 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of phpunit/php-code-coverage.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\CodeCoverage\StaticAnalysis;
+
+use SebastianBergmann\CodeCoverage\Filter;
+
+final class CacheWarmer
+{
+    public function warmCache(string $cacheDirectory, bool $useAnnotationsForIgnoringCode, bool $ignoreDeprecatedCode, Filter $filter): void
+    {
+        $coveredFileAnalyser = new CachingCoveredFileAnalyser(
+            $cacheDirectory,
+            new ParsingCoveredFileAnalyser(
+                $useAnnotationsForIgnoringCode,
+                $ignoreDeprecatedCode
+            )
+        );
+
+        $uncoveredFileAnalyser = new CachingUncoveredFileAnalyser(
+            $cacheDirectory,
+            new ParsingUncoveredFileAnalyser
+        );
+
+        foreach ($filter->files() as $file) {
+            $coveredFileAnalyser->process($file);
+
+            /* @noinspection UnusedFunctionResultInspection */
+            $uncoveredFileAnalyser->executableLinesIn($file);
+        }
+    }
+}
diff --git a/vendor/phpunit/php-code-coverage/src/StaticAnalysis/CachingCoveredFileAnalyser.php b/vendor/phpunit/php-code-coverage/src/StaticAnalysis/CachingCoveredFileAnalyser.php
new file mode 100644
index 0000000000000000000000000000000000000000..3fb95bd51c13726a57dc6b2423aaf9854014a2ff
--- /dev/null
+++ b/vendor/phpunit/php-code-coverage/src/StaticAnalysis/CachingCoveredFileAnalyser.php
@@ -0,0 +1,99 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of phpunit/php-code-coverage.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\CodeCoverage\StaticAnalysis;
+
+use SebastianBergmann\LinesOfCode\LinesOfCode;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage
+ */
+final class CachingCoveredFileAnalyser extends Cache implements CoveredFileAnalyser
+{
+    /**
+     * @var CoveredFileAnalyser
+     */
+    private $coveredFileAnalyser;
+
+    /**
+     * @var array
+     */
+    private $cache = [];
+
+    public function __construct(string $directory, CoveredFileAnalyser $coveredFileAnalyser)
+    {
+        parent::__construct($directory);
+
+        $this->coveredFileAnalyser = $coveredFileAnalyser;
+    }
+
+    public function classesIn(string $filename): array
+    {
+        if (!isset($this->cache[$filename])) {
+            $this->process($filename);
+        }
+
+        return $this->cache[$filename]['classesIn'];
+    }
+
+    public function traitsIn(string $filename): array
+    {
+        if (!isset($this->cache[$filename])) {
+            $this->process($filename);
+        }
+
+        return $this->cache[$filename]['traitsIn'];
+    }
+
+    public function functionsIn(string $filename): array
+    {
+        if (!isset($this->cache[$filename])) {
+            $this->process($filename);
+        }
+
+        return $this->cache[$filename]['functionsIn'];
+    }
+
+    public function linesOfCodeFor(string $filename): LinesOfCode
+    {
+        if (!isset($this->cache[$filename])) {
+            $this->process($filename);
+        }
+
+        return $this->cache[$filename]['linesOfCodeFor'];
+    }
+
+    public function ignoredLinesFor(string $filename): array
+    {
+        if (!isset($this->cache[$filename])) {
+            $this->process($filename);
+        }
+
+        return $this->cache[$filename]['ignoredLinesFor'];
+    }
+
+    public function process(string $filename): void
+    {
+        if ($this->has($filename, __CLASS__)) {
+            $this->cache[$filename] = $this->read($filename, __CLASS__, [LinesOfCode::class]);
+
+            return;
+        }
+
+        $this->cache[$filename] = [
+            'classesIn'       => $this->coveredFileAnalyser->classesIn($filename),
+            'traitsIn'        => $this->coveredFileAnalyser->traitsIn($filename),
+            'functionsIn'     => $this->coveredFileAnalyser->functionsIn($filename),
+            'linesOfCodeFor'  => $this->coveredFileAnalyser->linesOfCodeFor($filename),
+            'ignoredLinesFor' => $this->coveredFileAnalyser->ignoredLinesFor($filename),
+        ];
+
+        $this->write($filename, __CLASS__, $this->cache[$filename]);
+    }
+}
diff --git a/vendor/phpunit/php-code-coverage/src/StaticAnalysis/CachingUncoveredFileAnalyser.php b/vendor/phpunit/php-code-coverage/src/StaticAnalysis/CachingUncoveredFileAnalyser.php
new file mode 100644
index 0000000000000000000000000000000000000000..f52bb3518cb638d95afe05e7d95fb61d763818bc
--- /dev/null
+++ b/vendor/phpunit/php-code-coverage/src/StaticAnalysis/CachingUncoveredFileAnalyser.php
@@ -0,0 +1,41 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of phpunit/php-code-coverage.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\CodeCoverage\StaticAnalysis;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage
+ */
+final class CachingUncoveredFileAnalyser extends Cache implements UncoveredFileAnalyser
+{
+    /**
+     * @var UncoveredFileAnalyser
+     */
+    private $uncoveredFileAnalyser;
+
+    public function __construct(string $directory, UncoveredFileAnalyser $uncoveredFileAnalyser)
+    {
+        parent::__construct($directory);
+
+        $this->uncoveredFileAnalyser = $uncoveredFileAnalyser;
+    }
+
+    public function executableLinesIn(string $filename): array
+    {
+        if ($this->has($filename, __METHOD__)) {
+            return $this->read($filename, __METHOD__);
+        }
+
+        $data = $this->uncoveredFileAnalyser->executableLinesIn($filename);
+
+        $this->write($filename, __METHOD__, $data);
+
+        return $data;
+    }
+}
diff --git a/vendor/phpunit/php-code-coverage/src/StaticAnalysis/CodeUnitFindingVisitor.php b/vendor/phpunit/php-code-coverage/src/StaticAnalysis/CodeUnitFindingVisitor.php
new file mode 100644
index 0000000000000000000000000000000000000000..e79b59e579810d8a7ec3f2a556d89967c0961e44
--- /dev/null
+++ b/vendor/phpunit/php-code-coverage/src/StaticAnalysis/CodeUnitFindingVisitor.php
@@ -0,0 +1,293 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of phpunit/php-code-coverage.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\CodeCoverage\StaticAnalysis;
+
+use function implode;
+use function rtrim;
+use function trim;
+use PhpParser\Node;
+use PhpParser\Node\Identifier;
+use PhpParser\Node\Name;
+use PhpParser\Node\NullableType;
+use PhpParser\Node\Stmt\Class_;
+use PhpParser\Node\Stmt\ClassMethod;
+use PhpParser\Node\Stmt\Function_;
+use PhpParser\Node\Stmt\Interface_;
+use PhpParser\Node\Stmt\Trait_;
+use PhpParser\Node\UnionType;
+use PhpParser\NodeTraverser;
+use PhpParser\NodeVisitorAbstract;
+use SebastianBergmann\Complexity\CyclomaticComplexityCalculatingVisitor;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage
+ */
+final class CodeUnitFindingVisitor extends NodeVisitorAbstract
+{
+    /**
+     * @var array
+     */
+    private $classes = [];
+
+    /**
+     * @var array
+     */
+    private $traits = [];
+
+    /**
+     * @var array
+     */
+    private $functions = [];
+
+    public function enterNode(Node $node)
+    {
+        if ($node instanceof Class_) {
+            if ($node->isAnonymous()) {
+                return;
+            }
+
+            $this->processClass($node);
+        }
+
+        if ($node instanceof Trait_) {
+            $this->processTrait($node);
+        }
+
+        if (!$node instanceof ClassMethod && !$node instanceof Function_) {
+            return null;
+        }
+
+        if ($node instanceof ClassMethod) {
+            $parentNode = $node->getAttribute('parent');
+
+            if ($parentNode instanceof Class_ && $parentNode->isAnonymous()) {
+                return;
+            }
+
+            $this->processMethod($node);
+
+            return;
+        }
+
+        $this->processFunction($node);
+    }
+
+    public function classes(): array
+    {
+        return $this->classes;
+    }
+
+    public function traits(): array
+    {
+        return $this->traits;
+    }
+
+    public function functions(): array
+    {
+        return $this->functions;
+    }
+
+    /**
+     * @psalm-param ClassMethod|Function_ $node
+     */
+    private function cyclomaticComplexity(Node $node): int
+    {
+        assert($node instanceof ClassMethod || $node instanceof Function_);
+
+        $nodes = $node->getStmts();
+
+        if ($nodes === null) {
+            return 0;
+        }
+
+        $traverser = new NodeTraverser;
+
+        $cyclomaticComplexityCalculatingVisitor = new CyclomaticComplexityCalculatingVisitor;
+
+        $traverser->addVisitor($cyclomaticComplexityCalculatingVisitor);
+
+        /* @noinspection UnusedFunctionResultInspection */
+        $traverser->traverse($nodes);
+
+        return $cyclomaticComplexityCalculatingVisitor->cyclomaticComplexity();
+    }
+
+    /**
+     * @psalm-param ClassMethod|Function_ $node
+     */
+    private function signature(Node $node): string
+    {
+        assert($node instanceof ClassMethod || $node instanceof Function_);
+
+        $signature  = ($node->returnsByRef() ? '&' : '') . $node->name->toString() . '(';
+        $parameters = [];
+
+        foreach ($node->getParams() as $parameter) {
+            assert(isset($parameter->var->name));
+
+            $parameterAsString = '';
+
+            if ($parameter->type !== null) {
+                $parameterAsString = $this->type($parameter->type) . ' ';
+            }
+
+            $parameterAsString .= '$' . $parameter->var->name;
+
+            /* @todo Handle default values */
+
+            $parameters[] = $parameterAsString;
+        }
+
+        $signature .= implode(', ', $parameters) . ')';
+
+        $returnType = $node->getReturnType();
+
+        if ($returnType !== null) {
+            $signature .= ': ' . $this->type($returnType);
+        }
+
+        return $signature;
+    }
+
+    /**
+     * @psalm-param Identifier|Name|NullableType|UnionType $type
+     */
+    private function type(Node $type): string
+    {
+        assert($type instanceof Identifier || $type instanceof Name || $type instanceof NullableType || $type instanceof UnionType);
+
+        if ($type instanceof NullableType) {
+            return '?' . $type->type;
+        }
+
+        if ($type instanceof UnionType) {
+            $types = [];
+
+            foreach ($type->types as $_type) {
+                $types[] = $_type->toString();
+            }
+
+            return implode('|', $types);
+        }
+
+        return $type->toString();
+    }
+
+    private function visibility(ClassMethod $node): string
+    {
+        if ($node->isPrivate()) {
+            return 'private';
+        }
+
+        if ($node->isProtected()) {
+            return 'protected';
+        }
+
+        return 'public';
+    }
+
+    private function processClass(Class_ $node): void
+    {
+        $name           = $node->name->toString();
+        $namespacedName = $node->namespacedName->toString();
+
+        $this->classes[$namespacedName] = [
+            'name'           => $name,
+            'namespacedName' => $namespacedName,
+            'namespace'      => $this->namespace($namespacedName, $name),
+            'startLine'      => $node->getStartLine(),
+            'endLine'        => $node->getEndLine(),
+            'methods'        => [],
+        ];
+    }
+
+    private function processTrait(Trait_ $node): void
+    {
+        $name           = $node->name->toString();
+        $namespacedName = $node->namespacedName->toString();
+
+        $this->traits[$namespacedName] = [
+            'name'           => $name,
+            'namespacedName' => $namespacedName,
+            'namespace'      => $this->namespace($namespacedName, $name),
+            'startLine'      => $node->getStartLine(),
+            'endLine'        => $node->getEndLine(),
+            'methods'        => [],
+        ];
+    }
+
+    private function processMethod(ClassMethod $node): void
+    {
+        $parentNode = $node->getAttribute('parent');
+
+        if ($parentNode instanceof Interface_) {
+            return;
+        }
+
+        assert($parentNode instanceof Class_ || $parentNode instanceof Trait_);
+        assert(isset($parentNode->name));
+        assert(isset($parentNode->namespacedName));
+        assert($parentNode->namespacedName instanceof Name);
+
+        $parentName           = $parentNode->name->toString();
+        $parentNamespacedName = $parentNode->namespacedName->toString();
+
+        if ($parentNode instanceof Class_) {
+            $storage = &$this->classes;
+        } else {
+            $storage = &$this->traits;
+        }
+
+        if (!isset($storage[$parentNamespacedName])) {
+            $storage[$parentNamespacedName] = [
+                'name'           => $parentName,
+                'namespacedName' => $parentNamespacedName,
+                'namespace'      => $this->namespace($parentNamespacedName, $parentName),
+                'startLine'      => $parentNode->getStartLine(),
+                'endLine'        => $parentNode->getEndLine(),
+                'methods'        => [],
+            ];
+        }
+
+        $storage[$parentNamespacedName]['methods'][$node->name->toString()] = [
+            'methodName' => $node->name->toString(),
+            'signature'  => $this->signature($node),
+            'visibility' => $this->visibility($node),
+            'startLine'  => $node->getStartLine(),
+            'endLine'    => $node->getEndLine(),
+            'ccn'        => $this->cyclomaticComplexity($node),
+        ];
+    }
+
+    private function processFunction(Function_ $node): void
+    {
+        assert(isset($node->name));
+        assert(isset($node->namespacedName));
+        assert($node->namespacedName instanceof Name);
+
+        $name           = $node->name->toString();
+        $namespacedName = $node->namespacedName->toString();
+
+        $this->functions[$namespacedName] = [
+            'name'           => $name,
+            'namespacedName' => $namespacedName,
+            'namespace'      => $this->namespace($namespacedName, $name),
+            'signature'      => $this->signature($node),
+            'startLine'      => $node->getStartLine(),
+            'endLine'        => $node->getEndLine(),
+            'ccn'            => $this->cyclomaticComplexity($node),
+        ];
+    }
+
+    private function namespace(string $namespacedName, string $name): string
+    {
+        return trim(rtrim($namespacedName, $name), '\\');
+    }
+}
diff --git a/vendor/phpunit/php-code-coverage/src/StaticAnalysis/CoveredFileAnalyser.php b/vendor/phpunit/php-code-coverage/src/StaticAnalysis/CoveredFileAnalyser.php
new file mode 100644
index 0000000000000000000000000000000000000000..d1d5ff482a514ed6bf11647c98aed9ce375df1dc
--- /dev/null
+++ b/vendor/phpunit/php-code-coverage/src/StaticAnalysis/CoveredFileAnalyser.php
@@ -0,0 +1,28 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of phpunit/php-code-coverage.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\CodeCoverage\StaticAnalysis;
+
+use SebastianBergmann\LinesOfCode\LinesOfCode;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage
+ */
+interface CoveredFileAnalyser
+{
+    public function classesIn(string $filename): array;
+
+    public function traitsIn(string $filename): array;
+
+    public function functionsIn(string $filename): array;
+
+    public function linesOfCodeFor(string $filename): LinesOfCode;
+
+    public function ignoredLinesFor(string $filename): array;
+}
diff --git a/vendor/phpunit/php-code-coverage/src/StaticAnalysis/ExecutableLinesFindingVisitor.php b/vendor/phpunit/php-code-coverage/src/StaticAnalysis/ExecutableLinesFindingVisitor.php
new file mode 100644
index 0000000000000000000000000000000000000000..32205692dc36752314b816a54f3eda4f4474f1ad
--- /dev/null
+++ b/vendor/phpunit/php-code-coverage/src/StaticAnalysis/ExecutableLinesFindingVisitor.php
@@ -0,0 +1,91 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of phpunit/php-code-coverage.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\CodeCoverage\StaticAnalysis;
+
+use function array_unique;
+use function sort;
+use PhpParser\Node;
+use PhpParser\Node\Stmt\Break_;
+use PhpParser\Node\Stmt\Case_;
+use PhpParser\Node\Stmt\Catch_;
+use PhpParser\Node\Stmt\Continue_;
+use PhpParser\Node\Stmt\Do_;
+use PhpParser\Node\Stmt\Echo_;
+use PhpParser\Node\Stmt\Else_;
+use PhpParser\Node\Stmt\ElseIf_;
+use PhpParser\Node\Stmt\Expression;
+use PhpParser\Node\Stmt\Finally_;
+use PhpParser\Node\Stmt\For_;
+use PhpParser\Node\Stmt\Foreach_;
+use PhpParser\Node\Stmt\Goto_;
+use PhpParser\Node\Stmt\If_;
+use PhpParser\Node\Stmt\Return_;
+use PhpParser\Node\Stmt\Switch_;
+use PhpParser\Node\Stmt\Throw_;
+use PhpParser\Node\Stmt\TryCatch;
+use PhpParser\Node\Stmt\Unset_;
+use PhpParser\Node\Stmt\While_;
+use PhpParser\NodeVisitorAbstract;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage
+ */
+final class ExecutableLinesFindingVisitor extends NodeVisitorAbstract
+{
+    /**
+     * @psalm-var list<int>
+     */
+    private $executableLines = [];
+
+    public function enterNode(Node $node): void
+    {
+        if (!$this->isExecutable($node)) {
+            return;
+        }
+
+        $this->executableLines[] = $node->getStartLine();
+    }
+
+    /**
+     * @psalm-return list<int>
+     */
+    public function executableLines(): array
+    {
+        $executableLines = array_unique($this->executableLines);
+
+        sort($executableLines);
+
+        return $executableLines;
+    }
+
+    private function isExecutable(Node $node): bool
+    {
+        return $node instanceof Break_ ||
+               $node instanceof Case_ ||
+               $node instanceof Catch_ ||
+               $node instanceof Continue_ ||
+               $node instanceof Do_ ||
+               $node instanceof Echo_ ||
+               $node instanceof ElseIf_ ||
+               $node instanceof Else_ ||
+               $node instanceof Expression ||
+               $node instanceof Finally_ ||
+               $node instanceof Foreach_ ||
+               $node instanceof For_ ||
+               $node instanceof Goto_ ||
+               $node instanceof If_ ||
+               $node instanceof Return_ ||
+               $node instanceof Switch_ ||
+               $node instanceof Throw_ ||
+               $node instanceof TryCatch ||
+               $node instanceof Unset_ ||
+               $node instanceof While_;
+    }
+}
diff --git a/vendor/phpunit/php-code-coverage/src/StaticAnalysis/IgnoredLinesFindingVisitor.php b/vendor/phpunit/php-code-coverage/src/StaticAnalysis/IgnoredLinesFindingVisitor.php
new file mode 100644
index 0000000000000000000000000000000000000000..6800b06130a17968d9f89d01d21d7787bab5643f
--- /dev/null
+++ b/vendor/phpunit/php-code-coverage/src/StaticAnalysis/IgnoredLinesFindingVisitor.php
@@ -0,0 +1,113 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of phpunit/php-code-coverage.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\CodeCoverage\StaticAnalysis;
+
+use function array_merge;
+use function range;
+use function strpos;
+use PhpParser\Node;
+use PhpParser\Node\Stmt\Class_;
+use PhpParser\Node\Stmt\ClassMethod;
+use PhpParser\Node\Stmt\Function_;
+use PhpParser\Node\Stmt\Interface_;
+use PhpParser\Node\Stmt\Trait_;
+use PhpParser\NodeTraverser;
+use PhpParser\NodeVisitorAbstract;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage
+ */
+final class IgnoredLinesFindingVisitor extends NodeVisitorAbstract
+{
+    /**
+     * @psalm-var list<int>
+     */
+    private $ignoredLines = [];
+
+    /**
+     * @var bool
+     */
+    private $useAnnotationsForIgnoringCode;
+
+    /**
+     * @var bool
+     */
+    private $ignoreDeprecated;
+
+    public function __construct(bool $useAnnotationsForIgnoringCode, bool $ignoreDeprecated)
+    {
+        $this->useAnnotationsForIgnoringCode = $useAnnotationsForIgnoringCode;
+        $this->ignoreDeprecated              = $ignoreDeprecated;
+    }
+
+    public function enterNode(Node $node): ?int
+    {
+        if (!$node instanceof Class_ &&
+            !$node instanceof Trait_ &&
+            !$node instanceof Interface_ &&
+            !$node instanceof ClassMethod &&
+            !$node instanceof Function_) {
+            return null;
+        }
+
+        if ($node instanceof Class_ && $node->isAnonymous()) {
+            return null;
+        }
+
+        // Workaround for https://bugs.xdebug.org/view.php?id=1798
+        if ($node instanceof Class_ ||
+            $node instanceof Trait_ ||
+            $node instanceof Interface_) {
+            $this->ignoredLines[] = $node->getStartLine();
+        }
+
+        if (!$this->useAnnotationsForIgnoringCode) {
+            return null;
+        }
+
+        if ($node instanceof Interface_) {
+            return null;
+        }
+
+        $docComment = $node->getDocComment();
+
+        if ($docComment === null) {
+            return null;
+        }
+
+        if (strpos($docComment->getText(), '@codeCoverageIgnore') !== false) {
+            $this->ignoredLines = array_merge(
+                $this->ignoredLines,
+                range($node->getStartLine(), $node->getEndLine())
+            );
+        }
+
+        if ($this->ignoreDeprecated && strpos($docComment->getText(), '@deprecated') !== false) {
+            $this->ignoredLines = array_merge(
+                $this->ignoredLines,
+                range($node->getStartLine(), $node->getEndLine())
+            );
+        }
+
+        if ($node instanceof ClassMethod || $node instanceof Function_) {
+            return NodeTraverser::DONT_TRAVERSE_CHILDREN;
+        }
+
+        return null;
+    }
+
+    /**
+     * @psalm-return list<int>
+     */
+    public function ignoredLines(): array
+    {
+        return $this->ignoredLines;
+    }
+}
diff --git a/vendor/phpunit/php-code-coverage/src/StaticAnalysis/ParsingCoveredFileAnalyser.php b/vendor/phpunit/php-code-coverage/src/StaticAnalysis/ParsingCoveredFileAnalyser.php
new file mode 100644
index 0000000000000000000000000000000000000000..defefb5033e8fbb639f9306bf8d7c54a8fb18c0e
--- /dev/null
+++ b/vendor/phpunit/php-code-coverage/src/StaticAnalysis/ParsingCoveredFileAnalyser.php
@@ -0,0 +1,226 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of phpunit/php-code-coverage.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\CodeCoverage\StaticAnalysis;
+
+use function array_unique;
+use function assert;
+use function file_get_contents;
+use function is_array;
+use function sprintf;
+use function substr_count;
+use function token_get_all;
+use function trim;
+use PhpParser\Error;
+use PhpParser\Lexer;
+use PhpParser\NodeTraverser;
+use PhpParser\NodeVisitor\NameResolver;
+use PhpParser\NodeVisitor\ParentConnectingVisitor;
+use PhpParser\ParserFactory;
+use SebastianBergmann\CodeCoverage\ParserException;
+use SebastianBergmann\LinesOfCode\LineCountingVisitor;
+use SebastianBergmann\LinesOfCode\LinesOfCode;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage
+ */
+final class ParsingCoveredFileAnalyser implements CoveredFileAnalyser
+{
+    /**
+     * @var array
+     */
+    private $classes = [];
+
+    /**
+     * @var array
+     */
+    private $traits = [];
+
+    /**
+     * @var array
+     */
+    private $functions = [];
+
+    /**
+     * @var LinesOfCode[]
+     */
+    private $linesOfCode = [];
+
+    /**
+     * @var array
+     */
+    private $ignoredLines = [];
+
+    /**
+     * @var bool
+     */
+    private $useAnnotationsForIgnoringCode;
+
+    /**
+     * @var bool
+     */
+    private $ignoreDeprecatedCode;
+
+    public function __construct(bool $useAnnotationsForIgnoringCode, bool $ignoreDeprecatedCode)
+    {
+        $this->useAnnotationsForIgnoringCode = $useAnnotationsForIgnoringCode;
+        $this->ignoreDeprecatedCode          = $ignoreDeprecatedCode;
+    }
+
+    public function classesIn(string $filename): array
+    {
+        $this->analyse($filename);
+
+        return $this->classes[$filename];
+    }
+
+    public function traitsIn(string $filename): array
+    {
+        $this->analyse($filename);
+
+        return $this->traits[$filename];
+    }
+
+    public function functionsIn(string $filename): array
+    {
+        $this->analyse($filename);
+
+        return $this->functions[$filename];
+    }
+
+    public function linesOfCodeFor(string $filename): LinesOfCode
+    {
+        $this->analyse($filename);
+
+        return $this->linesOfCode[$filename];
+    }
+
+    public function ignoredLinesFor(string $filename): array
+    {
+        $this->analyse($filename);
+
+        return $this->ignoredLines[$filename];
+    }
+
+    /**
+     * @throws ParserException
+     */
+    private function analyse(string $filename): void
+    {
+        if (isset($this->classes[$filename])) {
+            return;
+        }
+
+        $source      = file_get_contents($filename);
+        $linesOfCode = substr_count($source, "\n");
+
+        if ($linesOfCode === 0 && !empty($source)) {
+            $linesOfCode = 1;
+        }
+
+        $parser = (new ParserFactory)->create(
+            ParserFactory::PREFER_PHP7,
+            new Lexer
+        );
+
+        try {
+            $nodes = $parser->parse($source);
+
+            assert($nodes !== null);
+
+            $traverser                  = new NodeTraverser;
+            $codeUnitFindingVisitor     = new CodeUnitFindingVisitor;
+            $lineCountingVisitor        = new LineCountingVisitor($linesOfCode);
+            $ignoredLinesFindingVisitor = new IgnoredLinesFindingVisitor($this->useAnnotationsForIgnoringCode, $this->ignoreDeprecatedCode);
+
+            $traverser->addVisitor(new NameResolver);
+            $traverser->addVisitor(new ParentConnectingVisitor);
+            $traverser->addVisitor($codeUnitFindingVisitor);
+            $traverser->addVisitor($lineCountingVisitor);
+            $traverser->addVisitor($ignoredLinesFindingVisitor);
+
+            /* @noinspection UnusedFunctionResultInspection */
+            $traverser->traverse($nodes);
+            // @codeCoverageIgnoreStart
+        } catch (Error $error) {
+            throw new ParserException(
+                sprintf(
+                    'Cannot parse %s: %s',
+                    $filename,
+                    $error->getMessage()
+                ),
+                (int) $error->getCode(),
+                $error
+            );
+        }
+        // @codeCoverageIgnoreEnd
+
+        $this->classes[$filename]      = $codeUnitFindingVisitor->classes();
+        $this->traits[$filename]       = $codeUnitFindingVisitor->traits();
+        $this->functions[$filename]    = $codeUnitFindingVisitor->functions();
+        $this->linesOfCode[$filename]  = $lineCountingVisitor->result();
+        $this->ignoredLines[$filename] = [];
+
+        $this->findLinesIgnoredByLineBasedAnnotations($filename, $source, $this->useAnnotationsForIgnoringCode);
+
+        $this->ignoredLines[$filename] = array_unique(
+            array_merge(
+                $this->ignoredLines[$filename],
+                $ignoredLinesFindingVisitor->ignoredLines()
+            )
+        );
+
+        sort($this->ignoredLines[$filename]);
+    }
+
+    private function findLinesIgnoredByLineBasedAnnotations(string $filename, string $source, bool $useAnnotationsForIgnoringCode): void
+    {
+        $ignore = false;
+        $stop   = false;
+
+        foreach (token_get_all($source) as $token) {
+            if (!is_array($token)) {
+                continue;
+            }
+
+            switch ($token[0]) {
+                case T_COMMENT:
+                case T_DOC_COMMENT:
+                    if (!$useAnnotationsForIgnoringCode) {
+                        break;
+                    }
+
+                    $comment = trim($token[1]);
+
+                    if ($comment === '// @codeCoverageIgnore' ||
+                        $comment === '//@codeCoverageIgnore') {
+                        $ignore = true;
+                        $stop   = true;
+                    } elseif ($comment === '// @codeCoverageIgnoreStart' ||
+                        $comment === '//@codeCoverageIgnoreStart') {
+                        $ignore = true;
+                    } elseif ($comment === '// @codeCoverageIgnoreEnd' ||
+                        $comment === '//@codeCoverageIgnoreEnd') {
+                        $stop = true;
+                    }
+
+                    break;
+            }
+
+            if ($ignore) {
+                $this->ignoredLines[$filename][] = $token[2];
+
+                if ($stop) {
+                    $ignore = false;
+                    $stop   = false;
+                }
+            }
+        }
+    }
+}
diff --git a/vendor/phpunit/php-code-coverage/src/StaticAnalysis/ParsingUncoveredFileAnalyser.php b/vendor/phpunit/php-code-coverage/src/StaticAnalysis/ParsingUncoveredFileAnalyser.php
new file mode 100644
index 0000000000000000000000000000000000000000..0ee7055d6335913986f80ed734aacc86c0cd38a7
--- /dev/null
+++ b/vendor/phpunit/php-code-coverage/src/StaticAnalysis/ParsingUncoveredFileAnalyser.php
@@ -0,0 +1,51 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of phpunit/php-code-coverage.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\CodeCoverage\StaticAnalysis;
+
+use PhpParser\Error;
+use PhpParser\Lexer;
+use PhpParser\NodeTraverser;
+use PhpParser\ParserFactory;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage
+ */
+final class ParsingUncoveredFileAnalyser implements UncoveredFileAnalyser
+{
+    public function executableLinesIn(string $filename): array
+    {
+        $parser = (new ParserFactory)->create(
+            ParserFactory::PREFER_PHP7,
+            new Lexer
+        );
+
+        try {
+            $nodes = $parser->parse(file_get_contents($filename));
+
+            assert($nodes !== null);
+
+            $traverser = new NodeTraverser;
+            $visitor   = new ExecutableLinesFindingVisitor;
+
+            $traverser->addVisitor($visitor);
+
+            /* @noinspection UnusedFunctionResultInspection */
+            $traverser->traverse($nodes);
+
+            return $visitor->executableLines();
+
+            // @codeCoverageIgnoreStart
+        } catch (Error $error) {
+        }
+        // @codeCoverageIgnoreEnd
+
+        return [];
+    }
+}
diff --git a/vendor/phpunit/php-code-coverage/src/StaticAnalysis/UncoveredFileAnalyser.php b/vendor/phpunit/php-code-coverage/src/StaticAnalysis/UncoveredFileAnalyser.php
new file mode 100644
index 0000000000000000000000000000000000000000..e89f2a954d624362cc2779dd3ba3a655f2c0a277
--- /dev/null
+++ b/vendor/phpunit/php-code-coverage/src/StaticAnalysis/UncoveredFileAnalyser.php
@@ -0,0 +1,18 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of phpunit/php-code-coverage.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\CodeCoverage\StaticAnalysis;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage
+ */
+interface UncoveredFileAnalyser
+{
+    public function executableLinesIn(string $filename): array;
+}
diff --git a/vendor/phpunit/php-code-coverage/src/Version.php b/vendor/phpunit/php-code-coverage/src/Version.php
new file mode 100644
index 0000000000000000000000000000000000000000..81c8cf204dab1b28ecf11a2cdbcc20e57bbec15b
--- /dev/null
+++ b/vendor/phpunit/php-code-coverage/src/Version.php
@@ -0,0 +1,30 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of phpunit/php-code-coverage.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\CodeCoverage;
+
+use function dirname;
+use SebastianBergmann\Version as VersionId;
+
+final class Version
+{
+    /**
+     * @var string
+     */
+    private static $version;
+
+    public static function id(): string
+    {
+        if (self::$version === null) {
+            self::$version = (new VersionId('9.2.5', dirname(__DIR__)))->getVersion();
+        }
+
+        return self::$version;
+    }
+}
diff --git a/vendor/phpunit/php-file-iterator/ChangeLog.md b/vendor/phpunit/php-file-iterator/ChangeLog.md
new file mode 100644
index 0000000000000000000000000000000000000000..40d3c7c7b4e4ddf61ea90dfea507db4d0cad4f1d
--- /dev/null
+++ b/vendor/phpunit/php-file-iterator/ChangeLog.md
@@ -0,0 +1,112 @@
+# Change Log
+
+All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/).
+
+## [3.0.5] - 2020-09-28
+
+### Changed
+
+* Changed PHP version constraint in `composer.json` from `^7.3 || ^8.0` to `>=7.3`
+
+## [3.0.4] - 2020-07-11
+
+### Fixed
+
+* [#67](https://github.com/sebastianbergmann/php-file-iterator/issues/67): `TypeError` in `SebastianBergmann\FileIterator\Iterator::accept()`
+
+## [3.0.3] - 2020-06-26
+
+### Added
+
+* This component is now supported on PHP 8
+
+## [3.0.2] - 2020-06-15
+
+### Changed
+
+* Tests etc. are now ignored for archive exports
+
+## [3.0.1] - 2020-04-18
+
+### Fixed
+
+* [#64](https://github.com/sebastianbergmann/php-file-iterator/issues/64): Release tarball contains Composer PHAR
+
+## [3.0.0] - 2020-02-07
+
+### Removed
+
+* This component is no longer supported on PHP 7.1 and PHP 7.2
+
+## [2.0.2] - 2018-09-13
+
+### Fixed
+
+* [#48](https://github.com/sebastianbergmann/php-file-iterator/issues/48): Excluding an array that contains false ends up excluding the current working directory
+
+## [2.0.1] - 2018-06-11
+
+### Fixed
+
+* [#46](https://github.com/sebastianbergmann/php-file-iterator/issues/46): Regression with hidden parent directory
+
+## [2.0.0] - 2018-05-28
+
+### Fixed
+
+* [#30](https://github.com/sebastianbergmann/php-file-iterator/issues/30): Exclude is not considered if it is a parent of the base path
+
+### Changed
+
+* This component now uses namespaces
+
+### Removed
+
+* This component is no longer supported on PHP 5.3, PHP 5.4, PHP 5.5, PHP 5.6, and PHP 7.0
+
+## [1.4.5] - 2017-11-27
+
+### Fixed
+
+* [#37](https://github.com/sebastianbergmann/php-file-iterator/issues/37): Regression caused by fix for [#30](https://github.com/sebastianbergmann/php-file-iterator/issues/30)
+
+## [1.4.4] - 2017-11-27
+
+### Fixed
+
+* [#30](https://github.com/sebastianbergmann/php-file-iterator/issues/30): Exclude is not considered if it is a parent of the base path
+
+## [1.4.3] - 2017-11-25
+
+### Fixed
+
+* [#34](https://github.com/sebastianbergmann/php-file-iterator/issues/34): Factory should use canonical directory names
+
+## [1.4.2] - 2016-11-26
+
+No changes
+
+## [1.4.1] - 2015-07-26
+
+No changes
+
+## 1.4.0 - 2015-04-02
+
+### Added
+
+* [#23](https://github.com/sebastianbergmann/php-file-iterator/pull/23): Added support for wildcards (glob) in exclude
+
+[3.0.5]: https://github.com/sebastianbergmann/php-file-iterator/compare/3.0.4...3.0.5
+[3.0.4]: https://github.com/sebastianbergmann/php-file-iterator/compare/3.0.3...3.0.4
+[3.0.3]: https://github.com/sebastianbergmann/php-file-iterator/compare/3.0.2...3.0.3
+[3.0.2]: https://github.com/sebastianbergmann/php-file-iterator/compare/3.0.1...3.0.2
+[3.0.1]: https://github.com/sebastianbergmann/php-file-iterator/compare/3.0.0...3.0.1
+[3.0.0]: https://github.com/sebastianbergmann/php-file-iterator/compare/2.0.2...3.0.0
+[2.0.2]: https://github.com/sebastianbergmann/php-file-iterator/compare/2.0.1...2.0.2
+[2.0.1]: https://github.com/sebastianbergmann/php-file-iterator/compare/2.0.0...2.0.1
+[2.0.0]: https://github.com/sebastianbergmann/php-file-iterator/compare/1.4...2.0.0
+[1.4.5]: https://github.com/sebastianbergmann/php-file-iterator/compare/1.4.4...1.4.5
+[1.4.4]: https://github.com/sebastianbergmann/php-file-iterator/compare/1.4.3...1.4.4
+[1.4.3]: https://github.com/sebastianbergmann/php-file-iterator/compare/1.4.2...1.4.3
+[1.4.2]: https://github.com/sebastianbergmann/php-file-iterator/compare/1.4.1...1.4.2
+[1.4.1]: https://github.com/sebastianbergmann/php-file-iterator/compare/1.4.0...1.4.1
diff --git a/vendor/phpunit/php-file-iterator/LICENSE b/vendor/phpunit/php-file-iterator/LICENSE
new file mode 100644
index 0000000000000000000000000000000000000000..a915a5449e7f15027e18066c7ea376046fcf05a8
--- /dev/null
+++ b/vendor/phpunit/php-file-iterator/LICENSE
@@ -0,0 +1,33 @@
+php-file-iterator
+
+Copyright (c) 2009-2020, Sebastian Bergmann <sebastian@phpunit.de>.
+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 Sebastian Bergmann nor the names of his
+   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/phpunit/php-file-iterator/README.md b/vendor/phpunit/php-file-iterator/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..3cbfdaae7e83a21a57659c8e448fc46195e51d8a
--- /dev/null
+++ b/vendor/phpunit/php-file-iterator/README.md
@@ -0,0 +1,14 @@
+[![Build Status](https://travis-ci.org/sebastianbergmann/php-file-iterator.svg?branch=master)](https://travis-ci.org/sebastianbergmann/php-file-iterator)
+
+# php-file-iterator
+
+## Installation
+
+You can add this library as a local, per-project dependency to your project using [Composer](https://getcomposer.org/):
+
+    composer require phpunit/php-file-iterator
+
+If you only need this library during development, for instance to run your project's test suite, then you should add it as a development-time dependency:
+
+    composer require --dev phpunit/php-file-iterator
+
diff --git a/vendor/phpunit/php-file-iterator/composer.json b/vendor/phpunit/php-file-iterator/composer.json
new file mode 100644
index 0000000000000000000000000000000000000000..f1b95b3f8922e6774c944d05381c5957d7a41443
--- /dev/null
+++ b/vendor/phpunit/php-file-iterator/composer.json
@@ -0,0 +1,45 @@
+{
+    "name": "phpunit/php-file-iterator",
+    "description": "FilterIterator implementation that filters files based on a list of suffixes.",
+    "type": "library",
+    "keywords": [
+        "iterator",
+        "filesystem"
+    ],
+    "homepage": "https://github.com/sebastianbergmann/php-file-iterator/",
+    "license": "BSD-3-Clause",
+    "authors": [
+        {
+            "name": "Sebastian Bergmann",
+            "email": "sebastian@phpunit.de",
+            "role": "lead"
+        }
+    ],
+    "support": {
+        "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues"
+    },
+    "config": {
+        "platform": {
+            "php": "7.3.0"
+        },
+        "optimize-autoloader": true,
+        "sort-packages": true
+    },
+    "prefer-stable": true,
+    "require": {
+        "php": ">=7.3"
+    },
+    "require-dev": {
+        "phpunit/phpunit": "^9.3"
+    },
+    "autoload": {
+        "classmap": [
+            "src/"
+        ]
+    },
+    "extra": {
+        "branch-alias": {
+            "dev-master": "3.0-dev"
+        }
+    }
+}
diff --git a/vendor/phpunit/php-file-iterator/src/Facade.php b/vendor/phpunit/php-file-iterator/src/Facade.php
new file mode 100644
index 0000000000000000000000000000000000000000..87b6588dd28b9bcbf4e4a117291cdddb95ea2168
--- /dev/null
+++ b/vendor/phpunit/php-file-iterator/src/Facade.php
@@ -0,0 +1,115 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of phpunit/php-file-iterator.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\FileIterator;
+
+use const DIRECTORY_SEPARATOR;
+use function array_unique;
+use function count;
+use function dirname;
+use function explode;
+use function is_file;
+use function is_string;
+use function realpath;
+use function sort;
+
+class Facade
+{
+    /**
+     * @param array|string $paths
+     * @param array|string $suffixes
+     * @param array|string $prefixes
+     */
+    public function getFilesAsArray($paths, $suffixes = '', $prefixes = '', array $exclude = [], bool $commonPath = false): array
+    {
+        if (is_string($paths)) {
+            $paths = [$paths];
+        }
+
+        $iterator = (new Factory)->getFileIterator($paths, $suffixes, $prefixes, $exclude);
+
+        $files = [];
+
+        foreach ($iterator as $file) {
+            $file = $file->getRealPath();
+
+            if ($file) {
+                $files[] = $file;
+            }
+        }
+
+        foreach ($paths as $path) {
+            if (is_file($path)) {
+                $files[] = realpath($path);
+            }
+        }
+
+        $files = array_unique($files);
+        sort($files);
+
+        if ($commonPath) {
+            return [
+                'commonPath' => $this->getCommonPath($files),
+                'files'      => $files,
+            ];
+        }
+
+        return $files;
+    }
+
+    protected function getCommonPath(array $files): string
+    {
+        $count = count($files);
+
+        if ($count === 0) {
+            return '';
+        }
+
+        if ($count === 1) {
+            return dirname($files[0]) . DIRECTORY_SEPARATOR;
+        }
+
+        $_files = [];
+
+        foreach ($files as $file) {
+            $_files[] = $_fileParts = explode(DIRECTORY_SEPARATOR, $file);
+
+            if (empty($_fileParts[0])) {
+                $_fileParts[0] = DIRECTORY_SEPARATOR;
+            }
+        }
+
+        $common = '';
+        $done   = false;
+        $j      = 0;
+        $count--;
+
+        while (!$done) {
+            for ($i = 0; $i < $count; $i++) {
+                if ($_files[$i][$j] != $_files[$i + 1][$j]) {
+                    $done = true;
+
+                    break;
+                }
+            }
+
+            if (!$done) {
+                $common .= $_files[0][$j];
+
+                if ($j > 0) {
+                    $common .= DIRECTORY_SEPARATOR;
+                }
+            }
+
+            $j++;
+        }
+
+        return DIRECTORY_SEPARATOR . $common;
+    }
+}
diff --git a/vendor/phpunit/php-file-iterator/src/Factory.php b/vendor/phpunit/php-file-iterator/src/Factory.php
new file mode 100644
index 0000000000000000000000000000000000000000..2620e3ec34e06fcb12cca7af72f70f80da2e79af
--- /dev/null
+++ b/vendor/phpunit/php-file-iterator/src/Factory.php
@@ -0,0 +1,91 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of phpunit/php-file-iterator.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\FileIterator;
+
+use const GLOB_ONLYDIR;
+use function array_filter;
+use function array_map;
+use function array_merge;
+use function glob;
+use function is_dir;
+use function is_string;
+use function realpath;
+use AppendIterator;
+use RecursiveDirectoryIterator;
+use RecursiveIteratorIterator;
+
+class Factory
+{
+    /**
+     * @param array|string $paths
+     * @param array|string $suffixes
+     * @param array|string $prefixes
+     */
+    public function getFileIterator($paths, $suffixes = '', $prefixes = '', array $exclude = []): AppendIterator
+    {
+        if (is_string($paths)) {
+            $paths = [$paths];
+        }
+
+        $paths   = $this->getPathsAfterResolvingWildcards($paths);
+        $exclude = $this->getPathsAfterResolvingWildcards($exclude);
+
+        if (is_string($prefixes)) {
+            if ($prefixes !== '') {
+                $prefixes = [$prefixes];
+            } else {
+                $prefixes = [];
+            }
+        }
+
+        if (is_string($suffixes)) {
+            if ($suffixes !== '') {
+                $suffixes = [$suffixes];
+            } else {
+                $suffixes = [];
+            }
+        }
+
+        $iterator = new AppendIterator;
+
+        foreach ($paths as $path) {
+            if (is_dir($path)) {
+                $iterator->append(
+                    new Iterator(
+                        $path,
+                        new RecursiveIteratorIterator(
+                            new RecursiveDirectoryIterator($path, RecursiveDirectoryIterator::FOLLOW_SYMLINKS | RecursiveDirectoryIterator::SKIP_DOTS)
+                        ),
+                        $suffixes,
+                        $prefixes,
+                        $exclude
+                    )
+                );
+            }
+        }
+
+        return $iterator;
+    }
+
+    protected function getPathsAfterResolvingWildcards(array $paths): array
+    {
+        $_paths = [];
+
+        foreach ($paths as $path) {
+            if ($locals = glob($path, GLOB_ONLYDIR)) {
+                $_paths = array_merge($_paths, array_map('\realpath', $locals));
+            } else {
+                $_paths[] = realpath($path);
+            }
+        }
+
+        return array_filter($_paths);
+    }
+}
diff --git a/vendor/phpunit/php-file-iterator/src/Iterator.php b/vendor/phpunit/php-file-iterator/src/Iterator.php
new file mode 100644
index 0000000000000000000000000000000000000000..7eb82ad68ebc9bbd054215036428bf4ad83003c0
--- /dev/null
+++ b/vendor/phpunit/php-file-iterator/src/Iterator.php
@@ -0,0 +1,119 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of phpunit/php-file-iterator.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\FileIterator;
+
+use function array_filter;
+use function array_map;
+use function preg_match;
+use function realpath;
+use function str_replace;
+use function strlen;
+use function strpos;
+use function substr;
+use FilterIterator;
+
+class Iterator extends FilterIterator
+{
+    public const PREFIX = 0;
+
+    public const SUFFIX = 1;
+
+    /**
+     * @var string
+     */
+    private $basePath;
+
+    /**
+     * @var array
+     */
+    private $suffixes = [];
+
+    /**
+     * @var array
+     */
+    private $prefixes = [];
+
+    /**
+     * @var array
+     */
+    private $exclude = [];
+
+    public function __construct(string $basePath, \Iterator $iterator, array $suffixes = [], array $prefixes = [], array $exclude = [])
+    {
+        $this->basePath = realpath($basePath);
+        $this->prefixes = $prefixes;
+        $this->suffixes = $suffixes;
+        $this->exclude  = array_filter(array_map('realpath', $exclude));
+
+        parent::__construct($iterator);
+    }
+
+    public function accept(): bool
+    {
+        $current  = $this->getInnerIterator()->current();
+        $filename = $current->getFilename();
+        $realPath = $current->getRealPath();
+
+        if ($realPath === false) {
+            return false;
+        }
+
+        return $this->acceptPath($realPath) &&
+               $this->acceptPrefix($filename) &&
+               $this->acceptSuffix($filename);
+    }
+
+    private function acceptPath(string $path): bool
+    {
+        // Filter files in hidden directories by checking path that is relative to the base path.
+        if (preg_match('=/\.[^/]*/=', str_replace($this->basePath, '', $path))) {
+            return false;
+        }
+
+        foreach ($this->exclude as $exclude) {
+            if (strpos($path, $exclude) === 0) {
+                return false;
+            }
+        }
+
+        return true;
+    }
+
+    private function acceptPrefix(string $filename): bool
+    {
+        return $this->acceptSubString($filename, $this->prefixes, self::PREFIX);
+    }
+
+    private function acceptSuffix(string $filename): bool
+    {
+        return $this->acceptSubString($filename, $this->suffixes, self::SUFFIX);
+    }
+
+    private function acceptSubString(string $filename, array $subStrings, int $type): bool
+    {
+        if (empty($subStrings)) {
+            return true;
+        }
+
+        $matched = false;
+
+        foreach ($subStrings as $string) {
+            if (($type === self::PREFIX && strpos($filename, $string) === 0) ||
+                ($type === self::SUFFIX &&
+                 substr($filename, -1 * strlen($string)) === $string)) {
+                $matched = true;
+
+                break;
+            }
+        }
+
+        return $matched;
+    }
+}
diff --git a/vendor/phpunit/php-invoker/ChangeLog.md b/vendor/phpunit/php-invoker/ChangeLog.md
new file mode 100644
index 0000000000000000000000000000000000000000..15cff1f112d1100c4f0c750e1108acde75f95c91
--- /dev/null
+++ b/vendor/phpunit/php-invoker/ChangeLog.md
@@ -0,0 +1,48 @@
+# ChangeLog
+
+All notable changes are documented in this file using the [Keep a CHANGELOG](https://keepachangelog.com/) principles.
+
+## [3.1.1] - 2020-09-28
+
+### Changed
+
+* Changed PHP version constraint in `composer.json` from `^7.3 || ^8.0` to `>=7.3`
+
+## [3.1.0] - 2020-08-06
+
+### Changed
+
+* [#14](https://github.com/sebastianbergmann/php-invoker/pull/14): Clear alarm in `finally` block
+
+## [3.0.2] - 2020-06-26
+
+### Added
+
+* This component is now supported on PHP 8
+
+## [3.0.1] - 2020-06-15
+
+### Changed
+
+* Tests etc. are now ignored for archive exports
+
+## [3.0.0] - 2020-02-07
+
+### Added
+
+* Added `canInvokeWithTimeout()` method to check requirements for the functionality provided by this component to work
+
+### Changed
+
+* Moved `"ext-pcntl": "*"` requirement from `require` to `suggest` so that this component can be installed even if `ext/pcntl` is not available
+* `invoke()` now raises an exception when the requirements for the functionality provided by this component to work are not met
+
+### Removed
+
+* This component is no longer supported on PHP 7.1 and PHP 7.2
+
+[3.1.1]: https://github.com/sebastianbergmann/php-invoker/compare/3.1.0...3.1.1
+[3.1.0]: https://github.com/sebastianbergmann/php-invoker/compare/3.0.2...3.1.0
+[3.0.2]: https://github.com/sebastianbergmann/php-invoker/compare/3.0.1...3.0.2
+[3.0.1]: https://github.com/sebastianbergmann/php-invoker/compare/3.0.0...3.0.1
+[3.0.0]: https://github.com/sebastianbergmann/php-invoker/compare/2.0.0...3.0.0
diff --git a/vendor/phpunit/php-invoker/LICENSE b/vendor/phpunit/php-invoker/LICENSE
new file mode 100644
index 0000000000000000000000000000000000000000..4620776e17dca07d34335c7193284304666c975d
--- /dev/null
+++ b/vendor/phpunit/php-invoker/LICENSE
@@ -0,0 +1,33 @@
+php-invoker
+
+Copyright (c) 2011-2020, Sebastian Bergmann <sebastian@phpunit.de>.
+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 Sebastian Bergmann nor the names of his
+   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/phpunit/php-invoker/README.md b/vendor/phpunit/php-invoker/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..ace07e5fde873dd9b4de641cccdb4744b14386df
--- /dev/null
+++ b/vendor/phpunit/php-invoker/README.md
@@ -0,0 +1,18 @@
+# phpunit/php-invoker
+
+[![CI Status](https://github.com/sebastianbergmann/php-invoker/workflows/CI/badge.svg)](https://github.com/sebastianbergmann/php-invoker/actions)
+[![Type Coverage](https://shepherd.dev/github/sebastianbergmann/php-invoker/coverage.svg)](https://shepherd.dev/github/sebastianbergmann/php-invoker)
+
+## Installation
+
+You can add this library as a local, per-project dependency to your project using [Composer](https://getcomposer.org/):
+
+```
+composer require phpunit/php-invoker
+```
+
+If you only need this library during development, for instance to run your project's test suite, then you should add it as a development-time dependency:
+
+```
+composer require --dev phpunit/php-invoker
+```
diff --git a/vendor/phpunit/php-invoker/composer.json b/vendor/phpunit/php-invoker/composer.json
new file mode 100644
index 0000000000000000000000000000000000000000..6c007cd81a33d6d50953e35be94d8d38678209d1
--- /dev/null
+++ b/vendor/phpunit/php-invoker/composer.json
@@ -0,0 +1,54 @@
+{
+    "name": "phpunit/php-invoker",
+    "description": "Invoke callables with a timeout",
+    "type": "library",
+    "keywords": [
+        "process"
+    ],
+    "homepage": "https://github.com/sebastianbergmann/php-invoker/",
+    "license": "BSD-3-Clause",
+    "authors": [
+        {
+            "name": "Sebastian Bergmann",
+            "email": "sebastian@phpunit.de",
+            "role": "lead"
+        }
+    ],
+    "support": {
+        "issues": "https://github.com/sebastianbergmann/php-invoker/issues"
+    },
+    "prefer-stable": true,
+    "config": {
+        "platform": {
+            "php": "7.3.0"
+        },
+        "optimize-autoloader": true,
+        "sort-packages": true
+    },
+    "require": {
+        "php": ">=7.3"
+    },
+    "require-dev": {
+        "ext-pcntl": "*",
+        "phpunit/phpunit": "^9.3"
+    },
+    "autoload": {
+        "classmap": [
+            "src/"
+        ]
+    },
+    "autoload-dev": {
+        "classmap": [
+            "tests/_fixture/"
+        ]
+    },
+    "suggest": {
+        "ext-pcntl": "*"
+    },
+    "extra": {
+        "branch-alias": {
+            "dev-master": "3.1-dev"
+        }
+    }
+}
+
diff --git a/vendor/phpunit/php-invoker/src/Invoker.php b/vendor/phpunit/php-invoker/src/Invoker.php
new file mode 100644
index 0000000000000000000000000000000000000000..656f4180a601adabe8b48baf14c0fecbe97d73ec
--- /dev/null
+++ b/vendor/phpunit/php-invoker/src/Invoker.php
@@ -0,0 +1,69 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of phpunit/php-invoker.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\Invoker;
+
+use const SIGALRM;
+use function call_user_func_array;
+use function function_exists;
+use function pcntl_alarm;
+use function pcntl_async_signals;
+use function pcntl_signal;
+use function sprintf;
+use Throwable;
+
+final class Invoker
+{
+    /**
+     * @var int
+     */
+    private $timeout;
+
+    /**
+     * @throws Throwable
+     */
+    public function invoke(callable $callable, array $arguments, int $timeout)
+    {
+        if (!$this->canInvokeWithTimeout()) {
+            throw new ProcessControlExtensionNotLoadedException(
+                'The pcntl (process control) extension for PHP is required'
+            );
+        }
+
+        pcntl_signal(
+            SIGALRM,
+            function (): void {
+                throw new TimeoutException(
+                    sprintf(
+                        'Execution aborted after %d second%s',
+                        $this->timeout,
+                        $this->timeout === 1 ? '' : 's'
+                    )
+                );
+            },
+            true
+        );
+
+        $this->timeout = $timeout;
+
+        pcntl_async_signals(true);
+        pcntl_alarm($timeout);
+
+        try {
+            return call_user_func_array($callable, $arguments);
+        } finally {
+            pcntl_alarm(0);
+        }
+    }
+
+    public function canInvokeWithTimeout(): bool
+    {
+        return function_exists('pcntl_signal') && function_exists('pcntl_async_signals') && function_exists('pcntl_alarm');
+    }
+}
diff --git a/vendor/phpunit/php-invoker/src/exceptions/Exception.php b/vendor/phpunit/php-invoker/src/exceptions/Exception.php
new file mode 100644
index 0000000000000000000000000000000000000000..6ecbf5dd3988fe9be566fa1307f7b45571e41ef8
--- /dev/null
+++ b/vendor/phpunit/php-invoker/src/exceptions/Exception.php
@@ -0,0 +1,16 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of phpunit/php-invoker.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\Invoker;
+
+use Throwable;
+
+interface Exception extends Throwable
+{
+}
diff --git a/vendor/phpunit/php-invoker/src/exceptions/ProcessControlExtensionNotLoadedException.php b/vendor/phpunit/php-invoker/src/exceptions/ProcessControlExtensionNotLoadedException.php
new file mode 100644
index 0000000000000000000000000000000000000000..ef42fd1958897e406f9fd2c6c21776e5eacdfe6b
--- /dev/null
+++ b/vendor/phpunit/php-invoker/src/exceptions/ProcessControlExtensionNotLoadedException.php
@@ -0,0 +1,16 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of phpunit/php-invoker.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\Invoker;
+
+use RuntimeException;
+
+final class ProcessControlExtensionNotLoadedException extends RuntimeException implements Exception
+{
+}
diff --git a/vendor/phpunit/php-invoker/src/exceptions/TimeoutException.php b/vendor/phpunit/php-invoker/src/exceptions/TimeoutException.php
new file mode 100644
index 0000000000000000000000000000000000000000..2f7631c0e4de9e8e81dcc53ecbbd0f1e9836778e
--- /dev/null
+++ b/vendor/phpunit/php-invoker/src/exceptions/TimeoutException.php
@@ -0,0 +1,16 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of phpunit/php-invoker.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\Invoker;
+
+use RuntimeException;
+
+final class TimeoutException extends RuntimeException implements Exception
+{
+}
diff --git a/vendor/phpunit/php-text-template/.psalm/baseline.xml b/vendor/phpunit/php-text-template/.psalm/baseline.xml
new file mode 100644
index 0000000000000000000000000000000000000000..77e688e07efe46415e5eaee84fbc946c36b82bcb
--- /dev/null
+++ b/vendor/phpunit/php-text-template/.psalm/baseline.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<files psalm-version="4.0.1@b1e2e30026936ef8d5bf6a354d1c3959b6231f44"/>
diff --git a/vendor/phpunit/php-text-template/.psalm/config.xml b/vendor/phpunit/php-text-template/.psalm/config.xml
new file mode 100644
index 0000000000000000000000000000000000000000..2a4b16f22703e24e4e45137a9fe06d144561c492
--- /dev/null
+++ b/vendor/phpunit/php-text-template/.psalm/config.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0"?>
+<psalm
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xmlns="https://getpsalm.org/schema/config"
+    xsi:schemaLocation="https://getpsalm.org/schema/config vendor/vimeo/psalm/config.xsd"
+    resolveFromConfigFile="false"
+    totallyTyped="false"
+    errorBaseline=".psalm/baseline.xml"
+>
+    <projectFiles>
+        <directory name="src" />
+        <ignoreFiles>
+            <directory name="vendor" />
+        </ignoreFiles>
+    </projectFiles>
+</psalm>
diff --git a/vendor/phpunit/php-text-template/ChangeLog.md b/vendor/phpunit/php-text-template/ChangeLog.md
new file mode 100644
index 0000000000000000000000000000000000000000..32a48a7a1cb4707627d03b1b5db19740c31c9126
--- /dev/null
+++ b/vendor/phpunit/php-text-template/ChangeLog.md
@@ -0,0 +1,43 @@
+# ChangeLog
+
+All notable changes are documented in this file using the [Keep a CHANGELOG](http://keepachangelog.com/) principles.
+
+## [2.0.4] - 2020-10-26
+
+### Fixed
+
+* `SebastianBergmann\Template\Exception` now correctly extends `\Throwable`
+
+## [2.0.3] - 2020-09-28
+
+### Changed
+
+* Changed PHP version constraint in `composer.json` from `^7.3 || ^8.0` to `>=7.3`
+
+## [2.0.2] - 2020-06-26
+
+### Added
+
+* This component is now supported on PHP 8
+
+## [2.0.1] - 2020-06-15
+
+### Changed
+
+* Tests etc. are now ignored for archive exports
+
+## [2.0.0] - 2020-02-07
+
+### Changed
+
+* The `Text_Template` class was renamed to `SebastianBergmann\Template\Template`
+
+### Removed
+
+* Removed support for PHP 5.3, PHP 5.4, PHP 5.5, PHP 5.6, PHP 7.0, PHP 7.1, and PHP 7.2 
+
+[2.0.4]: https://github.com/sebastianbergmann/php-text-template/compare/2.0.3...2.0.4
+[2.0.3]: https://github.com/sebastianbergmann/php-text-template/compare/2.0.2...2.0.3
+[2.0.2]: https://github.com/sebastianbergmann/php-text-template/compare/2.0.1...2.0.2
+[2.0.1]: https://github.com/sebastianbergmann/php-text-template/compare/2.0.0...2.0.1
+[2.0.0]: https://github.com/sebastianbergmann/php-text-template/compare/1.2.1...2.0.0
diff --git a/vendor/phpunit/php-text-template/LICENSE b/vendor/phpunit/php-text-template/LICENSE
new file mode 100644
index 0000000000000000000000000000000000000000..6db5566c87da2808d8c1d1ea7457f678bc3ee4fa
--- /dev/null
+++ b/vendor/phpunit/php-text-template/LICENSE
@@ -0,0 +1,33 @@
+phpunit/php-text-template
+
+Copyright (c) 2009-2020, Sebastian Bergmann <sebastian@phpunit.de>.
+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 Sebastian Bergmann nor the names of his
+   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/phpunit/php-text-template/README.md b/vendor/phpunit/php-text-template/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..b2865935457ff24e8d48045b30c4d7094c09158d
--- /dev/null
+++ b/vendor/phpunit/php-text-template/README.md
@@ -0,0 +1,12 @@
+# Text_Template
+
+## Installation
+
+You can add this library as a local, per-project dependency to your project using [Composer](https://getcomposer.org/):
+
+    composer require phpunit/php-text-template
+
+If you only need this library during development, for instance to run your project's test suite, then you should add it as a development-time dependency:
+
+    composer require --dev phpunit/php-text-template
+
diff --git a/vendor/phpunit/php-text-template/composer.json b/vendor/phpunit/php-text-template/composer.json
new file mode 100644
index 0000000000000000000000000000000000000000..a51b34b95c3d87dcc81354b3eab4e382fef1437b
--- /dev/null
+++ b/vendor/phpunit/php-text-template/composer.json
@@ -0,0 +1,43 @@
+{
+    "name": "phpunit/php-text-template",
+    "description": "Simple template engine.",
+    "type": "library",
+    "keywords": [
+        "template"
+    ],
+    "homepage": "https://github.com/sebastianbergmann/php-text-template/",
+    "license": "BSD-3-Clause",
+    "authors": [
+        {
+            "name": "Sebastian Bergmann",
+            "email": "sebastian@phpunit.de",
+            "role": "lead"
+        }
+    ],
+    "support": {
+        "issues": "https://github.com/sebastianbergmann/php-text-template/issues"
+    },
+    "config": {
+        "platform": {
+            "php": "7.3.0"
+        },
+        "optimize-autoloader": true,
+        "sort-packages": true
+    },
+    "require": {
+        "php": ">=7.3"
+    },
+    "require-dev": {
+        "phpunit/phpunit": "^9.3"
+    },
+    "autoload": {
+        "classmap": [
+            "src/"
+        ]
+    },
+    "extra": {
+        "branch-alias": {
+            "dev-master": "2.0-dev"
+        }
+    }
+}
diff --git a/vendor/phpunit/php-text-template/src/Template.php b/vendor/phpunit/php-text-template/src/Template.php
new file mode 100644
index 0000000000000000000000000000000000000000..25e29ea973eda753d427b6ab2c250f4277bfd1d9
--- /dev/null
+++ b/vendor/phpunit/php-text-template/src/Template.php
@@ -0,0 +1,107 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of phpunit/php-text-template.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\Template;
+
+use function array_merge;
+use function file_exists;
+use function file_get_contents;
+use function file_put_contents;
+use function sprintf;
+use function str_replace;
+
+final class Template
+{
+    /**
+     * @var string
+     */
+    private $template = '';
+
+    /**
+     * @var string
+     */
+    private $openDelimiter;
+
+    /**
+     * @var string
+     */
+    private $closeDelimiter;
+
+    /**
+     * @var array
+     */
+    private $values = [];
+
+    /**
+     * @throws InvalidArgumentException
+     */
+    public function __construct(string $file = '', string $openDelimiter = '{', string $closeDelimiter = '}')
+    {
+        $this->setFile($file);
+
+        $this->openDelimiter  = $openDelimiter;
+        $this->closeDelimiter = $closeDelimiter;
+    }
+
+    /**
+     * @throws InvalidArgumentException
+     */
+    public function setFile(string $file): void
+    {
+        $distFile = $file . '.dist';
+
+        if (file_exists($file)) {
+            $this->template = file_get_contents($file);
+        } elseif (file_exists($distFile)) {
+            $this->template = file_get_contents($distFile);
+        } else {
+            throw new InvalidArgumentException(
+                sprintf(
+                    'Failed to load template "%s"',
+                    $file
+                )
+            );
+        }
+    }
+
+    public function setVar(array $values, bool $merge = true): void
+    {
+        if (!$merge || empty($this->values)) {
+            $this->values = $values;
+        } else {
+            $this->values = array_merge($this->values, $values);
+        }
+    }
+
+    public function render(): string
+    {
+        $keys = [];
+
+        foreach ($this->values as $key => $value) {
+            $keys[] = $this->openDelimiter . $key . $this->closeDelimiter;
+        }
+
+        return str_replace($keys, $this->values, $this->template);
+    }
+
+    /**
+     * @codeCoverageIgnore
+     */
+    public function renderTo(string $target): void
+    {
+        if (!file_put_contents($target, $this->render())) {
+            throw new RuntimeException(
+                sprintf(
+                    'Writing rendered result to "%s" failed',
+                    $target
+                )
+            );
+        }
+    }
+}
diff --git a/vendor/phpunit/php-text-template/src/exceptions/Exception.php b/vendor/phpunit/php-text-template/src/exceptions/Exception.php
new file mode 100644
index 0000000000000000000000000000000000000000..d7dc5cbeaed52a0c4db553fffc510f575197465f
--- /dev/null
+++ b/vendor/phpunit/php-text-template/src/exceptions/Exception.php
@@ -0,0 +1,16 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of phpunit/php-text-template.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\Template;
+
+use Throwable;
+
+interface Exception extends Throwable
+{
+}
diff --git a/vendor/phpunit/php-text-template/src/exceptions/InvalidArgumentException.php b/vendor/phpunit/php-text-template/src/exceptions/InvalidArgumentException.php
new file mode 100644
index 0000000000000000000000000000000000000000..10e1cd11fad21fd4c00a0f7e500e7bfabc558d32
--- /dev/null
+++ b/vendor/phpunit/php-text-template/src/exceptions/InvalidArgumentException.php
@@ -0,0 +1,14 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of phpunit/php-text-template.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\Template;
+
+final class InvalidArgumentException extends \InvalidArgumentException implements Exception
+{
+}
diff --git a/vendor/phpunit/php-text-template/src/exceptions/RuntimeException.php b/vendor/phpunit/php-text-template/src/exceptions/RuntimeException.php
new file mode 100644
index 0000000000000000000000000000000000000000..131498e6101b81e59f92225f9f9df0a550728237
--- /dev/null
+++ b/vendor/phpunit/php-text-template/src/exceptions/RuntimeException.php
@@ -0,0 +1,16 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of phpunit/php-text-template.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\Template;
+
+use InvalidArgumentException;
+
+final class RuntimeException extends InvalidArgumentException implements Exception
+{
+}
diff --git a/vendor/phpunit/php-timer/.psalm/baseline.xml b/vendor/phpunit/php-timer/.psalm/baseline.xml
new file mode 100644
index 0000000000000000000000000000000000000000..77e688e07efe46415e5eaee84fbc946c36b82bcb
--- /dev/null
+++ b/vendor/phpunit/php-timer/.psalm/baseline.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<files psalm-version="4.0.1@b1e2e30026936ef8d5bf6a354d1c3959b6231f44"/>
diff --git a/vendor/phpunit/php-timer/.psalm/config.xml b/vendor/phpunit/php-timer/.psalm/config.xml
new file mode 100644
index 0000000000000000000000000000000000000000..15abef0580abbfdf63baa1a91ead072ce3fed20a
--- /dev/null
+++ b/vendor/phpunit/php-timer/.psalm/config.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0"?>
+<psalm
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xmlns="https://getpsalm.org/schema/config"
+    xsi:schemaLocation="https://getpsalm.org/schema/config vendor/vimeo/psalm/config.xsd"
+    resolveFromConfigFile="false"
+    totallyTyped="true"
+    errorBaseline=".psalm/baseline.xml"
+>
+    <projectFiles>
+        <directory name="src" />
+        <ignoreFiles>
+            <directory name="vendor" />
+        </ignoreFiles>
+    </projectFiles>
+</psalm>
diff --git a/vendor/phpunit/php-timer/ChangeLog.md b/vendor/phpunit/php-timer/ChangeLog.md
new file mode 100644
index 0000000000000000000000000000000000000000..34ef7d1d70003dac658a5914d0c87c9b9e1b61dd
--- /dev/null
+++ b/vendor/phpunit/php-timer/ChangeLog.md
@@ -0,0 +1,138 @@
+# ChangeLog
+
+All notable changes are documented in this file using the [Keep a CHANGELOG](http://keepachangelog.com/) principles.
+
+## [5.0.3] - 2020-10-26
+
+### Fixed
+
+* `SebastianBergmann\Timer\Exception` now correctly extends `\Throwable`
+
+## [5.0.2] - 2020-09-28
+
+### Changed
+
+* Changed PHP version constraint in `composer.json` from `^7.3 || ^8.0` to `>=7.3`
+
+## [5.0.1] - 2020-06-26
+
+### Added
+
+* This component is now supported on PHP 8
+
+## [5.0.0] - 2020-06-07
+
+### Changed
+
+* Parameter type for `SebastianBergmann\Timer\Duration::fromMicroseconds()` was changed from `int` to `float` 
+* Parameter type for `SebastianBergmann\Timer\Duration::fromNanoseconds()` was changed from `int` to `float`
+* Return type for `SebastianBergmann\Timer\Duration::asNanoseconds()` was changed from `int` to `float`
+
+### Fixed
+
+* [#31](https://github.com/sebastianbergmann/php-timer/issues/31): Type Error on 32-bit systems (where `hrtime()` returns `float` instead of `int`)
+
+## [4.0.0] - 2020-06-01
+
+### Added
+
+* Introduced `Duration` value object for encapsulating a duration with nanosecond granularity
+* Introduced `ResourceUsageFormatter` object for formatting resource usage with option to explicitly pass a duration (instead of looking at the unreliable `$_SERVER['REQUEST_TIME_FLOAT']` variable)
+
+### Changed
+
+* The methods of `Timer` are no longer static
+* `Timer::stop()` now returns a `Duration` value object
+
+### Removed
+
+* Functionality that is now implemented in `Duration` and `ResourceUsageFormatter` has been removed from `Timer`
+
+## [3.1.4] - 2020-04-20
+
+### Changed
+
+* `Timer::timeSinceStartOfRequest()` no longer tries `$_SERVER['REQUEST_TIME']` when `$_SERVER['REQUEST_TIME_FLOAT']` is not available (`$_SERVER['REQUEST_TIME_FLOAT']` was added in PHP 5.4 and this library requires PHP 7.3)
+* Improved exception messages when `$_SERVER['REQUEST_TIME_FLOAT']` is not set or is not of type `float`
+
+### Changed
+
+## [3.1.3] - 2020-04-20
+
+### Changed
+
+* `Timer::timeSinceStartOfRequest()` now raises an exception if `$_SERVER['REQUEST_TIME_FLOAT']` does not contain a `float` (or `$_SERVER['REQUEST_TIME']` does not contain an `int`)
+
+## [3.1.2] - 2020-04-17
+
+### Changed
+
+* Improved the fix for [#30](https://github.com/sebastianbergmann/php-timer/issues/30) and restored usage of `hrtime()`
+
+## [3.1.1] - 2020-04-17
+
+### Fixed
+
+* [#30](https://github.com/sebastianbergmann/php-timer/issues/30): Resolution of time returned by `Timer::stop()` is different than before (this reverts using `hrtime()` instead of `microtime()`)
+
+## [3.1.0] - 2020-04-17
+
+### Added
+
+* `Timer::secondsToShortTimeString()` as alternative to `Timer::secondsToTimeString()`
+
+### Changed
+
+* `Timer::start()` and `Timer::stop()` now use `hrtime()` (high resolution monotonic timer) instead of `microtime()`
+* `Timer::timeSinceStartOfRequest()` now uses `Timer::secondsToShortTimeString()` for time formatting
+* Improved formatting of `Timer::secondsToTimeString()` result
+
+## [3.0.0] - 2020-02-07
+
+### Removed
+
+* This component is no longer supported on PHP 7.1 and PHP 7.2
+
+## [2.1.2] - 2019-06-07
+
+### Fixed
+
+* [#21](https://github.com/sebastianbergmann/php-timer/pull/21): Formatting of memory consumption does not work on 32bit systems
+
+## [2.1.1] - 2019-02-20
+
+### Changed
+
+* Improved formatting of memory consumption for `resourceUsage()`
+
+## [2.1.0] - 2019-02-20
+
+### Changed
+
+* Improved formatting of memory consumption for `resourceUsage()`
+
+## [2.0.0] - 2018-02-01
+
+### Changed
+
+* This component now uses namespaces
+
+### Removed
+
+* This component is no longer supported on PHP 5.3, PHP 5.4, PHP 5.5, PHP 5.6, and PHP 7.0
+
+[5.0.3]: https://github.com/sebastianbergmann/php-timer/compare/5.0.2...5.0.3
+[5.0.2]: https://github.com/sebastianbergmann/php-timer/compare/5.0.1...5.0.2
+[5.0.1]: https://github.com/sebastianbergmann/php-timer/compare/5.0.0...5.0.1
+[5.0.0]: https://github.com/sebastianbergmann/php-timer/compare/4.0.0...5.0.0
+[4.0.0]: https://github.com/sebastianbergmann/php-timer/compare/3.1.4...4.0.0
+[3.1.4]: https://github.com/sebastianbergmann/php-timer/compare/3.1.3...3.1.4
+[3.1.3]: https://github.com/sebastianbergmann/php-timer/compare/3.1.2...3.1.3
+[3.1.2]: https://github.com/sebastianbergmann/php-timer/compare/3.1.1...3.1.2
+[3.1.1]: https://github.com/sebastianbergmann/php-timer/compare/3.1.0...3.1.1
+[3.1.0]: https://github.com/sebastianbergmann/php-timer/compare/3.0.0...3.1.0
+[3.0.0]: https://github.com/sebastianbergmann/php-timer/compare/2.1.2...3.0.0
+[2.1.2]: https://github.com/sebastianbergmann/php-timer/compare/2.1.1...2.1.2
+[2.1.1]: https://github.com/sebastianbergmann/php-timer/compare/2.1.0...2.1.1
+[2.1.0]: https://github.com/sebastianbergmann/php-timer/compare/2.0.0...2.1.0
+[2.0.0]: https://github.com/sebastianbergmann/php-timer/compare/1.0.9...2.0.0
diff --git a/vendor/phpunit/php-timer/LICENSE b/vendor/phpunit/php-timer/LICENSE
new file mode 100644
index 0000000000000000000000000000000000000000..4193d8ae63e66dfe8b01fc1964c8535b7d7935b3
--- /dev/null
+++ b/vendor/phpunit/php-timer/LICENSE
@@ -0,0 +1,33 @@
+phpunit/php-timer
+
+Copyright (c) 2010-2020, Sebastian Bergmann <sebastian@phpunit.de>.
+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 Sebastian Bergmann nor the names of his
+   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/phpunit/php-timer/README.md b/vendor/phpunit/php-timer/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..a7d1e70de38f66bf280ecbc71c869319f04bd741
--- /dev/null
+++ b/vendor/phpunit/php-timer/README.md
@@ -0,0 +1,104 @@
+# phpunit/php-timer
+
+[![CI Status](https://github.com/sebastianbergmann/php-timer/workflows/CI/badge.svg)](https://github.com/sebastianbergmann/php-timer/actions)
+[![Type Coverage](https://shepherd.dev/github/sebastianbergmann/php-timer/coverage.svg)](https://shepherd.dev/github/sebastianbergmann/php-timer)
+
+Utility class for timing things, factored out of PHPUnit into a stand-alone component.
+
+## Installation
+
+You can add this library as a local, per-project dependency to your project using [Composer](https://getcomposer.org/):
+
+```
+composer require phpunit/php-timer
+```
+
+If you only need this library during development, for instance to run your project's test suite, then you should add it as a development-time dependency:
+
+```
+composer require --dev phpunit/php-timer
+```
+
+## Usage
+
+### Basic Timing
+
+```php
+require __DIR__ . '/vendor/autoload.php';
+
+use SebastianBergmann\Timer\Timer;
+
+$timer = new Timer;
+
+$timer->start();
+
+foreach (\range(0, 100000) as $i) {
+    // ...
+}
+
+$duration = $timer->stop();
+
+var_dump(get_class($duration));
+var_dump($duration->asString());
+var_dump($duration->asSeconds());
+var_dump($duration->asMilliseconds());
+var_dump($duration->asMicroseconds());
+var_dump($duration->asNanoseconds());
+```
+
+The code above yields the output below:
+
+```
+string(32) "SebastianBergmann\Timer\Duration"
+string(9) "00:00.002"
+float(0.002851062)
+float(2.851062)
+float(2851.062)
+int(2851062)
+```
+
+### Resource Consumption
+
+#### Explicit duration
+
+```php
+require __DIR__ . '/vendor/autoload.php';
+
+use SebastianBergmann\Timer\ResourceUsageFormatter;
+use SebastianBergmann\Timer\Timer;
+
+$timer = new Timer;
+$timer->start();
+
+foreach (\range(0, 100000) as $i) {
+    // ...
+}
+
+print (new ResourceUsageFormatter)->resourceUsage($timer->stop());
+```
+
+The code above yields the output below:
+
+```
+Time: 00:00.002, Memory: 6.00 MB
+```
+
+#### Duration since PHP Startup (using unreliable `$_SERVER['REQUEST_TIME_FLOAT']`)
+
+```php
+require __DIR__ . '/vendor/autoload.php';
+
+use SebastianBergmann\Timer\ResourceUsageFormatter;
+
+foreach (\range(0, 100000) as $i) {
+    // ...
+}
+
+print (new ResourceUsageFormatter)->resourceUsageSinceStartOfRequest();
+```
+
+The code above yields the output below:
+
+```
+Time: 00:00.002, Memory: 6.00 MB
+```
diff --git a/vendor/phpunit/php-timer/composer.json b/vendor/phpunit/php-timer/composer.json
new file mode 100644
index 0000000000000000000000000000000000000000..001701c2413f5f194eef3011b015cf373da5784d
--- /dev/null
+++ b/vendor/phpunit/php-timer/composer.json
@@ -0,0 +1,45 @@
+{
+    "name": "phpunit/php-timer",
+    "description": "Utility class for timing",
+    "type": "library",
+    "keywords": [
+        "timer"
+    ],
+    "homepage": "https://github.com/sebastianbergmann/php-timer/",
+    "license": "BSD-3-Clause",
+    "authors": [
+        {
+            "name": "Sebastian Bergmann",
+            "email": "sebastian@phpunit.de",
+            "role": "lead"
+        }
+    ],
+    "support": {
+        "issues": "https://github.com/sebastianbergmann/php-timer/issues"
+    },
+    "prefer-stable": true,
+    "require": {
+        "php": ">=7.3"
+    },
+    "require-dev": {
+        "phpunit/phpunit": "^9.3"
+    },
+    "config": {
+        "platform": {
+            "php": "7.3.0"
+        },
+        "optimize-autoloader": true,
+        "sort-packages": true
+    },
+    "autoload": {
+        "classmap": [
+            "src/"
+        ]
+    },
+    "extra": {
+        "branch-alias": {
+            "dev-master": "5.0-dev"
+        }
+    }
+}
+
diff --git a/vendor/phpunit/php-timer/src/Duration.php b/vendor/phpunit/php-timer/src/Duration.php
new file mode 100644
index 0000000000000000000000000000000000000000..e52bf018f28837aafb839de0021de1e02aec1a80
--- /dev/null
+++ b/vendor/phpunit/php-timer/src/Duration.php
@@ -0,0 +1,109 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of phpunit/php-timer.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\Timer;
+
+use function floor;
+use function sprintf;
+
+/**
+ * @psalm-immutable
+ */
+final class Duration
+{
+    /**
+     * @var float
+     */
+    private $nanoseconds;
+
+    /**
+     * @var int
+     */
+    private $hours;
+
+    /**
+     * @var int
+     */
+    private $minutes;
+
+    /**
+     * @var int
+     */
+    private $seconds;
+
+    /**
+     * @var int
+     */
+    private $milliseconds;
+
+    public static function fromMicroseconds(float $microseconds): self
+    {
+        return new self($microseconds * 1000);
+    }
+
+    public static function fromNanoseconds(float $nanoseconds): self
+    {
+        return new self($nanoseconds);
+    }
+
+    private function __construct(float $nanoseconds)
+    {
+        $this->nanoseconds     = $nanoseconds;
+        $timeInMilliseconds    = $nanoseconds / 1000000;
+        $hours                 = floor($timeInMilliseconds / 60 / 60 / 1000);
+        $hoursInMilliseconds   = $hours * 60 * 60 * 1000;
+        $minutes               = floor($timeInMilliseconds / 60 / 1000) % 60;
+        $minutesInMilliseconds = $minutes * 60 * 1000;
+        $seconds               = floor(($timeInMilliseconds - $hoursInMilliseconds - $minutesInMilliseconds) / 1000);
+        $secondsInMilliseconds = $seconds * 1000;
+        $milliseconds          = $timeInMilliseconds - $hoursInMilliseconds - $minutesInMilliseconds - $secondsInMilliseconds;
+        $this->hours           = (int) $hours;
+        $this->minutes         = $minutes;
+        $this->seconds         = (int) $seconds;
+        $this->milliseconds    = (int) $milliseconds;
+    }
+
+    public function asNanoseconds(): float
+    {
+        return $this->nanoseconds;
+    }
+
+    public function asMicroseconds(): float
+    {
+        return $this->nanoseconds / 1000;
+    }
+
+    public function asMilliseconds(): float
+    {
+        return $this->nanoseconds / 1000000;
+    }
+
+    public function asSeconds(): float
+    {
+        return $this->nanoseconds / 1000000000;
+    }
+
+    public function asString(): string
+    {
+        $result = '';
+
+        if ($this->hours > 0) {
+            $result = sprintf('%02d', $this->hours) . ':';
+        }
+
+        $result .= sprintf('%02d', $this->minutes) . ':';
+        $result .= sprintf('%02d', $this->seconds);
+
+        if ($this->milliseconds > 0) {
+            $result .= '.' . sprintf('%03d', $this->milliseconds);
+        }
+
+        return $result;
+    }
+}
diff --git a/vendor/phpunit/php-timer/src/ResourceUsageFormatter.php b/vendor/phpunit/php-timer/src/ResourceUsageFormatter.php
new file mode 100644
index 0000000000000000000000000000000000000000..ad79262771ce155479048e2617426cf68f613f81
--- /dev/null
+++ b/vendor/phpunit/php-timer/src/ResourceUsageFormatter.php
@@ -0,0 +1,73 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of phpunit/php-timer.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\Timer;
+
+use function is_float;
+use function memory_get_peak_usage;
+use function microtime;
+use function sprintf;
+
+final class ResourceUsageFormatter
+{
+    /**
+     * @psalm-var array<string,int>
+     */
+    private const SIZES = [
+        'GB' => 1073741824,
+        'MB' => 1048576,
+        'KB' => 1024,
+    ];
+
+    public function resourceUsage(Duration $duration): string
+    {
+        return sprintf(
+            'Time: %s, Memory: %s',
+            $duration->asString(),
+            $this->bytesToString(memory_get_peak_usage(true))
+        );
+    }
+
+    /**
+     * @throws TimeSinceStartOfRequestNotAvailableException
+     */
+    public function resourceUsageSinceStartOfRequest(): string
+    {
+        if (!isset($_SERVER['REQUEST_TIME_FLOAT'])) {
+            throw new TimeSinceStartOfRequestNotAvailableException(
+                'Cannot determine time at which the request started because $_SERVER[\'REQUEST_TIME_FLOAT\'] is not available'
+            );
+        }
+
+        if (!is_float($_SERVER['REQUEST_TIME_FLOAT'])) {
+            throw new TimeSinceStartOfRequestNotAvailableException(
+                'Cannot determine time at which the request started because $_SERVER[\'REQUEST_TIME_FLOAT\'] is not of type float'
+            );
+        }
+
+        return $this->resourceUsage(
+            Duration::fromMicroseconds(
+                (1000000 * (microtime(true) - $_SERVER['REQUEST_TIME_FLOAT']))
+            )
+        );
+    }
+
+    private function bytesToString(int $bytes): string
+    {
+        foreach (self::SIZES as $unit => $value) {
+            if ($bytes >= $value) {
+                return sprintf('%.2f %s', $bytes >= 1024 ? $bytes / $value : $bytes, $unit);
+            }
+        }
+
+        // @codeCoverageIgnoreStart
+        return $bytes . ' byte' . ($bytes !== 1 ? 's' : '');
+        // @codeCoverageIgnoreEnd
+    }
+}
diff --git a/vendor/phpunit/php-timer/src/Timer.php b/vendor/phpunit/php-timer/src/Timer.php
new file mode 100644
index 0000000000000000000000000000000000000000..0917109bebb25775038c665adf95dbab858c828a
--- /dev/null
+++ b/vendor/phpunit/php-timer/src/Timer.php
@@ -0,0 +1,40 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of phpunit/php-timer.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\Timer;
+
+use function array_pop;
+use function hrtime;
+
+final class Timer
+{
+    /**
+     * @psalm-var list<float>
+     */
+    private $startTimes = [];
+
+    public function start(): void
+    {
+        $this->startTimes[] = (float) hrtime(true);
+    }
+
+    /**
+     * @throws NoActiveTimerException
+     */
+    public function stop(): Duration
+    {
+        if (empty($this->startTimes)) {
+            throw new NoActiveTimerException(
+                'Timer::start() has to be called before Timer::stop()'
+            );
+        }
+
+        return Duration::fromNanoseconds((float) hrtime(true) - array_pop($this->startTimes));
+    }
+}
diff --git a/vendor/phpunit/php-timer/src/exceptions/Exception.php b/vendor/phpunit/php-timer/src/exceptions/Exception.php
new file mode 100644
index 0000000000000000000000000000000000000000..996da08608f102a3697abe619c1fe51ef11ac485
--- /dev/null
+++ b/vendor/phpunit/php-timer/src/exceptions/Exception.php
@@ -0,0 +1,16 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of phpunit/php-timer.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\Timer;
+
+use Throwable;
+
+interface Exception extends Throwable
+{
+}
diff --git a/vendor/phpunit/php-timer/src/exceptions/NoActiveTimerException.php b/vendor/phpunit/php-timer/src/exceptions/NoActiveTimerException.php
new file mode 100644
index 0000000000000000000000000000000000000000..40fe45e86987f063b852a76525b1531f91404ef9
--- /dev/null
+++ b/vendor/phpunit/php-timer/src/exceptions/NoActiveTimerException.php
@@ -0,0 +1,16 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of phpunit/php-timer.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\Timer;
+
+use LogicException;
+
+final class NoActiveTimerException extends LogicException implements Exception
+{
+}
diff --git a/vendor/phpunit/php-timer/src/exceptions/TimeSinceStartOfRequestNotAvailableException.php b/vendor/phpunit/php-timer/src/exceptions/TimeSinceStartOfRequestNotAvailableException.php
new file mode 100644
index 0000000000000000000000000000000000000000..a2d94ce80c29011f954cbc4c324766bc3c1d512b
--- /dev/null
+++ b/vendor/phpunit/php-timer/src/exceptions/TimeSinceStartOfRequestNotAvailableException.php
@@ -0,0 +1,16 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of phpunit/php-timer.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\Timer;
+
+use RuntimeException;
+
+final class TimeSinceStartOfRequestNotAvailableException extends RuntimeException implements Exception
+{
+}
diff --git a/vendor/phpunit/phpunit/.phpstorm.meta.php b/vendor/phpunit/phpunit/.phpstorm.meta.php
new file mode 100644
index 0000000000000000000000000000000000000000..5e4c4c2d7dde04fabaa8a1ba115f2f0ce0b40f66
--- /dev/null
+++ b/vendor/phpunit/phpunit/.phpstorm.meta.php
@@ -0,0 +1,45 @@
+<?php
+namespace PHPSTORM_META {
+
+    override(
+        \PHPUnit\Framework\TestCase::createMock(0),
+        map([
+            '@&\PHPUnit\Framework\MockObject\MockObject',
+        ])
+    );
+
+    override(
+        \PHPUnit\Framework\TestCase::createStub(0),
+        map([
+            '@&\PHPUnit\Framework\MockObject\Stub',
+        ])
+    );
+
+    override(
+        \PHPUnit\Framework\TestCase::createConfiguredMock(0),
+        map([
+            '@&\PHPUnit\Framework\MockObject\MockObject',
+        ])
+    );
+
+    override(
+        \PHPUnit\Framework\TestCase::createPartialMock(0),
+        map([
+            '@&\PHPUnit\Framework\MockObject\MockObject',
+        ])
+    );
+
+    override(
+        \PHPUnit\Framework\TestCase::createTestProxy(0),
+        map([
+            '@&\PHPUnit\Framework\MockObject\MockObject',
+        ])
+    );
+
+    override(
+        \PHPUnit\Framework\TestCase::getMockForAbstractClass(0),
+        map([
+            '@&\PHPUnit\Framework\MockObject\MockObject',
+        ])
+    );
+}
diff --git a/vendor/phpunit/phpunit/ChangeLog-8.5.md b/vendor/phpunit/phpunit/ChangeLog-8.5.md
new file mode 100644
index 0000000000000000000000000000000000000000..fa6a534f3cec86334ecf93dfe4e48226c8c18e10
--- /dev/null
+++ b/vendor/phpunit/phpunit/ChangeLog-8.5.md
@@ -0,0 +1,148 @@
+# Changes in PHPUnit 8.5
+
+All notable changes of the PHPUnit 8.5 release series are documented in this file using the [Keep a CHANGELOG](https://keepachangelog.com/) principles.
+
+## [8.5.15] - 2021-03-17
+
+### Fixed
+
+* [#4591](https://github.com/sebastianbergmann/phpunit/issues/4591): TeamCity logger logs warnings as test failures
+
+## [8.5.14] - 2021-01-17
+
+### Fixed
+
+* [#4535](https://github.com/sebastianbergmann/phpunit/issues/4535): `getMockFromWsdl()` does not handle methods that do not have parameters correctly
+* [#4572](https://github.com/sebastianbergmann/phpunit/issues/4572): Schema validation does not work with `%xx` sequences in path to `phpunit.xsd`
+* [#4575](https://github.com/sebastianbergmann/phpunit/issues/4575): PHPUnit 8.5 incompatibility with PHP 8.1
+
+## [8.5.13] - 2020-12-01
+
+### Fixed
+
+* Running tests in isolated processes did not work with PHP 8 on Windows
+
+## [8.5.12] - 2020-11-30
+
+### Changed
+
+* Changed PHP version constraint in `composer.json` from `^7.2` to `>=7.2` to allow the installation of PHPUnit 8.5 on PHP 8. Please note that the code coverage functionality is not available for PHPUnit 8.5 on PHP 8.
+
+### Fixed
+
+* [#4529](https://github.com/sebastianbergmann/phpunit/issues/4529): Debug mode of Xdebug 2 is not disabled for PHPT tests
+
+## [8.5.11] - 2020-11-27
+
+### Changed
+
+* Bumped required version of `phpunit/php-code-coverage`
+
+## [8.5.10] - 2020-11-27
+
+### Added
+
+* Support for Xdebug 3
+
+### Fixed
+
+* [#4516](https://github.com/sebastianbergmann/phpunit/issues/4516): `phpunit/phpunit-selenium` does not work with PHPUnit 8.5.9
+
+## [8.5.9] - 2020-11-10
+
+### Fixed
+
+* [#3965](https://github.com/sebastianbergmann/phpunit/issues/3965): Process Isolation throws exceptions when PHPDBG is used
+* [#4470](https://github.com/sebastianbergmann/phpunit/pull/4470): Infinite recursion when `--static-backup --strict-global-state` is used
+
+## [8.5.8] - 2020-06-22
+
+### Fixed
+
+* [#4312](https://github.com/sebastianbergmann/phpunit/issues/4312): Fix for [#4299](https://github.com/sebastianbergmann/phpunit/issues/4299) breaks backward compatibility
+
+## [8.5.7] - 2020-06-21
+
+### Fixed
+
+* [#4299](https://github.com/sebastianbergmann/phpunit/issues/4299): "No tests executed" does not always result in exit code `1`
+* [#4306](https://github.com/sebastianbergmann/phpunit/issues/4306): Exceptions during code coverage driver initialization are not handled correctly
+
+## [8.5.6] - 2020-06-15
+
+### Fixed
+
+* [#4211](https://github.com/sebastianbergmann/phpunit/issues/4211): `phpdbg_*()` functions are scoped to `PHPUnit\phpdbg_*()`
+
+## [8.5.5] - 2020-05-22
+
+### Fixed
+
+* [#4033](https://github.com/sebastianbergmann/phpunit/issues/4033): Unexpected behaviour when `$GLOBALS` is deleted
+
+## [8.5.4] - 2020-04-23
+
+### Changed
+
+* Changed how `PHPUnit\TextUI\Command` passes warnings to `PHPUnit\TextUI\TestRunner`
+
+## [8.5.3] - 2020-03-31
+
+### Fixed
+
+* [#4017](https://github.com/sebastianbergmann/phpunit/issues/4017): Do not suggest refactoring to something that is also deprecated
+* [#4133](https://github.com/sebastianbergmann/phpunit/issues/4133): `expectExceptionMessageRegExp()` has been removed in PHPUnit 9 without a deprecation warning being given in PHPUnit 8
+* [#4139](https://github.com/sebastianbergmann/phpunit/issues/4139): Cannot double interfaces that declare a constructor with PHP 8
+* [#4144](https://github.com/sebastianbergmann/phpunit/issues/4144): Empty objects are converted to empty arrays in JSON comparison failure diff
+
+## [8.5.2] - 2020-01-08
+
+### Removed
+
+* `eval-stdin.php` has been removed, it was not used anymore since PHPUnit 7.2.7
+
+## [8.5.1] - 2019-12-25
+
+### Changed
+
+* `eval-stdin.php` can now only be executed with `cli` and `phpdbg`
+
+### Fixed
+
+* [#3983](https://github.com/sebastianbergmann/phpunit/issues/3983): Deprecation warning given too eagerly
+
+## [8.5.0] - 2019-12-06
+
+### Added
+
+* [#3911](https://github.com/sebastianbergmann/phpunit/issues/3911): Support combined use of `addMethods()` and `onlyMethods()`
+* [#3949](https://github.com/sebastianbergmann/phpunit/issues/3949): Introduce specialized assertions `assertFileEqualsCanonicalizing()`, `assertFileEqualsIgnoringCase()`, `assertStringEqualsFileCanonicalizing()`, `assertStringEqualsFileIgnoringCase()`, `assertFileNotEqualsCanonicalizing()`, `assertFileNotEqualsIgnoringCase()`, `assertStringNotEqualsFileCanonicalizing()`, and `assertStringNotEqualsFileIgnoringCase()` as alternative to using `assertFileEquals()` etc. with optional parameters
+
+### Changed
+
+* [#3860](https://github.com/sebastianbergmann/phpunit/pull/3860): Deprecate invoking PHPUnit commandline test runner with just a class name
+* [#3950](https://github.com/sebastianbergmann/phpunit/issues/3950): Deprecate optional parameters of `assertFileEquals()` etc.
+* [#3955](https://github.com/sebastianbergmann/phpunit/issues/3955): Deprecate support for doubling multiple interfaces
+
+### Fixed
+
+* [#3953](https://github.com/sebastianbergmann/phpunit/issues/3953): Code Coverage for test executed in isolation does not work when the PHAR is used
+* [#3967](https://github.com/sebastianbergmann/phpunit/issues/3967): Cannot double interface that extends interface that extends `\Throwable`
+* [#3968](https://github.com/sebastianbergmann/phpunit/pull/3968): Test class run in a separate PHP process are passing when `exit` called inside
+
+[8.5.15]: https://github.com/sebastianbergmann/phpunit/compare/8.5.14...8.5.15
+[8.5.14]: https://github.com/sebastianbergmann/phpunit/compare/8.5.13...8.5.14
+[8.5.13]: https://github.com/sebastianbergmann/phpunit/compare/8.5.12...8.5.13
+[8.5.12]: https://github.com/sebastianbergmann/phpunit/compare/8.5.11...8.5.12
+[8.5.11]: https://github.com/sebastianbergmann/phpunit/compare/8.5.10...8.5.11
+[8.5.10]: https://github.com/sebastianbergmann/phpunit/compare/8.5.9...8.5.10
+[8.5.9]: https://github.com/sebastianbergmann/phpunit/compare/8.5.8...8.5.9
+[8.5.8]: https://github.com/sebastianbergmann/phpunit/compare/8.5.7...8.5.8
+[8.5.7]: https://github.com/sebastianbergmann/phpunit/compare/8.5.6...8.5.7
+[8.5.6]: https://github.com/sebastianbergmann/phpunit/compare/8.5.5...8.5.6
+[8.5.5]: https://github.com/sebastianbergmann/phpunit/compare/8.5.4...8.5.5
+[8.5.4]: https://github.com/sebastianbergmann/phpunit/compare/8.5.3...8.5.4
+[8.5.3]: https://github.com/sebastianbergmann/phpunit/compare/8.5.2...8.5.3
+[8.5.2]: https://github.com/sebastianbergmann/phpunit/compare/8.5.1...8.5.2
+[8.5.1]: https://github.com/sebastianbergmann/phpunit/compare/8.5.0...8.5.1
+[8.5.0]: https://github.com/sebastianbergmann/phpunit/compare/8.4.3...8.5.0
diff --git a/vendor/phpunit/phpunit/ChangeLog-9.5.md b/vendor/phpunit/phpunit/ChangeLog-9.5.md
new file mode 100644
index 0000000000000000000000000000000000000000..65e0d7d8d2bb0abe41c6ba4cc626c87279e40d40
--- /dev/null
+++ b/vendor/phpunit/phpunit/ChangeLog-9.5.md
@@ -0,0 +1,41 @@
+# Changes in PHPUnit 9.5
+
+All notable changes of the PHPUnit 9.5 release series are documented in this file using the [Keep a CHANGELOG](https://keepachangelog.com/) principles.
+
+## [9.5.3] - 2021-03-17
+
+### Fixed
+
+* [#4591](https://github.com/sebastianbergmann/phpunit/issues/4591): TeamCity logger logs warnings as test failures
+* [#4620](https://github.com/sebastianbergmann/phpunit/issues/4620): No useful output when an error occurs in the bootstrap script
+
+## [9.5.2] - 2021-02-02
+
+### Fixed
+
+* [#4573](https://github.com/sebastianbergmann/phpunit/issues/4573): No stack trace printed when PHPUnit is used from PHAR
+* [#4590](https://github.com/sebastianbergmann/phpunit/issues/4590): `--coverage-text` CLI option is documented wrong
+
+## [9.5.1] - 2021-01-17
+
+### Fixed
+
+* [#4572](https://github.com/sebastianbergmann/phpunit/issues/4572): Schema validation does not work with `%xx` sequences in path to `phpunit.xsd`
+
+## [9.5.0] - 2020-12-04
+
+### Changed
+
+* [#4490](https://github.com/sebastianbergmann/phpunit/issues/4490): Emit Error instead of Warning when test case class cannot be instantiated
+* [#4491](https://github.com/sebastianbergmann/phpunit/issues/4491): Emit Error instead of Warning when data provider does not work correctly
+* [#4492](https://github.com/sebastianbergmann/phpunit/issues/4492): Emit Error instead of Warning when test double configuration is invalid
+* [#4493](https://github.com/sebastianbergmann/phpunit/issues/4493): Emit error when (configured) test directory does not exist
+
+### Fixed
+
+* [#4535](https://github.com/sebastianbergmann/phpunit/issues/4535): `getMockFromWsdl()` does not handle methods that do not have parameters correctly
+
+[9.5.3]: https://github.com/sebastianbergmann/phpunit/compare/9.5.2...9.5.3
+[9.5.2]: https://github.com/sebastianbergmann/phpunit/compare/9.5.1...9.5.2
+[9.5.1]: https://github.com/sebastianbergmann/phpunit/compare/9.5.0...9.5.1
+[9.5.0]: https://github.com/sebastianbergmann/phpunit/compare/9.4.4...9.5.0
diff --git a/vendor/phpunit/phpunit/LICENSE b/vendor/phpunit/phpunit/LICENSE
new file mode 100644
index 0000000000000000000000000000000000000000..0e3c9a0d586d8c69d58ef4b72619019a59c1ce80
--- /dev/null
+++ b/vendor/phpunit/phpunit/LICENSE
@@ -0,0 +1,33 @@
+PHPUnit
+
+Copyright (c) 2001-2021, Sebastian Bergmann <sebastian@phpunit.de>.
+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 Sebastian Bergmann nor the names of his
+   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/phpunit/phpunit/README.md b/vendor/phpunit/phpunit/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..d6bb0846cce31eb86d28b1c9d59a0934a892728e
--- /dev/null
+++ b/vendor/phpunit/phpunit/README.md
@@ -0,0 +1,41 @@
+# PHPUnit
+
+PHPUnit is a programmer-oriented testing framework for PHP. It is an instance of the xUnit architecture for unit testing frameworks.
+
+[![Latest Stable Version](https://img.shields.io/packagist/v/phpunit/phpunit.svg?style=flat-square)](https://packagist.org/packages/phpunit/phpunit)
+[![Minimum PHP Version](https://img.shields.io/badge/php-%3E%3D%207.3-8892BF.svg?style=flat-square)](https://php.net/)
+[![CI Status](https://github.com/sebastianbergmann/phpunit/workflows/CI/badge.svg?branch=9.5&event=push)](https://phpunit.de/build-status.html)
+[![Type Coverage](https://shepherd.dev/github/sebastianbergmann/phpunit/coverage.svg)](https://shepherd.dev/github/sebastianbergmann/phpunit)
+
+## Installation
+
+We distribute a [PHP Archive (PHAR)](https://php.net/phar) that has all required (as well as some optional) dependencies of PHPUnit 9.5 bundled in a single file:
+
+```bash
+$ wget https://phar.phpunit.de/phpunit-9.5.phar
+
+$ php phpunit-9.5.phar --version
+```
+
+Alternatively, you may use [Composer](https://getcomposer.org/) to download and install PHPUnit as well as its dependencies. Please refer to the "[Getting Started](https://phpunit.de/getting-started-with-phpunit.html)" guide for details on how to install PHPUnit.
+
+## Contribute
+
+Please refer to [CONTRIBUTING.md](https://github.com/sebastianbergmann/phpunit/blob/master/.github/CONTRIBUTING.md) for information on how to contribute to PHPUnit and its related projects.
+
+## List of Contributors
+
+Thanks to everyone who has contributed to PHPUnit! You can find a detailed list of contributors on every PHPUnit related package on GitHub. This list shows only the major components:
+
+* [PHPUnit](https://github.com/sebastianbergmann/phpunit/graphs/contributors)
+* [php-code-coverage](https://github.com/sebastianbergmann/php-code-coverage/graphs/contributors)
+
+A very special thanks to everyone who has contributed to the documentation and helps maintain the translations:
+
+* [English](https://github.com/sebastianbergmann/phpunit-documentation-english/graphs/contributors)
+* [Spanish](https://github.com/sebastianbergmann/phpunit-documentation-spanish/graphs/contributors)
+* [French](https://github.com/sebastianbergmann/phpunit-documentation-french/graphs/contributors)
+* [Japanese](https://github.com/sebastianbergmann/phpunit-documentation-japanese/graphs/contributors)
+* [Brazilian Portuguese](https://github.com/sebastianbergmann/phpunit-documentation-brazilian-portuguese/graphs/contributors)
+* [Simplified Chinese](https://github.com/sebastianbergmann/phpunit-documentation-chinese/graphs/contributors)
+
diff --git a/vendor/phpunit/phpunit/composer.json b/vendor/phpunit/phpunit/composer.json
new file mode 100644
index 0000000000000000000000000000000000000000..fd6461fc36040c46488595698b7ed877c430d8b8
--- /dev/null
+++ b/vendor/phpunit/phpunit/composer.json
@@ -0,0 +1,94 @@
+{
+    "name": "phpunit/phpunit",
+    "description": "The PHP Unit Testing framework.",
+    "type": "library",
+    "keywords": [
+        "phpunit",
+        "xunit",
+        "testing"
+    ],
+    "homepage": "https://phpunit.de/",
+    "license": "BSD-3-Clause",
+    "authors": [
+        {
+            "name": "Sebastian Bergmann",
+            "email": "sebastian@phpunit.de",
+            "role": "lead"
+        }
+    ],
+    "support": {
+        "issues": "https://github.com/sebastianbergmann/phpunit/issues"
+    },
+    "prefer-stable": true,
+    "require": {
+        "php": ">=7.3",
+        "ext-dom": "*",
+        "ext-json": "*",
+        "ext-libxml": "*",
+        "ext-mbstring": "*",
+        "ext-xml": "*",
+        "ext-xmlwriter": "*",
+        "doctrine/instantiator": "^1.3.1",
+        "myclabs/deep-copy": "^1.10.1",
+        "phar-io/manifest": "^2.0.1",
+        "phar-io/version": "^3.0.2",
+        "phpspec/prophecy": "^1.12.1",
+        "phpunit/php-code-coverage": "^9.2.3",
+        "phpunit/php-file-iterator": "^3.0.5",
+        "phpunit/php-invoker": "^3.1.1",
+        "phpunit/php-text-template": "^2.0.3",
+        "phpunit/php-timer": "^5.0.2",
+        "sebastian/cli-parser": "^1.0.1",
+        "sebastian/code-unit": "^1.0.6",
+        "sebastian/comparator": "^4.0.5",
+        "sebastian/diff": "^4.0.3",
+        "sebastian/environment": "^5.1.3",
+        "sebastian/exporter": "^4.0.3",
+        "sebastian/global-state": "^5.0.1",
+        "sebastian/object-enumerator": "^4.0.3",
+        "sebastian/resource-operations": "^3.0.3",
+        "sebastian/type": "^2.3",
+        "sebastian/version": "^3.0.2"
+    },
+    "require-dev": {
+        "ext-PDO": "*",
+        "phpspec/prophecy-phpunit": "^2.0.1"
+    },
+    "config": {
+        "platform": {
+            "php": "7.3.0"
+        },
+        "optimize-autoloader": true,
+        "sort-packages": true
+    },
+    "suggest": {
+        "ext-soap": "*",
+        "ext-xdebug": "*"
+    },
+    "bin": [
+        "phpunit"
+    ],
+    "autoload": {
+        "classmap": [
+            "src/"
+        ],
+        "files": [
+            "src/Framework/Assert/Functions.php"
+        ]
+    },
+    "autoload-dev": {
+        "classmap": [
+            "tests/"
+        ],
+        "files": [
+            "tests/_files/CoverageNamespacedFunctionTest.php",
+            "tests/_files/CoveredFunction.php",
+            "tests/_files/NamespaceCoveredFunction.php"
+        ]
+    },
+    "extra": {
+        "branch-alias": {
+            "dev-master": "9.5-dev"
+        }
+    }
+}
diff --git a/vendor/phpunit/phpunit/phpunit b/vendor/phpunit/phpunit/phpunit
new file mode 100755
index 0000000000000000000000000000000000000000..a4553367a0434737d82b89e76fcac8acb172b22a
--- /dev/null
+++ b/vendor/phpunit/phpunit/phpunit
@@ -0,0 +1,61 @@
+#!/usr/bin/env php
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+if (version_compare('7.3.0', PHP_VERSION, '>')) {
+    fwrite(
+        STDERR,
+        sprintf(
+            'This version of PHPUnit requires PHP >= 7.3.' . PHP_EOL .
+            'You are using PHP %s (%s).' . PHP_EOL,
+            PHP_VERSION,
+            PHP_BINARY
+        )
+    );
+
+    die(1);
+}
+
+if (!ini_get('date.timezone')) {
+    ini_set('date.timezone', 'UTC');
+}
+
+foreach (array(__DIR__ . '/../../autoload.php', __DIR__ . '/../vendor/autoload.php', __DIR__ . '/vendor/autoload.php') as $file) {
+    if (file_exists($file)) {
+        define('PHPUNIT_COMPOSER_INSTALL', $file);
+
+        break;
+    }
+}
+
+unset($file);
+
+if (!defined('PHPUNIT_COMPOSER_INSTALL')) {
+    fwrite(
+        STDERR,
+        'You need to set up the project dependencies using Composer:' . PHP_EOL . PHP_EOL .
+        '    composer install' . PHP_EOL . PHP_EOL .
+        'You can learn all about Composer on https://getcomposer.org/.' . PHP_EOL
+    );
+
+    die(1);
+}
+
+$options = getopt('', array('prepend:'));
+
+if (isset($options['prepend'])) {
+    require $options['prepend'];
+}
+
+unset($options);
+
+require PHPUNIT_COMPOSER_INSTALL;
+
+PHPUnit\TextUI\Command::main();
diff --git a/vendor/phpunit/phpunit/phpunit.xsd b/vendor/phpunit/phpunit/phpunit.xsd
new file mode 100644
index 0000000000000000000000000000000000000000..3785d21fef7737d158257360a3a14d2500efc215
--- /dev/null
+++ b/vendor/phpunit/phpunit/phpunit.xsd
@@ -0,0 +1,328 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
+    <xs:annotation>
+        <xs:documentation source="https://phpunit.de/documentation.html">
+            This Schema file defines the rules by which the XML configuration file of PHPUnit 9.5 may be structured.
+        </xs:documentation>
+        <xs:appinfo source="https://phpunit.de/documentation.html"/>
+    </xs:annotation>
+    <xs:element name="phpunit" type="phpUnitType">
+        <xs:annotation>
+            <xs:documentation>Root Element</xs:documentation>
+        </xs:annotation>
+    </xs:element>
+    <xs:complexType name="coverageType">
+        <xs:all>
+            <xs:element name="include" minOccurs="0" maxOccurs="1">
+                <xs:complexType>
+                    <xs:group ref="pathGroup"/>
+                </xs:complexType>
+            </xs:element>
+            <xs:element name="exclude" minOccurs="0" maxOccurs="1">
+                <xs:complexType>
+                    <xs:group ref="pathGroup"/>
+                </xs:complexType>
+            </xs:element>
+            <xs:element name="report" minOccurs="0" maxOccurs="1">
+                <xs:complexType>
+                    <xs:group ref="coverageReportGroup"/>
+                </xs:complexType>
+            </xs:element>
+        </xs:all>
+        <xs:attribute name="cacheDirectory" type="xs:anyURI"/>
+        <xs:attribute name="pathCoverage" type="xs:boolean" default="false"/>
+        <xs:attribute name="includeUncoveredFiles" type="xs:boolean" default="true"/>
+        <xs:attribute name="processUncoveredFiles" type="xs:boolean" default="false"/>
+        <xs:attribute name="ignoreDeprecatedCodeUnits" type="xs:boolean" default="false"/>
+        <xs:attribute name="disableCodeCoverageIgnore" type="xs:boolean" default="false"/>
+    </xs:complexType>
+    <xs:complexType name="loggingType">
+        <xs:group ref="loggingGroup"/>
+    </xs:complexType>
+    <xs:complexType name="groupsType">
+        <xs:choice>
+            <xs:sequence>
+                <xs:element name="include" type="groupType"/>
+                <xs:element name="exclude" type="groupType" minOccurs="0"/>
+            </xs:sequence>
+            <xs:sequence>
+                <xs:element name="exclude" type="groupType"/>
+            </xs:sequence>
+        </xs:choice>
+    </xs:complexType>
+    <xs:complexType name="groupType">
+        <xs:sequence>
+            <xs:element name="group" type="xs:string" maxOccurs="unbounded"/>
+        </xs:sequence>
+    </xs:complexType>
+    <xs:complexType name="extensionsType">
+        <xs:sequence>
+            <xs:element name="extension" type="objectType" maxOccurs="unbounded"/>
+        </xs:sequence>
+    </xs:complexType>
+    <xs:complexType name="listenersType">
+        <xs:sequence>
+            <xs:element name="listener" type="objectType" maxOccurs="unbounded"/>
+        </xs:sequence>
+    </xs:complexType>
+    <xs:complexType name="objectType">
+        <xs:sequence>
+            <xs:element name="arguments" minOccurs="0">
+                <xs:complexType>
+                    <xs:group ref="argumentsGroup"/>
+                </xs:complexType>
+            </xs:element>
+        </xs:sequence>
+        <xs:attribute name="class" type="xs:string" use="required"/>
+        <xs:attribute name="file" type="xs:anyURI"/>
+    </xs:complexType>
+    <xs:complexType name="arrayType">
+        <xs:sequence>
+            <xs:element name="element" type="argumentType" minOccurs="0" maxOccurs="unbounded"/>
+        </xs:sequence>
+    </xs:complexType>
+    <xs:complexType name="argumentType">
+        <xs:group ref="argumentChoice"/>
+        <xs:attribute name="key" use="required"/>
+    </xs:complexType>
+    <xs:group name="argumentsGroup">
+        <xs:sequence>
+            <xs:choice minOccurs="0" maxOccurs="unbounded">
+                <xs:element name="array" type="arrayType" />
+                <xs:element name="integer" type="xs:integer" />
+                <xs:element name="string" type="xs:string" />
+                <xs:element name="double" type="xs:double" />
+                <xs:element name="null" />
+                <xs:element name="object" type="objectType" />
+                <xs:element name="file" type="xs:anyURI" />
+                <xs:element name="directory" type="xs:anyURI" />
+                <xs:element name="boolean" type="xs:boolean" />
+            </xs:choice>
+        </xs:sequence>
+    </xs:group>
+    <xs:group name="argumentChoice">
+        <xs:choice>
+            <xs:element name="array" type="arrayType" minOccurs="0" maxOccurs="unbounded"/>
+            <xs:element name="integer" type="xs:integer" minOccurs="0" maxOccurs="unbounded"/>
+            <xs:element name="string" type="xs:string" minOccurs="0" maxOccurs="unbounded"/>
+            <xs:element name="double" type="xs:double" minOccurs="0" maxOccurs="unbounded"/>
+            <xs:element name="null" minOccurs="0" maxOccurs="unbounded"/>
+            <xs:element name="object" type="objectType" minOccurs="0" maxOccurs="unbounded"/>
+            <xs:element name="file" type="xs:anyURI" minOccurs="0" maxOccurs="unbounded"/>
+            <xs:element name="directory" type="xs:anyURI" minOccurs="0" maxOccurs="unbounded"/>
+            <xs:element name="boolean" type="xs:boolean" minOccurs="0" maxOccurs="unbounded"/>
+        </xs:choice>
+    </xs:group>
+    <xs:simpleType name="columnsType">
+        <xs:union>
+            <xs:simpleType>
+                <xs:restriction base="xs:integer"/>
+            </xs:simpleType>
+            <xs:simpleType>
+                <xs:restriction base="xs:string">
+                    <xs:enumeration value="max"/>
+                </xs:restriction>
+            </xs:simpleType>
+        </xs:union>
+    </xs:simpleType>
+    <xs:group name="pathGroup">
+        <xs:sequence>
+            <xs:choice minOccurs="0" maxOccurs="unbounded">
+                <xs:element name="directory" type="directoryFilterType"/>
+                <xs:element name="file" type="fileFilterType"/>
+            </xs:choice>
+        </xs:sequence>
+    </xs:group>
+    <xs:complexType name="directoryFilterType">
+        <xs:simpleContent>
+            <xs:extension base="xs:anyURI">
+                <xs:attribute type="xs:string" name="prefix" default=""/>
+                <xs:attribute type="xs:string" name="suffix" default="Test.php"/>
+                <xs:attributeGroup ref="phpVersionGroup"/>
+            </xs:extension>
+        </xs:simpleContent>
+    </xs:complexType>
+    <xs:simpleType name="executionOrderType">
+        <xs:restriction base="xs:string">
+            <xs:enumeration value="default"/>
+            <xs:enumeration value="defects"/>
+            <xs:enumeration value="depends"/>
+            <xs:enumeration value="depends,defects"/>
+            <xs:enumeration value="depends,duration"/>
+            <xs:enumeration value="depends,random"/>
+            <xs:enumeration value="depends,reverse"/>
+            <xs:enumeration value="depends,size"/>
+            <xs:enumeration value="duration"/>
+            <xs:enumeration value="no-depends"/>
+            <xs:enumeration value="no-depends,defects"/>
+            <xs:enumeration value="no-depends,duration"/>
+            <xs:enumeration value="no-depends,random"/>
+            <xs:enumeration value="no-depends,reverse"/>
+            <xs:enumeration value="no-depends,size"/>
+            <xs:enumeration value="random"/>
+            <xs:enumeration value="reverse"/>
+            <xs:enumeration value="size"/>
+        </xs:restriction>
+    </xs:simpleType>
+    <xs:complexType name="fileFilterType">
+        <xs:simpleContent>
+            <xs:extension base="xs:anyURI">
+                <xs:attributeGroup ref="phpVersionGroup"/>
+            </xs:extension>
+        </xs:simpleContent>
+    </xs:complexType>
+    <xs:attributeGroup name="phpVersionGroup">
+        <xs:attribute name="phpVersion" type="xs:string" default="5.3.0"/>
+        <xs:attribute name="phpVersionOperator" type="xs:string" default="&gt;="/>
+    </xs:attributeGroup>
+    <xs:complexType name="phpType">
+        <xs:sequence>
+            <xs:choice maxOccurs="unbounded">
+                <xs:element name="includePath" type="xs:anyURI" minOccurs="0" maxOccurs="unbounded"/>
+                <xs:element name="ini" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/>
+                <xs:element name="const" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/>
+                <xs:element name="var" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/>
+                <xs:element name="env" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/>
+                <xs:element name="post" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/>
+                <xs:element name="get" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/>
+                <xs:element name="cookie" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/>
+                <xs:element name="server" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/>
+                <xs:element name="files" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/>
+                <xs:element name="request" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/>
+            </xs:choice>
+        </xs:sequence>
+    </xs:complexType>
+    <xs:complexType name="namedValueType">
+        <xs:attribute name="name" use="required" type="xs:string"/>
+        <xs:attribute name="value" use="required" type="xs:anySimpleType"/>
+        <xs:attribute name="verbatim" use="optional" type="xs:boolean"/>
+        <xs:attribute name="force" use="optional" type="xs:boolean"/>
+    </xs:complexType>
+    <xs:complexType name="phpUnitType">
+        <xs:annotation>
+            <xs:documentation>The main type specifying the document structure</xs:documentation>
+        </xs:annotation>
+        <xs:group ref="configGroup"/>
+        <xs:attributeGroup ref="configAttributeGroup"/>
+    </xs:complexType>
+    <xs:attributeGroup name="configAttributeGroup">
+        <xs:attribute name="backupGlobals" type="xs:boolean" default="false"/>
+        <xs:attribute name="backupStaticAttributes" type="xs:boolean" default="false"/>
+        <xs:attribute name="bootstrap" type="xs:anyURI"/>
+        <xs:attribute name="cacheResult" type="xs:boolean" default="true"/>
+        <xs:attribute name="cacheResultFile" type="xs:anyURI"/>
+        <xs:attribute name="colors" type="xs:boolean" default="false"/>
+        <xs:attribute name="columns" type="columnsType" default="80"/>
+        <xs:attribute name="convertDeprecationsToExceptions" type="xs:boolean" default="true"/>
+        <xs:attribute name="convertErrorsToExceptions" type="xs:boolean" default="true"/>
+        <xs:attribute name="convertNoticesToExceptions" type="xs:boolean" default="true"/>
+        <xs:attribute name="convertWarningsToExceptions" type="xs:boolean" default="true"/>
+        <xs:attribute name="forceCoversAnnotation" type="xs:boolean" default="false"/>
+        <xs:attribute name="printerClass" type="xs:string" default="PHPUnit\TextUI\DefaultResultPrinter"/>
+        <xs:attribute name="printerFile" type="xs:anyURI"/>
+        <xs:attribute name="processIsolation" type="xs:boolean" default="false"/>
+        <xs:attribute name="stopOnDefect" type="xs:boolean" default="false"/>
+        <xs:attribute name="stopOnError" type="xs:boolean" default="false"/>
+        <xs:attribute name="stopOnFailure" type="xs:boolean" default="false"/>
+        <xs:attribute name="stopOnWarning" type="xs:boolean" default="false"/>
+        <xs:attribute name="stopOnIncomplete" type="xs:boolean" default="false"/>
+        <xs:attribute name="stopOnRisky" type="xs:boolean" default="false"/>
+        <xs:attribute name="stopOnSkipped" type="xs:boolean" default="false"/>
+        <xs:attribute name="failOnEmptyTestSuite" type="xs:boolean" default="false"/>
+        <xs:attribute name="failOnIncomplete" type="xs:boolean" default="false"/>
+        <xs:attribute name="failOnRisky" type="xs:boolean" default="false"/>
+        <xs:attribute name="failOnSkipped" type="xs:boolean" default="false"/>
+        <xs:attribute name="failOnWarning" type="xs:boolean" default="false"/>
+        <xs:attribute name="beStrictAboutChangesToGlobalState" type="xs:boolean" default="false"/>
+        <xs:attribute name="beStrictAboutOutputDuringTests" type="xs:boolean" default="false"/>
+        <xs:attribute name="beStrictAboutResourceUsageDuringSmallTests" type="xs:boolean" default="false"/>
+        <xs:attribute name="beStrictAboutTestsThatDoNotTestAnything" type="xs:boolean" default="true"/>
+        <xs:attribute name="beStrictAboutTodoAnnotatedTests" type="xs:boolean" default="false"/>
+        <xs:attribute name="beStrictAboutCoversAnnotation" type="xs:boolean" default="false"/>
+        <xs:attribute name="defaultTimeLimit" type="xs:integer" default="0"/>
+        <xs:attribute name="enforceTimeLimit" type="xs:boolean" default="false"/>
+        <xs:attribute name="timeoutForSmallTests" type="xs:integer" default="1"/>
+        <xs:attribute name="timeoutForMediumTests" type="xs:integer" default="10"/>
+        <xs:attribute name="timeoutForLargeTests" type="xs:integer" default="60"/>
+        <xs:attribute name="testSuiteLoaderClass" type="xs:string" default="PHPUnit\Runner\StandardTestSuiteLoader"/>
+        <xs:attribute name="testSuiteLoaderFile" type="xs:anyURI"/>
+        <xs:attribute name="defaultTestSuite" type="xs:string" default=""/>
+        <xs:attribute name="verbose" type="xs:boolean" default="false"/>
+        <xs:attribute name="testdox" type="xs:boolean" default="false"/>
+        <xs:attribute name="stderr" type="xs:boolean" default="false"/>
+        <xs:attribute name="reverseDefectList" type="xs:boolean" default="false"/>
+        <xs:attribute name="registerMockObjectsFromTestArgumentsRecursively" type="xs:boolean" default="false"/>
+        <xs:attribute name="extensionsDirectory" type="xs:string"/>
+        <xs:attribute name="executionOrder" type="executionOrderType" default="default"/>
+        <xs:attribute name="resolveDependencies" type="xs:boolean" default="true"/>
+        <xs:attribute name="noInteraction" type="xs:boolean" default="false"/>
+    </xs:attributeGroup>
+    <xs:group name="configGroup">
+        <xs:all>
+            <xs:element ref="testSuiteFacet" minOccurs="0"/>
+            <xs:element name="groups" type="groupsType" minOccurs="0"/>
+            <xs:element name="testdoxGroups" type="groupsType" minOccurs="0"/>
+            <xs:element name="coverage" type="coverageType" minOccurs="0"/>
+            <xs:element name="logging" type="loggingType" minOccurs="0"/>
+            <xs:element name="extensions" type="extensionsType" minOccurs="0"/>
+            <xs:element name="listeners" type="listenersType" minOccurs="0"/>
+            <xs:element name="php" type="phpType" minOccurs="0"/>
+        </xs:all>
+    </xs:group>
+    <xs:element name="testSuiteFacet" abstract="true"/>
+    <xs:element name="testsuite" type="testSuiteType" substitutionGroup="testSuiteFacet"/>
+    <xs:element name="testsuites" type="testSuitesType" substitutionGroup="testSuiteFacet"/>
+    <xs:complexType name="testSuitesType">
+        <xs:sequence>
+            <xs:element name="testsuite" type="testSuiteType" maxOccurs="unbounded"/>
+        </xs:sequence>
+    </xs:complexType>
+    <xs:complexType name="testSuiteType">
+        <xs:sequence>
+            <xs:group ref="pathGroup"/>
+            <xs:element name="exclude" type="xs:anyURI" minOccurs="0" maxOccurs="unbounded"/>
+        </xs:sequence>
+        <xs:attribute name="name" type="xs:string" use="required"/>
+    </xs:complexType>
+    <xs:group name="coverageReportGroup">
+        <xs:all>
+            <xs:element name="clover" type="logToFileType" minOccurs="0"/>
+            <xs:element name="cobertura" type="logToFileType" minOccurs="0"/>
+            <xs:element name="crap4j" type="coverageReportCrap4JType" minOccurs="0" />
+            <xs:element name="html" type="coverageReportHtmlType" minOccurs="0" />
+            <xs:element name="php" type="logToFileType" minOccurs="0" />
+            <xs:element name="text" type="coverageReportTextType" minOccurs="0" />
+            <xs:element name="xml" type="logToDirectoryType" minOccurs="0" />
+        </xs:all>
+    </xs:group>
+    <xs:group name="loggingGroup">
+        <xs:all>
+            <xs:element name="junit" type="logToFileType" minOccurs="0" />
+            <xs:element name="teamcity" type="logToFileType" minOccurs="0" />
+            <xs:element name="testdoxHtml" type="logToFileType" minOccurs="0" />
+            <xs:element name="testdoxText" type="logToFileType" minOccurs="0" />
+            <xs:element name="testdoxXml" type="logToFileType" minOccurs="0" />
+            <xs:element name="text" type="logToFileType" minOccurs="0"/>
+        </xs:all>
+    </xs:group>
+    <xs:complexType name="logToFileType">
+        <xs:attribute name="outputFile" type="xs:anyURI" use="required"/>
+    </xs:complexType>
+    <xs:complexType name="logToDirectoryType">
+        <xs:attribute name="outputDirectory" type="xs:anyURI" use="required"/>
+    </xs:complexType>
+    <xs:complexType name="coverageReportCrap4JType">
+        <xs:attribute name="outputFile" type="xs:anyURI" use="required"/>
+        <xs:attribute name="threshold" type="xs:integer"/>
+    </xs:complexType>
+    <xs:complexType name="coverageReportHtmlType">
+        <xs:attribute name="outputDirectory" type="xs:anyURI" use="required"/>
+        <xs:attribute name="lowUpperBound" type="xs:integer" default="50"/>
+        <xs:attribute name="highLowerBound" type="xs:integer" default="90"/>
+    </xs:complexType>
+    <xs:complexType name="coverageReportTextType">
+        <xs:attribute name="outputFile" type="xs:anyURI" use="required"/>
+        <xs:attribute name="showUncoveredFiles" type="xs:boolean" default="false"/>
+        <xs:attribute name="showOnlySummary" type="xs:boolean" default="false"/>
+    </xs:complexType>
+</xs:schema>
diff --git a/vendor/phpunit/phpunit/schema/8.5.xsd b/vendor/phpunit/phpunit/schema/8.5.xsd
new file mode 100644
index 0000000000000000000000000000000000000000..29cfcf2be8c49378f98c309c83c40d632d188cd8
--- /dev/null
+++ b/vendor/phpunit/phpunit/schema/8.5.xsd
@@ -0,0 +1,317 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
+    <xs:annotation>
+        <xs:documentation source="https://phpunit.de/documentation.html">
+            This Schema file defines the rules by which the XML configuration file of PHPUnit 8.5 may be structured.
+        </xs:documentation>
+        <xs:appinfo source="https://phpunit.de/documentation.html"/>
+    </xs:annotation>
+    <xs:element name="phpunit" type="phpUnitType">
+        <xs:annotation>
+            <xs:documentation>Root Element</xs:documentation>
+        </xs:annotation>
+    </xs:element>
+    <xs:complexType name="filtersType">
+        <xs:sequence>
+            <xs:element name="whitelist" type="whiteListType" minOccurs="0"/>
+        </xs:sequence>
+    </xs:complexType>
+    <xs:complexType name="filterType">
+        <xs:sequence>
+            <xs:choice maxOccurs="unbounded" minOccurs="0">
+                <xs:group ref="pathGroup"/>
+                <xs:element name="exclude">
+                    <xs:complexType>
+                        <xs:group ref="pathGroup"/>
+                    </xs:complexType>
+                </xs:element>
+            </xs:choice>
+        </xs:sequence>
+    </xs:complexType>
+    <xs:complexType name="whiteListType">
+        <xs:complexContent>
+            <xs:extension base="filterType">
+                <xs:attribute name="addUncoveredFilesFromWhitelist" default="true" type="xs:boolean"/>
+                <xs:attribute name="processUncoveredFilesFromWhitelist" default="false" type="xs:boolean"/>
+            </xs:extension>
+        </xs:complexContent>
+    </xs:complexType>
+    <xs:complexType name="groupsType">
+        <xs:choice>
+            <xs:sequence>
+                <xs:element name="include" type="groupType"/>
+                <xs:element name="exclude" type="groupType" minOccurs="0"/>
+            </xs:sequence>
+            <xs:sequence>
+                <xs:element name="exclude" type="groupType"/>
+            </xs:sequence>
+        </xs:choice>
+    </xs:complexType>
+    <xs:complexType name="groupType">
+        <xs:sequence>
+            <xs:element name="group" type="xs:string" maxOccurs="unbounded"/>
+        </xs:sequence>
+    </xs:complexType>
+    <xs:complexType name="extensionsType">
+        <xs:sequence>
+            <xs:element name="extension" type="objectType" maxOccurs="unbounded"/>
+        </xs:sequence>
+    </xs:complexType>
+    <xs:complexType name="listenersType">
+        <xs:sequence>
+            <xs:element name="listener" type="objectType" maxOccurs="unbounded"/>
+        </xs:sequence>
+    </xs:complexType>
+    <xs:complexType name="objectType">
+        <xs:sequence>
+            <xs:element name="arguments" minOccurs="0">
+                <xs:complexType>
+                    <xs:group ref="argumentsGroup"/>
+                </xs:complexType>
+            </xs:element>
+        </xs:sequence>
+        <xs:attribute name="class" type="xs:string" use="required"/>
+        <xs:attribute name="file" type="xs:anyURI"/>
+    </xs:complexType>
+    <xs:complexType name="arrayType">
+        <xs:sequence>
+            <xs:element name="element" type="argumentType" minOccurs="0" maxOccurs="unbounded"/>
+        </xs:sequence>
+    </xs:complexType>
+    <xs:complexType name="argumentType">
+        <xs:group ref="argumentChoice"/>
+        <xs:attribute name="key" use="required"/>
+    </xs:complexType>
+    <xs:group name="argumentsGroup">
+        <xs:sequence>
+            <xs:choice minOccurs="0" maxOccurs="unbounded">
+                <xs:element name="array" type="arrayType" />
+                <xs:element name="integer" type="xs:integer" />
+                <xs:element name="string" type="xs:string" />
+                <xs:element name="double" type="xs:double" />
+                <xs:element name="null" />
+                <xs:element name="object" type="objectType" />
+                <xs:element name="file" type="xs:anyURI" />
+                <xs:element name="directory" type="xs:anyURI" />
+                <xs:element name="boolean" type="xs:boolean" />
+            </xs:choice>
+        </xs:sequence>
+    </xs:group>
+    <xs:group name="argumentChoice">
+        <xs:choice>
+            <xs:element name="array" type="arrayType" minOccurs="0" maxOccurs="unbounded"/>
+            <xs:element name="integer" type="xs:integer" minOccurs="0" maxOccurs="unbounded"/>
+            <xs:element name="string" type="xs:string" minOccurs="0" maxOccurs="unbounded"/>
+            <xs:element name="double" type="xs:double" minOccurs="0" maxOccurs="unbounded"/>
+            <xs:element name="null" minOccurs="0" maxOccurs="unbounded"/>
+            <xs:element name="object" type="objectType" minOccurs="0" maxOccurs="unbounded"/>
+            <xs:element name="file" type="xs:anyURI" minOccurs="0" maxOccurs="unbounded"/>
+            <xs:element name="directory" type="xs:anyURI" minOccurs="0" maxOccurs="unbounded"/>
+            <xs:element name="boolean" type="xs:boolean" minOccurs="0" maxOccurs="unbounded"/>
+        </xs:choice>
+    </xs:group>
+    <xs:simpleType name="columnsType">
+        <xs:union>
+            <xs:simpleType>
+                <xs:restriction base="xs:integer"/>
+            </xs:simpleType>
+            <xs:simpleType>
+                <xs:restriction base="xs:string">
+                    <xs:enumeration value="max"/>
+                </xs:restriction>
+            </xs:simpleType>
+        </xs:union>
+    </xs:simpleType>
+    <xs:complexType name="loggersType">
+        <xs:sequence>
+            <xs:element name="log" type="loggerType" maxOccurs="unbounded"/>
+        </xs:sequence>
+    </xs:complexType>
+    <xs:complexType name="loggerType">
+        <xs:attribute name="type">
+            <xs:simpleType>
+                <xs:restriction base="xs:string">
+                    <xs:enumeration value="coverage-html"/>
+                    <xs:enumeration value="coverage-text"/>
+                    <xs:enumeration value="coverage-clover"/>
+                    <xs:enumeration value="coverage-crap4j"/>
+                    <xs:enumeration value="coverage-xml"/>
+                    <xs:enumeration value="coverage-php"/>
+                    <xs:enumeration value="json"/>
+                    <xs:enumeration value="plain"/>
+                    <xs:enumeration value="tap"/>
+                    <xs:enumeration value="teamcity"/>
+                    <xs:enumeration value="junit"/>
+                    <xs:enumeration value="testdox-html"/>
+                    <xs:enumeration value="testdox-text"/>
+                    <xs:enumeration value="testdox-xml"/>
+                </xs:restriction>
+            </xs:simpleType>
+        </xs:attribute>
+        <xs:attribute name="target" type="xs:anyURI"/>
+        <xs:attribute name="lowUpperBound" type="xs:nonNegativeInteger" default="50"/>
+        <xs:attribute name="highLowerBound" type="xs:nonNegativeInteger" default="90"/>
+        <xs:attribute name="showUncoveredFiles" type="xs:boolean" default="false"/>
+        <xs:attribute name="showOnlySummary" type="xs:boolean" default="false"/>
+        <xs:attribute name="threshold" type="xs:nonNegativeInteger" default="30"/>
+    </xs:complexType>
+    <xs:group name="pathGroup">
+        <xs:sequence>
+            <xs:choice minOccurs="0" maxOccurs="unbounded">
+                <xs:element name="directory" type="directoryFilterType"/>
+                <xs:element name="file" type="fileFilterType"/>
+            </xs:choice>
+        </xs:sequence>
+    </xs:group>
+    <xs:complexType name="directoryFilterType">
+        <xs:simpleContent>
+            <xs:extension base="xs:anyURI">
+                <xs:attribute type="xs:string" name="prefix" default=""/>
+                <xs:attribute type="xs:string" name="suffix" default="Test.php"/>
+                <xs:attributeGroup ref="phpVersionGroup"/>
+            </xs:extension>
+        </xs:simpleContent>
+    </xs:complexType>
+    <xs:simpleType name="executionOrderType">
+        <xs:restriction base="xs:string">
+            <xs:enumeration value="default"/>
+            <xs:enumeration value="defects"/>
+            <xs:enumeration value="depends"/>
+            <xs:enumeration value="depends,defects"/>
+            <xs:enumeration value="depends,duration"/>
+            <xs:enumeration value="depends,random"/>
+            <xs:enumeration value="depends,reverse"/>
+            <xs:enumeration value="depends,size"/>
+            <xs:enumeration value="duration"/>
+            <xs:enumeration value="no-depends"/>
+            <xs:enumeration value="no-depends,defects"/>
+            <xs:enumeration value="no-depends,duration"/>
+            <xs:enumeration value="no-depends,random"/>
+            <xs:enumeration value="no-depends,reverse"/>
+            <xs:enumeration value="no-depends,size"/>
+            <xs:enumeration value="random"/>
+            <xs:enumeration value="reverse"/>
+            <xs:enumeration value="size"/>
+        </xs:restriction>
+    </xs:simpleType>
+    <xs:complexType name="fileFilterType">
+        <xs:simpleContent>
+            <xs:extension base="xs:anyURI">
+                <xs:attributeGroup ref="phpVersionGroup"/>
+            </xs:extension>
+        </xs:simpleContent>
+    </xs:complexType>
+    <xs:attributeGroup name="phpVersionGroup">
+        <xs:attribute name="phpVersion" type="xs:string" default="5.3.0"/>
+        <xs:attribute name="phpVersionOperator" type="xs:string" default="&gt;="/>
+    </xs:attributeGroup>
+    <xs:complexType name="phpType">
+        <xs:sequence>
+            <xs:choice maxOccurs="unbounded">
+                <xs:element name="includePath" type="xs:anyURI" minOccurs="0" maxOccurs="unbounded"/>
+                <xs:element name="ini" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/>
+                <xs:element name="const" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/>
+                <xs:element name="var" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/>
+                <xs:element name="env" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/>
+                <xs:element name="post" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/>
+                <xs:element name="get" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/>
+                <xs:element name="cookie" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/>
+                <xs:element name="server" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/>
+                <xs:element name="files" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/>
+                <xs:element name="request" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/>
+            </xs:choice>
+        </xs:sequence>
+    </xs:complexType>
+    <xs:complexType name="namedValueType">
+        <xs:attribute name="name" use="required" type="xs:string"/>
+        <xs:attribute name="value" use="required" type="xs:anySimpleType"/>
+        <xs:attribute name="verbatim" use="optional" type="xs:boolean"/>
+        <xs:attribute name="force" use="optional" type="xs:boolean"/>
+    </xs:complexType>
+    <xs:complexType name="phpUnitType">
+        <xs:annotation>
+            <xs:documentation>The main type specifying the document structure</xs:documentation>
+        </xs:annotation>
+        <xs:group ref="configGroup"/>
+        <xs:attributeGroup ref="configAttributeGroup"/>
+    </xs:complexType>
+    <xs:attributeGroup name="configAttributeGroup">
+        <xs:attribute name="backupGlobals" type="xs:boolean" default="false"/>
+        <xs:attribute name="backupStaticAttributes" type="xs:boolean" default="false"/>
+        <xs:attribute name="bootstrap" type="xs:anyURI"/>
+        <xs:attribute name="cacheResult" type="xs:boolean" default="true"/>
+        <xs:attribute name="cacheResultFile" type="xs:anyURI"/>
+        <xs:attribute name="cacheTokens" type="xs:boolean" default="false"/>
+        <xs:attribute name="colors" type="xs:boolean" default="false"/>
+        <xs:attribute name="columns" type="columnsType" default="80"/>
+        <xs:attribute name="convertDeprecationsToExceptions" type="xs:boolean" default="true"/>
+        <xs:attribute name="convertErrorsToExceptions" type="xs:boolean" default="true"/>
+        <xs:attribute name="convertNoticesToExceptions" type="xs:boolean" default="true"/>
+        <xs:attribute name="convertWarningsToExceptions" type="xs:boolean" default="true"/>
+        <xs:attribute name="disableCodeCoverageIgnore" type="xs:boolean" default="false"/>
+        <xs:attribute name="forceCoversAnnotation" type="xs:boolean" default="false"/>
+        <xs:attribute name="printerClass" type="xs:string" default="PHPUnit\TextUI\ResultPrinter"/>
+        <xs:attribute name="printerFile" type="xs:anyURI"/>
+        <xs:attribute name="processIsolation" type="xs:boolean" default="false"/>
+        <xs:attribute name="stopOnDefect" type="xs:boolean" default="false"/>
+        <xs:attribute name="stopOnError" type="xs:boolean" default="false"/>
+        <xs:attribute name="stopOnFailure" type="xs:boolean" default="false"/>
+        <xs:attribute name="stopOnWarning" type="xs:boolean" default="false"/>
+        <xs:attribute name="stopOnIncomplete" type="xs:boolean" default="false"/>
+        <xs:attribute name="stopOnRisky" type="xs:boolean" default="false"/>
+        <xs:attribute name="stopOnSkipped" type="xs:boolean" default="false"/>
+        <xs:attribute name="failOnRisky" type="xs:boolean" default="false"/>
+        <xs:attribute name="failOnWarning" type="xs:boolean" default="false"/>
+        <xs:attribute name="beStrictAboutChangesToGlobalState" type="xs:boolean" default="false"/>
+        <xs:attribute name="beStrictAboutOutputDuringTests" type="xs:boolean" default="false"/>
+        <xs:attribute name="beStrictAboutResourceUsageDuringSmallTests" type="xs:boolean" default="false"/>
+        <xs:attribute name="beStrictAboutTestsThatDoNotTestAnything" type="xs:boolean" default="true"/>
+        <xs:attribute name="beStrictAboutTodoAnnotatedTests" type="xs:boolean" default="false"/>
+        <xs:attribute name="beStrictAboutCoversAnnotation" type="xs:boolean" default="false"/>
+        <xs:attribute name="defaultTimeLimit" type="xs:integer" default="0"/>
+        <xs:attribute name="enforceTimeLimit" type="xs:boolean" default="false"/>
+        <xs:attribute name="ignoreDeprecatedCodeUnitsFromCodeCoverage" type="xs:boolean" default="false"/>
+        <xs:attribute name="timeoutForSmallTests" type="xs:integer" default="1"/>
+        <xs:attribute name="timeoutForMediumTests" type="xs:integer" default="10"/>
+        <xs:attribute name="timeoutForLargeTests" type="xs:integer" default="60"/>
+        <xs:attribute name="testSuiteLoaderClass" type="xs:string" default="PHPUnit\Runner\StandardTestSuiteLoader"/>
+        <xs:attribute name="testSuiteLoaderFile" type="xs:anyURI"/>
+        <xs:attribute name="defaultTestSuite" type="xs:string" default=""/>
+        <xs:attribute name="verbose" type="xs:boolean" default="false"/>
+        <xs:attribute name="testdox" type="xs:boolean" default="false"/>
+        <xs:attribute name="stderr" type="xs:boolean" default="false"/>
+        <xs:attribute name="reverseDefectList" type="xs:boolean" default="false"/>
+        <xs:attribute name="registerMockObjectsFromTestArgumentsRecursively" type="xs:boolean" default="false"/>
+        <xs:attribute name="extensionsDirectory" type="xs:string"/>
+        <xs:attribute name="executionOrder" type="executionOrderType" default="default"/>
+        <xs:attribute name="resolveDependencies" type="xs:boolean" default="true"/>
+        <xs:attribute name="noInteraction" type="xs:boolean" default="false"/>
+    </xs:attributeGroup>
+    <xs:group name="configGroup">
+        <xs:all>
+            <xs:element ref="testSuiteFacet" minOccurs="0"/>
+            <xs:element name="groups" type="groupsType" minOccurs="0"/>
+            <xs:element name="testdoxGroups" type="groupsType" minOccurs="0"/>
+            <xs:element name="filter" type="filtersType" minOccurs="0"/>
+            <xs:element name="logging" type="loggersType" minOccurs="0"/>
+            <xs:element name="extensions" type="extensionsType" minOccurs="0"/>
+            <xs:element name="listeners" type="listenersType" minOccurs="0"/>
+            <xs:element name="php" type="phpType" minOccurs="0"/>
+        </xs:all>
+    </xs:group>
+    <xs:element name="testSuiteFacet" abstract="true"/>
+    <xs:element name="testsuite" type="testSuiteType" substitutionGroup="testSuiteFacet"/>
+    <xs:element name="testsuites" type="testSuitesType" substitutionGroup="testSuiteFacet"/>
+    <xs:complexType name="testSuitesType">
+        <xs:sequence>
+            <xs:element name="testsuite" type="testSuiteType" maxOccurs="unbounded"/>
+        </xs:sequence>
+    </xs:complexType>
+    <xs:complexType name="testSuiteType">
+        <xs:sequence>
+            <xs:group ref="pathGroup"/>
+            <xs:element name="exclude" type="xs:anyURI" minOccurs="0" maxOccurs="unbounded"/>
+        </xs:sequence>
+        <xs:attribute name="name" type="xs:string" use="required"/>
+    </xs:complexType>
+</xs:schema>
diff --git a/vendor/phpunit/phpunit/schema/9.2.xsd b/vendor/phpunit/phpunit/schema/9.2.xsd
new file mode 100644
index 0000000000000000000000000000000000000000..97e86d3ab35093171215284b402f33cda7a66d26
--- /dev/null
+++ b/vendor/phpunit/phpunit/schema/9.2.xsd
@@ -0,0 +1,317 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
+    <xs:annotation>
+        <xs:documentation source="https://phpunit.de/documentation.html">
+            This Schema file defines the rules by which the XML configuration file of PHPUnit 9.2 may be structured.
+        </xs:documentation>
+        <xs:appinfo source="https://phpunit.de/documentation.html"/>
+    </xs:annotation>
+    <xs:element name="phpunit" type="phpUnitType">
+        <xs:annotation>
+            <xs:documentation>Root Element</xs:documentation>
+        </xs:annotation>
+    </xs:element>
+    <xs:complexType name="filtersType">
+        <xs:sequence>
+            <xs:element name="whitelist" type="whiteListType" minOccurs="0"/>
+        </xs:sequence>
+    </xs:complexType>
+    <xs:complexType name="filterType">
+        <xs:sequence>
+            <xs:choice maxOccurs="unbounded" minOccurs="0">
+                <xs:group ref="pathGroup"/>
+                <xs:element name="exclude">
+                    <xs:complexType>
+                        <xs:group ref="pathGroup"/>
+                    </xs:complexType>
+                </xs:element>
+            </xs:choice>
+        </xs:sequence>
+    </xs:complexType>
+    <xs:complexType name="whiteListType">
+        <xs:complexContent>
+            <xs:extension base="filterType">
+                <xs:attribute name="addUncoveredFilesFromWhitelist" default="true" type="xs:boolean"/>
+                <xs:attribute name="processUncoveredFilesFromWhitelist" default="false" type="xs:boolean"/>
+            </xs:extension>
+        </xs:complexContent>
+    </xs:complexType>
+    <xs:complexType name="groupsType">
+        <xs:choice>
+            <xs:sequence>
+                <xs:element name="include" type="groupType"/>
+                <xs:element name="exclude" type="groupType" minOccurs="0"/>
+            </xs:sequence>
+            <xs:sequence>
+                <xs:element name="exclude" type="groupType"/>
+            </xs:sequence>
+        </xs:choice>
+    </xs:complexType>
+    <xs:complexType name="groupType">
+        <xs:sequence>
+            <xs:element name="group" type="xs:string" maxOccurs="unbounded"/>
+        </xs:sequence>
+    </xs:complexType>
+    <xs:complexType name="extensionsType">
+        <xs:sequence>
+            <xs:element name="extension" type="objectType" maxOccurs="unbounded"/>
+        </xs:sequence>
+    </xs:complexType>
+    <xs:complexType name="listenersType">
+        <xs:sequence>
+            <xs:element name="listener" type="objectType" maxOccurs="unbounded"/>
+        </xs:sequence>
+    </xs:complexType>
+    <xs:complexType name="objectType">
+        <xs:sequence>
+            <xs:element name="arguments" minOccurs="0">
+                <xs:complexType>
+                    <xs:group ref="argumentsGroup"/>
+                </xs:complexType>
+            </xs:element>
+        </xs:sequence>
+        <xs:attribute name="class" type="xs:string" use="required"/>
+        <xs:attribute name="file" type="xs:anyURI"/>
+    </xs:complexType>
+    <xs:complexType name="arrayType">
+        <xs:sequence>
+            <xs:element name="element" type="argumentType" minOccurs="0" maxOccurs="unbounded"/>
+        </xs:sequence>
+    </xs:complexType>
+    <xs:complexType name="argumentType">
+        <xs:group ref="argumentChoice"/>
+        <xs:attribute name="key" use="required"/>
+    </xs:complexType>
+    <xs:group name="argumentsGroup">
+        <xs:sequence>
+            <xs:choice minOccurs="0" maxOccurs="unbounded">
+                <xs:element name="array" type="arrayType" />
+                <xs:element name="integer" type="xs:integer" />
+                <xs:element name="string" type="xs:string" />
+                <xs:element name="double" type="xs:double" />
+                <xs:element name="null" />
+                <xs:element name="object" type="objectType" />
+                <xs:element name="file" type="xs:anyURI" />
+                <xs:element name="directory" type="xs:anyURI" />
+                <xs:element name="boolean" type="xs:boolean" />
+            </xs:choice>
+        </xs:sequence>
+    </xs:group>
+    <xs:group name="argumentChoice">
+        <xs:choice>
+            <xs:element name="array" type="arrayType" minOccurs="0" maxOccurs="unbounded"/>
+            <xs:element name="integer" type="xs:integer" minOccurs="0" maxOccurs="unbounded"/>
+            <xs:element name="string" type="xs:string" minOccurs="0" maxOccurs="unbounded"/>
+            <xs:element name="double" type="xs:double" minOccurs="0" maxOccurs="unbounded"/>
+            <xs:element name="null" minOccurs="0" maxOccurs="unbounded"/>
+            <xs:element name="object" type="objectType" minOccurs="0" maxOccurs="unbounded"/>
+            <xs:element name="file" type="xs:anyURI" minOccurs="0" maxOccurs="unbounded"/>
+            <xs:element name="directory" type="xs:anyURI" minOccurs="0" maxOccurs="unbounded"/>
+            <xs:element name="boolean" type="xs:boolean" minOccurs="0" maxOccurs="unbounded"/>
+        </xs:choice>
+    </xs:group>
+    <xs:simpleType name="columnsType">
+        <xs:union>
+            <xs:simpleType>
+                <xs:restriction base="xs:integer"/>
+            </xs:simpleType>
+            <xs:simpleType>
+                <xs:restriction base="xs:string">
+                    <xs:enumeration value="max"/>
+                </xs:restriction>
+            </xs:simpleType>
+        </xs:union>
+    </xs:simpleType>
+    <xs:complexType name="loggersType">
+        <xs:sequence>
+            <xs:element name="log" type="loggerType" maxOccurs="unbounded"/>
+        </xs:sequence>
+    </xs:complexType>
+    <xs:complexType name="loggerType">
+        <xs:attribute name="type">
+            <xs:simpleType>
+                <xs:restriction base="xs:string">
+                    <xs:enumeration value="coverage-html"/>
+                    <xs:enumeration value="coverage-text"/>
+                    <xs:enumeration value="coverage-clover"/>
+                    <xs:enumeration value="coverage-crap4j"/>
+                    <xs:enumeration value="coverage-xml"/>
+                    <xs:enumeration value="coverage-php"/>
+                    <xs:enumeration value="plain"/>
+                    <xs:enumeration value="teamcity"/>
+                    <xs:enumeration value="junit"/>
+                    <xs:enumeration value="testdox-html"/>
+                    <xs:enumeration value="testdox-text"/>
+                    <xs:enumeration value="testdox-xml"/>
+                </xs:restriction>
+            </xs:simpleType>
+        </xs:attribute>
+        <xs:attribute name="target" type="xs:anyURI"/>
+        <xs:attribute name="lowUpperBound" type="xs:nonNegativeInteger" default="50"/>
+        <xs:attribute name="highLowerBound" type="xs:nonNegativeInteger" default="90"/>
+        <xs:attribute name="showUncoveredFiles" type="xs:boolean" default="false"/>
+        <xs:attribute name="showOnlySummary" type="xs:boolean" default="false"/>
+        <xs:attribute name="threshold" type="xs:nonNegativeInteger" default="30"/>
+    </xs:complexType>
+    <xs:group name="pathGroup">
+        <xs:sequence>
+            <xs:choice minOccurs="0" maxOccurs="unbounded">
+                <xs:element name="directory" type="directoryFilterType"/>
+                <xs:element name="file" type="fileFilterType"/>
+            </xs:choice>
+        </xs:sequence>
+    </xs:group>
+    <xs:complexType name="directoryFilterType">
+        <xs:simpleContent>
+            <xs:extension base="xs:anyURI">
+                <xs:attribute type="xs:string" name="prefix" default=""/>
+                <xs:attribute type="xs:string" name="suffix" default="Test.php"/>
+                <xs:attributeGroup ref="phpVersionGroup"/>
+            </xs:extension>
+        </xs:simpleContent>
+    </xs:complexType>
+    <xs:simpleType name="executionOrderType">
+        <xs:restriction base="xs:string">
+            <xs:enumeration value="default"/>
+            <xs:enumeration value="defects"/>
+            <xs:enumeration value="depends"/>
+            <xs:enumeration value="depends,defects"/>
+            <xs:enumeration value="depends,duration"/>
+            <xs:enumeration value="depends,random"/>
+            <xs:enumeration value="depends,reverse"/>
+            <xs:enumeration value="depends,size"/>
+            <xs:enumeration value="duration"/>
+            <xs:enumeration value="no-depends"/>
+            <xs:enumeration value="no-depends,defects"/>
+            <xs:enumeration value="no-depends,duration"/>
+            <xs:enumeration value="no-depends,random"/>
+            <xs:enumeration value="no-depends,reverse"/>
+            <xs:enumeration value="no-depends,size"/>
+            <xs:enumeration value="random"/>
+            <xs:enumeration value="reverse"/>
+            <xs:enumeration value="size"/>
+        </xs:restriction>
+    </xs:simpleType>
+    <xs:complexType name="fileFilterType">
+        <xs:simpleContent>
+            <xs:extension base="xs:anyURI">
+                <xs:attributeGroup ref="phpVersionGroup"/>
+            </xs:extension>
+        </xs:simpleContent>
+    </xs:complexType>
+    <xs:attributeGroup name="phpVersionGroup">
+        <xs:attribute name="phpVersion" type="xs:string" default="5.3.0"/>
+        <xs:attribute name="phpVersionOperator" type="xs:string" default="&gt;="/>
+    </xs:attributeGroup>
+    <xs:complexType name="phpType">
+        <xs:sequence>
+            <xs:choice maxOccurs="unbounded">
+                <xs:element name="includePath" type="xs:anyURI" minOccurs="0" maxOccurs="unbounded"/>
+                <xs:element name="ini" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/>
+                <xs:element name="const" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/>
+                <xs:element name="var" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/>
+                <xs:element name="env" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/>
+                <xs:element name="post" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/>
+                <xs:element name="get" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/>
+                <xs:element name="cookie" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/>
+                <xs:element name="server" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/>
+                <xs:element name="files" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/>
+                <xs:element name="request" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/>
+            </xs:choice>
+        </xs:sequence>
+    </xs:complexType>
+    <xs:complexType name="namedValueType">
+        <xs:attribute name="name" use="required" type="xs:string"/>
+        <xs:attribute name="value" use="required" type="xs:anySimpleType"/>
+        <xs:attribute name="verbatim" use="optional" type="xs:boolean"/>
+        <xs:attribute name="force" use="optional" type="xs:boolean"/>
+    </xs:complexType>
+    <xs:complexType name="phpUnitType">
+        <xs:annotation>
+            <xs:documentation>The main type specifying the document structure</xs:documentation>
+        </xs:annotation>
+        <xs:group ref="configGroup"/>
+        <xs:attributeGroup ref="configAttributeGroup"/>
+    </xs:complexType>
+    <xs:attributeGroup name="configAttributeGroup">
+        <xs:attribute name="backupGlobals" type="xs:boolean" default="false"/>
+        <xs:attribute name="backupStaticAttributes" type="xs:boolean" default="false"/>
+        <xs:attribute name="bootstrap" type="xs:anyURI"/>
+        <xs:attribute name="cacheResult" type="xs:boolean" default="true"/>
+        <xs:attribute name="cacheResultFile" type="xs:anyURI"/>
+        <xs:attribute name="cacheTokens" type="xs:boolean" default="false"/>
+        <xs:attribute name="colors" type="xs:boolean" default="false"/>
+        <xs:attribute name="columns" type="columnsType" default="80"/>
+        <xs:attribute name="convertDeprecationsToExceptions" type="xs:boolean" default="true"/>
+        <xs:attribute name="convertErrorsToExceptions" type="xs:boolean" default="true"/>
+        <xs:attribute name="convertNoticesToExceptions" type="xs:boolean" default="true"/>
+        <xs:attribute name="convertWarningsToExceptions" type="xs:boolean" default="true"/>
+        <xs:attribute name="disableCodeCoverageIgnore" type="xs:boolean" default="false"/>
+        <xs:attribute name="forceCoversAnnotation" type="xs:boolean" default="false"/>
+        <xs:attribute name="printerClass" type="xs:string" default="PHPUnit\TextUI\ResultPrinter"/>
+        <xs:attribute name="printerFile" type="xs:anyURI"/>
+        <xs:attribute name="processIsolation" type="xs:boolean" default="false"/>
+        <xs:attribute name="stopOnDefect" type="xs:boolean" default="false"/>
+        <xs:attribute name="stopOnError" type="xs:boolean" default="false"/>
+        <xs:attribute name="stopOnFailure" type="xs:boolean" default="false"/>
+        <xs:attribute name="stopOnWarning" type="xs:boolean" default="false"/>
+        <xs:attribute name="stopOnIncomplete" type="xs:boolean" default="false"/>
+        <xs:attribute name="stopOnRisky" type="xs:boolean" default="false"/>
+        <xs:attribute name="stopOnSkipped" type="xs:boolean" default="false"/>
+        <xs:attribute name="failOnIncomplete" type="xs:boolean" default="false"/>
+        <xs:attribute name="failOnRisky" type="xs:boolean" default="false"/>
+        <xs:attribute name="failOnSkipped" type="xs:boolean" default="false"/>
+        <xs:attribute name="failOnWarning" type="xs:boolean" default="false"/>
+        <xs:attribute name="beStrictAboutChangesToGlobalState" type="xs:boolean" default="false"/>
+        <xs:attribute name="beStrictAboutOutputDuringTests" type="xs:boolean" default="false"/>
+        <xs:attribute name="beStrictAboutResourceUsageDuringSmallTests" type="xs:boolean" default="false"/>
+        <xs:attribute name="beStrictAboutTestsThatDoNotTestAnything" type="xs:boolean" default="true"/>
+        <xs:attribute name="beStrictAboutTodoAnnotatedTests" type="xs:boolean" default="false"/>
+        <xs:attribute name="beStrictAboutCoversAnnotation" type="xs:boolean" default="false"/>
+        <xs:attribute name="defaultTimeLimit" type="xs:integer" default="0"/>
+        <xs:attribute name="enforceTimeLimit" type="xs:boolean" default="false"/>
+        <xs:attribute name="ignoreDeprecatedCodeUnitsFromCodeCoverage" type="xs:boolean" default="false"/>
+        <xs:attribute name="timeoutForSmallTests" type="xs:integer" default="1"/>
+        <xs:attribute name="timeoutForMediumTests" type="xs:integer" default="10"/>
+        <xs:attribute name="timeoutForLargeTests" type="xs:integer" default="60"/>
+        <xs:attribute name="testSuiteLoaderClass" type="xs:string" default="PHPUnit\Runner\StandardTestSuiteLoader"/>
+        <xs:attribute name="testSuiteLoaderFile" type="xs:anyURI"/>
+        <xs:attribute name="defaultTestSuite" type="xs:string" default=""/>
+        <xs:attribute name="verbose" type="xs:boolean" default="false"/>
+        <xs:attribute name="testdox" type="xs:boolean" default="false"/>
+        <xs:attribute name="stderr" type="xs:boolean" default="false"/>
+        <xs:attribute name="reverseDefectList" type="xs:boolean" default="false"/>
+        <xs:attribute name="registerMockObjectsFromTestArgumentsRecursively" type="xs:boolean" default="false"/>
+        <xs:attribute name="extensionsDirectory" type="xs:string"/>
+        <xs:attribute name="executionOrder" type="executionOrderType" default="default"/>
+        <xs:attribute name="resolveDependencies" type="xs:boolean" default="true"/>
+        <xs:attribute name="noInteraction" type="xs:boolean" default="false"/>
+    </xs:attributeGroup>
+    <xs:group name="configGroup">
+        <xs:all>
+            <xs:element ref="testSuiteFacet" minOccurs="0"/>
+            <xs:element name="groups" type="groupsType" minOccurs="0"/>
+            <xs:element name="testdoxGroups" type="groupsType" minOccurs="0"/>
+            <xs:element name="filter" type="filtersType" minOccurs="0"/>
+            <xs:element name="logging" type="loggersType" minOccurs="0"/>
+            <xs:element name="extensions" type="extensionsType" minOccurs="0"/>
+            <xs:element name="listeners" type="listenersType" minOccurs="0"/>
+            <xs:element name="php" type="phpType" minOccurs="0"/>
+        </xs:all>
+    </xs:group>
+    <xs:element name="testSuiteFacet" abstract="true"/>
+    <xs:element name="testsuite" type="testSuiteType" substitutionGroup="testSuiteFacet"/>
+    <xs:element name="testsuites" type="testSuitesType" substitutionGroup="testSuiteFacet"/>
+    <xs:complexType name="testSuitesType">
+        <xs:sequence>
+            <xs:element name="testsuite" type="testSuiteType" maxOccurs="unbounded"/>
+        </xs:sequence>
+    </xs:complexType>
+    <xs:complexType name="testSuiteType">
+        <xs:sequence>
+            <xs:group ref="pathGroup"/>
+            <xs:element name="exclude" type="xs:anyURI" minOccurs="0" maxOccurs="unbounded"/>
+        </xs:sequence>
+        <xs:attribute name="name" type="xs:string" use="required"/>
+    </xs:complexType>
+</xs:schema>
diff --git a/vendor/phpunit/phpunit/src/Exception.php b/vendor/phpunit/phpunit/src/Exception.php
new file mode 100644
index 0000000000000000000000000000000000000000..4e7c33353b87aafcecc88198fe156a4d53517108
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Exception.php
@@ -0,0 +1,19 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit;
+
+use Throwable;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+interface Exception extends Throwable
+{
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/Assert.php b/vendor/phpunit/phpunit/src/Framework/Assert.php
new file mode 100644
index 0000000000000000000000000000000000000000..8053f28409365d3eb415f77cdf782f91a165d12a
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/Assert.php
@@ -0,0 +1,2854 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework;
+
+use const DEBUG_BACKTRACE_IGNORE_ARGS;
+use const PHP_EOL;
+use function array_shift;
+use function array_unshift;
+use function assert;
+use function class_exists;
+use function count;
+use function debug_backtrace;
+use function explode;
+use function file_get_contents;
+use function func_get_args;
+use function implode;
+use function interface_exists;
+use function is_array;
+use function is_bool;
+use function is_int;
+use function is_iterable;
+use function is_object;
+use function is_string;
+use function preg_match;
+use function preg_split;
+use function sprintf;
+use function strpos;
+use ArrayAccess;
+use Countable;
+use DOMAttr;
+use DOMDocument;
+use DOMElement;
+use PHPUnit\Framework\Constraint\ArrayHasKey;
+use PHPUnit\Framework\Constraint\Callback;
+use PHPUnit\Framework\Constraint\ClassHasAttribute;
+use PHPUnit\Framework\Constraint\ClassHasStaticAttribute;
+use PHPUnit\Framework\Constraint\Constraint;
+use PHPUnit\Framework\Constraint\Count;
+use PHPUnit\Framework\Constraint\DirectoryExists;
+use PHPUnit\Framework\Constraint\FileExists;
+use PHPUnit\Framework\Constraint\GreaterThan;
+use PHPUnit\Framework\Constraint\IsAnything;
+use PHPUnit\Framework\Constraint\IsEmpty;
+use PHPUnit\Framework\Constraint\IsEqual;
+use PHPUnit\Framework\Constraint\IsEqualCanonicalizing;
+use PHPUnit\Framework\Constraint\IsEqualIgnoringCase;
+use PHPUnit\Framework\Constraint\IsEqualWithDelta;
+use PHPUnit\Framework\Constraint\IsFalse;
+use PHPUnit\Framework\Constraint\IsFinite;
+use PHPUnit\Framework\Constraint\IsIdentical;
+use PHPUnit\Framework\Constraint\IsInfinite;
+use PHPUnit\Framework\Constraint\IsInstanceOf;
+use PHPUnit\Framework\Constraint\IsJson;
+use PHPUnit\Framework\Constraint\IsNan;
+use PHPUnit\Framework\Constraint\IsNull;
+use PHPUnit\Framework\Constraint\IsReadable;
+use PHPUnit\Framework\Constraint\IsTrue;
+use PHPUnit\Framework\Constraint\IsType;
+use PHPUnit\Framework\Constraint\IsWritable;
+use PHPUnit\Framework\Constraint\JsonMatches;
+use PHPUnit\Framework\Constraint\LessThan;
+use PHPUnit\Framework\Constraint\LogicalAnd;
+use PHPUnit\Framework\Constraint\LogicalNot;
+use PHPUnit\Framework\Constraint\LogicalOr;
+use PHPUnit\Framework\Constraint\LogicalXor;
+use PHPUnit\Framework\Constraint\ObjectEquals;
+use PHPUnit\Framework\Constraint\ObjectHasAttribute;
+use PHPUnit\Framework\Constraint\RegularExpression;
+use PHPUnit\Framework\Constraint\SameSize;
+use PHPUnit\Framework\Constraint\StringContains;
+use PHPUnit\Framework\Constraint\StringEndsWith;
+use PHPUnit\Framework\Constraint\StringMatchesFormatDescription;
+use PHPUnit\Framework\Constraint\StringStartsWith;
+use PHPUnit\Framework\Constraint\TraversableContainsEqual;
+use PHPUnit\Framework\Constraint\TraversableContainsIdentical;
+use PHPUnit\Framework\Constraint\TraversableContainsOnly;
+use PHPUnit\Util\Type;
+use PHPUnit\Util\Xml;
+use PHPUnit\Util\Xml\Loader as XmlLoader;
+
+/**
+ * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+ */
+abstract class Assert
+{
+    /**
+     * @var int
+     */
+    private static $count = 0;
+
+    /**
+     * Asserts that an array has a specified key.
+     *
+     * @param int|string        $key
+     * @param array|ArrayAccess $array
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws Exception
+     * @throws ExpectationFailedException
+     */
+    public static function assertArrayHasKey($key, $array, string $message = ''): void
+    {
+        if (!(is_int($key) || is_string($key))) {
+            throw InvalidArgumentException::create(
+                1,
+                'integer or string'
+            );
+        }
+
+        if (!(is_array($array) || $array instanceof ArrayAccess)) {
+            throw InvalidArgumentException::create(
+                2,
+                'array or ArrayAccess'
+            );
+        }
+
+        $constraint = new ArrayHasKey($key);
+
+        static::assertThat($array, $constraint, $message);
+    }
+
+    /**
+     * Asserts that an array does not have a specified key.
+     *
+     * @param int|string        $key
+     * @param array|ArrayAccess $array
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws Exception
+     * @throws ExpectationFailedException
+     */
+    public static function assertArrayNotHasKey($key, $array, string $message = ''): void
+    {
+        if (!(is_int($key) || is_string($key))) {
+            throw InvalidArgumentException::create(
+                1,
+                'integer or string'
+            );
+        }
+
+        if (!(is_array($array) || $array instanceof ArrayAccess)) {
+            throw InvalidArgumentException::create(
+                2,
+                'array or ArrayAccess'
+            );
+        }
+
+        $constraint = new LogicalNot(
+            new ArrayHasKey($key)
+        );
+
+        static::assertThat($array, $constraint, $message);
+    }
+
+    /**
+     * Asserts that a haystack contains a needle.
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws Exception
+     * @throws ExpectationFailedException
+     */
+    public static function assertContains($needle, iterable $haystack, string $message = ''): void
+    {
+        $constraint = new TraversableContainsIdentical($needle);
+
+        static::assertThat($haystack, $constraint, $message);
+    }
+
+    public static function assertContainsEquals($needle, iterable $haystack, string $message = ''): void
+    {
+        $constraint = new TraversableContainsEqual($needle);
+
+        static::assertThat($haystack, $constraint, $message);
+    }
+
+    /**
+     * Asserts that a haystack does not contain a needle.
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws Exception
+     * @throws ExpectationFailedException
+     */
+    public static function assertNotContains($needle, iterable $haystack, string $message = ''): void
+    {
+        $constraint = new LogicalNot(
+            new TraversableContainsIdentical($needle)
+        );
+
+        static::assertThat($haystack, $constraint, $message);
+    }
+
+    public static function assertNotContainsEquals($needle, iterable $haystack, string $message = ''): void
+    {
+        $constraint = new LogicalNot(new TraversableContainsEqual($needle));
+
+        static::assertThat($haystack, $constraint, $message);
+    }
+
+    /**
+     * Asserts that a haystack contains only values of a given type.
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws ExpectationFailedException
+     */
+    public static function assertContainsOnly(string $type, iterable $haystack, ?bool $isNativeType = null, string $message = ''): void
+    {
+        if ($isNativeType === null) {
+            $isNativeType = Type::isType($type);
+        }
+
+        static::assertThat(
+            $haystack,
+            new TraversableContainsOnly(
+                $type,
+                $isNativeType
+            ),
+            $message
+        );
+    }
+
+    /**
+     * Asserts that a haystack contains only instances of a given class name.
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws ExpectationFailedException
+     */
+    public static function assertContainsOnlyInstancesOf(string $className, iterable $haystack, string $message = ''): void
+    {
+        static::assertThat(
+            $haystack,
+            new TraversableContainsOnly(
+                $className,
+                false
+            ),
+            $message
+        );
+    }
+
+    /**
+     * Asserts that a haystack does not contain only values of a given type.
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws ExpectationFailedException
+     */
+    public static function assertNotContainsOnly(string $type, iterable $haystack, ?bool $isNativeType = null, string $message = ''): void
+    {
+        if ($isNativeType === null) {
+            $isNativeType = Type::isType($type);
+        }
+
+        static::assertThat(
+            $haystack,
+            new LogicalNot(
+                new TraversableContainsOnly(
+                    $type,
+                    $isNativeType
+                )
+            ),
+            $message
+        );
+    }
+
+    /**
+     * Asserts the number of elements of an array, Countable or Traversable.
+     *
+     * @param Countable|iterable $haystack
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws Exception
+     * @throws ExpectationFailedException
+     */
+    public static function assertCount(int $expectedCount, $haystack, string $message = ''): void
+    {
+        if (!$haystack instanceof Countable && !is_iterable($haystack)) {
+            throw InvalidArgumentException::create(2, 'countable or iterable');
+        }
+
+        static::assertThat(
+            $haystack,
+            new Count($expectedCount),
+            $message
+        );
+    }
+
+    /**
+     * Asserts the number of elements of an array, Countable or Traversable.
+     *
+     * @param Countable|iterable $haystack
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws Exception
+     * @throws ExpectationFailedException
+     */
+    public static function assertNotCount(int $expectedCount, $haystack, string $message = ''): void
+    {
+        if (!$haystack instanceof Countable && !is_iterable($haystack)) {
+            throw InvalidArgumentException::create(2, 'countable or iterable');
+        }
+
+        $constraint = new LogicalNot(
+            new Count($expectedCount)
+        );
+
+        static::assertThat($haystack, $constraint, $message);
+    }
+
+    /**
+     * Asserts that two variables are equal.
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws ExpectationFailedException
+     */
+    public static function assertEquals($expected, $actual, string $message = ''): void
+    {
+        $constraint = new IsEqual($expected);
+
+        static::assertThat($actual, $constraint, $message);
+    }
+
+    /**
+     * Asserts that two variables are equal (canonicalizing).
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws ExpectationFailedException
+     */
+    public static function assertEqualsCanonicalizing($expected, $actual, string $message = ''): void
+    {
+        $constraint = new IsEqualCanonicalizing($expected);
+
+        static::assertThat($actual, $constraint, $message);
+    }
+
+    /**
+     * Asserts that two variables are equal (ignoring case).
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws ExpectationFailedException
+     */
+    public static function assertEqualsIgnoringCase($expected, $actual, string $message = ''): void
+    {
+        $constraint = new IsEqualIgnoringCase($expected);
+
+        static::assertThat($actual, $constraint, $message);
+    }
+
+    /**
+     * Asserts that two variables are equal (with delta).
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws ExpectationFailedException
+     */
+    public static function assertEqualsWithDelta($expected, $actual, float $delta, string $message = ''): void
+    {
+        $constraint = new IsEqualWithDelta(
+            $expected,
+            $delta
+        );
+
+        static::assertThat($actual, $constraint, $message);
+    }
+
+    /**
+     * Asserts that two variables are not equal.
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws ExpectationFailedException
+     */
+    public static function assertNotEquals($expected, $actual, string $message = ''): void
+    {
+        $constraint = new LogicalNot(
+            new IsEqual($expected)
+        );
+
+        static::assertThat($actual, $constraint, $message);
+    }
+
+    /**
+     * Asserts that two variables are not equal (canonicalizing).
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws ExpectationFailedException
+     */
+    public static function assertNotEqualsCanonicalizing($expected, $actual, string $message = ''): void
+    {
+        $constraint = new LogicalNot(
+            new IsEqualCanonicalizing($expected)
+        );
+
+        static::assertThat($actual, $constraint, $message);
+    }
+
+    /**
+     * Asserts that two variables are not equal (ignoring case).
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws ExpectationFailedException
+     */
+    public static function assertNotEqualsIgnoringCase($expected, $actual, string $message = ''): void
+    {
+        $constraint = new LogicalNot(
+            new IsEqualIgnoringCase($expected)
+        );
+
+        static::assertThat($actual, $constraint, $message);
+    }
+
+    /**
+     * Asserts that two variables are not equal (with delta).
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws ExpectationFailedException
+     */
+    public static function assertNotEqualsWithDelta($expected, $actual, float $delta, string $message = ''): void
+    {
+        $constraint = new LogicalNot(
+            new IsEqualWithDelta(
+                $expected,
+                $delta
+            )
+        );
+
+        static::assertThat($actual, $constraint, $message);
+    }
+
+    /**
+     * @throws ExpectationFailedException
+     */
+    public static function assertObjectEquals(object $expected, object $actual, string $method = 'equals', string $message = ''): void
+    {
+        static::assertThat(
+            $actual,
+            static::objectEquals($expected, $method),
+            $message
+        );
+    }
+
+    /**
+     * Asserts that a variable is empty.
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws ExpectationFailedException
+     *
+     * @psalm-assert empty $actual
+     */
+    public static function assertEmpty($actual, string $message = ''): void
+    {
+        static::assertThat($actual, static::isEmpty(), $message);
+    }
+
+    /**
+     * Asserts that a variable is not empty.
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws ExpectationFailedException
+     *
+     * @psalm-assert !empty $actual
+     */
+    public static function assertNotEmpty($actual, string $message = ''): void
+    {
+        static::assertThat($actual, static::logicalNot(static::isEmpty()), $message);
+    }
+
+    /**
+     * Asserts that a value is greater than another value.
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws ExpectationFailedException
+     */
+    public static function assertGreaterThan($expected, $actual, string $message = ''): void
+    {
+        static::assertThat($actual, static::greaterThan($expected), $message);
+    }
+
+    /**
+     * Asserts that a value is greater than or equal to another value.
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws ExpectationFailedException
+     */
+    public static function assertGreaterThanOrEqual($expected, $actual, string $message = ''): void
+    {
+        static::assertThat(
+            $actual,
+            static::greaterThanOrEqual($expected),
+            $message
+        );
+    }
+
+    /**
+     * Asserts that a value is smaller than another value.
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws ExpectationFailedException
+     */
+    public static function assertLessThan($expected, $actual, string $message = ''): void
+    {
+        static::assertThat($actual, static::lessThan($expected), $message);
+    }
+
+    /**
+     * Asserts that a value is smaller than or equal to another value.
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws ExpectationFailedException
+     */
+    public static function assertLessThanOrEqual($expected, $actual, string $message = ''): void
+    {
+        static::assertThat($actual, static::lessThanOrEqual($expected), $message);
+    }
+
+    /**
+     * Asserts that the contents of one file is equal to the contents of another
+     * file.
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws ExpectationFailedException
+     */
+    public static function assertFileEquals(string $expected, string $actual, string $message = ''): void
+    {
+        static::assertFileExists($expected, $message);
+        static::assertFileExists($actual, $message);
+
+        $constraint = new IsEqual(file_get_contents($expected));
+
+        static::assertThat(file_get_contents($actual), $constraint, $message);
+    }
+
+    /**
+     * Asserts that the contents of one file is equal to the contents of another
+     * file (canonicalizing).
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws ExpectationFailedException
+     */
+    public static function assertFileEqualsCanonicalizing(string $expected, string $actual, string $message = ''): void
+    {
+        static::assertFileExists($expected, $message);
+        static::assertFileExists($actual, $message);
+
+        $constraint = new IsEqualCanonicalizing(
+            file_get_contents($expected)
+        );
+
+        static::assertThat(file_get_contents($actual), $constraint, $message);
+    }
+
+    /**
+     * Asserts that the contents of one file is equal to the contents of another
+     * file (ignoring case).
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws ExpectationFailedException
+     */
+    public static function assertFileEqualsIgnoringCase(string $expected, string $actual, string $message = ''): void
+    {
+        static::assertFileExists($expected, $message);
+        static::assertFileExists($actual, $message);
+
+        $constraint = new IsEqualIgnoringCase(file_get_contents($expected));
+
+        static::assertThat(file_get_contents($actual), $constraint, $message);
+    }
+
+    /**
+     * Asserts that the contents of one file is not equal to the contents of
+     * another file.
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws ExpectationFailedException
+     */
+    public static function assertFileNotEquals(string $expected, string $actual, string $message = ''): void
+    {
+        static::assertFileExists($expected, $message);
+        static::assertFileExists($actual, $message);
+
+        $constraint = new LogicalNot(
+            new IsEqual(file_get_contents($expected))
+        );
+
+        static::assertThat(file_get_contents($actual), $constraint, $message);
+    }
+
+    /**
+     * Asserts that the contents of one file is not equal to the contents of another
+     * file (canonicalizing).
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws ExpectationFailedException
+     */
+    public static function assertFileNotEqualsCanonicalizing(string $expected, string $actual, string $message = ''): void
+    {
+        static::assertFileExists($expected, $message);
+        static::assertFileExists($actual, $message);
+
+        $constraint = new LogicalNot(
+            new IsEqualCanonicalizing(file_get_contents($expected))
+        );
+
+        static::assertThat(file_get_contents($actual), $constraint, $message);
+    }
+
+    /**
+     * Asserts that the contents of one file is not equal to the contents of another
+     * file (ignoring case).
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws ExpectationFailedException
+     */
+    public static function assertFileNotEqualsIgnoringCase(string $expected, string $actual, string $message = ''): void
+    {
+        static::assertFileExists($expected, $message);
+        static::assertFileExists($actual, $message);
+
+        $constraint = new LogicalNot(
+            new IsEqualIgnoringCase(file_get_contents($expected))
+        );
+
+        static::assertThat(file_get_contents($actual), $constraint, $message);
+    }
+
+    /**
+     * Asserts that the contents of a string is equal
+     * to the contents of a file.
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws ExpectationFailedException
+     */
+    public static function assertStringEqualsFile(string $expectedFile, string $actualString, string $message = ''): void
+    {
+        static::assertFileExists($expectedFile, $message);
+
+        $constraint = new IsEqual(file_get_contents($expectedFile));
+
+        static::assertThat($actualString, $constraint, $message);
+    }
+
+    /**
+     * Asserts that the contents of a string is equal
+     * to the contents of a file (canonicalizing).
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws ExpectationFailedException
+     */
+    public static function assertStringEqualsFileCanonicalizing(string $expectedFile, string $actualString, string $message = ''): void
+    {
+        static::assertFileExists($expectedFile, $message);
+
+        $constraint = new IsEqualCanonicalizing(file_get_contents($expectedFile));
+
+        static::assertThat($actualString, $constraint, $message);
+    }
+
+    /**
+     * Asserts that the contents of a string is equal
+     * to the contents of a file (ignoring case).
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws ExpectationFailedException
+     */
+    public static function assertStringEqualsFileIgnoringCase(string $expectedFile, string $actualString, string $message = ''): void
+    {
+        static::assertFileExists($expectedFile, $message);
+
+        $constraint = new IsEqualIgnoringCase(file_get_contents($expectedFile));
+
+        static::assertThat($actualString, $constraint, $message);
+    }
+
+    /**
+     * Asserts that the contents of a string is not equal
+     * to the contents of a file.
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws ExpectationFailedException
+     */
+    public static function assertStringNotEqualsFile(string $expectedFile, string $actualString, string $message = ''): void
+    {
+        static::assertFileExists($expectedFile, $message);
+
+        $constraint = new LogicalNot(
+            new IsEqual(file_get_contents($expectedFile))
+        );
+
+        static::assertThat($actualString, $constraint, $message);
+    }
+
+    /**
+     * Asserts that the contents of a string is not equal
+     * to the contents of a file (canonicalizing).
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws ExpectationFailedException
+     */
+    public static function assertStringNotEqualsFileCanonicalizing(string $expectedFile, string $actualString, string $message = ''): void
+    {
+        static::assertFileExists($expectedFile, $message);
+
+        $constraint = new LogicalNot(
+            new IsEqualCanonicalizing(file_get_contents($expectedFile))
+        );
+
+        static::assertThat($actualString, $constraint, $message);
+    }
+
+    /**
+     * Asserts that the contents of a string is not equal
+     * to the contents of a file (ignoring case).
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws ExpectationFailedException
+     */
+    public static function assertStringNotEqualsFileIgnoringCase(string $expectedFile, string $actualString, string $message = ''): void
+    {
+        static::assertFileExists($expectedFile, $message);
+
+        $constraint = new LogicalNot(
+            new IsEqualIgnoringCase(file_get_contents($expectedFile))
+        );
+
+        static::assertThat($actualString, $constraint, $message);
+    }
+
+    /**
+     * Asserts that a file/dir is readable.
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws ExpectationFailedException
+     */
+    public static function assertIsReadable(string $filename, string $message = ''): void
+    {
+        static::assertThat($filename, new IsReadable, $message);
+    }
+
+    /**
+     * Asserts that a file/dir exists and is not readable.
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws ExpectationFailedException
+     */
+    public static function assertIsNotReadable(string $filename, string $message = ''): void
+    {
+        static::assertThat($filename, new LogicalNot(new IsReadable), $message);
+    }
+
+    /**
+     * Asserts that a file/dir exists and is not readable.
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws ExpectationFailedException
+     *
+     * @codeCoverageIgnore
+     *
+     * @deprecated https://github.com/sebastianbergmann/phpunit/issues/4062
+     */
+    public static function assertNotIsReadable(string $filename, string $message = ''): void
+    {
+        self::createWarning('assertNotIsReadable() is deprecated and will be removed in PHPUnit 10. Refactor your code to use assertIsNotReadable() instead.');
+
+        static::assertThat($filename, new LogicalNot(new IsReadable), $message);
+    }
+
+    /**
+     * Asserts that a file/dir exists and is writable.
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws ExpectationFailedException
+     */
+    public static function assertIsWritable(string $filename, string $message = ''): void
+    {
+        static::assertThat($filename, new IsWritable, $message);
+    }
+
+    /**
+     * Asserts that a file/dir exists and is not writable.
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws ExpectationFailedException
+     */
+    public static function assertIsNotWritable(string $filename, string $message = ''): void
+    {
+        static::assertThat($filename, new LogicalNot(new IsWritable), $message);
+    }
+
+    /**
+     * Asserts that a file/dir exists and is not writable.
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws ExpectationFailedException
+     *
+     * @codeCoverageIgnore
+     *
+     * @deprecated https://github.com/sebastianbergmann/phpunit/issues/4065
+     */
+    public static function assertNotIsWritable(string $filename, string $message = ''): void
+    {
+        self::createWarning('assertNotIsWritable() is deprecated and will be removed in PHPUnit 10. Refactor your code to use assertIsNotWritable() instead.');
+
+        static::assertThat($filename, new LogicalNot(new IsWritable), $message);
+    }
+
+    /**
+     * Asserts that a directory exists.
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws ExpectationFailedException
+     */
+    public static function assertDirectoryExists(string $directory, string $message = ''): void
+    {
+        static::assertThat($directory, new DirectoryExists, $message);
+    }
+
+    /**
+     * Asserts that a directory does not exist.
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws ExpectationFailedException
+     */
+    public static function assertDirectoryDoesNotExist(string $directory, string $message = ''): void
+    {
+        static::assertThat($directory, new LogicalNot(new DirectoryExists), $message);
+    }
+
+    /**
+     * Asserts that a directory does not exist.
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws ExpectationFailedException
+     *
+     * @codeCoverageIgnore
+     *
+     * @deprecated https://github.com/sebastianbergmann/phpunit/issues/4068
+     */
+    public static function assertDirectoryNotExists(string $directory, string $message = ''): void
+    {
+        self::createWarning('assertDirectoryNotExists() is deprecated and will be removed in PHPUnit 10. Refactor your code to use assertDirectoryDoesNotExist() instead.');
+
+        static::assertThat($directory, new LogicalNot(new DirectoryExists), $message);
+    }
+
+    /**
+     * Asserts that a directory exists and is readable.
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws ExpectationFailedException
+     */
+    public static function assertDirectoryIsReadable(string $directory, string $message = ''): void
+    {
+        self::assertDirectoryExists($directory, $message);
+        self::assertIsReadable($directory, $message);
+    }
+
+    /**
+     * Asserts that a directory exists and is not readable.
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws ExpectationFailedException
+     */
+    public static function assertDirectoryIsNotReadable(string $directory, string $message = ''): void
+    {
+        self::assertDirectoryExists($directory, $message);
+        self::assertIsNotReadable($directory, $message);
+    }
+
+    /**
+     * Asserts that a directory exists and is not readable.
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws ExpectationFailedException
+     *
+     * @codeCoverageIgnore
+     *
+     * @deprecated https://github.com/sebastianbergmann/phpunit/issues/4071
+     */
+    public static function assertDirectoryNotIsReadable(string $directory, string $message = ''): void
+    {
+        self::createWarning('assertDirectoryNotIsReadable() is deprecated and will be removed in PHPUnit 10. Refactor your code to use assertDirectoryIsNotReadable() instead.');
+
+        self::assertDirectoryExists($directory, $message);
+        self::assertIsNotReadable($directory, $message);
+    }
+
+    /**
+     * Asserts that a directory exists and is writable.
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws ExpectationFailedException
+     */
+    public static function assertDirectoryIsWritable(string $directory, string $message = ''): void
+    {
+        self::assertDirectoryExists($directory, $message);
+        self::assertIsWritable($directory, $message);
+    }
+
+    /**
+     * Asserts that a directory exists and is not writable.
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws ExpectationFailedException
+     */
+    public static function assertDirectoryIsNotWritable(string $directory, string $message = ''): void
+    {
+        self::assertDirectoryExists($directory, $message);
+        self::assertIsNotWritable($directory, $message);
+    }
+
+    /**
+     * Asserts that a directory exists and is not writable.
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws ExpectationFailedException
+     *
+     * @codeCoverageIgnore
+     *
+     * @deprecated https://github.com/sebastianbergmann/phpunit/issues/4074
+     */
+    public static function assertDirectoryNotIsWritable(string $directory, string $message = ''): void
+    {
+        self::createWarning('assertDirectoryNotIsWritable() is deprecated and will be removed in PHPUnit 10. Refactor your code to use assertDirectoryIsNotWritable() instead.');
+
+        self::assertDirectoryExists($directory, $message);
+        self::assertIsNotWritable($directory, $message);
+    }
+
+    /**
+     * Asserts that a file exists.
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws ExpectationFailedException
+     */
+    public static function assertFileExists(string $filename, string $message = ''): void
+    {
+        static::assertThat($filename, new FileExists, $message);
+    }
+
+    /**
+     * Asserts that a file does not exist.
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws ExpectationFailedException
+     */
+    public static function assertFileDoesNotExist(string $filename, string $message = ''): void
+    {
+        static::assertThat($filename, new LogicalNot(new FileExists), $message);
+    }
+
+    /**
+     * Asserts that a file does not exist.
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws ExpectationFailedException
+     *
+     * @codeCoverageIgnore
+     *
+     * @deprecated https://github.com/sebastianbergmann/phpunit/issues/4077
+     */
+    public static function assertFileNotExists(string $filename, string $message = ''): void
+    {
+        self::createWarning('assertFileNotExists() is deprecated and will be removed in PHPUnit 10. Refactor your code to use assertFileDoesNotExist() instead.');
+
+        static::assertThat($filename, new LogicalNot(new FileExists), $message);
+    }
+
+    /**
+     * Asserts that a file exists and is readable.
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws ExpectationFailedException
+     */
+    public static function assertFileIsReadable(string $file, string $message = ''): void
+    {
+        self::assertFileExists($file, $message);
+        self::assertIsReadable($file, $message);
+    }
+
+    /**
+     * Asserts that a file exists and is not readable.
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws ExpectationFailedException
+     */
+    public static function assertFileIsNotReadable(string $file, string $message = ''): void
+    {
+        self::assertFileExists($file, $message);
+        self::assertIsNotReadable($file, $message);
+    }
+
+    /**
+     * Asserts that a file exists and is not readable.
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws ExpectationFailedException
+     *
+     * @codeCoverageIgnore
+     *
+     * @deprecated https://github.com/sebastianbergmann/phpunit/issues/4080
+     */
+    public static function assertFileNotIsReadable(string $file, string $message = ''): void
+    {
+        self::createWarning('assertFileNotIsReadable() is deprecated and will be removed in PHPUnit 10. Refactor your code to use assertFileIsNotReadable() instead.');
+
+        self::assertFileExists($file, $message);
+        self::assertIsNotReadable($file, $message);
+    }
+
+    /**
+     * Asserts that a file exists and is writable.
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws ExpectationFailedException
+     */
+    public static function assertFileIsWritable(string $file, string $message = ''): void
+    {
+        self::assertFileExists($file, $message);
+        self::assertIsWritable($file, $message);
+    }
+
+    /**
+     * Asserts that a file exists and is not writable.
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws ExpectationFailedException
+     */
+    public static function assertFileIsNotWritable(string $file, string $message = ''): void
+    {
+        self::assertFileExists($file, $message);
+        self::assertIsNotWritable($file, $message);
+    }
+
+    /**
+     * Asserts that a file exists and is not writable.
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws ExpectationFailedException
+     *
+     * @codeCoverageIgnore
+     *
+     * @deprecated https://github.com/sebastianbergmann/phpunit/issues/4083
+     */
+    public static function assertFileNotIsWritable(string $file, string $message = ''): void
+    {
+        self::createWarning('assertFileNotIsWritable() is deprecated and will be removed in PHPUnit 10. Refactor your code to use assertFileIsNotWritable() instead.');
+
+        self::assertFileExists($file, $message);
+        self::assertIsNotWritable($file, $message);
+    }
+
+    /**
+     * Asserts that a condition is true.
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws ExpectationFailedException
+     *
+     * @psalm-assert true $condition
+     */
+    public static function assertTrue($condition, string $message = ''): void
+    {
+        static::assertThat($condition, static::isTrue(), $message);
+    }
+
+    /**
+     * Asserts that a condition is not true.
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws ExpectationFailedException
+     *
+     * @psalm-assert !true $condition
+     */
+    public static function assertNotTrue($condition, string $message = ''): void
+    {
+        static::assertThat($condition, static::logicalNot(static::isTrue()), $message);
+    }
+
+    /**
+     * Asserts that a condition is false.
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws ExpectationFailedException
+     *
+     * @psalm-assert false $condition
+     */
+    public static function assertFalse($condition, string $message = ''): void
+    {
+        static::assertThat($condition, static::isFalse(), $message);
+    }
+
+    /**
+     * Asserts that a condition is not false.
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws ExpectationFailedException
+     *
+     * @psalm-assert !false $condition
+     */
+    public static function assertNotFalse($condition, string $message = ''): void
+    {
+        static::assertThat($condition, static::logicalNot(static::isFalse()), $message);
+    }
+
+    /**
+     * Asserts that a variable is null.
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws ExpectationFailedException
+     *
+     * @psalm-assert null $actual
+     */
+    public static function assertNull($actual, string $message = ''): void
+    {
+        static::assertThat($actual, static::isNull(), $message);
+    }
+
+    /**
+     * Asserts that a variable is not null.
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws ExpectationFailedException
+     *
+     * @psalm-assert !null $actual
+     */
+    public static function assertNotNull($actual, string $message = ''): void
+    {
+        static::assertThat($actual, static::logicalNot(static::isNull()), $message);
+    }
+
+    /**
+     * Asserts that a variable is finite.
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws ExpectationFailedException
+     */
+    public static function assertFinite($actual, string $message = ''): void
+    {
+        static::assertThat($actual, static::isFinite(), $message);
+    }
+
+    /**
+     * Asserts that a variable is infinite.
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws ExpectationFailedException
+     */
+    public static function assertInfinite($actual, string $message = ''): void
+    {
+        static::assertThat($actual, static::isInfinite(), $message);
+    }
+
+    /**
+     * Asserts that a variable is nan.
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws ExpectationFailedException
+     */
+    public static function assertNan($actual, string $message = ''): void
+    {
+        static::assertThat($actual, static::isNan(), $message);
+    }
+
+    /**
+     * Asserts that a class has a specified attribute.
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws Exception
+     * @throws ExpectationFailedException
+     */
+    public static function assertClassHasAttribute(string $attributeName, string $className, string $message = ''): void
+    {
+        if (!self::isValidClassAttributeName($attributeName)) {
+            throw InvalidArgumentException::create(1, 'valid attribute name');
+        }
+
+        if (!class_exists($className)) {
+            throw InvalidArgumentException::create(2, 'class name');
+        }
+
+        static::assertThat($className, new ClassHasAttribute($attributeName), $message);
+    }
+
+    /**
+     * Asserts that a class does not have a specified attribute.
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws Exception
+     * @throws ExpectationFailedException
+     */
+    public static function assertClassNotHasAttribute(string $attributeName, string $className, string $message = ''): void
+    {
+        if (!self::isValidClassAttributeName($attributeName)) {
+            throw InvalidArgumentException::create(1, 'valid attribute name');
+        }
+
+        if (!class_exists($className)) {
+            throw InvalidArgumentException::create(2, 'class name');
+        }
+
+        static::assertThat(
+            $className,
+            new LogicalNot(
+                new ClassHasAttribute($attributeName)
+            ),
+            $message
+        );
+    }
+
+    /**
+     * Asserts that a class has a specified static attribute.
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws Exception
+     * @throws ExpectationFailedException
+     */
+    public static function assertClassHasStaticAttribute(string $attributeName, string $className, string $message = ''): void
+    {
+        if (!self::isValidClassAttributeName($attributeName)) {
+            throw InvalidArgumentException::create(1, 'valid attribute name');
+        }
+
+        if (!class_exists($className)) {
+            throw InvalidArgumentException::create(2, 'class name');
+        }
+
+        static::assertThat(
+            $className,
+            new ClassHasStaticAttribute($attributeName),
+            $message
+        );
+    }
+
+    /**
+     * Asserts that a class does not have a specified static attribute.
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws Exception
+     * @throws ExpectationFailedException
+     */
+    public static function assertClassNotHasStaticAttribute(string $attributeName, string $className, string $message = ''): void
+    {
+        if (!self::isValidClassAttributeName($attributeName)) {
+            throw InvalidArgumentException::create(1, 'valid attribute name');
+        }
+
+        if (!class_exists($className)) {
+            throw InvalidArgumentException::create(2, 'class name');
+        }
+
+        static::assertThat(
+            $className,
+            new LogicalNot(
+                new ClassHasStaticAttribute($attributeName)
+            ),
+            $message
+        );
+    }
+
+    /**
+     * Asserts that an object has a specified attribute.
+     *
+     * @param object $object
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws Exception
+     * @throws ExpectationFailedException
+     */
+    public static function assertObjectHasAttribute(string $attributeName, $object, string $message = ''): void
+    {
+        if (!self::isValidObjectAttributeName($attributeName)) {
+            throw InvalidArgumentException::create(1, 'valid attribute name');
+        }
+
+        if (!is_object($object)) {
+            throw InvalidArgumentException::create(2, 'object');
+        }
+
+        static::assertThat(
+            $object,
+            new ObjectHasAttribute($attributeName),
+            $message
+        );
+    }
+
+    /**
+     * Asserts that an object does not have a specified attribute.
+     *
+     * @param object $object
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws Exception
+     * @throws ExpectationFailedException
+     */
+    public static function assertObjectNotHasAttribute(string $attributeName, $object, string $message = ''): void
+    {
+        if (!self::isValidObjectAttributeName($attributeName)) {
+            throw InvalidArgumentException::create(1, 'valid attribute name');
+        }
+
+        if (!is_object($object)) {
+            throw InvalidArgumentException::create(2, 'object');
+        }
+
+        static::assertThat(
+            $object,
+            new LogicalNot(
+                new ObjectHasAttribute($attributeName)
+            ),
+            $message
+        );
+    }
+
+    /**
+     * Asserts that two variables have the same type and value.
+     * Used on objects, it asserts that two variables reference
+     * the same object.
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws ExpectationFailedException
+     *
+     * @psalm-template ExpectedType
+     * @psalm-param ExpectedType $expected
+     * @psalm-assert =ExpectedType $actual
+     */
+    public static function assertSame($expected, $actual, string $message = ''): void
+    {
+        static::assertThat(
+            $actual,
+            new IsIdentical($expected),
+            $message
+        );
+    }
+
+    /**
+     * Asserts that two variables do not have the same type and value.
+     * Used on objects, it asserts that two variables do not reference
+     * the same object.
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws ExpectationFailedException
+     */
+    public static function assertNotSame($expected, $actual, string $message = ''): void
+    {
+        if (is_bool($expected) && is_bool($actual)) {
+            static::assertNotEquals($expected, $actual, $message);
+        }
+
+        static::assertThat(
+            $actual,
+            new LogicalNot(
+                new IsIdentical($expected)
+            ),
+            $message
+        );
+    }
+
+    /**
+     * Asserts that a variable is of a given type.
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws Exception
+     * @throws ExpectationFailedException
+     *
+     * @psalm-template ExpectedType of object
+     * @psalm-param class-string<ExpectedType> $expected
+     * @psalm-assert =ExpectedType $actual
+     */
+    public static function assertInstanceOf(string $expected, $actual, string $message = ''): void
+    {
+        if (!class_exists($expected) && !interface_exists($expected)) {
+            throw InvalidArgumentException::create(1, 'class or interface name');
+        }
+
+        static::assertThat(
+            $actual,
+            new IsInstanceOf($expected),
+            $message
+        );
+    }
+
+    /**
+     * Asserts that a variable is not of a given type.
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws Exception
+     * @throws ExpectationFailedException
+     *
+     * @psalm-template ExpectedType of object
+     * @psalm-param class-string<ExpectedType> $expected
+     * @psalm-assert !ExpectedType $actual
+     */
+    public static function assertNotInstanceOf(string $expected, $actual, string $message = ''): void
+    {
+        if (!class_exists($expected) && !interface_exists($expected)) {
+            throw InvalidArgumentException::create(1, 'class or interface name');
+        }
+
+        static::assertThat(
+            $actual,
+            new LogicalNot(
+                new IsInstanceOf($expected)
+            ),
+            $message
+        );
+    }
+
+    /**
+     * Asserts that a variable is of type array.
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws ExpectationFailedException
+     *
+     * @psalm-assert array $actual
+     */
+    public static function assertIsArray($actual, string $message = ''): void
+    {
+        static::assertThat(
+            $actual,
+            new IsType(IsType::TYPE_ARRAY),
+            $message
+        );
+    }
+
+    /**
+     * Asserts that a variable is of type bool.
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws ExpectationFailedException
+     *
+     * @psalm-assert bool $actual
+     */
+    public static function assertIsBool($actual, string $message = ''): void
+    {
+        static::assertThat(
+            $actual,
+            new IsType(IsType::TYPE_BOOL),
+            $message
+        );
+    }
+
+    /**
+     * Asserts that a variable is of type float.
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws ExpectationFailedException
+     *
+     * @psalm-assert float $actual
+     */
+    public static function assertIsFloat($actual, string $message = ''): void
+    {
+        static::assertThat(
+            $actual,
+            new IsType(IsType::TYPE_FLOAT),
+            $message
+        );
+    }
+
+    /**
+     * Asserts that a variable is of type int.
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws ExpectationFailedException
+     *
+     * @psalm-assert int $actual
+     */
+    public static function assertIsInt($actual, string $message = ''): void
+    {
+        static::assertThat(
+            $actual,
+            new IsType(IsType::TYPE_INT),
+            $message
+        );
+    }
+
+    /**
+     * Asserts that a variable is of type numeric.
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws ExpectationFailedException
+     *
+     * @psalm-assert numeric $actual
+     */
+    public static function assertIsNumeric($actual, string $message = ''): void
+    {
+        static::assertThat(
+            $actual,
+            new IsType(IsType::TYPE_NUMERIC),
+            $message
+        );
+    }
+
+    /**
+     * Asserts that a variable is of type object.
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws ExpectationFailedException
+     *
+     * @psalm-assert object $actual
+     */
+    public static function assertIsObject($actual, string $message = ''): void
+    {
+        static::assertThat(
+            $actual,
+            new IsType(IsType::TYPE_OBJECT),
+            $message
+        );
+    }
+
+    /**
+     * Asserts that a variable is of type resource.
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws ExpectationFailedException
+     *
+     * @psalm-assert resource $actual
+     */
+    public static function assertIsResource($actual, string $message = ''): void
+    {
+        static::assertThat(
+            $actual,
+            new IsType(IsType::TYPE_RESOURCE),
+            $message
+        );
+    }
+
+    /**
+     * Asserts that a variable is of type resource and is closed.
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws ExpectationFailedException
+     *
+     * @psalm-assert resource $actual
+     */
+    public static function assertIsClosedResource($actual, string $message = ''): void
+    {
+        static::assertThat(
+            $actual,
+            new IsType(IsType::TYPE_CLOSED_RESOURCE),
+            $message
+        );
+    }
+
+    /**
+     * Asserts that a variable is of type string.
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws ExpectationFailedException
+     *
+     * @psalm-assert string $actual
+     */
+    public static function assertIsString($actual, string $message = ''): void
+    {
+        static::assertThat(
+            $actual,
+            new IsType(IsType::TYPE_STRING),
+            $message
+        );
+    }
+
+    /**
+     * Asserts that a variable is of type scalar.
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws ExpectationFailedException
+     *
+     * @psalm-assert scalar $actual
+     */
+    public static function assertIsScalar($actual, string $message = ''): void
+    {
+        static::assertThat(
+            $actual,
+            new IsType(IsType::TYPE_SCALAR),
+            $message
+        );
+    }
+
+    /**
+     * Asserts that a variable is of type callable.
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws ExpectationFailedException
+     *
+     * @psalm-assert callable $actual
+     */
+    public static function assertIsCallable($actual, string $message = ''): void
+    {
+        static::assertThat(
+            $actual,
+            new IsType(IsType::TYPE_CALLABLE),
+            $message
+        );
+    }
+
+    /**
+     * Asserts that a variable is of type iterable.
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws ExpectationFailedException
+     *
+     * @psalm-assert iterable $actual
+     */
+    public static function assertIsIterable($actual, string $message = ''): void
+    {
+        static::assertThat(
+            $actual,
+            new IsType(IsType::TYPE_ITERABLE),
+            $message
+        );
+    }
+
+    /**
+     * Asserts that a variable is not of type array.
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws ExpectationFailedException
+     *
+     * @psalm-assert !array $actual
+     */
+    public static function assertIsNotArray($actual, string $message = ''): void
+    {
+        static::assertThat(
+            $actual,
+            new LogicalNot(new IsType(IsType::TYPE_ARRAY)),
+            $message
+        );
+    }
+
+    /**
+     * Asserts that a variable is not of type bool.
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws ExpectationFailedException
+     *
+     * @psalm-assert !bool $actual
+     */
+    public static function assertIsNotBool($actual, string $message = ''): void
+    {
+        static::assertThat(
+            $actual,
+            new LogicalNot(new IsType(IsType::TYPE_BOOL)),
+            $message
+        );
+    }
+
+    /**
+     * Asserts that a variable is not of type float.
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws ExpectationFailedException
+     *
+     * @psalm-assert !float $actual
+     */
+    public static function assertIsNotFloat($actual, string $message = ''): void
+    {
+        static::assertThat(
+            $actual,
+            new LogicalNot(new IsType(IsType::TYPE_FLOAT)),
+            $message
+        );
+    }
+
+    /**
+     * Asserts that a variable is not of type int.
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws ExpectationFailedException
+     *
+     * @psalm-assert !int $actual
+     */
+    public static function assertIsNotInt($actual, string $message = ''): void
+    {
+        static::assertThat(
+            $actual,
+            new LogicalNot(new IsType(IsType::TYPE_INT)),
+            $message
+        );
+    }
+
+    /**
+     * Asserts that a variable is not of type numeric.
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws ExpectationFailedException
+     *
+     * @psalm-assert !numeric $actual
+     */
+    public static function assertIsNotNumeric($actual, string $message = ''): void
+    {
+        static::assertThat(
+            $actual,
+            new LogicalNot(new IsType(IsType::TYPE_NUMERIC)),
+            $message
+        );
+    }
+
+    /**
+     * Asserts that a variable is not of type object.
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws ExpectationFailedException
+     *
+     * @psalm-assert !object $actual
+     */
+    public static function assertIsNotObject($actual, string $message = ''): void
+    {
+        static::assertThat(
+            $actual,
+            new LogicalNot(new IsType(IsType::TYPE_OBJECT)),
+            $message
+        );
+    }
+
+    /**
+     * Asserts that a variable is not of type resource.
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws ExpectationFailedException
+     *
+     * @psalm-assert !resource $actual
+     */
+    public static function assertIsNotResource($actual, string $message = ''): void
+    {
+        static::assertThat(
+            $actual,
+            new LogicalNot(new IsType(IsType::TYPE_RESOURCE)),
+            $message
+        );
+    }
+
+    /**
+     * Asserts that a variable is not of type resource.
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws ExpectationFailedException
+     *
+     * @psalm-assert !resource $actual
+     */
+    public static function assertIsNotClosedResource($actual, string $message = ''): void
+    {
+        static::assertThat(
+            $actual,
+            new LogicalNot(new IsType(IsType::TYPE_CLOSED_RESOURCE)),
+            $message
+        );
+    }
+
+    /**
+     * Asserts that a variable is not of type string.
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws ExpectationFailedException
+     *
+     * @psalm-assert !string $actual
+     */
+    public static function assertIsNotString($actual, string $message = ''): void
+    {
+        static::assertThat(
+            $actual,
+            new LogicalNot(new IsType(IsType::TYPE_STRING)),
+            $message
+        );
+    }
+
+    /**
+     * Asserts that a variable is not of type scalar.
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws ExpectationFailedException
+     *
+     * @psalm-assert !scalar $actual
+     */
+    public static function assertIsNotScalar($actual, string $message = ''): void
+    {
+        static::assertThat(
+            $actual,
+            new LogicalNot(new IsType(IsType::TYPE_SCALAR)),
+            $message
+        );
+    }
+
+    /**
+     * Asserts that a variable is not of type callable.
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws ExpectationFailedException
+     *
+     * @psalm-assert !callable $actual
+     */
+    public static function assertIsNotCallable($actual, string $message = ''): void
+    {
+        static::assertThat(
+            $actual,
+            new LogicalNot(new IsType(IsType::TYPE_CALLABLE)),
+            $message
+        );
+    }
+
+    /**
+     * Asserts that a variable is not of type iterable.
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws ExpectationFailedException
+     *
+     * @psalm-assert !iterable $actual
+     */
+    public static function assertIsNotIterable($actual, string $message = ''): void
+    {
+        static::assertThat(
+            $actual,
+            new LogicalNot(new IsType(IsType::TYPE_ITERABLE)),
+            $message
+        );
+    }
+
+    /**
+     * Asserts that a string matches a given regular expression.
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws ExpectationFailedException
+     */
+    public static function assertMatchesRegularExpression(string $pattern, string $string, string $message = ''): void
+    {
+        static::assertThat($string, new RegularExpression($pattern), $message);
+    }
+
+    /**
+     * Asserts that a string matches a given regular expression.
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws ExpectationFailedException
+     *
+     * @codeCoverageIgnore
+     *
+     * @deprecated https://github.com/sebastianbergmann/phpunit/issues/4086
+     */
+    public static function assertRegExp(string $pattern, string $string, string $message = ''): void
+    {
+        self::createWarning('assertRegExp() is deprecated and will be removed in PHPUnit 10. Refactor your code to use assertMatchesRegularExpression() instead.');
+
+        static::assertThat($string, new RegularExpression($pattern), $message);
+    }
+
+    /**
+     * Asserts that a string does not match a given regular expression.
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws ExpectationFailedException
+     */
+    public static function assertDoesNotMatchRegularExpression(string $pattern, string $string, string $message = ''): void
+    {
+        static::assertThat(
+            $string,
+            new LogicalNot(
+                new RegularExpression($pattern)
+            ),
+            $message
+        );
+    }
+
+    /**
+     * Asserts that a string does not match a given regular expression.
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws ExpectationFailedException
+     *
+     * @codeCoverageIgnore
+     *
+     * @deprecated https://github.com/sebastianbergmann/phpunit/issues/4089
+     */
+    public static function assertNotRegExp(string $pattern, string $string, string $message = ''): void
+    {
+        self::createWarning('assertNotRegExp() is deprecated and will be removed in PHPUnit 10. Refactor your code to use assertDoesNotMatchRegularExpression() instead.');
+
+        static::assertThat(
+            $string,
+            new LogicalNot(
+                new RegularExpression($pattern)
+            ),
+            $message
+        );
+    }
+
+    /**
+     * Assert that the size of two arrays (or `Countable` or `Traversable` objects)
+     * is the same.
+     *
+     * @param Countable|iterable $expected
+     * @param Countable|iterable $actual
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws Exception
+     * @throws ExpectationFailedException
+     */
+    public static function assertSameSize($expected, $actual, string $message = ''): void
+    {
+        if (!$expected instanceof Countable && !is_iterable($expected)) {
+            throw InvalidArgumentException::create(1, 'countable or iterable');
+        }
+
+        if (!$actual instanceof Countable && !is_iterable($actual)) {
+            throw InvalidArgumentException::create(2, 'countable or iterable');
+        }
+
+        static::assertThat(
+            $actual,
+            new SameSize($expected),
+            $message
+        );
+    }
+
+    /**
+     * Assert that the size of two arrays (or `Countable` or `Traversable` objects)
+     * is not the same.
+     *
+     * @param Countable|iterable $expected
+     * @param Countable|iterable $actual
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws Exception
+     * @throws ExpectationFailedException
+     */
+    public static function assertNotSameSize($expected, $actual, string $message = ''): void
+    {
+        if (!$expected instanceof Countable && !is_iterable($expected)) {
+            throw InvalidArgumentException::create(1, 'countable or iterable');
+        }
+
+        if (!$actual instanceof Countable && !is_iterable($actual)) {
+            throw InvalidArgumentException::create(2, 'countable or iterable');
+        }
+
+        static::assertThat(
+            $actual,
+            new LogicalNot(
+                new SameSize($expected)
+            ),
+            $message
+        );
+    }
+
+    /**
+     * Asserts that a string matches a given format string.
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws ExpectationFailedException
+     */
+    public static function assertStringMatchesFormat(string $format, string $string, string $message = ''): void
+    {
+        static::assertThat($string, new StringMatchesFormatDescription($format), $message);
+    }
+
+    /**
+     * Asserts that a string does not match a given format string.
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws ExpectationFailedException
+     */
+    public static function assertStringNotMatchesFormat(string $format, string $string, string $message = ''): void
+    {
+        static::assertThat(
+            $string,
+            new LogicalNot(
+                new StringMatchesFormatDescription($format)
+            ),
+            $message
+        );
+    }
+
+    /**
+     * Asserts that a string matches a given format file.
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws ExpectationFailedException
+     */
+    public static function assertStringMatchesFormatFile(string $formatFile, string $string, string $message = ''): void
+    {
+        static::assertFileExists($formatFile, $message);
+
+        static::assertThat(
+            $string,
+            new StringMatchesFormatDescription(
+                file_get_contents($formatFile)
+            ),
+            $message
+        );
+    }
+
+    /**
+     * Asserts that a string does not match a given format string.
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws ExpectationFailedException
+     */
+    public static function assertStringNotMatchesFormatFile(string $formatFile, string $string, string $message = ''): void
+    {
+        static::assertFileExists($formatFile, $message);
+
+        static::assertThat(
+            $string,
+            new LogicalNot(
+                new StringMatchesFormatDescription(
+                    file_get_contents($formatFile)
+                )
+            ),
+            $message
+        );
+    }
+
+    /**
+     * Asserts that a string starts with a given prefix.
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws ExpectationFailedException
+     */
+    public static function assertStringStartsWith(string $prefix, string $string, string $message = ''): void
+    {
+        static::assertThat($string, new StringStartsWith($prefix), $message);
+    }
+
+    /**
+     * Asserts that a string starts not with a given prefix.
+     *
+     * @param string $prefix
+     * @param string $string
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws ExpectationFailedException
+     */
+    public static function assertStringStartsNotWith($prefix, $string, string $message = ''): void
+    {
+        static::assertThat(
+            $string,
+            new LogicalNot(
+                new StringStartsWith($prefix)
+            ),
+            $message
+        );
+    }
+
+    /**
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws ExpectationFailedException
+     */
+    public static function assertStringContainsString(string $needle, string $haystack, string $message = ''): void
+    {
+        $constraint = new StringContains($needle, false);
+
+        static::assertThat($haystack, $constraint, $message);
+    }
+
+    /**
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws ExpectationFailedException
+     */
+    public static function assertStringContainsStringIgnoringCase(string $needle, string $haystack, string $message = ''): void
+    {
+        $constraint = new StringContains($needle, true);
+
+        static::assertThat($haystack, $constraint, $message);
+    }
+
+    /**
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws ExpectationFailedException
+     */
+    public static function assertStringNotContainsString(string $needle, string $haystack, string $message = ''): void
+    {
+        $constraint = new LogicalNot(new StringContains($needle));
+
+        static::assertThat($haystack, $constraint, $message);
+    }
+
+    /**
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws ExpectationFailedException
+     */
+    public static function assertStringNotContainsStringIgnoringCase(string $needle, string $haystack, string $message = ''): void
+    {
+        $constraint = new LogicalNot(new StringContains($needle, true));
+
+        static::assertThat($haystack, $constraint, $message);
+    }
+
+    /**
+     * Asserts that a string ends with a given suffix.
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws ExpectationFailedException
+     */
+    public static function assertStringEndsWith(string $suffix, string $string, string $message = ''): void
+    {
+        static::assertThat($string, new StringEndsWith($suffix), $message);
+    }
+
+    /**
+     * Asserts that a string ends not with a given suffix.
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws ExpectationFailedException
+     */
+    public static function assertStringEndsNotWith(string $suffix, string $string, string $message = ''): void
+    {
+        static::assertThat(
+            $string,
+            new LogicalNot(
+                new StringEndsWith($suffix)
+            ),
+            $message
+        );
+    }
+
+    /**
+     * Asserts that two XML files are equal.
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws Exception
+     * @throws ExpectationFailedException
+     */
+    public static function assertXmlFileEqualsXmlFile(string $expectedFile, string $actualFile, string $message = ''): void
+    {
+        $expected = (new XmlLoader)->loadFile($expectedFile);
+        $actual   = (new XmlLoader)->loadFile($actualFile);
+
+        static::assertEquals($expected, $actual, $message);
+    }
+
+    /**
+     * Asserts that two XML files are not equal.
+     *
+     * @throws \PHPUnit\Util\Exception
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws ExpectationFailedException
+     */
+    public static function assertXmlFileNotEqualsXmlFile(string $expectedFile, string $actualFile, string $message = ''): void
+    {
+        $expected = (new XmlLoader)->loadFile($expectedFile);
+        $actual   = (new XmlLoader)->loadFile($actualFile);
+
+        static::assertNotEquals($expected, $actual, $message);
+    }
+
+    /**
+     * Asserts that two XML documents are equal.
+     *
+     * @param DOMDocument|string $actualXml
+     *
+     * @throws \PHPUnit\Util\Xml\Exception
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws ExpectationFailedException
+     */
+    public static function assertXmlStringEqualsXmlFile(string $expectedFile, $actualXml, string $message = ''): void
+    {
+        if (!is_string($actualXml)) {
+            self::createWarning('Passing an argument of type DOMDocument for the $actualXml parameter is deprecated. Support for this will be removed in PHPUnit 10.');
+
+            $actual = $actualXml;
+        } else {
+            $actual = (new XmlLoader)->load($actualXml);
+        }
+
+        $expected = (new XmlLoader)->loadFile($expectedFile);
+
+        static::assertEquals($expected, $actual, $message);
+    }
+
+    /**
+     * Asserts that two XML documents are not equal.
+     *
+     * @param DOMDocument|string $actualXml
+     *
+     * @throws \PHPUnit\Util\Xml\Exception
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws ExpectationFailedException
+     */
+    public static function assertXmlStringNotEqualsXmlFile(string $expectedFile, $actualXml, string $message = ''): void
+    {
+        if (!is_string($actualXml)) {
+            self::createWarning('Passing an argument of type DOMDocument for the $actualXml parameter is deprecated. Support for this will be removed in PHPUnit 10.');
+
+            $actual = $actualXml;
+        } else {
+            $actual = (new XmlLoader)->load($actualXml);
+        }
+
+        $expected = (new XmlLoader)->loadFile($expectedFile);
+
+        static::assertNotEquals($expected, $actual, $message);
+    }
+
+    /**
+     * Asserts that two XML documents are equal.
+     *
+     * @param DOMDocument|string $expectedXml
+     * @param DOMDocument|string $actualXml
+     *
+     * @throws \PHPUnit\Util\Xml\Exception
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws ExpectationFailedException
+     */
+    public static function assertXmlStringEqualsXmlString($expectedXml, $actualXml, string $message = ''): void
+    {
+        if (!is_string($expectedXml)) {
+            self::createWarning('Passing an argument of type DOMDocument for the $expectedXml parameter is deprecated. Support for this will be removed in PHPUnit 10.');
+
+            $expected = $expectedXml;
+        } else {
+            $expected = (new XmlLoader)->load($expectedXml);
+        }
+
+        if (!is_string($actualXml)) {
+            self::createWarning('Passing an argument of type DOMDocument for the $actualXml parameter is deprecated. Support for this will be removed in PHPUnit 10.');
+
+            $actual = $actualXml;
+        } else {
+            $actual = (new XmlLoader)->load($actualXml);
+        }
+
+        static::assertEquals($expected, $actual, $message);
+    }
+
+    /**
+     * Asserts that two XML documents are not equal.
+     *
+     * @param DOMDocument|string $expectedXml
+     * @param DOMDocument|string $actualXml
+     *
+     * @throws \PHPUnit\Util\Xml\Exception
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws ExpectationFailedException
+     */
+    public static function assertXmlStringNotEqualsXmlString($expectedXml, $actualXml, string $message = ''): void
+    {
+        if (!is_string($expectedXml)) {
+            self::createWarning('Passing an argument of type DOMDocument for the $expectedXml parameter is deprecated. Support for this will be removed in PHPUnit 10.');
+
+            $expected = $expectedXml;
+        } else {
+            $expected = (new XmlLoader)->load($expectedXml);
+        }
+
+        if (!is_string($actualXml)) {
+            self::createWarning('Passing an argument of type DOMDocument for the $actualXml parameter is deprecated. Support for this will be removed in PHPUnit 10.');
+
+            $actual = $actualXml;
+        } else {
+            $actual = (new XmlLoader)->load($actualXml);
+        }
+
+        static::assertNotEquals($expected, $actual, $message);
+    }
+
+    /**
+     * Asserts that a hierarchy of DOMElements matches.
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws AssertionFailedError
+     * @throws ExpectationFailedException
+     *
+     * @codeCoverageIgnore
+     *
+     * @deprecated https://github.com/sebastianbergmann/phpunit/issues/4091
+     */
+    public static function assertEqualXMLStructure(DOMElement $expectedElement, DOMElement $actualElement, bool $checkAttributes = false, string $message = ''): void
+    {
+        self::createWarning('assertEqualXMLStructure() is deprecated and will be removed in PHPUnit 10.');
+
+        $expectedElement = Xml::import($expectedElement);
+        $actualElement   = Xml::import($actualElement);
+
+        static::assertSame(
+            $expectedElement->tagName,
+            $actualElement->tagName,
+            $message
+        );
+
+        if ($checkAttributes) {
+            static::assertSame(
+                $expectedElement->attributes->length,
+                $actualElement->attributes->length,
+                sprintf(
+                    '%s%sNumber of attributes on node "%s" does not match',
+                    $message,
+                    !empty($message) ? "\n" : '',
+                    $expectedElement->tagName
+                )
+            );
+
+            for ($i = 0; $i < $expectedElement->attributes->length; $i++) {
+                $expectedAttribute = $expectedElement->attributes->item($i);
+                $actualAttribute   = $actualElement->attributes->getNamedItem($expectedAttribute->name);
+
+                assert($expectedAttribute instanceof DOMAttr);
+
+                if (!$actualAttribute) {
+                    static::fail(
+                        sprintf(
+                            '%s%sCould not find attribute "%s" on node "%s"',
+                            $message,
+                            !empty($message) ? "\n" : '',
+                            $expectedAttribute->name,
+                            $expectedElement->tagName
+                        )
+                    );
+                }
+            }
+        }
+
+        Xml::removeCharacterDataNodes($expectedElement);
+        Xml::removeCharacterDataNodes($actualElement);
+
+        static::assertSame(
+            $expectedElement->childNodes->length,
+            $actualElement->childNodes->length,
+            sprintf(
+                '%s%sNumber of child nodes of "%s" differs',
+                $message,
+                !empty($message) ? "\n" : '',
+                $expectedElement->tagName
+            )
+        );
+
+        for ($i = 0; $i < $expectedElement->childNodes->length; $i++) {
+            static::assertEqualXMLStructure(
+                $expectedElement->childNodes->item($i),
+                $actualElement->childNodes->item($i),
+                $checkAttributes,
+                $message
+            );
+        }
+    }
+
+    /**
+     * Evaluates a PHPUnit\Framework\Constraint matcher object.
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws ExpectationFailedException
+     */
+    public static function assertThat($value, Constraint $constraint, string $message = ''): void
+    {
+        self::$count += count($constraint);
+
+        $constraint->evaluate($value, $message);
+    }
+
+    /**
+     * Asserts that a string is a valid JSON string.
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws ExpectationFailedException
+     */
+    public static function assertJson(string $actualJson, string $message = ''): void
+    {
+        static::assertThat($actualJson, static::isJson(), $message);
+    }
+
+    /**
+     * Asserts that two given JSON encoded objects or arrays are equal.
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws ExpectationFailedException
+     */
+    public static function assertJsonStringEqualsJsonString(string $expectedJson, string $actualJson, string $message = ''): void
+    {
+        static::assertJson($expectedJson, $message);
+        static::assertJson($actualJson, $message);
+
+        static::assertThat($actualJson, new JsonMatches($expectedJson), $message);
+    }
+
+    /**
+     * Asserts that two given JSON encoded objects or arrays are not equal.
+     *
+     * @param string $expectedJson
+     * @param string $actualJson
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws ExpectationFailedException
+     */
+    public static function assertJsonStringNotEqualsJsonString($expectedJson, $actualJson, string $message = ''): void
+    {
+        static::assertJson($expectedJson, $message);
+        static::assertJson($actualJson, $message);
+
+        static::assertThat(
+            $actualJson,
+            new LogicalNot(
+                new JsonMatches($expectedJson)
+            ),
+            $message
+        );
+    }
+
+    /**
+     * Asserts that the generated JSON encoded object and the content of the given file are equal.
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws ExpectationFailedException
+     */
+    public static function assertJsonStringEqualsJsonFile(string $expectedFile, string $actualJson, string $message = ''): void
+    {
+        static::assertFileExists($expectedFile, $message);
+        $expectedJson = file_get_contents($expectedFile);
+
+        static::assertJson($expectedJson, $message);
+        static::assertJson($actualJson, $message);
+
+        static::assertThat($actualJson, new JsonMatches($expectedJson), $message);
+    }
+
+    /**
+     * Asserts that the generated JSON encoded object and the content of the given file are not equal.
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws ExpectationFailedException
+     */
+    public static function assertJsonStringNotEqualsJsonFile(string $expectedFile, string $actualJson, string $message = ''): void
+    {
+        static::assertFileExists($expectedFile, $message);
+        $expectedJson = file_get_contents($expectedFile);
+
+        static::assertJson($expectedJson, $message);
+        static::assertJson($actualJson, $message);
+
+        static::assertThat(
+            $actualJson,
+            new LogicalNot(
+                new JsonMatches($expectedJson)
+            ),
+            $message
+        );
+    }
+
+    /**
+     * Asserts that two JSON files are equal.
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws ExpectationFailedException
+     */
+    public static function assertJsonFileEqualsJsonFile(string $expectedFile, string $actualFile, string $message = ''): void
+    {
+        static::assertFileExists($expectedFile, $message);
+        static::assertFileExists($actualFile, $message);
+
+        $actualJson   = file_get_contents($actualFile);
+        $expectedJson = file_get_contents($expectedFile);
+
+        static::assertJson($expectedJson, $message);
+        static::assertJson($actualJson, $message);
+
+        $constraintExpected = new JsonMatches(
+            $expectedJson
+        );
+
+        $constraintActual = new JsonMatches($actualJson);
+
+        static::assertThat($expectedJson, $constraintActual, $message);
+        static::assertThat($actualJson, $constraintExpected, $message);
+    }
+
+    /**
+     * Asserts that two JSON files are not equal.
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws ExpectationFailedException
+     */
+    public static function assertJsonFileNotEqualsJsonFile(string $expectedFile, string $actualFile, string $message = ''): void
+    {
+        static::assertFileExists($expectedFile, $message);
+        static::assertFileExists($actualFile, $message);
+
+        $actualJson   = file_get_contents($actualFile);
+        $expectedJson = file_get_contents($expectedFile);
+
+        static::assertJson($expectedJson, $message);
+        static::assertJson($actualJson, $message);
+
+        $constraintExpected = new JsonMatches(
+            $expectedJson
+        );
+
+        $constraintActual = new JsonMatches($actualJson);
+
+        static::assertThat($expectedJson, new LogicalNot($constraintActual), $message);
+        static::assertThat($actualJson, new LogicalNot($constraintExpected), $message);
+    }
+
+    /**
+     * @throws Exception
+     */
+    public static function logicalAnd(): LogicalAnd
+    {
+        $constraints = func_get_args();
+
+        $constraint = new LogicalAnd;
+        $constraint->setConstraints($constraints);
+
+        return $constraint;
+    }
+
+    public static function logicalOr(): LogicalOr
+    {
+        $constraints = func_get_args();
+
+        $constraint = new LogicalOr;
+        $constraint->setConstraints($constraints);
+
+        return $constraint;
+    }
+
+    public static function logicalNot(Constraint $constraint): LogicalNot
+    {
+        return new LogicalNot($constraint);
+    }
+
+    public static function logicalXor(): LogicalXor
+    {
+        $constraints = func_get_args();
+
+        $constraint = new LogicalXor;
+        $constraint->setConstraints($constraints);
+
+        return $constraint;
+    }
+
+    public static function anything(): IsAnything
+    {
+        return new IsAnything;
+    }
+
+    public static function isTrue(): IsTrue
+    {
+        return new IsTrue;
+    }
+
+    /**
+     * @psalm-template CallbackInput of mixed
+     *
+     * @psalm-param callable(CallbackInput $callback): bool $callback
+     *
+     * @psalm-return Callback<CallbackInput>
+     */
+    public static function callback(callable $callback): Callback
+    {
+        return new Callback($callback);
+    }
+
+    public static function isFalse(): IsFalse
+    {
+        return new IsFalse;
+    }
+
+    public static function isJson(): IsJson
+    {
+        return new IsJson;
+    }
+
+    public static function isNull(): IsNull
+    {
+        return new IsNull;
+    }
+
+    public static function isFinite(): IsFinite
+    {
+        return new IsFinite;
+    }
+
+    public static function isInfinite(): IsInfinite
+    {
+        return new IsInfinite;
+    }
+
+    public static function isNan(): IsNan
+    {
+        return new IsNan;
+    }
+
+    public static function containsEqual($value): TraversableContainsEqual
+    {
+        return new TraversableContainsEqual($value);
+    }
+
+    public static function containsIdentical($value): TraversableContainsIdentical
+    {
+        return new TraversableContainsIdentical($value);
+    }
+
+    public static function containsOnly(string $type): TraversableContainsOnly
+    {
+        return new TraversableContainsOnly($type);
+    }
+
+    public static function containsOnlyInstancesOf(string $className): TraversableContainsOnly
+    {
+        return new TraversableContainsOnly($className, false);
+    }
+
+    /**
+     * @param int|string $key
+     */
+    public static function arrayHasKey($key): ArrayHasKey
+    {
+        return new ArrayHasKey($key);
+    }
+
+    public static function equalTo($value): IsEqual
+    {
+        return new IsEqual($value, 0.0, false, false);
+    }
+
+    public static function equalToCanonicalizing($value): IsEqualCanonicalizing
+    {
+        return new IsEqualCanonicalizing($value);
+    }
+
+    public static function equalToIgnoringCase($value): IsEqualIgnoringCase
+    {
+        return new IsEqualIgnoringCase($value);
+    }
+
+    public static function equalToWithDelta($value, float $delta): IsEqualWithDelta
+    {
+        return new IsEqualWithDelta($value, $delta);
+    }
+
+    public static function isEmpty(): IsEmpty
+    {
+        return new IsEmpty;
+    }
+
+    public static function isWritable(): IsWritable
+    {
+        return new IsWritable;
+    }
+
+    public static function isReadable(): IsReadable
+    {
+        return new IsReadable;
+    }
+
+    public static function directoryExists(): DirectoryExists
+    {
+        return new DirectoryExists;
+    }
+
+    public static function fileExists(): FileExists
+    {
+        return new FileExists;
+    }
+
+    public static function greaterThan($value): GreaterThan
+    {
+        return new GreaterThan($value);
+    }
+
+    public static function greaterThanOrEqual($value): LogicalOr
+    {
+        return static::logicalOr(
+            new IsEqual($value),
+            new GreaterThan($value)
+        );
+    }
+
+    public static function classHasAttribute(string $attributeName): ClassHasAttribute
+    {
+        return new ClassHasAttribute($attributeName);
+    }
+
+    public static function classHasStaticAttribute(string $attributeName): ClassHasStaticAttribute
+    {
+        return new ClassHasStaticAttribute($attributeName);
+    }
+
+    public static function objectHasAttribute($attributeName): ObjectHasAttribute
+    {
+        return new ObjectHasAttribute($attributeName);
+    }
+
+    public static function identicalTo($value): IsIdentical
+    {
+        return new IsIdentical($value);
+    }
+
+    public static function isInstanceOf(string $className): IsInstanceOf
+    {
+        return new IsInstanceOf($className);
+    }
+
+    public static function isType(string $type): IsType
+    {
+        return new IsType($type);
+    }
+
+    public static function lessThan($value): LessThan
+    {
+        return new LessThan($value);
+    }
+
+    public static function lessThanOrEqual($value): LogicalOr
+    {
+        return static::logicalOr(
+            new IsEqual($value),
+            new LessThan($value)
+        );
+    }
+
+    public static function matchesRegularExpression(string $pattern): RegularExpression
+    {
+        return new RegularExpression($pattern);
+    }
+
+    public static function matches(string $string): StringMatchesFormatDescription
+    {
+        return new StringMatchesFormatDescription($string);
+    }
+
+    public static function stringStartsWith($prefix): StringStartsWith
+    {
+        return new StringStartsWith($prefix);
+    }
+
+    public static function stringContains(string $string, bool $case = true): StringContains
+    {
+        return new StringContains($string, $case);
+    }
+
+    public static function stringEndsWith(string $suffix): StringEndsWith
+    {
+        return new StringEndsWith($suffix);
+    }
+
+    public static function countOf(int $count): Count
+    {
+        return new Count($count);
+    }
+
+    public static function objectEquals(object $object, string $method = 'equals'): ObjectEquals
+    {
+        return new ObjectEquals($object, $method);
+    }
+
+    /**
+     * Fails a test with the given message.
+     *
+     * @throws AssertionFailedError
+     *
+     * @psalm-return never-return
+     */
+    public static function fail(string $message = ''): void
+    {
+        self::$count++;
+
+        throw new AssertionFailedError($message);
+    }
+
+    /**
+     * Mark the test as incomplete.
+     *
+     * @throws IncompleteTestError
+     *
+     * @psalm-return never-return
+     */
+    public static function markTestIncomplete(string $message = ''): void
+    {
+        throw new IncompleteTestError($message);
+    }
+
+    /**
+     * Mark the test as skipped.
+     *
+     * @throws SkippedTestError
+     * @throws SyntheticSkippedError
+     *
+     * @psalm-return never-return
+     */
+    public static function markTestSkipped(string $message = ''): void
+    {
+        if ($hint = self::detectLocationHint($message)) {
+            $trace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);
+            array_unshift($trace, $hint);
+
+            throw new SyntheticSkippedError($hint['message'], 0, $hint['file'], (int) $hint['line'], $trace);
+        }
+
+        throw new SkippedTestError($message);
+    }
+
+    /**
+     * Return the current assertion count.
+     */
+    public static function getCount(): int
+    {
+        return self::$count;
+    }
+
+    /**
+     * Reset the assertion counter.
+     */
+    public static function resetCount(): void
+    {
+        self::$count = 0;
+    }
+
+    private static function detectLocationHint(string $message): ?array
+    {
+        $hint  = null;
+        $lines = preg_split('/\r\n|\r|\n/', $message);
+
+        while (strpos($lines[0], '__OFFSET') !== false) {
+            $offset = explode('=', array_shift($lines));
+
+            if ($offset[0] === '__OFFSET_FILE') {
+                $hint['file'] = $offset[1];
+            }
+
+            if ($offset[0] === '__OFFSET_LINE') {
+                $hint['line'] = $offset[1];
+            }
+        }
+
+        if ($hint) {
+            $hint['message'] = implode(PHP_EOL, $lines);
+        }
+
+        return $hint;
+    }
+
+    private static function isValidObjectAttributeName(string $attributeName): bool
+    {
+        return (bool) preg_match('/[^\x00-\x1f\x7f-\x9f]+/', $attributeName);
+    }
+
+    private static function isValidClassAttributeName(string $attributeName): bool
+    {
+        return (bool) preg_match('/[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*/', $attributeName);
+    }
+
+    /**
+     * @codeCoverageIgnore
+     */
+    private static function createWarning(string $warning): void
+    {
+        foreach (debug_backtrace() as $step) {
+            if (isset($step['object']) && $step['object'] instanceof TestCase) {
+                assert($step['object'] instanceof TestCase);
+
+                $step['object']->addWarning($warning);
+
+                break;
+            }
+        }
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/Assert/Functions.php b/vendor/phpunit/phpunit/src/Framework/Assert/Functions.php
new file mode 100644
index 0000000000000000000000000000000000000000..7c4831d0f64819ed9a8c9edf65fbbbb19f55f45c
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/Assert/Functions.php
@@ -0,0 +1,3035 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework;
+
+use function func_get_args;
+use ArrayAccess;
+use Countable;
+use DOMDocument;
+use DOMElement;
+use PHPUnit\Framework\Constraint\ArrayHasKey;
+use PHPUnit\Framework\Constraint\Callback;
+use PHPUnit\Framework\Constraint\ClassHasAttribute;
+use PHPUnit\Framework\Constraint\ClassHasStaticAttribute;
+use PHPUnit\Framework\Constraint\Constraint;
+use PHPUnit\Framework\Constraint\Count;
+use PHPUnit\Framework\Constraint\DirectoryExists;
+use PHPUnit\Framework\Constraint\FileExists;
+use PHPUnit\Framework\Constraint\GreaterThan;
+use PHPUnit\Framework\Constraint\IsAnything;
+use PHPUnit\Framework\Constraint\IsEmpty;
+use PHPUnit\Framework\Constraint\IsEqual;
+use PHPUnit\Framework\Constraint\IsEqualCanonicalizing;
+use PHPUnit\Framework\Constraint\IsEqualIgnoringCase;
+use PHPUnit\Framework\Constraint\IsEqualWithDelta;
+use PHPUnit\Framework\Constraint\IsFalse;
+use PHPUnit\Framework\Constraint\IsFinite;
+use PHPUnit\Framework\Constraint\IsIdentical;
+use PHPUnit\Framework\Constraint\IsInfinite;
+use PHPUnit\Framework\Constraint\IsInstanceOf;
+use PHPUnit\Framework\Constraint\IsJson;
+use PHPUnit\Framework\Constraint\IsNan;
+use PHPUnit\Framework\Constraint\IsNull;
+use PHPUnit\Framework\Constraint\IsReadable;
+use PHPUnit\Framework\Constraint\IsTrue;
+use PHPUnit\Framework\Constraint\IsType;
+use PHPUnit\Framework\Constraint\IsWritable;
+use PHPUnit\Framework\Constraint\LessThan;
+use PHPUnit\Framework\Constraint\LogicalAnd;
+use PHPUnit\Framework\Constraint\LogicalNot;
+use PHPUnit\Framework\Constraint\LogicalOr;
+use PHPUnit\Framework\Constraint\LogicalXor;
+use PHPUnit\Framework\Constraint\ObjectEquals;
+use PHPUnit\Framework\Constraint\ObjectHasAttribute;
+use PHPUnit\Framework\Constraint\RegularExpression;
+use PHPUnit\Framework\Constraint\StringContains;
+use PHPUnit\Framework\Constraint\StringEndsWith;
+use PHPUnit\Framework\Constraint\StringMatchesFormatDescription;
+use PHPUnit\Framework\Constraint\StringStartsWith;
+use PHPUnit\Framework\Constraint\TraversableContainsEqual;
+use PHPUnit\Framework\Constraint\TraversableContainsIdentical;
+use PHPUnit\Framework\Constraint\TraversableContainsOnly;
+use PHPUnit\Framework\MockObject\Rule\AnyInvokedCount as AnyInvokedCountMatcher;
+use PHPUnit\Framework\MockObject\Rule\InvokedAtIndex as InvokedAtIndexMatcher;
+use PHPUnit\Framework\MockObject\Rule\InvokedAtLeastCount as InvokedAtLeastCountMatcher;
+use PHPUnit\Framework\MockObject\Rule\InvokedAtLeastOnce as InvokedAtLeastOnceMatcher;
+use PHPUnit\Framework\MockObject\Rule\InvokedAtMostCount as InvokedAtMostCountMatcher;
+use PHPUnit\Framework\MockObject\Rule\InvokedCount as InvokedCountMatcher;
+use PHPUnit\Framework\MockObject\Stub\ConsecutiveCalls as ConsecutiveCallsStub;
+use PHPUnit\Framework\MockObject\Stub\Exception as ExceptionStub;
+use PHPUnit\Framework\MockObject\Stub\ReturnArgument as ReturnArgumentStub;
+use PHPUnit\Framework\MockObject\Stub\ReturnCallback as ReturnCallbackStub;
+use PHPUnit\Framework\MockObject\Stub\ReturnSelf as ReturnSelfStub;
+use PHPUnit\Framework\MockObject\Stub\ReturnStub;
+use PHPUnit\Framework\MockObject\Stub\ReturnValueMap as ReturnValueMapStub;
+use Throwable;
+
+if (!function_exists('PHPUnit\Framework\assertArrayHasKey')) {
+    /**
+     * Asserts that an array has a specified key.
+     *
+     * @param int|string        $key
+     * @param array|ArrayAccess $array
+     *
+     * @throws ExpectationFailedException
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws Exception
+     *
+     * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+     *
+     * @see Assert::assertArrayHasKey
+     */
+    function assertArrayHasKey($key, $array, string $message = ''): void
+    {
+        Assert::assertArrayHasKey(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\assertArrayNotHasKey')) {
+    /**
+     * Asserts that an array does not have a specified key.
+     *
+     * @param int|string        $key
+     * @param array|ArrayAccess $array
+     *
+     * @throws ExpectationFailedException
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws Exception
+     *
+     * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+     *
+     * @see Assert::assertArrayNotHasKey
+     */
+    function assertArrayNotHasKey($key, $array, string $message = ''): void
+    {
+        Assert::assertArrayNotHasKey(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\assertContains')) {
+    /**
+     * Asserts that a haystack contains a needle.
+     *
+     * @throws ExpectationFailedException
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws Exception
+     *
+     * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+     *
+     * @see Assert::assertContains
+     */
+    function assertContains($needle, iterable $haystack, string $message = ''): void
+    {
+        Assert::assertContains(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\assertContainsEquals')) {
+    function assertContainsEquals($needle, iterable $haystack, string $message = ''): void
+    {
+        Assert::assertContainsEquals(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\assertNotContains')) {
+    /**
+     * Asserts that a haystack does not contain a needle.
+     *
+     * @throws ExpectationFailedException
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws Exception
+     *
+     * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+     *
+     * @see Assert::assertNotContains
+     */
+    function assertNotContains($needle, iterable $haystack, string $message = ''): void
+    {
+        Assert::assertNotContains(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\assertNotContainsEquals')) {
+    function assertNotContainsEquals($needle, iterable $haystack, string $message = ''): void
+    {
+        Assert::assertNotContainsEquals(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\assertContainsOnly')) {
+    /**
+     * Asserts that a haystack contains only values of a given type.
+     *
+     * @throws ExpectationFailedException
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     *
+     * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+     *
+     * @see Assert::assertContainsOnly
+     */
+    function assertContainsOnly(string $type, iterable $haystack, ?bool $isNativeType = null, string $message = ''): void
+    {
+        Assert::assertContainsOnly(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\assertContainsOnlyInstancesOf')) {
+    /**
+     * Asserts that a haystack contains only instances of a given class name.
+     *
+     * @throws ExpectationFailedException
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     *
+     * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+     *
+     * @see Assert::assertContainsOnlyInstancesOf
+     */
+    function assertContainsOnlyInstancesOf(string $className, iterable $haystack, string $message = ''): void
+    {
+        Assert::assertContainsOnlyInstancesOf(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\assertNotContainsOnly')) {
+    /**
+     * Asserts that a haystack does not contain only values of a given type.
+     *
+     * @throws ExpectationFailedException
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     *
+     * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+     *
+     * @see Assert::assertNotContainsOnly
+     */
+    function assertNotContainsOnly(string $type, iterable $haystack, ?bool $isNativeType = null, string $message = ''): void
+    {
+        Assert::assertNotContainsOnly(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\assertCount')) {
+    /**
+     * Asserts the number of elements of an array, Countable or Traversable.
+     *
+     * @param Countable|iterable $haystack
+     *
+     * @throws ExpectationFailedException
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws Exception
+     *
+     * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+     *
+     * @see Assert::assertCount
+     */
+    function assertCount(int $expectedCount, $haystack, string $message = ''): void
+    {
+        Assert::assertCount(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\assertNotCount')) {
+    /**
+     * Asserts the number of elements of an array, Countable or Traversable.
+     *
+     * @param Countable|iterable $haystack
+     *
+     * @throws ExpectationFailedException
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws Exception
+     *
+     * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+     *
+     * @see Assert::assertNotCount
+     */
+    function assertNotCount(int $expectedCount, $haystack, string $message = ''): void
+    {
+        Assert::assertNotCount(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\assertEquals')) {
+    /**
+     * Asserts that two variables are equal.
+     *
+     * @throws ExpectationFailedException
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     *
+     * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+     *
+     * @see Assert::assertEquals
+     */
+    function assertEquals($expected, $actual, string $message = ''): void
+    {
+        Assert::assertEquals(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\assertEqualsCanonicalizing')) {
+    /**
+     * Asserts that two variables are equal (canonicalizing).
+     *
+     * @throws ExpectationFailedException
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     *
+     * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+     *
+     * @see Assert::assertEqualsCanonicalizing
+     */
+    function assertEqualsCanonicalizing($expected, $actual, string $message = ''): void
+    {
+        Assert::assertEqualsCanonicalizing(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\assertEqualsIgnoringCase')) {
+    /**
+     * Asserts that two variables are equal (ignoring case).
+     *
+     * @throws ExpectationFailedException
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     *
+     * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+     *
+     * @see Assert::assertEqualsIgnoringCase
+     */
+    function assertEqualsIgnoringCase($expected, $actual, string $message = ''): void
+    {
+        Assert::assertEqualsIgnoringCase(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\assertEqualsWithDelta')) {
+    /**
+     * Asserts that two variables are equal (with delta).
+     *
+     * @throws ExpectationFailedException
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     *
+     * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+     *
+     * @see Assert::assertEqualsWithDelta
+     */
+    function assertEqualsWithDelta($expected, $actual, float $delta, string $message = ''): void
+    {
+        Assert::assertEqualsWithDelta(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\assertNotEquals')) {
+    /**
+     * Asserts that two variables are not equal.
+     *
+     * @throws ExpectationFailedException
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     *
+     * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+     *
+     * @see Assert::assertNotEquals
+     */
+    function assertNotEquals($expected, $actual, string $message = ''): void
+    {
+        Assert::assertNotEquals(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\assertNotEqualsCanonicalizing')) {
+    /**
+     * Asserts that two variables are not equal (canonicalizing).
+     *
+     * @throws ExpectationFailedException
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     *
+     * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+     *
+     * @see Assert::assertNotEqualsCanonicalizing
+     */
+    function assertNotEqualsCanonicalizing($expected, $actual, string $message = ''): void
+    {
+        Assert::assertNotEqualsCanonicalizing(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\assertNotEqualsIgnoringCase')) {
+    /**
+     * Asserts that two variables are not equal (ignoring case).
+     *
+     * @throws ExpectationFailedException
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     *
+     * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+     *
+     * @see Assert::assertNotEqualsIgnoringCase
+     */
+    function assertNotEqualsIgnoringCase($expected, $actual, string $message = ''): void
+    {
+        Assert::assertNotEqualsIgnoringCase(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\assertNotEqualsWithDelta')) {
+    /**
+     * Asserts that two variables are not equal (with delta).
+     *
+     * @throws ExpectationFailedException
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     *
+     * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+     *
+     * @see Assert::assertNotEqualsWithDelta
+     */
+    function assertNotEqualsWithDelta($expected, $actual, float $delta, string $message = ''): void
+    {
+        Assert::assertNotEqualsWithDelta(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\assertObjectEquals')) {
+    /**
+     * @throws ExpectationFailedException
+     *
+     * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+     *
+     * @see Assert::assertObjectEquals
+     */
+    function assertObjectEquals(object $expected, object $actual, string $method = 'equals', string $message = ''): void
+    {
+        Assert::assertObjectEquals(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\assertEmpty')) {
+    /**
+     * Asserts that a variable is empty.
+     *
+     * @throws ExpectationFailedException
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     *
+     * @psalm-assert empty $actual
+     *
+     * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+     *
+     * @see Assert::assertEmpty
+     */
+    function assertEmpty($actual, string $message = ''): void
+    {
+        Assert::assertEmpty(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\assertNotEmpty')) {
+    /**
+     * Asserts that a variable is not empty.
+     *
+     * @throws ExpectationFailedException
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     *
+     * @psalm-assert !empty $actual
+     *
+     * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+     *
+     * @see Assert::assertNotEmpty
+     */
+    function assertNotEmpty($actual, string $message = ''): void
+    {
+        Assert::assertNotEmpty(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\assertGreaterThan')) {
+    /**
+     * Asserts that a value is greater than another value.
+     *
+     * @throws ExpectationFailedException
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     *
+     * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+     *
+     * @see Assert::assertGreaterThan
+     */
+    function assertGreaterThan($expected, $actual, string $message = ''): void
+    {
+        Assert::assertGreaterThan(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\assertGreaterThanOrEqual')) {
+    /**
+     * Asserts that a value is greater than or equal to another value.
+     *
+     * @throws ExpectationFailedException
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     *
+     * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+     *
+     * @see Assert::assertGreaterThanOrEqual
+     */
+    function assertGreaterThanOrEqual($expected, $actual, string $message = ''): void
+    {
+        Assert::assertGreaterThanOrEqual(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\assertLessThan')) {
+    /**
+     * Asserts that a value is smaller than another value.
+     *
+     * @throws ExpectationFailedException
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     *
+     * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+     *
+     * @see Assert::assertLessThan
+     */
+    function assertLessThan($expected, $actual, string $message = ''): void
+    {
+        Assert::assertLessThan(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\assertLessThanOrEqual')) {
+    /**
+     * Asserts that a value is smaller than or equal to another value.
+     *
+     * @throws ExpectationFailedException
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     *
+     * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+     *
+     * @see Assert::assertLessThanOrEqual
+     */
+    function assertLessThanOrEqual($expected, $actual, string $message = ''): void
+    {
+        Assert::assertLessThanOrEqual(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\assertFileEquals')) {
+    /**
+     * Asserts that the contents of one file is equal to the contents of another
+     * file.
+     *
+     * @throws ExpectationFailedException
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     *
+     * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+     *
+     * @see Assert::assertFileEquals
+     */
+    function assertFileEquals(string $expected, string $actual, string $message = ''): void
+    {
+        Assert::assertFileEquals(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\assertFileEqualsCanonicalizing')) {
+    /**
+     * Asserts that the contents of one file is equal to the contents of another
+     * file (canonicalizing).
+     *
+     * @throws ExpectationFailedException
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     *
+     * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+     *
+     * @see Assert::assertFileEqualsCanonicalizing
+     */
+    function assertFileEqualsCanonicalizing(string $expected, string $actual, string $message = ''): void
+    {
+        Assert::assertFileEqualsCanonicalizing(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\assertFileEqualsIgnoringCase')) {
+    /**
+     * Asserts that the contents of one file is equal to the contents of another
+     * file (ignoring case).
+     *
+     * @throws ExpectationFailedException
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     *
+     * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+     *
+     * @see Assert::assertFileEqualsIgnoringCase
+     */
+    function assertFileEqualsIgnoringCase(string $expected, string $actual, string $message = ''): void
+    {
+        Assert::assertFileEqualsIgnoringCase(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\assertFileNotEquals')) {
+    /**
+     * Asserts that the contents of one file is not equal to the contents of
+     * another file.
+     *
+     * @throws ExpectationFailedException
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     *
+     * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+     *
+     * @see Assert::assertFileNotEquals
+     */
+    function assertFileNotEquals(string $expected, string $actual, string $message = ''): void
+    {
+        Assert::assertFileNotEquals(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\assertFileNotEqualsCanonicalizing')) {
+    /**
+     * Asserts that the contents of one file is not equal to the contents of another
+     * file (canonicalizing).
+     *
+     * @throws ExpectationFailedException
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     *
+     * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+     *
+     * @see Assert::assertFileNotEqualsCanonicalizing
+     */
+    function assertFileNotEqualsCanonicalizing(string $expected, string $actual, string $message = ''): void
+    {
+        Assert::assertFileNotEqualsCanonicalizing(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\assertFileNotEqualsIgnoringCase')) {
+    /**
+     * Asserts that the contents of one file is not equal to the contents of another
+     * file (ignoring case).
+     *
+     * @throws ExpectationFailedException
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     *
+     * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+     *
+     * @see Assert::assertFileNotEqualsIgnoringCase
+     */
+    function assertFileNotEqualsIgnoringCase(string $expected, string $actual, string $message = ''): void
+    {
+        Assert::assertFileNotEqualsIgnoringCase(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\assertStringEqualsFile')) {
+    /**
+     * Asserts that the contents of a string is equal
+     * to the contents of a file.
+     *
+     * @throws ExpectationFailedException
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     *
+     * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+     *
+     * @see Assert::assertStringEqualsFile
+     */
+    function assertStringEqualsFile(string $expectedFile, string $actualString, string $message = ''): void
+    {
+        Assert::assertStringEqualsFile(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\assertStringEqualsFileCanonicalizing')) {
+    /**
+     * Asserts that the contents of a string is equal
+     * to the contents of a file (canonicalizing).
+     *
+     * @throws ExpectationFailedException
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     *
+     * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+     *
+     * @see Assert::assertStringEqualsFileCanonicalizing
+     */
+    function assertStringEqualsFileCanonicalizing(string $expectedFile, string $actualString, string $message = ''): void
+    {
+        Assert::assertStringEqualsFileCanonicalizing(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\assertStringEqualsFileIgnoringCase')) {
+    /**
+     * Asserts that the contents of a string is equal
+     * to the contents of a file (ignoring case).
+     *
+     * @throws ExpectationFailedException
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     *
+     * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+     *
+     * @see Assert::assertStringEqualsFileIgnoringCase
+     */
+    function assertStringEqualsFileIgnoringCase(string $expectedFile, string $actualString, string $message = ''): void
+    {
+        Assert::assertStringEqualsFileIgnoringCase(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\assertStringNotEqualsFile')) {
+    /**
+     * Asserts that the contents of a string is not equal
+     * to the contents of a file.
+     *
+     * @throws ExpectationFailedException
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     *
+     * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+     *
+     * @see Assert::assertStringNotEqualsFile
+     */
+    function assertStringNotEqualsFile(string $expectedFile, string $actualString, string $message = ''): void
+    {
+        Assert::assertStringNotEqualsFile(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\assertStringNotEqualsFileCanonicalizing')) {
+    /**
+     * Asserts that the contents of a string is not equal
+     * to the contents of a file (canonicalizing).
+     *
+     * @throws ExpectationFailedException
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     *
+     * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+     *
+     * @see Assert::assertStringNotEqualsFileCanonicalizing
+     */
+    function assertStringNotEqualsFileCanonicalizing(string $expectedFile, string $actualString, string $message = ''): void
+    {
+        Assert::assertStringNotEqualsFileCanonicalizing(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\assertStringNotEqualsFileIgnoringCase')) {
+    /**
+     * Asserts that the contents of a string is not equal
+     * to the contents of a file (ignoring case).
+     *
+     * @throws ExpectationFailedException
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     *
+     * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+     *
+     * @see Assert::assertStringNotEqualsFileIgnoringCase
+     */
+    function assertStringNotEqualsFileIgnoringCase(string $expectedFile, string $actualString, string $message = ''): void
+    {
+        Assert::assertStringNotEqualsFileIgnoringCase(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\assertIsReadable')) {
+    /**
+     * Asserts that a file/dir is readable.
+     *
+     * @throws ExpectationFailedException
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     *
+     * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+     *
+     * @see Assert::assertIsReadable
+     */
+    function assertIsReadable(string $filename, string $message = ''): void
+    {
+        Assert::assertIsReadable(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\assertIsNotReadable')) {
+    /**
+     * Asserts that a file/dir exists and is not readable.
+     *
+     * @throws ExpectationFailedException
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     *
+     * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+     *
+     * @see Assert::assertIsNotReadable
+     */
+    function assertIsNotReadable(string $filename, string $message = ''): void
+    {
+        Assert::assertIsNotReadable(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\assertNotIsReadable')) {
+    /**
+     * Asserts that a file/dir exists and is not readable.
+     *
+     * @throws ExpectationFailedException
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     *
+     * @codeCoverageIgnore
+     *
+     * @deprecated https://github.com/sebastianbergmann/phpunit/issues/4062
+     *
+     * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+     *
+     * @see Assert::assertNotIsReadable
+     */
+    function assertNotIsReadable(string $filename, string $message = ''): void
+    {
+        Assert::assertNotIsReadable(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\assertIsWritable')) {
+    /**
+     * Asserts that a file/dir exists and is writable.
+     *
+     * @throws ExpectationFailedException
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     *
+     * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+     *
+     * @see Assert::assertIsWritable
+     */
+    function assertIsWritable(string $filename, string $message = ''): void
+    {
+        Assert::assertIsWritable(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\assertIsNotWritable')) {
+    /**
+     * Asserts that a file/dir exists and is not writable.
+     *
+     * @throws ExpectationFailedException
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     *
+     * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+     *
+     * @see Assert::assertIsNotWritable
+     */
+    function assertIsNotWritable(string $filename, string $message = ''): void
+    {
+        Assert::assertIsNotWritable(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\assertNotIsWritable')) {
+    /**
+     * Asserts that a file/dir exists and is not writable.
+     *
+     * @throws ExpectationFailedException
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     *
+     * @codeCoverageIgnore
+     *
+     * @deprecated https://github.com/sebastianbergmann/phpunit/issues/4065
+     *
+     * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+     *
+     * @see Assert::assertNotIsWritable
+     */
+    function assertNotIsWritable(string $filename, string $message = ''): void
+    {
+        Assert::assertNotIsWritable(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\assertDirectoryExists')) {
+    /**
+     * Asserts that a directory exists.
+     *
+     * @throws ExpectationFailedException
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     *
+     * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+     *
+     * @see Assert::assertDirectoryExists
+     */
+    function assertDirectoryExists(string $directory, string $message = ''): void
+    {
+        Assert::assertDirectoryExists(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\assertDirectoryDoesNotExist')) {
+    /**
+     * Asserts that a directory does not exist.
+     *
+     * @throws ExpectationFailedException
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     *
+     * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+     *
+     * @see Assert::assertDirectoryDoesNotExist
+     */
+    function assertDirectoryDoesNotExist(string $directory, string $message = ''): void
+    {
+        Assert::assertDirectoryDoesNotExist(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\assertDirectoryNotExists')) {
+    /**
+     * Asserts that a directory does not exist.
+     *
+     * @throws ExpectationFailedException
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     *
+     * @codeCoverageIgnore
+     *
+     * @deprecated https://github.com/sebastianbergmann/phpunit/issues/4068
+     *
+     * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+     *
+     * @see Assert::assertDirectoryNotExists
+     */
+    function assertDirectoryNotExists(string $directory, string $message = ''): void
+    {
+        Assert::assertDirectoryNotExists(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\assertDirectoryIsReadable')) {
+    /**
+     * Asserts that a directory exists and is readable.
+     *
+     * @throws ExpectationFailedException
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     *
+     * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+     *
+     * @see Assert::assertDirectoryIsReadable
+     */
+    function assertDirectoryIsReadable(string $directory, string $message = ''): void
+    {
+        Assert::assertDirectoryIsReadable(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\assertDirectoryIsNotReadable')) {
+    /**
+     * Asserts that a directory exists and is not readable.
+     *
+     * @throws ExpectationFailedException
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     *
+     * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+     *
+     * @see Assert::assertDirectoryIsNotReadable
+     */
+    function assertDirectoryIsNotReadable(string $directory, string $message = ''): void
+    {
+        Assert::assertDirectoryIsNotReadable(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\assertDirectoryNotIsReadable')) {
+    /**
+     * Asserts that a directory exists and is not readable.
+     *
+     * @throws ExpectationFailedException
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     *
+     * @codeCoverageIgnore
+     *
+     * @deprecated https://github.com/sebastianbergmann/phpunit/issues/4071
+     *
+     * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+     *
+     * @see Assert::assertDirectoryNotIsReadable
+     */
+    function assertDirectoryNotIsReadable(string $directory, string $message = ''): void
+    {
+        Assert::assertDirectoryNotIsReadable(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\assertDirectoryIsWritable')) {
+    /**
+     * Asserts that a directory exists and is writable.
+     *
+     * @throws ExpectationFailedException
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     *
+     * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+     *
+     * @see Assert::assertDirectoryIsWritable
+     */
+    function assertDirectoryIsWritable(string $directory, string $message = ''): void
+    {
+        Assert::assertDirectoryIsWritable(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\assertDirectoryIsNotWritable')) {
+    /**
+     * Asserts that a directory exists and is not writable.
+     *
+     * @throws ExpectationFailedException
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     *
+     * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+     *
+     * @see Assert::assertDirectoryIsNotWritable
+     */
+    function assertDirectoryIsNotWritable(string $directory, string $message = ''): void
+    {
+        Assert::assertDirectoryIsNotWritable(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\assertDirectoryNotIsWritable')) {
+    /**
+     * Asserts that a directory exists and is not writable.
+     *
+     * @throws ExpectationFailedException
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     *
+     * @codeCoverageIgnore
+     *
+     * @deprecated https://github.com/sebastianbergmann/phpunit/issues/4074
+     *
+     * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+     *
+     * @see Assert::assertDirectoryNotIsWritable
+     */
+    function assertDirectoryNotIsWritable(string $directory, string $message = ''): void
+    {
+        Assert::assertDirectoryNotIsWritable(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\assertFileExists')) {
+    /**
+     * Asserts that a file exists.
+     *
+     * @throws ExpectationFailedException
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     *
+     * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+     *
+     * @see Assert::assertFileExists
+     */
+    function assertFileExists(string $filename, string $message = ''): void
+    {
+        Assert::assertFileExists(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\assertFileDoesNotExist')) {
+    /**
+     * Asserts that a file does not exist.
+     *
+     * @throws ExpectationFailedException
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     *
+     * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+     *
+     * @see Assert::assertFileDoesNotExist
+     */
+    function assertFileDoesNotExist(string $filename, string $message = ''): void
+    {
+        Assert::assertFileDoesNotExist(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\assertFileNotExists')) {
+    /**
+     * Asserts that a file does not exist.
+     *
+     * @throws ExpectationFailedException
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     *
+     * @codeCoverageIgnore
+     *
+     * @deprecated https://github.com/sebastianbergmann/phpunit/issues/4077
+     *
+     * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+     *
+     * @see Assert::assertFileNotExists
+     */
+    function assertFileNotExists(string $filename, string $message = ''): void
+    {
+        Assert::assertFileNotExists(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\assertFileIsReadable')) {
+    /**
+     * Asserts that a file exists and is readable.
+     *
+     * @throws ExpectationFailedException
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     *
+     * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+     *
+     * @see Assert::assertFileIsReadable
+     */
+    function assertFileIsReadable(string $file, string $message = ''): void
+    {
+        Assert::assertFileIsReadable(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\assertFileIsNotReadable')) {
+    /**
+     * Asserts that a file exists and is not readable.
+     *
+     * @throws ExpectationFailedException
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     *
+     * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+     *
+     * @see Assert::assertFileIsNotReadable
+     */
+    function assertFileIsNotReadable(string $file, string $message = ''): void
+    {
+        Assert::assertFileIsNotReadable(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\assertFileNotIsReadable')) {
+    /**
+     * Asserts that a file exists and is not readable.
+     *
+     * @throws ExpectationFailedException
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     *
+     * @codeCoverageIgnore
+     *
+     * @deprecated https://github.com/sebastianbergmann/phpunit/issues/4080
+     *
+     * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+     *
+     * @see Assert::assertFileNotIsReadable
+     */
+    function assertFileNotIsReadable(string $file, string $message = ''): void
+    {
+        Assert::assertFileNotIsReadable(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\assertFileIsWritable')) {
+    /**
+     * Asserts that a file exists and is writable.
+     *
+     * @throws ExpectationFailedException
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     *
+     * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+     *
+     * @see Assert::assertFileIsWritable
+     */
+    function assertFileIsWritable(string $file, string $message = ''): void
+    {
+        Assert::assertFileIsWritable(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\assertFileIsNotWritable')) {
+    /**
+     * Asserts that a file exists and is not writable.
+     *
+     * @throws ExpectationFailedException
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     *
+     * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+     *
+     * @see Assert::assertFileIsNotWritable
+     */
+    function assertFileIsNotWritable(string $file, string $message = ''): void
+    {
+        Assert::assertFileIsNotWritable(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\assertFileNotIsWritable')) {
+    /**
+     * Asserts that a file exists and is not writable.
+     *
+     * @throws ExpectationFailedException
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     *
+     * @codeCoverageIgnore
+     *
+     * @deprecated https://github.com/sebastianbergmann/phpunit/issues/4083
+     *
+     * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+     *
+     * @see Assert::assertFileNotIsWritable
+     */
+    function assertFileNotIsWritable(string $file, string $message = ''): void
+    {
+        Assert::assertFileNotIsWritable(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\assertTrue')) {
+    /**
+     * Asserts that a condition is true.
+     *
+     * @throws ExpectationFailedException
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     *
+     * @psalm-assert true $condition
+     *
+     * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+     *
+     * @see Assert::assertTrue
+     */
+    function assertTrue($condition, string $message = ''): void
+    {
+        Assert::assertTrue(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\assertNotTrue')) {
+    /**
+     * Asserts that a condition is not true.
+     *
+     * @throws ExpectationFailedException
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     *
+     * @psalm-assert !true $condition
+     *
+     * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+     *
+     * @see Assert::assertNotTrue
+     */
+    function assertNotTrue($condition, string $message = ''): void
+    {
+        Assert::assertNotTrue(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\assertFalse')) {
+    /**
+     * Asserts that a condition is false.
+     *
+     * @throws ExpectationFailedException
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     *
+     * @psalm-assert false $condition
+     *
+     * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+     *
+     * @see Assert::assertFalse
+     */
+    function assertFalse($condition, string $message = ''): void
+    {
+        Assert::assertFalse(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\assertNotFalse')) {
+    /**
+     * Asserts that a condition is not false.
+     *
+     * @throws ExpectationFailedException
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     *
+     * @psalm-assert !false $condition
+     *
+     * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+     *
+     * @see Assert::assertNotFalse
+     */
+    function assertNotFalse($condition, string $message = ''): void
+    {
+        Assert::assertNotFalse(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\assertNull')) {
+    /**
+     * Asserts that a variable is null.
+     *
+     * @throws ExpectationFailedException
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     *
+     * @psalm-assert null $actual
+     *
+     * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+     *
+     * @see Assert::assertNull
+     */
+    function assertNull($actual, string $message = ''): void
+    {
+        Assert::assertNull(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\assertNotNull')) {
+    /**
+     * Asserts that a variable is not null.
+     *
+     * @throws ExpectationFailedException
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     *
+     * @psalm-assert !null $actual
+     *
+     * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+     *
+     * @see Assert::assertNotNull
+     */
+    function assertNotNull($actual, string $message = ''): void
+    {
+        Assert::assertNotNull(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\assertFinite')) {
+    /**
+     * Asserts that a variable is finite.
+     *
+     * @throws ExpectationFailedException
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     *
+     * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+     *
+     * @see Assert::assertFinite
+     */
+    function assertFinite($actual, string $message = ''): void
+    {
+        Assert::assertFinite(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\assertInfinite')) {
+    /**
+     * Asserts that a variable is infinite.
+     *
+     * @throws ExpectationFailedException
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     *
+     * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+     *
+     * @see Assert::assertInfinite
+     */
+    function assertInfinite($actual, string $message = ''): void
+    {
+        Assert::assertInfinite(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\assertNan')) {
+    /**
+     * Asserts that a variable is nan.
+     *
+     * @throws ExpectationFailedException
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     *
+     * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+     *
+     * @see Assert::assertNan
+     */
+    function assertNan($actual, string $message = ''): void
+    {
+        Assert::assertNan(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\assertClassHasAttribute')) {
+    /**
+     * Asserts that a class has a specified attribute.
+     *
+     * @throws ExpectationFailedException
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws Exception
+     *
+     * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+     *
+     * @see Assert::assertClassHasAttribute
+     */
+    function assertClassHasAttribute(string $attributeName, string $className, string $message = ''): void
+    {
+        Assert::assertClassHasAttribute(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\assertClassNotHasAttribute')) {
+    /**
+     * Asserts that a class does not have a specified attribute.
+     *
+     * @throws ExpectationFailedException
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws Exception
+     *
+     * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+     *
+     * @see Assert::assertClassNotHasAttribute
+     */
+    function assertClassNotHasAttribute(string $attributeName, string $className, string $message = ''): void
+    {
+        Assert::assertClassNotHasAttribute(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\assertClassHasStaticAttribute')) {
+    /**
+     * Asserts that a class has a specified static attribute.
+     *
+     * @throws ExpectationFailedException
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws Exception
+     *
+     * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+     *
+     * @see Assert::assertClassHasStaticAttribute
+     */
+    function assertClassHasStaticAttribute(string $attributeName, string $className, string $message = ''): void
+    {
+        Assert::assertClassHasStaticAttribute(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\assertClassNotHasStaticAttribute')) {
+    /**
+     * Asserts that a class does not have a specified static attribute.
+     *
+     * @throws ExpectationFailedException
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws Exception
+     *
+     * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+     *
+     * @see Assert::assertClassNotHasStaticAttribute
+     */
+    function assertClassNotHasStaticAttribute(string $attributeName, string $className, string $message = ''): void
+    {
+        Assert::assertClassNotHasStaticAttribute(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\assertObjectHasAttribute')) {
+    /**
+     * Asserts that an object has a specified attribute.
+     *
+     * @param object $object
+     *
+     * @throws ExpectationFailedException
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws Exception
+     *
+     * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+     *
+     * @see Assert::assertObjectHasAttribute
+     */
+    function assertObjectHasAttribute(string $attributeName, $object, string $message = ''): void
+    {
+        Assert::assertObjectHasAttribute(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\assertObjectNotHasAttribute')) {
+    /**
+     * Asserts that an object does not have a specified attribute.
+     *
+     * @param object $object
+     *
+     * @throws ExpectationFailedException
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws Exception
+     *
+     * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+     *
+     * @see Assert::assertObjectNotHasAttribute
+     */
+    function assertObjectNotHasAttribute(string $attributeName, $object, string $message = ''): void
+    {
+        Assert::assertObjectNotHasAttribute(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\assertSame')) {
+    /**
+     * Asserts that two variables have the same type and value.
+     * Used on objects, it asserts that two variables reference
+     * the same object.
+     *
+     * @throws ExpectationFailedException
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     *
+     * @psalm-template ExpectedType
+     * @psalm-param ExpectedType $expected
+     * @psalm-assert =ExpectedType $actual
+     *
+     * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+     *
+     * @see Assert::assertSame
+     */
+    function assertSame($expected, $actual, string $message = ''): void
+    {
+        Assert::assertSame(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\assertNotSame')) {
+    /**
+     * Asserts that two variables do not have the same type and value.
+     * Used on objects, it asserts that two variables do not reference
+     * the same object.
+     *
+     * @throws ExpectationFailedException
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     *
+     * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+     *
+     * @see Assert::assertNotSame
+     */
+    function assertNotSame($expected, $actual, string $message = ''): void
+    {
+        Assert::assertNotSame(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\assertInstanceOf')) {
+    /**
+     * Asserts that a variable is of a given type.
+     *
+     * @throws ExpectationFailedException
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws Exception
+     *
+     * @psalm-template ExpectedType of object
+     * @psalm-param class-string<ExpectedType> $expected
+     * @psalm-assert =ExpectedType $actual
+     *
+     * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+     *
+     * @see Assert::assertInstanceOf
+     */
+    function assertInstanceOf(string $expected, $actual, string $message = ''): void
+    {
+        Assert::assertInstanceOf(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\assertNotInstanceOf')) {
+    /**
+     * Asserts that a variable is not of a given type.
+     *
+     * @throws ExpectationFailedException
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws Exception
+     *
+     * @psalm-template ExpectedType of object
+     * @psalm-param class-string<ExpectedType> $expected
+     * @psalm-assert !ExpectedType $actual
+     *
+     * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+     *
+     * @see Assert::assertNotInstanceOf
+     */
+    function assertNotInstanceOf(string $expected, $actual, string $message = ''): void
+    {
+        Assert::assertNotInstanceOf(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\assertIsArray')) {
+    /**
+     * Asserts that a variable is of type array.
+     *
+     * @throws ExpectationFailedException
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     *
+     * @psalm-assert array $actual
+     *
+     * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+     *
+     * @see Assert::assertIsArray
+     */
+    function assertIsArray($actual, string $message = ''): void
+    {
+        Assert::assertIsArray(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\assertIsBool')) {
+    /**
+     * Asserts that a variable is of type bool.
+     *
+     * @throws ExpectationFailedException
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     *
+     * @psalm-assert bool $actual
+     *
+     * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+     *
+     * @see Assert::assertIsBool
+     */
+    function assertIsBool($actual, string $message = ''): void
+    {
+        Assert::assertIsBool(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\assertIsFloat')) {
+    /**
+     * Asserts that a variable is of type float.
+     *
+     * @throws ExpectationFailedException
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     *
+     * @psalm-assert float $actual
+     *
+     * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+     *
+     * @see Assert::assertIsFloat
+     */
+    function assertIsFloat($actual, string $message = ''): void
+    {
+        Assert::assertIsFloat(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\assertIsInt')) {
+    /**
+     * Asserts that a variable is of type int.
+     *
+     * @throws ExpectationFailedException
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     *
+     * @psalm-assert int $actual
+     *
+     * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+     *
+     * @see Assert::assertIsInt
+     */
+    function assertIsInt($actual, string $message = ''): void
+    {
+        Assert::assertIsInt(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\assertIsNumeric')) {
+    /**
+     * Asserts that a variable is of type numeric.
+     *
+     * @throws ExpectationFailedException
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     *
+     * @psalm-assert numeric $actual
+     *
+     * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+     *
+     * @see Assert::assertIsNumeric
+     */
+    function assertIsNumeric($actual, string $message = ''): void
+    {
+        Assert::assertIsNumeric(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\assertIsObject')) {
+    /**
+     * Asserts that a variable is of type object.
+     *
+     * @throws ExpectationFailedException
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     *
+     * @psalm-assert object $actual
+     *
+     * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+     *
+     * @see Assert::assertIsObject
+     */
+    function assertIsObject($actual, string $message = ''): void
+    {
+        Assert::assertIsObject(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\assertIsResource')) {
+    /**
+     * Asserts that a variable is of type resource.
+     *
+     * @throws ExpectationFailedException
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     *
+     * @psalm-assert resource $actual
+     *
+     * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+     *
+     * @see Assert::assertIsResource
+     */
+    function assertIsResource($actual, string $message = ''): void
+    {
+        Assert::assertIsResource(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\assertIsClosedResource')) {
+    /**
+     * Asserts that a variable is of type resource and is closed.
+     *
+     * @throws ExpectationFailedException
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     *
+     * @psalm-assert resource $actual
+     *
+     * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+     *
+     * @see Assert::assertIsClosedResource
+     */
+    function assertIsClosedResource($actual, string $message = ''): void
+    {
+        Assert::assertIsClosedResource(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\assertIsString')) {
+    /**
+     * Asserts that a variable is of type string.
+     *
+     * @throws ExpectationFailedException
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     *
+     * @psalm-assert string $actual
+     *
+     * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+     *
+     * @see Assert::assertIsString
+     */
+    function assertIsString($actual, string $message = ''): void
+    {
+        Assert::assertIsString(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\assertIsScalar')) {
+    /**
+     * Asserts that a variable is of type scalar.
+     *
+     * @throws ExpectationFailedException
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     *
+     * @psalm-assert scalar $actual
+     *
+     * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+     *
+     * @see Assert::assertIsScalar
+     */
+    function assertIsScalar($actual, string $message = ''): void
+    {
+        Assert::assertIsScalar(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\assertIsCallable')) {
+    /**
+     * Asserts that a variable is of type callable.
+     *
+     * @throws ExpectationFailedException
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     *
+     * @psalm-assert callable $actual
+     *
+     * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+     *
+     * @see Assert::assertIsCallable
+     */
+    function assertIsCallable($actual, string $message = ''): void
+    {
+        Assert::assertIsCallable(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\assertIsIterable')) {
+    /**
+     * Asserts that a variable is of type iterable.
+     *
+     * @throws ExpectationFailedException
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     *
+     * @psalm-assert iterable $actual
+     *
+     * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+     *
+     * @see Assert::assertIsIterable
+     */
+    function assertIsIterable($actual, string $message = ''): void
+    {
+        Assert::assertIsIterable(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\assertIsNotArray')) {
+    /**
+     * Asserts that a variable is not of type array.
+     *
+     * @throws ExpectationFailedException
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     *
+     * @psalm-assert !array $actual
+     *
+     * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+     *
+     * @see Assert::assertIsNotArray
+     */
+    function assertIsNotArray($actual, string $message = ''): void
+    {
+        Assert::assertIsNotArray(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\assertIsNotBool')) {
+    /**
+     * Asserts that a variable is not of type bool.
+     *
+     * @throws ExpectationFailedException
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     *
+     * @psalm-assert !bool $actual
+     *
+     * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+     *
+     * @see Assert::assertIsNotBool
+     */
+    function assertIsNotBool($actual, string $message = ''): void
+    {
+        Assert::assertIsNotBool(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\assertIsNotFloat')) {
+    /**
+     * Asserts that a variable is not of type float.
+     *
+     * @throws ExpectationFailedException
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     *
+     * @psalm-assert !float $actual
+     *
+     * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+     *
+     * @see Assert::assertIsNotFloat
+     */
+    function assertIsNotFloat($actual, string $message = ''): void
+    {
+        Assert::assertIsNotFloat(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\assertIsNotInt')) {
+    /**
+     * Asserts that a variable is not of type int.
+     *
+     * @throws ExpectationFailedException
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     *
+     * @psalm-assert !int $actual
+     *
+     * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+     *
+     * @see Assert::assertIsNotInt
+     */
+    function assertIsNotInt($actual, string $message = ''): void
+    {
+        Assert::assertIsNotInt(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\assertIsNotNumeric')) {
+    /**
+     * Asserts that a variable is not of type numeric.
+     *
+     * @throws ExpectationFailedException
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     *
+     * @psalm-assert !numeric $actual
+     *
+     * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+     *
+     * @see Assert::assertIsNotNumeric
+     */
+    function assertIsNotNumeric($actual, string $message = ''): void
+    {
+        Assert::assertIsNotNumeric(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\assertIsNotObject')) {
+    /**
+     * Asserts that a variable is not of type object.
+     *
+     * @throws ExpectationFailedException
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     *
+     * @psalm-assert !object $actual
+     *
+     * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+     *
+     * @see Assert::assertIsNotObject
+     */
+    function assertIsNotObject($actual, string $message = ''): void
+    {
+        Assert::assertIsNotObject(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\assertIsNotResource')) {
+    /**
+     * Asserts that a variable is not of type resource.
+     *
+     * @throws ExpectationFailedException
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     *
+     * @psalm-assert !resource $actual
+     *
+     * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+     *
+     * @see Assert::assertIsNotResource
+     */
+    function assertIsNotResource($actual, string $message = ''): void
+    {
+        Assert::assertIsNotResource(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\assertIsNotClosedResource')) {
+    /**
+     * Asserts that a variable is not of type resource.
+     *
+     * @throws ExpectationFailedException
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     *
+     * @psalm-assert !resource $actual
+     *
+     * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+     *
+     * @see Assert::assertIsNotClosedResource
+     */
+    function assertIsNotClosedResource($actual, string $message = ''): void
+    {
+        Assert::assertIsNotClosedResource(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\assertIsNotString')) {
+    /**
+     * Asserts that a variable is not of type string.
+     *
+     * @throws ExpectationFailedException
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     *
+     * @psalm-assert !string $actual
+     *
+     * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+     *
+     * @see Assert::assertIsNotString
+     */
+    function assertIsNotString($actual, string $message = ''): void
+    {
+        Assert::assertIsNotString(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\assertIsNotScalar')) {
+    /**
+     * Asserts that a variable is not of type scalar.
+     *
+     * @throws ExpectationFailedException
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     *
+     * @psalm-assert !scalar $actual
+     *
+     * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+     *
+     * @see Assert::assertIsNotScalar
+     */
+    function assertIsNotScalar($actual, string $message = ''): void
+    {
+        Assert::assertIsNotScalar(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\assertIsNotCallable')) {
+    /**
+     * Asserts that a variable is not of type callable.
+     *
+     * @throws ExpectationFailedException
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     *
+     * @psalm-assert !callable $actual
+     *
+     * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+     *
+     * @see Assert::assertIsNotCallable
+     */
+    function assertIsNotCallable($actual, string $message = ''): void
+    {
+        Assert::assertIsNotCallable(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\assertIsNotIterable')) {
+    /**
+     * Asserts that a variable is not of type iterable.
+     *
+     * @throws ExpectationFailedException
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     *
+     * @psalm-assert !iterable $actual
+     *
+     * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+     *
+     * @see Assert::assertIsNotIterable
+     */
+    function assertIsNotIterable($actual, string $message = ''): void
+    {
+        Assert::assertIsNotIterable(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\assertMatchesRegularExpression')) {
+    /**
+     * Asserts that a string matches a given regular expression.
+     *
+     * @throws ExpectationFailedException
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     *
+     * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+     *
+     * @see Assert::assertMatchesRegularExpression
+     */
+    function assertMatchesRegularExpression(string $pattern, string $string, string $message = ''): void
+    {
+        Assert::assertMatchesRegularExpression(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\assertRegExp')) {
+    /**
+     * Asserts that a string matches a given regular expression.
+     *
+     * @throws ExpectationFailedException
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     *
+     * @codeCoverageIgnore
+     *
+     * @deprecated https://github.com/sebastianbergmann/phpunit/issues/4086
+     *
+     * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+     *
+     * @see Assert::assertRegExp
+     */
+    function assertRegExp(string $pattern, string $string, string $message = ''): void
+    {
+        Assert::assertRegExp(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\assertDoesNotMatchRegularExpression')) {
+    /**
+     * Asserts that a string does not match a given regular expression.
+     *
+     * @throws ExpectationFailedException
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     *
+     * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+     *
+     * @see Assert::assertDoesNotMatchRegularExpression
+     */
+    function assertDoesNotMatchRegularExpression(string $pattern, string $string, string $message = ''): void
+    {
+        Assert::assertDoesNotMatchRegularExpression(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\assertNotRegExp')) {
+    /**
+     * Asserts that a string does not match a given regular expression.
+     *
+     * @throws ExpectationFailedException
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     *
+     * @codeCoverageIgnore
+     *
+     * @deprecated https://github.com/sebastianbergmann/phpunit/issues/4089
+     *
+     * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+     *
+     * @see Assert::assertNotRegExp
+     */
+    function assertNotRegExp(string $pattern, string $string, string $message = ''): void
+    {
+        Assert::assertNotRegExp(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\assertSameSize')) {
+    /**
+     * Assert that the size of two arrays (or `Countable` or `Traversable` objects)
+     * is the same.
+     *
+     * @param Countable|iterable $expected
+     * @param Countable|iterable $actual
+     *
+     * @throws ExpectationFailedException
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws Exception
+     *
+     * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+     *
+     * @see Assert::assertSameSize
+     */
+    function assertSameSize($expected, $actual, string $message = ''): void
+    {
+        Assert::assertSameSize(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\assertNotSameSize')) {
+    /**
+     * Assert that the size of two arrays (or `Countable` or `Traversable` objects)
+     * is not the same.
+     *
+     * @param Countable|iterable $expected
+     * @param Countable|iterable $actual
+     *
+     * @throws ExpectationFailedException
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws Exception
+     *
+     * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+     *
+     * @see Assert::assertNotSameSize
+     */
+    function assertNotSameSize($expected, $actual, string $message = ''): void
+    {
+        Assert::assertNotSameSize(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\assertStringMatchesFormat')) {
+    /**
+     * Asserts that a string matches a given format string.
+     *
+     * @throws ExpectationFailedException
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     *
+     * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+     *
+     * @see Assert::assertStringMatchesFormat
+     */
+    function assertStringMatchesFormat(string $format, string $string, string $message = ''): void
+    {
+        Assert::assertStringMatchesFormat(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\assertStringNotMatchesFormat')) {
+    /**
+     * Asserts that a string does not match a given format string.
+     *
+     * @throws ExpectationFailedException
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     *
+     * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+     *
+     * @see Assert::assertStringNotMatchesFormat
+     */
+    function assertStringNotMatchesFormat(string $format, string $string, string $message = ''): void
+    {
+        Assert::assertStringNotMatchesFormat(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\assertStringMatchesFormatFile')) {
+    /**
+     * Asserts that a string matches a given format file.
+     *
+     * @throws ExpectationFailedException
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     *
+     * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+     *
+     * @see Assert::assertStringMatchesFormatFile
+     */
+    function assertStringMatchesFormatFile(string $formatFile, string $string, string $message = ''): void
+    {
+        Assert::assertStringMatchesFormatFile(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\assertStringNotMatchesFormatFile')) {
+    /**
+     * Asserts that a string does not match a given format string.
+     *
+     * @throws ExpectationFailedException
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     *
+     * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+     *
+     * @see Assert::assertStringNotMatchesFormatFile
+     */
+    function assertStringNotMatchesFormatFile(string $formatFile, string $string, string $message = ''): void
+    {
+        Assert::assertStringNotMatchesFormatFile(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\assertStringStartsWith')) {
+    /**
+     * Asserts that a string starts with a given prefix.
+     *
+     * @throws ExpectationFailedException
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     *
+     * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+     *
+     * @see Assert::assertStringStartsWith
+     */
+    function assertStringStartsWith(string $prefix, string $string, string $message = ''): void
+    {
+        Assert::assertStringStartsWith(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\assertStringStartsNotWith')) {
+    /**
+     * Asserts that a string starts not with a given prefix.
+     *
+     * @param string $prefix
+     * @param string $string
+     *
+     * @throws ExpectationFailedException
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     *
+     * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+     *
+     * @see Assert::assertStringStartsNotWith
+     */
+    function assertStringStartsNotWith($prefix, $string, string $message = ''): void
+    {
+        Assert::assertStringStartsNotWith(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\assertStringContainsString')) {
+    /**
+     * @throws ExpectationFailedException
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     *
+     * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+     *
+     * @see Assert::assertStringContainsString
+     */
+    function assertStringContainsString(string $needle, string $haystack, string $message = ''): void
+    {
+        Assert::assertStringContainsString(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\assertStringContainsStringIgnoringCase')) {
+    /**
+     * @throws ExpectationFailedException
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     *
+     * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+     *
+     * @see Assert::assertStringContainsStringIgnoringCase
+     */
+    function assertStringContainsStringIgnoringCase(string $needle, string $haystack, string $message = ''): void
+    {
+        Assert::assertStringContainsStringIgnoringCase(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\assertStringNotContainsString')) {
+    /**
+     * @throws ExpectationFailedException
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     *
+     * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+     *
+     * @see Assert::assertStringNotContainsString
+     */
+    function assertStringNotContainsString(string $needle, string $haystack, string $message = ''): void
+    {
+        Assert::assertStringNotContainsString(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\assertStringNotContainsStringIgnoringCase')) {
+    /**
+     * @throws ExpectationFailedException
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     *
+     * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+     *
+     * @see Assert::assertStringNotContainsStringIgnoringCase
+     */
+    function assertStringNotContainsStringIgnoringCase(string $needle, string $haystack, string $message = ''): void
+    {
+        Assert::assertStringNotContainsStringIgnoringCase(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\assertStringEndsWith')) {
+    /**
+     * Asserts that a string ends with a given suffix.
+     *
+     * @throws ExpectationFailedException
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     *
+     * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+     *
+     * @see Assert::assertStringEndsWith
+     */
+    function assertStringEndsWith(string $suffix, string $string, string $message = ''): void
+    {
+        Assert::assertStringEndsWith(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\assertStringEndsNotWith')) {
+    /**
+     * Asserts that a string ends not with a given suffix.
+     *
+     * @throws ExpectationFailedException
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     *
+     * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+     *
+     * @see Assert::assertStringEndsNotWith
+     */
+    function assertStringEndsNotWith(string $suffix, string $string, string $message = ''): void
+    {
+        Assert::assertStringEndsNotWith(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\assertXmlFileEqualsXmlFile')) {
+    /**
+     * Asserts that two XML files are equal.
+     *
+     * @throws ExpectationFailedException
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws Exception
+     *
+     * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+     *
+     * @see Assert::assertXmlFileEqualsXmlFile
+     */
+    function assertXmlFileEqualsXmlFile(string $expectedFile, string $actualFile, string $message = ''): void
+    {
+        Assert::assertXmlFileEqualsXmlFile(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\assertXmlFileNotEqualsXmlFile')) {
+    /**
+     * Asserts that two XML files are not equal.
+     *
+     * @throws ExpectationFailedException
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws \PHPUnit\Util\Exception
+     *
+     * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+     *
+     * @see Assert::assertXmlFileNotEqualsXmlFile
+     */
+    function assertXmlFileNotEqualsXmlFile(string $expectedFile, string $actualFile, string $message = ''): void
+    {
+        Assert::assertXmlFileNotEqualsXmlFile(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\assertXmlStringEqualsXmlFile')) {
+    /**
+     * Asserts that two XML documents are equal.
+     *
+     * @param DOMDocument|string $actualXml
+     *
+     * @throws ExpectationFailedException
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws \PHPUnit\Util\Xml\Exception
+     *
+     * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+     *
+     * @see Assert::assertXmlStringEqualsXmlFile
+     */
+    function assertXmlStringEqualsXmlFile(string $expectedFile, $actualXml, string $message = ''): void
+    {
+        Assert::assertXmlStringEqualsXmlFile(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\assertXmlStringNotEqualsXmlFile')) {
+    /**
+     * Asserts that two XML documents are not equal.
+     *
+     * @param DOMDocument|string $actualXml
+     *
+     * @throws ExpectationFailedException
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws \PHPUnit\Util\Xml\Exception
+     *
+     * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+     *
+     * @see Assert::assertXmlStringNotEqualsXmlFile
+     */
+    function assertXmlStringNotEqualsXmlFile(string $expectedFile, $actualXml, string $message = ''): void
+    {
+        Assert::assertXmlStringNotEqualsXmlFile(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\assertXmlStringEqualsXmlString')) {
+    /**
+     * Asserts that two XML documents are equal.
+     *
+     * @param DOMDocument|string $expectedXml
+     * @param DOMDocument|string $actualXml
+     *
+     * @throws ExpectationFailedException
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws \PHPUnit\Util\Xml\Exception
+     *
+     * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+     *
+     * @see Assert::assertXmlStringEqualsXmlString
+     */
+    function assertXmlStringEqualsXmlString($expectedXml, $actualXml, string $message = ''): void
+    {
+        Assert::assertXmlStringEqualsXmlString(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\assertXmlStringNotEqualsXmlString')) {
+    /**
+     * Asserts that two XML documents are not equal.
+     *
+     * @param DOMDocument|string $expectedXml
+     * @param DOMDocument|string $actualXml
+     *
+     * @throws ExpectationFailedException
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws \PHPUnit\Util\Xml\Exception
+     *
+     * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+     *
+     * @see Assert::assertXmlStringNotEqualsXmlString
+     */
+    function assertXmlStringNotEqualsXmlString($expectedXml, $actualXml, string $message = ''): void
+    {
+        Assert::assertXmlStringNotEqualsXmlString(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\assertEqualXMLStructure')) {
+    /**
+     * Asserts that a hierarchy of DOMElements matches.
+     *
+     * @throws AssertionFailedError
+     * @throws ExpectationFailedException
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     *
+     * @codeCoverageIgnore
+     *
+     * @deprecated https://github.com/sebastianbergmann/phpunit/issues/4091
+     *
+     * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+     *
+     * @see Assert::assertEqualXMLStructure
+     */
+    function assertEqualXMLStructure(DOMElement $expectedElement, DOMElement $actualElement, bool $checkAttributes = false, string $message = ''): void
+    {
+        Assert::assertEqualXMLStructure(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\assertThat')) {
+    /**
+     * Evaluates a PHPUnit\Framework\Constraint matcher object.
+     *
+     * @throws ExpectationFailedException
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     *
+     * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+     *
+     * @see Assert::assertThat
+     */
+    function assertThat($value, Constraint $constraint, string $message = ''): void
+    {
+        Assert::assertThat(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\assertJson')) {
+    /**
+     * Asserts that a string is a valid JSON string.
+     *
+     * @throws ExpectationFailedException
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     *
+     * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+     *
+     * @see Assert::assertJson
+     */
+    function assertJson(string $actualJson, string $message = ''): void
+    {
+        Assert::assertJson(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\assertJsonStringEqualsJsonString')) {
+    /**
+     * Asserts that two given JSON encoded objects or arrays are equal.
+     *
+     * @throws ExpectationFailedException
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     *
+     * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+     *
+     * @see Assert::assertJsonStringEqualsJsonString
+     */
+    function assertJsonStringEqualsJsonString(string $expectedJson, string $actualJson, string $message = ''): void
+    {
+        Assert::assertJsonStringEqualsJsonString(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\assertJsonStringNotEqualsJsonString')) {
+    /**
+     * Asserts that two given JSON encoded objects or arrays are not equal.
+     *
+     * @param string $expectedJson
+     * @param string $actualJson
+     *
+     * @throws ExpectationFailedException
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     *
+     * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+     *
+     * @see Assert::assertJsonStringNotEqualsJsonString
+     */
+    function assertJsonStringNotEqualsJsonString($expectedJson, $actualJson, string $message = ''): void
+    {
+        Assert::assertJsonStringNotEqualsJsonString(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\assertJsonStringEqualsJsonFile')) {
+    /**
+     * Asserts that the generated JSON encoded object and the content of the given file are equal.
+     *
+     * @throws ExpectationFailedException
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     *
+     * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+     *
+     * @see Assert::assertJsonStringEqualsJsonFile
+     */
+    function assertJsonStringEqualsJsonFile(string $expectedFile, string $actualJson, string $message = ''): void
+    {
+        Assert::assertJsonStringEqualsJsonFile(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\assertJsonStringNotEqualsJsonFile')) {
+    /**
+     * Asserts that the generated JSON encoded object and the content of the given file are not equal.
+     *
+     * @throws ExpectationFailedException
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     *
+     * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+     *
+     * @see Assert::assertJsonStringNotEqualsJsonFile
+     */
+    function assertJsonStringNotEqualsJsonFile(string $expectedFile, string $actualJson, string $message = ''): void
+    {
+        Assert::assertJsonStringNotEqualsJsonFile(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\assertJsonFileEqualsJsonFile')) {
+    /**
+     * Asserts that two JSON files are equal.
+     *
+     * @throws ExpectationFailedException
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     *
+     * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+     *
+     * @see Assert::assertJsonFileEqualsJsonFile
+     */
+    function assertJsonFileEqualsJsonFile(string $expectedFile, string $actualFile, string $message = ''): void
+    {
+        Assert::assertJsonFileEqualsJsonFile(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\assertJsonFileNotEqualsJsonFile')) {
+    /**
+     * Asserts that two JSON files are not equal.
+     *
+     * @throws ExpectationFailedException
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     *
+     * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+     *
+     * @see Assert::assertJsonFileNotEqualsJsonFile
+     */
+    function assertJsonFileNotEqualsJsonFile(string $expectedFile, string $actualFile, string $message = ''): void
+    {
+        Assert::assertJsonFileNotEqualsJsonFile(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\logicalAnd')) {
+    function logicalAnd(): LogicalAnd
+    {
+        return Assert::logicalAnd(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\logicalOr')) {
+    function logicalOr(): LogicalOr
+    {
+        return Assert::logicalOr(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\logicalNot')) {
+    function logicalNot(Constraint $constraint): LogicalNot
+    {
+        return Assert::logicalNot(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\logicalXor')) {
+    function logicalXor(): LogicalXor
+    {
+        return Assert::logicalXor(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\anything')) {
+    function anything(): IsAnything
+    {
+        return Assert::anything(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\isTrue')) {
+    function isTrue(): IsTrue
+    {
+        return Assert::isTrue(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\callback')) {
+    function callback(callable $callback): Callback
+    {
+        return Assert::callback(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\isFalse')) {
+    function isFalse(): IsFalse
+    {
+        return Assert::isFalse(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\isJson')) {
+    function isJson(): IsJson
+    {
+        return Assert::isJson(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\isNull')) {
+    function isNull(): IsNull
+    {
+        return Assert::isNull(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\isFinite')) {
+    function isFinite(): IsFinite
+    {
+        return Assert::isFinite(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\isInfinite')) {
+    function isInfinite(): IsInfinite
+    {
+        return Assert::isInfinite(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\isNan')) {
+    function isNan(): IsNan
+    {
+        return Assert::isNan(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\containsEqual')) {
+    function containsEqual($value): TraversableContainsEqual
+    {
+        return Assert::containsEqual(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\containsIdentical')) {
+    function containsIdentical($value): TraversableContainsIdentical
+    {
+        return Assert::containsIdentical(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\containsOnly')) {
+    function containsOnly(string $type): TraversableContainsOnly
+    {
+        return Assert::containsOnly(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\containsOnlyInstancesOf')) {
+    function containsOnlyInstancesOf(string $className): TraversableContainsOnly
+    {
+        return Assert::containsOnlyInstancesOf(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\arrayHasKey')) {
+    function arrayHasKey($key): ArrayHasKey
+    {
+        return Assert::arrayHasKey(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\equalTo')) {
+    function equalTo($value): IsEqual
+    {
+        return Assert::equalTo(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\equalToCanonicalizing')) {
+    function equalToCanonicalizing($value): IsEqualCanonicalizing
+    {
+        return Assert::equalToCanonicalizing(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\equalToIgnoringCase')) {
+    function equalToIgnoringCase($value): IsEqualIgnoringCase
+    {
+        return Assert::equalToIgnoringCase(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\equalToWithDelta')) {
+    function equalToWithDelta($value, float $delta): IsEqualWithDelta
+    {
+        return Assert::equalToWithDelta(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\isEmpty')) {
+    function isEmpty(): IsEmpty
+    {
+        return Assert::isEmpty(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\isWritable')) {
+    function isWritable(): IsWritable
+    {
+        return Assert::isWritable(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\isReadable')) {
+    function isReadable(): IsReadable
+    {
+        return Assert::isReadable(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\directoryExists')) {
+    function directoryExists(): DirectoryExists
+    {
+        return Assert::directoryExists(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\fileExists')) {
+    function fileExists(): FileExists
+    {
+        return Assert::fileExists(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\greaterThan')) {
+    function greaterThan($value): GreaterThan
+    {
+        return Assert::greaterThan(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\greaterThanOrEqual')) {
+    function greaterThanOrEqual($value): LogicalOr
+    {
+        return Assert::greaterThanOrEqual(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\classHasAttribute')) {
+    function classHasAttribute(string $attributeName): ClassHasAttribute
+    {
+        return Assert::classHasAttribute(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\classHasStaticAttribute')) {
+    function classHasStaticAttribute(string $attributeName): ClassHasStaticAttribute
+    {
+        return Assert::classHasStaticAttribute(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\objectHasAttribute')) {
+    function objectHasAttribute($attributeName): ObjectHasAttribute
+    {
+        return Assert::objectHasAttribute(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\identicalTo')) {
+    function identicalTo($value): IsIdentical
+    {
+        return Assert::identicalTo(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\isInstanceOf')) {
+    function isInstanceOf(string $className): IsInstanceOf
+    {
+        return Assert::isInstanceOf(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\isType')) {
+    function isType(string $type): IsType
+    {
+        return Assert::isType(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\lessThan')) {
+    function lessThan($value): LessThan
+    {
+        return Assert::lessThan(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\lessThanOrEqual')) {
+    function lessThanOrEqual($value): LogicalOr
+    {
+        return Assert::lessThanOrEqual(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\matchesRegularExpression')) {
+    function matchesRegularExpression(string $pattern): RegularExpression
+    {
+        return Assert::matchesRegularExpression(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\matches')) {
+    function matches(string $string): StringMatchesFormatDescription
+    {
+        return Assert::matches(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\stringStartsWith')) {
+    function stringStartsWith($prefix): StringStartsWith
+    {
+        return Assert::stringStartsWith(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\stringContains')) {
+    function stringContains(string $string, bool $case = true): StringContains
+    {
+        return Assert::stringContains(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\stringEndsWith')) {
+    function stringEndsWith(string $suffix): StringEndsWith
+    {
+        return Assert::stringEndsWith(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\countOf')) {
+    function countOf(int $count): Count
+    {
+        return Assert::countOf(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\objectEquals')) {
+    function objectEquals(object $object, string $method = 'equals'): ObjectEquals
+    {
+        return Assert::objectEquals(...func_get_args());
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\any')) {
+    /**
+     * Returns a matcher that matches when the method is executed
+     * zero or more times.
+     */
+    function any(): AnyInvokedCountMatcher
+    {
+        return new AnyInvokedCountMatcher;
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\never')) {
+    /**
+     * Returns a matcher that matches when the method is never executed.
+     */
+    function never(): InvokedCountMatcher
+    {
+        return new InvokedCountMatcher(0);
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\atLeast')) {
+    /**
+     * Returns a matcher that matches when the method is executed
+     * at least N times.
+     */
+    function atLeast(int $requiredInvocations): InvokedAtLeastCountMatcher
+    {
+        return new InvokedAtLeastCountMatcher(
+            $requiredInvocations
+        );
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\atLeastOnce')) {
+    /**
+     * Returns a matcher that matches when the method is executed at least once.
+     */
+    function atLeastOnce(): InvokedAtLeastOnceMatcher
+    {
+        return new InvokedAtLeastOnceMatcher;
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\once')) {
+    /**
+     * Returns a matcher that matches when the method is executed exactly once.
+     */
+    function once(): InvokedCountMatcher
+    {
+        return new InvokedCountMatcher(1);
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\exactly')) {
+    /**
+     * Returns a matcher that matches when the method is executed
+     * exactly $count times.
+     */
+    function exactly(int $count): InvokedCountMatcher
+    {
+        return new InvokedCountMatcher($count);
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\atMost')) {
+    /**
+     * Returns a matcher that matches when the method is executed
+     * at most N times.
+     */
+    function atMost(int $allowedInvocations): InvokedAtMostCountMatcher
+    {
+        return new InvokedAtMostCountMatcher($allowedInvocations);
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\at')) {
+    /**
+     * Returns a matcher that matches when the method is executed
+     * at the given index.
+     */
+    function at(int $index): InvokedAtIndexMatcher
+    {
+        return new InvokedAtIndexMatcher($index);
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\returnValue')) {
+    function returnValue($value): ReturnStub
+    {
+        return new ReturnStub($value);
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\returnValueMap')) {
+    function returnValueMap(array $valueMap): ReturnValueMapStub
+    {
+        return new ReturnValueMapStub($valueMap);
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\returnArgument')) {
+    function returnArgument(int $argumentIndex): ReturnArgumentStub
+    {
+        return new ReturnArgumentStub($argumentIndex);
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\returnCallback')) {
+    function returnCallback($callback): ReturnCallbackStub
+    {
+        return new ReturnCallbackStub($callback);
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\returnSelf')) {
+    /**
+     * Returns the current object.
+     *
+     * This method is useful when mocking a fluent interface.
+     */
+    function returnSelf(): ReturnSelfStub
+    {
+        return new ReturnSelfStub;
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\throwException')) {
+    function throwException(Throwable $exception): ExceptionStub
+    {
+        return new ExceptionStub($exception);
+    }
+}
+
+if (!function_exists('PHPUnit\Framework\onConsecutiveCalls')) {
+    function onConsecutiveCalls(): ConsecutiveCallsStub
+    {
+        $args = func_get_args();
+
+        return new ConsecutiveCallsStub($args);
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/Constraint/Boolean/IsFalse.php b/vendor/phpunit/phpunit/src/Framework/Constraint/Boolean/IsFalse.php
new file mode 100644
index 0000000000000000000000000000000000000000..212e2bcb4c747e6a7ab396c14b96b31ac4bc8077
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/Constraint/Boolean/IsFalse.php
@@ -0,0 +1,35 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework\Constraint;
+
+/**
+ * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+ */
+final class IsFalse extends Constraint
+{
+    /**
+     * Returns a string representation of the constraint.
+     */
+    public function toString(): string
+    {
+        return 'is false';
+    }
+
+    /**
+     * Evaluates the constraint for parameter $other. Returns true if the
+     * constraint is met, false otherwise.
+     *
+     * @param mixed $other value or object to evaluate
+     */
+    protected function matches($other): bool
+    {
+        return $other === false;
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/Constraint/Boolean/IsTrue.php b/vendor/phpunit/phpunit/src/Framework/Constraint/Boolean/IsTrue.php
new file mode 100644
index 0000000000000000000000000000000000000000..e1d6b2691d83125cca54def21afe577fab3ad711
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/Constraint/Boolean/IsTrue.php
@@ -0,0 +1,35 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework\Constraint;
+
+/**
+ * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+ */
+final class IsTrue extends Constraint
+{
+    /**
+     * Returns a string representation of the constraint.
+     */
+    public function toString(): string
+    {
+        return 'is true';
+    }
+
+    /**
+     * Evaluates the constraint for parameter $other. Returns true if the
+     * constraint is met, false otherwise.
+     *
+     * @param mixed $other value or object to evaluate
+     */
+    protected function matches($other): bool
+    {
+        return $other === true;
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/Constraint/Callback.php b/vendor/phpunit/phpunit/src/Framework/Constraint/Callback.php
new file mode 100644
index 0000000000000000000000000000000000000000..b7cf95a1286582a6dea878f9089f81c3a6a1a2fe
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/Constraint/Callback.php
@@ -0,0 +1,52 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework\Constraint;
+
+/**
+ * @psalm-template CallbackInput of mixed
+ *
+ * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+ */
+final class Callback extends Constraint
+{
+    /**
+     * @var callable
+     *
+     * @psalm-var callable(CallbackInput $input): bool
+     */
+    private $callback;
+
+    /** @psalm-param callable(CallbackInput $input): bool $callback */
+    public function __construct(callable $callback)
+    {
+        $this->callback = $callback;
+    }
+
+    /**
+     * Returns a string representation of the constraint.
+     */
+    public function toString(): string
+    {
+        return 'is accepted by specified callback';
+    }
+
+    /**
+     * Evaluates the constraint for parameter $value. Returns true if the
+     * constraint is met, false otherwise.
+     *
+     * @param mixed $other value or object to evaluate
+     *
+     * @psalm-param CallbackInput $other
+     */
+    protected function matches($other): bool
+    {
+        return ($this->callback)($other);
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/Constraint/Cardinality/Count.php b/vendor/phpunit/phpunit/src/Framework/Constraint/Cardinality/Count.php
new file mode 100644
index 0000000000000000000000000000000000000000..8e27fbfd4198c89dbc51abb01d06bf87bea254c8
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/Constraint/Cardinality/Count.php
@@ -0,0 +1,142 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework\Constraint;
+
+use function count;
+use function is_array;
+use function iterator_count;
+use function sprintf;
+use Countable;
+use EmptyIterator;
+use Generator;
+use Iterator;
+use IteratorAggregate;
+use PHPUnit\Framework\Exception;
+use Traversable;
+
+/**
+ * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+ */
+class Count extends Constraint
+{
+    /**
+     * @var int
+     */
+    private $expectedCount;
+
+    public function __construct(int $expected)
+    {
+        $this->expectedCount = $expected;
+    }
+
+    public function toString(): string
+    {
+        return sprintf(
+            'count matches %d',
+            $this->expectedCount
+        );
+    }
+
+    /**
+     * Evaluates the constraint for parameter $other. Returns true if the
+     * constraint is met, false otherwise.
+     *
+     * @throws Exception
+     */
+    protected function matches($other): bool
+    {
+        return $this->expectedCount === $this->getCountOf($other);
+    }
+
+    /**
+     * @throws Exception
+     */
+    protected function getCountOf($other): ?int
+    {
+        if ($other instanceof Countable || is_array($other)) {
+            return count($other);
+        }
+
+        if ($other instanceof EmptyIterator) {
+            return 0;
+        }
+
+        if ($other instanceof Traversable) {
+            while ($other instanceof IteratorAggregate) {
+                try {
+                    $other = $other->getIterator();
+                } catch (\Exception $e) {
+                    throw new Exception(
+                        $e->getMessage(),
+                        $e->getCode(),
+                        $e
+                    );
+                }
+            }
+
+            $iterator = $other;
+
+            if ($iterator instanceof Generator) {
+                return $this->getCountOfGenerator($iterator);
+            }
+
+            if (!$iterator instanceof Iterator) {
+                return iterator_count($iterator);
+            }
+
+            $key   = $iterator->key();
+            $count = iterator_count($iterator);
+
+            // Manually rewind $iterator to previous key, since iterator_count
+            // moves pointer.
+            if ($key !== null) {
+                $iterator->rewind();
+
+                while ($iterator->valid() && $key !== $iterator->key()) {
+                    $iterator->next();
+                }
+            }
+
+            return $count;
+        }
+
+        return null;
+    }
+
+    /**
+     * Returns the total number of iterations from a generator.
+     * This will fully exhaust the generator.
+     */
+    protected function getCountOfGenerator(Generator $generator): int
+    {
+        for ($count = 0; $generator->valid(); $generator->next()) {
+            $count++;
+        }
+
+        return $count;
+    }
+
+    /**
+     * Returns the description of the failure.
+     *
+     * The beginning of failure messages is "Failed asserting that" in most
+     * cases. This method should return the second part of that sentence.
+     *
+     * @param mixed $other evaluated value or object
+     */
+    protected function failureDescription($other): string
+    {
+        return sprintf(
+            'actual size %d matches expected size %d',
+            (int) $this->getCountOf($other),
+            $this->expectedCount
+        );
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/Constraint/Cardinality/GreaterThan.php b/vendor/phpunit/phpunit/src/Framework/Constraint/Cardinality/GreaterThan.php
new file mode 100644
index 0000000000000000000000000000000000000000..31df5020172045561dd8e012a9269c36df4d6265
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/Constraint/Cardinality/GreaterThan.php
@@ -0,0 +1,50 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework\Constraint;
+
+/**
+ * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+ */
+final class GreaterThan extends Constraint
+{
+    /**
+     * @var float|int
+     */
+    private $value;
+
+    /**
+     * @param float|int $value
+     */
+    public function __construct($value)
+    {
+        $this->value = $value;
+    }
+
+    /**
+     * Returns a string representation of the constraint.
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     */
+    public function toString(): string
+    {
+        return 'is greater than ' . $this->exporter()->export($this->value);
+    }
+
+    /**
+     * Evaluates the constraint for parameter $other. Returns true if the
+     * constraint is met, false otherwise.
+     *
+     * @param mixed $other value or object to evaluate
+     */
+    protected function matches($other): bool
+    {
+        return $this->value < $other;
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/Constraint/Cardinality/IsEmpty.php b/vendor/phpunit/phpunit/src/Framework/Constraint/Cardinality/IsEmpty.php
new file mode 100644
index 0000000000000000000000000000000000000000..e6371d536c86a55cb633017f6b4f142e27dccfad
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/Constraint/Cardinality/IsEmpty.php
@@ -0,0 +1,70 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework\Constraint;
+
+use function count;
+use function gettype;
+use function sprintf;
+use function strpos;
+use Countable;
+use EmptyIterator;
+
+/**
+ * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+ */
+final class IsEmpty extends Constraint
+{
+    /**
+     * Returns a string representation of the constraint.
+     */
+    public function toString(): string
+    {
+        return 'is empty';
+    }
+
+    /**
+     * Evaluates the constraint for parameter $other. Returns true if the
+     * constraint is met, false otherwise.
+     *
+     * @param mixed $other value or object to evaluate
+     */
+    protected function matches($other): bool
+    {
+        if ($other instanceof EmptyIterator) {
+            return true;
+        }
+
+        if ($other instanceof Countable) {
+            return count($other) === 0;
+        }
+
+        return empty($other);
+    }
+
+    /**
+     * Returns the description of the failure.
+     *
+     * The beginning of failure messages is "Failed asserting that" in most
+     * cases. This method should return the second part of that sentence.
+     *
+     * @param mixed $other evaluated value or object
+     */
+    protected function failureDescription($other): string
+    {
+        $type = gettype($other);
+
+        return sprintf(
+            '%s %s %s',
+            strpos($type, 'a') === 0 || strpos($type, 'o') === 0 ? 'an' : 'a',
+            $type,
+            $this->toString()
+        );
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/Constraint/Cardinality/LessThan.php b/vendor/phpunit/phpunit/src/Framework/Constraint/Cardinality/LessThan.php
new file mode 100644
index 0000000000000000000000000000000000000000..c7884ba1d2fb6703fb495bebb9060d34edc30ccd
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/Constraint/Cardinality/LessThan.php
@@ -0,0 +1,50 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework\Constraint;
+
+/**
+ * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+ */
+final class LessThan extends Constraint
+{
+    /**
+     * @var float|int
+     */
+    private $value;
+
+    /**
+     * @param float|int $value
+     */
+    public function __construct($value)
+    {
+        $this->value = $value;
+    }
+
+    /**
+     * Returns a string representation of the constraint.
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     */
+    public function toString(): string
+    {
+        return 'is less than ' . $this->exporter()->export($this->value);
+    }
+
+    /**
+     * Evaluates the constraint for parameter $other. Returns true if the
+     * constraint is met, false otherwise.
+     *
+     * @param mixed $other value or object to evaluate
+     */
+    protected function matches($other): bool
+    {
+        return $this->value > $other;
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/Constraint/Cardinality/SameSize.php b/vendor/phpunit/phpunit/src/Framework/Constraint/Cardinality/SameSize.php
new file mode 100644
index 0000000000000000000000000000000000000000..a54679425c0b34c7ef13f766253fd0bb1daec54f
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/Constraint/Cardinality/SameSize.php
@@ -0,0 +1,21 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework\Constraint;
+
+/**
+ * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+ */
+final class SameSize extends Count
+{
+    public function __construct(iterable $expected)
+    {
+        parent::__construct((int) $this->getCountOf($expected));
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/Constraint/Constraint.php b/vendor/phpunit/phpunit/src/Framework/Constraint/Constraint.php
new file mode 100644
index 0000000000000000000000000000000000000000..c012d6275a17022e33043848651336db266a679a
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/Constraint/Constraint.php
@@ -0,0 +1,269 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework\Constraint;
+
+use function sprintf;
+use Countable;
+use PHPUnit\Framework\ExpectationFailedException;
+use PHPUnit\Framework\SelfDescribing;
+use SebastianBergmann\Comparator\ComparisonFailure;
+use SebastianBergmann\Exporter\Exporter;
+
+/**
+ * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+ */
+abstract class Constraint implements Countable, SelfDescribing
+{
+    /**
+     * @var ?Exporter
+     */
+    private $exporter;
+
+    /**
+     * Evaluates the constraint for parameter $other.
+     *
+     * If $returnResult is set to false (the default), an exception is thrown
+     * in case of a failure. null is returned otherwise.
+     *
+     * If $returnResult is true, the result of the evaluation is returned as
+     * a boolean value instead: true in case of success, false in case of a
+     * failure.
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws ExpectationFailedException
+     */
+    public function evaluate($other, string $description = '', bool $returnResult = false): ?bool
+    {
+        $success = false;
+
+        if ($this->matches($other)) {
+            $success = true;
+        }
+
+        if ($returnResult) {
+            return $success;
+        }
+
+        if (!$success) {
+            $this->fail($other, $description);
+        }
+
+        return null;
+    }
+
+    /**
+     * Counts the number of constraint elements.
+     */
+    public function count(): int
+    {
+        return 1;
+    }
+
+    protected function exporter(): Exporter
+    {
+        if ($this->exporter === null) {
+            $this->exporter = new Exporter;
+        }
+
+        return $this->exporter;
+    }
+
+    /**
+     * Evaluates the constraint for parameter $other. Returns true if the
+     * constraint is met, false otherwise.
+     *
+     * This method can be overridden to implement the evaluation algorithm.
+     *
+     * @param mixed $other value or object to evaluate
+     * @codeCoverageIgnore
+     */
+    protected function matches($other): bool
+    {
+        return false;
+    }
+
+    /**
+     * Throws an exception for the given compared value and test description.
+     *
+     * @param mixed             $other             evaluated value or object
+     * @param string            $description       Additional information about the test
+     * @param ComparisonFailure $comparisonFailure
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws ExpectationFailedException
+     *
+     * @psalm-return never-return
+     */
+    protected function fail($other, $description, ComparisonFailure $comparisonFailure = null): void
+    {
+        $failureDescription = sprintf(
+            'Failed asserting that %s.',
+            $this->failureDescription($other)
+        );
+
+        $additionalFailureDescription = $this->additionalFailureDescription($other);
+
+        if ($additionalFailureDescription) {
+            $failureDescription .= "\n" . $additionalFailureDescription;
+        }
+
+        if (!empty($description)) {
+            $failureDescription = $description . "\n" . $failureDescription;
+        }
+
+        throw new ExpectationFailedException(
+            $failureDescription,
+            $comparisonFailure
+        );
+    }
+
+    /**
+     * Return additional failure description where needed.
+     *
+     * The function can be overridden to provide additional failure
+     * information like a diff
+     *
+     * @param mixed $other evaluated value or object
+     */
+    protected function additionalFailureDescription($other): string
+    {
+        return '';
+    }
+
+    /**
+     * Returns the description of the failure.
+     *
+     * The beginning of failure messages is "Failed asserting that" in most
+     * cases. This method should return the second part of that sentence.
+     *
+     * To provide additional failure information additionalFailureDescription
+     * can be used.
+     *
+     * @param mixed $other evaluated value or object
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     */
+    protected function failureDescription($other): string
+    {
+        return $this->exporter()->export($other) . ' ' . $this->toString();
+    }
+
+    /**
+     * Returns a custom string representation of the constraint object when it
+     * appears in context of an $operator expression.
+     *
+     * The purpose of this method is to provide meaningful descriptive string
+     * in context of operators such as LogicalNot. Native PHPUnit constraints
+     * are supported out of the box by LogicalNot, but externally developed
+     * ones had no way to provide correct strings in this context.
+     *
+     * The method shall return empty string, when it does not handle
+     * customization by itself.
+     *
+     * @param Operator $operator the $operator of the expression
+     * @param mixed    $role     role of $this constraint in the $operator expression
+     */
+    protected function toStringInContext(Operator $operator, $role): string
+    {
+        return '';
+    }
+
+    /**
+     * Returns the description of the failure when this constraint appears in
+     * context of an $operator expression.
+     *
+     * The purpose of this method is to provide meaningful failue description
+     * in context of operators such as LogicalNot. Native PHPUnit constraints
+     * are supported out of the box by LogicalNot, but externally developed
+     * ones had no way to provide correct messages in this context.
+     *
+     * The method shall return empty string, when it does not handle
+     * customization by itself.
+     *
+     * @param Operator $operator the $operator of the expression
+     * @param mixed    $role     role of $this constraint in the $operator expression
+     * @param mixed    $other    evaluated value or object
+     */
+    protected function failureDescriptionInContext(Operator $operator, $role, $other): string
+    {
+        $string = $this->toStringInContext($operator, $role);
+
+        if ($string === '') {
+            return '';
+        }
+
+        return $this->exporter()->export($other) . ' ' . $string;
+    }
+
+    /**
+     * Reduces the sub-expression starting at $this by skipping degenerate
+     * sub-expression and returns first descendant constraint that starts
+     * a non-reducible sub-expression.
+     *
+     * Returns $this for terminal constraints and for operators that start
+     * non-reducible sub-expression, or the nearest descendant of $this that
+     * starts a non-reducible sub-expression.
+     *
+     * A constraint expression may be modelled as a tree with non-terminal
+     * nodes (operators) and terminal nodes. For example:
+     *
+     *      LogicalOr           (operator, non-terminal)
+     *      + LogicalAnd        (operator, non-terminal)
+     *      | + IsType('int')   (terminal)
+     *      | + GreaterThan(10) (terminal)
+     *      + LogicalNot        (operator, non-terminal)
+     *        + IsType('array') (terminal)
+     *
+     * A degenerate sub-expression is a part of the tree, that effectively does
+     * not contribute to the evaluation of the expression it appears in. An example
+     * of degenerate sub-expression is a BinaryOperator constructed with single
+     * operand or nested BinaryOperators, each with single operand. An
+     * expression involving a degenerate sub-expression is equivalent to a
+     * reduced expression with the degenerate sub-expression removed, for example
+     *
+     *      LogicalAnd          (operator)
+     *      + LogicalOr         (degenerate operator)
+     *      | + LogicalAnd      (degenerate operator)
+     *      |   + IsType('int') (terminal)
+     *      + GreaterThan(10)   (terminal)
+     *
+     * is equivalent to
+     *
+     *      LogicalAnd          (operator)
+     *      + IsType('int')     (terminal)
+     *      + GreaterThan(10)   (terminal)
+     *
+     * because the subexpression
+     *
+     *      + LogicalOr
+     *        + LogicalAnd
+     *          + -
+     *
+     * is degenerate. Calling reduce() on the LogicalOr object above, as well
+     * as on LogicalAnd, shall return the IsType('int') instance.
+     *
+     * Other specific reductions can be implemented, for example cascade of
+     * LogicalNot operators
+     *
+     *      + LogicalNot
+     *        + LogicalNot
+     *          +LogicalNot
+     *           + IsTrue
+     *
+     * can be reduced to
+     *
+     *      LogicalNot
+     *      + IsTrue
+     */
+    protected function reduce(): self
+    {
+        return $this;
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/Constraint/Equality/IsEqual.php b/vendor/phpunit/phpunit/src/Framework/Constraint/Equality/IsEqual.php
new file mode 100644
index 0000000000000000000000000000000000000000..6a61ebfba99be412e8241a92e36a1e3e0b8610e9
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/Constraint/Equality/IsEqual.php
@@ -0,0 +1,138 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework\Constraint;
+
+use function is_string;
+use function sprintf;
+use function strpos;
+use function trim;
+use PHPUnit\Framework\ExpectationFailedException;
+use SebastianBergmann\Comparator\ComparisonFailure;
+use SebastianBergmann\Comparator\Factory as ComparatorFactory;
+
+/**
+ * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+ */
+final class IsEqual extends Constraint
+{
+    /**
+     * @var mixed
+     */
+    private $value;
+
+    /**
+     * @var float
+     */
+    private $delta;
+
+    /**
+     * @var bool
+     */
+    private $canonicalize;
+
+    /**
+     * @var bool
+     */
+    private $ignoreCase;
+
+    public function __construct($value, float $delta = 0.0, bool $canonicalize = false, bool $ignoreCase = false)
+    {
+        $this->value        = $value;
+        $this->delta        = $delta;
+        $this->canonicalize = $canonicalize;
+        $this->ignoreCase   = $ignoreCase;
+    }
+
+    /**
+     * Evaluates the constraint for parameter $other.
+     *
+     * If $returnResult is set to false (the default), an exception is thrown
+     * in case of a failure. null is returned otherwise.
+     *
+     * If $returnResult is true, the result of the evaluation is returned as
+     * a boolean value instead: true in case of success, false in case of a
+     * failure.
+     *
+     * @throws ExpectationFailedException
+     *
+     * @return bool
+     */
+    public function evaluate($other, string $description = '', bool $returnResult = false): ?bool
+    {
+        // If $this->value and $other are identical, they are also equal.
+        // This is the most common path and will allow us to skip
+        // initialization of all the comparators.
+        if ($this->value === $other) {
+            return true;
+        }
+
+        $comparatorFactory = ComparatorFactory::getInstance();
+
+        try {
+            $comparator = $comparatorFactory->getComparatorFor(
+                $this->value,
+                $other
+            );
+
+            $comparator->assertEquals(
+                $this->value,
+                $other,
+                $this->delta,
+                $this->canonicalize,
+                $this->ignoreCase
+            );
+        } catch (ComparisonFailure $f) {
+            if ($returnResult) {
+                return false;
+            }
+
+            throw new ExpectationFailedException(
+                trim($description . "\n" . $f->getMessage()),
+                $f
+            );
+        }
+
+        return true;
+    }
+
+    /**
+     * Returns a string representation of the constraint.
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     */
+    public function toString(): string
+    {
+        $delta = '';
+
+        if (is_string($this->value)) {
+            if (strpos($this->value, "\n") !== false) {
+                return 'is equal to <text>';
+            }
+
+            return sprintf(
+                "is equal to '%s'",
+                $this->value
+            );
+        }
+
+        if ($this->delta != 0) {
+            $delta = sprintf(
+                ' with delta <%F>',
+                $this->delta
+            );
+        }
+
+        return sprintf(
+            'is equal to %s%s',
+            $this->exporter()->export($this->value),
+            $delta
+        );
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/Constraint/Equality/IsEqualCanonicalizing.php b/vendor/phpunit/phpunit/src/Framework/Constraint/Equality/IsEqualCanonicalizing.php
new file mode 100644
index 0000000000000000000000000000000000000000..57bb91ca1faa85052f98ab4c167a80b23365fd67
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/Constraint/Equality/IsEqualCanonicalizing.php
@@ -0,0 +1,108 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework\Constraint;
+
+use function is_string;
+use function sprintf;
+use function strpos;
+use function trim;
+use PHPUnit\Framework\ExpectationFailedException;
+use SebastianBergmann\Comparator\ComparisonFailure;
+use SebastianBergmann\Comparator\Factory as ComparatorFactory;
+
+/**
+ * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+ */
+final class IsEqualCanonicalizing extends Constraint
+{
+    /**
+     * @var mixed
+     */
+    private $value;
+
+    public function __construct($value)
+    {
+        $this->value = $value;
+    }
+
+    /**
+     * Evaluates the constraint for parameter $other.
+     *
+     * If $returnResult is set to false (the default), an exception is thrown
+     * in case of a failure. null is returned otherwise.
+     *
+     * If $returnResult is true, the result of the evaluation is returned as
+     * a boolean value instead: true in case of success, false in case of a
+     * failure.
+     *
+     * @throws ExpectationFailedException
+     */
+    public function evaluate($other, string $description = '', bool $returnResult = false): ?bool
+    {
+        // If $this->value and $other are identical, they are also equal.
+        // This is the most common path and will allow us to skip
+        // initialization of all the comparators.
+        if ($this->value === $other) {
+            return true;
+        }
+
+        $comparatorFactory = ComparatorFactory::getInstance();
+
+        try {
+            $comparator = $comparatorFactory->getComparatorFor(
+                $this->value,
+                $other
+            );
+
+            $comparator->assertEquals(
+                $this->value,
+                $other,
+                0.0,
+                true,
+                false
+            );
+        } catch (ComparisonFailure $f) {
+            if ($returnResult) {
+                return false;
+            }
+
+            throw new ExpectationFailedException(
+                trim($description . "\n" . $f->getMessage()),
+                $f
+            );
+        }
+
+        return true;
+    }
+
+    /**
+     * Returns a string representation of the constraint.
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     */
+    public function toString(): string
+    {
+        if (is_string($this->value)) {
+            if (strpos($this->value, "\n") !== false) {
+                return 'is equal to <text>';
+            }
+
+            return sprintf(
+                "is equal to '%s'",
+                $this->value
+            );
+        }
+
+        return sprintf(
+            'is equal to %s',
+            $this->exporter()->export($this->value)
+        );
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/Constraint/Equality/IsEqualIgnoringCase.php b/vendor/phpunit/phpunit/src/Framework/Constraint/Equality/IsEqualIgnoringCase.php
new file mode 100644
index 0000000000000000000000000000000000000000..d657e96a22af7d7370edf95608ac24861837367b
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/Constraint/Equality/IsEqualIgnoringCase.php
@@ -0,0 +1,108 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework\Constraint;
+
+use function is_string;
+use function sprintf;
+use function strpos;
+use function trim;
+use PHPUnit\Framework\ExpectationFailedException;
+use SebastianBergmann\Comparator\ComparisonFailure;
+use SebastianBergmann\Comparator\Factory as ComparatorFactory;
+
+/**
+ * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+ */
+final class IsEqualIgnoringCase extends Constraint
+{
+    /**
+     * @var mixed
+     */
+    private $value;
+
+    public function __construct($value)
+    {
+        $this->value = $value;
+    }
+
+    /**
+     * Evaluates the constraint for parameter $other.
+     *
+     * If $returnResult is set to false (the default), an exception is thrown
+     * in case of a failure. null is returned otherwise.
+     *
+     * If $returnResult is true, the result of the evaluation is returned as
+     * a boolean value instead: true in case of success, false in case of a
+     * failure.
+     *
+     * @throws ExpectationFailedException
+     */
+    public function evaluate($other, string $description = '', bool $returnResult = false): ?bool
+    {
+        // If $this->value and $other are identical, they are also equal.
+        // This is the most common path and will allow us to skip
+        // initialization of all the comparators.
+        if ($this->value === $other) {
+            return true;
+        }
+
+        $comparatorFactory = ComparatorFactory::getInstance();
+
+        try {
+            $comparator = $comparatorFactory->getComparatorFor(
+                $this->value,
+                $other
+            );
+
+            $comparator->assertEquals(
+                $this->value,
+                $other,
+                0.0,
+                false,
+                true
+            );
+        } catch (ComparisonFailure $f) {
+            if ($returnResult) {
+                return false;
+            }
+
+            throw new ExpectationFailedException(
+                trim($description . "\n" . $f->getMessage()),
+                $f
+            );
+        }
+
+        return true;
+    }
+
+    /**
+     * Returns a string representation of the constraint.
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     */
+    public function toString(): string
+    {
+        if (is_string($this->value)) {
+            if (strpos($this->value, "\n") !== false) {
+                return 'is equal to <text>';
+            }
+
+            return sprintf(
+                "is equal to '%s'",
+                $this->value
+            );
+        }
+
+        return sprintf(
+            'is equal to %s',
+            $this->exporter()->export($this->value)
+        );
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/Constraint/Equality/IsEqualWithDelta.php b/vendor/phpunit/phpunit/src/Framework/Constraint/Equality/IsEqualWithDelta.php
new file mode 100644
index 0000000000000000000000000000000000000000..0370b5118f322e0e3cea55d7a607171386978684
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/Constraint/Equality/IsEqualWithDelta.php
@@ -0,0 +1,100 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework\Constraint;
+
+use function sprintf;
+use function trim;
+use PHPUnit\Framework\ExpectationFailedException;
+use SebastianBergmann\Comparator\ComparisonFailure;
+use SebastianBergmann\Comparator\Factory as ComparatorFactory;
+
+/**
+ * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+ */
+final class IsEqualWithDelta extends Constraint
+{
+    /**
+     * @var mixed
+     */
+    private $value;
+
+    /**
+     * @var float
+     */
+    private $delta;
+
+    public function __construct($value, float $delta)
+    {
+        $this->value = $value;
+        $this->delta = $delta;
+    }
+
+    /**
+     * Evaluates the constraint for parameter $other.
+     *
+     * If $returnResult is set to false (the default), an exception is thrown
+     * in case of a failure. null is returned otherwise.
+     *
+     * If $returnResult is true, the result of the evaluation is returned as
+     * a boolean value instead: true in case of success, false in case of a
+     * failure.
+     *
+     * @throws ExpectationFailedException
+     */
+    public function evaluate($other, string $description = '', bool $returnResult = false): ?bool
+    {
+        // If $this->value and $other are identical, they are also equal.
+        // This is the most common path and will allow us to skip
+        // initialization of all the comparators.
+        if ($this->value === $other) {
+            return true;
+        }
+
+        $comparatorFactory = ComparatorFactory::getInstance();
+
+        try {
+            $comparator = $comparatorFactory->getComparatorFor(
+                $this->value,
+                $other
+            );
+
+            $comparator->assertEquals(
+                $this->value,
+                $other,
+                $this->delta
+            );
+        } catch (ComparisonFailure $f) {
+            if ($returnResult) {
+                return false;
+            }
+
+            throw new ExpectationFailedException(
+                trim($description . "\n" . $f->getMessage()),
+                $f
+            );
+        }
+
+        return true;
+    }
+
+    /**
+     * Returns a string representation of the constraint.
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     */
+    public function toString(): string
+    {
+        return sprintf(
+            'is equal to %s with delta <%F>>',
+            $this->exporter()->export($this->value),
+            $this->delta
+        );
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/Constraint/Exception/Exception.php b/vendor/phpunit/phpunit/src/Framework/Constraint/Exception/Exception.php
new file mode 100644
index 0000000000000000000000000000000000000000..860c0030f6e1d9ce3ebec47bbcbc1e96acc192d0
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/Constraint/Exception/Exception.php
@@ -0,0 +1,85 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework\Constraint;
+
+use function get_class;
+use function sprintf;
+use PHPUnit\Util\Filter;
+use Throwable;
+
+/**
+ * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+ */
+final class Exception extends Constraint
+{
+    /**
+     * @var string
+     */
+    private $className;
+
+    public function __construct(string $className)
+    {
+        $this->className = $className;
+    }
+
+    /**
+     * Returns a string representation of the constraint.
+     */
+    public function toString(): string
+    {
+        return sprintf(
+            'exception of type "%s"',
+            $this->className
+        );
+    }
+
+    /**
+     * Evaluates the constraint for parameter $other. Returns true if the
+     * constraint is met, false otherwise.
+     *
+     * @param mixed $other value or object to evaluate
+     */
+    protected function matches($other): bool
+    {
+        return $other instanceof $this->className;
+    }
+
+    /**
+     * Returns the description of the failure.
+     *
+     * The beginning of failure messages is "Failed asserting that" in most
+     * cases. This method should return the second part of that sentence.
+     *
+     * @param mixed $other evaluated value or object
+     */
+    protected function failureDescription($other): string
+    {
+        if ($other !== null) {
+            $message = '';
+
+            if ($other instanceof Throwable) {
+                $message = '. Message was: "' . $other->getMessage() . '" at'
+                    . "\n" . Filter::getFilteredStacktrace($other);
+            }
+
+            return sprintf(
+                'exception of type "%s" matches expected exception "%s"%s',
+                get_class($other),
+                $this->className,
+                $message
+            );
+        }
+
+        return sprintf(
+            'exception of type "%s" is thrown',
+            $this->className
+        );
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/Constraint/Exception/ExceptionCode.php b/vendor/phpunit/phpunit/src/Framework/Constraint/Exception/ExceptionCode.php
new file mode 100644
index 0000000000000000000000000000000000000000..b8054a949f8bf3708118f721575c3cbd174917ca
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/Constraint/Exception/ExceptionCode.php
@@ -0,0 +1,67 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework\Constraint;
+
+use function sprintf;
+use Throwable;
+
+/**
+ * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+ */
+final class ExceptionCode extends Constraint
+{
+    /**
+     * @var int|string
+     */
+    private $expectedCode;
+
+    /**
+     * @param int|string $expected
+     */
+    public function __construct($expected)
+    {
+        $this->expectedCode = $expected;
+    }
+
+    public function toString(): string
+    {
+        return 'exception code is ';
+    }
+
+    /**
+     * Evaluates the constraint for parameter $other. Returns true if the
+     * constraint is met, false otherwise.
+     *
+     * @param Throwable $other
+     */
+    protected function matches($other): bool
+    {
+        return (string) $other->getCode() === (string) $this->expectedCode;
+    }
+
+    /**
+     * Returns the description of the failure.
+     *
+     * The beginning of failure messages is "Failed asserting that" in most
+     * cases. This method should return the second part of that sentence.
+     *
+     * @param mixed $other evaluated value or object
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     */
+    protected function failureDescription($other): string
+    {
+        return sprintf(
+            '%s is equal to expected exception code %s',
+            $this->exporter()->export($other->getCode()),
+            $this->exporter()->export($this->expectedCode)
+        );
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/Constraint/Exception/ExceptionMessage.php b/vendor/phpunit/phpunit/src/Framework/Constraint/Exception/ExceptionMessage.php
new file mode 100644
index 0000000000000000000000000000000000000000..030beff986d6e393b435639596aa52afbfa13c91
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/Constraint/Exception/ExceptionMessage.php
@@ -0,0 +1,78 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework\Constraint;
+
+use function sprintf;
+use function strpos;
+use Throwable;
+
+/**
+ * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+ */
+final class ExceptionMessage extends Constraint
+{
+    /**
+     * @var string
+     */
+    private $expectedMessage;
+
+    public function __construct(string $expected)
+    {
+        $this->expectedMessage = $expected;
+    }
+
+    public function toString(): string
+    {
+        if ($this->expectedMessage === '') {
+            return 'exception message is empty';
+        }
+
+        return 'exception message contains ';
+    }
+
+    /**
+     * Evaluates the constraint for parameter $other. Returns true if the
+     * constraint is met, false otherwise.
+     *
+     * @param Throwable $other
+     */
+    protected function matches($other): bool
+    {
+        if ($this->expectedMessage === '') {
+            return $other->getMessage() === '';
+        }
+
+        return strpos((string) $other->getMessage(), $this->expectedMessage) !== false;
+    }
+
+    /**
+     * Returns the description of the failure.
+     *
+     * The beginning of failure messages is "Failed asserting that" in most
+     * cases. This method should return the second part of that sentence.
+     *
+     * @param mixed $other evaluated value or object
+     */
+    protected function failureDescription($other): string
+    {
+        if ($this->expectedMessage === '') {
+            return sprintf(
+                "exception message is empty but is '%s'",
+                $other->getMessage()
+            );
+        }
+
+        return sprintf(
+            "exception message '%s' contains '%s'",
+            $other->getMessage(),
+            $this->expectedMessage
+        );
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/Constraint/Exception/ExceptionMessageRegularExpression.php b/vendor/phpunit/phpunit/src/Framework/Constraint/Exception/ExceptionMessageRegularExpression.php
new file mode 100644
index 0000000000000000000000000000000000000000..fd0db1c8fc5e579efc9b889bbc9cc0e9912d16b9
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/Constraint/Exception/ExceptionMessageRegularExpression.php
@@ -0,0 +1,74 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework\Constraint;
+
+use function sprintf;
+use Exception;
+use PHPUnit\Util\RegularExpression as RegularExpressionUtil;
+
+/**
+ * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+ */
+final class ExceptionMessageRegularExpression extends Constraint
+{
+    /**
+     * @var string
+     */
+    private $expectedMessageRegExp;
+
+    public function __construct(string $expected)
+    {
+        $this->expectedMessageRegExp = $expected;
+    }
+
+    public function toString(): string
+    {
+        return 'exception message matches ';
+    }
+
+    /**
+     * Evaluates the constraint for parameter $other. Returns true if the
+     * constraint is met, false otherwise.
+     *
+     * @param \PHPUnit\Framework\Exception $other
+     *
+     * @throws \PHPUnit\Framework\Exception
+     * @throws Exception
+     */
+    protected function matches($other): bool
+    {
+        $match = RegularExpressionUtil::safeMatch($this->expectedMessageRegExp, $other->getMessage());
+
+        if ($match === false) {
+            throw new \PHPUnit\Framework\Exception(
+                "Invalid expected exception message regex given: '{$this->expectedMessageRegExp}'"
+            );
+        }
+
+        return $match === 1;
+    }
+
+    /**
+     * Returns the description of the failure.
+     *
+     * The beginning of failure messages is "Failed asserting that" in most
+     * cases. This method should return the second part of that sentence.
+     *
+     * @param mixed $other evaluated value or object
+     */
+    protected function failureDescription($other): string
+    {
+        return sprintf(
+            "exception message '%s' matches '%s'",
+            $other->getMessage(),
+            $this->expectedMessageRegExp
+        );
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/Constraint/Filesystem/DirectoryExists.php b/vendor/phpunit/phpunit/src/Framework/Constraint/Filesystem/DirectoryExists.php
new file mode 100644
index 0000000000000000000000000000000000000000..ef4b2baf01cd0216916003ed3381cae0f69ab773
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/Constraint/Filesystem/DirectoryExists.php
@@ -0,0 +1,54 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework\Constraint;
+
+use function is_dir;
+use function sprintf;
+
+/**
+ * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+ */
+final class DirectoryExists extends Constraint
+{
+    /**
+     * Returns a string representation of the constraint.
+     */
+    public function toString(): string
+    {
+        return 'directory exists';
+    }
+
+    /**
+     * Evaluates the constraint for parameter $other. Returns true if the
+     * constraint is met, false otherwise.
+     *
+     * @param mixed $other value or object to evaluate
+     */
+    protected function matches($other): bool
+    {
+        return is_dir($other);
+    }
+
+    /**
+     * Returns the description of the failure.
+     *
+     * The beginning of failure messages is "Failed asserting that" in most
+     * cases. This method should return the second part of that sentence.
+     *
+     * @param mixed $other evaluated value or object
+     */
+    protected function failureDescription($other): string
+    {
+        return sprintf(
+            'directory "%s" exists',
+            $other
+        );
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/Constraint/Filesystem/FileExists.php b/vendor/phpunit/phpunit/src/Framework/Constraint/Filesystem/FileExists.php
new file mode 100644
index 0000000000000000000000000000000000000000..41b3136e99a4b99ef2fe1686287173cbefa6b85f
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/Constraint/Filesystem/FileExists.php
@@ -0,0 +1,54 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework\Constraint;
+
+use function file_exists;
+use function sprintf;
+
+/**
+ * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+ */
+final class FileExists extends Constraint
+{
+    /**
+     * Returns a string representation of the constraint.
+     */
+    public function toString(): string
+    {
+        return 'file exists';
+    }
+
+    /**
+     * Evaluates the constraint for parameter $other. Returns true if the
+     * constraint is met, false otherwise.
+     *
+     * @param mixed $other value or object to evaluate
+     */
+    protected function matches($other): bool
+    {
+        return file_exists($other);
+    }
+
+    /**
+     * Returns the description of the failure.
+     *
+     * The beginning of failure messages is "Failed asserting that" in most
+     * cases. This method should return the second part of that sentence.
+     *
+     * @param mixed $other evaluated value or object
+     */
+    protected function failureDescription($other): string
+    {
+        return sprintf(
+            'file "%s" exists',
+            $other
+        );
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/Constraint/Filesystem/IsReadable.php b/vendor/phpunit/phpunit/src/Framework/Constraint/Filesystem/IsReadable.php
new file mode 100644
index 0000000000000000000000000000000000000000..e33d7e04514e9a51f1c52e3abd5f446e8d2d7ef6
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/Constraint/Filesystem/IsReadable.php
@@ -0,0 +1,54 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework\Constraint;
+
+use function is_readable;
+use function sprintf;
+
+/**
+ * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+ */
+final class IsReadable extends Constraint
+{
+    /**
+     * Returns a string representation of the constraint.
+     */
+    public function toString(): string
+    {
+        return 'is readable';
+    }
+
+    /**
+     * Evaluates the constraint for parameter $other. Returns true if the
+     * constraint is met, false otherwise.
+     *
+     * @param mixed $other value or object to evaluate
+     */
+    protected function matches($other): bool
+    {
+        return is_readable($other);
+    }
+
+    /**
+     * Returns the description of the failure.
+     *
+     * The beginning of failure messages is "Failed asserting that" in most
+     * cases. This method should return the second part of that sentence.
+     *
+     * @param mixed $other evaluated value or object
+     */
+    protected function failureDescription($other): string
+    {
+        return sprintf(
+            '"%s" is readable',
+            $other
+        );
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/Constraint/Filesystem/IsWritable.php b/vendor/phpunit/phpunit/src/Framework/Constraint/Filesystem/IsWritable.php
new file mode 100644
index 0000000000000000000000000000000000000000..93981224a141357cd74ec68eea49441db562a300
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/Constraint/Filesystem/IsWritable.php
@@ -0,0 +1,54 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework\Constraint;
+
+use function is_writable;
+use function sprintf;
+
+/**
+ * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+ */
+final class IsWritable extends Constraint
+{
+    /**
+     * Returns a string representation of the constraint.
+     */
+    public function toString(): string
+    {
+        return 'is writable';
+    }
+
+    /**
+     * Evaluates the constraint for parameter $other. Returns true if the
+     * constraint is met, false otherwise.
+     *
+     * @param mixed $other value or object to evaluate
+     */
+    protected function matches($other): bool
+    {
+        return is_writable($other);
+    }
+
+    /**
+     * Returns the description of the failure.
+     *
+     * The beginning of failure messages is "Failed asserting that" in most
+     * cases. This method should return the second part of that sentence.
+     *
+     * @param mixed $other evaluated value or object
+     */
+    protected function failureDescription($other): string
+    {
+        return sprintf(
+            '"%s" is writable',
+            $other
+        );
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/Constraint/IsAnything.php b/vendor/phpunit/phpunit/src/Framework/Constraint/IsAnything.php
new file mode 100644
index 0000000000000000000000000000000000000000..db84a7431eed8a31093ce63e78502f773042858c
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/Constraint/IsAnything.php
@@ -0,0 +1,51 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework\Constraint;
+
+use PHPUnit\Framework\ExpectationFailedException;
+
+/**
+ * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+ */
+final class IsAnything extends Constraint
+{
+    /**
+     * Evaluates the constraint for parameter $other.
+     *
+     * If $returnResult is set to false (the default), an exception is thrown
+     * in case of a failure. null is returned otherwise.
+     *
+     * If $returnResult is true, the result of the evaluation is returned as
+     * a boolean value instead: true in case of success, false in case of a
+     * failure.
+     *
+     * @throws ExpectationFailedException
+     */
+    public function evaluate($other, string $description = '', bool $returnResult = false): ?bool
+    {
+        return $returnResult ? true : null;
+    }
+
+    /**
+     * Returns a string representation of the constraint.
+     */
+    public function toString(): string
+    {
+        return 'is anything';
+    }
+
+    /**
+     * Counts the number of constraint elements.
+     */
+    public function count(): int
+    {
+        return 0;
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/Constraint/IsIdentical.php b/vendor/phpunit/phpunit/src/Framework/Constraint/IsIdentical.php
new file mode 100644
index 0000000000000000000000000000000000000000..b49d992938dc8a5f9432b7738971c04f0fa2d668
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/Constraint/IsIdentical.php
@@ -0,0 +1,141 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework\Constraint;
+
+use function abs;
+use function get_class;
+use function is_array;
+use function is_float;
+use function is_infinite;
+use function is_nan;
+use function is_object;
+use function is_string;
+use function sprintf;
+use PHPUnit\Framework\ExpectationFailedException;
+use SebastianBergmann\Comparator\ComparisonFailure;
+
+/**
+ * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+ */
+final class IsIdentical extends Constraint
+{
+    /**
+     * @var float
+     */
+    private const EPSILON = 0.0000000001;
+
+    /**
+     * @var mixed
+     */
+    private $value;
+
+    public function __construct($value)
+    {
+        $this->value = $value;
+    }
+
+    /**
+     * Evaluates the constraint for parameter $other.
+     *
+     * If $returnResult is set to false (the default), an exception is thrown
+     * in case of a failure. null is returned otherwise.
+     *
+     * If $returnResult is true, the result of the evaluation is returned as
+     * a boolean value instead: true in case of success, false in case of a
+     * failure.
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws ExpectationFailedException
+     */
+    public function evaluate($other, string $description = '', bool $returnResult = false): ?bool
+    {
+        if (is_float($this->value) && is_float($other) &&
+            !is_infinite($this->value) && !is_infinite($other) &&
+            !is_nan($this->value) && !is_nan($other)) {
+            $success = abs($this->value - $other) < self::EPSILON;
+        } else {
+            $success = $this->value === $other;
+        }
+
+        if ($returnResult) {
+            return $success;
+        }
+
+        if (!$success) {
+            $f = null;
+
+            // if both values are strings, make sure a diff is generated
+            if (is_string($this->value) && is_string($other)) {
+                $f = new ComparisonFailure(
+                    $this->value,
+                    $other,
+                    sprintf("'%s'", $this->value),
+                    sprintf("'%s'", $other)
+                );
+            }
+
+            // if both values are array, make sure a diff is generated
+            if (is_array($this->value) && is_array($other)) {
+                $f = new ComparisonFailure(
+                    $this->value,
+                    $other,
+                    $this->exporter()->export($this->value),
+                    $this->exporter()->export($other)
+                );
+            }
+
+            $this->fail($other, $description, $f);
+        }
+
+        return null;
+    }
+
+    /**
+     * Returns a string representation of the constraint.
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     */
+    public function toString(): string
+    {
+        if (is_object($this->value)) {
+            return 'is identical to an object of class "' .
+                get_class($this->value) . '"';
+        }
+
+        return 'is identical to ' . $this->exporter()->export($this->value);
+    }
+
+    /**
+     * Returns the description of the failure.
+     *
+     * The beginning of failure messages is "Failed asserting that" in most
+     * cases. This method should return the second part of that sentence.
+     *
+     * @param mixed $other evaluated value or object
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     */
+    protected function failureDescription($other): string
+    {
+        if (is_object($this->value) && is_object($other)) {
+            return 'two variables reference the same object';
+        }
+
+        if (is_string($this->value) && is_string($other)) {
+            return 'two strings are identical';
+        }
+
+        if (is_array($this->value) && is_array($other)) {
+            return 'two arrays are identical';
+        }
+
+        return parent::failureDescription($other);
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/Constraint/JsonMatches.php b/vendor/phpunit/phpunit/src/Framework/Constraint/JsonMatches.php
new file mode 100644
index 0000000000000000000000000000000000000000..23a4de7e99fed07b401e8817ce7c2efbe6c56a64
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/Constraint/JsonMatches.php
@@ -0,0 +1,109 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework\Constraint;
+
+use function json_decode;
+use function sprintf;
+use PHPUnit\Framework\ExpectationFailedException;
+use PHPUnit\Util\Json;
+use SebastianBergmann\Comparator\ComparisonFailure;
+
+/**
+ * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+ */
+final class JsonMatches extends Constraint
+{
+    /**
+     * @var string
+     */
+    private $value;
+
+    public function __construct(string $value)
+    {
+        $this->value = $value;
+    }
+
+    /**
+     * Returns a string representation of the object.
+     */
+    public function toString(): string
+    {
+        return sprintf(
+            'matches JSON string "%s"',
+            $this->value
+        );
+    }
+
+    /**
+     * Evaluates the constraint for parameter $other. Returns true if the
+     * constraint is met, false otherwise.
+     *
+     * This method can be overridden to implement the evaluation algorithm.
+     *
+     * @param mixed $other value or object to evaluate
+     */
+    protected function matches($other): bool
+    {
+        [$error, $recodedOther] = Json::canonicalize($other);
+
+        if ($error) {
+            return false;
+        }
+
+        [$error, $recodedValue] = Json::canonicalize($this->value);
+
+        if ($error) {
+            return false;
+        }
+
+        return $recodedOther == $recodedValue;
+    }
+
+    /**
+     * Throws an exception for the given compared value and test description.
+     *
+     * @param mixed             $other             evaluated value or object
+     * @param string            $description       Additional information about the test
+     * @param ComparisonFailure $comparisonFailure
+     *
+     * @throws \PHPUnit\Framework\Exception
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws ExpectationFailedException
+     *
+     * @psalm-return never-return
+     */
+    protected function fail($other, $description, ComparisonFailure $comparisonFailure = null): void
+    {
+        if ($comparisonFailure === null) {
+            [$error, $recodedOther] = Json::canonicalize($other);
+
+            if ($error) {
+                parent::fail($other, $description);
+            }
+
+            [$error, $recodedValue] = Json::canonicalize($this->value);
+
+            if ($error) {
+                parent::fail($other, $description);
+            }
+
+            $comparisonFailure = new ComparisonFailure(
+                json_decode($this->value),
+                json_decode($other),
+                Json::prettify($recodedValue),
+                Json::prettify($recodedOther),
+                false,
+                'Failed asserting that two json values are equal.'
+            );
+        }
+
+        parent::fail($other, $description, $comparisonFailure);
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/Constraint/JsonMatchesErrorMessageProvider.php b/vendor/phpunit/phpunit/src/Framework/Constraint/JsonMatchesErrorMessageProvider.php
new file mode 100644
index 0000000000000000000000000000000000000000..8ded556ce1d748157869de40634e8fc89fab4089
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/Constraint/JsonMatchesErrorMessageProvider.php
@@ -0,0 +1,72 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework\Constraint;
+
+use const JSON_ERROR_CTRL_CHAR;
+use const JSON_ERROR_DEPTH;
+use const JSON_ERROR_NONE;
+use const JSON_ERROR_STATE_MISMATCH;
+use const JSON_ERROR_SYNTAX;
+use const JSON_ERROR_UTF8;
+use function strtolower;
+
+/**
+ * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+ */
+final class JsonMatchesErrorMessageProvider
+{
+    /**
+     * Translates JSON error to a human readable string.
+     */
+    public static function determineJsonError(string $error, string $prefix = ''): ?string
+    {
+        switch ($error) {
+            case JSON_ERROR_NONE:
+                return null;
+            case JSON_ERROR_DEPTH:
+                return $prefix . 'Maximum stack depth exceeded';
+            case JSON_ERROR_STATE_MISMATCH:
+                return $prefix . 'Underflow or the modes mismatch';
+            case JSON_ERROR_CTRL_CHAR:
+                return $prefix . 'Unexpected control character found';
+            case JSON_ERROR_SYNTAX:
+                return $prefix . 'Syntax error, malformed JSON';
+            case JSON_ERROR_UTF8:
+                return $prefix . 'Malformed UTF-8 characters, possibly incorrectly encoded';
+
+            default:
+                return $prefix . 'Unknown error';
+        }
+    }
+
+    /**
+     * Translates a given type to a human readable message prefix.
+     */
+    public static function translateTypeToPrefix(string $type): string
+    {
+        switch (strtolower($type)) {
+            case 'expected':
+                $prefix = 'Expected value JSON decode error - ';
+
+                break;
+            case 'actual':
+                $prefix = 'Actual value JSON decode error - ';
+
+                break;
+
+            default:
+                $prefix = '';
+
+                break;
+        }
+
+        return $prefix;
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/Constraint/Math/IsFinite.php b/vendor/phpunit/phpunit/src/Framework/Constraint/Math/IsFinite.php
new file mode 100644
index 0000000000000000000000000000000000000000..9a2f328668803d622e144dcf02c5d943520d66ac
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/Constraint/Math/IsFinite.php
@@ -0,0 +1,37 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework\Constraint;
+
+use function is_finite;
+
+/**
+ * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+ */
+final class IsFinite extends Constraint
+{
+    /**
+     * Returns a string representation of the constraint.
+     */
+    public function toString(): string
+    {
+        return 'is finite';
+    }
+
+    /**
+     * Evaluates the constraint for parameter $other. Returns true if the
+     * constraint is met, false otherwise.
+     *
+     * @param mixed $other value or object to evaluate
+     */
+    protected function matches($other): bool
+    {
+        return is_finite($other);
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/Constraint/Math/IsInfinite.php b/vendor/phpunit/phpunit/src/Framework/Constraint/Math/IsInfinite.php
new file mode 100644
index 0000000000000000000000000000000000000000..c718514c2b116239b5284b5bc9f092f061bbe69b
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/Constraint/Math/IsInfinite.php
@@ -0,0 +1,37 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework\Constraint;
+
+use function is_infinite;
+
+/**
+ * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+ */
+final class IsInfinite extends Constraint
+{
+    /**
+     * Returns a string representation of the constraint.
+     */
+    public function toString(): string
+    {
+        return 'is infinite';
+    }
+
+    /**
+     * Evaluates the constraint for parameter $other. Returns true if the
+     * constraint is met, false otherwise.
+     *
+     * @param mixed $other value or object to evaluate
+     */
+    protected function matches($other): bool
+    {
+        return is_infinite($other);
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/Constraint/Math/IsNan.php b/vendor/phpunit/phpunit/src/Framework/Constraint/Math/IsNan.php
new file mode 100644
index 0000000000000000000000000000000000000000..0062c5b5cbdb45d92623622c4661667b55ae851c
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/Constraint/Math/IsNan.php
@@ -0,0 +1,37 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework\Constraint;
+
+use function is_nan;
+
+/**
+ * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+ */
+final class IsNan extends Constraint
+{
+    /**
+     * Returns a string representation of the constraint.
+     */
+    public function toString(): string
+    {
+        return 'is nan';
+    }
+
+    /**
+     * Evaluates the constraint for parameter $other. Returns true if the
+     * constraint is met, false otherwise.
+     *
+     * @param mixed $other value or object to evaluate
+     */
+    protected function matches($other): bool
+    {
+        return is_nan($other);
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/Constraint/Object/ClassHasAttribute.php b/vendor/phpunit/phpunit/src/Framework/Constraint/Object/ClassHasAttribute.php
new file mode 100644
index 0000000000000000000000000000000000000000..daa14027d5b6df15c22df80920dacd79c2d86b2f
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/Constraint/Object/ClassHasAttribute.php
@@ -0,0 +1,88 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework\Constraint;
+
+use function get_class;
+use function is_object;
+use function sprintf;
+use PHPUnit\Framework\Exception;
+use ReflectionClass;
+use ReflectionException;
+
+/**
+ * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+ */
+class ClassHasAttribute extends Constraint
+{
+    /**
+     * @var string
+     */
+    private $attributeName;
+
+    public function __construct(string $attributeName)
+    {
+        $this->attributeName = $attributeName;
+    }
+
+    /**
+     * Returns a string representation of the constraint.
+     */
+    public function toString(): string
+    {
+        return sprintf(
+            'has attribute "%s"',
+            $this->attributeName
+        );
+    }
+
+    /**
+     * Evaluates the constraint for parameter $other. Returns true if the
+     * constraint is met, false otherwise.
+     *
+     * @param mixed $other value or object to evaluate
+     */
+    protected function matches($other): bool
+    {
+        try {
+            return (new ReflectionClass($other))->hasProperty($this->attributeName);
+            // @codeCoverageIgnoreStart
+        } catch (ReflectionException $e) {
+            throw new Exception(
+                $e->getMessage(),
+                (int) $e->getCode(),
+                $e
+            );
+        }
+        // @codeCoverageIgnoreEnd
+    }
+
+    /**
+     * Returns the description of the failure.
+     *
+     * The beginning of failure messages is "Failed asserting that" in most
+     * cases. This method should return the second part of that sentence.
+     *
+     * @param mixed $other evaluated value or object
+     */
+    protected function failureDescription($other): string
+    {
+        return sprintf(
+            '%sclass "%s" %s',
+            is_object($other) ? 'object of ' : '',
+            is_object($other) ? get_class($other) : $other,
+            $this->toString()
+        );
+    }
+
+    protected function attributeName(): string
+    {
+        return $this->attributeName;
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/Constraint/Object/ClassHasStaticAttribute.php b/vendor/phpunit/phpunit/src/Framework/Constraint/Object/ClassHasStaticAttribute.php
new file mode 100644
index 0000000000000000000000000000000000000000..cacd0d75298808249e8430f4b343dcc40a0a2df8
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/Constraint/Object/ClassHasStaticAttribute.php
@@ -0,0 +1,59 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework\Constraint;
+
+use function sprintf;
+use PHPUnit\Framework\Exception;
+use ReflectionClass;
+use ReflectionException;
+
+/**
+ * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+ */
+final class ClassHasStaticAttribute extends ClassHasAttribute
+{
+    /**
+     * Returns a string representation of the constraint.
+     */
+    public function toString(): string
+    {
+        return sprintf(
+            'has static attribute "%s"',
+            $this->attributeName()
+        );
+    }
+
+    /**
+     * Evaluates the constraint for parameter $other. Returns true if the
+     * constraint is met, false otherwise.
+     *
+     * @param mixed $other value or object to evaluate
+     */
+    protected function matches($other): bool
+    {
+        try {
+            $class = new ReflectionClass($other);
+
+            if ($class->hasProperty($this->attributeName())) {
+                return $class->getProperty($this->attributeName())->isStatic();
+            }
+            // @codeCoverageIgnoreStart
+        } catch (ReflectionException $e) {
+            throw new Exception(
+                $e->getMessage(),
+                (int) $e->getCode(),
+                $e
+            );
+        }
+        // @codeCoverageIgnoreEnd
+
+        return false;
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/Constraint/Object/ObjectEquals.php b/vendor/phpunit/phpunit/src/Framework/Constraint/Object/ObjectEquals.php
new file mode 100644
index 0000000000000000000000000000000000000000..30f3a330caa4fc89dd1b26141aef0470fa1bb68c
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/Constraint/Object/ObjectEquals.php
@@ -0,0 +1,151 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework\Constraint;
+
+use function get_class;
+use function is_object;
+use PHPUnit\Framework\ActualValueIsNotAnObjectException;
+use PHPUnit\Framework\ComparisonMethodDoesNotAcceptParameterTypeException;
+use PHPUnit\Framework\ComparisonMethodDoesNotDeclareBoolReturnTypeException;
+use PHPUnit\Framework\ComparisonMethodDoesNotDeclareExactlyOneParameterException;
+use PHPUnit\Framework\ComparisonMethodDoesNotDeclareParameterTypeException;
+use PHPUnit\Framework\ComparisonMethodDoesNotExistException;
+use ReflectionNamedType;
+use ReflectionObject;
+
+/**
+ * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+ */
+final class ObjectEquals extends Constraint
+{
+    /**
+     * @var object
+     */
+    private $expected;
+
+    /**
+     * @var string
+     */
+    private $method;
+
+    public function __construct(object $object, string $method = 'equals')
+    {
+        $this->expected = $object;
+        $this->method   = $method;
+    }
+
+    public function toString(): string
+    {
+        return 'two objects are equal';
+    }
+
+    /**
+     * @throws ActualValueIsNotAnObjectException
+     * @throws ComparisonMethodDoesNotAcceptParameterTypeException
+     * @throws ComparisonMethodDoesNotDeclareBoolReturnTypeException
+     * @throws ComparisonMethodDoesNotDeclareExactlyOneParameterException
+     * @throws ComparisonMethodDoesNotDeclareParameterTypeException
+     * @throws ComparisonMethodDoesNotExistException
+     */
+    protected function matches($other): bool
+    {
+        if (!is_object($other)) {
+            throw new ActualValueIsNotAnObjectException;
+        }
+
+        $object = new ReflectionObject($other);
+
+        if (!$object->hasMethod($this->method)) {
+            throw new ComparisonMethodDoesNotExistException(
+                get_class($other),
+                $this->method
+            );
+        }
+
+        /** @noinspection PhpUnhandledExceptionInspection */
+        $method = $object->getMethod($this->method);
+
+        if (!$method->hasReturnType()) {
+            throw new ComparisonMethodDoesNotDeclareBoolReturnTypeException(
+                get_class($other),
+                $this->method
+            );
+        }
+
+        $returnType = $method->getReturnType();
+
+        if (!$returnType instanceof ReflectionNamedType) {
+            throw new ComparisonMethodDoesNotDeclareBoolReturnTypeException(
+                get_class($other),
+                $this->method
+            );
+        }
+
+        if ($returnType->allowsNull()) {
+            throw new ComparisonMethodDoesNotDeclareBoolReturnTypeException(
+                get_class($other),
+                $this->method
+            );
+        }
+
+        if ($returnType->getName() !== 'bool') {
+            throw new ComparisonMethodDoesNotDeclareBoolReturnTypeException(
+                get_class($other),
+                $this->method
+            );
+        }
+
+        if ($method->getNumberOfParameters() !== 1 || $method->getNumberOfRequiredParameters() !== 1) {
+            throw new ComparisonMethodDoesNotDeclareExactlyOneParameterException(
+                get_class($other),
+                $this->method
+            );
+        }
+
+        $parameter = $method->getParameters()[0];
+
+        if (!$parameter->hasType()) {
+            throw new ComparisonMethodDoesNotDeclareParameterTypeException(
+                get_class($other),
+                $this->method
+            );
+        }
+
+        $type = $parameter->getType();
+
+        if (!$type instanceof ReflectionNamedType) {
+            throw new ComparisonMethodDoesNotDeclareParameterTypeException(
+                get_class($other),
+                $this->method
+            );
+        }
+
+        $typeName = $type->getName();
+
+        if ($typeName === 'self') {
+            $typeName = get_class($other);
+        }
+
+        if (!$this->expected instanceof $typeName) {
+            throw new ComparisonMethodDoesNotAcceptParameterTypeException(
+                get_class($other),
+                $this->method,
+                get_class($this->expected)
+            );
+        }
+
+        return $other->{$this->method}($this->expected);
+    }
+
+    protected function failureDescription($other): string
+    {
+        return $this->toString();
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/Constraint/Object/ObjectHasAttribute.php b/vendor/phpunit/phpunit/src/Framework/Constraint/Object/ObjectHasAttribute.php
new file mode 100644
index 0000000000000000000000000000000000000000..5fbc0888c33dea1383379ec42a9d42f37d66bfd7
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/Constraint/Object/ObjectHasAttribute.php
@@ -0,0 +1,29 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework\Constraint;
+
+use ReflectionObject;
+
+/**
+ * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+ */
+final class ObjectHasAttribute extends ClassHasAttribute
+{
+    /**
+     * Evaluates the constraint for parameter $other. Returns true if the
+     * constraint is met, false otherwise.
+     *
+     * @param mixed $other value or object to evaluate
+     */
+    protected function matches($other): bool
+    {
+        return (new ReflectionObject($other))->hasProperty($this->attributeName());
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/Constraint/Operator/BinaryOperator.php b/vendor/phpunit/phpunit/src/Framework/Constraint/Operator/BinaryOperator.php
new file mode 100644
index 0000000000000000000000000000000000000000..4588e7c07d91c46138e18ff00d2c97daae76c41f
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/Constraint/Operator/BinaryOperator.php
@@ -0,0 +1,147 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework\Constraint;
+
+use function array_map;
+use function array_values;
+use function count;
+
+/**
+ * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+ */
+abstract class BinaryOperator extends Operator
+{
+    /**
+     * @var Constraint[]
+     */
+    private $constraints = [];
+
+    public static function fromConstraints(Constraint ...$constraints): self
+    {
+        $constraint = new static;
+
+        $constraint->constraints = $constraints;
+
+        return $constraint;
+    }
+
+    /**
+     * @param mixed[] $constraints
+     */
+    public function setConstraints(array $constraints): void
+    {
+        $this->constraints = array_map(function ($constraint): Constraint {
+            return $this->checkConstraint($constraint);
+        }, array_values($constraints));
+    }
+
+    /**
+     * Returns the number of operands (constraints).
+     */
+    final public function arity(): int
+    {
+        return count($this->constraints);
+    }
+
+    /**
+     * Returns a string representation of the constraint.
+     */
+    public function toString(): string
+    {
+        $reduced = $this->reduce();
+
+        if ($reduced !== $this) {
+            return $reduced->toString();
+        }
+
+        $text = '';
+
+        foreach ($this->constraints as $key => $constraint) {
+            $constraint = $constraint->reduce();
+
+            $text .= $this->constraintToString($constraint, $key);
+        }
+
+        return $text;
+    }
+
+    /**
+     * Counts the number of constraint elements.
+     */
+    public function count(): int
+    {
+        $count = 0;
+
+        foreach ($this->constraints as $constraint) {
+            $count += count($constraint);
+        }
+
+        return $count;
+    }
+
+    /**
+     * Returns the nested constraints.
+     */
+    final protected function constraints(): array
+    {
+        return $this->constraints;
+    }
+
+    /**
+     * Returns true if the $constraint needs to be wrapped with braces.
+     */
+    final protected function constraintNeedsParentheses(Constraint $constraint): bool
+    {
+        return $this->arity() > 1 && parent::constraintNeedsParentheses($constraint);
+    }
+
+    /**
+     * Reduces the sub-expression starting at $this by skipping degenerate
+     * sub-expression and returns first descendant constraint that starts
+     * a non-reducible sub-expression.
+     *
+     * See Constraint::reduce() for more.
+     */
+    protected function reduce(): Constraint
+    {
+        if ($this->arity() === 1 && $this->constraints[0] instanceof Operator) {
+            return $this->constraints[0]->reduce();
+        }
+
+        return parent::reduce();
+    }
+
+    /**
+     * Returns string representation of given operand in context of this operator.
+     *
+     * @param Constraint $constraint operand constraint
+     * @param int        $position   position of $constraint in this expression
+     */
+    private function constraintToString(Constraint $constraint, int $position): string
+    {
+        $prefix = '';
+
+        if ($position > 0) {
+            $prefix = (' ' . $this->operator() . ' ');
+        }
+
+        if ($this->constraintNeedsParentheses($constraint)) {
+            return $prefix . '( ' . $constraint->toString() . ' )';
+        }
+
+        $string = $constraint->toStringInContext($this, $position);
+
+        if ($string === '') {
+            $string = $constraint->toString();
+        }
+
+        return $prefix . $string;
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/Constraint/Operator/LogicalAnd.php b/vendor/phpunit/phpunit/src/Framework/Constraint/Operator/LogicalAnd.php
new file mode 100644
index 0000000000000000000000000000000000000000..a1af4dd3200de9e679e5b9923bd714f9a924818a
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/Constraint/Operator/LogicalAnd.php
@@ -0,0 +1,51 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework\Constraint;
+
+/**
+ * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+ */
+final class LogicalAnd extends BinaryOperator
+{
+    /**
+     * Returns the name of this operator.
+     */
+    public function operator(): string
+    {
+        return 'and';
+    }
+
+    /**
+     * Returns this operator's precedence.
+     *
+     * @see https://www.php.net/manual/en/language.operators.precedence.php
+     */
+    public function precedence(): int
+    {
+        return 22;
+    }
+
+    /**
+     * Evaluates the constraint for parameter $other. Returns true if the
+     * constraint is met, false otherwise.
+     *
+     * @param mixed $other value or object to evaluate
+     */
+    protected function matches($other): bool
+    {
+        foreach ($this->constraints() as $constraint) {
+            if (!$constraint->evaluate($other, '', true)) {
+                return false;
+            }
+        }
+
+        return [] !== $this->constraints();
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/Constraint/Operator/LogicalNot.php b/vendor/phpunit/phpunit/src/Framework/Constraint/Operator/LogicalNot.php
new file mode 100644
index 0000000000000000000000000000000000000000..a89d6780d5f75e654f8afa7343234515165c666d
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/Constraint/Operator/LogicalNot.php
@@ -0,0 +1,135 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework\Constraint;
+
+use function array_map;
+use function count;
+use function preg_match;
+use function preg_quote;
+use function preg_replace;
+
+/**
+ * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+ */
+final class LogicalNot extends UnaryOperator
+{
+    public static function negate(string $string): string
+    {
+        $positives = [
+            'contains ',
+            'exists',
+            'has ',
+            'is ',
+            'are ',
+            'matches ',
+            'starts with ',
+            'ends with ',
+            'reference ',
+            'not not ',
+        ];
+
+        $negatives = [
+            'does not contain ',
+            'does not exist',
+            'does not have ',
+            'is not ',
+            'are not ',
+            'does not match ',
+            'starts not with ',
+            'ends not with ',
+            'don\'t reference ',
+            'not ',
+        ];
+
+        preg_match('/(\'[\w\W]*\')([\w\W]*)("[\w\W]*")/i', $string, $matches);
+
+        $positives = array_map(static function (string $s) {
+            return '/\\b' . preg_quote($s, '/') . '/';
+        }, $positives);
+
+        if (count($matches) > 0) {
+            $nonInput = $matches[2];
+
+            $negatedString = preg_replace(
+                '/' . preg_quote($nonInput, '/') . '/',
+                preg_replace(
+                    $positives,
+                    $negatives,
+                    $nonInput
+                ),
+                $string
+            );
+        } else {
+            $negatedString = preg_replace(
+                $positives,
+                $negatives,
+                $string
+            );
+        }
+
+        return $negatedString;
+    }
+
+    /**
+     * Returns the name of this operator.
+     */
+    public function operator(): string
+    {
+        return 'not';
+    }
+
+    /**
+     * Returns this operator's precedence.
+     *
+     * @see https://www.php.net/manual/en/language.operators.precedence.php
+     */
+    public function precedence(): int
+    {
+        return 5;
+    }
+
+    /**
+     * Evaluates the constraint for parameter $other. Returns true if the
+     * constraint is met, false otherwise.
+     *
+     * @param mixed $other value or object to evaluate
+     */
+    protected function matches($other): bool
+    {
+        return !$this->constraint()->evaluate($other, '', true);
+    }
+
+    /**
+     * Applies additional transformation to strings returned by toString() or
+     * failureDescription().
+     */
+    protected function transformString(string $string): string
+    {
+        return self::negate($string);
+    }
+
+    /**
+     * Reduces the sub-expression starting at $this by skipping degenerate
+     * sub-expression and returns first descendant constraint that starts
+     * a non-reducible sub-expression.
+     *
+     * See Constraint::reduce() for more.
+     */
+    protected function reduce(): Constraint
+    {
+        $constraint = $this->constraint();
+
+        if ($constraint instanceof self) {
+            return $constraint->constraint()->reduce();
+        }
+
+        return parent::reduce();
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/Constraint/Operator/LogicalOr.php b/vendor/phpunit/phpunit/src/Framework/Constraint/Operator/LogicalOr.php
new file mode 100644
index 0000000000000000000000000000000000000000..2932de6753a7e3efc46968986706cb2e1f265adc
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/Constraint/Operator/LogicalOr.php
@@ -0,0 +1,51 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework\Constraint;
+
+/**
+ * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+ */
+final class LogicalOr extends BinaryOperator
+{
+    /**
+     * Returns the name of this operator.
+     */
+    public function operator(): string
+    {
+        return 'or';
+    }
+
+    /**
+     * Returns this operator's precedence.
+     *
+     * @see https://www.php.net/manual/en/language.operators.precedence.php
+     */
+    public function precedence(): int
+    {
+        return 24;
+    }
+
+    /**
+     * Evaluates the constraint for parameter $other. Returns true if the
+     * constraint is met, false otherwise.
+     *
+     * @param mixed $other value or object to evaluate
+     */
+    public function matches($other): bool
+    {
+        foreach ($this->constraints() as $constraint) {
+            if ($constraint->evaluate($other, '', true)) {
+                return true;
+            }
+        }
+
+        return false;
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/Constraint/Operator/LogicalXor.php b/vendor/phpunit/phpunit/src/Framework/Constraint/Operator/LogicalXor.php
new file mode 100644
index 0000000000000000000000000000000000000000..157643f8210283acde2957da21b79d6155eec480
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/Constraint/Operator/LogicalXor.php
@@ -0,0 +1,62 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework\Constraint;
+
+use function array_reduce;
+use function array_shift;
+
+/**
+ * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+ */
+final class LogicalXor extends BinaryOperator
+{
+    /**
+     * Returns the name of this operator.
+     */
+    public function operator(): string
+    {
+        return 'xor';
+    }
+
+    /**
+     * Returns this operator's precedence.
+     *
+     * @see https://www.php.net/manual/en/language.operators.precedence.php.
+     */
+    public function precedence(): int
+    {
+        return 23;
+    }
+
+    /**
+     * Evaluates the constraint for parameter $other. Returns true if the
+     * constraint is met, false otherwise.
+     *
+     * @param mixed $other value or object to evaluate
+     */
+    public function matches($other): bool
+    {
+        $constraints = $this->constraints();
+
+        $initial = array_shift($constraints);
+
+        if ($initial === null) {
+            return false;
+        }
+
+        return array_reduce(
+            $constraints,
+            static function (bool $matches, Constraint $constraint) use ($other): bool {
+                return $matches xor $constraint->evaluate($other, '', true);
+            },
+            $initial->evaluate($other, '', true)
+        );
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/Constraint/Operator/Operator.php b/vendor/phpunit/phpunit/src/Framework/Constraint/Operator/Operator.php
new file mode 100644
index 0000000000000000000000000000000000000000..3f51a0f409398ad1404437e585e9d272b7435c8a
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/Constraint/Operator/Operator.php
@@ -0,0 +1,55 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework\Constraint;
+
+/**
+ * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+ */
+abstract class Operator extends Constraint
+{
+    /**
+     * Returns the name of this operator.
+     */
+    abstract public function operator(): string;
+
+    /**
+     * Returns this operator's precedence.
+     *
+     * @see https://www.php.net/manual/en/language.operators.precedence.php
+     */
+    abstract public function precedence(): int;
+
+    /**
+     * Returns the number of operands.
+     */
+    abstract public function arity(): int;
+
+    /**
+     * Validates $constraint argument.
+     */
+    protected function checkConstraint($constraint): Constraint
+    {
+        if (!$constraint instanceof Constraint) {
+            return new IsEqual($constraint);
+        }
+
+        return $constraint;
+    }
+
+    /**
+     * Returns true if the $constraint needs to be wrapped with braces.
+     */
+    protected function constraintNeedsParentheses(Constraint $constraint): bool
+    {
+        return $constraint instanceof self &&
+               $constraint->arity() > 1 &&
+               $this->precedence() <= $constraint->precedence();
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/Constraint/Operator/UnaryOperator.php b/vendor/phpunit/phpunit/src/Framework/Constraint/Operator/UnaryOperator.php
new file mode 100644
index 0000000000000000000000000000000000000000..0a7a5fa2f9268f5cd613881191148d8d8012670e
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/Constraint/Operator/UnaryOperator.php
@@ -0,0 +1,140 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework\Constraint;
+
+use function count;
+
+/**
+ * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+ */
+abstract class UnaryOperator extends Operator
+{
+    /**
+     * @var Constraint
+     */
+    private $constraint;
+
+    /**
+     * @param Constraint|mixed $constraint
+     */
+    public function __construct($constraint)
+    {
+        $this->constraint = $this->checkConstraint($constraint);
+    }
+
+    /**
+     * Returns the number of operands (constraints).
+     */
+    public function arity(): int
+    {
+        return 1;
+    }
+
+    /**
+     * Returns a string representation of the constraint.
+     */
+    public function toString(): string
+    {
+        $reduced = $this->reduce();
+
+        if ($reduced !== $this) {
+            return $reduced->toString();
+        }
+
+        $constraint = $this->constraint->reduce();
+
+        if ($this->constraintNeedsParentheses($constraint)) {
+            return $this->operator() . '( ' . $constraint->toString() . ' )';
+        }
+
+        $string = $constraint->toStringInContext($this, 0);
+
+        if ($string === '') {
+            return $this->transformString($constraint->toString());
+        }
+
+        return $string;
+    }
+
+    /**
+     * Counts the number of constraint elements.
+     */
+    public function count(): int
+    {
+        return count($this->constraint);
+    }
+
+    /**
+     * Returns the description of the failure.
+     *
+     * The beginning of failure messages is "Failed asserting that" in most
+     * cases. This method should return the second part of that sentence.
+     *
+     * @param mixed $other evaluated value or object
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     */
+    protected function failureDescription($other): string
+    {
+        $reduced = $this->reduce();
+
+        if ($reduced !== $this) {
+            return $reduced->failureDescription($other);
+        }
+
+        $constraint = $this->constraint->reduce();
+
+        if ($this->constraintNeedsParentheses($constraint)) {
+            return $this->operator() . '( ' . $constraint->failureDescription($other) . ' )';
+        }
+
+        $string = $constraint->failureDescriptionInContext($this, 0, $other);
+
+        if ($string === '') {
+            return $this->transformString($constraint->failureDescription($other));
+        }
+
+        return $string;
+    }
+
+    /**
+     * Transforms string returned by the memeber constraint's toString() or
+     * failureDescription() such that it reflects constraint's participation in
+     * this expression.
+     *
+     * The method may be overwritten in a subclass to apply default
+     * transformation in case the operand constraint does not provide its own
+     * custom strings via toStringInContext() or failureDescriptionInContext().
+     *
+     * @param string $string the string to be transformed
+     */
+    protected function transformString(string $string): string
+    {
+        return $string;
+    }
+
+    /**
+     * Provides access to $this->constraint for subclasses.
+     */
+    final protected function constraint(): Constraint
+    {
+        return $this->constraint;
+    }
+
+    /**
+     * Returns true if the $constraint needs to be wrapped with parentheses.
+     */
+    protected function constraintNeedsParentheses(Constraint $constraint): bool
+    {
+        $constraint = $constraint->reduce();
+
+        return $constraint instanceof self || parent::constraintNeedsParentheses($constraint);
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/Constraint/String/IsJson.php b/vendor/phpunit/phpunit/src/Framework/Constraint/String/IsJson.php
new file mode 100644
index 0000000000000000000000000000000000000000..97b294617f43db71b823f06563ca1f3f67b412f2
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/Constraint/String/IsJson.php
@@ -0,0 +1,77 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework\Constraint;
+
+use function json_decode;
+use function json_last_error;
+use function sprintf;
+
+/**
+ * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+ */
+final class IsJson extends Constraint
+{
+    /**
+     * Returns a string representation of the constraint.
+     */
+    public function toString(): string
+    {
+        return 'is valid JSON';
+    }
+
+    /**
+     * Evaluates the constraint for parameter $other. Returns true if the
+     * constraint is met, false otherwise.
+     *
+     * @param mixed $other value or object to evaluate
+     */
+    protected function matches($other): bool
+    {
+        if ($other === '') {
+            return false;
+        }
+
+        json_decode($other);
+
+        if (json_last_error()) {
+            return false;
+        }
+
+        return true;
+    }
+
+    /**
+     * Returns the description of the failure.
+     *
+     * The beginning of failure messages is "Failed asserting that" in most
+     * cases. This method should return the second part of that sentence.
+     *
+     * @param mixed $other evaluated value or object
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     */
+    protected function failureDescription($other): string
+    {
+        if ($other === '') {
+            return 'an empty string is valid JSON';
+        }
+
+        json_decode($other);
+        $error = (string) JsonMatchesErrorMessageProvider::determineJsonError(
+            (string) json_last_error()
+        );
+
+        return sprintf(
+            '%s is valid JSON (%s)',
+            $this->exporter()->shortenedExport($other),
+            $error
+        );
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/Constraint/String/RegularExpression.php b/vendor/phpunit/phpunit/src/Framework/Constraint/String/RegularExpression.php
new file mode 100644
index 0000000000000000000000000000000000000000..8e609e7958f0d50fac00f181cc4cea9c40cf8a14
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/Constraint/String/RegularExpression.php
@@ -0,0 +1,51 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework\Constraint;
+
+use function preg_match;
+use function sprintf;
+
+/**
+ * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+ */
+class RegularExpression extends Constraint
+{
+    /**
+     * @var string
+     */
+    private $pattern;
+
+    public function __construct(string $pattern)
+    {
+        $this->pattern = $pattern;
+    }
+
+    /**
+     * Returns a string representation of the constraint.
+     */
+    public function toString(): string
+    {
+        return sprintf(
+            'matches PCRE pattern "%s"',
+            $this->pattern
+        );
+    }
+
+    /**
+     * Evaluates the constraint for parameter $other. Returns true if the
+     * constraint is met, false otherwise.
+     *
+     * @param mixed $other value or object to evaluate
+     */
+    protected function matches($other): bool
+    {
+        return preg_match($this->pattern, $other) > 0;
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/Constraint/String/StringContains.php b/vendor/phpunit/phpunit/src/Framework/Constraint/String/StringContains.php
new file mode 100644
index 0000000000000000000000000000000000000000..6279f37ba4fb1b8bd333b703b3dd0da826d886ec
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/Constraint/String/StringContains.php
@@ -0,0 +1,85 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework\Constraint;
+
+use function mb_stripos;
+use function mb_strtolower;
+use function sprintf;
+use function strpos;
+
+/**
+ * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+ */
+final class StringContains extends Constraint
+{
+    /**
+     * @var string
+     */
+    private $string;
+
+    /**
+     * @var bool
+     */
+    private $ignoreCase;
+
+    public function __construct(string $string, bool $ignoreCase = false)
+    {
+        $this->string     = $string;
+        $this->ignoreCase = $ignoreCase;
+    }
+
+    /**
+     * Returns a string representation of the constraint.
+     */
+    public function toString(): string
+    {
+        if ($this->ignoreCase) {
+            $string = mb_strtolower($this->string, 'UTF-8');
+        } else {
+            $string = $this->string;
+        }
+
+        return sprintf(
+            'contains "%s"',
+            $string
+        );
+    }
+
+    /**
+     * Evaluates the constraint for parameter $other. Returns true if the
+     * constraint is met, false otherwise.
+     *
+     * @param mixed $other value or object to evaluate
+     */
+    protected function matches($other): bool
+    {
+        if ('' === $this->string) {
+            return true;
+        }
+
+        if ($this->ignoreCase) {
+            /*
+             * We must use the multi byte safe version so we can accurately compare non latin upper characters with
+             * their lowercase equivalents.
+             */
+            return mb_stripos($other, $this->string, 0, 'UTF-8') !== false;
+        }
+
+        /*
+         * Use the non multi byte safe functions to see if the string is contained in $other.
+         *
+         * This function is very fast and we don't care about the character position in the string.
+         *
+         * Additionally, we want this method to be binary safe so we can check if some binary data is in other binary
+         * data.
+         */
+        return strpos($other, $this->string) !== false;
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/Constraint/String/StringEndsWith.php b/vendor/phpunit/phpunit/src/Framework/Constraint/String/StringEndsWith.php
new file mode 100644
index 0000000000000000000000000000000000000000..bb4ce23be56b7bc89a1df9545c14d7d22510c8df
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/Constraint/String/StringEndsWith.php
@@ -0,0 +1,48 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework\Constraint;
+
+use function strlen;
+use function substr;
+
+/**
+ * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+ */
+final class StringEndsWith extends Constraint
+{
+    /**
+     * @var string
+     */
+    private $suffix;
+
+    public function __construct(string $suffix)
+    {
+        $this->suffix = $suffix;
+    }
+
+    /**
+     * Returns a string representation of the constraint.
+     */
+    public function toString(): string
+    {
+        return 'ends with "' . $this->suffix . '"';
+    }
+
+    /**
+     * Evaluates the constraint for parameter $other. Returns true if the
+     * constraint is met, false otherwise.
+     *
+     * @param mixed $other value or object to evaluate
+     */
+    protected function matches($other): bool
+    {
+        return substr($other, 0 - strlen($this->suffix)) === $this->suffix;
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/Constraint/String/StringMatchesFormatDescription.php b/vendor/phpunit/phpunit/src/Framework/Constraint/String/StringMatchesFormatDescription.php
new file mode 100644
index 0000000000000000000000000000000000000000..c4f7324ec52ae70580562177c65931ac7cf877e5
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/Constraint/String/StringMatchesFormatDescription.php
@@ -0,0 +1,109 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework\Constraint;
+
+use const DIRECTORY_SEPARATOR;
+use function explode;
+use function implode;
+use function preg_match;
+use function preg_quote;
+use function preg_replace;
+use function strtr;
+use SebastianBergmann\Diff\Differ;
+use SebastianBergmann\Diff\Output\UnifiedDiffOutputBuilder;
+
+/**
+ * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+ */
+final class StringMatchesFormatDescription extends RegularExpression
+{
+    /**
+     * @var string
+     */
+    private $string;
+
+    public function __construct(string $string)
+    {
+        parent::__construct(
+            $this->createPatternFromFormat(
+                $this->convertNewlines($string)
+            )
+        );
+
+        $this->string = $string;
+    }
+
+    /**
+     * Evaluates the constraint for parameter $other. Returns true if the
+     * constraint is met, false otherwise.
+     *
+     * @param mixed $other value or object to evaluate
+     */
+    protected function matches($other): bool
+    {
+        return parent::matches(
+            $this->convertNewlines($other)
+        );
+    }
+
+    protected function failureDescription($other): string
+    {
+        return 'string matches format description';
+    }
+
+    protected function additionalFailureDescription($other): string
+    {
+        $from = explode("\n", $this->string);
+        $to   = explode("\n", $this->convertNewlines($other));
+
+        foreach ($from as $index => $line) {
+            if (isset($to[$index]) && $line !== $to[$index]) {
+                $line = $this->createPatternFromFormat($line);
+
+                if (preg_match($line, $to[$index]) > 0) {
+                    $from[$index] = $to[$index];
+                }
+            }
+        }
+
+        $this->string = implode("\n", $from);
+        $other        = implode("\n", $to);
+
+        return (new Differ(new UnifiedDiffOutputBuilder("--- Expected\n+++ Actual\n")))->diff($this->string, $other);
+    }
+
+    private function createPatternFromFormat(string $string): string
+    {
+        $string = strtr(
+            preg_quote($string, '/'),
+            [
+                '%%' => '%',
+                '%e' => '\\' . DIRECTORY_SEPARATOR,
+                '%s' => '[^\r\n]+',
+                '%S' => '[^\r\n]*',
+                '%a' => '.+',
+                '%A' => '.*',
+                '%w' => '\s*',
+                '%i' => '[+-]?\d+',
+                '%d' => '\d+',
+                '%x' => '[0-9a-fA-F]+',
+                '%f' => '[+-]?\.?\d+\.?\d*(?:[Ee][+-]?\d+)?',
+                '%c' => '.',
+            ]
+        );
+
+        return '/^' . $string . '$/s';
+    }
+
+    private function convertNewlines(string $text): string
+    {
+        return preg_replace('/\r\n/', "\n", $text);
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/Constraint/String/StringStartsWith.php b/vendor/phpunit/phpunit/src/Framework/Constraint/String/StringStartsWith.php
new file mode 100644
index 0000000000000000000000000000000000000000..089545c122736086ea3f110a6d30104f45375d3d
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/Constraint/String/StringStartsWith.php
@@ -0,0 +1,53 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework\Constraint;
+
+use function strlen;
+use function strpos;
+use PHPUnit\Framework\InvalidArgumentException;
+
+/**
+ * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+ */
+final class StringStartsWith extends Constraint
+{
+    /**
+     * @var string
+     */
+    private $prefix;
+
+    public function __construct(string $prefix)
+    {
+        if (strlen($prefix) === 0) {
+            throw InvalidArgumentException::create(1, 'non-empty string');
+        }
+
+        $this->prefix = $prefix;
+    }
+
+    /**
+     * Returns a string representation of the constraint.
+     */
+    public function toString(): string
+    {
+        return 'starts with "' . $this->prefix . '"';
+    }
+
+    /**
+     * Evaluates the constraint for parameter $other. Returns true if the
+     * constraint is met, false otherwise.
+     *
+     * @param mixed $other value or object to evaluate
+     */
+    protected function matches($other): bool
+    {
+        return strpos((string) $other, $this->prefix) === 0;
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/Constraint/Traversable/ArrayHasKey.php b/vendor/phpunit/phpunit/src/Framework/Constraint/Traversable/ArrayHasKey.php
new file mode 100644
index 0000000000000000000000000000000000000000..44cada3a7dd0fccfa504fc88344854d7c60f1843
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/Constraint/Traversable/ArrayHasKey.php
@@ -0,0 +1,77 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework\Constraint;
+
+use function array_key_exists;
+use function is_array;
+use ArrayAccess;
+
+/**
+ * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+ */
+final class ArrayHasKey extends Constraint
+{
+    /**
+     * @var int|string
+     */
+    private $key;
+
+    /**
+     * @param int|string $key
+     */
+    public function __construct($key)
+    {
+        $this->key = $key;
+    }
+
+    /**
+     * Returns a string representation of the constraint.
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     */
+    public function toString(): string
+    {
+        return 'has the key ' . $this->exporter()->export($this->key);
+    }
+
+    /**
+     * Evaluates the constraint for parameter $other. Returns true if the
+     * constraint is met, false otherwise.
+     *
+     * @param mixed $other value or object to evaluate
+     */
+    protected function matches($other): bool
+    {
+        if (is_array($other)) {
+            return array_key_exists($this->key, $other);
+        }
+
+        if ($other instanceof ArrayAccess) {
+            return $other->offsetExists($this->key);
+        }
+
+        return false;
+    }
+
+    /**
+     * Returns the description of the failure.
+     *
+     * The beginning of failure messages is "Failed asserting that" in most
+     * cases. This method should return the second part of that sentence.
+     *
+     * @param mixed $other evaluated value or object
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     */
+    protected function failureDescription($other): string
+    {
+        return 'an array ' . $this->toString();
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/Constraint/Traversable/TraversableContains.php b/vendor/phpunit/phpunit/src/Framework/Constraint/Traversable/TraversableContains.php
new file mode 100644
index 0000000000000000000000000000000000000000..39660a9857d3244b9512b1327cc1c53c7c900079
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/Constraint/Traversable/TraversableContains.php
@@ -0,0 +1,63 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework\Constraint;
+
+use function is_array;
+use function sprintf;
+
+/**
+ * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+ */
+abstract class TraversableContains extends Constraint
+{
+    /**
+     * @var mixed
+     */
+    private $value;
+
+    public function __construct($value)
+    {
+        $this->value = $value;
+    }
+
+    /**
+     * Returns a string representation of the constraint.
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     */
+    public function toString(): string
+    {
+        return 'contains ' . $this->exporter()->export($this->value);
+    }
+
+    /**
+     * Returns the description of the failure.
+     *
+     * The beginning of failure messages is "Failed asserting that" in most
+     * cases. This method should return the second part of that sentence.
+     *
+     * @param mixed $other evaluated value or object
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     */
+    protected function failureDescription($other): string
+    {
+        return sprintf(
+            '%s %s',
+            is_array($other) ? 'an array' : 'a traversable',
+            $this->toString()
+        );
+    }
+
+    protected function value()
+    {
+        return $this->value;
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/Constraint/Traversable/TraversableContainsEqual.php b/vendor/phpunit/phpunit/src/Framework/Constraint/Traversable/TraversableContainsEqual.php
new file mode 100644
index 0000000000000000000000000000000000000000..c315e709ae37725bdbbf2c40c08c388b7066530c
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/Constraint/Traversable/TraversableContainsEqual.php
@@ -0,0 +1,40 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework\Constraint;
+
+use SplObjectStorage;
+
+/**
+ * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+ */
+final class TraversableContainsEqual extends TraversableContains
+{
+    /**
+     * Evaluates the constraint for parameter $other. Returns true if the
+     * constraint is met, false otherwise.
+     *
+     * @param mixed $other value or object to evaluate
+     */
+    protected function matches($other): bool
+    {
+        if ($other instanceof SplObjectStorage) {
+            return $other->contains($this->value());
+        }
+
+        foreach ($other as $element) {
+            /* @noinspection TypeUnsafeComparisonInspection */
+            if ($this->value() == $element) {
+                return true;
+            }
+        }
+
+        return false;
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/Constraint/Traversable/TraversableContainsIdentical.php b/vendor/phpunit/phpunit/src/Framework/Constraint/Traversable/TraversableContainsIdentical.php
new file mode 100644
index 0000000000000000000000000000000000000000..a3437dbc9df90ef4a02a94f4872cb382cf2146bd
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/Constraint/Traversable/TraversableContainsIdentical.php
@@ -0,0 +1,39 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework\Constraint;
+
+use SplObjectStorage;
+
+/**
+ * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+ */
+final class TraversableContainsIdentical extends TraversableContains
+{
+    /**
+     * Evaluates the constraint for parameter $other. Returns true if the
+     * constraint is met, false otherwise.
+     *
+     * @param mixed $other value or object to evaluate
+     */
+    protected function matches($other): bool
+    {
+        if ($other instanceof SplObjectStorage) {
+            return $other->contains($this->value());
+        }
+
+        foreach ($other as $element) {
+            if ($this->value() === $element) {
+                return true;
+            }
+        }
+
+        return false;
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/Constraint/Traversable/TraversableContainsOnly.php b/vendor/phpunit/phpunit/src/Framework/Constraint/Traversable/TraversableContainsOnly.php
new file mode 100644
index 0000000000000000000000000000000000000000..cf4a46b4221ebd991c15d6061b0d5a9fe0fb6ea9
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/Constraint/Traversable/TraversableContainsOnly.php
@@ -0,0 +1,91 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework\Constraint;
+
+use PHPUnit\Framework\ExpectationFailedException;
+use Traversable;
+
+/**
+ * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+ */
+final class TraversableContainsOnly extends Constraint
+{
+    /**
+     * @var Constraint
+     */
+    private $constraint;
+
+    /**
+     * @var string
+     */
+    private $type;
+
+    /**
+     * @throws \PHPUnit\Framework\Exception
+     */
+    public function __construct(string $type, bool $isNativeType = true)
+    {
+        if ($isNativeType) {
+            $this->constraint = new IsType($type);
+        } else {
+            $this->constraint = new IsInstanceOf(
+                $type
+            );
+        }
+
+        $this->type = $type;
+    }
+
+    /**
+     * Evaluates the constraint for parameter $other.
+     *
+     * If $returnResult is set to false (the default), an exception is thrown
+     * in case of a failure. null is returned otherwise.
+     *
+     * If $returnResult is true, the result of the evaluation is returned as
+     * a boolean value instead: true in case of success, false in case of a
+     * failure.
+     *
+     * @param mixed|Traversable $other
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws ExpectationFailedException
+     */
+    public function evaluate($other, string $description = '', bool $returnResult = false): ?bool
+    {
+        $success = true;
+
+        foreach ($other as $item) {
+            if (!$this->constraint->evaluate($item, '', true)) {
+                $success = false;
+
+                break;
+            }
+        }
+
+        if ($returnResult) {
+            return $success;
+        }
+
+        if (!$success) {
+            $this->fail($other, $description);
+        }
+
+        return null;
+    }
+
+    /**
+     * Returns a string representation of the constraint.
+     */
+    public function toString(): string
+    {
+        return 'contains only values of type "' . $this->type . '"';
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/Constraint/Type/IsInstanceOf.php b/vendor/phpunit/phpunit/src/Framework/Constraint/Type/IsInstanceOf.php
new file mode 100644
index 0000000000000000000000000000000000000000..f0fa02b99961f48c057b3b1bfbda972dda47fbdc
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/Constraint/Type/IsInstanceOf.php
@@ -0,0 +1,87 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework\Constraint;
+
+use function sprintf;
+use ReflectionClass;
+use ReflectionException;
+
+/**
+ * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+ */
+final class IsInstanceOf extends Constraint
+{
+    /**
+     * @var string
+     */
+    private $className;
+
+    public function __construct(string $className)
+    {
+        $this->className = $className;
+    }
+
+    /**
+     * Returns a string representation of the constraint.
+     */
+    public function toString(): string
+    {
+        return sprintf(
+            'is instance of %s "%s"',
+            $this->getType(),
+            $this->className
+        );
+    }
+
+    /**
+     * Evaluates the constraint for parameter $other. Returns true if the
+     * constraint is met, false otherwise.
+     *
+     * @param mixed $other value or object to evaluate
+     */
+    protected function matches($other): bool
+    {
+        return $other instanceof $this->className;
+    }
+
+    /**
+     * Returns the description of the failure.
+     *
+     * The beginning of failure messages is "Failed asserting that" in most
+     * cases. This method should return the second part of that sentence.
+     *
+     * @param mixed $other evaluated value or object
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     */
+    protected function failureDescription($other): string
+    {
+        return sprintf(
+            '%s is an instance of %s "%s"',
+            $this->exporter()->shortenedExport($other),
+            $this->getType(),
+            $this->className
+        );
+    }
+
+    private function getType(): string
+    {
+        try {
+            $reflection = new ReflectionClass($this->className);
+
+            if ($reflection->isInterface()) {
+                return 'interface';
+            }
+        } catch (ReflectionException $e) {
+        }
+
+        return 'class';
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/Constraint/Type/IsNull.php b/vendor/phpunit/phpunit/src/Framework/Constraint/Type/IsNull.php
new file mode 100644
index 0000000000000000000000000000000000000000..b9fcdd7a7b2fdfb741a941250b7c4375ca62deff
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/Constraint/Type/IsNull.php
@@ -0,0 +1,35 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework\Constraint;
+
+/**
+ * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+ */
+final class IsNull extends Constraint
+{
+    /**
+     * Returns a string representation of the constraint.
+     */
+    public function toString(): string
+    {
+        return 'is null';
+    }
+
+    /**
+     * Evaluates the constraint for parameter $other. Returns true if the
+     * constraint is met, false otherwise.
+     *
+     * @param mixed $other value or object to evaluate
+     */
+    protected function matches($other): bool
+    {
+        return $other === null;
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/Constraint/Type/IsType.php b/vendor/phpunit/phpunit/src/Framework/Constraint/Type/IsType.php
new file mode 100644
index 0000000000000000000000000000000000000000..5bc691d746be773bc74ff13bfb734f91c05a136e
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/Constraint/Type/IsType.php
@@ -0,0 +1,210 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework\Constraint;
+
+use function gettype;
+use function is_array;
+use function is_bool;
+use function is_callable;
+use function is_float;
+use function is_int;
+use function is_iterable;
+use function is_numeric;
+use function is_object;
+use function is_scalar;
+use function is_string;
+use function sprintf;
+
+/**
+ * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+ */
+final class IsType extends Constraint
+{
+    /**
+     * @var string
+     */
+    public const TYPE_ARRAY = 'array';
+
+    /**
+     * @var string
+     */
+    public const TYPE_BOOL = 'bool';
+
+    /**
+     * @var string
+     */
+    public const TYPE_FLOAT = 'float';
+
+    /**
+     * @var string
+     */
+    public const TYPE_INT = 'int';
+
+    /**
+     * @var string
+     */
+    public const TYPE_NULL = 'null';
+
+    /**
+     * @var string
+     */
+    public const TYPE_NUMERIC = 'numeric';
+
+    /**
+     * @var string
+     */
+    public const TYPE_OBJECT = 'object';
+
+    /**
+     * @var string
+     */
+    public const TYPE_RESOURCE = 'resource';
+
+    /**
+     * @var string
+     */
+    public const TYPE_CLOSED_RESOURCE = 'resource (closed)';
+
+    /**
+     * @var string
+     */
+    public const TYPE_STRING = 'string';
+
+    /**
+     * @var string
+     */
+    public const TYPE_SCALAR = 'scalar';
+
+    /**
+     * @var string
+     */
+    public const TYPE_CALLABLE = 'callable';
+
+    /**
+     * @var string
+     */
+    public const TYPE_ITERABLE = 'iterable';
+
+    /**
+     * @var array<string,bool>
+     */
+    private const KNOWN_TYPES = [
+        'array'             => true,
+        'boolean'           => true,
+        'bool'              => true,
+        'double'            => true,
+        'float'             => true,
+        'integer'           => true,
+        'int'               => true,
+        'null'              => true,
+        'numeric'           => true,
+        'object'            => true,
+        'real'              => true,
+        'resource'          => true,
+        'resource (closed)' => true,
+        'string'            => true,
+        'scalar'            => true,
+        'callable'          => true,
+        'iterable'          => true,
+    ];
+
+    /**
+     * @var string
+     */
+    private $type;
+
+    /**
+     * @throws \PHPUnit\Framework\Exception
+     */
+    public function __construct(string $type)
+    {
+        if (!isset(self::KNOWN_TYPES[$type])) {
+            throw new \PHPUnit\Framework\Exception(
+                sprintf(
+                    'Type specified for PHPUnit\Framework\Constraint\IsType <%s> ' .
+                    'is not a valid type.',
+                    $type
+                )
+            );
+        }
+
+        $this->type = $type;
+    }
+
+    /**
+     * Returns a string representation of the constraint.
+     */
+    public function toString(): string
+    {
+        return sprintf(
+            'is of type "%s"',
+            $this->type
+        );
+    }
+
+    /**
+     * Evaluates the constraint for parameter $other. Returns true if the
+     * constraint is met, false otherwise.
+     *
+     * @param mixed $other value or object to evaluate
+     */
+    protected function matches($other): bool
+    {
+        switch ($this->type) {
+            case 'numeric':
+                return is_numeric($other);
+
+            case 'integer':
+            case 'int':
+                return is_int($other);
+
+            case 'double':
+            case 'float':
+            case 'real':
+                return is_float($other);
+
+            case 'string':
+                return is_string($other);
+
+            case 'boolean':
+            case 'bool':
+                return is_bool($other);
+
+            case 'null':
+                return null === $other;
+
+            case 'array':
+                return is_array($other);
+
+            case 'object':
+                return is_object($other);
+
+            case 'resource':
+                $type = gettype($other);
+
+                return $type === 'resource' || $type === 'resource (closed)';
+
+            case 'resource (closed)':
+                return gettype($other) === 'resource (closed)';
+
+            case 'scalar':
+                return is_scalar($other);
+
+            case 'callable':
+                return is_callable($other);
+
+            case 'iterable':
+                return is_iterable($other);
+
+            default:
+                return false;
+        }
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/DataProviderTestSuite.php b/vendor/phpunit/phpunit/src/Framework/DataProviderTestSuite.php
new file mode 100644
index 0000000000000000000000000000000000000000..18b5499965e203d25eeb65ecdb40ff2ad8fc18d6
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/DataProviderTestSuite.php
@@ -0,0 +1,75 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework;
+
+use function explode;
+use PHPUnit\Util\Test as TestUtil;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class DataProviderTestSuite extends TestSuite
+{
+    /**
+     * @var list<ExecutionOrderDependency>
+     */
+    private $dependencies = [];
+
+    /**
+     * @param list<ExecutionOrderDependency> $dependencies
+     */
+    public function setDependencies(array $dependencies): void
+    {
+        $this->dependencies = $dependencies;
+
+        foreach ($this->tests as $test) {
+            if (!$test instanceof TestCase) {
+                // @codeCoverageIgnoreStart
+                continue;
+                // @codeCoverageIgnoreStart
+            }
+            $test->setDependencies($dependencies);
+        }
+    }
+
+    /**
+     * @return list<ExecutionOrderDependency>
+     */
+    public function provides(): array
+    {
+        if ($this->providedTests === null) {
+            $this->providedTests = [new ExecutionOrderDependency($this->getName())];
+        }
+
+        return $this->providedTests;
+    }
+
+    /**
+     * @return list<ExecutionOrderDependency>
+     */
+    public function requires(): array
+    {
+        // A DataProviderTestSuite does not have to traverse its child tests
+        // as these are inherited and cannot reference dataProvider rows directly
+        return $this->dependencies;
+    }
+
+    /**
+     * Returns the size of the each test created using the data provider(s).
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     */
+    public function getSize(): int
+    {
+        [$className, $methodName] = explode('::', $this->getName());
+
+        return TestUtil::getSize($className, $methodName);
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/Error/Deprecated.php b/vendor/phpunit/phpunit/src/Framework/Error/Deprecated.php
new file mode 100644
index 0000000000000000000000000000000000000000..db62195f8da41a59c6c44096ff86bcfb47fdf2a6
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/Error/Deprecated.php
@@ -0,0 +1,17 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework\Error;
+
+/**
+ * @internal
+ */
+final class Deprecated extends Error
+{
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/Error/Error.php b/vendor/phpunit/phpunit/src/Framework/Error/Error.php
new file mode 100644
index 0000000000000000000000000000000000000000..2990b360e301de30f4d270408b0a871c053fe052
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/Error/Error.php
@@ -0,0 +1,26 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework\Error;
+
+use PHPUnit\Framework\Exception;
+
+/**
+ * @internal
+ */
+class Error extends Exception
+{
+    public function __construct(string $message, int $code, string $file, int $line, \Exception $previous = null)
+    {
+        parent::__construct($message, $code, $previous);
+
+        $this->file = $file;
+        $this->line = $line;
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/Error/Notice.php b/vendor/phpunit/phpunit/src/Framework/Error/Notice.php
new file mode 100644
index 0000000000000000000000000000000000000000..54e5e31ea8d45ac9c7221d23d64a53c52333faad
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/Error/Notice.php
@@ -0,0 +1,17 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework\Error;
+
+/**
+ * @internal
+ */
+final class Notice extends Error
+{
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/Error/Warning.php b/vendor/phpunit/phpunit/src/Framework/Error/Warning.php
new file mode 100644
index 0000000000000000000000000000000000000000..0c0c0064f7daf1f47eccb46ef0266144bde22d38
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/Error/Warning.php
@@ -0,0 +1,17 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework\Error;
+
+/**
+ * @internal
+ */
+final class Warning extends Error
+{
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/ErrorTestCase.php b/vendor/phpunit/phpunit/src/Framework/ErrorTestCase.php
new file mode 100644
index 0000000000000000000000000000000000000000..841247d720d449b071502cce1b6190b11aedb3a1
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/ErrorTestCase.php
@@ -0,0 +1,66 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class ErrorTestCase extends TestCase
+{
+    /**
+     * @var bool
+     */
+    protected $backupGlobals = false;
+
+    /**
+     * @var bool
+     */
+    protected $backupStaticAttributes = false;
+
+    /**
+     * @var bool
+     */
+    protected $runTestInSeparateProcess = false;
+
+    /**
+     * @var string
+     */
+    private $message;
+
+    public function __construct(string $message = '')
+    {
+        $this->message = $message;
+
+        parent::__construct('Error');
+    }
+
+    public function getMessage(): string
+    {
+        return $this->message;
+    }
+
+    /**
+     * Returns a string representation of the test case.
+     */
+    public function toString(): string
+    {
+        return 'Error';
+    }
+
+    /**
+     * @throws Exception
+     *
+     * @psalm-return never-return
+     */
+    protected function runTest(): void
+    {
+        throw new Error($this->message);
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/Exception/ActualValueIsNotAnObjectException.php b/vendor/phpunit/phpunit/src/Framework/Exception/ActualValueIsNotAnObjectException.php
new file mode 100644
index 0000000000000000000000000000000000000000..adae2829439b7adecda8933ae1792e91994daf3f
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/Exception/ActualValueIsNotAnObjectException.php
@@ -0,0 +1,32 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework;
+
+use const PHP_EOL;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class ActualValueIsNotAnObjectException extends Exception
+{
+    public function __construct()
+    {
+        parent::__construct(
+            'Actual value is not an object',
+            0,
+            null
+        );
+    }
+
+    public function __toString(): string
+    {
+        return $this->getMessage() . PHP_EOL;
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/Exception/AssertionFailedError.php b/vendor/phpunit/phpunit/src/Framework/Exception/AssertionFailedError.php
new file mode 100644
index 0000000000000000000000000000000000000000..0ba25286f6ca39cbaf03676d19dc03b7d877e66b
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/Exception/AssertionFailedError.php
@@ -0,0 +1,24 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+class AssertionFailedError extends Exception implements SelfDescribing
+{
+    /**
+     * Wrapper for getMessage() which is declared as final.
+     */
+    public function toString(): string
+    {
+        return $this->getMessage();
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/Exception/CodeCoverageException.php b/vendor/phpunit/phpunit/src/Framework/Exception/CodeCoverageException.php
new file mode 100644
index 0000000000000000000000000000000000000000..36b072313010b8b8d51c45eba153675964faa832
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/Exception/CodeCoverageException.php
@@ -0,0 +1,17 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+class CodeCoverageException extends Exception
+{
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/Exception/ComparisonMethodDoesNotAcceptParameterTypeException.php b/vendor/phpunit/phpunit/src/Framework/Exception/ComparisonMethodDoesNotAcceptParameterTypeException.php
new file mode 100644
index 0000000000000000000000000000000000000000..ebd68f34c8e15bec48e15d4c26fc5d98b0c4f473
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/Exception/ComparisonMethodDoesNotAcceptParameterTypeException.php
@@ -0,0 +1,38 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework;
+
+use const PHP_EOL;
+use function sprintf;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class ComparisonMethodDoesNotAcceptParameterTypeException extends Exception
+{
+    public function __construct(string $className, string $methodName, string $type)
+    {
+        parent::__construct(
+            sprintf(
+                '%s is not an accepted argument type for comparison method %s::%s().',
+                $type,
+                $className,
+                $methodName
+            ),
+            0,
+            null
+        );
+    }
+
+    public function __toString(): string
+    {
+        return $this->getMessage() . PHP_EOL;
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/Exception/ComparisonMethodDoesNotDeclareBoolReturnTypeException.php b/vendor/phpunit/phpunit/src/Framework/Exception/ComparisonMethodDoesNotDeclareBoolReturnTypeException.php
new file mode 100644
index 0000000000000000000000000000000000000000..20189cde4de0daeffbc8f9b37a55b5955175c7db
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/Exception/ComparisonMethodDoesNotDeclareBoolReturnTypeException.php
@@ -0,0 +1,37 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework;
+
+use const PHP_EOL;
+use function sprintf;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class ComparisonMethodDoesNotDeclareBoolReturnTypeException extends Exception
+{
+    public function __construct(string $className, string $methodName)
+    {
+        parent::__construct(
+            sprintf(
+                'Comparison method %s::%s() does not declare bool return type.',
+                $className,
+                $methodName
+            ),
+            0,
+            null
+        );
+    }
+
+    public function __toString(): string
+    {
+        return $this->getMessage() . PHP_EOL;
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/Exception/ComparisonMethodDoesNotDeclareExactlyOneParameterException.php b/vendor/phpunit/phpunit/src/Framework/Exception/ComparisonMethodDoesNotDeclareExactlyOneParameterException.php
new file mode 100644
index 0000000000000000000000000000000000000000..bd09d87ccf18e8bde74ad69d11a011b66219e7c0
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/Exception/ComparisonMethodDoesNotDeclareExactlyOneParameterException.php
@@ -0,0 +1,37 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework;
+
+use const PHP_EOL;
+use function sprintf;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class ComparisonMethodDoesNotDeclareExactlyOneParameterException extends Exception
+{
+    public function __construct(string $className, string $methodName)
+    {
+        parent::__construct(
+            sprintf(
+                'Comparison method %s::%s() does not declare exactly one parameter.',
+                $className,
+                $methodName
+            ),
+            0,
+            null
+        );
+    }
+
+    public function __toString(): string
+    {
+        return $this->getMessage() . PHP_EOL;
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/Exception/ComparisonMethodDoesNotDeclareParameterTypeException.php b/vendor/phpunit/phpunit/src/Framework/Exception/ComparisonMethodDoesNotDeclareParameterTypeException.php
new file mode 100644
index 0000000000000000000000000000000000000000..9bbb112eaf58659bcaafccbb1d155a30b5d34a56
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/Exception/ComparisonMethodDoesNotDeclareParameterTypeException.php
@@ -0,0 +1,37 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework;
+
+use const PHP_EOL;
+use function sprintf;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class ComparisonMethodDoesNotDeclareParameterTypeException extends Exception
+{
+    public function __construct(string $className, string $methodName)
+    {
+        parent::__construct(
+            sprintf(
+                'Parameter of comparison method %s::%s() does not have a declared type.',
+                $className,
+                $methodName
+            ),
+            0,
+            null
+        );
+    }
+
+    public function __toString(): string
+    {
+        return $this->getMessage() . PHP_EOL;
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/Exception/ComparisonMethodDoesNotExistException.php b/vendor/phpunit/phpunit/src/Framework/Exception/ComparisonMethodDoesNotExistException.php
new file mode 100644
index 0000000000000000000000000000000000000000..ad0e2d08895fba0570a7fee6ec7335359bd4c531
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/Exception/ComparisonMethodDoesNotExistException.php
@@ -0,0 +1,37 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework;
+
+use const PHP_EOL;
+use function sprintf;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class ComparisonMethodDoesNotExistException extends Exception
+{
+    public function __construct(string $className, string $methodName)
+    {
+        parent::__construct(
+            sprintf(
+                'Comparison method %s::%s() does not exist.',
+                $className,
+                $methodName
+            ),
+            0,
+            null
+        );
+    }
+
+    public function __toString(): string
+    {
+        return $this->getMessage() . PHP_EOL;
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/Exception/CoveredCodeNotExecutedException.php b/vendor/phpunit/phpunit/src/Framework/Exception/CoveredCodeNotExecutedException.php
new file mode 100644
index 0000000000000000000000000000000000000000..78f89bc39ee737ec1a3b47810537ae03fd6207ad
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/Exception/CoveredCodeNotExecutedException.php
@@ -0,0 +1,17 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class CoveredCodeNotExecutedException extends RiskyTestError
+{
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/Exception/Error.php b/vendor/phpunit/phpunit/src/Framework/Exception/Error.php
new file mode 100644
index 0000000000000000000000000000000000000000..d43e42186ac04aff257de2ed5e861e4c89d6b2f6
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/Exception/Error.php
@@ -0,0 +1,24 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class Error extends Exception implements SelfDescribing
+{
+    /**
+     * Wrapper for getMessage() which is declared as final.
+     */
+    public function toString(): string
+    {
+        return $this->getMessage();
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/Exception/Exception.php b/vendor/phpunit/phpunit/src/Framework/Exception/Exception.php
new file mode 100644
index 0000000000000000000000000000000000000000..0b21e6de3000f886bfd592546c6e179406a2b148
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/Exception/Exception.php
@@ -0,0 +1,81 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework;
+
+use function array_keys;
+use function get_object_vars;
+use PHPUnit\Util\Filter;
+use RuntimeException;
+use Throwable;
+
+/**
+ * Base class for all PHPUnit Framework exceptions.
+ *
+ * Ensures that exceptions thrown during a test run do not leave stray
+ * references behind.
+ *
+ * Every Exception contains a stack trace. Each stack frame contains the 'args'
+ * of the called function. The function arguments can contain references to
+ * instantiated objects. The references prevent the objects from being
+ * destructed (until test results are eventually printed), so memory cannot be
+ * freed up.
+ *
+ * With enabled process isolation, test results are serialized in the child
+ * process and unserialized in the parent process. The stack trace of Exceptions
+ * may contain objects that cannot be serialized or unserialized (e.g., PDO
+ * connections). Unserializing user-space objects from the child process into
+ * the parent would break the intended encapsulation of process isolation.
+ *
+ * @see http://fabien.potencier.org/article/9/php-serialization-stack-traces-and-exceptions
+ *
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+class Exception extends RuntimeException implements \PHPUnit\Exception
+{
+    /**
+     * @var array
+     */
+    protected $serializableTrace;
+
+    public function __construct($message = '', $code = 0, Throwable $previous = null)
+    {
+        parent::__construct($message, $code, $previous);
+
+        $this->serializableTrace = $this->getTrace();
+
+        foreach (array_keys($this->serializableTrace) as $key) {
+            unset($this->serializableTrace[$key]['args']);
+        }
+    }
+
+    public function __toString(): string
+    {
+        $string = TestFailure::exceptionToString($this);
+
+        if ($trace = Filter::getFilteredStacktrace($this)) {
+            $string .= "\n" . $trace;
+        }
+
+        return $string;
+    }
+
+    public function __sleep(): array
+    {
+        return array_keys(get_object_vars($this));
+    }
+
+    /**
+     * Returns the serializable trace (without 'args').
+     */
+    public function getSerializableTrace(): array
+    {
+        return $this->serializableTrace;
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/Exception/ExpectationFailedException.php b/vendor/phpunit/phpunit/src/Framework/Exception/ExpectationFailedException.php
new file mode 100644
index 0000000000000000000000000000000000000000..b9a595a88c4f7dc01053c28e37171babf5f5a62c
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/Exception/ExpectationFailedException.php
@@ -0,0 +1,42 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework;
+
+use Exception;
+use SebastianBergmann\Comparator\ComparisonFailure;
+
+/**
+ * Exception for expectations which failed their check.
+ *
+ * The exception contains the error message and optionally a
+ * SebastianBergmann\Comparator\ComparisonFailure which is used to
+ * generate diff output of the failed expectations.
+ *
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class ExpectationFailedException extends AssertionFailedError
+{
+    /**
+     * @var ComparisonFailure
+     */
+    protected $comparisonFailure;
+
+    public function __construct(string $message, ComparisonFailure $comparisonFailure = null, Exception $previous = null)
+    {
+        $this->comparisonFailure = $comparisonFailure;
+
+        parent::__construct($message, 0, $previous);
+    }
+
+    public function getComparisonFailure(): ?ComparisonFailure
+    {
+        return $this->comparisonFailure;
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/Exception/IncompleteTestError.php b/vendor/phpunit/phpunit/src/Framework/Exception/IncompleteTestError.php
new file mode 100644
index 0000000000000000000000000000000000000000..65f9c8bc3435f6206b9e8cbda5c64915173cc271
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/Exception/IncompleteTestError.php
@@ -0,0 +1,17 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class IncompleteTestError extends AssertionFailedError implements IncompleteTest
+{
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/Exception/InvalidArgumentException.php b/vendor/phpunit/phpunit/src/Framework/Exception/InvalidArgumentException.php
new file mode 100644
index 0000000000000000000000000000000000000000..aec29f432a472eff8a578134a6191cada29f55c1
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/Exception/InvalidArgumentException.php
@@ -0,0 +1,42 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework;
+
+use function debug_backtrace;
+use function in_array;
+use function lcfirst;
+use function sprintf;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class InvalidArgumentException extends Exception
+{
+    public static function create(int $argument, string $type): self
+    {
+        $stack = debug_backtrace();
+
+        return new self(
+            sprintf(
+                'Argument #%d of %s::%s() must be %s %s',
+                $argument,
+                $stack[1]['class'],
+                $stack[1]['function'],
+                in_array(lcfirst($type)[0], ['a', 'e', 'i', 'o', 'u'], true) ? 'an' : 'a',
+                $type
+            )
+        );
+    }
+
+    private function __construct(string $message = '', int $code = 0, \Exception $previous = null)
+    {
+        parent::__construct($message, $code, $previous);
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/Exception/InvalidCoversTargetException.php b/vendor/phpunit/phpunit/src/Framework/Exception/InvalidCoversTargetException.php
new file mode 100644
index 0000000000000000000000000000000000000000..ebf2994a94e61fa2ce03555843349567d3a8c1de
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/Exception/InvalidCoversTargetException.php
@@ -0,0 +1,17 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class InvalidCoversTargetException extends CodeCoverageException
+{
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/Exception/InvalidDataProviderException.php b/vendor/phpunit/phpunit/src/Framework/Exception/InvalidDataProviderException.php
new file mode 100644
index 0000000000000000000000000000000000000000..7e2ef24c6375b37ba82bf9ea943580801932275f
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/Exception/InvalidDataProviderException.php
@@ -0,0 +1,17 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class InvalidDataProviderException extends Exception
+{
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/Exception/MissingCoversAnnotationException.php b/vendor/phpunit/phpunit/src/Framework/Exception/MissingCoversAnnotationException.php
new file mode 100644
index 0000000000000000000000000000000000000000..567a6c4c5818951ba1fba62beb8891f94e681c5a
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/Exception/MissingCoversAnnotationException.php
@@ -0,0 +1,17 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class MissingCoversAnnotationException extends RiskyTestError
+{
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/Exception/NoChildTestSuiteException.php b/vendor/phpunit/phpunit/src/Framework/Exception/NoChildTestSuiteException.php
new file mode 100644
index 0000000000000000000000000000000000000000..7ef4153b0f0c0a08a48b14bb535d479515a233ce
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/Exception/NoChildTestSuiteException.php
@@ -0,0 +1,17 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class NoChildTestSuiteException extends Exception
+{
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/Exception/OutputError.php b/vendor/phpunit/phpunit/src/Framework/Exception/OutputError.php
new file mode 100644
index 0000000000000000000000000000000000000000..1c8b37e5617028506ad404597bfd5970fc490a4f
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/Exception/OutputError.php
@@ -0,0 +1,17 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class OutputError extends AssertionFailedError
+{
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/Exception/PHPTAssertionFailedError.php b/vendor/phpunit/phpunit/src/Framework/Exception/PHPTAssertionFailedError.php
new file mode 100644
index 0000000000000000000000000000000000000000..17126139f906f16d2179d210eb8671a679b3c4d9
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/Exception/PHPTAssertionFailedError.php
@@ -0,0 +1,32 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class PHPTAssertionFailedError extends SyntheticError
+{
+    /**
+     * @var string
+     */
+    private $diff;
+
+    public function __construct(string $message, int $code, string $file, int $line, array $trace, string $diff)
+    {
+        parent::__construct($message, $code, $file, $line, $trace);
+        $this->diff = $diff;
+    }
+
+    public function getDiff(): string
+    {
+        return $this->diff;
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/Exception/RiskyTestError.php b/vendor/phpunit/phpunit/src/Framework/Exception/RiskyTestError.php
new file mode 100644
index 0000000000000000000000000000000000000000..a66552c0d6862fa15340482090faab7cd01b8155
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/Exception/RiskyTestError.php
@@ -0,0 +1,17 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+class RiskyTestError extends AssertionFailedError
+{
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/Exception/SkippedTestError.php b/vendor/phpunit/phpunit/src/Framework/Exception/SkippedTestError.php
new file mode 100644
index 0000000000000000000000000000000000000000..7d553dcf3f12b4d65fad9c3248cf160136e5aaf7
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/Exception/SkippedTestError.php
@@ -0,0 +1,17 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class SkippedTestError extends AssertionFailedError implements SkippedTest
+{
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/Exception/SkippedTestSuiteError.php b/vendor/phpunit/phpunit/src/Framework/Exception/SkippedTestSuiteError.php
new file mode 100644
index 0000000000000000000000000000000000000000..5448508a1ea1f209cfbc52446bd0750fc78c54e7
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/Exception/SkippedTestSuiteError.php
@@ -0,0 +1,17 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class SkippedTestSuiteError extends AssertionFailedError implements SkippedTest
+{
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/Exception/SyntheticError.php b/vendor/phpunit/phpunit/src/Framework/Exception/SyntheticError.php
new file mode 100644
index 0000000000000000000000000000000000000000..c3124ba0c74cc321955ef44bd056b7694c5247af
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/Exception/SyntheticError.php
@@ -0,0 +1,61 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+class SyntheticError extends AssertionFailedError
+{
+    /**
+     * The synthetic file.
+     *
+     * @var string
+     */
+    protected $syntheticFile = '';
+
+    /**
+     * The synthetic line number.
+     *
+     * @var int
+     */
+    protected $syntheticLine = 0;
+
+    /**
+     * The synthetic trace.
+     *
+     * @var array
+     */
+    protected $syntheticTrace = [];
+
+    public function __construct(string $message, int $code, string $file, int $line, array $trace)
+    {
+        parent::__construct($message, $code);
+
+        $this->syntheticFile  = $file;
+        $this->syntheticLine  = $line;
+        $this->syntheticTrace = $trace;
+    }
+
+    public function getSyntheticFile(): string
+    {
+        return $this->syntheticFile;
+    }
+
+    public function getSyntheticLine(): int
+    {
+        return $this->syntheticLine;
+    }
+
+    public function getSyntheticTrace(): array
+    {
+        return $this->syntheticTrace;
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/Exception/SyntheticSkippedError.php b/vendor/phpunit/phpunit/src/Framework/Exception/SyntheticSkippedError.php
new file mode 100644
index 0000000000000000000000000000000000000000..f6e155d7b9e35adfafe30e96b10f32ff1c17d215
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/Exception/SyntheticSkippedError.php
@@ -0,0 +1,17 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class SyntheticSkippedError extends SyntheticError implements SkippedTest
+{
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/Exception/UnintentionallyCoveredCodeError.php b/vendor/phpunit/phpunit/src/Framework/Exception/UnintentionallyCoveredCodeError.php
new file mode 100644
index 0000000000000000000000000000000000000000..fcd1d824964a0ca4381379f431cc672dfdeb1650
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/Exception/UnintentionallyCoveredCodeError.php
@@ -0,0 +1,17 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class UnintentionallyCoveredCodeError extends RiskyTestError
+{
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/Exception/Warning.php b/vendor/phpunit/phpunit/src/Framework/Exception/Warning.php
new file mode 100644
index 0000000000000000000000000000000000000000..35e94493cf057df6a5f73f59b5fca3617ab9b45f
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/Exception/Warning.php
@@ -0,0 +1,24 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class Warning extends Exception implements SelfDescribing
+{
+    /**
+     * Wrapper for getMessage() which is declared as final.
+     */
+    public function toString(): string
+    {
+        return $this->getMessage();
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/ExceptionWrapper.php b/vendor/phpunit/phpunit/src/Framework/ExceptionWrapper.php
new file mode 100644
index 0000000000000000000000000000000000000000..d1ff4abc6aea2e383cf9476a35c5cd0762218f39
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/ExceptionWrapper.php
@@ -0,0 +1,122 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework;
+
+use function array_keys;
+use function get_class;
+use function spl_object_hash;
+use PHPUnit\Util\Filter;
+use Throwable;
+
+/**
+ * Wraps Exceptions thrown by code under test.
+ *
+ * Re-instantiates Exceptions thrown by user-space code to retain their original
+ * class names, properties, and stack traces (but without arguments).
+ *
+ * Unlike PHPUnit\Framework\Exception, the complete stack of previous Exceptions
+ * is processed.
+ *
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class ExceptionWrapper extends Exception
+{
+    /**
+     * @var string
+     */
+    protected $className;
+
+    /**
+     * @var null|ExceptionWrapper
+     */
+    protected $previous;
+
+    public function __construct(Throwable $t)
+    {
+        // PDOException::getCode() is a string.
+        // @see https://php.net/manual/en/class.pdoexception.php#95812
+        parent::__construct($t->getMessage(), (int) $t->getCode());
+
+        $this->setOriginalException($t);
+    }
+
+    public function __toString(): string
+    {
+        $string = TestFailure::exceptionToString($this);
+
+        if ($trace = Filter::getFilteredStacktrace($this)) {
+            $string .= "\n" . $trace;
+        }
+
+        if ($this->previous) {
+            $string .= "\nCaused by\n" . $this->previous;
+        }
+
+        return $string;
+    }
+
+    public function getClassName(): string
+    {
+        return $this->className;
+    }
+
+    public function getPreviousWrapped(): ?self
+    {
+        return $this->previous;
+    }
+
+    public function setClassName(string $className): void
+    {
+        $this->className = $className;
+    }
+
+    public function setOriginalException(Throwable $t): void
+    {
+        $this->originalException($t);
+
+        $this->className = get_class($t);
+        $this->file      = $t->getFile();
+        $this->line      = $t->getLine();
+
+        $this->serializableTrace = $t->getTrace();
+
+        foreach (array_keys($this->serializableTrace) as $key) {
+            unset($this->serializableTrace[$key]['args']);
+        }
+
+        if ($t->getPrevious()) {
+            $this->previous = new self($t->getPrevious());
+        }
+    }
+
+    public function getOriginalException(): ?Throwable
+    {
+        return $this->originalException();
+    }
+
+    /**
+     * Method to contain static originalException to exclude it from stacktrace to prevent the stacktrace contents,
+     * which can be quite big, from being garbage-collected, thus blocking memory until shutdown.
+     *
+     * Approach works both for var_dump() and var_export() and print_r().
+     */
+    private function originalException(Throwable $exceptionToStore = null): ?Throwable
+    {
+        static $originalExceptions;
+
+        $instanceId = spl_object_hash($this);
+
+        if ($exceptionToStore) {
+            $originalExceptions[$instanceId] = $exceptionToStore;
+        }
+
+        return $originalExceptions[$instanceId] ?? null;
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/ExecutionOrderDependency.php b/vendor/phpunit/phpunit/src/Framework/ExecutionOrderDependency.php
new file mode 100644
index 0000000000000000000000000000000000000000..8ba5b242d6a6727e117dd89f6e726f6f12100293
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/ExecutionOrderDependency.php
@@ -0,0 +1,203 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework;
+
+use function array_filter;
+use function array_map;
+use function array_values;
+use function count;
+use function explode;
+use function in_array;
+use function strpos;
+use function trim;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class ExecutionOrderDependency
+{
+    /**
+     * @var string
+     */
+    private $className = '';
+
+    /**
+     * @var string
+     */
+    private $methodName = '';
+
+    /**
+     * @var bool
+     */
+    private $useShallowClone = false;
+
+    /**
+     * @var bool
+     */
+    private $useDeepClone = false;
+
+    public static function createFromDependsAnnotation(string $className, string $annotation): self
+    {
+        // Split clone option and target
+        $parts = explode(' ', trim($annotation), 2);
+
+        if (count($parts) === 1) {
+            $cloneOption = '';
+            $target      = $parts[0];
+        } else {
+            $cloneOption = $parts[0];
+            $target      = $parts[1];
+        }
+
+        // Prefix provided class for targets assumed to be in scope
+        if ($target !== '' && strpos($target, '::') === false) {
+            $target = $className . '::' . $target;
+        }
+
+        return new self($target, null, $cloneOption);
+    }
+
+    /**
+     * @psalm-param list<ExecutionOrderDependency> $dependencies
+     *
+     * @psalm-return list<ExecutionOrderDependency>
+     */
+    public static function filterInvalid(array $dependencies): array
+    {
+        return array_values(
+            array_filter(
+                $dependencies,
+                static function (self $d) {
+                    return $d->isValid();
+                }
+            )
+        );
+    }
+
+    /**
+     * @psalm-param list<ExecutionOrderDependency> $existing
+     * @psalm-param list<ExecutionOrderDependency> $additional
+     *
+     * @psalm-return list<ExecutionOrderDependency>
+     */
+    public static function mergeUnique(array $existing, array $additional): array
+    {
+        $existingTargets = array_map(
+            static function ($dependency) {
+                return $dependency->getTarget();
+            },
+            $existing
+        );
+
+        foreach ($additional as $dependency) {
+            if (in_array($dependency->getTarget(), $existingTargets, true)) {
+                continue;
+            }
+
+            $existingTargets[] = $dependency->getTarget();
+            $existing[]        = $dependency;
+        }
+
+        return $existing;
+    }
+
+    /**
+     * @psalm-param list<ExecutionOrderDependency> $left
+     * @psalm-param list<ExecutionOrderDependency> $right
+     *
+     * @psalm-return list<ExecutionOrderDependency>
+     */
+    public static function diff(array $left, array $right): array
+    {
+        if ($right === []) {
+            return $left;
+        }
+
+        if ($left === []) {
+            return [];
+        }
+
+        $diff         = [];
+        $rightTargets = array_map(
+            static function ($dependency) {
+                return $dependency->getTarget();
+            },
+            $right
+        );
+
+        foreach ($left as $dependency) {
+            if (in_array($dependency->getTarget(), $rightTargets, true)) {
+                continue;
+            }
+
+            $diff[] = $dependency;
+        }
+
+        return $diff;
+    }
+
+    public function __construct(string $classOrCallableName, ?string $methodName = null, ?string $option = null)
+    {
+        if ($classOrCallableName === '') {
+            return;
+        }
+
+        if (strpos($classOrCallableName, '::') !== false) {
+            [$this->className, $this->methodName] = explode('::', $classOrCallableName);
+        } else {
+            $this->className  = $classOrCallableName;
+            $this->methodName = !empty($methodName) ? $methodName : 'class';
+        }
+
+        if ($option === 'clone') {
+            $this->useDeepClone = true;
+        } elseif ($option === 'shallowClone') {
+            $this->useShallowClone = true;
+        }
+    }
+
+    public function __toString(): string
+    {
+        return $this->getTarget();
+    }
+
+    public function isValid(): bool
+    {
+        // Invalid dependencies can be declared and are skipped by the runner
+        return $this->className !== '' && $this->methodName !== '';
+    }
+
+    public function useShallowClone(): bool
+    {
+        return $this->useShallowClone;
+    }
+
+    public function useDeepClone(): bool
+    {
+        return $this->useDeepClone;
+    }
+
+    public function targetIsClass(): bool
+    {
+        return $this->methodName === 'class';
+    }
+
+    public function getTarget(): string
+    {
+        return $this->isValid()
+            ? $this->className . '::' . $this->methodName
+            : '';
+    }
+
+    public function getTargetClassName(): string
+    {
+        return $this->className;
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/IncompleteTest.php b/vendor/phpunit/phpunit/src/Framework/IncompleteTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..b77b1afff2c282cf96746a9aeff1c13bb796c623
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/IncompleteTest.php
@@ -0,0 +1,19 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework;
+
+use Throwable;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+interface IncompleteTest extends Throwable
+{
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/IncompleteTestCase.php b/vendor/phpunit/phpunit/src/Framework/IncompleteTestCase.php
new file mode 100644
index 0000000000000000000000000000000000000000..ee1e3e9fe035c582b25e353cb582d9a10e25dd91
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/IncompleteTestCase.php
@@ -0,0 +1,66 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class IncompleteTestCase extends TestCase
+{
+    /**
+     * @var bool
+     */
+    protected $backupGlobals = false;
+
+    /**
+     * @var bool
+     */
+    protected $backupStaticAttributes = false;
+
+    /**
+     * @var bool
+     */
+    protected $runTestInSeparateProcess = false;
+
+    /**
+     * @var string
+     */
+    private $message;
+
+    public function __construct(string $className, string $methodName, string $message = '')
+    {
+        parent::__construct($className . '::' . $methodName);
+
+        $this->message = $message;
+    }
+
+    public function getMessage(): string
+    {
+        return $this->message;
+    }
+
+    /**
+     * Returns a string representation of the test case.
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     */
+    public function toString(): string
+    {
+        return $this->getName();
+    }
+
+    /**
+     * @throws Exception
+     */
+    protected function runTest(): void
+    {
+        $this->markTestIncomplete($this->message);
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/InvalidParameterGroupException.php b/vendor/phpunit/phpunit/src/Framework/InvalidParameterGroupException.php
new file mode 100644
index 0000000000000000000000000000000000000000..feb9cc989f11623bfa4d16d707d6b32746efc083
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/InvalidParameterGroupException.php
@@ -0,0 +1,17 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class InvalidParameterGroupException extends Exception
+{
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/Api/Api.php b/vendor/phpunit/phpunit/src/Framework/MockObject/Api/Api.php
new file mode 100644
index 0000000000000000000000000000000000000000..e2f0a2802d6c7f97bcc732d7f3abd096449a5d15
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/MockObject/Api/Api.php
@@ -0,0 +1,97 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework\MockObject;
+
+use PHPUnit\Framework\MockObject\Builder\InvocationMocker as InvocationMockerBuilder;
+use PHPUnit\Framework\MockObject\Rule\InvocationOrder;
+
+/**
+ * @internal This trait is not covered by the backward compatibility promise for PHPUnit
+ */
+trait Api
+{
+    /**
+     * @var ConfigurableMethod[]
+     */
+    private static $__phpunit_configurableMethods;
+
+    /**
+     * @var object
+     */
+    private $__phpunit_originalObject;
+
+    /**
+     * @var bool
+     */
+    private $__phpunit_returnValueGeneration = true;
+
+    /**
+     * @var InvocationHandler
+     */
+    private $__phpunit_invocationMocker;
+
+    /** @noinspection MagicMethodsValidityInspection */
+    public static function __phpunit_initConfigurableMethods(ConfigurableMethod ...$configurableMethods): void
+    {
+        if (isset(static::$__phpunit_configurableMethods)) {
+            throw new ConfigurableMethodsAlreadyInitializedException(
+                'Configurable methods is already initialized and can not be reinitialized'
+            );
+        }
+
+        static::$__phpunit_configurableMethods = $configurableMethods;
+    }
+
+    /** @noinspection MagicMethodsValidityInspection */
+    public function __phpunit_setOriginalObject($originalObject): void
+    {
+        $this->__phpunit_originalObject = $originalObject;
+    }
+
+    /** @noinspection MagicMethodsValidityInspection */
+    public function __phpunit_setReturnValueGeneration(bool $returnValueGeneration): void
+    {
+        $this->__phpunit_returnValueGeneration = $returnValueGeneration;
+    }
+
+    /** @noinspection MagicMethodsValidityInspection */
+    public function __phpunit_getInvocationHandler(): InvocationHandler
+    {
+        if ($this->__phpunit_invocationMocker === null) {
+            $this->__phpunit_invocationMocker = new InvocationHandler(
+                static::$__phpunit_configurableMethods,
+                $this->__phpunit_returnValueGeneration
+            );
+        }
+
+        return $this->__phpunit_invocationMocker;
+    }
+
+    /** @noinspection MagicMethodsValidityInspection */
+    public function __phpunit_hasMatchers(): bool
+    {
+        return $this->__phpunit_getInvocationHandler()->hasMatchers();
+    }
+
+    /** @noinspection MagicMethodsValidityInspection */
+    public function __phpunit_verify(bool $unsetInvocationMocker = true): void
+    {
+        $this->__phpunit_getInvocationHandler()->verify();
+
+        if ($unsetInvocationMocker) {
+            $this->__phpunit_invocationMocker = null;
+        }
+    }
+
+    public function expects(InvocationOrder $matcher): InvocationMockerBuilder
+    {
+        return $this->__phpunit_getInvocationHandler()->expects($matcher);
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/Api/Method.php b/vendor/phpunit/phpunit/src/Framework/MockObject/Api/Method.php
new file mode 100644
index 0000000000000000000000000000000000000000..f6df7533c1fd6558f38ee994f82494f45a6ef899
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/MockObject/Api/Method.php
@@ -0,0 +1,30 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework\MockObject;
+
+use function call_user_func_array;
+use function func_get_args;
+use PHPUnit\Framework\MockObject\Rule\AnyInvokedCount;
+
+/**
+ * @internal This trait is not covered by the backward compatibility promise for PHPUnit
+ */
+trait Method
+{
+    public function method()
+    {
+        $expects = $this->expects(new AnyInvokedCount);
+
+        return call_user_func_array(
+            [$expects, 'method'],
+            func_get_args()
+        );
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/Api/MockedCloneMethod.php b/vendor/phpunit/phpunit/src/Framework/MockObject/Api/MockedCloneMethod.php
new file mode 100644
index 0000000000000000000000000000000000000000..91e35f937f16c068dcdbe120bfc2296607124f30
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/MockObject/Api/MockedCloneMethod.php
@@ -0,0 +1,21 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework\MockObject;
+
+/**
+ * @internal This trait is not covered by the backward compatibility promise for PHPUnit
+ */
+trait MockedCloneMethod
+{
+    public function __clone()
+    {
+        $this->__phpunit_invocationMocker = clone $this->__phpunit_getInvocationHandler();
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/Api/UnmockedCloneMethod.php b/vendor/phpunit/phpunit/src/Framework/MockObject/Api/UnmockedCloneMethod.php
new file mode 100644
index 0000000000000000000000000000000000000000..3f493d203d137e852a5c57981bfade8758cf7a24
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/MockObject/Api/UnmockedCloneMethod.php
@@ -0,0 +1,23 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework\MockObject;
+
+/**
+ * @internal This trait is not covered by the backward compatibility promise for PHPUnit
+ */
+trait UnmockedCloneMethod
+{
+    public function __clone()
+    {
+        $this->__phpunit_invocationMocker = clone $this->__phpunit_getInvocationHandler();
+
+        parent::__clone();
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/Builder/Identity.php b/vendor/phpunit/phpunit/src/Framework/MockObject/Builder/Identity.php
new file mode 100644
index 0000000000000000000000000000000000000000..a68bfadf9dcbed1581097f02a1328a607e359e53
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/MockObject/Builder/Identity.php
@@ -0,0 +1,25 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework\MockObject\Builder;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+interface Identity
+{
+    /**
+     * Sets the identification of the expectation to $id.
+     *
+     * @note The identifier is unique per mock object.
+     *
+     * @param string $id unique identification of expectation
+     */
+    public function id($id);
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/Builder/InvocationMocker.php b/vendor/phpunit/phpunit/src/Framework/MockObject/Builder/InvocationMocker.php
new file mode 100644
index 0000000000000000000000000000000000000000..3f8312afc51398d2a4f7427df16947b7f51f1ed9
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/MockObject/Builder/InvocationMocker.php
@@ -0,0 +1,305 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework\MockObject\Builder;
+
+use function array_map;
+use function array_merge;
+use function count;
+use function in_array;
+use function is_string;
+use function strtolower;
+use PHPUnit\Framework\Constraint\Constraint;
+use PHPUnit\Framework\MockObject\ConfigurableMethod;
+use PHPUnit\Framework\MockObject\IncompatibleReturnValueException;
+use PHPUnit\Framework\MockObject\InvocationHandler;
+use PHPUnit\Framework\MockObject\Matcher;
+use PHPUnit\Framework\MockObject\MatcherAlreadyRegisteredException;
+use PHPUnit\Framework\MockObject\MethodCannotBeConfiguredException;
+use PHPUnit\Framework\MockObject\MethodNameAlreadyConfiguredException;
+use PHPUnit\Framework\MockObject\MethodNameNotConfiguredException;
+use PHPUnit\Framework\MockObject\MethodParametersAlreadyConfiguredException;
+use PHPUnit\Framework\MockObject\Rule;
+use PHPUnit\Framework\MockObject\Stub\ConsecutiveCalls;
+use PHPUnit\Framework\MockObject\Stub\Exception;
+use PHPUnit\Framework\MockObject\Stub\ReturnArgument;
+use PHPUnit\Framework\MockObject\Stub\ReturnCallback;
+use PHPUnit\Framework\MockObject\Stub\ReturnReference;
+use PHPUnit\Framework\MockObject\Stub\ReturnSelf;
+use PHPUnit\Framework\MockObject\Stub\ReturnStub;
+use PHPUnit\Framework\MockObject\Stub\ReturnValueMap;
+use PHPUnit\Framework\MockObject\Stub\Stub;
+use Throwable;
+
+/**
+ * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+ */
+final class InvocationMocker implements InvocationStubber, MethodNameMatch
+{
+    /**
+     * @var InvocationHandler
+     */
+    private $invocationHandler;
+
+    /**
+     * @var Matcher
+     */
+    private $matcher;
+
+    /**
+     * @var ConfigurableMethod[]
+     */
+    private $configurableMethods;
+
+    public function __construct(InvocationHandler $handler, Matcher $matcher, ConfigurableMethod ...$configurableMethods)
+    {
+        $this->invocationHandler   = $handler;
+        $this->matcher             = $matcher;
+        $this->configurableMethods = $configurableMethods;
+    }
+
+    /**
+     * @throws MatcherAlreadyRegisteredException
+     *
+     * @return $this
+     */
+    public function id($id): self
+    {
+        $this->invocationHandler->registerMatcher($id, $this->matcher);
+
+        return $this;
+    }
+
+    /**
+     * @return $this
+     */
+    public function will(Stub $stub): Identity
+    {
+        $this->matcher->setStub($stub);
+
+        return $this;
+    }
+
+    /**
+     * @param mixed   $value
+     * @param mixed[] $nextValues
+     *
+     * @throws IncompatibleReturnValueException
+     */
+    public function willReturn($value, ...$nextValues): self
+    {
+        if (count($nextValues) === 0) {
+            $this->ensureTypeOfReturnValues([$value]);
+
+            $stub = $value instanceof Stub ? $value : new ReturnStub($value);
+        } else {
+            $values = array_merge([$value], $nextValues);
+
+            $this->ensureTypeOfReturnValues($values);
+
+            $stub = new ConsecutiveCalls($values);
+        }
+
+        return $this->will($stub);
+    }
+
+    public function willReturnReference(&$reference): self
+    {
+        $stub = new ReturnReference($reference);
+
+        return $this->will($stub);
+    }
+
+    public function willReturnMap(array $valueMap): self
+    {
+        $stub = new ReturnValueMap($valueMap);
+
+        return $this->will($stub);
+    }
+
+    public function willReturnArgument($argumentIndex): self
+    {
+        $stub = new ReturnArgument($argumentIndex);
+
+        return $this->will($stub);
+    }
+
+    public function willReturnCallback($callback): self
+    {
+        $stub = new ReturnCallback($callback);
+
+        return $this->will($stub);
+    }
+
+    public function willReturnSelf(): self
+    {
+        $stub = new ReturnSelf;
+
+        return $this->will($stub);
+    }
+
+    public function willReturnOnConsecutiveCalls(...$values): self
+    {
+        $stub = new ConsecutiveCalls($values);
+
+        return $this->will($stub);
+    }
+
+    public function willThrowException(Throwable $exception): self
+    {
+        $stub = new Exception($exception);
+
+        return $this->will($stub);
+    }
+
+    /**
+     * @return $this
+     */
+    public function after($id): self
+    {
+        $this->matcher->setAfterMatchBuilderId($id);
+
+        return $this;
+    }
+
+    /**
+     * @param mixed[] $arguments
+     *
+     * @throws \PHPUnit\Framework\Exception
+     * @throws MethodNameNotConfiguredException
+     * @throws MethodParametersAlreadyConfiguredException
+     *
+     * @return $this
+     */
+    public function with(...$arguments): self
+    {
+        $this->ensureParametersCanBeConfigured();
+
+        $this->matcher->setParametersRule(new Rule\Parameters($arguments));
+
+        return $this;
+    }
+
+    /**
+     * @param array ...$arguments
+     *
+     * @throws \PHPUnit\Framework\Exception
+     * @throws MethodNameNotConfiguredException
+     * @throws MethodParametersAlreadyConfiguredException
+     *
+     * @return $this
+     */
+    public function withConsecutive(...$arguments): self
+    {
+        $this->ensureParametersCanBeConfigured();
+
+        $this->matcher->setParametersRule(new Rule\ConsecutiveParameters($arguments));
+
+        return $this;
+    }
+
+    /**
+     * @throws MethodNameNotConfiguredException
+     * @throws MethodParametersAlreadyConfiguredException
+     *
+     * @return $this
+     */
+    public function withAnyParameters(): self
+    {
+        $this->ensureParametersCanBeConfigured();
+
+        $this->matcher->setParametersRule(new Rule\AnyParameters);
+
+        return $this;
+    }
+
+    /**
+     * @param Constraint|string $constraint
+     *
+     * @throws \PHPUnit\Framework\InvalidArgumentException
+     * @throws MethodCannotBeConfiguredException
+     * @throws MethodNameAlreadyConfiguredException
+     *
+     * @return $this
+     */
+    public function method($constraint): self
+    {
+        if ($this->matcher->hasMethodNameRule()) {
+            throw new MethodNameAlreadyConfiguredException;
+        }
+
+        $configurableMethodNames = array_map(
+            static function (ConfigurableMethod $configurable) {
+                return strtolower($configurable->getName());
+            },
+            $this->configurableMethods
+        );
+
+        if (is_string($constraint) && !in_array(strtolower($constraint), $configurableMethodNames, true)) {
+            throw new MethodCannotBeConfiguredException($constraint);
+        }
+
+        $this->matcher->setMethodNameRule(new Rule\MethodName($constraint));
+
+        return $this;
+    }
+
+    /**
+     * @throws MethodNameNotConfiguredException
+     * @throws MethodParametersAlreadyConfiguredException
+     */
+    private function ensureParametersCanBeConfigured(): void
+    {
+        if (!$this->matcher->hasMethodNameRule()) {
+            throw new MethodNameNotConfiguredException;
+        }
+
+        if ($this->matcher->hasParametersRule()) {
+            throw new MethodParametersAlreadyConfiguredException;
+        }
+    }
+
+    private function getConfiguredMethod(): ?ConfigurableMethod
+    {
+        $configuredMethod = null;
+
+        foreach ($this->configurableMethods as $configurableMethod) {
+            if ($this->matcher->getMethodNameRule()->matchesName($configurableMethod->getName())) {
+                if ($configuredMethod !== null) {
+                    return null;
+                }
+
+                $configuredMethod = $configurableMethod;
+            }
+        }
+
+        return $configuredMethod;
+    }
+
+    /**
+     * @throws IncompatibleReturnValueException
+     */
+    private function ensureTypeOfReturnValues(array $values): void
+    {
+        $configuredMethod = $this->getConfiguredMethod();
+
+        if ($configuredMethod === null) {
+            return;
+        }
+
+        foreach ($values as $value) {
+            if (!$configuredMethod->mayReturn($value)) {
+                throw new IncompatibleReturnValueException(
+                    $configuredMethod,
+                    $value
+                );
+            }
+        }
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/Builder/InvocationStubber.php b/vendor/phpunit/phpunit/src/Framework/MockObject/Builder/InvocationStubber.php
new file mode 100644
index 0000000000000000000000000000000000000000..f32ff0e7c27dda304dc9f2f1e7975bdf2fde3cbb
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/MockObject/Builder/InvocationStubber.php
@@ -0,0 +1,65 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework\MockObject\Builder;
+
+use PHPUnit\Framework\MockObject\Stub\Stub;
+use Throwable;
+
+/**
+ * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+ */
+interface InvocationStubber
+{
+    public function will(Stub $stub): Identity;
+
+    /** @return self */
+    public function willReturn($value, ...$nextValues)/*: self */;
+
+    /**
+     * @param mixed $reference
+     *
+     * @return self
+     */
+    public function willReturnReference(&$reference)/*: self */;
+
+    /**
+     * @param array<int, array<int, mixed>> $valueMap
+     *
+     * @return self
+     */
+    public function willReturnMap(array $valueMap)/*: self */;
+
+    /**
+     * @param int $argumentIndex
+     *
+     * @return self
+     */
+    public function willReturnArgument($argumentIndex)/*: self */;
+
+    /**
+     * @param callable $callback
+     *
+     * @return self
+     */
+    public function willReturnCallback($callback)/*: self */;
+
+    /** @return self */
+    public function willReturnSelf()/*: self */;
+
+    /**
+     * @param mixed $values
+     *
+     * @return self
+     */
+    public function willReturnOnConsecutiveCalls(...$values)/*: self */;
+
+    /** @return self */
+    public function willThrowException(Throwable $exception)/*: self */;
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/Builder/MethodNameMatch.php b/vendor/phpunit/phpunit/src/Framework/MockObject/Builder/MethodNameMatch.php
new file mode 100644
index 0000000000000000000000000000000000000000..f4b1150b5add6307db009cbd2388b6b9a9363f5e
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/MockObject/Builder/MethodNameMatch.php
@@ -0,0 +1,26 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework\MockObject\Builder;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+interface MethodNameMatch extends ParametersMatch
+{
+    /**
+     * Adds a new method name match and returns the parameter match object for
+     * further matching possibilities.
+     *
+     * @param \PHPUnit\Framework\Constraint\Constraint $name Constraint for matching method, if a string is passed it will use the PHPUnit_Framework_Constraint_IsEqual
+     *
+     * @return ParametersMatch
+     */
+    public function method($name);
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/Builder/ParametersMatch.php b/vendor/phpunit/phpunit/src/Framework/MockObject/Builder/ParametersMatch.php
new file mode 100644
index 0000000000000000000000000000000000000000..707d82551ad8d6f24191ef26710c0955d6688a74
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/MockObject/Builder/ParametersMatch.php
@@ -0,0 +1,58 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework\MockObject\Builder;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+interface ParametersMatch extends Stub
+{
+    /**
+     * Defines the expectation which must occur before the current is valid.
+     *
+     * @param string $id the identification of the expectation that should
+     *                   occur before this one
+     *
+     * @return Stub
+     */
+    public function after($id);
+
+    /**
+     * Sets the parameters to match for, each parameter to this function will
+     * be part of match. To perform specific matches or constraints create a
+     * new PHPUnit\Framework\Constraint\Constraint and use it for the parameter.
+     * If the parameter value is not a constraint it will use the
+     * PHPUnit\Framework\Constraint\IsEqual for the value.
+     *
+     * Some examples:
+     * <code>
+     * // match first parameter with value 2
+     * $b->with(2);
+     * // match first parameter with value 'smock' and second identical to 42
+     * $b->with('smock', new PHPUnit\Framework\Constraint\IsEqual(42));
+     * </code>
+     *
+     * @return ParametersMatch
+     */
+    public function with(...$arguments);
+
+    /**
+     * Sets a rule which allows any kind of parameters.
+     *
+     * Some examples:
+     * <code>
+     * // match any number of parameters
+     * $b->withAnyParameters();
+     * </code>
+     *
+     * @return ParametersMatch
+     */
+    public function withAnyParameters();
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/Builder/Stub.php b/vendor/phpunit/phpunit/src/Framework/MockObject/Builder/Stub.php
new file mode 100644
index 0000000000000000000000000000000000000000..d7cb78fc4e342a7fb8a4f4da0f49556fc844d831
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/MockObject/Builder/Stub.php
@@ -0,0 +1,24 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework\MockObject\Builder;
+
+use PHPUnit\Framework\MockObject\Stub\Stub as BaseStub;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+interface Stub extends Identity
+{
+    /**
+     * Stubs the matching method with the stub object $stub. Any invocations of
+     * the matched method will now be handled by the stub instead.
+     */
+    public function will(BaseStub $stub): Identity;
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/ConfigurableMethod.php b/vendor/phpunit/phpunit/src/Framework/MockObject/ConfigurableMethod.php
new file mode 100644
index 0000000000000000000000000000000000000000..4757dc637433fb8e7f2191116a9d58c9d1abcba2
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/MockObject/ConfigurableMethod.php
@@ -0,0 +1,53 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework\MockObject;
+
+use SebastianBergmann\Type\Type;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class ConfigurableMethod
+{
+    /**
+     * @var string
+     */
+    private $name;
+
+    /**
+     * @var Type
+     */
+    private $returnType;
+
+    public function __construct(string $name, Type $returnType)
+    {
+        $this->name       = $name;
+        $this->returnType = $returnType;
+    }
+
+    public function getName(): string
+    {
+        return $this->name;
+    }
+
+    public function mayReturn($value): bool
+    {
+        if ($value === null && $this->returnType->allowsNull()) {
+            return true;
+        }
+
+        return $this->returnType->isAssignable(Type::fromValue($value, false));
+    }
+
+    public function getReturnTypeDeclaration(): string
+    {
+        return $this->returnType->asString();
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/BadMethodCallException.php b/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/BadMethodCallException.php
new file mode 100644
index 0000000000000000000000000000000000000000..7e655e235a9e9fa6a70f6a1c76778ed4617384ce
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/BadMethodCallException.php
@@ -0,0 +1,17 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework\MockObject;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class BadMethodCallException extends \BadMethodCallException implements Exception
+{
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/CannotUseAddMethodsException.php b/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/CannotUseAddMethodsException.php
new file mode 100644
index 0000000000000000000000000000000000000000..12fa8b5c17ca59afb316bfde7e81d27b4acc4333
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/CannotUseAddMethodsException.php
@@ -0,0 +1,29 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework\MockObject;
+
+use function sprintf;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class CannotUseAddMethodsException extends \PHPUnit\Framework\Exception implements Exception
+{
+    public function __construct(string $type, string $methodName)
+    {
+        parent::__construct(
+            sprintf(
+                'Trying to set mock method "%s" with addMethods(), but it exists in class "%s". Use onlyMethods() for methods that exist in the class',
+                $methodName,
+                $type
+            )
+        );
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/CannotUseOnlyMethodsException.php b/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/CannotUseOnlyMethodsException.php
new file mode 100644
index 0000000000000000000000000000000000000000..95c302b3cad89f2ea7d56c8ef41e2e90855f5d40
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/CannotUseOnlyMethodsException.php
@@ -0,0 +1,29 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework\MockObject;
+
+use function sprintf;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class CannotUseOnlyMethodsException extends \PHPUnit\Framework\Exception implements Exception
+{
+    public function __construct(string $type, string $methodName)
+    {
+        parent::__construct(
+            sprintf(
+                'Trying to set mock method "%s" with onlyMethods, but it does not exist in class "%s". Use addMethods() for methods that do not exist in the class',
+                $methodName,
+                $type
+            )
+        );
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/ClassAlreadyExistsException.php b/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/ClassAlreadyExistsException.php
new file mode 100644
index 0000000000000000000000000000000000000000..0ba9a187d02aacd1810d823b95ba603290b6940d
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/ClassAlreadyExistsException.php
@@ -0,0 +1,28 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework\MockObject;
+
+use function sprintf;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class ClassAlreadyExistsException extends \PHPUnit\Framework\Exception implements Exception
+{
+    public function __construct(string $className)
+    {
+        parent::__construct(
+            sprintf(
+                'Class "%s" already exists',
+                $className
+            )
+        );
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/ClassIsFinalException.php b/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/ClassIsFinalException.php
new file mode 100644
index 0000000000000000000000000000000000000000..9b11f8c084e528c502cdeca18737b9a62770c6c1
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/ClassIsFinalException.php
@@ -0,0 +1,28 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework\MockObject;
+
+use function sprintf;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class ClassIsFinalException extends \PHPUnit\Framework\Exception implements Exception
+{
+    public function __construct(string $className)
+    {
+        parent::__construct(
+            sprintf(
+                'Class "%s" is declared "final" and cannot be mocked',
+                $className
+            )
+        );
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/ConfigurableMethodsAlreadyInitializedException.php b/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/ConfigurableMethodsAlreadyInitializedException.php
new file mode 100644
index 0000000000000000000000000000000000000000..d12ac997382b15b8af6562de7e010cbf504fba0d
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/ConfigurableMethodsAlreadyInitializedException.php
@@ -0,0 +1,17 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework\MockObject;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class ConfigurableMethodsAlreadyInitializedException extends \PHPUnit\Framework\Exception implements Exception
+{
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/DuplicateMethodException.php b/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/DuplicateMethodException.php
new file mode 100644
index 0000000000000000000000000000000000000000..6eb421774275152016d0ea7a4e5b19ef77e3a3ed
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/DuplicateMethodException.php
@@ -0,0 +1,32 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework\MockObject;
+
+use function sprintf;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class DuplicateMethodException extends \PHPUnit\Framework\Exception implements Exception
+{
+    /**
+     * @psalm-param list<string> $methods
+     */
+    public function __construct(array $methods)
+    {
+        parent::__construct(
+            sprintf(
+                'Cannot stub or mock using a method list that contains duplicates: "%s" (duplicate: "%s")',
+                implode(', ', $methods),
+                implode(', ', array_unique(array_diff_assoc($methods, array_unique($methods))))
+            )
+        );
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/Exception.php b/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/Exception.php
new file mode 100644
index 0000000000000000000000000000000000000000..5880bc033ecc31c1e941f7771e0d90486eb8fb1a
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/Exception.php
@@ -0,0 +1,19 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework\MockObject;
+
+use Throwable;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+interface Exception extends Throwable
+{
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/IncompatibleReturnValueException.php b/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/IncompatibleReturnValueException.php
new file mode 100644
index 0000000000000000000000000000000000000000..1bacc35163e7db00f326cde5c9a471d400ef4d28
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/IncompatibleReturnValueException.php
@@ -0,0 +1,33 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework\MockObject;
+
+use function sprintf;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class IncompatibleReturnValueException extends \PHPUnit\Framework\Exception implements Exception
+{
+    /**
+     * @param mixed $value
+     */
+    public function __construct(ConfigurableMethod $method, $value)
+    {
+        parent::__construct(
+            sprintf(
+                'Method %s may not return value of type %s, its return declaration is "%s"',
+                $method->getName(),
+                is_object($value) ? get_class($value) : gettype($value),
+                $method->getReturnTypeDeclaration()
+            )
+        );
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/InvalidMethodNameException.php b/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/InvalidMethodNameException.php
new file mode 100644
index 0000000000000000000000000000000000000000..5d85290fa452e0c9ee0e8a5214d1197b388de6b1
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/InvalidMethodNameException.php
@@ -0,0 +1,28 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework\MockObject;
+
+use function sprintf;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class InvalidMethodNameException extends \PHPUnit\Framework\Exception implements Exception
+{
+    public function __construct(string $method)
+    {
+        parent::__construct(
+            sprintf(
+                'Cannot stub or mock method with invalid name "%s"',
+                $method
+            )
+        );
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/MatchBuilderNotFoundException.php b/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/MatchBuilderNotFoundException.php
new file mode 100644
index 0000000000000000000000000000000000000000..c05b2bce69cce0e7ede2271cb045e02ea79f49ca
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/MatchBuilderNotFoundException.php
@@ -0,0 +1,28 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework\MockObject;
+
+use function sprintf;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class MatchBuilderNotFoundException extends \PHPUnit\Framework\Exception implements Exception
+{
+    public function __construct(string $id)
+    {
+        parent::__construct(
+            sprintf(
+                'No builder found for match builder identification <%s>',
+                $id
+            )
+        );
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/MatcherAlreadyRegisteredException.php b/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/MatcherAlreadyRegisteredException.php
new file mode 100644
index 0000000000000000000000000000000000000000..efcc13ed9601081ec07b2c6394dcdaaf9f2267b9
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/MatcherAlreadyRegisteredException.php
@@ -0,0 +1,28 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework\MockObject;
+
+use function sprintf;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class MatcherAlreadyRegisteredException extends \PHPUnit\Framework\Exception implements Exception
+{
+    public function __construct(string $id)
+    {
+        parent::__construct(
+            sprintf(
+                'Matcher with id <%s> is already registered',
+                $id
+            )
+        );
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/MethodCannotBeConfiguredException.php b/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/MethodCannotBeConfiguredException.php
new file mode 100644
index 0000000000000000000000000000000000000000..707290439a435c5cdc91adc9fb11851e285946b9
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/MethodCannotBeConfiguredException.php
@@ -0,0 +1,28 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework\MockObject;
+
+use function sprintf;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class MethodCannotBeConfiguredException extends \PHPUnit\Framework\Exception implements Exception
+{
+    public function __construct(string $method)
+    {
+        parent::__construct(
+            sprintf(
+                'Trying to configure method "%s" which cannot be configured because it does not exist, has not been specified, is final, or is static',
+                $method
+            )
+        );
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/MethodNameAlreadyConfiguredException.php b/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/MethodNameAlreadyConfiguredException.php
new file mode 100644
index 0000000000000000000000000000000000000000..1e9f2c04cacdc2b9ab62c60564181a635916b427
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/MethodNameAlreadyConfiguredException.php
@@ -0,0 +1,21 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework\MockObject;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class MethodNameAlreadyConfiguredException extends \PHPUnit\Framework\Exception implements Exception
+{
+    public function __construct()
+    {
+        parent::__construct('Method name is already configured');
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/MethodNameNotConfiguredException.php b/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/MethodNameNotConfiguredException.php
new file mode 100644
index 0000000000000000000000000000000000000000..89565b77ee2146bd1898b02e7f1cb45bbb3f4c62
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/MethodNameNotConfiguredException.php
@@ -0,0 +1,21 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework\MockObject;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class MethodNameNotConfiguredException extends \PHPUnit\Framework\Exception implements Exception
+{
+    public function __construct()
+    {
+        parent::__construct('Method name is not configured');
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/MethodParametersAlreadyConfiguredException.php b/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/MethodParametersAlreadyConfiguredException.php
new file mode 100644
index 0000000000000000000000000000000000000000..1609c6ffb6bb6293ae0edc3bf03bc580c4957851
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/MethodParametersAlreadyConfiguredException.php
@@ -0,0 +1,21 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework\MockObject;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class MethodParametersAlreadyConfiguredException extends \PHPUnit\Framework\Exception implements Exception
+{
+    public function __construct()
+    {
+        parent::__construct('Method parameters already configured');
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/OriginalConstructorInvocationRequiredException.php b/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/OriginalConstructorInvocationRequiredException.php
new file mode 100644
index 0000000000000000000000000000000000000000..ecb9b63cfc59c92a4b2b8d06e72ea3d44992ac61
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/OriginalConstructorInvocationRequiredException.php
@@ -0,0 +1,21 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework\MockObject;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class OriginalConstructorInvocationRequiredException extends \PHPUnit\Framework\Exception implements Exception
+{
+    public function __construct()
+    {
+        parent::__construct('Proxying to original methods requires invoking the original constructor');
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/ReflectionException.php b/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/ReflectionException.php
new file mode 100644
index 0000000000000000000000000000000000000000..d6319c694bb3f13825da66f4156fcf29447c72fc
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/ReflectionException.php
@@ -0,0 +1,19 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework\MockObject;
+
+use RuntimeException;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class ReflectionException extends RuntimeException implements Exception
+{
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/ReturnValueNotConfiguredException.php b/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/ReturnValueNotConfiguredException.php
new file mode 100644
index 0000000000000000000000000000000000000000..8121e369b24554c3b588d8a3d400a6acfe1425ab
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/ReturnValueNotConfiguredException.php
@@ -0,0 +1,27 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework\MockObject;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class ReturnValueNotConfiguredException extends \PHPUnit\Framework\Exception implements Exception
+{
+    public function __construct(Invocation $invocation)
+    {
+        parent::__construct(
+            sprintf(
+                'Return value inference disabled and no expectation set up for %s::%s()',
+                $invocation->getClassName(),
+                $invocation->getMethodName()
+            )
+        );
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/RuntimeException.php b/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/RuntimeException.php
new file mode 100644
index 0000000000000000000000000000000000000000..33b6a5be32f532e63c852e987035f2e004eff5f7
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/RuntimeException.php
@@ -0,0 +1,17 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework\MockObject;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class RuntimeException extends \RuntimeException implements Exception
+{
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/SoapExtensionNotAvailableException.php b/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/SoapExtensionNotAvailableException.php
new file mode 100644
index 0000000000000000000000000000000000000000..98837c9542e28f2bea9803c5c40d3c512a4d84cf
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/SoapExtensionNotAvailableException.php
@@ -0,0 +1,23 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework\MockObject;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class SoapExtensionNotAvailableException extends \PHPUnit\Framework\Exception implements Exception
+{
+    public function __construct()
+    {
+        parent::__construct(
+            'The SOAP extension is required to generate a test double from WSDL'
+        );
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/UnknownClassException.php b/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/UnknownClassException.php
new file mode 100644
index 0000000000000000000000000000000000000000..e124f9b18a5184b606c7bd718eb2fe4c1c5d114f
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/UnknownClassException.php
@@ -0,0 +1,28 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework\MockObject;
+
+use function sprintf;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class UnknownClassException extends \PHPUnit\Framework\Exception implements Exception
+{
+    public function __construct(string $className)
+    {
+        parent::__construct(
+            sprintf(
+                'Class "%s" does not exist',
+                $className
+            )
+        );
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/UnknownTraitException.php b/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/UnknownTraitException.php
new file mode 100644
index 0000000000000000000000000000000000000000..90fc8d848218c776d995ed926bb7492f4fc78ecd
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/UnknownTraitException.php
@@ -0,0 +1,28 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework\MockObject;
+
+use function sprintf;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class UnknownTraitException extends \PHPUnit\Framework\Exception implements Exception
+{
+    public function __construct(string $traitName)
+    {
+        parent::__construct(
+            sprintf(
+                'Trait "%s" does not exist',
+                $traitName
+            )
+        );
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/UnknownTypeException.php b/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/UnknownTypeException.php
new file mode 100644
index 0000000000000000000000000000000000000000..b1a70edd6d1445af92c6b20c97420bcf7f961de5
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/UnknownTypeException.php
@@ -0,0 +1,28 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework\MockObject;
+
+use function sprintf;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class UnknownTypeException extends \PHPUnit\Framework\Exception implements Exception
+{
+    public function __construct(string $type)
+    {
+        parent::__construct(
+            sprintf(
+                'Class or interface "%s" does not exist',
+                $type
+            )
+        );
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/Generator.php b/vendor/phpunit/phpunit/src/Framework/MockObject/Generator.php
new file mode 100644
index 0000000000000000000000000000000000000000..cb8531cd33e99c77c2d03e5de9fb0ad15b522bb1
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/MockObject/Generator.php
@@ -0,0 +1,1004 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework\MockObject;
+
+use const DIRECTORY_SEPARATOR;
+use const PHP_EOL;
+use const PHP_MAJOR_VERSION;
+use const PREG_OFFSET_CAPTURE;
+use const WSDL_CACHE_NONE;
+use function array_merge;
+use function array_pop;
+use function array_unique;
+use function class_exists;
+use function count;
+use function explode;
+use function extension_loaded;
+use function implode;
+use function in_array;
+use function interface_exists;
+use function is_array;
+use function is_object;
+use function md5;
+use function mt_rand;
+use function preg_match;
+use function preg_match_all;
+use function range;
+use function serialize;
+use function sort;
+use function sprintf;
+use function str_replace;
+use function strlen;
+use function strpos;
+use function strtolower;
+use function substr;
+use function trait_exists;
+use Doctrine\Instantiator\Exception\ExceptionInterface as InstantiatorException;
+use Doctrine\Instantiator\Instantiator;
+use Exception;
+use Iterator;
+use IteratorAggregate;
+use PHPUnit\Framework\InvalidArgumentException;
+use ReflectionClass;
+use ReflectionMethod;
+use SebastianBergmann\Template\Exception as TemplateException;
+use SebastianBergmann\Template\Template;
+use SoapClient;
+use SoapFault;
+use Throwable;
+use Traversable;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class Generator
+{
+    /**
+     * @var array
+     */
+    private const EXCLUDED_METHOD_NAMES = [
+        '__CLASS__'       => true,
+        '__DIR__'         => true,
+        '__FILE__'        => true,
+        '__FUNCTION__'    => true,
+        '__LINE__'        => true,
+        '__METHOD__'      => true,
+        '__NAMESPACE__'   => true,
+        '__TRAIT__'       => true,
+        '__clone'         => true,
+        '__halt_compiler' => true,
+    ];
+
+    /**
+     * @var array
+     */
+    private static $cache = [];
+
+    /**
+     * @var Template[]
+     */
+    private static $templates = [];
+
+    /**
+     * Returns a mock object for the specified class.
+     *
+     * @param null|array $methods
+     *
+     * @throws \PHPUnit\Framework\InvalidArgumentException
+     * @throws ClassAlreadyExistsException
+     * @throws ClassIsFinalException
+     * @throws DuplicateMethodException
+     * @throws InvalidMethodNameException
+     * @throws OriginalConstructorInvocationRequiredException
+     * @throws ReflectionException
+     * @throws RuntimeException
+     * @throws UnknownTypeException
+     */
+    public function getMock(string $type, $methods = [], array $arguments = [], string $mockClassName = '', bool $callOriginalConstructor = true, bool $callOriginalClone = true, bool $callAutoload = true, bool $cloneArguments = true, bool $callOriginalMethods = false, object $proxyTarget = null, bool $allowMockingUnknownTypes = true, bool $returnValueGeneration = true): MockObject
+    {
+        if (!is_array($methods) && null !== $methods) {
+            throw InvalidArgumentException::create(2, 'array');
+        }
+
+        if ($type === 'Traversable' || $type === '\\Traversable') {
+            $type = 'Iterator';
+        }
+
+        if (!$allowMockingUnknownTypes && !class_exists($type, $callAutoload) && !interface_exists($type, $callAutoload)) {
+            throw new UnknownTypeException($type);
+        }
+
+        if (null !== $methods) {
+            foreach ($methods as $method) {
+                if (!preg_match('~[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*~', (string) $method)) {
+                    throw new InvalidMethodNameException((string) $method);
+                }
+            }
+
+            if ($methods !== array_unique($methods)) {
+                throw new DuplicateMethodException($methods);
+            }
+        }
+
+        if ($mockClassName !== '' && class_exists($mockClassName, false)) {
+            try {
+                $reflector = new ReflectionClass($mockClassName);
+                // @codeCoverageIgnoreStart
+            } catch (\ReflectionException $e) {
+                throw new ReflectionException(
+                    $e->getMessage(),
+                    (int) $e->getCode(),
+                    $e
+                );
+            }
+            // @codeCoverageIgnoreEnd
+
+            if (!$reflector->implementsInterface(MockObject::class)) {
+                throw new ClassAlreadyExistsException($mockClassName);
+            }
+        }
+
+        if (!$callOriginalConstructor && $callOriginalMethods) {
+            throw new OriginalConstructorInvocationRequiredException;
+        }
+
+        $mock = $this->generate(
+            $type,
+            $methods,
+            $mockClassName,
+            $callOriginalClone,
+            $callAutoload,
+            $cloneArguments,
+            $callOriginalMethods
+        );
+
+        return $this->getObject(
+            $mock,
+            $type,
+            $callOriginalConstructor,
+            $callAutoload,
+            $arguments,
+            $callOriginalMethods,
+            $proxyTarget,
+            $returnValueGeneration
+        );
+    }
+
+    /**
+     * Returns a mock object for the specified abstract class with all abstract
+     * methods of the class mocked.
+     *
+     * Concrete methods to mock can be specified with the $mockedMethods parameter.
+     *
+     * @psalm-template RealInstanceType of object
+     * @psalm-param class-string<RealInstanceType> $originalClassName
+     * @psalm-return MockObject&RealInstanceType
+     *
+     * @throws \PHPUnit\Framework\InvalidArgumentException
+     * @throws ClassAlreadyExistsException
+     * @throws ClassIsFinalException
+     * @throws DuplicateMethodException
+     * @throws InvalidMethodNameException
+     * @throws OriginalConstructorInvocationRequiredException
+     * @throws ReflectionException
+     * @throws RuntimeException
+     * @throws UnknownClassException
+     * @throws UnknownTypeException
+     */
+    public function getMockForAbstractClass(string $originalClassName, array $arguments = [], string $mockClassName = '', bool $callOriginalConstructor = true, bool $callOriginalClone = true, bool $callAutoload = true, array $mockedMethods = null, bool $cloneArguments = true): MockObject
+    {
+        if (class_exists($originalClassName, $callAutoload) ||
+            interface_exists($originalClassName, $callAutoload)) {
+            try {
+                $reflector = new ReflectionClass($originalClassName);
+                // @codeCoverageIgnoreStart
+            } catch (\ReflectionException $e) {
+                throw new ReflectionException(
+                    $e->getMessage(),
+                    (int) $e->getCode(),
+                    $e
+                );
+            }
+            // @codeCoverageIgnoreEnd
+
+            $methods = $mockedMethods;
+
+            foreach ($reflector->getMethods() as $method) {
+                if ($method->isAbstract() && !in_array($method->getName(), $methods ?? [], true)) {
+                    $methods[] = $method->getName();
+                }
+            }
+
+            if (empty($methods)) {
+                $methods = null;
+            }
+
+            return $this->getMock(
+                $originalClassName,
+                $methods,
+                $arguments,
+                $mockClassName,
+                $callOriginalConstructor,
+                $callOriginalClone,
+                $callAutoload,
+                $cloneArguments
+            );
+        }
+
+        throw new UnknownClassException($originalClassName);
+    }
+
+    /**
+     * Returns a mock object for the specified trait with all abstract methods
+     * of the trait mocked. Concrete methods to mock can be specified with the
+     * `$mockedMethods` parameter.
+     *
+     * @psalm-param trait-string $traitName
+     *
+     * @throws \PHPUnit\Framework\InvalidArgumentException
+     * @throws ClassAlreadyExistsException
+     * @throws ClassIsFinalException
+     * @throws DuplicateMethodException
+     * @throws InvalidMethodNameException
+     * @throws OriginalConstructorInvocationRequiredException
+     * @throws ReflectionException
+     * @throws RuntimeException
+     * @throws UnknownClassException
+     * @throws UnknownTraitException
+     * @throws UnknownTypeException
+     */
+    public function getMockForTrait(string $traitName, array $arguments = [], string $mockClassName = '', bool $callOriginalConstructor = true, bool $callOriginalClone = true, bool $callAutoload = true, array $mockedMethods = null, bool $cloneArguments = true): MockObject
+    {
+        if (!trait_exists($traitName, $callAutoload)) {
+            throw new UnknownTraitException($traitName);
+        }
+
+        $className = $this->generateClassName(
+            $traitName,
+            '',
+            'Trait_'
+        );
+
+        $classTemplate = $this->getTemplate('trait_class.tpl');
+
+        $classTemplate->setVar(
+            [
+                'prologue'   => 'abstract ',
+                'class_name' => $className['className'],
+                'trait_name' => $traitName,
+            ]
+        );
+
+        $mockTrait = new MockTrait($classTemplate->render(), $className['className']);
+        $mockTrait->generate();
+
+        return $this->getMockForAbstractClass($className['className'], $arguments, $mockClassName, $callOriginalConstructor, $callOriginalClone, $callAutoload, $mockedMethods, $cloneArguments);
+    }
+
+    /**
+     * Returns an object for the specified trait.
+     *
+     * @psalm-param trait-string $traitName
+     *
+     * @throws ReflectionException
+     * @throws RuntimeException
+     * @throws UnknownTraitException
+     */
+    public function getObjectForTrait(string $traitName, string $traitClassName = '', bool $callAutoload = true, bool $callOriginalConstructor = false, array $arguments = []): object
+    {
+        if (!trait_exists($traitName, $callAutoload)) {
+            throw new UnknownTraitException($traitName);
+        }
+
+        $className = $this->generateClassName(
+            $traitName,
+            $traitClassName,
+            'Trait_'
+        );
+
+        $classTemplate = $this->getTemplate('trait_class.tpl');
+
+        $classTemplate->setVar(
+            [
+                'prologue'   => '',
+                'class_name' => $className['className'],
+                'trait_name' => $traitName,
+            ]
+        );
+
+        return $this->getObject(
+            new MockTrait(
+                $classTemplate->render(),
+                $className['className']
+            ),
+            '',
+            $callOriginalConstructor,
+            $callAutoload,
+            $arguments
+        );
+    }
+
+    /**
+     * @throws ClassIsFinalException
+     * @throws ReflectionException
+     * @throws RuntimeException
+     */
+    public function generate(string $type, array $methods = null, string $mockClassName = '', bool $callOriginalClone = true, bool $callAutoload = true, bool $cloneArguments = true, bool $callOriginalMethods = false): MockClass
+    {
+        if ($mockClassName !== '') {
+            return $this->generateMock(
+                $type,
+                $methods,
+                $mockClassName,
+                $callOriginalClone,
+                $callAutoload,
+                $cloneArguments,
+                $callOriginalMethods
+            );
+        }
+
+        $key = md5(
+            $type .
+            serialize($methods) .
+            serialize($callOriginalClone) .
+            serialize($cloneArguments) .
+            serialize($callOriginalMethods)
+        );
+
+        if (!isset(self::$cache[$key])) {
+            self::$cache[$key] = $this->generateMock(
+                $type,
+                $methods,
+                $mockClassName,
+                $callOriginalClone,
+                $callAutoload,
+                $cloneArguments,
+                $callOriginalMethods
+            );
+        }
+
+        return self::$cache[$key];
+    }
+
+    /**
+     * @throws RuntimeException
+     * @throws SoapExtensionNotAvailableException
+     */
+    public function generateClassFromWsdl(string $wsdlFile, string $className, array $methods = [], array $options = []): string
+    {
+        if (!extension_loaded('soap')) {
+            throw new SoapExtensionNotAvailableException;
+        }
+
+        $options = array_merge($options, ['cache_wsdl' => WSDL_CACHE_NONE]);
+
+        try {
+            $client   = new SoapClient($wsdlFile, $options);
+            $_methods = array_unique($client->__getFunctions());
+            unset($client);
+        } catch (SoapFault $e) {
+            throw new RuntimeException(
+                $e->getMessage(),
+                (int) $e->getCode(),
+                $e
+            );
+        }
+
+        sort($_methods);
+
+        $methodTemplate = $this->getTemplate('wsdl_method.tpl');
+        $methodsBuffer  = '';
+
+        foreach ($_methods as $method) {
+            preg_match_all('/[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*\(/', $method, $matches, PREG_OFFSET_CAPTURE);
+            $lastFunction = array_pop($matches[0]);
+            $nameStart    = $lastFunction[1];
+            $nameEnd      = $nameStart + strlen($lastFunction[0]) - 1;
+            $name         = str_replace('(', '', $lastFunction[0]);
+
+            if (empty($methods) || in_array($name, $methods, true)) {
+                $args = explode(
+                    ',',
+                    str_replace(')', '', substr($method, $nameEnd + 1))
+                );
+
+                foreach (range(0, count($args) - 1) as $i) {
+                    $parameterStart = strpos($args[$i], '$');
+
+                    if (!$parameterStart) {
+                        continue;
+                    }
+
+                    $args[$i] = substr($args[$i], $parameterStart);
+                }
+
+                $methodTemplate->setVar(
+                    [
+                        'method_name' => $name,
+                        'arguments'   => implode(', ', $args),
+                    ]
+                );
+
+                $methodsBuffer .= $methodTemplate->render();
+            }
+        }
+
+        $optionsBuffer = '[';
+
+        foreach ($options as $key => $value) {
+            $optionsBuffer .= $key . ' => ' . $value;
+        }
+
+        $optionsBuffer .= ']';
+
+        $classTemplate = $this->getTemplate('wsdl_class.tpl');
+        $namespace     = '';
+
+        if (strpos($className, '\\') !== false) {
+            $parts     = explode('\\', $className);
+            $className = array_pop($parts);
+            $namespace = 'namespace ' . implode('\\', $parts) . ';' . "\n\n";
+        }
+
+        $classTemplate->setVar(
+            [
+                'namespace'  => $namespace,
+                'class_name' => $className,
+                'wsdl'       => $wsdlFile,
+                'options'    => $optionsBuffer,
+                'methods'    => $methodsBuffer,
+            ]
+        );
+
+        return $classTemplate->render();
+    }
+
+    /**
+     * @throws ReflectionException
+     *
+     * @return string[]
+     */
+    public function getClassMethods(string $className): array
+    {
+        try {
+            $class = new ReflectionClass($className);
+            // @codeCoverageIgnoreStart
+        } catch (\ReflectionException $e) {
+            throw new ReflectionException(
+                $e->getMessage(),
+                (int) $e->getCode(),
+                $e
+            );
+        }
+        // @codeCoverageIgnoreEnd
+
+        $methods = [];
+
+        foreach ($class->getMethods() as $method) {
+            if ($method->isPublic() || $method->isAbstract()) {
+                $methods[] = $method->getName();
+            }
+        }
+
+        return $methods;
+    }
+
+    /**
+     * @throws ReflectionException
+     *
+     * @return MockMethod[]
+     */
+    public function mockClassMethods(string $className, bool $callOriginalMethods, bool $cloneArguments): array
+    {
+        try {
+            $class = new ReflectionClass($className);
+            // @codeCoverageIgnoreStart
+        } catch (\ReflectionException $e) {
+            throw new ReflectionException(
+                $e->getMessage(),
+                (int) $e->getCode(),
+                $e
+            );
+        }
+        // @codeCoverageIgnoreEnd
+
+        $methods = [];
+
+        foreach ($class->getMethods() as $method) {
+            if (($method->isPublic() || $method->isAbstract()) && $this->canMockMethod($method)) {
+                $methods[] = MockMethod::fromReflection($method, $callOriginalMethods, $cloneArguments);
+            }
+        }
+
+        return $methods;
+    }
+
+    /**
+     * @throws ReflectionException
+     *
+     * @return MockMethod[]
+     */
+    public function mockInterfaceMethods(string $interfaceName, bool $cloneArguments): array
+    {
+        try {
+            $class = new ReflectionClass($interfaceName);
+            // @codeCoverageIgnoreStart
+        } catch (\ReflectionException $e) {
+            throw new ReflectionException(
+                $e->getMessage(),
+                (int) $e->getCode(),
+                $e
+            );
+        }
+        // @codeCoverageIgnoreEnd
+
+        $methods = [];
+
+        foreach ($class->getMethods() as $method) {
+            $methods[] = MockMethod::fromReflection($method, false, $cloneArguments);
+        }
+
+        return $methods;
+    }
+
+    /**
+     * @psalm-param class-string $interfaceName
+     *
+     * @throws ReflectionException
+     *
+     * @return ReflectionMethod[]
+     */
+    private function userDefinedInterfaceMethods(string $interfaceName): array
+    {
+        try {
+            // @codeCoverageIgnoreStart
+            $interface = new ReflectionClass($interfaceName);
+        } catch (\ReflectionException $e) {
+            throw new ReflectionException(
+                $e->getMessage(),
+                (int) $e->getCode(),
+                $e
+            );
+        }
+        // @codeCoverageIgnoreEnd
+
+        $methods = [];
+
+        foreach ($interface->getMethods() as $method) {
+            if (!$method->isUserDefined()) {
+                continue;
+            }
+
+            $methods[] = $method;
+        }
+
+        return $methods;
+    }
+
+    /**
+     * @throws ReflectionException
+     * @throws RuntimeException
+     */
+    private function getObject(MockType $mockClass, $type = '', bool $callOriginalConstructor = false, bool $callAutoload = false, array $arguments = [], bool $callOriginalMethods = false, object $proxyTarget = null, bool $returnValueGeneration = true)
+    {
+        $className = $mockClass->generate();
+
+        if ($callOriginalConstructor) {
+            if (count($arguments) === 0) {
+                $object = new $className;
+            } else {
+                try {
+                    $class = new ReflectionClass($className);
+                    // @codeCoverageIgnoreStart
+                } catch (\ReflectionException $e) {
+                    throw new ReflectionException(
+                        $e->getMessage(),
+                        (int) $e->getCode(),
+                        $e
+                    );
+                }
+                // @codeCoverageIgnoreEnd
+
+                $object = $class->newInstanceArgs($arguments);
+            }
+        } else {
+            try {
+                $object = (new Instantiator)->instantiate($className);
+            } catch (InstantiatorException $e) {
+                throw new RuntimeException($e->getMessage());
+            }
+        }
+
+        if ($callOriginalMethods) {
+            if (!is_object($proxyTarget)) {
+                if (count($arguments) === 0) {
+                    $proxyTarget = new $type;
+                } else {
+                    try {
+                        $class = new ReflectionClass($type);
+                        // @codeCoverageIgnoreStart
+                    } catch (\ReflectionException $e) {
+                        throw new ReflectionException(
+                            $e->getMessage(),
+                            (int) $e->getCode(),
+                            $e
+                        );
+                    }
+                    // @codeCoverageIgnoreEnd
+
+                    $proxyTarget = $class->newInstanceArgs($arguments);
+                }
+            }
+
+            $object->__phpunit_setOriginalObject($proxyTarget);
+        }
+
+        if ($object instanceof MockObject) {
+            $object->__phpunit_setReturnValueGeneration($returnValueGeneration);
+        }
+
+        return $object;
+    }
+
+    /**
+     * @throws ClassIsFinalException
+     * @throws ReflectionException
+     * @throws RuntimeException
+     */
+    private function generateMock(string $type, ?array $explicitMethods, string $mockClassName, bool $callOriginalClone, bool $callAutoload, bool $cloneArguments, bool $callOriginalMethods): MockClass
+    {
+        $classTemplate        = $this->getTemplate('mocked_class.tpl');
+        $additionalInterfaces = [];
+        $mockedCloneMethod    = false;
+        $unmockedCloneMethod  = false;
+        $isClass              = false;
+        $isInterface          = false;
+        $class                = null;
+        $mockMethods          = new MockMethodSet;
+
+        $_mockClassName = $this->generateClassName(
+            $type,
+            $mockClassName,
+            'Mock_'
+        );
+
+        if (class_exists($_mockClassName['fullClassName'], $callAutoload)) {
+            $isClass = true;
+        } elseif (interface_exists($_mockClassName['fullClassName'], $callAutoload)) {
+            $isInterface = true;
+        }
+
+        if (!$isClass && !$isInterface) {
+            $prologue = 'class ' . $_mockClassName['originalClassName'] . "\n{\n}\n\n";
+
+            if (!empty($_mockClassName['namespaceName'])) {
+                $prologue = 'namespace ' . $_mockClassName['namespaceName'] .
+                            " {\n\n" . $prologue . "}\n\n" .
+                            "namespace {\n\n";
+
+                $epilogue = "\n\n}";
+            }
+
+            $mockedCloneMethod = true;
+        } else {
+            try {
+                $class = new ReflectionClass($_mockClassName['fullClassName']);
+                // @codeCoverageIgnoreStart
+            } catch (\ReflectionException $e) {
+                throw new ReflectionException(
+                    $e->getMessage(),
+                    (int) $e->getCode(),
+                    $e
+                );
+            }
+            // @codeCoverageIgnoreEnd
+
+            if ($class->isFinal()) {
+                throw new ClassIsFinalException($_mockClassName['fullClassName']);
+            }
+
+            // @see https://github.com/sebastianbergmann/phpunit/issues/2995
+            if ($isInterface && $class->implementsInterface(Throwable::class)) {
+                $actualClassName        = Exception::class;
+                $additionalInterfaces[] = $class->getName();
+                $isInterface            = false;
+
+                try {
+                    $class = new ReflectionClass($actualClassName);
+                    // @codeCoverageIgnoreStart
+                } catch (\ReflectionException $e) {
+                    throw new ReflectionException(
+                        $e->getMessage(),
+                        (int) $e->getCode(),
+                        $e
+                    );
+                }
+                // @codeCoverageIgnoreEnd
+
+                foreach ($this->userDefinedInterfaceMethods($_mockClassName['fullClassName']) as $method) {
+                    $methodName = $method->getName();
+
+                    if ($class->hasMethod($methodName)) {
+                        try {
+                            $classMethod = $class->getMethod($methodName);
+                            // @codeCoverageIgnoreStart
+                        } catch (\ReflectionException $e) {
+                            throw new ReflectionException(
+                                $e->getMessage(),
+                                (int) $e->getCode(),
+                                $e
+                            );
+                        }
+                        // @codeCoverageIgnoreEnd
+
+                        if (!$this->canMockMethod($classMethod)) {
+                            continue;
+                        }
+                    }
+
+                    $mockMethods->addMethods(
+                        MockMethod::fromReflection($method, $callOriginalMethods, $cloneArguments)
+                    );
+                }
+
+                $_mockClassName = $this->generateClassName(
+                    $actualClassName,
+                    $_mockClassName['className'],
+                    'Mock_'
+                );
+            }
+
+            // @see https://github.com/sebastianbergmann/phpunit-mock-objects/issues/103
+            if ($isInterface && $class->implementsInterface(Traversable::class) &&
+                !$class->implementsInterface(Iterator::class) &&
+                !$class->implementsInterface(IteratorAggregate::class)) {
+                $additionalInterfaces[] = Iterator::class;
+
+                $mockMethods->addMethods(
+                    ...$this->mockClassMethods(Iterator::class, $callOriginalMethods, $cloneArguments)
+                );
+            }
+
+            if ($class->hasMethod('__clone')) {
+                try {
+                    $cloneMethod = $class->getMethod('__clone');
+                    // @codeCoverageIgnoreStart
+                } catch (\ReflectionException $e) {
+                    throw new ReflectionException(
+                        $e->getMessage(),
+                        (int) $e->getCode(),
+                        $e
+                    );
+                }
+                // @codeCoverageIgnoreEnd
+
+                if (!$cloneMethod->isFinal()) {
+                    if ($callOriginalClone && !$isInterface) {
+                        $unmockedCloneMethod = true;
+                    } else {
+                        $mockedCloneMethod = true;
+                    }
+                }
+            } else {
+                $mockedCloneMethod = true;
+            }
+        }
+
+        if ($isClass && $explicitMethods === []) {
+            $mockMethods->addMethods(
+                ...$this->mockClassMethods($_mockClassName['fullClassName'], $callOriginalMethods, $cloneArguments)
+            );
+        }
+
+        if ($isInterface && ($explicitMethods === [] || $explicitMethods === null)) {
+            $mockMethods->addMethods(
+                ...$this->mockInterfaceMethods($_mockClassName['fullClassName'], $cloneArguments)
+            );
+        }
+
+        if (is_array($explicitMethods)) {
+            foreach ($explicitMethods as $methodName) {
+                if ($class !== null && $class->hasMethod($methodName)) {
+                    try {
+                        $method = $class->getMethod($methodName);
+                        // @codeCoverageIgnoreStart
+                    } catch (\ReflectionException $e) {
+                        throw new ReflectionException(
+                            $e->getMessage(),
+                            (int) $e->getCode(),
+                            $e
+                        );
+                    }
+                    // @codeCoverageIgnoreEnd
+
+                    if ($this->canMockMethod($method)) {
+                        $mockMethods->addMethods(
+                            MockMethod::fromReflection($method, $callOriginalMethods, $cloneArguments)
+                        );
+                    }
+                } else {
+                    $mockMethods->addMethods(
+                        MockMethod::fromName(
+                            $_mockClassName['fullClassName'],
+                            $methodName,
+                            $cloneArguments
+                        )
+                    );
+                }
+            }
+        }
+
+        $mockedMethods = '';
+        $configurable  = [];
+
+        foreach ($mockMethods->asArray() as $mockMethod) {
+            $mockedMethods .= $mockMethod->generateCode();
+            $configurable[] = new ConfigurableMethod($mockMethod->getName(), $mockMethod->getReturnType());
+        }
+
+        $method = '';
+
+        if (!$mockMethods->hasMethod('method') && (!isset($class) || !$class->hasMethod('method'))) {
+            $method = PHP_EOL . '    use \PHPUnit\Framework\MockObject\Method;';
+        }
+
+        $cloneTrait = '';
+
+        if ($mockedCloneMethod) {
+            $cloneTrait = PHP_EOL . '    use \PHPUnit\Framework\MockObject\MockedCloneMethod;';
+        }
+
+        if ($unmockedCloneMethod) {
+            $cloneTrait = PHP_EOL . '    use \PHPUnit\Framework\MockObject\UnmockedCloneMethod;';
+        }
+
+        $classTemplate->setVar(
+            [
+                'prologue'          => $prologue ?? '',
+                'epilogue'          => $epilogue ?? '',
+                'class_declaration' => $this->generateMockClassDeclaration(
+                    $_mockClassName,
+                    $isInterface,
+                    $additionalInterfaces
+                ),
+                'clone'           => $cloneTrait,
+                'mock_class_name' => $_mockClassName['className'],
+                'mocked_methods'  => $mockedMethods,
+                'method'          => $method,
+            ]
+        );
+
+        return new MockClass(
+            $classTemplate->render(),
+            $_mockClassName['className'],
+            $configurable
+        );
+    }
+
+    private function generateClassName(string $type, string $className, string $prefix): array
+    {
+        if ($type[0] === '\\') {
+            $type = substr($type, 1);
+        }
+
+        $classNameParts = explode('\\', $type);
+
+        if (count($classNameParts) > 1) {
+            $type          = array_pop($classNameParts);
+            $namespaceName = implode('\\', $classNameParts);
+            $fullClassName = $namespaceName . '\\' . $type;
+        } else {
+            $namespaceName = '';
+            $fullClassName = $type;
+        }
+
+        if ($className === '') {
+            do {
+                $className = $prefix . $type . '_' .
+                             substr(md5((string) mt_rand()), 0, 8);
+            } while (class_exists($className, false));
+        }
+
+        return [
+            'className'         => $className,
+            'originalClassName' => $type,
+            'fullClassName'     => $fullClassName,
+            'namespaceName'     => $namespaceName,
+        ];
+    }
+
+    private function generateMockClassDeclaration(array $mockClassName, bool $isInterface, array $additionalInterfaces = []): string
+    {
+        $buffer = 'class ';
+
+        $additionalInterfaces[] = MockObject::class;
+        $interfaces             = implode(', ', $additionalInterfaces);
+
+        if ($isInterface) {
+            $buffer .= sprintf(
+                '%s implements %s',
+                $mockClassName['className'],
+                $interfaces
+            );
+
+            if (!in_array($mockClassName['originalClassName'], $additionalInterfaces, true)) {
+                $buffer .= ', ';
+
+                if (!empty($mockClassName['namespaceName'])) {
+                    $buffer .= $mockClassName['namespaceName'] . '\\';
+                }
+
+                $buffer .= $mockClassName['originalClassName'];
+            }
+        } else {
+            $buffer .= sprintf(
+                '%s extends %s%s implements %s',
+                $mockClassName['className'],
+                !empty($mockClassName['namespaceName']) ? $mockClassName['namespaceName'] . '\\' : '',
+                $mockClassName['originalClassName'],
+                $interfaces
+            );
+        }
+
+        return $buffer;
+    }
+
+    private function canMockMethod(ReflectionMethod $method): bool
+    {
+        return !($this->isConstructor($method) || $method->isFinal() || $method->isPrivate() || $this->isMethodNameExcluded($method->getName()));
+    }
+
+    private function isMethodNameExcluded(string $name): bool
+    {
+        return isset(self::EXCLUDED_METHOD_NAMES[$name]);
+    }
+
+    /**
+     * @throws RuntimeException
+     */
+    private function getTemplate(string $template): Template
+    {
+        $filename = __DIR__ . DIRECTORY_SEPARATOR . 'Generator' . DIRECTORY_SEPARATOR . $template;
+
+        if (!isset(self::$templates[$filename])) {
+            try {
+                self::$templates[$filename] = new Template($filename);
+            } catch (TemplateException $e) {
+                throw new RuntimeException(
+                    $e->getMessage(),
+                    (int) $e->getCode(),
+                    $e
+                );
+            }
+        }
+
+        return self::$templates[$filename];
+    }
+
+    /**
+     * @see https://github.com/sebastianbergmann/phpunit/issues/4139#issuecomment-605409765
+     */
+    private function isConstructor(ReflectionMethod $method): bool
+    {
+        $methodName = strtolower($method->getName());
+
+        if ($methodName === '__construct') {
+            return true;
+        }
+
+        if (PHP_MAJOR_VERSION >= 8) {
+            return false;
+        }
+
+        $className = strtolower($method->getDeclaringClass()->getName());
+
+        return $methodName === $className;
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/deprecation.tpl b/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/deprecation.tpl
new file mode 100644
index 0000000000000000000000000000000000000000..5bf06f52de12cae60512f7bbb370c4f53c2dde1c
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/deprecation.tpl
@@ -0,0 +1,2 @@
+
+        @trigger_error({deprecation}, E_USER_DEPRECATED);
diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/mocked_class.tpl b/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/mocked_class.tpl
new file mode 100644
index 0000000000000000000000000000000000000000..593119fb26f9700f5202f714a690eaf83c29922d
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/mocked_class.tpl
@@ -0,0 +1,6 @@
+declare(strict_types=1);
+
+{prologue}{class_declaration}
+{
+    use \PHPUnit\Framework\MockObject\Api;{method}{clone}
+{mocked_methods}}{epilogue}
diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/mocked_method.tpl b/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/mocked_method.tpl
new file mode 100644
index 0000000000000000000000000000000000000000..114ff8d0d923a35e129df07a7961095e28df0683
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/mocked_method.tpl
@@ -0,0 +1,22 @@
+
+    {modifier} function {reference}{method_name}({arguments_decl}){return_declaration}
+    {{deprecation}
+        $__phpunit_arguments = [{arguments_call}];
+        $__phpunit_count     = func_num_args();
+
+        if ($__phpunit_count > {arguments_count}) {
+            $__phpunit_arguments_tmp = func_get_args();
+
+            for ($__phpunit_i = {arguments_count}; $__phpunit_i < $__phpunit_count; $__phpunit_i++) {
+                $__phpunit_arguments[] = $__phpunit_arguments_tmp[$__phpunit_i];
+            }
+        }
+
+        $__phpunit_result = $this->__phpunit_getInvocationHandler()->invoke(
+            new \PHPUnit\Framework\MockObject\Invocation(
+                '{class_name}', '{method_name}', $__phpunit_arguments, '{return_type}', $this, {clone_arguments}
+            )
+        );
+
+        return $__phpunit_result;
+    }
diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/mocked_method_void.tpl b/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/mocked_method_void.tpl
new file mode 100644
index 0000000000000000000000000000000000000000..390202201a24e7502056c4708ed2c7320905d293
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/mocked_method_void.tpl
@@ -0,0 +1,20 @@
+
+    {modifier} function {reference}{method_name}({arguments_decl}){return_declaration}
+    {{deprecation}
+        $__phpunit_arguments = [{arguments_call}];
+        $__phpunit_count     = func_num_args();
+
+        if ($__phpunit_count > {arguments_count}) {
+            $__phpunit_arguments_tmp = func_get_args();
+
+            for ($__phpunit_i = {arguments_count}; $__phpunit_i < $__phpunit_count; $__phpunit_i++) {
+                $__phpunit_arguments[] = $__phpunit_arguments_tmp[$__phpunit_i];
+            }
+        }
+
+        $this->__phpunit_getInvocationHandler()->invoke(
+            new \PHPUnit\Framework\MockObject\Invocation(
+                '{class_name}', '{method_name}', $__phpunit_arguments, '{return_type}', $this, {clone_arguments}
+            )
+        );
+    }
diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/mocked_static_method.tpl b/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/mocked_static_method.tpl
new file mode 100644
index 0000000000000000000000000000000000000000..5e5cf23cdddca7f6ed47e0e4cdbe92b84364f842
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/mocked_static_method.tpl
@@ -0,0 +1,5 @@
+
+    {modifier} function {reference}{method_name}({arguments_decl}){return_declaration}
+    {
+        throw new \PHPUnit\Framework\MockObject\BadMethodCallException('Static method "{method_name}" cannot be invoked on mock object');
+    }
diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/proxied_method.tpl b/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/proxied_method.tpl
new file mode 100644
index 0000000000000000000000000000000000000000..91bef463d9f709bc695487c57888cb39130a7316
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/proxied_method.tpl
@@ -0,0 +1,22 @@
+
+    {modifier} function {reference}{method_name}({arguments_decl}){return_declaration}
+    {
+        $__phpunit_arguments = [{arguments_call}];
+        $__phpunit_count     = func_num_args();
+
+        if ($__phpunit_count > {arguments_count}) {
+            $__phpunit_arguments_tmp = func_get_args();
+
+            for ($__phpunit_i = {arguments_count}; $__phpunit_i < $__phpunit_count; $__phpunit_i++) {
+                $__phpunit_arguments[] = $__phpunit_arguments_tmp[$__phpunit_i];
+            }
+        }
+
+        $this->__phpunit_getInvocationHandler()->invoke(
+            new \PHPUnit\Framework\MockObject\Invocation(
+                '{class_name}', '{method_name}', $__phpunit_arguments, '{return_type}', $this, {clone_arguments}, true
+            )
+        );
+
+        return call_user_func_array(array($this->__phpunit_originalObject, "{method_name}"), $__phpunit_arguments);
+    }
diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/proxied_method_void.tpl b/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/proxied_method_void.tpl
new file mode 100644
index 0000000000000000000000000000000000000000..cce19882649da013003c6fe8abaed2b26d3a0224
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/proxied_method_void.tpl
@@ -0,0 +1,22 @@
+
+    {modifier} function {reference}{method_name}({arguments_decl}){return_declaration}
+    {
+        $__phpunit_arguments = [{arguments_call}];
+        $__phpunit_count     = func_num_args();
+
+        if ($__phpunit_count > {arguments_count}) {
+            $__phpunit_arguments_tmp = func_get_args();
+
+            for ($__phpunit_i = {arguments_count}; $__phpunit_i < $__phpunit_count; $__phpunit_i++) {
+                $__phpunit_arguments[] = $__phpunit_arguments_tmp[$__phpunit_i];
+            }
+        }
+
+        $this->__phpunit_getInvocationHandler()->invoke(
+            new \PHPUnit\Framework\MockObject\Invocation(
+                '{class_name}', '{method_name}', $__phpunit_arguments, '{return_type}', $this, {clone_arguments}, true
+            )
+        );
+
+        call_user_func_array(array($this->__phpunit_originalObject, "{method_name}"), $__phpunit_arguments);
+    }
diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/trait_class.tpl b/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/trait_class.tpl
new file mode 100644
index 0000000000000000000000000000000000000000..a8fe470fdc4fc05539c2219451394e30fac9b661
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/trait_class.tpl
@@ -0,0 +1,6 @@
+declare(strict_types=1);
+
+{prologue}class {class_name}
+{
+    use {trait_name};
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/wsdl_class.tpl b/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/wsdl_class.tpl
new file mode 100644
index 0000000000000000000000000000000000000000..b3100b41417aebc97f4c7de0d7b1362b8bd827aa
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/wsdl_class.tpl
@@ -0,0 +1,9 @@
+declare(strict_types=1);
+
+{namespace}class {class_name} extends \SoapClient
+{
+    public function __construct($wsdl, array $options)
+    {
+        parent::__construct('{wsdl}', $options);
+    }
+{methods}}
diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/wsdl_method.tpl b/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/wsdl_method.tpl
new file mode 100644
index 0000000000000000000000000000000000000000..bb16e763ebac62e93a96f0d52e4ed53dfbc40318
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/wsdl_method.tpl
@@ -0,0 +1,4 @@
+
+    public function {method_name}({arguments})
+    {
+    }
diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/Invocation.php b/vendor/phpunit/phpunit/src/Framework/MockObject/Invocation.php
new file mode 100644
index 0000000000000000000000000000000000000000..f4bbfa1c3aafedd3cf39dbb8e78d8c7844d1b80b
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/MockObject/Invocation.php
@@ -0,0 +1,216 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework\MockObject;
+
+use function array_map;
+use function explode;
+use function get_class;
+use function implode;
+use function is_object;
+use function sprintf;
+use function strpos;
+use function strtolower;
+use function substr;
+use Doctrine\Instantiator\Instantiator;
+use PHPUnit\Framework\SelfDescribing;
+use PHPUnit\Util\Type;
+use SebastianBergmann\Exporter\Exporter;
+use stdClass;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class Invocation implements SelfDescribing
+{
+    /**
+     * @var string
+     */
+    private $className;
+
+    /**
+     * @var string
+     */
+    private $methodName;
+
+    /**
+     * @var array
+     */
+    private $parameters;
+
+    /**
+     * @var string
+     */
+    private $returnType;
+
+    /**
+     * @var bool
+     */
+    private $isReturnTypeNullable = false;
+
+    /**
+     * @var bool
+     */
+    private $proxiedCall;
+
+    /**
+     * @var object
+     */
+    private $object;
+
+    public function __construct(string $className, string $methodName, array $parameters, string $returnType, object $object, bool $cloneObjects = false, bool $proxiedCall = false)
+    {
+        $this->className   = $className;
+        $this->methodName  = $methodName;
+        $this->parameters  = $parameters;
+        $this->object      = $object;
+        $this->proxiedCall = $proxiedCall;
+
+        if (strtolower($methodName) === '__tostring') {
+            $returnType = 'string';
+        }
+
+        if (strpos($returnType, '?') === 0) {
+            $returnType                 = substr($returnType, 1);
+            $this->isReturnTypeNullable = true;
+        }
+
+        $this->returnType = $returnType;
+
+        if (!$cloneObjects) {
+            return;
+        }
+
+        foreach ($this->parameters as $key => $value) {
+            if (is_object($value)) {
+                $this->parameters[$key] = $this->cloneObject($value);
+            }
+        }
+    }
+
+    public function getClassName(): string
+    {
+        return $this->className;
+    }
+
+    public function getMethodName(): string
+    {
+        return $this->methodName;
+    }
+
+    public function getParameters(): array
+    {
+        return $this->parameters;
+    }
+
+    /**
+     * @throws RuntimeException
+     *
+     * @return mixed Mocked return value
+     */
+    public function generateReturnValue()
+    {
+        if ($this->isReturnTypeNullable || $this->proxiedCall) {
+            return;
+        }
+
+        $returnType = $this->returnType;
+
+        if (strpos($returnType, '|') !== false) {
+            $types      = explode('|', $returnType);
+            $returnType = $types[0];
+
+            foreach ($types as $type) {
+                if ($type === 'null') {
+                    return;
+                }
+            }
+        }
+
+        switch (strtolower($returnType)) {
+            case '':
+            case 'void':
+                return;
+
+            case 'string':
+                return '';
+
+            case 'float':
+                return 0.0;
+
+            case 'int':
+                return 0;
+
+            case 'bool':
+                return false;
+
+            case 'array':
+                return [];
+
+            case 'static':
+                return (new Instantiator)->instantiate(get_class($this->object));
+
+            case 'object':
+                return new stdClass;
+
+            case 'callable':
+            case 'closure':
+                return static function (): void {
+                };
+
+            case 'traversable':
+            case 'generator':
+            case 'iterable':
+                $generator = static function (): \Generator {
+                    yield;
+                };
+
+                return $generator();
+
+            case 'mixed':
+                return null;
+
+            default:
+                return (new Generator)->getMock($this->returnType, [], [], '', false);
+        }
+    }
+
+    public function toString(): string
+    {
+        $exporter = new Exporter;
+
+        return sprintf(
+            '%s::%s(%s)%s',
+            $this->className,
+            $this->methodName,
+            implode(
+                ', ',
+                array_map(
+                    [$exporter, 'shortenedExport'],
+                    $this->parameters
+                )
+            ),
+            $this->returnType ? sprintf(': %s', $this->returnType) : ''
+        );
+    }
+
+    public function getObject(): object
+    {
+        return $this->object;
+    }
+
+    private function cloneObject(object $original): object
+    {
+        if (Type::isCloneable($original)) {
+            return clone $original;
+        }
+
+        return $original;
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/InvocationHandler.php b/vendor/phpunit/phpunit/src/Framework/MockObject/InvocationHandler.php
new file mode 100644
index 0000000000000000000000000000000000000000..b9d62610ae7f2ce9e8d9b183ce096887ee3134d1
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/MockObject/InvocationHandler.php
@@ -0,0 +1,186 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework\MockObject;
+
+use function strtolower;
+use Exception;
+use PHPUnit\Framework\MockObject\Builder\InvocationMocker;
+use PHPUnit\Framework\MockObject\Rule\InvocationOrder;
+use Throwable;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class InvocationHandler
+{
+    /**
+     * @var Matcher[]
+     */
+    private $matchers = [];
+
+    /**
+     * @var Matcher[]
+     */
+    private $matcherMap = [];
+
+    /**
+     * @var ConfigurableMethod[]
+     */
+    private $configurableMethods;
+
+    /**
+     * @var bool
+     */
+    private $returnValueGeneration;
+
+    /**
+     * @var Throwable
+     */
+    private $deferredError;
+
+    public function __construct(array $configurableMethods, bool $returnValueGeneration)
+    {
+        $this->configurableMethods   = $configurableMethods;
+        $this->returnValueGeneration = $returnValueGeneration;
+    }
+
+    public function hasMatchers(): bool
+    {
+        foreach ($this->matchers as $matcher) {
+            if ($matcher->hasMatchers()) {
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+    /**
+     * Looks up the match builder with identification $id and returns it.
+     *
+     * @param string $id The identification of the match builder
+     */
+    public function lookupMatcher(string $id): ?Matcher
+    {
+        if (isset($this->matcherMap[$id])) {
+            return $this->matcherMap[$id];
+        }
+
+        return null;
+    }
+
+    /**
+     * Registers a matcher with the identification $id. The matcher can later be
+     * looked up using lookupMatcher() to figure out if it has been invoked.
+     *
+     * @param string  $id      The identification of the matcher
+     * @param Matcher $matcher The builder which is being registered
+     *
+     * @throws MatcherAlreadyRegisteredException
+     */
+    public function registerMatcher(string $id, Matcher $matcher): void
+    {
+        if (isset($this->matcherMap[$id])) {
+            throw new MatcherAlreadyRegisteredException($id);
+        }
+
+        $this->matcherMap[$id] = $matcher;
+    }
+
+    public function expects(InvocationOrder $rule): InvocationMocker
+    {
+        $matcher = new Matcher($rule);
+        $this->addMatcher($matcher);
+
+        return new InvocationMocker(
+            $this,
+            $matcher,
+            ...$this->configurableMethods
+        );
+    }
+
+    /**
+     * @throws Exception
+     * @throws RuntimeException
+     */
+    public function invoke(Invocation $invocation)
+    {
+        $exception      = null;
+        $hasReturnValue = false;
+        $returnValue    = null;
+
+        foreach ($this->matchers as $match) {
+            try {
+                if ($match->matches($invocation)) {
+                    $value = $match->invoked($invocation);
+
+                    if (!$hasReturnValue) {
+                        $returnValue    = $value;
+                        $hasReturnValue = true;
+                    }
+                }
+            } catch (Exception $e) {
+                $exception = $e;
+            }
+        }
+
+        if ($exception !== null) {
+            throw $exception;
+        }
+
+        if ($hasReturnValue) {
+            return $returnValue;
+        }
+
+        if (!$this->returnValueGeneration) {
+            $exception = new ReturnValueNotConfiguredException($invocation);
+
+            if (strtolower($invocation->getMethodName()) === '__tostring') {
+                $this->deferredError = $exception;
+
+                return '';
+            }
+
+            throw $exception;
+        }
+
+        return $invocation->generateReturnValue();
+    }
+
+    public function matches(Invocation $invocation): bool
+    {
+        foreach ($this->matchers as $matcher) {
+            if (!$matcher->matches($invocation)) {
+                return false;
+            }
+        }
+
+        return true;
+    }
+
+    /**
+     * @throws Throwable
+     */
+    public function verify(): void
+    {
+        foreach ($this->matchers as $matcher) {
+            $matcher->verify();
+        }
+
+        if ($this->deferredError) {
+            throw $this->deferredError;
+        }
+    }
+
+    private function addMatcher(Matcher $matcher): void
+    {
+        $this->matchers[] = $matcher;
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/Matcher.php b/vendor/phpunit/phpunit/src/Framework/MockObject/Matcher.php
new file mode 100644
index 0000000000000000000000000000000000000000..a0f8817bdbe04dae182a81ae01111ccdc4cd8347
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/MockObject/Matcher.php
@@ -0,0 +1,272 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework\MockObject;
+
+use function assert;
+use function implode;
+use function sprintf;
+use PHPUnit\Framework\ExpectationFailedException;
+use PHPUnit\Framework\MockObject\Rule\AnyInvokedCount;
+use PHPUnit\Framework\MockObject\Rule\AnyParameters;
+use PHPUnit\Framework\MockObject\Rule\InvocationOrder;
+use PHPUnit\Framework\MockObject\Rule\InvokedCount;
+use PHPUnit\Framework\MockObject\Rule\MethodName;
+use PHPUnit\Framework\MockObject\Rule\ParametersRule;
+use PHPUnit\Framework\MockObject\Stub\Stub;
+use PHPUnit\Framework\TestFailure;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class Matcher
+{
+    /**
+     * @var InvocationOrder
+     */
+    private $invocationRule;
+
+    /**
+     * @var mixed
+     */
+    private $afterMatchBuilderId;
+
+    /**
+     * @var bool
+     */
+    private $afterMatchBuilderIsInvoked = false;
+
+    /**
+     * @var MethodName
+     */
+    private $methodNameRule;
+
+    /**
+     * @var ParametersRule
+     */
+    private $parametersRule;
+
+    /**
+     * @var Stub
+     */
+    private $stub;
+
+    public function __construct(InvocationOrder $rule)
+    {
+        $this->invocationRule = $rule;
+    }
+
+    public function hasMatchers(): bool
+    {
+        return !$this->invocationRule instanceof AnyInvokedCount;
+    }
+
+    public function hasMethodNameRule(): bool
+    {
+        return $this->methodNameRule !== null;
+    }
+
+    public function getMethodNameRule(): MethodName
+    {
+        return $this->methodNameRule;
+    }
+
+    public function setMethodNameRule(MethodName $rule): void
+    {
+        $this->methodNameRule = $rule;
+    }
+
+    public function hasParametersRule(): bool
+    {
+        return $this->parametersRule !== null;
+    }
+
+    public function setParametersRule(ParametersRule $rule): void
+    {
+        $this->parametersRule = $rule;
+    }
+
+    public function setStub(Stub $stub): void
+    {
+        $this->stub = $stub;
+    }
+
+    public function setAfterMatchBuilderId(string $id): void
+    {
+        $this->afterMatchBuilderId = $id;
+    }
+
+    /**
+     * @throws ExpectationFailedException
+     * @throws MatchBuilderNotFoundException
+     * @throws MethodNameNotConfiguredException
+     * @throws RuntimeException
+     */
+    public function invoked(Invocation $invocation)
+    {
+        if ($this->methodNameRule === null) {
+            throw new MethodNameNotConfiguredException;
+        }
+
+        if ($this->afterMatchBuilderId !== null) {
+            $matcher = $invocation->getObject()
+                                  ->__phpunit_getInvocationHandler()
+                                  ->lookupMatcher($this->afterMatchBuilderId);
+
+            if (!$matcher) {
+                throw new MatchBuilderNotFoundException($this->afterMatchBuilderId);
+            }
+
+            assert($matcher instanceof self);
+
+            if ($matcher->invocationRule->hasBeenInvoked()) {
+                $this->afterMatchBuilderIsInvoked = true;
+            }
+        }
+
+        $this->invocationRule->invoked($invocation);
+
+        try {
+            if ($this->parametersRule !== null) {
+                $this->parametersRule->apply($invocation);
+            }
+        } catch (ExpectationFailedException $e) {
+            throw new ExpectationFailedException(
+                sprintf(
+                    "Expectation failed for %s when %s\n%s",
+                    $this->methodNameRule->toString(),
+                    $this->invocationRule->toString(),
+                    $e->getMessage()
+                ),
+                $e->getComparisonFailure()
+            );
+        }
+
+        if ($this->stub) {
+            return $this->stub->invoke($invocation);
+        }
+
+        return $invocation->generateReturnValue();
+    }
+
+    /**
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws ExpectationFailedException
+     * @throws MatchBuilderNotFoundException
+     * @throws MethodNameNotConfiguredException
+     * @throws RuntimeException
+     */
+    public function matches(Invocation $invocation): bool
+    {
+        if ($this->afterMatchBuilderId !== null) {
+            $matcher = $invocation->getObject()
+                                  ->__phpunit_getInvocationHandler()
+                                  ->lookupMatcher($this->afterMatchBuilderId);
+
+            if (!$matcher) {
+                throw new MatchBuilderNotFoundException($this->afterMatchBuilderId);
+            }
+
+            assert($matcher instanceof self);
+
+            if (!$matcher->invocationRule->hasBeenInvoked()) {
+                return false;
+            }
+        }
+
+        if ($this->methodNameRule === null) {
+            throw new MethodNameNotConfiguredException;
+        }
+
+        if (!$this->invocationRule->matches($invocation)) {
+            return false;
+        }
+
+        try {
+            if (!$this->methodNameRule->matches($invocation)) {
+                return false;
+            }
+        } catch (ExpectationFailedException $e) {
+            throw new ExpectationFailedException(
+                sprintf(
+                    "Expectation failed for %s when %s\n%s",
+                    $this->methodNameRule->toString(),
+                    $this->invocationRule->toString(),
+                    $e->getMessage()
+                ),
+                $e->getComparisonFailure()
+            );
+        }
+
+        return true;
+    }
+
+    /**
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws ExpectationFailedException
+     * @throws MethodNameNotConfiguredException
+     */
+    public function verify(): void
+    {
+        if ($this->methodNameRule === null) {
+            throw new MethodNameNotConfiguredException;
+        }
+
+        try {
+            $this->invocationRule->verify();
+
+            if ($this->parametersRule === null) {
+                $this->parametersRule = new AnyParameters;
+            }
+
+            $invocationIsAny   = $this->invocationRule instanceof AnyInvokedCount;
+            $invocationIsNever = $this->invocationRule instanceof InvokedCount && $this->invocationRule->isNever();
+
+            if (!$invocationIsAny && !$invocationIsNever) {
+                $this->parametersRule->verify();
+            }
+        } catch (ExpectationFailedException $e) {
+            throw new ExpectationFailedException(
+                sprintf(
+                    "Expectation failed for %s when %s.\n%s",
+                    $this->methodNameRule->toString(),
+                    $this->invocationRule->toString(),
+                    TestFailure::exceptionToString($e)
+                )
+            );
+        }
+    }
+
+    public function toString(): string
+    {
+        $list = [];
+
+        if ($this->invocationRule !== null) {
+            $list[] = $this->invocationRule->toString();
+        }
+
+        if ($this->methodNameRule !== null) {
+            $list[] = 'where ' . $this->methodNameRule->toString();
+        }
+
+        if ($this->parametersRule !== null) {
+            $list[] = 'and ' . $this->parametersRule->toString();
+        }
+
+        if ($this->afterMatchBuilderId !== null) {
+            $list[] = 'after ' . $this->afterMatchBuilderId;
+        }
+
+        if ($this->stub !== null) {
+            $list[] = 'will ' . $this->stub->toString();
+        }
+
+        return implode(' ', $list);
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/MethodNameConstraint.php b/vendor/phpunit/phpunit/src/Framework/MockObject/MethodNameConstraint.php
new file mode 100644
index 0000000000000000000000000000000000000000..3082ab384c971c72bd6fbf06c24958d5b52019dd
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/MockObject/MethodNameConstraint.php
@@ -0,0 +1,48 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework\MockObject;
+
+use function is_string;
+use function sprintf;
+use function strtolower;
+use PHPUnit\Framework\Constraint\Constraint;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class MethodNameConstraint extends Constraint
+{
+    /**
+     * @var string
+     */
+    private $methodName;
+
+    public function __construct(string $methodName)
+    {
+        $this->methodName = $methodName;
+    }
+
+    public function toString(): string
+    {
+        return sprintf(
+            'is "%s"',
+            $this->methodName
+        );
+    }
+
+    protected function matches($other): bool
+    {
+        if (!is_string($other)) {
+            return false;
+        }
+
+        return strtolower($this->methodName) === strtolower($other);
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/MockBuilder.php b/vendor/phpunit/phpunit/src/Framework/MockObject/MockBuilder.php
new file mode 100644
index 0000000000000000000000000000000000000000..aec32a2d443d5b2979d539301817a0777876aed9
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/MockObject/MockBuilder.php
@@ -0,0 +1,516 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework\MockObject;
+
+use function array_diff;
+use function array_merge;
+use PHPUnit\Framework\TestCase;
+use ReflectionClass;
+
+/**
+ * @psalm-template MockedType
+ *
+ * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+ */
+final class MockBuilder
+{
+    /**
+     * @var TestCase
+     */
+    private $testCase;
+
+    /**
+     * @var string
+     */
+    private $type;
+
+    /**
+     * @var null|string[]
+     */
+    private $methods = [];
+
+    /**
+     * @var bool
+     */
+    private $emptyMethodsArray = false;
+
+    /**
+     * @var string
+     */
+    private $mockClassName = '';
+
+    /**
+     * @var array
+     */
+    private $constructorArgs = [];
+
+    /**
+     * @var bool
+     */
+    private $originalConstructor = true;
+
+    /**
+     * @var bool
+     */
+    private $originalClone = true;
+
+    /**
+     * @var bool
+     */
+    private $autoload = true;
+
+    /**
+     * @var bool
+     */
+    private $cloneArguments = false;
+
+    /**
+     * @var bool
+     */
+    private $callOriginalMethods = false;
+
+    /**
+     * @var ?object
+     */
+    private $proxyTarget;
+
+    /**
+     * @var bool
+     */
+    private $allowMockingUnknownTypes = true;
+
+    /**
+     * @var bool
+     */
+    private $returnValueGeneration = true;
+
+    /**
+     * @var Generator
+     */
+    private $generator;
+
+    /**
+     * @param string|string[] $type
+     *
+     * @psalm-param class-string<MockedType>|string|string[] $type
+     */
+    public function __construct(TestCase $testCase, $type)
+    {
+        $this->testCase  = $testCase;
+        $this->type      = $type;
+        $this->generator = new Generator;
+    }
+
+    /**
+     * Creates a mock object using a fluent interface.
+     *
+     * @throws \PHPUnit\Framework\InvalidArgumentException
+     * @throws ClassAlreadyExistsException
+     * @throws ClassIsFinalException
+     * @throws DuplicateMethodException
+     * @throws InvalidMethodNameException
+     * @throws OriginalConstructorInvocationRequiredException
+     * @throws ReflectionException
+     * @throws RuntimeException
+     * @throws UnknownTypeException
+     *
+     * @psalm-return MockObject&MockedType
+     */
+    public function getMock(): MockObject
+    {
+        $object = $this->generator->getMock(
+            $this->type,
+            !$this->emptyMethodsArray ? $this->methods : null,
+            $this->constructorArgs,
+            $this->mockClassName,
+            $this->originalConstructor,
+            $this->originalClone,
+            $this->autoload,
+            $this->cloneArguments,
+            $this->callOriginalMethods,
+            $this->proxyTarget,
+            $this->allowMockingUnknownTypes,
+            $this->returnValueGeneration
+        );
+
+        $this->testCase->registerMockObject($object);
+
+        return $object;
+    }
+
+    /**
+     * Creates a mock object for an abstract class using a fluent interface.
+     *
+     * @psalm-return MockObject&MockedType
+     *
+     * @throws \PHPUnit\Framework\Exception
+     * @throws ReflectionException
+     * @throws RuntimeException
+     */
+    public function getMockForAbstractClass(): MockObject
+    {
+        $object = $this->generator->getMockForAbstractClass(
+            $this->type,
+            $this->constructorArgs,
+            $this->mockClassName,
+            $this->originalConstructor,
+            $this->originalClone,
+            $this->autoload,
+            $this->methods,
+            $this->cloneArguments
+        );
+
+        $this->testCase->registerMockObject($object);
+
+        return $object;
+    }
+
+    /**
+     * Creates a mock object for a trait using a fluent interface.
+     *
+     * @psalm-return MockObject&MockedType
+     *
+     * @throws \PHPUnit\Framework\Exception
+     * @throws ReflectionException
+     * @throws RuntimeException
+     */
+    public function getMockForTrait(): MockObject
+    {
+        $object = $this->generator->getMockForTrait(
+            $this->type,
+            $this->constructorArgs,
+            $this->mockClassName,
+            $this->originalConstructor,
+            $this->originalClone,
+            $this->autoload,
+            $this->methods,
+            $this->cloneArguments
+        );
+
+        $this->testCase->registerMockObject($object);
+
+        return $object;
+    }
+
+    /**
+     * Specifies the subset of methods to mock. Default is to mock none of them.
+     *
+     * @deprecated https://github.com/sebastianbergmann/phpunit/pull/3687
+     *
+     * @return $this
+     */
+    public function setMethods(?array $methods = null): self
+    {
+        if ($methods === null) {
+            $this->methods = $methods;
+        } else {
+            $this->methods = array_merge($this->methods ?? [], $methods);
+        }
+
+        return $this;
+    }
+
+    /**
+     * Specifies the subset of methods to mock, requiring each to exist in the class.
+     *
+     * @param string[] $methods
+     *
+     * @throws CannotUseOnlyMethodsException
+     * @throws ReflectionException
+     *
+     * @return $this
+     */
+    public function onlyMethods(array $methods): self
+    {
+        if (empty($methods)) {
+            $this->emptyMethodsArray = true;
+
+            return $this;
+        }
+
+        try {
+            $reflector = new ReflectionClass($this->type);
+            // @codeCoverageIgnoreStart
+        } catch (\ReflectionException $e) {
+            throw new ReflectionException(
+                $e->getMessage(),
+                (int) $e->getCode(),
+                $e
+            );
+        }
+        // @codeCoverageIgnoreEnd
+
+        foreach ($methods as $method) {
+            if (!$reflector->hasMethod($method)) {
+                throw new CannotUseOnlyMethodsException($this->type, $method);
+            }
+        }
+
+        $this->methods = array_merge($this->methods ?? [], $methods);
+
+        return $this;
+    }
+
+    /**
+     * Specifies methods that don't exist in the class which you want to mock.
+     *
+     * @param string[] $methods
+     *
+     * @throws CannotUseAddMethodsException
+     * @throws ReflectionException
+     * @throws RuntimeException
+     *
+     * @return $this
+     */
+    public function addMethods(array $methods): self
+    {
+        if (empty($methods)) {
+            $this->emptyMethodsArray = true;
+
+            return $this;
+        }
+
+        try {
+            $reflector = new ReflectionClass($this->type);
+            // @codeCoverageIgnoreStart
+        } catch (\ReflectionException $e) {
+            throw new ReflectionException(
+                $e->getMessage(),
+                (int) $e->getCode(),
+                $e
+            );
+        }
+        // @codeCoverageIgnoreEnd
+
+        foreach ($methods as $method) {
+            if ($reflector->hasMethod($method)) {
+                throw new CannotUseAddMethodsException($this->type, $method);
+            }
+        }
+
+        $this->methods = array_merge($this->methods ?? [], $methods);
+
+        return $this;
+    }
+
+    /**
+     * Specifies the subset of methods to not mock. Default is to mock all of them.
+     *
+     * @deprecated https://github.com/sebastianbergmann/phpunit/pull/3687
+     *
+     * @throws ReflectionException
+     */
+    public function setMethodsExcept(array $methods = []): self
+    {
+        return $this->setMethods(
+            array_diff(
+                $this->generator->getClassMethods($this->type),
+                $methods
+            )
+        );
+    }
+
+    /**
+     * Specifies the arguments for the constructor.
+     *
+     * @return $this
+     */
+    public function setConstructorArgs(array $args): self
+    {
+        $this->constructorArgs = $args;
+
+        return $this;
+    }
+
+    /**
+     * Specifies the name for the mock class.
+     *
+     * @return $this
+     */
+    public function setMockClassName(string $name): self
+    {
+        $this->mockClassName = $name;
+
+        return $this;
+    }
+
+    /**
+     * Disables the invocation of the original constructor.
+     *
+     * @return $this
+     */
+    public function disableOriginalConstructor(): self
+    {
+        $this->originalConstructor = false;
+
+        return $this;
+    }
+
+    /**
+     * Enables the invocation of the original constructor.
+     *
+     * @return $this
+     */
+    public function enableOriginalConstructor(): self
+    {
+        $this->originalConstructor = true;
+
+        return $this;
+    }
+
+    /**
+     * Disables the invocation of the original clone constructor.
+     *
+     * @return $this
+     */
+    public function disableOriginalClone(): self
+    {
+        $this->originalClone = false;
+
+        return $this;
+    }
+
+    /**
+     * Enables the invocation of the original clone constructor.
+     *
+     * @return $this
+     */
+    public function enableOriginalClone(): self
+    {
+        $this->originalClone = true;
+
+        return $this;
+    }
+
+    /**
+     * Disables the use of class autoloading while creating the mock object.
+     *
+     * @return $this
+     */
+    public function disableAutoload(): self
+    {
+        $this->autoload = false;
+
+        return $this;
+    }
+
+    /**
+     * Enables the use of class autoloading while creating the mock object.
+     *
+     * @return $this
+     */
+    public function enableAutoload(): self
+    {
+        $this->autoload = true;
+
+        return $this;
+    }
+
+    /**
+     * Disables the cloning of arguments passed to mocked methods.
+     *
+     * @return $this
+     */
+    public function disableArgumentCloning(): self
+    {
+        $this->cloneArguments = false;
+
+        return $this;
+    }
+
+    /**
+     * Enables the cloning of arguments passed to mocked methods.
+     *
+     * @return $this
+     */
+    public function enableArgumentCloning(): self
+    {
+        $this->cloneArguments = true;
+
+        return $this;
+    }
+
+    /**
+     * Enables the invocation of the original methods.
+     *
+     * @return $this
+     */
+    public function enableProxyingToOriginalMethods(): self
+    {
+        $this->callOriginalMethods = true;
+
+        return $this;
+    }
+
+    /**
+     * Disables the invocation of the original methods.
+     *
+     * @return $this
+     */
+    public function disableProxyingToOriginalMethods(): self
+    {
+        $this->callOriginalMethods = false;
+        $this->proxyTarget         = null;
+
+        return $this;
+    }
+
+    /**
+     * Sets the proxy target.
+     *
+     * @return $this
+     */
+    public function setProxyTarget(object $object): self
+    {
+        $this->proxyTarget = $object;
+
+        return $this;
+    }
+
+    /**
+     * @return $this
+     */
+    public function allowMockingUnknownTypes(): self
+    {
+        $this->allowMockingUnknownTypes = true;
+
+        return $this;
+    }
+
+    /**
+     * @return $this
+     */
+    public function disallowMockingUnknownTypes(): self
+    {
+        $this->allowMockingUnknownTypes = false;
+
+        return $this;
+    }
+
+    /**
+     * @return $this
+     */
+    public function enableAutoReturnValueGeneration(): self
+    {
+        $this->returnValueGeneration = true;
+
+        return $this;
+    }
+
+    /**
+     * @return $this
+     */
+    public function disableAutoReturnValueGeneration(): self
+    {
+        $this->returnValueGeneration = false;
+
+        return $this;
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/MockClass.php b/vendor/phpunit/phpunit/src/Framework/MockObject/MockClass.php
new file mode 100644
index 0000000000000000000000000000000000000000..253d7846050fa4c6a903b87e6b0c34bbce8b9615
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/MockObject/MockClass.php
@@ -0,0 +1,69 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework\MockObject;
+
+use function call_user_func;
+use function class_exists;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class MockClass implements MockType
+{
+    /**
+     * @var string
+     */
+    private $classCode;
+
+    /**
+     * @var class-string
+     */
+    private $mockName;
+
+    /**
+     * @var ConfigurableMethod[]
+     */
+    private $configurableMethods;
+
+    /**
+     * @psalm-param class-string $mockName
+     */
+    public function __construct(string $classCode, string $mockName, array $configurableMethods)
+    {
+        $this->classCode           = $classCode;
+        $this->mockName            = $mockName;
+        $this->configurableMethods = $configurableMethods;
+    }
+
+    /**
+     * @psalm-return class-string
+     */
+    public function generate(): string
+    {
+        if (!class_exists($this->mockName, false)) {
+            eval($this->classCode);
+
+            call_user_func(
+                [
+                    $this->mockName,
+                    '__phpunit_initConfigurableMethods',
+                ],
+                ...$this->configurableMethods
+            );
+        }
+
+        return $this->mockName;
+    }
+
+    public function getClassCode(): string
+    {
+        return $this->classCode;
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/MockMethod.php b/vendor/phpunit/phpunit/src/Framework/MockObject/MockMethod.php
new file mode 100644
index 0000000000000000000000000000000000000000..5e02cae5f0fef25b81c5d9c088e060902babaf12
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/MockObject/MockMethod.php
@@ -0,0 +1,398 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework\MockObject;
+
+use const DIRECTORY_SEPARATOR;
+use function implode;
+use function is_string;
+use function preg_match;
+use function preg_replace;
+use function sprintf;
+use function substr_count;
+use function trim;
+use function var_export;
+use ReflectionMethod;
+use ReflectionNamedType;
+use ReflectionParameter;
+use ReflectionUnionType;
+use SebastianBergmann\Template\Exception as TemplateException;
+use SebastianBergmann\Template\Template;
+use SebastianBergmann\Type\ReflectionMapper;
+use SebastianBergmann\Type\Type;
+use SebastianBergmann\Type\UnknownType;
+use SebastianBergmann\Type\VoidType;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class MockMethod
+{
+    /**
+     * @var Template[]
+     */
+    private static $templates = [];
+
+    /**
+     * @var string
+     */
+    private $className;
+
+    /**
+     * @var string
+     */
+    private $methodName;
+
+    /**
+     * @var bool
+     */
+    private $cloneArguments;
+
+    /**
+     * @var string string
+     */
+    private $modifier;
+
+    /**
+     * @var string
+     */
+    private $argumentsForDeclaration;
+
+    /**
+     * @var string
+     */
+    private $argumentsForCall;
+
+    /**
+     * @var Type
+     */
+    private $returnType;
+
+    /**
+     * @var string
+     */
+    private $reference;
+
+    /**
+     * @var bool
+     */
+    private $callOriginalMethod;
+
+    /**
+     * @var bool
+     */
+    private $static;
+
+    /**
+     * @var ?string
+     */
+    private $deprecation;
+
+    /**
+     * @throws ReflectionException
+     * @throws RuntimeException
+     */
+    public static function fromReflection(ReflectionMethod $method, bool $callOriginalMethod, bool $cloneArguments): self
+    {
+        if ($method->isPrivate()) {
+            $modifier = 'private';
+        } elseif ($method->isProtected()) {
+            $modifier = 'protected';
+        } else {
+            $modifier = 'public';
+        }
+
+        if ($method->isStatic()) {
+            $modifier .= ' static';
+        }
+
+        if ($method->returnsReference()) {
+            $reference = '&';
+        } else {
+            $reference = '';
+        }
+
+        $docComment = $method->getDocComment();
+
+        if (is_string($docComment) &&
+            preg_match('#\*[ \t]*+@deprecated[ \t]*+(.*?)\r?+\n[ \t]*+\*(?:[ \t]*+@|/$)#s', $docComment, $deprecation)) {
+            $deprecation = trim(preg_replace('#[ \t]*\r?\n[ \t]*+\*[ \t]*+#', ' ', $deprecation[1]));
+        } else {
+            $deprecation = null;
+        }
+
+        return new self(
+            $method->getDeclaringClass()->getName(),
+            $method->getName(),
+            $cloneArguments,
+            $modifier,
+            self::getMethodParametersForDeclaration($method),
+            self::getMethodParametersForCall($method),
+            (new ReflectionMapper)->fromMethodReturnType($method),
+            $reference,
+            $callOriginalMethod,
+            $method->isStatic(),
+            $deprecation
+        );
+    }
+
+    public static function fromName(string $fullClassName, string $methodName, bool $cloneArguments): self
+    {
+        return new self(
+            $fullClassName,
+            $methodName,
+            $cloneArguments,
+            'public',
+            '',
+            '',
+            new UnknownType,
+            '',
+            false,
+            false,
+            null
+        );
+    }
+
+    public function __construct(string $className, string $methodName, bool $cloneArguments, string $modifier, string $argumentsForDeclaration, string $argumentsForCall, Type $returnType, string $reference, bool $callOriginalMethod, bool $static, ?string $deprecation)
+    {
+        $this->className               = $className;
+        $this->methodName              = $methodName;
+        $this->cloneArguments          = $cloneArguments;
+        $this->modifier                = $modifier;
+        $this->argumentsForDeclaration = $argumentsForDeclaration;
+        $this->argumentsForCall        = $argumentsForCall;
+        $this->returnType              = $returnType;
+        $this->reference               = $reference;
+        $this->callOriginalMethod      = $callOriginalMethod;
+        $this->static                  = $static;
+        $this->deprecation             = $deprecation;
+    }
+
+    public function getName(): string
+    {
+        return $this->methodName;
+    }
+
+    /**
+     * @throws RuntimeException
+     */
+    public function generateCode(): string
+    {
+        if ($this->static) {
+            $templateFile = 'mocked_static_method.tpl';
+        } elseif ($this->returnType instanceof VoidType) {
+            $templateFile = sprintf(
+                '%s_method_void.tpl',
+                $this->callOriginalMethod ? 'proxied' : 'mocked'
+            );
+        } else {
+            $templateFile = sprintf(
+                '%s_method.tpl',
+                $this->callOriginalMethod ? 'proxied' : 'mocked'
+            );
+        }
+
+        $deprecation = $this->deprecation;
+
+        if (null !== $this->deprecation) {
+            $deprecation         = "The {$this->className}::{$this->methodName} method is deprecated ({$this->deprecation}).";
+            $deprecationTemplate = $this->getTemplate('deprecation.tpl');
+
+            $deprecationTemplate->setVar(
+                [
+                    'deprecation' => var_export($deprecation, true),
+                ]
+            );
+
+            $deprecation = $deprecationTemplate->render();
+        }
+
+        $template = $this->getTemplate($templateFile);
+
+        $template->setVar(
+            [
+                'arguments_decl'     => $this->argumentsForDeclaration,
+                'arguments_call'     => $this->argumentsForCall,
+                'return_declaration' => !empty($this->returnType->asString()) ? (': ' . $this->returnType->asString()) : '',
+                'return_type'        => $this->returnType->asString(),
+                'arguments_count'    => !empty($this->argumentsForCall) ? substr_count($this->argumentsForCall, ',') + 1 : 0,
+                'class_name'         => $this->className,
+                'method_name'        => $this->methodName,
+                'modifier'           => $this->modifier,
+                'reference'          => $this->reference,
+                'clone_arguments'    => $this->cloneArguments ? 'true' : 'false',
+                'deprecation'        => $deprecation,
+            ]
+        );
+
+        return $template->render();
+    }
+
+    public function getReturnType(): Type
+    {
+        return $this->returnType;
+    }
+
+    /**
+     * @throws RuntimeException
+     */
+    private function getTemplate(string $template): Template
+    {
+        $filename = __DIR__ . DIRECTORY_SEPARATOR . 'Generator' . DIRECTORY_SEPARATOR . $template;
+
+        if (!isset(self::$templates[$filename])) {
+            try {
+                self::$templates[$filename] = new Template($filename);
+            } catch (TemplateException $e) {
+                throw new RuntimeException(
+                    $e->getMessage(),
+                    (int) $e->getCode(),
+                    $e
+                );
+            }
+        }
+
+        return self::$templates[$filename];
+    }
+
+    /**
+     * Returns the parameters of a function or method.
+     *
+     * @throws RuntimeException
+     */
+    private static function getMethodParametersForDeclaration(ReflectionMethod $method): string
+    {
+        $parameters = [];
+
+        foreach ($method->getParameters() as $i => $parameter) {
+            $name = '$' . $parameter->getName();
+
+            /* Note: PHP extensions may use empty names for reference arguments
+             * or "..." for methods taking a variable number of arguments.
+             */
+            if ($name === '$' || $name === '$...') {
+                $name = '$arg' . $i;
+            }
+
+            $nullable        = '';
+            $default         = '';
+            $reference       = '';
+            $typeDeclaration = '';
+            $type            = null;
+            $typeName        = null;
+
+            if ($parameter->hasType()) {
+                $type = $parameter->getType();
+
+                if ($type instanceof ReflectionNamedType) {
+                    $typeName = $type->getName();
+                }
+            }
+
+            if ($parameter->isVariadic()) {
+                $name = '...' . $name;
+            } elseif ($parameter->isDefaultValueAvailable()) {
+                $default = ' = ' . self::exportDefaultValue($parameter);
+            } elseif ($parameter->isOptional()) {
+                $default = ' = null';
+            }
+
+            if ($type !== null) {
+                if ($typeName !== 'mixed' && $parameter->allowsNull() && !$type instanceof ReflectionUnionType) {
+                    $nullable = '?';
+                }
+
+                if ($typeName === 'self') {
+                    $typeDeclaration = $method->getDeclaringClass()->getName() . ' ';
+                } elseif ($typeName !== null) {
+                    $typeDeclaration = $typeName . ' ';
+                } elseif ($type instanceof ReflectionUnionType) {
+                    $typeDeclaration = self::unionTypeAsString(
+                        $type,
+                        $method->getDeclaringClass()->getName()
+                    );
+                }
+            }
+
+            if ($parameter->isPassedByReference()) {
+                $reference = '&';
+            }
+
+            $parameters[] = $nullable . $typeDeclaration . $reference . $name . $default;
+        }
+
+        return implode(', ', $parameters);
+    }
+
+    /**
+     * Returns the parameters of a function or method.
+     *
+     * @throws ReflectionException
+     */
+    private static function getMethodParametersForCall(ReflectionMethod $method): string
+    {
+        $parameters = [];
+
+        foreach ($method->getParameters() as $i => $parameter) {
+            $name = '$' . $parameter->getName();
+
+            /* Note: PHP extensions may use empty names for reference arguments
+             * or "..." for methods taking a variable number of arguments.
+             */
+            if ($name === '$' || $name === '$...') {
+                $name = '$arg' . $i;
+            }
+
+            if ($parameter->isVariadic()) {
+                continue;
+            }
+
+            if ($parameter->isPassedByReference()) {
+                $parameters[] = '&' . $name;
+            } else {
+                $parameters[] = $name;
+            }
+        }
+
+        return implode(', ', $parameters);
+    }
+
+    /**
+     * @throws ReflectionException
+     */
+    private static function exportDefaultValue(ReflectionParameter $parameter): string
+    {
+        try {
+            return (string) var_export($parameter->getDefaultValue(), true);
+            // @codeCoverageIgnoreStart
+        } catch (\ReflectionException $e) {
+            throw new ReflectionException(
+                $e->getMessage(),
+                (int) $e->getCode(),
+                $e
+            );
+        }
+        // @codeCoverageIgnoreEnd
+    }
+
+    private static function unionTypeAsString(ReflectionUnionType $union, string $self): string
+    {
+        $types = [];
+
+        foreach ($union->getTypes() as $type) {
+            if ((string) $type === 'self') {
+                $types[] = $self;
+            } else {
+                $types[] = $type;
+            }
+        }
+
+        return implode('|', $types) . ' ';
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/MockMethodSet.php b/vendor/phpunit/phpunit/src/Framework/MockObject/MockMethodSet.php
new file mode 100644
index 0000000000000000000000000000000000000000..1c78963c08b62bb1903c6a1ded0b4c7bce1cc90d
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/MockObject/MockMethodSet.php
@@ -0,0 +1,45 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework\MockObject;
+
+use function array_key_exists;
+use function array_values;
+use function strtolower;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class MockMethodSet
+{
+    /**
+     * @var MockMethod[]
+     */
+    private $methods = [];
+
+    public function addMethods(MockMethod ...$methods): void
+    {
+        foreach ($methods as $method) {
+            $this->methods[strtolower($method->getName())] = $method;
+        }
+    }
+
+    /**
+     * @return MockMethod[]
+     */
+    public function asArray(): array
+    {
+        return array_values($this->methods);
+    }
+
+    public function hasMethod(string $methodName): bool
+    {
+        return array_key_exists(strtolower($methodName), $this->methods);
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/MockObject.php b/vendor/phpunit/phpunit/src/Framework/MockObject/MockObject.php
new file mode 100644
index 0000000000000000000000000000000000000000..094decf431f829e90da45bd76a73238707ab10e6
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/MockObject/MockObject.php
@@ -0,0 +1,27 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework\MockObject;
+
+use PHPUnit\Framework\MockObject\Builder\InvocationMocker as BuilderInvocationMocker;
+use PHPUnit\Framework\MockObject\Rule\InvocationOrder;
+
+/**
+ * @method BuilderInvocationMocker method($constraint)
+ *
+ * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+ */
+interface MockObject extends Stub
+{
+    public function __phpunit_setOriginalObject($originalObject): void;
+
+    public function __phpunit_verify(bool $unsetInvocationMocker = true): void;
+
+    public function expects(InvocationOrder $invocationRule): BuilderInvocationMocker;
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/MockTrait.php b/vendor/phpunit/phpunit/src/Framework/MockObject/MockTrait.php
new file mode 100644
index 0000000000000000000000000000000000000000..7c326988f14d0433b59d038755287b640e5fe7ce
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/MockObject/MockTrait.php
@@ -0,0 +1,54 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework\MockObject;
+
+use function class_exists;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class MockTrait implements MockType
+{
+    /**
+     * @var string
+     */
+    private $classCode;
+
+    /**
+     * @var class-string
+     */
+    private $mockName;
+
+    /**
+     * @psalm-param class-string $mockName
+     */
+    public function __construct(string $classCode, string $mockName)
+    {
+        $this->classCode = $classCode;
+        $this->mockName  = $mockName;
+    }
+
+    /**
+     * @psalm-return class-string
+     */
+    public function generate(): string
+    {
+        if (!class_exists($this->mockName, false)) {
+            eval($this->classCode);
+        }
+
+        return $this->mockName;
+    }
+
+    public function getClassCode(): string
+    {
+        return $this->classCode;
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/MockType.php b/vendor/phpunit/phpunit/src/Framework/MockObject/MockType.php
new file mode 100644
index 0000000000000000000000000000000000000000..6a03fb51a9d4044d97dc215884d97fc77645bb45
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/MockObject/MockType.php
@@ -0,0 +1,21 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework\MockObject;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+interface MockType
+{
+    /**
+     * @psalm-return class-string
+     */
+    public function generate(): string;
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/Rule/AnyInvokedCount.php b/vendor/phpunit/phpunit/src/Framework/MockObject/Rule/AnyInvokedCount.php
new file mode 100644
index 0000000000000000000000000000000000000000..f93e5686bc45902add097fb81ed21a7b65fcb6aa
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/MockObject/Rule/AnyInvokedCount.php
@@ -0,0 +1,36 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework\MockObject\Rule;
+
+use PHPUnit\Framework\MockObject\Invocation as BaseInvocation;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class AnyInvokedCount extends InvocationOrder
+{
+    public function toString(): string
+    {
+        return 'invoked zero or more times';
+    }
+
+    public function verify(): void
+    {
+    }
+
+    public function matches(BaseInvocation $invocation): bool
+    {
+        return true;
+    }
+
+    protected function invokedDo(BaseInvocation $invocation): void
+    {
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/Rule/AnyParameters.php b/vendor/phpunit/phpunit/src/Framework/MockObject/Rule/AnyParameters.php
new file mode 100644
index 0000000000000000000000000000000000000000..61de788786b48179c9434aae3886da8779c9fe39
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/MockObject/Rule/AnyParameters.php
@@ -0,0 +1,31 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework\MockObject\Rule;
+
+use PHPUnit\Framework\MockObject\Invocation as BaseInvocation;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class AnyParameters implements ParametersRule
+{
+    public function toString(): string
+    {
+        return 'with any parameters';
+    }
+
+    public function apply(BaseInvocation $invocation): void
+    {
+    }
+
+    public function verify(): void
+    {
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/Rule/ConsecutiveParameters.php b/vendor/phpunit/phpunit/src/Framework/MockObject/Rule/ConsecutiveParameters.php
new file mode 100644
index 0000000000000000000000000000000000000000..6025c0a160438c8461b7b2b649c1d0c5988cb0ef
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/MockObject/Rule/ConsecutiveParameters.php
@@ -0,0 +1,130 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework\MockObject\Rule;
+
+use function count;
+use function gettype;
+use function is_iterable;
+use function sprintf;
+use PHPUnit\Framework\Constraint\Constraint;
+use PHPUnit\Framework\Constraint\IsEqual;
+use PHPUnit\Framework\ExpectationFailedException;
+use PHPUnit\Framework\InvalidParameterGroupException;
+use PHPUnit\Framework\MockObject\Invocation as BaseInvocation;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class ConsecutiveParameters implements ParametersRule
+{
+    /**
+     * @var array
+     */
+    private $parameterGroups = [];
+
+    /**
+     * @var array
+     */
+    private $invocations = [];
+
+    /**
+     * @throws \PHPUnit\Framework\Exception
+     */
+    public function __construct(array $parameterGroups)
+    {
+        foreach ($parameterGroups as $index => $parameters) {
+            if (!is_iterable($parameters)) {
+                throw new InvalidParameterGroupException(
+                    sprintf(
+                        'Parameter group #%d must be an array or Traversable, got %s',
+                        $index,
+                        gettype($parameters)
+                    )
+                );
+            }
+
+            foreach ($parameters as $parameter) {
+                if (!$parameter instanceof Constraint) {
+                    $parameter = new IsEqual($parameter);
+                }
+
+                $this->parameterGroups[$index][] = $parameter;
+            }
+        }
+    }
+
+    public function toString(): string
+    {
+        return 'with consecutive parameters';
+    }
+
+    /**
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws ExpectationFailedException
+     */
+    public function apply(BaseInvocation $invocation): void
+    {
+        $this->invocations[] = $invocation;
+        $callIndex           = count($this->invocations) - 1;
+
+        $this->verifyInvocation($invocation, $callIndex);
+    }
+
+    /**
+     * @throws \PHPUnit\Framework\ExpectationFailedException
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     */
+    public function verify(): void
+    {
+        foreach ($this->invocations as $callIndex => $invocation) {
+            $this->verifyInvocation($invocation, $callIndex);
+        }
+    }
+
+    /**
+     * Verify a single invocation.
+     *
+     * @param int $callIndex
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws ExpectationFailedException
+     */
+    private function verifyInvocation(BaseInvocation $invocation, $callIndex): void
+    {
+        if (!isset($this->parameterGroups[$callIndex])) {
+            // no parameter assertion for this call index
+            return;
+        }
+
+        $parameters = $this->parameterGroups[$callIndex];
+
+        if (count($invocation->getParameters()) < count($parameters)) {
+            throw new ExpectationFailedException(
+                sprintf(
+                    'Parameter count for invocation %s is too low.',
+                    $invocation->toString()
+                )
+            );
+        }
+
+        foreach ($parameters as $i => $parameter) {
+            $parameter->evaluate(
+                $invocation->getParameters()[$i],
+                sprintf(
+                    'Parameter %s for invocation #%d %s does not match expected ' .
+                    'value.',
+                    $i,
+                    $callIndex,
+                    $invocation->toString()
+                )
+            );
+        }
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/Rule/InvocationOrder.php b/vendor/phpunit/phpunit/src/Framework/MockObject/Rule/InvocationOrder.php
new file mode 100644
index 0000000000000000000000000000000000000000..90aa49350de34f85911c4e023bd5482dff50bc71
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/MockObject/Rule/InvocationOrder.php
@@ -0,0 +1,47 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework\MockObject\Rule;
+
+use function count;
+use PHPUnit\Framework\MockObject\Invocation as BaseInvocation;
+use PHPUnit\Framework\MockObject\Verifiable;
+use PHPUnit\Framework\SelfDescribing;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+abstract class InvocationOrder implements SelfDescribing, Verifiable
+{
+    /**
+     * @var BaseInvocation[]
+     */
+    private $invocations = [];
+
+    public function getInvocationCount(): int
+    {
+        return count($this->invocations);
+    }
+
+    public function hasBeenInvoked(): bool
+    {
+        return count($this->invocations) > 0;
+    }
+
+    final public function invoked(BaseInvocation $invocation)
+    {
+        $this->invocations[] = $invocation;
+
+        return $this->invokedDo($invocation);
+    }
+
+    abstract public function matches(BaseInvocation $invocation): bool;
+
+    abstract protected function invokedDo(BaseInvocation $invocation);
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/Rule/InvokedAtIndex.php b/vendor/phpunit/phpunit/src/Framework/MockObject/Rule/InvokedAtIndex.php
new file mode 100644
index 0000000000000000000000000000000000000000..2a6625e2f79e3d0037d3ea037800503a82f6c7d0
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/MockObject/Rule/InvokedAtIndex.php
@@ -0,0 +1,75 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework\MockObject\Rule;
+
+use function sprintf;
+use PHPUnit\Framework\ExpectationFailedException;
+use PHPUnit\Framework\MockObject\Invocation as BaseInvocation;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ *
+ * @deprecated https://github.com/sebastianbergmann/phpunit/issues/4297
+ * @codeCoverageIgnore
+ */
+final class InvokedAtIndex extends InvocationOrder
+{
+    /**
+     * @var int
+     */
+    private $sequenceIndex;
+
+    /**
+     * @var int
+     */
+    private $currentIndex = -1;
+
+    /**
+     * @param int $sequenceIndex
+     */
+    public function __construct($sequenceIndex)
+    {
+        $this->sequenceIndex = $sequenceIndex;
+    }
+
+    public function toString(): string
+    {
+        return 'invoked at sequence index ' . $this->sequenceIndex;
+    }
+
+    public function matches(BaseInvocation $invocation): bool
+    {
+        $this->currentIndex++;
+
+        return $this->currentIndex == $this->sequenceIndex;
+    }
+
+    /**
+     * Verifies that the current expectation is valid. If everything is OK the
+     * code should just return, if not it must throw an exception.
+     *
+     * @throws ExpectationFailedException
+     */
+    public function verify(): void
+    {
+        if ($this->currentIndex < $this->sequenceIndex) {
+            throw new ExpectationFailedException(
+                sprintf(
+                    'The expected invocation at index %s was never reached.',
+                    $this->sequenceIndex
+                )
+            );
+        }
+    }
+
+    protected function invokedDo(BaseInvocation $invocation): void
+    {
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/Rule/InvokedAtLeastCount.php b/vendor/phpunit/phpunit/src/Framework/MockObject/Rule/InvokedAtLeastCount.php
new file mode 100644
index 0000000000000000000000000000000000000000..a84aa6559043009c0d9b1c4b36163ab89dfaa284
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/MockObject/Rule/InvokedAtLeastCount.php
@@ -0,0 +1,64 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework\MockObject\Rule;
+
+use PHPUnit\Framework\ExpectationFailedException;
+use PHPUnit\Framework\MockObject\Invocation as BaseInvocation;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class InvokedAtLeastCount extends InvocationOrder
+{
+    /**
+     * @var int
+     */
+    private $requiredInvocations;
+
+    /**
+     * @param int $requiredInvocations
+     */
+    public function __construct($requiredInvocations)
+    {
+        $this->requiredInvocations = $requiredInvocations;
+    }
+
+    public function toString(): string
+    {
+        return 'invoked at least ' . $this->requiredInvocations . ' times';
+    }
+
+    /**
+     * Verifies that the current expectation is valid. If everything is OK the
+     * code should just return, if not it must throw an exception.
+     *
+     * @throws ExpectationFailedException
+     */
+    public function verify(): void
+    {
+        $count = $this->getInvocationCount();
+
+        if ($count < $this->requiredInvocations) {
+            throw new ExpectationFailedException(
+                'Expected invocation at least ' . $this->requiredInvocations .
+                ' times but it occurred ' . $count . ' time(s).'
+            );
+        }
+    }
+
+    public function matches(BaseInvocation $invocation): bool
+    {
+        return true;
+    }
+
+    protected function invokedDo(BaseInvocation $invocation): void
+    {
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/Rule/InvokedAtLeastOnce.php b/vendor/phpunit/phpunit/src/Framework/MockObject/Rule/InvokedAtLeastOnce.php
new file mode 100644
index 0000000000000000000000000000000000000000..d0ad1f80159c3d0027e1a3ce0e992c3080deb0cc
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/MockObject/Rule/InvokedAtLeastOnce.php
@@ -0,0 +1,50 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework\MockObject\Rule;
+
+use PHPUnit\Framework\ExpectationFailedException;
+use PHPUnit\Framework\MockObject\Invocation as BaseInvocation;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class InvokedAtLeastOnce extends InvocationOrder
+{
+    public function toString(): string
+    {
+        return 'invoked at least once';
+    }
+
+    /**
+     * Verifies that the current expectation is valid. If everything is OK the
+     * code should just return, if not it must throw an exception.
+     *
+     * @throws ExpectationFailedException
+     */
+    public function verify(): void
+    {
+        $count = $this->getInvocationCount();
+
+        if ($count < 1) {
+            throw new ExpectationFailedException(
+                'Expected invocation at least once but it never occurred.'
+            );
+        }
+    }
+
+    public function matches(BaseInvocation $invocation): bool
+    {
+        return true;
+    }
+
+    protected function invokedDo(BaseInvocation $invocation): void
+    {
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/Rule/InvokedAtMostCount.php b/vendor/phpunit/phpunit/src/Framework/MockObject/Rule/InvokedAtMostCount.php
new file mode 100644
index 0000000000000000000000000000000000000000..c3b815aa45e2c1dd7b94961ad21b05b74cedb28c
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/MockObject/Rule/InvokedAtMostCount.php
@@ -0,0 +1,64 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework\MockObject\Rule;
+
+use PHPUnit\Framework\ExpectationFailedException;
+use PHPUnit\Framework\MockObject\Invocation as BaseInvocation;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class InvokedAtMostCount extends InvocationOrder
+{
+    /**
+     * @var int
+     */
+    private $allowedInvocations;
+
+    /**
+     * @param int $allowedInvocations
+     */
+    public function __construct($allowedInvocations)
+    {
+        $this->allowedInvocations = $allowedInvocations;
+    }
+
+    public function toString(): string
+    {
+        return 'invoked at most ' . $this->allowedInvocations . ' times';
+    }
+
+    /**
+     * Verifies that the current expectation is valid. If everything is OK the
+     * code should just return, if not it must throw an exception.
+     *
+     * @throws ExpectationFailedException
+     */
+    public function verify(): void
+    {
+        $count = $this->getInvocationCount();
+
+        if ($count > $this->allowedInvocations) {
+            throw new ExpectationFailedException(
+                'Expected invocation at most ' . $this->allowedInvocations .
+                ' times but it occurred ' . $count . ' time(s).'
+            );
+        }
+    }
+
+    public function matches(BaseInvocation $invocation): bool
+    {
+        return true;
+    }
+
+    protected function invokedDo(BaseInvocation $invocation): void
+    {
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/Rule/InvokedCount.php b/vendor/phpunit/phpunit/src/Framework/MockObject/Rule/InvokedCount.php
new file mode 100644
index 0000000000000000000000000000000000000000..188326c91f56450b071bbda3e6e3bc440cdecd22
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/MockObject/Rule/InvokedCount.php
@@ -0,0 +1,102 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework\MockObject\Rule;
+
+use function sprintf;
+use PHPUnit\Framework\ExpectationFailedException;
+use PHPUnit\Framework\MockObject\Invocation as BaseInvocation;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class InvokedCount extends InvocationOrder
+{
+    /**
+     * @var int
+     */
+    private $expectedCount;
+
+    /**
+     * @param int $expectedCount
+     */
+    public function __construct($expectedCount)
+    {
+        $this->expectedCount = $expectedCount;
+    }
+
+    public function isNever(): bool
+    {
+        return $this->expectedCount === 0;
+    }
+
+    public function toString(): string
+    {
+        return 'invoked ' . $this->expectedCount . ' time(s)';
+    }
+
+    public function matches(BaseInvocation $invocation): bool
+    {
+        return true;
+    }
+
+    /**
+     * Verifies that the current expectation is valid. If everything is OK the
+     * code should just return, if not it must throw an exception.
+     *
+     * @throws ExpectationFailedException
+     */
+    public function verify(): void
+    {
+        $count = $this->getInvocationCount();
+
+        if ($count !== $this->expectedCount) {
+            throw new ExpectationFailedException(
+                sprintf(
+                    'Method was expected to be called %d times, ' .
+                    'actually called %d times.',
+                    $this->expectedCount,
+                    $count
+                )
+            );
+        }
+    }
+
+    /**
+     * @throws ExpectationFailedException
+     */
+    protected function invokedDo(BaseInvocation $invocation): void
+    {
+        $count = $this->getInvocationCount();
+
+        if ($count > $this->expectedCount) {
+            $message = $invocation->toString() . ' ';
+
+            switch ($this->expectedCount) {
+                case 0:
+                    $message .= 'was not expected to be called.';
+
+                    break;
+
+                case 1:
+                    $message .= 'was not expected to be called more than once.';
+
+                    break;
+
+                default:
+                    $message .= sprintf(
+                        'was not expected to be called more than %d times.',
+                        $this->expectedCount
+                    );
+            }
+
+            throw new ExpectationFailedException($message);
+        }
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/Rule/MethodName.php b/vendor/phpunit/phpunit/src/Framework/MockObject/Rule/MethodName.php
new file mode 100644
index 0000000000000000000000000000000000000000..83ba3b8da35ca01b1ae3921081d4823edc27fb28
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/MockObject/Rule/MethodName.php
@@ -0,0 +1,68 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework\MockObject\Rule;
+
+use function is_string;
+use PHPUnit\Framework\Constraint\Constraint;
+use PHPUnit\Framework\InvalidArgumentException;
+use PHPUnit\Framework\MockObject\Invocation as BaseInvocation;
+use PHPUnit\Framework\MockObject\MethodNameConstraint;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class MethodName
+{
+    /**
+     * @var Constraint
+     */
+    private $constraint;
+
+    /**
+     * @param Constraint|string $constraint
+     *
+     * @throws InvalidArgumentException
+     */
+    public function __construct($constraint)
+    {
+        if (is_string($constraint)) {
+            $constraint = new MethodNameConstraint($constraint);
+        }
+
+        if (!$constraint instanceof Constraint) {
+            throw InvalidArgumentException::create(1, 'PHPUnit\Framework\Constraint\Constraint object or string');
+        }
+
+        $this->constraint = $constraint;
+    }
+
+    public function toString(): string
+    {
+        return 'method name ' . $this->constraint->toString();
+    }
+
+    /**
+     * @throws \PHPUnit\Framework\ExpectationFailedException
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     */
+    public function matches(BaseInvocation $invocation): bool
+    {
+        return $this->matchesName($invocation->getMethodName());
+    }
+
+    /**
+     * @throws \PHPUnit\Framework\ExpectationFailedException
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     */
+    public function matchesName(string $methodName): bool
+    {
+        return (bool) $this->constraint->evaluate($methodName, '', true);
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/Rule/Parameters.php b/vendor/phpunit/phpunit/src/Framework/MockObject/Rule/Parameters.php
new file mode 100644
index 0000000000000000000000000000000000000000..3f1cc53ae0d0259279ee25c07099067ab186f106
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/MockObject/Rule/Parameters.php
@@ -0,0 +1,160 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework\MockObject\Rule;
+
+use function count;
+use function get_class;
+use function sprintf;
+use Exception;
+use PHPUnit\Framework\Constraint\Constraint;
+use PHPUnit\Framework\Constraint\IsAnything;
+use PHPUnit\Framework\Constraint\IsEqual;
+use PHPUnit\Framework\ExpectationFailedException;
+use PHPUnit\Framework\MockObject\Invocation as BaseInvocation;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class Parameters implements ParametersRule
+{
+    /**
+     * @var Constraint[]
+     */
+    private $parameters = [];
+
+    /**
+     * @var BaseInvocation
+     */
+    private $invocation;
+
+    /**
+     * @var bool|ExpectationFailedException
+     */
+    private $parameterVerificationResult;
+
+    /**
+     * @throws \PHPUnit\Framework\Exception
+     */
+    public function __construct(array $parameters)
+    {
+        foreach ($parameters as $parameter) {
+            if (!($parameter instanceof Constraint)) {
+                $parameter = new IsEqual(
+                    $parameter
+                );
+            }
+
+            $this->parameters[] = $parameter;
+        }
+    }
+
+    public function toString(): string
+    {
+        $text = 'with parameter';
+
+        foreach ($this->parameters as $index => $parameter) {
+            if ($index > 0) {
+                $text .= ' and';
+            }
+
+            $text .= ' ' . $index . ' ' . $parameter->toString();
+        }
+
+        return $text;
+    }
+
+    /**
+     * @throws Exception
+     */
+    public function apply(BaseInvocation $invocation): void
+    {
+        $this->invocation                  = $invocation;
+        $this->parameterVerificationResult = null;
+
+        try {
+            $this->parameterVerificationResult = $this->doVerify();
+        } catch (ExpectationFailedException $e) {
+            $this->parameterVerificationResult = $e;
+
+            throw $this->parameterVerificationResult;
+        }
+    }
+
+    /**
+     * Checks if the invocation $invocation matches the current rules. If it
+     * does the rule will get the invoked() method called which should check
+     * if an expectation is met.
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws ExpectationFailedException
+     */
+    public function verify(): void
+    {
+        $this->doVerify();
+    }
+
+    /**
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws ExpectationFailedException
+     */
+    private function doVerify(): bool
+    {
+        if (isset($this->parameterVerificationResult)) {
+            return $this->guardAgainstDuplicateEvaluationOfParameterConstraints();
+        }
+
+        if ($this->invocation === null) {
+            throw new ExpectationFailedException('Mocked method does not exist.');
+        }
+
+        if (count($this->invocation->getParameters()) < count($this->parameters)) {
+            $message = 'Parameter count for invocation %s is too low.';
+
+            // The user called `->with($this->anything())`, but may have meant
+            // `->withAnyParameters()`.
+            //
+            // @see https://github.com/sebastianbergmann/phpunit-mock-objects/issues/199
+            if (count($this->parameters) === 1 &&
+                get_class($this->parameters[0]) === IsAnything::class) {
+                $message .= "\nTo allow 0 or more parameters with any value, omit ->with() or use ->withAnyParameters() instead.";
+            }
+
+            throw new ExpectationFailedException(
+                sprintf($message, $this->invocation->toString())
+            );
+        }
+
+        foreach ($this->parameters as $i => $parameter) {
+            $parameter->evaluate(
+                $this->invocation->getParameters()[$i],
+                sprintf(
+                    'Parameter %s for invocation %s does not match expected ' .
+                    'value.',
+                    $i,
+                    $this->invocation->toString()
+                )
+            );
+        }
+
+        return true;
+    }
+
+    /**
+     * @throws ExpectationFailedException
+     */
+    private function guardAgainstDuplicateEvaluationOfParameterConstraints(): bool
+    {
+        if ($this->parameterVerificationResult instanceof ExpectationFailedException) {
+            throw $this->parameterVerificationResult;
+        }
+
+        return (bool) $this->parameterVerificationResult;
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/Rule/ParametersRule.php b/vendor/phpunit/phpunit/src/Framework/MockObject/Rule/ParametersRule.php
new file mode 100644
index 0000000000000000000000000000000000000000..70c47fe326b936a5a83ec841e37bf24a44497946
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/MockObject/Rule/ParametersRule.php
@@ -0,0 +1,28 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework\MockObject\Rule;
+
+use PHPUnit\Framework\ExpectationFailedException;
+use PHPUnit\Framework\MockObject\Invocation as BaseInvocation;
+use PHPUnit\Framework\MockObject\Verifiable;
+use PHPUnit\Framework\SelfDescribing;
+
+/**
+ * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+ */
+interface ParametersRule extends SelfDescribing, Verifiable
+{
+    /**
+     * @throws ExpectationFailedException if the invocation violates the rule
+     */
+    public function apply(BaseInvocation $invocation): void;
+
+    public function verify(): void;
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/Stub.php b/vendor/phpunit/phpunit/src/Framework/MockObject/Stub.php
new file mode 100644
index 0000000000000000000000000000000000000000..2b032e2dc9ad9be9aca5aca6df18ad5ca54ab82f
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/MockObject/Stub.php
@@ -0,0 +1,26 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework\MockObject;
+
+use PHPUnit\Framework\MockObject\Builder\InvocationStubber;
+
+/**
+ * @method InvocationStubber method($constraint)
+ *
+ * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+ */
+interface Stub
+{
+    public function __phpunit_getInvocationHandler(): InvocationHandler;
+
+    public function __phpunit_hasMatchers(): bool;
+
+    public function __phpunit_setReturnValueGeneration(bool $returnValueGeneration): void;
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/Stub/ConsecutiveCalls.php b/vendor/phpunit/phpunit/src/Framework/MockObject/Stub/ConsecutiveCalls.php
new file mode 100644
index 0000000000000000000000000000000000000000..0dcf386b3fb8f7c9764720fdd271474052e09e9f
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/MockObject/Stub/ConsecutiveCalls.php
@@ -0,0 +1,57 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework\MockObject\Stub;
+
+use function array_shift;
+use function sprintf;
+use PHPUnit\Framework\MockObject\Invocation;
+use SebastianBergmann\Exporter\Exporter;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class ConsecutiveCalls implements Stub
+{
+    /**
+     * @var array
+     */
+    private $stack;
+
+    /**
+     * @var mixed
+     */
+    private $value;
+
+    public function __construct(array $stack)
+    {
+        $this->stack = $stack;
+    }
+
+    public function invoke(Invocation $invocation)
+    {
+        $this->value = array_shift($this->stack);
+
+        if ($this->value instanceof Stub) {
+            $this->value = $this->value->invoke($invocation);
+        }
+
+        return $this->value;
+    }
+
+    public function toString(): string
+    {
+        $exporter = new Exporter;
+
+        return sprintf(
+            'return user-specified value %s',
+            $exporter->export($this->value)
+        );
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/Stub/Exception.php b/vendor/phpunit/phpunit/src/Framework/MockObject/Stub/Exception.php
new file mode 100644
index 0000000000000000000000000000000000000000..5d64c96a50097bd6407901a5a260e0ef8b624010
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/MockObject/Stub/Exception.php
@@ -0,0 +1,46 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework\MockObject\Stub;
+
+use function sprintf;
+use PHPUnit\Framework\MockObject\Invocation;
+use SebastianBergmann\Exporter\Exporter;
+use Throwable;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class Exception implements Stub
+{
+    private $exception;
+
+    public function __construct(Throwable $exception)
+    {
+        $this->exception = $exception;
+    }
+
+    /**
+     * @throws Throwable
+     */
+    public function invoke(Invocation $invocation): void
+    {
+        throw $this->exception;
+    }
+
+    public function toString(): string
+    {
+        $exporter = new Exporter;
+
+        return sprintf(
+            'raise user-specified exception %s',
+            $exporter->export($this->exception)
+        );
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/Stub/ReturnArgument.php b/vendor/phpunit/phpunit/src/Framework/MockObject/Stub/ReturnArgument.php
new file mode 100644
index 0000000000000000000000000000000000000000..c7b3f8f410a85b5c3d5eae4f6a8c80e6769f0663
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/MockObject/Stub/ReturnArgument.php
@@ -0,0 +1,41 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework\MockObject\Stub;
+
+use function sprintf;
+use PHPUnit\Framework\MockObject\Invocation;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class ReturnArgument implements Stub
+{
+    /**
+     * @var int
+     */
+    private $argumentIndex;
+
+    public function __construct($argumentIndex)
+    {
+        $this->argumentIndex = $argumentIndex;
+    }
+
+    public function invoke(Invocation $invocation)
+    {
+        if (isset($invocation->getParameters()[$this->argumentIndex])) {
+            return $invocation->getParameters()[$this->argumentIndex];
+        }
+    }
+
+    public function toString(): string
+    {
+        return sprintf('return argument #%d', $this->argumentIndex);
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/Stub/ReturnCallback.php b/vendor/phpunit/phpunit/src/Framework/MockObject/Stub/ReturnCallback.php
new file mode 100644
index 0000000000000000000000000000000000000000..e02181e90b541af2277bbfc07ead7f049c533d77
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/MockObject/Stub/ReturnCallback.php
@@ -0,0 +1,59 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework\MockObject\Stub;
+
+use function call_user_func_array;
+use function get_class;
+use function is_array;
+use function is_object;
+use function sprintf;
+use PHPUnit\Framework\MockObject\Invocation;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class ReturnCallback implements Stub
+{
+    private $callback;
+
+    public function __construct($callback)
+    {
+        $this->callback = $callback;
+    }
+
+    public function invoke(Invocation $invocation)
+    {
+        return call_user_func_array($this->callback, $invocation->getParameters());
+    }
+
+    public function toString(): string
+    {
+        if (is_array($this->callback)) {
+            if (is_object($this->callback[0])) {
+                $class = get_class($this->callback[0]);
+                $type  = '->';
+            } else {
+                $class = $this->callback[0];
+                $type  = '::';
+            }
+
+            return sprintf(
+                'return result of user defined callback %s%s%s() with the ' .
+                'passed arguments',
+                $class,
+                $type,
+                $this->callback[1]
+            );
+        }
+
+        return 'return result of user defined callback ' . $this->callback .
+               ' with the passed arguments';
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/Stub/ReturnReference.php b/vendor/phpunit/phpunit/src/Framework/MockObject/Stub/ReturnReference.php
new file mode 100644
index 0000000000000000000000000000000000000000..0d288cebe0750acb70f33ae9bb4071d23900c29b
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/MockObject/Stub/ReturnReference.php
@@ -0,0 +1,45 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework\MockObject\Stub;
+
+use function sprintf;
+use PHPUnit\Framework\MockObject\Invocation;
+use SebastianBergmann\Exporter\Exporter;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class ReturnReference implements Stub
+{
+    /**
+     * @var mixed
+     */
+    private $reference;
+
+    public function __construct(&$reference)
+    {
+        $this->reference = &$reference;
+    }
+
+    public function invoke(Invocation $invocation)
+    {
+        return $this->reference;
+    }
+
+    public function toString(): string
+    {
+        $exporter = new Exporter;
+
+        return sprintf(
+            'return user-specified reference %s',
+            $exporter->export($this->reference)
+        );
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/Stub/ReturnSelf.php b/vendor/phpunit/phpunit/src/Framework/MockObject/Stub/ReturnSelf.php
new file mode 100644
index 0000000000000000000000000000000000000000..6d2137bfbf84baaa6d642123d1416c33f1ca60d7
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/MockObject/Stub/ReturnSelf.php
@@ -0,0 +1,32 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework\MockObject\Stub;
+
+use PHPUnit\Framework\MockObject\Invocation;
+use PHPUnit\Framework\MockObject\RuntimeException;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class ReturnSelf implements Stub
+{
+    /**
+     * @throws RuntimeException
+     */
+    public function invoke(Invocation $invocation)
+    {
+        return $invocation->getObject();
+    }
+
+    public function toString(): string
+    {
+        return 'return the current object';
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/Stub/ReturnStub.php b/vendor/phpunit/phpunit/src/Framework/MockObject/Stub/ReturnStub.php
new file mode 100644
index 0000000000000000000000000000000000000000..fbcd0a07a8030cb4f4be85cf42e1f0a5030aafd2
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/MockObject/Stub/ReturnStub.php
@@ -0,0 +1,45 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework\MockObject\Stub;
+
+use function sprintf;
+use PHPUnit\Framework\MockObject\Invocation;
+use SebastianBergmann\Exporter\Exporter;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class ReturnStub implements Stub
+{
+    /**
+     * @var mixed
+     */
+    private $value;
+
+    public function __construct($value)
+    {
+        $this->value = $value;
+    }
+
+    public function invoke(Invocation $invocation)
+    {
+        return $this->value;
+    }
+
+    public function toString(): string
+    {
+        $exporter = new Exporter;
+
+        return sprintf(
+            'return user-specified value %s',
+            $exporter->export($this->value)
+        );
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/Stub/ReturnValueMap.php b/vendor/phpunit/phpunit/src/Framework/MockObject/Stub/ReturnValueMap.php
new file mode 100644
index 0000000000000000000000000000000000000000..5fcd3a09adff2c8cf821b30943bdd0352b87d1b2
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/MockObject/Stub/ReturnValueMap.php
@@ -0,0 +1,53 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework\MockObject\Stub;
+
+use function array_pop;
+use function count;
+use function is_array;
+use PHPUnit\Framework\MockObject\Invocation;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class ReturnValueMap implements Stub
+{
+    /**
+     * @var array
+     */
+    private $valueMap;
+
+    public function __construct(array $valueMap)
+    {
+        $this->valueMap = $valueMap;
+    }
+
+    public function invoke(Invocation $invocation)
+    {
+        $parameterCount = count($invocation->getParameters());
+
+        foreach ($this->valueMap as $map) {
+            if (!is_array($map) || $parameterCount !== (count($map) - 1)) {
+                continue;
+            }
+
+            $return = array_pop($map);
+
+            if ($invocation->getParameters() === $map) {
+                return $return;
+            }
+        }
+    }
+
+    public function toString(): string
+    {
+        return 'return value from a map';
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/Stub/Stub.php b/vendor/phpunit/phpunit/src/Framework/MockObject/Stub/Stub.php
new file mode 100644
index 0000000000000000000000000000000000000000..15cfce5c3cda7d82fecb35f4faf984dea0ac6d00
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/MockObject/Stub/Stub.php
@@ -0,0 +1,27 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework\MockObject\Stub;
+
+use PHPUnit\Framework\MockObject\Invocation;
+use PHPUnit\Framework\SelfDescribing;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+interface Stub extends SelfDescribing
+{
+    /**
+     * Fakes the processing of the invocation $invocation by returning a
+     * specific value.
+     *
+     * @param Invocation $invocation The invocation which was mocked and matched by the current method and argument matchers
+     */
+    public function invoke(Invocation $invocation);
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/Verifiable.php b/vendor/phpunit/phpunit/src/Framework/MockObject/Verifiable.php
new file mode 100644
index 0000000000000000000000000000000000000000..8c9a82c5aa7fa224aad7f311caceade4ea7b49b6
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/MockObject/Verifiable.php
@@ -0,0 +1,26 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework\MockObject;
+
+use PHPUnit\Framework\ExpectationFailedException;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+interface Verifiable
+{
+    /**
+     * Verifies that the current expectation is valid. If everything is OK the
+     * code should just return, if not it must throw an exception.
+     *
+     * @throws ExpectationFailedException
+     */
+    public function verify(): void;
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/Reorderable.php b/vendor/phpunit/phpunit/src/Framework/Reorderable.php
new file mode 100644
index 0000000000000000000000000000000000000000..34951f8dc97dc3ff0e96134d429c9159702bb377
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/Reorderable.php
@@ -0,0 +1,28 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+interface Reorderable
+{
+    public function sortId(): string;
+
+    /**
+     * @return list<ExecutionOrderDependency>
+     */
+    public function provides(): array;
+
+    /**
+     * @return list<ExecutionOrderDependency>
+     */
+    public function requires(): array;
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/SelfDescribing.php b/vendor/phpunit/phpunit/src/Framework/SelfDescribing.php
new file mode 100644
index 0000000000000000000000000000000000000000..73034f650ab464fd9ada6420bab756900d5c2ea7
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/SelfDescribing.php
@@ -0,0 +1,21 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+interface SelfDescribing
+{
+    /**
+     * Returns a string representation of the object.
+     */
+    public function toString(): string;
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/SkippedTest.php b/vendor/phpunit/phpunit/src/Framework/SkippedTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..a12aa402da57724af4d4680c1f36f6de6cd6a59c
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/SkippedTest.php
@@ -0,0 +1,19 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework;
+
+use Throwable;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+interface SkippedTest extends Throwable
+{
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/SkippedTestCase.php b/vendor/phpunit/phpunit/src/Framework/SkippedTestCase.php
new file mode 100644
index 0000000000000000000000000000000000000000..51c00619c549be5dc78b501831a26bb24ac89c22
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/SkippedTestCase.php
@@ -0,0 +1,66 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class SkippedTestCase extends TestCase
+{
+    /**
+     * @var bool
+     */
+    protected $backupGlobals = false;
+
+    /**
+     * @var bool
+     */
+    protected $backupStaticAttributes = false;
+
+    /**
+     * @var bool
+     */
+    protected $runTestInSeparateProcess = false;
+
+    /**
+     * @var string
+     */
+    private $message;
+
+    public function __construct(string $className, string $methodName, string $message = '')
+    {
+        parent::__construct($className . '::' . $methodName);
+
+        $this->message = $message;
+    }
+
+    public function getMessage(): string
+    {
+        return $this->message;
+    }
+
+    /**
+     * Returns a string representation of the test case.
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     */
+    public function toString(): string
+    {
+        return $this->getName();
+    }
+
+    /**
+     * @throws Exception
+     */
+    protected function runTest(): void
+    {
+        $this->markTestSkipped($this->message);
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/Test.php b/vendor/phpunit/phpunit/src/Framework/Test.php
new file mode 100644
index 0000000000000000000000000000000000000000..be0dcd0ef419a2a04e2d33d3d0024c673132df61
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/Test.php
@@ -0,0 +1,23 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework;
+
+use Countable;
+
+/**
+ * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+ */
+interface Test extends Countable
+{
+    /**
+     * Runs a test and collects its result in a TestResult instance.
+     */
+    public function run(TestResult $result = null): TestResult;
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/TestBuilder.php b/vendor/phpunit/phpunit/src/Framework/TestBuilder.php
new file mode 100644
index 0000000000000000000000000000000000000000..5dd91e2196bc54df44b2fb82324c1f102bc58ce6
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/TestBuilder.php
@@ -0,0 +1,239 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework;
+
+use function assert;
+use function count;
+use function get_class;
+use function sprintf;
+use function trim;
+use PHPUnit\Util\Filter;
+use PHPUnit\Util\InvalidDataSetException;
+use PHPUnit\Util\Test as TestUtil;
+use ReflectionClass;
+use Throwable;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class TestBuilder
+{
+    public function build(ReflectionClass $theClass, string $methodName): Test
+    {
+        $className = $theClass->getName();
+
+        if (!$theClass->isInstantiable()) {
+            return new ErrorTestCase(
+                sprintf('Cannot instantiate class "%s".', $className)
+            );
+        }
+
+        $backupSettings = TestUtil::getBackupSettings(
+            $className,
+            $methodName
+        );
+
+        $preserveGlobalState = TestUtil::getPreserveGlobalStateSettings(
+            $className,
+            $methodName
+        );
+
+        $runTestInSeparateProcess = TestUtil::getProcessIsolationSettings(
+            $className,
+            $methodName
+        );
+
+        $runClassInSeparateProcess = TestUtil::getClassProcessIsolationSettings(
+            $className,
+            $methodName
+        );
+
+        $constructor = $theClass->getConstructor();
+
+        if ($constructor === null) {
+            throw new Exception('No valid test provided.');
+        }
+
+        $parameters = $constructor->getParameters();
+
+        // TestCase() or TestCase($name)
+        if (count($parameters) < 2) {
+            $test = $this->buildTestWithoutData($className);
+        } // TestCase($name, $data)
+        else {
+            try {
+                $data = TestUtil::getProvidedData(
+                    $className,
+                    $methodName
+                );
+            } catch (IncompleteTestError $e) {
+                $message = sprintf(
+                    "Test for %s::%s marked incomplete by data provider\n%s",
+                    $className,
+                    $methodName,
+                    $this->throwableToString($e)
+                );
+
+                $data = new IncompleteTestCase($className, $methodName, $message);
+            } catch (SkippedTestError $e) {
+                $message = sprintf(
+                    "Test for %s::%s skipped by data provider\n%s",
+                    $className,
+                    $methodName,
+                    $this->throwableToString($e)
+                );
+
+                $data = new SkippedTestCase($className, $methodName, $message);
+            } catch (Throwable $t) {
+                $message = sprintf(
+                    "The data provider specified for %s::%s is invalid.\n%s",
+                    $className,
+                    $methodName,
+                    $this->throwableToString($t)
+                );
+
+                $data = new ErrorTestCase($message);
+            }
+
+            // Test method with @dataProvider.
+            if (isset($data)) {
+                $test = $this->buildDataProviderTestSuite(
+                    $methodName,
+                    $className,
+                    $data,
+                    $runTestInSeparateProcess,
+                    $preserveGlobalState,
+                    $runClassInSeparateProcess,
+                    $backupSettings
+                );
+            } else {
+                $test = $this->buildTestWithoutData($className);
+            }
+        }
+
+        if ($test instanceof TestCase) {
+            $test->setName($methodName);
+            $this->configureTestCase(
+                $test,
+                $runTestInSeparateProcess,
+                $preserveGlobalState,
+                $runClassInSeparateProcess,
+                $backupSettings
+            );
+        }
+
+        return $test;
+    }
+
+    /** @psalm-param class-string $className */
+    private function buildTestWithoutData(string $className)
+    {
+        return new $className;
+    }
+
+    /** @psalm-param class-string $className */
+    private function buildDataProviderTestSuite(
+        string $methodName,
+        string $className,
+        $data,
+        bool $runTestInSeparateProcess,
+        ?bool $preserveGlobalState,
+        bool $runClassInSeparateProcess,
+        array $backupSettings
+    ): DataProviderTestSuite {
+        $dataProviderTestSuite = new DataProviderTestSuite(
+            $className . '::' . $methodName
+        );
+
+        $groups = TestUtil::getGroups($className, $methodName);
+
+        if ($data instanceof ErrorTestCase ||
+            $data instanceof SkippedTestCase ||
+            $data instanceof IncompleteTestCase) {
+            $dataProviderTestSuite->addTest($data, $groups);
+        } else {
+            foreach ($data as $_dataName => $_data) {
+                $_test = new $className($methodName, $_data, $_dataName);
+
+                assert($_test instanceof TestCase);
+
+                $this->configureTestCase(
+                    $_test,
+                    $runTestInSeparateProcess,
+                    $preserveGlobalState,
+                    $runClassInSeparateProcess,
+                    $backupSettings
+                );
+
+                $dataProviderTestSuite->addTest($_test, $groups);
+            }
+        }
+
+        return $dataProviderTestSuite;
+    }
+
+    private function configureTestCase(
+        TestCase $test,
+        bool $runTestInSeparateProcess,
+        ?bool $preserveGlobalState,
+        bool $runClassInSeparateProcess,
+        array $backupSettings
+    ): void {
+        if ($runTestInSeparateProcess) {
+            $test->setRunTestInSeparateProcess(true);
+
+            if ($preserveGlobalState !== null) {
+                $test->setPreserveGlobalState($preserveGlobalState);
+            }
+        }
+
+        if ($runClassInSeparateProcess) {
+            $test->setRunClassInSeparateProcess(true);
+
+            if ($preserveGlobalState !== null) {
+                $test->setPreserveGlobalState($preserveGlobalState);
+            }
+        }
+
+        if ($backupSettings['backupGlobals'] !== null) {
+            $test->setBackupGlobals($backupSettings['backupGlobals']);
+        }
+
+        if ($backupSettings['backupStaticAttributes'] !== null) {
+            $test->setBackupStaticAttributes(
+                $backupSettings['backupStaticAttributes']
+            );
+        }
+    }
+
+    private function throwableToString(Throwable $t): string
+    {
+        $message = $t->getMessage();
+
+        if (empty(trim($message))) {
+            $message = '<no message>';
+        }
+
+        if ($t instanceof InvalidDataSetException) {
+            return sprintf(
+                "%s\n%s",
+                $message,
+                Filter::getFilteredStacktrace($t)
+            );
+        }
+
+        return sprintf(
+            "%s: %s\n%s",
+            get_class($t),
+            $message,
+            Filter::getFilteredStacktrace($t)
+        );
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/TestCase.php b/vendor/phpunit/phpunit/src/Framework/TestCase.php
new file mode 100644
index 0000000000000000000000000000000000000000..882b26aed4a2ca4848f4e282f8a9bce8540f6c8c
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/TestCase.php
@@ -0,0 +1,2569 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework;
+
+use const LC_ALL;
+use const LC_COLLATE;
+use const LC_CTYPE;
+use const LC_MONETARY;
+use const LC_NUMERIC;
+use const LC_TIME;
+use const PATHINFO_FILENAME;
+use const PHP_EOL;
+use const PHP_URL_PATH;
+use function array_filter;
+use function array_flip;
+use function array_keys;
+use function array_merge;
+use function array_pop;
+use function array_search;
+use function array_unique;
+use function array_values;
+use function basename;
+use function call_user_func;
+use function chdir;
+use function class_exists;
+use function clearstatcache;
+use function count;
+use function debug_backtrace;
+use function defined;
+use function explode;
+use function get_class;
+use function get_include_path;
+use function getcwd;
+use function implode;
+use function in_array;
+use function ini_set;
+use function is_array;
+use function is_callable;
+use function is_int;
+use function is_object;
+use function is_string;
+use function libxml_clear_errors;
+use function method_exists;
+use function ob_end_clean;
+use function ob_get_contents;
+use function ob_get_level;
+use function ob_start;
+use function parse_url;
+use function pathinfo;
+use function preg_replace;
+use function serialize;
+use function setlocale;
+use function sprintf;
+use function strpos;
+use function substr;
+use function trim;
+use function var_export;
+use DeepCopy\DeepCopy;
+use PHPUnit\Framework\Constraint\Exception as ExceptionConstraint;
+use PHPUnit\Framework\Constraint\ExceptionCode;
+use PHPUnit\Framework\Constraint\ExceptionMessage;
+use PHPUnit\Framework\Constraint\ExceptionMessageRegularExpression;
+use PHPUnit\Framework\Error\Deprecated;
+use PHPUnit\Framework\Error\Error;
+use PHPUnit\Framework\Error\Notice;
+use PHPUnit\Framework\Error\Warning as WarningError;
+use PHPUnit\Framework\MockObject\Generator as MockGenerator;
+use PHPUnit\Framework\MockObject\MockBuilder;
+use PHPUnit\Framework\MockObject\MockObject;
+use PHPUnit\Framework\MockObject\Rule\AnyInvokedCount as AnyInvokedCountMatcher;
+use PHPUnit\Framework\MockObject\Rule\InvokedAtIndex as InvokedAtIndexMatcher;
+use PHPUnit\Framework\MockObject\Rule\InvokedAtLeastCount as InvokedAtLeastCountMatcher;
+use PHPUnit\Framework\MockObject\Rule\InvokedAtLeastOnce as InvokedAtLeastOnceMatcher;
+use PHPUnit\Framework\MockObject\Rule\InvokedAtMostCount as InvokedAtMostCountMatcher;
+use PHPUnit\Framework\MockObject\Rule\InvokedCount as InvokedCountMatcher;
+use PHPUnit\Framework\MockObject\Stub;
+use PHPUnit\Framework\MockObject\Stub\ConsecutiveCalls as ConsecutiveCallsStub;
+use PHPUnit\Framework\MockObject\Stub\Exception as ExceptionStub;
+use PHPUnit\Framework\MockObject\Stub\ReturnArgument as ReturnArgumentStub;
+use PHPUnit\Framework\MockObject\Stub\ReturnCallback as ReturnCallbackStub;
+use PHPUnit\Framework\MockObject\Stub\ReturnSelf as ReturnSelfStub;
+use PHPUnit\Framework\MockObject\Stub\ReturnStub;
+use PHPUnit\Framework\MockObject\Stub\ReturnValueMap as ReturnValueMapStub;
+use PHPUnit\Runner\BaseTestRunner;
+use PHPUnit\Runner\PhptTestCase;
+use PHPUnit\Util\Exception as UtilException;
+use PHPUnit\Util\GlobalState;
+use PHPUnit\Util\PHP\AbstractPhpProcess;
+use PHPUnit\Util\Test as TestUtil;
+use PHPUnit\Util\Type;
+use Prophecy\Exception\Prediction\PredictionException;
+use Prophecy\Prophecy\MethodProphecy;
+use Prophecy\Prophecy\ObjectProphecy;
+use Prophecy\Prophet;
+use ReflectionClass;
+use ReflectionException;
+use SebastianBergmann\Comparator\Comparator;
+use SebastianBergmann\Comparator\Factory as ComparatorFactory;
+use SebastianBergmann\Diff\Differ;
+use SebastianBergmann\Exporter\Exporter;
+use SebastianBergmann\GlobalState\ExcludeList;
+use SebastianBergmann\GlobalState\Restorer;
+use SebastianBergmann\GlobalState\Snapshot;
+use SebastianBergmann\ObjectEnumerator\Enumerator;
+use SebastianBergmann\Template\Template;
+use SoapClient;
+use Throwable;
+
+/**
+ * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+ */
+abstract class TestCase extends Assert implements Reorderable, SelfDescribing, Test
+{
+    private const LOCALE_CATEGORIES = [LC_ALL, LC_COLLATE, LC_CTYPE, LC_MONETARY, LC_NUMERIC, LC_TIME];
+
+    /**
+     * @var ?bool
+     */
+    protected $backupGlobals;
+
+    /**
+     * @var string[]
+     */
+    protected $backupGlobalsExcludeList = [];
+
+    /**
+     * @var string[]
+     *
+     * @deprecated Use $backupGlobalsExcludeList instead
+     */
+    protected $backupGlobalsBlacklist = [];
+
+    /**
+     * @var bool
+     */
+    protected $backupStaticAttributes;
+
+    /**
+     * @var array<string,array<int,string>>
+     */
+    protected $backupStaticAttributesExcludeList = [];
+
+    /**
+     * @var array<string,array<int,string>>
+     *
+     * @deprecated Use $backupStaticAttributesExcludeList instead
+     */
+    protected $backupStaticAttributesBlacklist = [];
+
+    /**
+     * @var bool
+     */
+    protected $runTestInSeparateProcess;
+
+    /**
+     * @var bool
+     */
+    protected $preserveGlobalState = true;
+
+    /**
+     * @var list<ExecutionOrderDependency>
+     */
+    protected $providedTests = [];
+
+    /**
+     * @var bool
+     */
+    private $runClassInSeparateProcess;
+
+    /**
+     * @var bool
+     */
+    private $inIsolation = false;
+
+    /**
+     * @var array
+     */
+    private $data;
+
+    /**
+     * @var int|string
+     */
+    private $dataName;
+
+    /**
+     * @var null|string
+     */
+    private $expectedException;
+
+    /**
+     * @var null|string
+     */
+    private $expectedExceptionMessage;
+
+    /**
+     * @var null|string
+     */
+    private $expectedExceptionMessageRegExp;
+
+    /**
+     * @var null|int|string
+     */
+    private $expectedExceptionCode;
+
+    /**
+     * @var string
+     */
+    private $name = '';
+
+    /**
+     * @var list<ExecutionOrderDependency>
+     */
+    private $dependencies = [];
+
+    /**
+     * @var array
+     */
+    private $dependencyInput = [];
+
+    /**
+     * @var array<string,string>
+     */
+    private $iniSettings = [];
+
+    /**
+     * @var array
+     */
+    private $locale = [];
+
+    /**
+     * @var MockObject[]
+     */
+    private $mockObjects = [];
+
+    /**
+     * @var MockGenerator
+     */
+    private $mockObjectGenerator;
+
+    /**
+     * @var int
+     */
+    private $status = BaseTestRunner::STATUS_UNKNOWN;
+
+    /**
+     * @var string
+     */
+    private $statusMessage = '';
+
+    /**
+     * @var int
+     */
+    private $numAssertions = 0;
+
+    /**
+     * @var TestResult
+     */
+    private $result;
+
+    /**
+     * @var mixed
+     */
+    private $testResult;
+
+    /**
+     * @var string
+     */
+    private $output = '';
+
+    /**
+     * @var string
+     */
+    private $outputExpectedRegex;
+
+    /**
+     * @var string
+     */
+    private $outputExpectedString;
+
+    /**
+     * @var mixed
+     */
+    private $outputCallback = false;
+
+    /**
+     * @var bool
+     */
+    private $outputBufferingActive = false;
+
+    /**
+     * @var int
+     */
+    private $outputBufferingLevel;
+
+    /**
+     * @var bool
+     */
+    private $outputRetrievedForAssertion = false;
+
+    /**
+     * @var Snapshot
+     */
+    private $snapshot;
+
+    /**
+     * @var \Prophecy\Prophet
+     */
+    private $prophet;
+
+    /**
+     * @var bool
+     */
+    private $beStrictAboutChangesToGlobalState = false;
+
+    /**
+     * @var bool
+     */
+    private $registerMockObjectsFromTestArgumentsRecursively = false;
+
+    /**
+     * @var string[]
+     */
+    private $warnings = [];
+
+    /**
+     * @var string[]
+     */
+    private $groups = [];
+
+    /**
+     * @var bool
+     */
+    private $doesNotPerformAssertions = false;
+
+    /**
+     * @var Comparator[]
+     */
+    private $customComparators = [];
+
+    /**
+     * @var string[]
+     */
+    private $doubledTypes = [];
+
+    /**
+     * Returns a matcher that matches when the method is executed
+     * zero or more times.
+     */
+    public static function any(): AnyInvokedCountMatcher
+    {
+        return new AnyInvokedCountMatcher;
+    }
+
+    /**
+     * Returns a matcher that matches when the method is never executed.
+     */
+    public static function never(): InvokedCountMatcher
+    {
+        return new InvokedCountMatcher(0);
+    }
+
+    /**
+     * Returns a matcher that matches when the method is executed
+     * at least N times.
+     */
+    public static function atLeast(int $requiredInvocations): InvokedAtLeastCountMatcher
+    {
+        return new InvokedAtLeastCountMatcher(
+            $requiredInvocations
+        );
+    }
+
+    /**
+     * Returns a matcher that matches when the method is executed at least once.
+     */
+    public static function atLeastOnce(): InvokedAtLeastOnceMatcher
+    {
+        return new InvokedAtLeastOnceMatcher;
+    }
+
+    /**
+     * Returns a matcher that matches when the method is executed exactly once.
+     */
+    public static function once(): InvokedCountMatcher
+    {
+        return new InvokedCountMatcher(1);
+    }
+
+    /**
+     * Returns a matcher that matches when the method is executed
+     * exactly $count times.
+     */
+    public static function exactly(int $count): InvokedCountMatcher
+    {
+        return new InvokedCountMatcher($count);
+    }
+
+    /**
+     * Returns a matcher that matches when the method is executed
+     * at most N times.
+     */
+    public static function atMost(int $allowedInvocations): InvokedAtMostCountMatcher
+    {
+        return new InvokedAtMostCountMatcher($allowedInvocations);
+    }
+
+    /**
+     * Returns a matcher that matches when the method is executed
+     * at the given index.
+     *
+     * @deprecated https://github.com/sebastianbergmann/phpunit/issues/4297
+     * @codeCoverageIgnore
+     */
+    public static function at(int $index): InvokedAtIndexMatcher
+    {
+        $stack = debug_backtrace();
+
+        while (!empty($stack)) {
+            $frame = array_pop($stack);
+
+            if (isset($frame['object']) && $frame['object'] instanceof self) {
+                $frame['object']->addWarning(
+                    'The at() matcher has been deprecated. It will be removed in PHPUnit 10. Please refactor your test to not rely on the order in which methods are invoked.'
+                );
+
+                break;
+            }
+        }
+
+        return new InvokedAtIndexMatcher($index);
+    }
+
+    public static function returnValue($value): ReturnStub
+    {
+        return new ReturnStub($value);
+    }
+
+    public static function returnValueMap(array $valueMap): ReturnValueMapStub
+    {
+        return new ReturnValueMapStub($valueMap);
+    }
+
+    public static function returnArgument(int $argumentIndex): ReturnArgumentStub
+    {
+        return new ReturnArgumentStub($argumentIndex);
+    }
+
+    public static function returnCallback($callback): ReturnCallbackStub
+    {
+        return new ReturnCallbackStub($callback);
+    }
+
+    /**
+     * Returns the current object.
+     *
+     * This method is useful when mocking a fluent interface.
+     */
+    public static function returnSelf(): ReturnSelfStub
+    {
+        return new ReturnSelfStub;
+    }
+
+    public static function throwException(Throwable $exception): ExceptionStub
+    {
+        return new ExceptionStub($exception);
+    }
+
+    public static function onConsecutiveCalls(...$args): ConsecutiveCallsStub
+    {
+        return new ConsecutiveCallsStub($args);
+    }
+
+    /**
+     * @param int|string $dataName
+     *
+     * @internal This method is not covered by the backward compatibility promise for PHPUnit
+     */
+    public function __construct(?string $name = null, array $data = [], $dataName = '')
+    {
+        if ($name !== null) {
+            $this->setName($name);
+        }
+
+        $this->data     = $data;
+        $this->dataName = $dataName;
+    }
+
+    /**
+     * This method is called before the first test of this test class is run.
+     */
+    public static function setUpBeforeClass(): void
+    {
+    }
+
+    /**
+     * This method is called after the last test of this test class is run.
+     */
+    public static function tearDownAfterClass(): void
+    {
+    }
+
+    /**
+     * This method is called before each test.
+     */
+    protected function setUp(): void
+    {
+    }
+
+    /**
+     * This method is called after each test.
+     */
+    protected function tearDown(): void
+    {
+    }
+
+    /**
+     * Returns a string representation of the test case.
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws Exception
+     */
+    public function toString(): string
+    {
+        try {
+            $class = new ReflectionClass($this);
+            // @codeCoverageIgnoreStart
+        } catch (ReflectionException $e) {
+            throw new Exception(
+                $e->getMessage(),
+                (int) $e->getCode(),
+                $e
+            );
+        }
+        // @codeCoverageIgnoreEnd
+
+        $buffer = sprintf(
+            '%s::%s',
+            $class->name,
+            $this->getName(false)
+        );
+
+        return $buffer . $this->getDataSetAsString();
+    }
+
+    public function count(): int
+    {
+        return 1;
+    }
+
+    public function getActualOutputForAssertion(): string
+    {
+        $this->outputRetrievedForAssertion = true;
+
+        return $this->getActualOutput();
+    }
+
+    public function expectOutputRegex(string $expectedRegex): void
+    {
+        $this->outputExpectedRegex = $expectedRegex;
+    }
+
+    public function expectOutputString(string $expectedString): void
+    {
+        $this->outputExpectedString = $expectedString;
+    }
+
+    /**
+     * @psalm-param class-string<\Throwable> $exception
+     */
+    public function expectException(string $exception): void
+    {
+        // @codeCoverageIgnoreStart
+        switch ($exception) {
+            case Deprecated::class:
+                $this->addWarning('Support for using expectException() with PHPUnit\Framework\Error\Deprecated is deprecated and will be removed in PHPUnit 10. Use expectDeprecation() instead.');
+
+            break;
+
+            case Error::class:
+                $this->addWarning('Support for using expectException() with PHPUnit\Framework\Error\Error is deprecated and will be removed in PHPUnit 10. Use expectError() instead.');
+
+            break;
+
+            case Notice::class:
+                $this->addWarning('Support for using expectException() with PHPUnit\Framework\Error\Notice is deprecated and will be removed in PHPUnit 10. Use expectNotice() instead.');
+
+            break;
+
+            case WarningError::class:
+                $this->addWarning('Support for using expectException() with PHPUnit\Framework\Error\Warning is deprecated and will be removed in PHPUnit 10. Use expectWarning() instead.');
+
+            break;
+        }
+        // @codeCoverageIgnoreEnd
+
+        $this->expectedException = $exception;
+    }
+
+    /**
+     * @param int|string $code
+     */
+    public function expectExceptionCode($code): void
+    {
+        $this->expectedExceptionCode = $code;
+    }
+
+    public function expectExceptionMessage(string $message): void
+    {
+        $this->expectedExceptionMessage = $message;
+    }
+
+    public function expectExceptionMessageMatches(string $regularExpression): void
+    {
+        $this->expectedExceptionMessageRegExp = $regularExpression;
+    }
+
+    /**
+     * Sets up an expectation for an exception to be raised by the code under test.
+     * Information for expected exception class, expected exception message, and
+     * expected exception code are retrieved from a given Exception object.
+     */
+    public function expectExceptionObject(\Exception $exception): void
+    {
+        $this->expectException(get_class($exception));
+        $this->expectExceptionMessage($exception->getMessage());
+        $this->expectExceptionCode($exception->getCode());
+    }
+
+    public function expectNotToPerformAssertions(): void
+    {
+        $this->doesNotPerformAssertions = true;
+    }
+
+    public function expectDeprecation(): void
+    {
+        $this->expectedException = Deprecated::class;
+    }
+
+    public function expectDeprecationMessage(string $message): void
+    {
+        $this->expectExceptionMessage($message);
+    }
+
+    public function expectDeprecationMessageMatches(string $regularExpression): void
+    {
+        $this->expectExceptionMessageMatches($regularExpression);
+    }
+
+    public function expectNotice(): void
+    {
+        $this->expectedException = Notice::class;
+    }
+
+    public function expectNoticeMessage(string $message): void
+    {
+        $this->expectExceptionMessage($message);
+    }
+
+    public function expectNoticeMessageMatches(string $regularExpression): void
+    {
+        $this->expectExceptionMessageMatches($regularExpression);
+    }
+
+    public function expectWarning(): void
+    {
+        $this->expectedException = WarningError::class;
+    }
+
+    public function expectWarningMessage(string $message): void
+    {
+        $this->expectExceptionMessage($message);
+    }
+
+    public function expectWarningMessageMatches(string $regularExpression): void
+    {
+        $this->expectExceptionMessageMatches($regularExpression);
+    }
+
+    public function expectError(): void
+    {
+        $this->expectedException = Error::class;
+    }
+
+    public function expectErrorMessage(string $message): void
+    {
+        $this->expectExceptionMessage($message);
+    }
+
+    public function expectErrorMessageMatches(string $regularExpression): void
+    {
+        $this->expectExceptionMessageMatches($regularExpression);
+    }
+
+    public function getStatus(): int
+    {
+        return $this->status;
+    }
+
+    public function markAsRisky(): void
+    {
+        $this->status = BaseTestRunner::STATUS_RISKY;
+    }
+
+    public function getStatusMessage(): string
+    {
+        return $this->statusMessage;
+    }
+
+    public function hasFailed(): bool
+    {
+        $status = $this->getStatus();
+
+        return $status === BaseTestRunner::STATUS_FAILURE || $status === BaseTestRunner::STATUS_ERROR;
+    }
+
+    /**
+     * Runs the test case and collects the results in a TestResult object.
+     * If no TestResult object is passed a new one will be created.
+     *
+     * @throws \SebastianBergmann\CodeCoverage\InvalidArgumentException
+     * @throws \SebastianBergmann\CodeCoverage\UnintentionallyCoveredCodeException
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws CodeCoverageException
+     * @throws UtilException
+     */
+    public function run(TestResult $result = null): TestResult
+    {
+        if ($result === null) {
+            $result = $this->createResult();
+        }
+
+        if (!$this instanceof ErrorTestCase && !$this instanceof WarningTestCase) {
+            $this->setTestResultObject($result);
+        }
+
+        if (!$this instanceof ErrorTestCase &&
+            !$this instanceof WarningTestCase &&
+            !$this instanceof SkippedTestCase &&
+            !$this->handleDependencies()) {
+            return $result;
+        }
+
+        if ($this->runInSeparateProcess()) {
+            $runEntireClass = $this->runClassInSeparateProcess && !$this->runTestInSeparateProcess;
+
+            try {
+                $class = new ReflectionClass($this);
+                // @codeCoverageIgnoreStart
+            } catch (ReflectionException $e) {
+                throw new Exception(
+                    $e->getMessage(),
+                    (int) $e->getCode(),
+                    $e
+                );
+            }
+            // @codeCoverageIgnoreEnd
+
+            if ($runEntireClass) {
+                $template = new Template(
+                    __DIR__ . '/../Util/PHP/Template/TestCaseClass.tpl'
+                );
+            } else {
+                $template = new Template(
+                    __DIR__ . '/../Util/PHP/Template/TestCaseMethod.tpl'
+                );
+            }
+
+            if ($this->preserveGlobalState) {
+                $constants     = GlobalState::getConstantsAsString();
+                $globals       = GlobalState::getGlobalsAsString();
+                $includedFiles = GlobalState::getIncludedFilesAsString();
+                $iniSettings   = GlobalState::getIniSettingsAsString();
+            } else {
+                $constants = '';
+
+                if (!empty($GLOBALS['__PHPUNIT_BOOTSTRAP'])) {
+                    $globals = '$GLOBALS[\'__PHPUNIT_BOOTSTRAP\'] = ' . var_export($GLOBALS['__PHPUNIT_BOOTSTRAP'], true) . ";\n";
+                } else {
+                    $globals = '';
+                }
+
+                $includedFiles = '';
+                $iniSettings   = '';
+            }
+
+            $coverage                                   = $result->getCollectCodeCoverageInformation() ? 'true' : 'false';
+            $isStrictAboutTestsThatDoNotTestAnything    = $result->isStrictAboutTestsThatDoNotTestAnything() ? 'true' : 'false';
+            $isStrictAboutOutputDuringTests             = $result->isStrictAboutOutputDuringTests() ? 'true' : 'false';
+            $enforcesTimeLimit                          = $result->enforcesTimeLimit() ? 'true' : 'false';
+            $isStrictAboutTodoAnnotatedTests            = $result->isStrictAboutTodoAnnotatedTests() ? 'true' : 'false';
+            $isStrictAboutResourceUsageDuringSmallTests = $result->isStrictAboutResourceUsageDuringSmallTests() ? 'true' : 'false';
+
+            if (defined('PHPUNIT_COMPOSER_INSTALL')) {
+                $composerAutoload = var_export(PHPUNIT_COMPOSER_INSTALL, true);
+            } else {
+                $composerAutoload = '\'\'';
+            }
+
+            if (defined('__PHPUNIT_PHAR__')) {
+                $phar = var_export(__PHPUNIT_PHAR__, true);
+            } else {
+                $phar = '\'\'';
+            }
+
+            $codeCoverage               = $result->getCodeCoverage();
+            $codeCoverageFilter         = null;
+            $cachesStaticAnalysis       = 'false';
+            $codeCoverageCacheDirectory = null;
+            $driverMethod               = 'forLineCoverage';
+
+            if ($codeCoverage) {
+                $codeCoverageFilter = $codeCoverage->filter();
+
+                if ($codeCoverage->collectsBranchAndPathCoverage()) {
+                    $driverMethod = 'forLineAndPathCoverage';
+                }
+
+                if ($codeCoverage->cachesStaticAnalysis()) {
+                    $cachesStaticAnalysis       = 'true';
+                    $codeCoverageCacheDirectory = $codeCoverage->cacheDirectory();
+                }
+            }
+
+            $data                       = var_export(serialize($this->data), true);
+            $dataName                   = var_export($this->dataName, true);
+            $dependencyInput            = var_export(serialize($this->dependencyInput), true);
+            $includePath                = var_export(get_include_path(), true);
+            $codeCoverageFilter         = var_export(serialize($codeCoverageFilter), true);
+            $codeCoverageCacheDirectory = var_export(serialize($codeCoverageCacheDirectory), true);
+            // must do these fixes because TestCaseMethod.tpl has unserialize('{data}') in it, and we can't break BC
+            // the lines above used to use addcslashes() rather than var_export(), which breaks null byte escape sequences
+            $data                       = "'." . $data . ".'";
+            $dataName                   = "'.(" . $dataName . ").'";
+            $dependencyInput            = "'." . $dependencyInput . ".'";
+            $includePath                = "'." . $includePath . ".'";
+            $codeCoverageFilter         = "'." . $codeCoverageFilter . ".'";
+            $codeCoverageCacheDirectory = "'." . $codeCoverageCacheDirectory . ".'";
+
+            $configurationFilePath = $GLOBALS['__PHPUNIT_CONFIGURATION_FILE'] ?? '';
+
+            $var = [
+                'composerAutoload'                           => $composerAutoload,
+                'phar'                                       => $phar,
+                'filename'                                   => $class->getFileName(),
+                'className'                                  => $class->getName(),
+                'collectCodeCoverageInformation'             => $coverage,
+                'cachesStaticAnalysis'                       => $cachesStaticAnalysis,
+                'codeCoverageCacheDirectory'                 => $codeCoverageCacheDirectory,
+                'driverMethod'                               => $driverMethod,
+                'data'                                       => $data,
+                'dataName'                                   => $dataName,
+                'dependencyInput'                            => $dependencyInput,
+                'constants'                                  => $constants,
+                'globals'                                    => $globals,
+                'include_path'                               => $includePath,
+                'included_files'                             => $includedFiles,
+                'iniSettings'                                => $iniSettings,
+                'isStrictAboutTestsThatDoNotTestAnything'    => $isStrictAboutTestsThatDoNotTestAnything,
+                'isStrictAboutOutputDuringTests'             => $isStrictAboutOutputDuringTests,
+                'enforcesTimeLimit'                          => $enforcesTimeLimit,
+                'isStrictAboutTodoAnnotatedTests'            => $isStrictAboutTodoAnnotatedTests,
+                'isStrictAboutResourceUsageDuringSmallTests' => $isStrictAboutResourceUsageDuringSmallTests,
+                'codeCoverageFilter'                         => $codeCoverageFilter,
+                'configurationFilePath'                      => $configurationFilePath,
+                'name'                                       => $this->getName(false),
+            ];
+
+            if (!$runEntireClass) {
+                $var['methodName'] = $this->name;
+            }
+
+            $template->setVar($var);
+
+            $php = AbstractPhpProcess::factory();
+            $php->runTestJob($template->render(), $this, $result);
+        } else {
+            $result->run($this);
+        }
+
+        $this->result = null;
+
+        return $result;
+    }
+
+    /**
+     * Returns a builder object to create mock objects using a fluent interface.
+     *
+     * @psalm-template RealInstanceType of object
+     * @psalm-param class-string<RealInstanceType> $className
+     * @psalm-return MockBuilder<RealInstanceType>
+     */
+    public function getMockBuilder(string $className): MockBuilder
+    {
+        $this->recordDoubledType($className);
+
+        return new MockBuilder($this, $className);
+    }
+
+    public function registerComparator(Comparator $comparator): void
+    {
+        ComparatorFactory::getInstance()->register($comparator);
+
+        $this->customComparators[] = $comparator;
+    }
+
+    /**
+     * @return string[]
+     *
+     * @internal This method is not covered by the backward compatibility promise for PHPUnit
+     */
+    public function doubledTypes(): array
+    {
+        return array_unique($this->doubledTypes);
+    }
+
+    /**
+     * @internal This method is not covered by the backward compatibility promise for PHPUnit
+     */
+    public function getGroups(): array
+    {
+        return $this->groups;
+    }
+
+    /**
+     * @internal This method is not covered by the backward compatibility promise for PHPUnit
+     */
+    public function setGroups(array $groups): void
+    {
+        $this->groups = $groups;
+    }
+
+    /**
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     *
+     * @internal This method is not covered by the backward compatibility promise for PHPUnit
+     */
+    public function getName(bool $withDataSet = true): string
+    {
+        if ($withDataSet) {
+            return $this->name . $this->getDataSetAsString(false);
+        }
+
+        return $this->name;
+    }
+
+    /**
+     * Returns the size of the test.
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     *
+     * @internal This method is not covered by the backward compatibility promise for PHPUnit
+     */
+    public function getSize(): int
+    {
+        return TestUtil::getSize(
+            static::class,
+            $this->getName(false)
+        );
+    }
+
+    /**
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     *
+     * @internal This method is not covered by the backward compatibility promise for PHPUnit
+     */
+    public function hasSize(): bool
+    {
+        return $this->getSize() !== TestUtil::UNKNOWN;
+    }
+
+    /**
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     *
+     * @internal This method is not covered by the backward compatibility promise for PHPUnit
+     */
+    public function isSmall(): bool
+    {
+        return $this->getSize() === TestUtil::SMALL;
+    }
+
+    /**
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     *
+     * @internal This method is not covered by the backward compatibility promise for PHPUnit
+     */
+    public function isMedium(): bool
+    {
+        return $this->getSize() === TestUtil::MEDIUM;
+    }
+
+    /**
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     *
+     * @internal This method is not covered by the backward compatibility promise for PHPUnit
+     */
+    public function isLarge(): bool
+    {
+        return $this->getSize() === TestUtil::LARGE;
+    }
+
+    /**
+     * @internal This method is not covered by the backward compatibility promise for PHPUnit
+     */
+    public function getActualOutput(): string
+    {
+        if (!$this->outputBufferingActive) {
+            return $this->output;
+        }
+
+        return (string) ob_get_contents();
+    }
+
+    /**
+     * @internal This method is not covered by the backward compatibility promise for PHPUnit
+     */
+    public function hasOutput(): bool
+    {
+        if ($this->output === '') {
+            return false;
+        }
+
+        if ($this->hasExpectationOnOutput()) {
+            return false;
+        }
+
+        return true;
+    }
+
+    /**
+     * @internal This method is not covered by the backward compatibility promise for PHPUnit
+     */
+    public function doesNotPerformAssertions(): bool
+    {
+        return $this->doesNotPerformAssertions;
+    }
+
+    /**
+     * @internal This method is not covered by the backward compatibility promise for PHPUnit
+     */
+    public function hasExpectationOnOutput(): bool
+    {
+        return is_string($this->outputExpectedString) || is_string($this->outputExpectedRegex) || $this->outputRetrievedForAssertion;
+    }
+
+    /**
+     * @internal This method is not covered by the backward compatibility promise for PHPUnit
+     */
+    public function getExpectedException(): ?string
+    {
+        return $this->expectedException;
+    }
+
+    /**
+     * @return null|int|string
+     *
+     * @internal This method is not covered by the backward compatibility promise for PHPUnit
+     */
+    public function getExpectedExceptionCode()
+    {
+        return $this->expectedExceptionCode;
+    }
+
+    /**
+     * @internal This method is not covered by the backward compatibility promise for PHPUnit
+     */
+    public function getExpectedExceptionMessage(): ?string
+    {
+        return $this->expectedExceptionMessage;
+    }
+
+    /**
+     * @internal This method is not covered by the backward compatibility promise for PHPUnit
+     */
+    public function getExpectedExceptionMessageRegExp(): ?string
+    {
+        return $this->expectedExceptionMessageRegExp;
+    }
+
+    /**
+     * @internal This method is not covered by the backward compatibility promise for PHPUnit
+     */
+    public function setRegisterMockObjectsFromTestArgumentsRecursively(bool $flag): void
+    {
+        $this->registerMockObjectsFromTestArgumentsRecursively = $flag;
+    }
+
+    /**
+     * @throws Throwable
+     *
+     * @internal This method is not covered by the backward compatibility promise for PHPUnit
+     */
+    public function runBare(): void
+    {
+        $this->numAssertions = 0;
+
+        $this->snapshotGlobalState();
+        $this->startOutputBuffering();
+        clearstatcache();
+        $currentWorkingDirectory = getcwd();
+
+        $hookMethods = TestUtil::getHookMethods(static::class);
+
+        $hasMetRequirements = false;
+
+        try {
+            $this->checkRequirements();
+            $hasMetRequirements = true;
+
+            if ($this->inIsolation) {
+                foreach ($hookMethods['beforeClass'] as $method) {
+                    $this->{$method}();
+                }
+            }
+
+            $this->setDoesNotPerformAssertionsFromAnnotation();
+
+            foreach ($hookMethods['before'] as $method) {
+                $this->{$method}();
+            }
+
+            foreach ($hookMethods['preCondition'] as $method) {
+                $this->{$method}();
+            }
+
+            $this->testResult = $this->runTest();
+            $this->verifyMockObjects();
+
+            foreach ($hookMethods['postCondition'] as $method) {
+                $this->{$method}();
+            }
+
+            if (!empty($this->warnings)) {
+                throw new Warning(
+                    implode(
+                        "\n",
+                        array_unique($this->warnings)
+                    )
+                );
+            }
+
+            $this->status = BaseTestRunner::STATUS_PASSED;
+        } catch (IncompleteTest $e) {
+            $this->status        = BaseTestRunner::STATUS_INCOMPLETE;
+            $this->statusMessage = $e->getMessage();
+        } catch (SkippedTest $e) {
+            $this->status        = BaseTestRunner::STATUS_SKIPPED;
+            $this->statusMessage = $e->getMessage();
+        } catch (Warning $e) {
+            $this->status        = BaseTestRunner::STATUS_WARNING;
+            $this->statusMessage = $e->getMessage();
+        } catch (AssertionFailedError $e) {
+            $this->status        = BaseTestRunner::STATUS_FAILURE;
+            $this->statusMessage = $e->getMessage();
+        } catch (PredictionException $e) {
+            $this->status        = BaseTestRunner::STATUS_FAILURE;
+            $this->statusMessage = $e->getMessage();
+        } catch (Throwable $_e) {
+            $e                   = $_e;
+            $this->status        = BaseTestRunner::STATUS_ERROR;
+            $this->statusMessage = $_e->getMessage();
+        }
+
+        $this->mockObjects = [];
+        $this->prophet     = null;
+
+        // Tear down the fixture. An exception raised in tearDown() will be
+        // caught and passed on when no exception was raised before.
+        try {
+            if ($hasMetRequirements) {
+                foreach ($hookMethods['after'] as $method) {
+                    $this->{$method}();
+                }
+
+                if ($this->inIsolation) {
+                    foreach ($hookMethods['afterClass'] as $method) {
+                        $this->{$method}();
+                    }
+                }
+            }
+        } catch (Throwable $_e) {
+            $e = $e ?? $_e;
+        }
+
+        try {
+            $this->stopOutputBuffering();
+        } catch (RiskyTestError $_e) {
+            $e = $e ?? $_e;
+        }
+
+        if (isset($_e)) {
+            $this->status        = BaseTestRunner::STATUS_ERROR;
+            $this->statusMessage = $_e->getMessage();
+        }
+
+        clearstatcache();
+
+        if ($currentWorkingDirectory !== getcwd()) {
+            chdir($currentWorkingDirectory);
+        }
+
+        $this->restoreGlobalState();
+        $this->unregisterCustomComparators();
+        $this->cleanupIniSettings();
+        $this->cleanupLocaleSettings();
+        libxml_clear_errors();
+
+        // Perform assertion on output.
+        if (!isset($e)) {
+            try {
+                if ($this->outputExpectedRegex !== null) {
+                    $this->assertMatchesRegularExpression($this->outputExpectedRegex, $this->output);
+                } elseif ($this->outputExpectedString !== null) {
+                    $this->assertEquals($this->outputExpectedString, $this->output);
+                }
+            } catch (Throwable $_e) {
+                $e = $_e;
+            }
+        }
+
+        // Workaround for missing "finally".
+        if (isset($e)) {
+            if ($e instanceof PredictionException) {
+                $e = new AssertionFailedError($e->getMessage());
+            }
+
+            $this->onNotSuccessfulTest($e);
+        }
+    }
+
+    /**
+     * @internal This method is not covered by the backward compatibility promise for PHPUnit
+     */
+    public function setName(string $name): void
+    {
+        $this->name = $name;
+
+        if (is_callable($this->sortId(), true)) {
+            $this->providedTests = [new ExecutionOrderDependency($this->sortId())];
+        }
+    }
+
+    /**
+     * @param list<ExecutionOrderDependency> $dependencies
+     *
+     * @internal This method is not covered by the backward compatibility promise for PHPUnit
+     */
+    public function setDependencies(array $dependencies): void
+    {
+        $this->dependencies = $dependencies;
+    }
+
+    /**
+     * @internal This method is not covered by the backward compatibility promise for PHPUnit
+     */
+    public function setDependencyInput(array $dependencyInput): void
+    {
+        $this->dependencyInput = $dependencyInput;
+    }
+
+    /**
+     * @internal This method is not covered by the backward compatibility promise for PHPUnit
+     */
+    public function setBeStrictAboutChangesToGlobalState(?bool $beStrictAboutChangesToGlobalState): void
+    {
+        $this->beStrictAboutChangesToGlobalState = $beStrictAboutChangesToGlobalState;
+    }
+
+    /**
+     * @internal This method is not covered by the backward compatibility promise for PHPUnit
+     */
+    public function setBackupGlobals(?bool $backupGlobals): void
+    {
+        if ($this->backupGlobals === null && $backupGlobals !== null) {
+            $this->backupGlobals = $backupGlobals;
+        }
+    }
+
+    /**
+     * @internal This method is not covered by the backward compatibility promise for PHPUnit
+     */
+    public function setBackupStaticAttributes(?bool $backupStaticAttributes): void
+    {
+        if ($this->backupStaticAttributes === null && $backupStaticAttributes !== null) {
+            $this->backupStaticAttributes = $backupStaticAttributes;
+        }
+    }
+
+    /**
+     * @internal This method is not covered by the backward compatibility promise for PHPUnit
+     */
+    public function setRunTestInSeparateProcess(bool $runTestInSeparateProcess): void
+    {
+        if ($this->runTestInSeparateProcess === null) {
+            $this->runTestInSeparateProcess = $runTestInSeparateProcess;
+        }
+    }
+
+    /**
+     * @internal This method is not covered by the backward compatibility promise for PHPUnit
+     */
+    public function setRunClassInSeparateProcess(bool $runClassInSeparateProcess): void
+    {
+        if ($this->runClassInSeparateProcess === null) {
+            $this->runClassInSeparateProcess = $runClassInSeparateProcess;
+        }
+    }
+
+    /**
+     * @internal This method is not covered by the backward compatibility promise for PHPUnit
+     */
+    public function setPreserveGlobalState(bool $preserveGlobalState): void
+    {
+        $this->preserveGlobalState = $preserveGlobalState;
+    }
+
+    /**
+     * @internal This method is not covered by the backward compatibility promise for PHPUnit
+     */
+    public function setInIsolation(bool $inIsolation): void
+    {
+        $this->inIsolation = $inIsolation;
+    }
+
+    /**
+     * @internal This method is not covered by the backward compatibility promise for PHPUnit
+     */
+    public function isInIsolation(): bool
+    {
+        return $this->inIsolation;
+    }
+
+    /**
+     * @internal This method is not covered by the backward compatibility promise for PHPUnit
+     */
+    public function getResult()
+    {
+        return $this->testResult;
+    }
+
+    /**
+     * @internal This method is not covered by the backward compatibility promise for PHPUnit
+     */
+    public function setResult($result): void
+    {
+        $this->testResult = $result;
+    }
+
+    /**
+     * @internal This method is not covered by the backward compatibility promise for PHPUnit
+     */
+    public function setOutputCallback(callable $callback): void
+    {
+        $this->outputCallback = $callback;
+    }
+
+    /**
+     * @internal This method is not covered by the backward compatibility promise for PHPUnit
+     */
+    public function getTestResultObject(): ?TestResult
+    {
+        return $this->result;
+    }
+
+    /**
+     * @internal This method is not covered by the backward compatibility promise for PHPUnit
+     */
+    public function setTestResultObject(TestResult $result): void
+    {
+        $this->result = $result;
+    }
+
+    /**
+     * @internal This method is not covered by the backward compatibility promise for PHPUnit
+     */
+    public function registerMockObject(MockObject $mockObject): void
+    {
+        $this->mockObjects[] = $mockObject;
+    }
+
+    /**
+     * @internal This method is not covered by the backward compatibility promise for PHPUnit
+     */
+    public function addToAssertionCount(int $count): void
+    {
+        $this->numAssertions += $count;
+    }
+
+    /**
+     * Returns the number of assertions performed by this test.
+     *
+     * @internal This method is not covered by the backward compatibility promise for PHPUnit
+     */
+    public function getNumAssertions(): int
+    {
+        return $this->numAssertions;
+    }
+
+    /**
+     * @internal This method is not covered by the backward compatibility promise for PHPUnit
+     */
+    public function usesDataProvider(): bool
+    {
+        return !empty($this->data);
+    }
+
+    /**
+     * @return int|string
+     *
+     * @internal This method is not covered by the backward compatibility promise for PHPUnit
+     */
+    public function dataName()
+    {
+        return $this->dataName;
+    }
+
+    /**
+     * @internal This method is not covered by the backward compatibility promise for PHPUnit
+     */
+    public function getDataSetAsString(bool $includeData = true): string
+    {
+        $buffer = '';
+
+        if (!empty($this->data)) {
+            if (is_int($this->dataName)) {
+                $buffer .= sprintf(' with data set #%d', $this->dataName);
+            } else {
+                $buffer .= sprintf(' with data set "%s"', $this->dataName);
+            }
+
+            if ($includeData) {
+                $exporter = new Exporter;
+
+                $buffer .= sprintf(' (%s)', $exporter->shortenedRecursiveExport($this->data));
+            }
+        }
+
+        return $buffer;
+    }
+
+    /**
+     * Gets the data set of a TestCase.
+     *
+     * @internal This method is not covered by the backward compatibility promise for PHPUnit
+     */
+    public function getProvidedData(): array
+    {
+        return $this->data;
+    }
+
+    /**
+     * @internal This method is not covered by the backward compatibility promise for PHPUnit
+     */
+    public function addWarning(string $warning): void
+    {
+        $this->warnings[] = $warning;
+    }
+
+    public function sortId(): string
+    {
+        $id = $this->name;
+
+        if (strpos($id, '::') === false) {
+            $id = static::class . '::' . $id;
+        }
+
+        if ($this->usesDataProvider()) {
+            $id .= $this->getDataSetAsString(false);
+        }
+
+        return $id;
+    }
+
+    /**
+     * Returns the normalized test name as class::method.
+     *
+     * @return list<ExecutionOrderDependency>
+     */
+    public function provides(): array
+    {
+        return $this->providedTests;
+    }
+
+    /**
+     * Returns a list of normalized dependency names, class::method.
+     *
+     * This list can differ from the raw dependencies as the resolver has
+     * no need for the [!][shallow]clone prefix that is filtered out
+     * during normalization.
+     *
+     * @return list<ExecutionOrderDependency>
+     */
+    public function requires(): array
+    {
+        return $this->dependencies;
+    }
+
+    /**
+     * Override to run the test and assert its state.
+     *
+     * @throws \SebastianBergmann\ObjectEnumerator\InvalidArgumentException
+     * @throws AssertionFailedError
+     * @throws Exception
+     * @throws ExpectationFailedException
+     * @throws Throwable
+     */
+    protected function runTest()
+    {
+        if (trim($this->name) === '') {
+            throw new Exception(
+                'PHPUnit\Framework\TestCase::$name must be a non-blank string.'
+            );
+        }
+
+        $testArguments = array_merge($this->data, $this->dependencyInput);
+
+        $this->registerMockObjectsFromTestArguments($testArguments);
+
+        try {
+            $testResult = $this->{$this->name}(...array_values($testArguments));
+        } catch (Throwable $exception) {
+            if (!$this->checkExceptionExpectations($exception)) {
+                throw $exception;
+            }
+
+            if ($this->expectedException !== null) {
+                $this->assertThat(
+                    $exception,
+                    new ExceptionConstraint(
+                        $this->expectedException
+                    )
+                );
+            }
+
+            if ($this->expectedExceptionMessage !== null) {
+                $this->assertThat(
+                    $exception,
+                    new ExceptionMessage(
+                        $this->expectedExceptionMessage
+                    )
+                );
+            }
+
+            if ($this->expectedExceptionMessageRegExp !== null) {
+                $this->assertThat(
+                    $exception,
+                    new ExceptionMessageRegularExpression(
+                        $this->expectedExceptionMessageRegExp
+                    )
+                );
+            }
+
+            if ($this->expectedExceptionCode !== null) {
+                $this->assertThat(
+                    $exception,
+                    new ExceptionCode(
+                        $this->expectedExceptionCode
+                    )
+                );
+            }
+
+            return;
+        }
+
+        if ($this->expectedException !== null) {
+            $this->assertThat(
+                null,
+                new ExceptionConstraint(
+                    $this->expectedException
+                )
+            );
+        } elseif ($this->expectedExceptionMessage !== null) {
+            $this->numAssertions++;
+
+            throw new AssertionFailedError(
+                sprintf(
+                    'Failed asserting that exception with message "%s" is thrown',
+                    $this->expectedExceptionMessage
+                )
+            );
+        } elseif ($this->expectedExceptionMessageRegExp !== null) {
+            $this->numAssertions++;
+
+            throw new AssertionFailedError(
+                sprintf(
+                    'Failed asserting that exception with message matching "%s" is thrown',
+                    $this->expectedExceptionMessageRegExp
+                )
+            );
+        } elseif ($this->expectedExceptionCode !== null) {
+            $this->numAssertions++;
+
+            throw new AssertionFailedError(
+                sprintf(
+                    'Failed asserting that exception with code "%s" is thrown',
+                    $this->expectedExceptionCode
+                )
+            );
+        }
+
+        return $testResult;
+    }
+
+    /**
+     * This method is a wrapper for the ini_set() function that automatically
+     * resets the modified php.ini setting to its original value after the
+     * test is run.
+     *
+     * @throws Exception
+     */
+    protected function iniSet(string $varName, string $newValue): void
+    {
+        $currentValue = ini_set($varName, $newValue);
+
+        if ($currentValue !== false) {
+            $this->iniSettings[$varName] = $currentValue;
+        } else {
+            throw new Exception(
+                sprintf(
+                    'INI setting "%s" could not be set to "%s".',
+                    $varName,
+                    $newValue
+                )
+            );
+        }
+    }
+
+    /**
+     * This method is a wrapper for the setlocale() function that automatically
+     * resets the locale to its original value after the test is run.
+     *
+     * @throws Exception
+     */
+    protected function setLocale(...$args): void
+    {
+        if (count($args) < 2) {
+            throw new Exception;
+        }
+
+        [$category, $locale] = $args;
+
+        if (!in_array($category, self::LOCALE_CATEGORIES, true)) {
+            throw new Exception;
+        }
+
+        if (!is_array($locale) && !is_string($locale)) {
+            throw new Exception;
+        }
+
+        $this->locale[$category] = setlocale($category, 0);
+
+        $result = setlocale(...$args);
+
+        if ($result === false) {
+            throw new Exception(
+                'The locale functionality is not implemented on your platform, ' .
+                'the specified locale does not exist or the category name is ' .
+                'invalid.'
+            );
+        }
+    }
+
+    /**
+     * Makes configurable stub for the specified class.
+     *
+     * @psalm-template RealInstanceType of object
+     * @psalm-param    class-string<RealInstanceType> $originalClassName
+     * @psalm-return   Stub&RealInstanceType
+     */
+    protected function createStub(string $originalClassName): Stub
+    {
+        return $this->createMockObject($originalClassName);
+    }
+
+    /**
+     * Returns a mock object for the specified class.
+     *
+     * @psalm-template RealInstanceType of object
+     * @psalm-param class-string<RealInstanceType> $originalClassName
+     * @psalm-return MockObject&RealInstanceType
+     */
+    protected function createMock(string $originalClassName): MockObject
+    {
+        return $this->createMockObject($originalClassName);
+    }
+
+    /**
+     * Returns a configured mock object for the specified class.
+     *
+     * @psalm-template RealInstanceType of object
+     * @psalm-param class-string<RealInstanceType> $originalClassName
+     * @psalm-return MockObject&RealInstanceType
+     */
+    protected function createConfiguredMock(string $originalClassName, array $configuration): MockObject
+    {
+        $o = $this->createMockObject($originalClassName);
+
+        foreach ($configuration as $method => $return) {
+            $o->method($method)->willReturn($return);
+        }
+
+        return $o;
+    }
+
+    /**
+     * Returns a partial mock object for the specified class.
+     *
+     * @param string[] $methods
+     *
+     * @psalm-template RealInstanceType of object
+     * @psalm-param class-string<RealInstanceType> $originalClassName
+     * @psalm-return MockObject&RealInstanceType
+     */
+    protected function createPartialMock(string $originalClassName, array $methods): MockObject
+    {
+        try {
+            $reflector = new ReflectionClass($originalClassName);
+            // @codeCoverageIgnoreStart
+        } catch (ReflectionException $e) {
+            throw new Exception(
+                $e->getMessage(),
+                (int) $e->getCode(),
+                $e
+            );
+        }
+        // @codeCoverageIgnoreEnd
+
+        $mockedMethodsThatDontExist = array_filter(
+            $methods,
+            static function (string $method) use ($reflector) {
+                return !$reflector->hasMethod($method);
+            }
+        );
+
+        if ($mockedMethodsThatDontExist) {
+            $this->addWarning(
+                sprintf(
+                    'createPartialMock() called with method(s) %s that do not exist in %s. This will not be allowed in future versions of PHPUnit.',
+                    implode(', ', $mockedMethodsThatDontExist),
+                    $originalClassName
+                )
+            );
+        }
+
+        return $this->getMockBuilder($originalClassName)
+                    ->disableOriginalConstructor()
+                    ->disableOriginalClone()
+                    ->disableArgumentCloning()
+                    ->disallowMockingUnknownTypes()
+                    ->setMethods(empty($methods) ? null : $methods)
+                    ->getMock();
+    }
+
+    /**
+     * Returns a test proxy for the specified class.
+     *
+     * @psalm-template RealInstanceType of object
+     * @psalm-param class-string<RealInstanceType> $originalClassName
+     * @psalm-return MockObject&RealInstanceType
+     */
+    protected function createTestProxy(string $originalClassName, array $constructorArguments = []): MockObject
+    {
+        return $this->getMockBuilder($originalClassName)
+                    ->setConstructorArgs($constructorArguments)
+                    ->enableProxyingToOriginalMethods()
+                    ->getMock();
+    }
+
+    /**
+     * Mocks the specified class and returns the name of the mocked class.
+     *
+     * @param null|array $methods $methods
+     *
+     * @psalm-template RealInstanceType of object
+     * @psalm-param class-string<RealInstanceType>|string $originalClassName
+     * @psalm-return class-string<MockObject&RealInstanceType>
+     */
+    protected function getMockClass(string $originalClassName, $methods = [], array $arguments = [], string $mockClassName = '', bool $callOriginalConstructor = false, bool $callOriginalClone = true, bool $callAutoload = true, bool $cloneArguments = false): string
+    {
+        $this->recordDoubledType($originalClassName);
+
+        $mock = $this->getMockObjectGenerator()->getMock(
+            $originalClassName,
+            $methods,
+            $arguments,
+            $mockClassName,
+            $callOriginalConstructor,
+            $callOriginalClone,
+            $callAutoload,
+            $cloneArguments
+        );
+
+        return get_class($mock);
+    }
+
+    /**
+     * Returns a mock object for the specified abstract class with all abstract
+     * methods of the class mocked. Concrete methods are not mocked by default.
+     * To mock concrete methods, use the 7th parameter ($mockedMethods).
+     *
+     * @psalm-template RealInstanceType of object
+     * @psalm-param class-string<RealInstanceType> $originalClassName
+     * @psalm-return MockObject&RealInstanceType
+     */
+    protected function getMockForAbstractClass(string $originalClassName, array $arguments = [], string $mockClassName = '', bool $callOriginalConstructor = true, bool $callOriginalClone = true, bool $callAutoload = true, array $mockedMethods = [], bool $cloneArguments = false): MockObject
+    {
+        $this->recordDoubledType($originalClassName);
+
+        $mockObject = $this->getMockObjectGenerator()->getMockForAbstractClass(
+            $originalClassName,
+            $arguments,
+            $mockClassName,
+            $callOriginalConstructor,
+            $callOriginalClone,
+            $callAutoload,
+            $mockedMethods,
+            $cloneArguments
+        );
+
+        $this->registerMockObject($mockObject);
+
+        return $mockObject;
+    }
+
+    /**
+     * Returns a mock object based on the given WSDL file.
+     *
+     * @psalm-template RealInstanceType of object
+     * @psalm-param class-string<RealInstanceType>|string $originalClassName
+     * @psalm-return MockObject&RealInstanceType
+     */
+    protected function getMockFromWsdl(string $wsdlFile, string $originalClassName = '', string $mockClassName = '', array $methods = [], bool $callOriginalConstructor = true, array $options = []): MockObject
+    {
+        $this->recordDoubledType(SoapClient::class);
+
+        if ($originalClassName === '') {
+            $fileName          = pathinfo(basename(parse_url($wsdlFile, PHP_URL_PATH)), PATHINFO_FILENAME);
+            $originalClassName = preg_replace('/\W/', '', $fileName);
+        }
+
+        if (!class_exists($originalClassName)) {
+            eval(
+                $this->getMockObjectGenerator()->generateClassFromWsdl(
+                    $wsdlFile,
+                    $originalClassName,
+                    $methods,
+                    $options
+                )
+            );
+        }
+
+        $mockObject = $this->getMockObjectGenerator()->getMock(
+            $originalClassName,
+            $methods,
+            ['', $options],
+            $mockClassName,
+            $callOriginalConstructor,
+            false,
+            false
+        );
+
+        $this->registerMockObject($mockObject);
+
+        return $mockObject;
+    }
+
+    /**
+     * Returns a mock object for the specified trait with all abstract methods
+     * of the trait mocked. Concrete methods to mock can be specified with the
+     * `$mockedMethods` parameter.
+     *
+     * @psalm-param trait-string $traitName
+     */
+    protected function getMockForTrait(string $traitName, array $arguments = [], string $mockClassName = '', bool $callOriginalConstructor = true, bool $callOriginalClone = true, bool $callAutoload = true, array $mockedMethods = [], bool $cloneArguments = false): MockObject
+    {
+        $this->recordDoubledType($traitName);
+
+        $mockObject = $this->getMockObjectGenerator()->getMockForTrait(
+            $traitName,
+            $arguments,
+            $mockClassName,
+            $callOriginalConstructor,
+            $callOriginalClone,
+            $callAutoload,
+            $mockedMethods,
+            $cloneArguments
+        );
+
+        $this->registerMockObject($mockObject);
+
+        return $mockObject;
+    }
+
+    /**
+     * Returns an object for the specified trait.
+     *
+     * @psalm-param trait-string $traitName
+     */
+    protected function getObjectForTrait(string $traitName, array $arguments = [], string $traitClassName = '', bool $callOriginalConstructor = true, bool $callOriginalClone = true, bool $callAutoload = true): object
+    {
+        $this->recordDoubledType($traitName);
+
+        return $this->getMockObjectGenerator()->getObjectForTrait(
+            $traitName,
+            $traitClassName,
+            $callAutoload,
+            $callOriginalConstructor,
+            $arguments
+        );
+    }
+
+    /**
+     * @throws \Prophecy\Exception\Doubler\ClassNotFoundException
+     * @throws \Prophecy\Exception\Doubler\DoubleException
+     * @throws \Prophecy\Exception\Doubler\InterfaceNotFoundException
+     *
+     * @psalm-param class-string|null $classOrInterface
+     */
+    protected function prophesize(?string $classOrInterface = null): ObjectProphecy
+    {
+        $this->addWarning('PHPUnit\Framework\TestCase::prophesize() is deprecated and will be removed in PHPUnit 10. Please use the trait provided by phpspec/prophecy-phpunit.');
+
+        if (is_string($classOrInterface)) {
+            $this->recordDoubledType($classOrInterface);
+        }
+
+        return $this->getProphet()->prophesize($classOrInterface);
+    }
+
+    /**
+     * Creates a default TestResult object.
+     *
+     * @internal This method is not covered by the backward compatibility promise for PHPUnit
+     */
+    protected function createResult(): TestResult
+    {
+        return new TestResult;
+    }
+
+    /**
+     * Performs assertions shared by all tests of a test case.
+     *
+     * This method is called between setUp() and test.
+     */
+    protected function assertPreConditions(): void
+    {
+    }
+
+    /**
+     * Performs assertions shared by all tests of a test case.
+     *
+     * This method is called between test and tearDown().
+     */
+    protected function assertPostConditions(): void
+    {
+    }
+
+    /**
+     * This method is called when a test method did not execute successfully.
+     *
+     * @throws Throwable
+     */
+    protected function onNotSuccessfulTest(Throwable $t): void
+    {
+        throw $t;
+    }
+
+    protected function recordDoubledType(string $originalClassName): void
+    {
+        $this->doubledTypes[] = $originalClassName;
+    }
+
+    /**
+     * @throws Throwable
+     */
+    private function verifyMockObjects(): void
+    {
+        foreach ($this->mockObjects as $mockObject) {
+            if ($mockObject->__phpunit_hasMatchers()) {
+                $this->numAssertions++;
+            }
+
+            $mockObject->__phpunit_verify(
+                $this->shouldInvocationMockerBeReset($mockObject)
+            );
+        }
+
+        if ($this->prophet !== null) {
+            try {
+                $this->prophet->checkPredictions();
+            } finally {
+                foreach ($this->prophet->getProphecies() as $objectProphecy) {
+                    foreach ($objectProphecy->getMethodProphecies() as $methodProphecies) {
+                        foreach ($methodProphecies as $methodProphecy) {
+                            /* @var MethodProphecy $methodProphecy */
+                            $this->numAssertions += count($methodProphecy->getCheckedPredictions());
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     * @throws SkippedTestError
+     * @throws SyntheticSkippedError
+     * @throws Warning
+     */
+    private function checkRequirements(): void
+    {
+        if (!$this->name || !method_exists($this, $this->name)) {
+            return;
+        }
+
+        $missingRequirements = TestUtil::getMissingRequirements(
+            static::class,
+            $this->name
+        );
+
+        if (!empty($missingRequirements)) {
+            $this->markTestSkipped(implode(PHP_EOL, $missingRequirements));
+        }
+    }
+
+    private function handleDependencies(): bool
+    {
+        if ([] === $this->dependencies || $this->inIsolation) {
+            return true;
+        }
+
+        $passed     = $this->result->passed();
+        $passedKeys = array_keys($passed);
+        $numKeys    = count($passedKeys);
+
+        for ($i = 0; $i < $numKeys; $i++) {
+            $pos = strpos($passedKeys[$i], ' with data set');
+
+            if ($pos !== false) {
+                $passedKeys[$i] = substr($passedKeys[$i], 0, $pos);
+            }
+        }
+
+        $passedKeys = array_flip(array_unique($passedKeys));
+
+        foreach ($this->dependencies as $dependency) {
+            if (!$dependency->isValid()) {
+                $this->markSkippedForNotSpecifyingDependency();
+
+                return false;
+            }
+
+            if ($dependency->targetIsClass()) {
+                $dependencyClassName = $dependency->getTargetClassName();
+
+                if (array_search($dependencyClassName, $this->result->passedClasses(), true) === false) {
+                    $this->markSkippedForMissingDependency($dependency);
+
+                    return false;
+                }
+
+                continue;
+            }
+
+            $dependencyTarget = $dependency->getTarget();
+
+            if (!isset($passedKeys[$dependencyTarget])) {
+                if (!$this->isCallableTestMethod($dependencyTarget)) {
+                    $this->markWarningForUncallableDependency($dependency);
+                } else {
+                    $this->markSkippedForMissingDependency($dependency);
+                }
+
+                return false;
+            }
+
+            if (isset($passed[$dependencyTarget])) {
+                if ($passed[$dependencyTarget]['size'] != \PHPUnit\Util\Test::UNKNOWN &&
+                    $this->getSize() != \PHPUnit\Util\Test::UNKNOWN &&
+                    $passed[$dependencyTarget]['size'] > $this->getSize()) {
+                    $this->result->addError(
+                        $this,
+                        new SkippedTestError(
+                            'This test depends on a test that is larger than itself.'
+                        ),
+                        0
+                    );
+
+                    return false;
+                }
+
+                if ($dependency->useDeepClone()) {
+                    $deepCopy = new DeepCopy;
+                    $deepCopy->skipUncloneable(false);
+
+                    $this->dependencyInput[$dependencyTarget] = $deepCopy->copy($passed[$dependencyTarget]['result']);
+                } elseif ($dependency->useShallowClone()) {
+                    $this->dependencyInput[$dependencyTarget] = clone $passed[$dependencyTarget]['result'];
+                } else {
+                    $this->dependencyInput[$dependencyTarget] = $passed[$dependencyTarget]['result'];
+                }
+            } else {
+                $this->dependencyInput[$dependencyTarget] = null;
+            }
+        }
+
+        return true;
+    }
+
+    private function markSkippedForNotSpecifyingDependency(): void
+    {
+        $this->status = BaseTestRunner::STATUS_SKIPPED;
+
+        $this->result->startTest($this);
+
+        $this->result->addError(
+            $this,
+            new SkippedTestError(
+                'This method has an invalid @depends annotation.'
+            ),
+            0
+        );
+
+        $this->result->endTest($this, 0);
+    }
+
+    private function markSkippedForMissingDependency(ExecutionOrderDependency $dependency): void
+    {
+        $this->status = BaseTestRunner::STATUS_SKIPPED;
+
+        $this->result->startTest($this);
+
+        $this->result->addError(
+            $this,
+            new SkippedTestError(
+                sprintf(
+                    'This test depends on "%s" to pass.',
+                    $dependency->getTarget()
+                )
+            ),
+            0
+        );
+
+        $this->result->endTest($this, 0);
+    }
+
+    private function markWarningForUncallableDependency(ExecutionOrderDependency $dependency): void
+    {
+        $this->status = BaseTestRunner::STATUS_WARNING;
+
+        $this->result->startTest($this);
+
+        $this->result->addWarning(
+            $this,
+            new Warning(
+                sprintf(
+                    'This test depends on "%s" which does not exist.',
+                    $dependency->getTarget()
+                )
+            ),
+            0
+        );
+
+        $this->result->endTest($this, 0);
+    }
+
+    /**
+     * Get the mock object generator, creating it if it doesn't exist.
+     */
+    private function getMockObjectGenerator(): MockGenerator
+    {
+        if ($this->mockObjectGenerator === null) {
+            $this->mockObjectGenerator = new MockGenerator;
+        }
+
+        return $this->mockObjectGenerator;
+    }
+
+    private function startOutputBuffering(): void
+    {
+        ob_start();
+
+        $this->outputBufferingActive = true;
+        $this->outputBufferingLevel  = ob_get_level();
+    }
+
+    /**
+     * @throws RiskyTestError
+     */
+    private function stopOutputBuffering(): void
+    {
+        if (ob_get_level() !== $this->outputBufferingLevel) {
+            while (ob_get_level() >= $this->outputBufferingLevel) {
+                ob_end_clean();
+            }
+
+            throw new RiskyTestError(
+                'Test code or tested code did not (only) close its own output buffers'
+            );
+        }
+
+        $this->output = ob_get_contents();
+
+        if ($this->outputCallback !== false) {
+            $this->output = (string) call_user_func($this->outputCallback, $this->output);
+        }
+
+        ob_end_clean();
+
+        $this->outputBufferingActive = false;
+        $this->outputBufferingLevel  = ob_get_level();
+    }
+
+    private function snapshotGlobalState(): void
+    {
+        if ($this->runTestInSeparateProcess || $this->inIsolation ||
+            (!$this->backupGlobals && !$this->backupStaticAttributes)) {
+            return;
+        }
+
+        $this->snapshot = $this->createGlobalStateSnapshot($this->backupGlobals === true);
+    }
+
+    /**
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws RiskyTestError
+     */
+    private function restoreGlobalState(): void
+    {
+        if (!$this->snapshot instanceof Snapshot) {
+            return;
+        }
+
+        if ($this->beStrictAboutChangesToGlobalState) {
+            try {
+                $this->compareGlobalStateSnapshots(
+                    $this->snapshot,
+                    $this->createGlobalStateSnapshot($this->backupGlobals === true)
+                );
+            } catch (RiskyTestError $rte) {
+                // Intentionally left empty
+            }
+        }
+
+        $restorer = new Restorer;
+
+        if ($this->backupGlobals) {
+            $restorer->restoreGlobalVariables($this->snapshot);
+        }
+
+        if ($this->backupStaticAttributes) {
+            $restorer->restoreStaticAttributes($this->snapshot);
+        }
+
+        $this->snapshot = null;
+
+        if (isset($rte)) {
+            throw $rte;
+        }
+    }
+
+    private function createGlobalStateSnapshot(bool $backupGlobals): Snapshot
+    {
+        $excludeList = new ExcludeList;
+
+        foreach ($this->backupGlobalsExcludeList as $globalVariable) {
+            $excludeList->addGlobalVariable($globalVariable);
+        }
+
+        if (!empty($this->backupGlobalsBlacklist)) {
+            $this->addWarning('PHPUnit\Framework\TestCase::$backupGlobalsBlacklist is deprecated and will be removed in PHPUnit 10. Please use PHPUnit\Framework\TestCase::$backupGlobalsExcludeList instead.');
+
+            foreach ($this->backupGlobalsBlacklist as $globalVariable) {
+                $excludeList->addGlobalVariable($globalVariable);
+            }
+        }
+
+        if (!defined('PHPUNIT_TESTSUITE')) {
+            $excludeList->addClassNamePrefix('PHPUnit');
+            $excludeList->addClassNamePrefix('SebastianBergmann\CodeCoverage');
+            $excludeList->addClassNamePrefix('SebastianBergmann\FileIterator');
+            $excludeList->addClassNamePrefix('SebastianBergmann\Invoker');
+            $excludeList->addClassNamePrefix('SebastianBergmann\Template');
+            $excludeList->addClassNamePrefix('SebastianBergmann\Timer');
+            $excludeList->addClassNamePrefix('Symfony');
+            $excludeList->addClassNamePrefix('Doctrine\Instantiator');
+            $excludeList->addClassNamePrefix('Prophecy');
+            $excludeList->addStaticAttribute(ComparatorFactory::class, 'instance');
+
+            foreach ($this->backupStaticAttributesExcludeList as $class => $attributes) {
+                foreach ($attributes as $attribute) {
+                    $excludeList->addStaticAttribute($class, $attribute);
+                }
+            }
+
+            if (!empty($this->backupStaticAttributesBlacklist)) {
+                $this->addWarning('PHPUnit\Framework\TestCase::$backupStaticAttributesBlacklist is deprecated and will be removed in PHPUnit 10. Please use PHPUnit\Framework\TestCase::$backupStaticAttributesExcludeList instead.');
+
+                foreach ($this->backupStaticAttributesBlacklist as $class => $attributes) {
+                    foreach ($attributes as $attribute) {
+                        $excludeList->addStaticAttribute($class, $attribute);
+                    }
+                }
+            }
+        }
+
+        return new Snapshot(
+            $excludeList,
+            $backupGlobals,
+            (bool) $this->backupStaticAttributes,
+            false,
+            false,
+            false,
+            false,
+            false,
+            false,
+            false
+        );
+    }
+
+    /**
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws RiskyTestError
+     */
+    private function compareGlobalStateSnapshots(Snapshot $before, Snapshot $after): void
+    {
+        $backupGlobals = $this->backupGlobals === null || $this->backupGlobals;
+
+        if ($backupGlobals) {
+            $this->compareGlobalStateSnapshotPart(
+                $before->globalVariables(),
+                $after->globalVariables(),
+                "--- Global variables before the test\n+++ Global variables after the test\n"
+            );
+
+            $this->compareGlobalStateSnapshotPart(
+                $before->superGlobalVariables(),
+                $after->superGlobalVariables(),
+                "--- Super-global variables before the test\n+++ Super-global variables after the test\n"
+            );
+        }
+
+        if ($this->backupStaticAttributes) {
+            $this->compareGlobalStateSnapshotPart(
+                $before->staticAttributes(),
+                $after->staticAttributes(),
+                "--- Static attributes before the test\n+++ Static attributes after the test\n"
+            );
+        }
+    }
+
+    /**
+     * @throws RiskyTestError
+     */
+    private function compareGlobalStateSnapshotPart(array $before, array $after, string $header): void
+    {
+        if ($before != $after) {
+            $differ   = new Differ($header);
+            $exporter = new Exporter;
+
+            $diff = $differ->diff(
+                $exporter->export($before),
+                $exporter->export($after)
+            );
+
+            throw new RiskyTestError(
+                $diff
+            );
+        }
+    }
+
+    private function getProphet(): Prophet
+    {
+        if ($this->prophet === null) {
+            $this->prophet = new Prophet;
+        }
+
+        return $this->prophet;
+    }
+
+    /**
+     * @throws \SebastianBergmann\ObjectEnumerator\InvalidArgumentException
+     */
+    private function shouldInvocationMockerBeReset(MockObject $mock): bool
+    {
+        $enumerator = new Enumerator;
+
+        foreach ($enumerator->enumerate($this->dependencyInput) as $object) {
+            if ($mock === $object) {
+                return false;
+            }
+        }
+
+        if (!is_array($this->testResult) && !is_object($this->testResult)) {
+            return true;
+        }
+
+        return !in_array($mock, $enumerator->enumerate($this->testResult), true);
+    }
+
+    /**
+     * @throws \SebastianBergmann\ObjectEnumerator\InvalidArgumentException
+     * @throws \SebastianBergmann\ObjectReflector\InvalidArgumentException
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     */
+    private function registerMockObjectsFromTestArguments(array $testArguments, array &$visited = []): void
+    {
+        if ($this->registerMockObjectsFromTestArgumentsRecursively) {
+            foreach ((new Enumerator)->enumerate($testArguments) as $object) {
+                if ($object instanceof MockObject) {
+                    $this->registerMockObject($object);
+                }
+            }
+        } else {
+            foreach ($testArguments as $testArgument) {
+                if ($testArgument instanceof MockObject) {
+                    if (Type::isCloneable($testArgument)) {
+                        $testArgument = clone $testArgument;
+                    }
+
+                    $this->registerMockObject($testArgument);
+                } elseif (is_array($testArgument) && !in_array($testArgument, $visited, true)) {
+                    $visited[] = $testArgument;
+
+                    $this->registerMockObjectsFromTestArguments(
+                        $testArgument,
+                        $visited
+                    );
+                }
+            }
+        }
+    }
+
+    private function setDoesNotPerformAssertionsFromAnnotation(): void
+    {
+        $annotations = TestUtil::parseTestMethodAnnotations(
+            static::class,
+            $this->name
+        );
+
+        if (isset($annotations['method']['doesNotPerformAssertions'])) {
+            $this->doesNotPerformAssertions = true;
+        }
+    }
+
+    private function unregisterCustomComparators(): void
+    {
+        $factory = ComparatorFactory::getInstance();
+
+        foreach ($this->customComparators as $comparator) {
+            $factory->unregister($comparator);
+        }
+
+        $this->customComparators = [];
+    }
+
+    private function cleanupIniSettings(): void
+    {
+        foreach ($this->iniSettings as $varName => $oldValue) {
+            ini_set($varName, $oldValue);
+        }
+
+        $this->iniSettings = [];
+    }
+
+    private function cleanupLocaleSettings(): void
+    {
+        foreach ($this->locale as $category => $locale) {
+            setlocale($category, $locale);
+        }
+
+        $this->locale = [];
+    }
+
+    /**
+     * @throws Exception
+     */
+    private function checkExceptionExpectations(Throwable $throwable): bool
+    {
+        $result = false;
+
+        if ($this->expectedException !== null || $this->expectedExceptionCode !== null || $this->expectedExceptionMessage !== null || $this->expectedExceptionMessageRegExp !== null) {
+            $result = true;
+        }
+
+        if ($throwable instanceof Exception) {
+            $result = false;
+        }
+
+        if (is_string($this->expectedException)) {
+            try {
+                $reflector = new ReflectionClass($this->expectedException);
+                // @codeCoverageIgnoreStart
+            } catch (ReflectionException $e) {
+                throw new Exception(
+                    $e->getMessage(),
+                    (int) $e->getCode(),
+                    $e
+                );
+            }
+            // @codeCoverageIgnoreEnd
+
+            if ($this->expectedException === 'PHPUnit\Framework\Exception' ||
+                $this->expectedException === '\PHPUnit\Framework\Exception' ||
+                $reflector->isSubclassOf(Exception::class)) {
+                $result = true;
+            }
+        }
+
+        return $result;
+    }
+
+    private function runInSeparateProcess(): bool
+    {
+        return ($this->runTestInSeparateProcess || $this->runClassInSeparateProcess) &&
+            !$this->inIsolation && !$this instanceof PhptTestCase;
+    }
+
+    private function isCallableTestMethod(string $dependency): bool
+    {
+        [$className, $methodName] = explode('::', $dependency);
+
+        if (!class_exists($className)) {
+            return false;
+        }
+
+        try {
+            $class = new ReflectionClass($className);
+        } catch (ReflectionException $e) {
+            return false;
+        }
+
+        if (!$class->isSubclassOf(__CLASS__)) {
+            return false;
+        }
+
+        if (!$class->hasMethod($methodName)) {
+            return false;
+        }
+
+        try {
+            $method = $class->getMethod($methodName);
+        } catch (ReflectionException $e) {
+            return false;
+        }
+
+        return TestUtil::isTestMethod($method);
+    }
+
+    /**
+     * @psalm-template RealInstanceType of object
+     * @psalm-param class-string<RealInstanceType> $originalClassName
+     * @psalm-return MockObject&RealInstanceType
+     */
+    private function createMockObject(string $originalClassName): MockObject
+    {
+        return $this->getMockBuilder($originalClassName)
+                    ->disableOriginalConstructor()
+                    ->disableOriginalClone()
+                    ->disableArgumentCloning()
+                    ->disallowMockingUnknownTypes()
+                    ->getMock();
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/TestFailure.php b/vendor/phpunit/phpunit/src/Framework/TestFailure.php
new file mode 100644
index 0000000000000000000000000000000000000000..0764bc7896aebb5c5ba0ebfb044b564b77cf04ae
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/TestFailure.php
@@ -0,0 +1,155 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework;
+
+use function get_class;
+use function sprintf;
+use function trim;
+use PHPUnit\Framework\Error\Error;
+use Throwable;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class TestFailure
+{
+    /**
+     * @var null|Test
+     */
+    private $failedTest;
+
+    /**
+     * @var Throwable
+     */
+    private $thrownException;
+
+    /**
+     * @var string
+     */
+    private $testName;
+
+    /**
+     * Returns a description for an exception.
+     */
+    public static function exceptionToString(Throwable $e): string
+    {
+        if ($e instanceof SelfDescribing) {
+            $buffer = $e->toString();
+
+            if ($e instanceof ExpectationFailedException && $e->getComparisonFailure()) {
+                $buffer .= $e->getComparisonFailure()->getDiff();
+            }
+
+            if ($e instanceof PHPTAssertionFailedError) {
+                $buffer .= $e->getDiff();
+            }
+
+            if (!empty($buffer)) {
+                $buffer = trim($buffer) . "\n";
+            }
+
+            return $buffer;
+        }
+
+        if ($e instanceof Error) {
+            return $e->getMessage() . "\n";
+        }
+
+        if ($e instanceof ExceptionWrapper) {
+            return $e->getClassName() . ': ' . $e->getMessage() . "\n";
+        }
+
+        return get_class($e) . ': ' . $e->getMessage() . "\n";
+    }
+
+    /**
+     * Constructs a TestFailure with the given test and exception.
+     */
+    public function __construct(Test $failedTest, Throwable $t)
+    {
+        if ($failedTest instanceof SelfDescribing) {
+            $this->testName = $failedTest->toString();
+        } else {
+            $this->testName = get_class($failedTest);
+        }
+
+        if (!$failedTest instanceof TestCase || !$failedTest->isInIsolation()) {
+            $this->failedTest = $failedTest;
+        }
+
+        $this->thrownException = $t;
+    }
+
+    /**
+     * Returns a short description of the failure.
+     */
+    public function toString(): string
+    {
+        return sprintf(
+            '%s: %s',
+            $this->testName,
+            $this->thrownException->getMessage()
+        );
+    }
+
+    /**
+     * Returns a description for the thrown exception.
+     */
+    public function getExceptionAsString(): string
+    {
+        return self::exceptionToString($this->thrownException);
+    }
+
+    /**
+     * Returns the name of the failing test (including data set, if any).
+     */
+    public function getTestName(): string
+    {
+        return $this->testName;
+    }
+
+    /**
+     * Returns the failing test.
+     *
+     * Note: The test object is not set when the test is executed in process
+     * isolation.
+     *
+     * @see Exception
+     */
+    public function failedTest(): ?Test
+    {
+        return $this->failedTest;
+    }
+
+    /**
+     * Gets the thrown exception.
+     */
+    public function thrownException(): Throwable
+    {
+        return $this->thrownException;
+    }
+
+    /**
+     * Returns the exception's message.
+     */
+    public function exceptionMessage(): string
+    {
+        return $this->thrownException()->getMessage();
+    }
+
+    /**
+     * Returns true if the thrown exception
+     * is of type AssertionFailedError.
+     */
+    public function isFailure(): bool
+    {
+        return $this->thrownException() instanceof AssertionFailedError;
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/TestListener.php b/vendor/phpunit/phpunit/src/Framework/TestListener.php
new file mode 100644
index 0000000000000000000000000000000000000000..aaf5e7cd978534be94ebb1c58cca26c10d91bac9
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/TestListener.php
@@ -0,0 +1,85 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework;
+
+use Throwable;
+
+/**
+ * @deprecated Use the `TestHook` interfaces instead
+ * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+ */
+interface TestListener
+{
+    /**
+     * An error occurred.
+     *
+     * @deprecated Use `AfterTestErrorHook::executeAfterTestError` instead
+     */
+    public function addError(Test $test, Throwable $t, float $time): void;
+
+    /**
+     * A warning occurred.
+     *
+     * @deprecated Use `AfterTestWarningHook::executeAfterTestWarning` instead
+     */
+    public function addWarning(Test $test, Warning $e, float $time): void;
+
+    /**
+     * A failure occurred.
+     *
+     * @deprecated Use `AfterTestFailureHook::executeAfterTestFailure` instead
+     */
+    public function addFailure(Test $test, AssertionFailedError $e, float $time): void;
+
+    /**
+     * Incomplete test.
+     *
+     * @deprecated Use `AfterIncompleteTestHook::executeAfterIncompleteTest` instead
+     */
+    public function addIncompleteTest(Test $test, Throwable $t, float $time): void;
+
+    /**
+     * Risky test.
+     *
+     * @deprecated Use `AfterRiskyTestHook::executeAfterRiskyTest` instead
+     */
+    public function addRiskyTest(Test $test, Throwable $t, float $time): void;
+
+    /**
+     * Skipped test.
+     *
+     * @deprecated Use `AfterSkippedTestHook::executeAfterSkippedTest` instead
+     */
+    public function addSkippedTest(Test $test, Throwable $t, float $time): void;
+
+    /**
+     * A test suite started.
+     */
+    public function startTestSuite(TestSuite $suite): void;
+
+    /**
+     * A test suite ended.
+     */
+    public function endTestSuite(TestSuite $suite): void;
+
+    /**
+     * A test started.
+     *
+     * @deprecated Use `BeforeTestHook::executeBeforeTest` instead
+     */
+    public function startTest(Test $test): void;
+
+    /**
+     * A test ended.
+     *
+     * @deprecated Use `AfterTestHook::executeAfterTest` instead
+     */
+    public function endTest(Test $test, float $time): void;
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/TestListenerDefaultImplementation.php b/vendor/phpunit/phpunit/src/Framework/TestListenerDefaultImplementation.php
new file mode 100644
index 0000000000000000000000000000000000000000..3e56708b649027d6b5a7ac9c5b063860c2e7c0f5
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/TestListenerDefaultImplementation.php
@@ -0,0 +1,59 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework;
+
+use Throwable;
+
+/**
+ * @deprecated The `TestListener` interface is deprecated
+ * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+ */
+trait TestListenerDefaultImplementation
+{
+    public function addError(Test $test, Throwable $t, float $time): void
+    {
+    }
+
+    public function addWarning(Test $test, Warning $e, float $time): void
+    {
+    }
+
+    public function addFailure(Test $test, AssertionFailedError $e, float $time): void
+    {
+    }
+
+    public function addIncompleteTest(Test $test, Throwable $t, float $time): void
+    {
+    }
+
+    public function addRiskyTest(Test $test, Throwable $t, float $time): void
+    {
+    }
+
+    public function addSkippedTest(Test $test, Throwable $t, float $time): void
+    {
+    }
+
+    public function startTestSuite(TestSuite $suite): void
+    {
+    }
+
+    public function endTestSuite(TestSuite $suite): void
+    {
+    }
+
+    public function startTest(Test $test): void
+    {
+    }
+
+    public function endTest(Test $test, float $time): void
+    {
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/TestResult.php b/vendor/phpunit/phpunit/src/Framework/TestResult.php
new file mode 100644
index 0000000000000000000000000000000000000000..fc00628f1a05e038deb044ee38800a8db69a69a0
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/TestResult.php
@@ -0,0 +1,1289 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework;
+
+use const PHP_EOL;
+use function count;
+use function function_exists;
+use function get_class;
+use function sprintf;
+use AssertionError;
+use Countable;
+use Error;
+use PHPUnit\Util\ErrorHandler;
+use PHPUnit\Util\ExcludeList;
+use PHPUnit\Util\Printer;
+use PHPUnit\Util\Test as TestUtil;
+use ReflectionClass;
+use ReflectionException;
+use SebastianBergmann\CodeCoverage\CodeCoverage;
+use SebastianBergmann\CodeCoverage\Exception as OriginalCodeCoverageException;
+use SebastianBergmann\CodeCoverage\UnintentionallyCoveredCodeException;
+use SebastianBergmann\Invoker\Invoker;
+use SebastianBergmann\Invoker\TimeoutException;
+use SebastianBergmann\ResourceOperations\ResourceOperations;
+use SebastianBergmann\Timer\Timer;
+use Throwable;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class TestResult implements Countable
+{
+    /**
+     * @var array
+     */
+    private $passed = [];
+
+    /**
+     * @var array<string>
+     */
+    private $passedTestClasses = [];
+
+    /**
+     * @var bool
+     */
+    private $currentTestSuiteFailed = false;
+
+    /**
+     * @var TestFailure[]
+     */
+    private $errors = [];
+
+    /**
+     * @var TestFailure[]
+     */
+    private $failures = [];
+
+    /**
+     * @var TestFailure[]
+     */
+    private $warnings = [];
+
+    /**
+     * @var TestFailure[]
+     */
+    private $notImplemented = [];
+
+    /**
+     * @var TestFailure[]
+     */
+    private $risky = [];
+
+    /**
+     * @var TestFailure[]
+     */
+    private $skipped = [];
+
+    /**
+     * @deprecated Use the `TestHook` interfaces instead
+     *
+     * @var TestListener[]
+     */
+    private $listeners = [];
+
+    /**
+     * @var int
+     */
+    private $runTests = 0;
+
+    /**
+     * @var float
+     */
+    private $time = 0;
+
+    /**
+     * Code Coverage information.
+     *
+     * @var CodeCoverage
+     */
+    private $codeCoverage;
+
+    /**
+     * @var bool
+     */
+    private $convertDeprecationsToExceptions = true;
+
+    /**
+     * @var bool
+     */
+    private $convertErrorsToExceptions = true;
+
+    /**
+     * @var bool
+     */
+    private $convertNoticesToExceptions = true;
+
+    /**
+     * @var bool
+     */
+    private $convertWarningsToExceptions = true;
+
+    /**
+     * @var bool
+     */
+    private $stop = false;
+
+    /**
+     * @var bool
+     */
+    private $stopOnError = false;
+
+    /**
+     * @var bool
+     */
+    private $stopOnFailure = false;
+
+    /**
+     * @var bool
+     */
+    private $stopOnWarning = false;
+
+    /**
+     * @var bool
+     */
+    private $beStrictAboutTestsThatDoNotTestAnything = true;
+
+    /**
+     * @var bool
+     */
+    private $beStrictAboutOutputDuringTests = false;
+
+    /**
+     * @var bool
+     */
+    private $beStrictAboutTodoAnnotatedTests = false;
+
+    /**
+     * @var bool
+     */
+    private $beStrictAboutResourceUsageDuringSmallTests = false;
+
+    /**
+     * @var bool
+     */
+    private $enforceTimeLimit = false;
+
+    /**
+     * @var bool
+     */
+    private $forceCoversAnnotation = false;
+
+    /**
+     * @var int
+     */
+    private $timeoutForSmallTests = 1;
+
+    /**
+     * @var int
+     */
+    private $timeoutForMediumTests = 10;
+
+    /**
+     * @var int
+     */
+    private $timeoutForLargeTests = 60;
+
+    /**
+     * @var bool
+     */
+    private $stopOnRisky = false;
+
+    /**
+     * @var bool
+     */
+    private $stopOnIncomplete = false;
+
+    /**
+     * @var bool
+     */
+    private $stopOnSkipped = false;
+
+    /**
+     * @var bool
+     */
+    private $lastTestFailed = false;
+
+    /**
+     * @var int
+     */
+    private $defaultTimeLimit = 0;
+
+    /**
+     * @var bool
+     */
+    private $stopOnDefect = false;
+
+    /**
+     * @var bool
+     */
+    private $registerMockObjectsFromTestArgumentsRecursively = false;
+
+    /**
+     * @deprecated Use the `TestHook` interfaces instead
+     *
+     * @codeCoverageIgnore
+     *
+     * Registers a TestListener.
+     */
+    public function addListener(TestListener $listener): void
+    {
+        $this->listeners[] = $listener;
+    }
+
+    /**
+     * @deprecated Use the `TestHook` interfaces instead
+     *
+     * @codeCoverageIgnore
+     *
+     * Unregisters a TestListener.
+     */
+    public function removeListener(TestListener $listener): void
+    {
+        foreach ($this->listeners as $key => $_listener) {
+            if ($listener === $_listener) {
+                unset($this->listeners[$key]);
+            }
+        }
+    }
+
+    /**
+     * @deprecated Use the `TestHook` interfaces instead
+     *
+     * @codeCoverageIgnore
+     *
+     * Flushes all flushable TestListeners.
+     */
+    public function flushListeners(): void
+    {
+        foreach ($this->listeners as $listener) {
+            if ($listener instanceof Printer) {
+                $listener->flush();
+            }
+        }
+    }
+
+    /**
+     * Adds an error to the list of errors.
+     */
+    public function addError(Test $test, Throwable $t, float $time): void
+    {
+        if ($t instanceof RiskyTestError) {
+            $this->recordRisky($test, $t);
+
+            $notifyMethod = 'addRiskyTest';
+
+            if ($test instanceof TestCase) {
+                $test->markAsRisky();
+            }
+
+            if ($this->stopOnRisky || $this->stopOnDefect) {
+                $this->stop();
+            }
+        } elseif ($t instanceof IncompleteTest) {
+            $this->recordNotImplemented($test, $t);
+
+            $notifyMethod = 'addIncompleteTest';
+
+            if ($this->stopOnIncomplete) {
+                $this->stop();
+            }
+        } elseif ($t instanceof SkippedTest) {
+            $this->recordSkipped($test, $t);
+
+            $notifyMethod = 'addSkippedTest';
+
+            if ($this->stopOnSkipped) {
+                $this->stop();
+            }
+        } else {
+            $this->recordError($test, $t);
+
+            $notifyMethod = 'addError';
+
+            if ($this->stopOnError || $this->stopOnFailure) {
+                $this->stop();
+            }
+        }
+
+        // @see https://github.com/sebastianbergmann/phpunit/issues/1953
+        if ($t instanceof Error) {
+            $t = new ExceptionWrapper($t);
+        }
+
+        foreach ($this->listeners as $listener) {
+            $listener->{$notifyMethod}($test, $t, $time);
+        }
+
+        $this->lastTestFailed = true;
+        $this->time += $time;
+    }
+
+    /**
+     * Adds a warning to the list of warnings.
+     * The passed in exception caused the warning.
+     */
+    public function addWarning(Test $test, Warning $e, float $time): void
+    {
+        if ($this->stopOnWarning || $this->stopOnDefect) {
+            $this->stop();
+        }
+
+        $this->recordWarning($test, $e);
+
+        foreach ($this->listeners as $listener) {
+            $listener->addWarning($test, $e, $time);
+        }
+
+        $this->time += $time;
+    }
+
+    /**
+     * Adds a failure to the list of failures.
+     * The passed in exception caused the failure.
+     */
+    public function addFailure(Test $test, AssertionFailedError $e, float $time): void
+    {
+        if ($e instanceof RiskyTestError || $e instanceof OutputError) {
+            $this->recordRisky($test, $e);
+
+            $notifyMethod = 'addRiskyTest';
+
+            if ($test instanceof TestCase) {
+                $test->markAsRisky();
+            }
+
+            if ($this->stopOnRisky || $this->stopOnDefect) {
+                $this->stop();
+            }
+        } elseif ($e instanceof IncompleteTest) {
+            $this->recordNotImplemented($test, $e);
+
+            $notifyMethod = 'addIncompleteTest';
+
+            if ($this->stopOnIncomplete) {
+                $this->stop();
+            }
+        } elseif ($e instanceof SkippedTest) {
+            $this->recordSkipped($test, $e);
+
+            $notifyMethod = 'addSkippedTest';
+
+            if ($this->stopOnSkipped) {
+                $this->stop();
+            }
+        } else {
+            $this->failures[] = new TestFailure($test, $e);
+            $notifyMethod     = 'addFailure';
+
+            if ($this->stopOnFailure || $this->stopOnDefect) {
+                $this->stop();
+            }
+        }
+
+        foreach ($this->listeners as $listener) {
+            $listener->{$notifyMethod}($test, $e, $time);
+        }
+
+        $this->lastTestFailed = true;
+        $this->time += $time;
+    }
+
+    /**
+     * Informs the result that a test suite will be started.
+     */
+    public function startTestSuite(TestSuite $suite): void
+    {
+        $this->currentTestSuiteFailed = false;
+
+        foreach ($this->listeners as $listener) {
+            $listener->startTestSuite($suite);
+        }
+    }
+
+    /**
+     * Informs the result that a test suite was completed.
+     */
+    public function endTestSuite(TestSuite $suite): void
+    {
+        if (!$this->currentTestSuiteFailed) {
+            $this->passedTestClasses[] = $suite->getName();
+        }
+
+        foreach ($this->listeners as $listener) {
+            $listener->endTestSuite($suite);
+        }
+    }
+
+    /**
+     * Informs the result that a test will be started.
+     */
+    public function startTest(Test $test): void
+    {
+        $this->lastTestFailed = false;
+        $this->runTests += count($test);
+
+        foreach ($this->listeners as $listener) {
+            $listener->startTest($test);
+        }
+    }
+
+    /**
+     * Informs the result that a test was completed.
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     */
+    public function endTest(Test $test, float $time): void
+    {
+        foreach ($this->listeners as $listener) {
+            $listener->endTest($test, $time);
+        }
+
+        if (!$this->lastTestFailed && $test instanceof TestCase) {
+            $class = get_class($test);
+            $key   = $class . '::' . $test->getName();
+
+            $this->passed[$key] = [
+                'result' => $test->getResult(),
+                'size'   => \PHPUnit\Util\Test::getSize(
+                    $class,
+                    $test->getName(false)
+                ),
+            ];
+
+            $this->time += $time;
+        }
+
+        if ($this->lastTestFailed && $test instanceof TestCase) {
+            $this->currentTestSuiteFailed = true;
+        }
+    }
+
+    /**
+     * Returns true if no risky test occurred.
+     */
+    public function allHarmless(): bool
+    {
+        return $this->riskyCount() === 0;
+    }
+
+    /**
+     * Gets the number of risky tests.
+     */
+    public function riskyCount(): int
+    {
+        return count($this->risky);
+    }
+
+    /**
+     * Returns true if no incomplete test occurred.
+     */
+    public function allCompletelyImplemented(): bool
+    {
+        return $this->notImplementedCount() === 0;
+    }
+
+    /**
+     * Gets the number of incomplete tests.
+     */
+    public function notImplementedCount(): int
+    {
+        return count($this->notImplemented);
+    }
+
+    /**
+     * Returns an array of TestFailure objects for the risky tests.
+     *
+     * @return TestFailure[]
+     */
+    public function risky(): array
+    {
+        return $this->risky;
+    }
+
+    /**
+     * Returns an array of TestFailure objects for the incomplete tests.
+     *
+     * @return TestFailure[]
+     */
+    public function notImplemented(): array
+    {
+        return $this->notImplemented;
+    }
+
+    /**
+     * Returns true if no test has been skipped.
+     */
+    public function noneSkipped(): bool
+    {
+        return $this->skippedCount() === 0;
+    }
+
+    /**
+     * Gets the number of skipped tests.
+     */
+    public function skippedCount(): int
+    {
+        return count($this->skipped);
+    }
+
+    /**
+     * Returns an array of TestFailure objects for the skipped tests.
+     *
+     * @return TestFailure[]
+     */
+    public function skipped(): array
+    {
+        return $this->skipped;
+    }
+
+    /**
+     * Gets the number of detected errors.
+     */
+    public function errorCount(): int
+    {
+        return count($this->errors);
+    }
+
+    /**
+     * Returns an array of TestFailure objects for the errors.
+     *
+     * @return TestFailure[]
+     */
+    public function errors(): array
+    {
+        return $this->errors;
+    }
+
+    /**
+     * Gets the number of detected failures.
+     */
+    public function failureCount(): int
+    {
+        return count($this->failures);
+    }
+
+    /**
+     * Returns an array of TestFailure objects for the failures.
+     *
+     * @return TestFailure[]
+     */
+    public function failures(): array
+    {
+        return $this->failures;
+    }
+
+    /**
+     * Gets the number of detected warnings.
+     */
+    public function warningCount(): int
+    {
+        return count($this->warnings);
+    }
+
+    /**
+     * Returns an array of TestFailure objects for the warnings.
+     *
+     * @return TestFailure[]
+     */
+    public function warnings(): array
+    {
+        return $this->warnings;
+    }
+
+    /**
+     * Returns the names of the tests that have passed.
+     */
+    public function passed(): array
+    {
+        return $this->passed;
+    }
+
+    /**
+     * Returns the names of the TestSuites that have passed.
+     *
+     * This enables @depends-annotations for TestClassName::class
+     */
+    public function passedClasses(): array
+    {
+        return $this->passedTestClasses;
+    }
+
+    /**
+     * Returns whether code coverage information should be collected.
+     */
+    public function getCollectCodeCoverageInformation(): bool
+    {
+        return $this->codeCoverage !== null;
+    }
+
+    /**
+     * Runs a TestCase.
+     *
+     * @throws \SebastianBergmann\CodeCoverage\InvalidArgumentException
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws CodeCoverageException
+     * @throws UnintentionallyCoveredCodeException
+     */
+    public function run(Test $test): void
+    {
+        Assert::resetCount();
+
+        if ($test instanceof TestCase) {
+            $test->setRegisterMockObjectsFromTestArgumentsRecursively(
+                $this->registerMockObjectsFromTestArgumentsRecursively
+            );
+
+            $isAnyCoverageRequired = TestUtil::requiresCodeCoverageDataCollection($test);
+        }
+
+        $error      = false;
+        $failure    = false;
+        $warning    = false;
+        $incomplete = false;
+        $risky      = false;
+        $skipped    = false;
+
+        $this->startTest($test);
+
+        if ($this->convertDeprecationsToExceptions || $this->convertErrorsToExceptions || $this->convertNoticesToExceptions || $this->convertWarningsToExceptions) {
+            $errorHandler = new ErrorHandler(
+                $this->convertDeprecationsToExceptions,
+                $this->convertErrorsToExceptions,
+                $this->convertNoticesToExceptions,
+                $this->convertWarningsToExceptions
+            );
+
+            $errorHandler->register();
+        }
+
+        $collectCodeCoverage = $this->codeCoverage !== null &&
+                               !$test instanceof ErrorTestCase &&
+                               !$test instanceof WarningTestCase &&
+                               $isAnyCoverageRequired;
+
+        if ($collectCodeCoverage) {
+            $this->codeCoverage->start($test);
+        }
+
+        $monitorFunctions = $this->beStrictAboutResourceUsageDuringSmallTests &&
+                            !$test instanceof ErrorTestCase &&
+                            !$test instanceof WarningTestCase &&
+                            $test->getSize() === \PHPUnit\Util\Test::SMALL &&
+                            function_exists('xdebug_start_function_monitor');
+
+        if ($monitorFunctions) {
+            /* @noinspection ForgottenDebugOutputInspection */
+            xdebug_start_function_monitor(ResourceOperations::getFunctions());
+        }
+
+        $timer = new Timer;
+        $timer->start();
+
+        try {
+            $invoker = new Invoker;
+
+            if (!$test instanceof ErrorTestCase &&
+                !$test instanceof WarningTestCase &&
+                $this->enforceTimeLimit &&
+                ($this->defaultTimeLimit || $test->getSize() != \PHPUnit\Util\Test::UNKNOWN) &&
+                $invoker->canInvokeWithTimeout()) {
+                switch ($test->getSize()) {
+                    case \PHPUnit\Util\Test::SMALL:
+                        $_timeout = $this->timeoutForSmallTests;
+
+                        break;
+
+                    case \PHPUnit\Util\Test::MEDIUM:
+                        $_timeout = $this->timeoutForMediumTests;
+
+                        break;
+
+                    case \PHPUnit\Util\Test::LARGE:
+                        $_timeout = $this->timeoutForLargeTests;
+
+                        break;
+
+                    case \PHPUnit\Util\Test::UNKNOWN:
+                        $_timeout = $this->defaultTimeLimit;
+
+                        break;
+                }
+
+                $invoker->invoke([$test, 'runBare'], [], $_timeout);
+            } else {
+                $test->runBare();
+            }
+        } catch (TimeoutException $e) {
+            $this->addFailure(
+                $test,
+                new RiskyTestError(
+                    $e->getMessage()
+                ),
+                $_timeout
+            );
+
+            $risky = true;
+        } catch (AssertionFailedError $e) {
+            $failure = true;
+
+            if ($e instanceof RiskyTestError) {
+                $risky = true;
+            } elseif ($e instanceof IncompleteTestError) {
+                $incomplete = true;
+            } elseif ($e instanceof SkippedTestError) {
+                $skipped = true;
+            }
+        } catch (AssertionError $e) {
+            $test->addToAssertionCount(1);
+
+            $failure = true;
+            $frame   = $e->getTrace()[0];
+
+            $e = new AssertionFailedError(
+                sprintf(
+                    '%s in %s:%s',
+                    $e->getMessage(),
+                    $frame['file'],
+                    $frame['line']
+                )
+            );
+        } catch (Warning $e) {
+            $warning = true;
+        } catch (Exception $e) {
+            $error = true;
+        } catch (Throwable $e) {
+            $e     = new ExceptionWrapper($e);
+            $error = true;
+        }
+
+        $time = $timer->stop()->asSeconds();
+
+        $test->addToAssertionCount(Assert::getCount());
+
+        if ($monitorFunctions) {
+            $excludeList = new ExcludeList;
+
+            /** @noinspection ForgottenDebugOutputInspection */
+            $functions = xdebug_get_monitored_functions();
+
+            /* @noinspection ForgottenDebugOutputInspection */
+            xdebug_stop_function_monitor();
+
+            foreach ($functions as $function) {
+                if (!$excludeList->isExcluded($function['filename'])) {
+                    $this->addFailure(
+                        $test,
+                        new RiskyTestError(
+                            sprintf(
+                                '%s() used in %s:%s',
+                                $function['function'],
+                                $function['filename'],
+                                $function['lineno']
+                            )
+                        ),
+                        $time
+                    );
+                }
+            }
+        }
+
+        if ($this->beStrictAboutTestsThatDoNotTestAnything &&
+            $test->getNumAssertions() === 0) {
+            $risky = true;
+        }
+
+        if ($this->forceCoversAnnotation && !$error && !$failure && !$warning && !$incomplete && !$skipped && !$risky) {
+            $annotations = TestUtil::parseTestMethodAnnotations(
+                get_class($test),
+                $test->getName(false)
+            );
+
+            if (!isset($annotations['class']['covers']) &&
+                !isset($annotations['method']['covers']) &&
+                !isset($annotations['class']['coversNothing']) &&
+                !isset($annotations['method']['coversNothing'])) {
+                $this->addFailure(
+                    $test,
+                    new MissingCoversAnnotationException(
+                        'This test does not have a @covers annotation but is expected to have one'
+                    ),
+                    $time
+                );
+
+                $risky = true;
+            }
+        }
+
+        if ($collectCodeCoverage) {
+            $append           = !$risky && !$incomplete && !$skipped;
+            $linesToBeCovered = [];
+            $linesToBeUsed    = [];
+
+            if ($append && $test instanceof TestCase) {
+                try {
+                    $linesToBeCovered = \PHPUnit\Util\Test::getLinesToBeCovered(
+                        get_class($test),
+                        $test->getName(false)
+                    );
+
+                    $linesToBeUsed = \PHPUnit\Util\Test::getLinesToBeUsed(
+                        get_class($test),
+                        $test->getName(false)
+                    );
+                } catch (InvalidCoversTargetException $cce) {
+                    $this->addWarning(
+                        $test,
+                        new Warning(
+                            $cce->getMessage()
+                        ),
+                        $time
+                    );
+                }
+            }
+
+            try {
+                $this->codeCoverage->stop(
+                    $append,
+                    $linesToBeCovered,
+                    $linesToBeUsed
+                );
+            } catch (UnintentionallyCoveredCodeException $cce) {
+                $unintentionallyCoveredCodeError = new UnintentionallyCoveredCodeError(
+                    'This test executed code that is not listed as code to be covered or used:' .
+                    PHP_EOL . $cce->getMessage()
+                );
+            } catch (OriginalCodeCoverageException $cce) {
+                $error = true;
+
+                $e = $e ?? $cce;
+            }
+        }
+
+        if (isset($errorHandler)) {
+            $errorHandler->unregister();
+
+            unset($errorHandler);
+        }
+
+        if ($error) {
+            $this->addError($test, $e, $time);
+        } elseif ($failure) {
+            $this->addFailure($test, $e, $time);
+        } elseif ($warning) {
+            $this->addWarning($test, $e, $time);
+        } elseif (isset($unintentionallyCoveredCodeError)) {
+            $this->addFailure(
+                $test,
+                $unintentionallyCoveredCodeError,
+                $time
+            );
+        } elseif ($this->beStrictAboutTestsThatDoNotTestAnything &&
+            !$test->doesNotPerformAssertions() &&
+            $test->getNumAssertions() === 0) {
+            try {
+                $reflected = new ReflectionClass($test);
+                // @codeCoverageIgnoreStart
+            } catch (ReflectionException $e) {
+                throw new Exception(
+                    $e->getMessage(),
+                    (int) $e->getCode(),
+                    $e
+                );
+            }
+            // @codeCoverageIgnoreEnd
+
+            $name = $test->getName(false);
+
+            if ($name && $reflected->hasMethod($name)) {
+                try {
+                    $reflected = $reflected->getMethod($name);
+                    // @codeCoverageIgnoreStart
+                } catch (ReflectionException $e) {
+                    throw new Exception(
+                        $e->getMessage(),
+                        (int) $e->getCode(),
+                        $e
+                    );
+                }
+                // @codeCoverageIgnoreEnd
+            }
+
+            $this->addFailure(
+                $test,
+                new RiskyTestError(
+                    sprintf(
+                        "This test did not perform any assertions\n\n%s:%d",
+                        $reflected->getFileName(),
+                        $reflected->getStartLine()
+                    )
+                ),
+                $time
+            );
+        } elseif ($this->beStrictAboutTestsThatDoNotTestAnything &&
+            $test->doesNotPerformAssertions() &&
+            $test->getNumAssertions() > 0) {
+            $this->addFailure(
+                $test,
+                new RiskyTestError(
+                    sprintf(
+                        'This test is annotated with "@doesNotPerformAssertions" but performed %d assertions',
+                        $test->getNumAssertions()
+                    )
+                ),
+                $time
+            );
+        } elseif ($this->beStrictAboutOutputDuringTests && $test->hasOutput()) {
+            $this->addFailure(
+                $test,
+                new OutputError(
+                    sprintf(
+                        'This test printed output: %s',
+                        $test->getActualOutput()
+                    )
+                ),
+                $time
+            );
+        } elseif ($this->beStrictAboutTodoAnnotatedTests && $test instanceof TestCase) {
+            $annotations = TestUtil::parseTestMethodAnnotations(
+                get_class($test),
+                $test->getName(false)
+            );
+
+            if (isset($annotations['method']['todo'])) {
+                $this->addFailure(
+                    $test,
+                    new RiskyTestError(
+                        'Test method is annotated with @todo'
+                    ),
+                    $time
+                );
+            }
+        }
+
+        $this->endTest($test, $time);
+    }
+
+    /**
+     * Gets the number of run tests.
+     */
+    public function count(): int
+    {
+        return $this->runTests;
+    }
+
+    /**
+     * Checks whether the test run should stop.
+     */
+    public function shouldStop(): bool
+    {
+        return $this->stop;
+    }
+
+    /**
+     * Marks that the test run should stop.
+     */
+    public function stop(): void
+    {
+        $this->stop = true;
+    }
+
+    /**
+     * Returns the code coverage object.
+     */
+    public function getCodeCoverage(): ?CodeCoverage
+    {
+        return $this->codeCoverage;
+    }
+
+    /**
+     * Sets the code coverage object.
+     */
+    public function setCodeCoverage(CodeCoverage $codeCoverage): void
+    {
+        $this->codeCoverage = $codeCoverage;
+    }
+
+    /**
+     * Enables or disables the deprecation-to-exception conversion.
+     */
+    public function convertDeprecationsToExceptions(bool $flag): void
+    {
+        $this->convertDeprecationsToExceptions = $flag;
+    }
+
+    /**
+     * Returns the deprecation-to-exception conversion setting.
+     */
+    public function getConvertDeprecationsToExceptions(): bool
+    {
+        return $this->convertDeprecationsToExceptions;
+    }
+
+    /**
+     * Enables or disables the error-to-exception conversion.
+     */
+    public function convertErrorsToExceptions(bool $flag): void
+    {
+        $this->convertErrorsToExceptions = $flag;
+    }
+
+    /**
+     * Returns the error-to-exception conversion setting.
+     */
+    public function getConvertErrorsToExceptions(): bool
+    {
+        return $this->convertErrorsToExceptions;
+    }
+
+    /**
+     * Enables or disables the notice-to-exception conversion.
+     */
+    public function convertNoticesToExceptions(bool $flag): void
+    {
+        $this->convertNoticesToExceptions = $flag;
+    }
+
+    /**
+     * Returns the notice-to-exception conversion setting.
+     */
+    public function getConvertNoticesToExceptions(): bool
+    {
+        return $this->convertNoticesToExceptions;
+    }
+
+    /**
+     * Enables or disables the warning-to-exception conversion.
+     */
+    public function convertWarningsToExceptions(bool $flag): void
+    {
+        $this->convertWarningsToExceptions = $flag;
+    }
+
+    /**
+     * Returns the warning-to-exception conversion setting.
+     */
+    public function getConvertWarningsToExceptions(): bool
+    {
+        return $this->convertWarningsToExceptions;
+    }
+
+    /**
+     * Enables or disables the stopping when an error occurs.
+     */
+    public function stopOnError(bool $flag): void
+    {
+        $this->stopOnError = $flag;
+    }
+
+    /**
+     * Enables or disables the stopping when a failure occurs.
+     */
+    public function stopOnFailure(bool $flag): void
+    {
+        $this->stopOnFailure = $flag;
+    }
+
+    /**
+     * Enables or disables the stopping when a warning occurs.
+     */
+    public function stopOnWarning(bool $flag): void
+    {
+        $this->stopOnWarning = $flag;
+    }
+
+    public function beStrictAboutTestsThatDoNotTestAnything(bool $flag): void
+    {
+        $this->beStrictAboutTestsThatDoNotTestAnything = $flag;
+    }
+
+    public function isStrictAboutTestsThatDoNotTestAnything(): bool
+    {
+        return $this->beStrictAboutTestsThatDoNotTestAnything;
+    }
+
+    public function beStrictAboutOutputDuringTests(bool $flag): void
+    {
+        $this->beStrictAboutOutputDuringTests = $flag;
+    }
+
+    public function isStrictAboutOutputDuringTests(): bool
+    {
+        return $this->beStrictAboutOutputDuringTests;
+    }
+
+    public function beStrictAboutResourceUsageDuringSmallTests(bool $flag): void
+    {
+        $this->beStrictAboutResourceUsageDuringSmallTests = $flag;
+    }
+
+    public function isStrictAboutResourceUsageDuringSmallTests(): bool
+    {
+        return $this->beStrictAboutResourceUsageDuringSmallTests;
+    }
+
+    public function enforceTimeLimit(bool $flag): void
+    {
+        $this->enforceTimeLimit = $flag;
+    }
+
+    public function enforcesTimeLimit(): bool
+    {
+        return $this->enforceTimeLimit;
+    }
+
+    public function beStrictAboutTodoAnnotatedTests(bool $flag): void
+    {
+        $this->beStrictAboutTodoAnnotatedTests = $flag;
+    }
+
+    public function isStrictAboutTodoAnnotatedTests(): bool
+    {
+        return $this->beStrictAboutTodoAnnotatedTests;
+    }
+
+    public function forceCoversAnnotation(): void
+    {
+        $this->forceCoversAnnotation = true;
+    }
+
+    public function forcesCoversAnnotation(): bool
+    {
+        return $this->forceCoversAnnotation;
+    }
+
+    /**
+     * Enables or disables the stopping for risky tests.
+     */
+    public function stopOnRisky(bool $flag): void
+    {
+        $this->stopOnRisky = $flag;
+    }
+
+    /**
+     * Enables or disables the stopping for incomplete tests.
+     */
+    public function stopOnIncomplete(bool $flag): void
+    {
+        $this->stopOnIncomplete = $flag;
+    }
+
+    /**
+     * Enables or disables the stopping for skipped tests.
+     */
+    public function stopOnSkipped(bool $flag): void
+    {
+        $this->stopOnSkipped = $flag;
+    }
+
+    /**
+     * Enables or disables the stopping for defects: error, failure, warning.
+     */
+    public function stopOnDefect(bool $flag): void
+    {
+        $this->stopOnDefect = $flag;
+    }
+
+    /**
+     * Returns the time spent running the tests.
+     */
+    public function time(): float
+    {
+        return $this->time;
+    }
+
+    /**
+     * Returns whether the entire test was successful or not.
+     */
+    public function wasSuccessful(): bool
+    {
+        return $this->wasSuccessfulIgnoringWarnings() && empty($this->warnings);
+    }
+
+    public function wasSuccessfulIgnoringWarnings(): bool
+    {
+        return empty($this->errors) && empty($this->failures);
+    }
+
+    public function wasSuccessfulAndNoTestIsRiskyOrSkippedOrIncomplete(): bool
+    {
+        return $this->wasSuccessful() && $this->allHarmless() && $this->allCompletelyImplemented() && $this->noneSkipped();
+    }
+
+    /**
+     * Sets the default timeout for tests.
+     */
+    public function setDefaultTimeLimit(int $timeout): void
+    {
+        $this->defaultTimeLimit = $timeout;
+    }
+
+    /**
+     * Sets the timeout for small tests.
+     */
+    public function setTimeoutForSmallTests(int $timeout): void
+    {
+        $this->timeoutForSmallTests = $timeout;
+    }
+
+    /**
+     * Sets the timeout for medium tests.
+     */
+    public function setTimeoutForMediumTests(int $timeout): void
+    {
+        $this->timeoutForMediumTests = $timeout;
+    }
+
+    /**
+     * Sets the timeout for large tests.
+     */
+    public function setTimeoutForLargeTests(int $timeout): void
+    {
+        $this->timeoutForLargeTests = $timeout;
+    }
+
+    /**
+     * Returns the set timeout for large tests.
+     */
+    public function getTimeoutForLargeTests(): int
+    {
+        return $this->timeoutForLargeTests;
+    }
+
+    public function setRegisterMockObjectsFromTestArgumentsRecursively(bool $flag): void
+    {
+        $this->registerMockObjectsFromTestArgumentsRecursively = $flag;
+    }
+
+    private function recordError(Test $test, Throwable $t): void
+    {
+        $this->errors[] = new TestFailure($test, $t);
+    }
+
+    private function recordNotImplemented(Test $test, Throwable $t): void
+    {
+        $this->notImplemented[] = new TestFailure($test, $t);
+    }
+
+    private function recordRisky(Test $test, Throwable $t): void
+    {
+        $this->risky[] = new TestFailure($test, $t);
+    }
+
+    private function recordSkipped(Test $test, Throwable $t): void
+    {
+        $this->skipped[] = new TestFailure($test, $t);
+    }
+
+    private function recordWarning(Test $test, Throwable $t): void
+    {
+        $this->warnings[] = new TestFailure($test, $t);
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/TestSuite.php b/vendor/phpunit/phpunit/src/Framework/TestSuite.php
new file mode 100644
index 0000000000000000000000000000000000000000..16422562c6a5d870df95ef7556644252135b3608
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/TestSuite.php
@@ -0,0 +1,914 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework;
+
+use const PHP_EOL;
+use function array_diff;
+use function array_keys;
+use function array_map;
+use function array_merge;
+use function array_unique;
+use function basename;
+use function call_user_func;
+use function class_exists;
+use function count;
+use function dirname;
+use function get_declared_classes;
+use function implode;
+use function is_bool;
+use function is_callable;
+use function is_file;
+use function is_object;
+use function is_string;
+use function method_exists;
+use function preg_match;
+use function preg_quote;
+use function sprintf;
+use function strpos;
+use function substr;
+use Iterator;
+use IteratorAggregate;
+use PHPUnit\Runner\BaseTestRunner;
+use PHPUnit\Runner\Filter\Factory;
+use PHPUnit\Runner\PhptTestCase;
+use PHPUnit\Util\FileLoader;
+use PHPUnit\Util\Test as TestUtil;
+use ReflectionClass;
+use ReflectionException;
+use ReflectionMethod;
+use Throwable;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+class TestSuite implements IteratorAggregate, Reorderable, SelfDescribing, Test
+{
+    /**
+     * Enable or disable the backup and restoration of the $GLOBALS array.
+     *
+     * @var bool
+     */
+    protected $backupGlobals;
+
+    /**
+     * Enable or disable the backup and restoration of static attributes.
+     *
+     * @var bool
+     */
+    protected $backupStaticAttributes;
+
+    /**
+     * @var bool
+     */
+    protected $runTestInSeparateProcess = false;
+
+    /**
+     * The name of the test suite.
+     *
+     * @var string
+     */
+    protected $name = '';
+
+    /**
+     * The test groups of the test suite.
+     *
+     * @psalm-var array<string,list<Test>>
+     */
+    protected $groups = [];
+
+    /**
+     * The tests in the test suite.
+     *
+     * @var Test[]
+     */
+    protected $tests = [];
+
+    /**
+     * The number of tests in the test suite.
+     *
+     * @var int
+     */
+    protected $numTests = -1;
+
+    /**
+     * @var bool
+     */
+    protected $testCase = false;
+
+    /**
+     * @var string[]
+     */
+    protected $foundClasses = [];
+
+    /**
+     * @var null|list<ExecutionOrderDependency>
+     */
+    protected $providedTests;
+
+    /**
+     * @var null|list<ExecutionOrderDependency>
+     */
+    protected $requiredTests;
+
+    /**
+     * @var bool
+     */
+    private $beStrictAboutChangesToGlobalState;
+
+    /**
+     * @var Factory
+     */
+    private $iteratorFilter;
+
+    /**
+     * @var string[]
+     */
+    private $declaredClasses;
+
+    /**
+     * @psalm-var array<int,string>
+     */
+    private $warnings = [];
+
+    /**
+     * Constructs a new TestSuite.
+     *
+     *   - PHPUnit\Framework\TestSuite() constructs an empty TestSuite.
+     *
+     *   - PHPUnit\Framework\TestSuite(ReflectionClass) constructs a
+     *     TestSuite from the given class.
+     *
+     *   - PHPUnit\Framework\TestSuite(ReflectionClass, String)
+     *     constructs a TestSuite from the given class with the given
+     *     name.
+     *
+     *   - PHPUnit\Framework\TestSuite(String) either constructs a
+     *     TestSuite from the given class (if the passed string is the
+     *     name of an existing class) or constructs an empty TestSuite
+     *     with the given name.
+     *
+     * @param ReflectionClass|string $theClass
+     *
+     * @throws Exception
+     */
+    public function __construct($theClass = '', string $name = '')
+    {
+        if (!is_string($theClass) && !$theClass instanceof ReflectionClass) {
+            throw InvalidArgumentException::create(
+                1,
+                'ReflectionClass object or string'
+            );
+        }
+
+        $this->declaredClasses = get_declared_classes();
+
+        if (!$theClass instanceof ReflectionClass) {
+            if (class_exists($theClass, true)) {
+                if ($name === '') {
+                    $name = $theClass;
+                }
+
+                try {
+                    $theClass = new ReflectionClass($theClass);
+                } catch (ReflectionException $e) {
+                    throw new Exception(
+                        $e->getMessage(),
+                        (int) $e->getCode(),
+                        $e
+                    );
+                }
+                // @codeCoverageIgnoreEnd
+            } else {
+                $this->setName($theClass);
+
+                return;
+            }
+        }
+
+        if (!$theClass->isSubclassOf(TestCase::class)) {
+            $this->setName((string) $theClass);
+
+            return;
+        }
+
+        if ($name !== '') {
+            $this->setName($name);
+        } else {
+            $this->setName($theClass->getName());
+        }
+
+        $constructor = $theClass->getConstructor();
+
+        if ($constructor !== null &&
+            !$constructor->isPublic()) {
+            $this->addTest(
+                new WarningTestCase(
+                    sprintf(
+                        'Class "%s" has no public constructor.',
+                        $theClass->getName()
+                    )
+                )
+            );
+
+            return;
+        }
+
+        foreach ($theClass->getMethods() as $method) {
+            if ($method->getDeclaringClass()->getName() === Assert::class) {
+                continue;
+            }
+
+            if ($method->getDeclaringClass()->getName() === TestCase::class) {
+                continue;
+            }
+
+            if (!TestUtil::isTestMethod($method)) {
+                continue;
+            }
+
+            $this->addTestMethod($theClass, $method);
+        }
+
+        if (empty($this->tests)) {
+            $this->addTest(
+                new WarningTestCase(
+                    sprintf(
+                        'No tests found in class "%s".',
+                        $theClass->getName()
+                    )
+                )
+            );
+        }
+
+        $this->testCase = true;
+    }
+
+    /**
+     * Returns a string representation of the test suite.
+     */
+    public function toString(): string
+    {
+        return $this->getName();
+    }
+
+    /**
+     * Adds a test to the suite.
+     *
+     * @param array $groups
+     */
+    public function addTest(Test $test, $groups = []): void
+    {
+        try {
+            $class = new ReflectionClass($test);
+            // @codeCoverageIgnoreStart
+        } catch (ReflectionException $e) {
+            throw new Exception(
+                $e->getMessage(),
+                (int) $e->getCode(),
+                $e
+            );
+        }
+        // @codeCoverageIgnoreEnd
+
+        if (!$class->isAbstract()) {
+            $this->tests[] = $test;
+            $this->clearCaches();
+
+            if ($test instanceof self && empty($groups)) {
+                $groups = $test->getGroups();
+            }
+
+            if ($this->containsOnlyVirtualGroups($groups)) {
+                $groups[] = 'default';
+            }
+
+            foreach ($groups as $group) {
+                if (!isset($this->groups[$group])) {
+                    $this->groups[$group] = [$test];
+                } else {
+                    $this->groups[$group][] = $test;
+                }
+            }
+
+            if ($test instanceof TestCase) {
+                $test->setGroups($groups);
+            }
+        }
+    }
+
+    /**
+     * Adds the tests from the given class to the suite.
+     *
+     * @psalm-param object|class-string $testClass
+     *
+     * @throws Exception
+     */
+    public function addTestSuite($testClass): void
+    {
+        if (!(is_object($testClass) || (is_string($testClass) && class_exists($testClass)))) {
+            throw InvalidArgumentException::create(
+                1,
+                'class name or object'
+            );
+        }
+
+        if (!is_object($testClass)) {
+            try {
+                $testClass = new ReflectionClass($testClass);
+                // @codeCoverageIgnoreStart
+            } catch (ReflectionException $e) {
+                throw new Exception(
+                    $e->getMessage(),
+                    (int) $e->getCode(),
+                    $e
+                );
+            }
+            // @codeCoverageIgnoreEnd
+        }
+
+        if ($testClass instanceof self) {
+            $this->addTest($testClass);
+        } elseif ($testClass instanceof ReflectionClass) {
+            $suiteMethod = false;
+
+            if (!$testClass->isAbstract() && $testClass->hasMethod(BaseTestRunner::SUITE_METHODNAME)) {
+                try {
+                    $method = $testClass->getMethod(
+                        BaseTestRunner::SUITE_METHODNAME
+                    );
+                    // @codeCoverageIgnoreStart
+                } catch (ReflectionException $e) {
+                    throw new Exception(
+                        $e->getMessage(),
+                        (int) $e->getCode(),
+                        $e
+                    );
+                }
+                // @codeCoverageIgnoreEnd
+
+                if ($method->isStatic()) {
+                    $this->addTest(
+                        $method->invoke(null, $testClass->getName())
+                    );
+
+                    $suiteMethod = true;
+                }
+            }
+
+            if (!$suiteMethod && !$testClass->isAbstract() && $testClass->isSubclassOf(TestCase::class)) {
+                $this->addTest(new self($testClass));
+            }
+        } else {
+            throw new Exception;
+        }
+    }
+
+    public function addWarning(string $warning): void
+    {
+        $this->warnings[] = $warning;
+    }
+
+    /**
+     * Wraps both <code>addTest()</code> and <code>addTestSuite</code>
+     * as well as the separate import statements for the user's convenience.
+     *
+     * If the named file cannot be read or there are no new tests that can be
+     * added, a <code>PHPUnit\Framework\WarningTestCase</code> will be created instead,
+     * leaving the current test run untouched.
+     *
+     * @throws Exception
+     */
+    public function addTestFile(string $filename): void
+    {
+        if (is_file($filename) && substr($filename, -5) === '.phpt') {
+            $this->addTest(new PhptTestCase($filename));
+
+            $this->declaredClasses = get_declared_classes();
+
+            return;
+        }
+
+        $numTests = count($this->tests);
+
+        // The given file may contain further stub classes in addition to the
+        // test class itself. Figure out the actual test class.
+        $filename   = FileLoader::checkAndLoad($filename);
+        $newClasses = array_diff(get_declared_classes(), $this->declaredClasses);
+
+        // The diff is empty in case a parent class (with test methods) is added
+        // AFTER a child class that inherited from it. To account for that case,
+        // accumulate all discovered classes, so the parent class may be found in
+        // a later invocation.
+        if (!empty($newClasses)) {
+            // On the assumption that test classes are defined first in files,
+            // process discovered classes in approximate LIFO order, so as to
+            // avoid unnecessary reflection.
+            $this->foundClasses    = array_merge($newClasses, $this->foundClasses);
+            $this->declaredClasses = get_declared_classes();
+        }
+
+        // The test class's name must match the filename, either in full, or as
+        // a PEAR/PSR-0 prefixed short name ('NameSpace_ShortName'), or as a
+        // PSR-1 local short name ('NameSpace\ShortName'). The comparison must be
+        // anchored to prevent false-positive matches (e.g., 'OtherShortName').
+        $shortName      = basename($filename, '.php');
+        $shortNameRegEx = '/(?:^|_|\\\\)' . preg_quote($shortName, '/') . '$/';
+
+        foreach ($this->foundClasses as $i => $className) {
+            if (preg_match($shortNameRegEx, $className)) {
+                try {
+                    $class = new ReflectionClass($className);
+                    // @codeCoverageIgnoreStart
+                } catch (ReflectionException $e) {
+                    throw new Exception(
+                        $e->getMessage(),
+                        (int) $e->getCode(),
+                        $e
+                    );
+                }
+                // @codeCoverageIgnoreEnd
+
+                if ($class->getFileName() == $filename) {
+                    $newClasses = [$className];
+                    unset($this->foundClasses[$i]);
+
+                    break;
+                }
+            }
+        }
+
+        foreach ($newClasses as $className) {
+            try {
+                $class = new ReflectionClass($className);
+                // @codeCoverageIgnoreStart
+            } catch (ReflectionException $e) {
+                throw new Exception(
+                    $e->getMessage(),
+                    (int) $e->getCode(),
+                    $e
+                );
+            }
+            // @codeCoverageIgnoreEnd
+
+            if (dirname($class->getFileName()) === __DIR__) {
+                continue;
+            }
+
+            if (!$class->isAbstract()) {
+                if ($class->hasMethod(BaseTestRunner::SUITE_METHODNAME)) {
+                    try {
+                        $method = $class->getMethod(
+                            BaseTestRunner::SUITE_METHODNAME
+                        );
+                        // @codeCoverageIgnoreStart
+                    } catch (ReflectionException $e) {
+                        throw new Exception(
+                            $e->getMessage(),
+                            (int) $e->getCode(),
+                            $e
+                        );
+                    }
+                    // @codeCoverageIgnoreEnd
+
+                    if ($method->isStatic()) {
+                        $this->addTest($method->invoke(null, $className));
+                    }
+                } elseif ($class->implementsInterface(Test::class)) {
+                    $expectedClassName = $shortName;
+
+                    if (($pos = strpos($expectedClassName, '.')) !== false) {
+                        $expectedClassName = substr(
+                            $expectedClassName,
+                            0,
+                            $pos
+                        );
+                    }
+
+                    if ($class->getShortName() !== $expectedClassName) {
+                        $this->addWarning(
+                            sprintf(
+                                "Test case class not matching filename is deprecated\n               in %s\n               Class name was '%s', expected '%s'",
+                                $filename,
+                                $class->getShortName(),
+                                $expectedClassName
+                            )
+                        );
+                    }
+
+                    $this->addTestSuite($class);
+                }
+            }
+        }
+
+        if (count($this->tests) > ++$numTests) {
+            $this->addWarning(
+                sprintf(
+                    "Multiple test case classes per file is deprecated\n               in %s",
+                    $filename
+                )
+            );
+        }
+
+        $this->numTests = -1;
+    }
+
+    /**
+     * Wrapper for addTestFile() that adds multiple test files.
+     *
+     * @throws Exception
+     */
+    public function addTestFiles(iterable $fileNames): void
+    {
+        foreach ($fileNames as $filename) {
+            $this->addTestFile((string) $filename);
+        }
+    }
+
+    /**
+     * Counts the number of test cases that will be run by this test.
+     *
+     * @todo refactor usage of numTests in DefaultResultPrinter
+     */
+    public function count(): int
+    {
+        $this->numTests = 0;
+
+        foreach ($this as $test) {
+            $this->numTests += count($test);
+        }
+
+        return $this->numTests;
+    }
+
+    /**
+     * Returns the name of the suite.
+     */
+    public function getName(): string
+    {
+        return $this->name;
+    }
+
+    /**
+     * Returns the test groups of the suite.
+     *
+     * @psalm-return list<string>
+     */
+    public function getGroups(): array
+    {
+        return array_map(
+            static function ($key): string {
+                return (string) $key;
+            },
+            array_keys($this->groups)
+        );
+    }
+
+    public function getGroupDetails(): array
+    {
+        return $this->groups;
+    }
+
+    /**
+     * Set tests groups of the test case.
+     */
+    public function setGroupDetails(array $groups): void
+    {
+        $this->groups = $groups;
+    }
+
+    /**
+     * Runs the tests and collects their result in a TestResult.
+     *
+     * @throws \PHPUnit\Framework\CodeCoverageException
+     * @throws \SebastianBergmann\CodeCoverage\InvalidArgumentException
+     * @throws \SebastianBergmann\CodeCoverage\UnintentionallyCoveredCodeException
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws Warning
+     */
+    public function run(TestResult $result = null): TestResult
+    {
+        if ($result === null) {
+            $result = $this->createResult();
+        }
+
+        if (count($this) === 0) {
+            return $result;
+        }
+
+        /** @psalm-var class-string $className */
+        $className   = $this->name;
+        $hookMethods = TestUtil::getHookMethods($className);
+
+        $result->startTestSuite($this);
+
+        $test = null;
+
+        if ($this->testCase && class_exists($this->name, false)) {
+            try {
+                foreach ($hookMethods['beforeClass'] as $beforeClassMethod) {
+                    if (method_exists($this->name, $beforeClassMethod)) {
+                        if ($missingRequirements = TestUtil::getMissingRequirements($this->name, $beforeClassMethod)) {
+                            $this->markTestSuiteSkipped(implode(PHP_EOL, $missingRequirements));
+                        }
+
+                        call_user_func([$this->name, $beforeClassMethod]);
+                    }
+                }
+            } catch (SkippedTestSuiteError $error) {
+                foreach ($this->tests() as $test) {
+                    $result->startTest($test);
+                    $result->addFailure($test, $error, 0);
+                    $result->endTest($test, 0);
+                }
+
+                $result->endTestSuite($this);
+
+                return $result;
+            } catch (Throwable $t) {
+                $errorAdded = false;
+
+                foreach ($this->tests() as $test) {
+                    if ($result->shouldStop()) {
+                        break;
+                    }
+
+                    $result->startTest($test);
+
+                    if (!$errorAdded) {
+                        $result->addError($test, $t, 0);
+
+                        $errorAdded = true;
+                    } else {
+                        $result->addFailure(
+                            $test,
+                            new SkippedTestError('Test skipped because of an error in hook method'),
+                            0
+                        );
+                    }
+
+                    $result->endTest($test, 0);
+                }
+
+                $result->endTestSuite($this);
+
+                return $result;
+            }
+        }
+
+        foreach ($this as $test) {
+            if ($result->shouldStop()) {
+                break;
+            }
+
+            if ($test instanceof TestCase || $test instanceof self) {
+                $test->setBeStrictAboutChangesToGlobalState($this->beStrictAboutChangesToGlobalState);
+                $test->setBackupGlobals($this->backupGlobals);
+                $test->setBackupStaticAttributes($this->backupStaticAttributes);
+                $test->setRunTestInSeparateProcess($this->runTestInSeparateProcess);
+            }
+
+            $test->run($result);
+        }
+
+        if ($this->testCase && class_exists($this->name, false)) {
+            foreach ($hookMethods['afterClass'] as $afterClassMethod) {
+                if (method_exists($this->name, $afterClassMethod)) {
+                    try {
+                        call_user_func([$this->name, $afterClassMethod]);
+                    } catch (Throwable $t) {
+                        $message = "Exception in {$this->name}::{$afterClassMethod}" . PHP_EOL . $t->getMessage();
+                        $error   = new SyntheticError($message, 0, $t->getFile(), $t->getLine(), $t->getTrace());
+
+                        $placeholderTest = clone $test;
+                        $placeholderTest->setName($afterClassMethod);
+
+                        $result->startTest($placeholderTest);
+                        $result->addFailure($placeholderTest, $error, 0);
+                        $result->endTest($placeholderTest, 0);
+                    }
+                }
+            }
+        }
+
+        $result->endTestSuite($this);
+
+        return $result;
+    }
+
+    public function setRunTestInSeparateProcess(bool $runTestInSeparateProcess): void
+    {
+        $this->runTestInSeparateProcess = $runTestInSeparateProcess;
+    }
+
+    public function setName(string $name): void
+    {
+        $this->name = $name;
+    }
+
+    /**
+     * Returns the tests as an enumeration.
+     *
+     * @return Test[]
+     */
+    public function tests(): array
+    {
+        return $this->tests;
+    }
+
+    /**
+     * Set tests of the test suite.
+     *
+     * @param Test[] $tests
+     */
+    public function setTests(array $tests): void
+    {
+        $this->tests = $tests;
+    }
+
+    /**
+     * Mark the test suite as skipped.
+     *
+     * @param string $message
+     *
+     * @throws SkippedTestSuiteError
+     *
+     * @psalm-return never-return
+     */
+    public function markTestSuiteSkipped($message = ''): void
+    {
+        throw new SkippedTestSuiteError($message);
+    }
+
+    /**
+     * @param bool $beStrictAboutChangesToGlobalState
+     */
+    public function setBeStrictAboutChangesToGlobalState($beStrictAboutChangesToGlobalState): void
+    {
+        if (null === $this->beStrictAboutChangesToGlobalState && is_bool($beStrictAboutChangesToGlobalState)) {
+            $this->beStrictAboutChangesToGlobalState = $beStrictAboutChangesToGlobalState;
+        }
+    }
+
+    /**
+     * @param bool $backupGlobals
+     */
+    public function setBackupGlobals($backupGlobals): void
+    {
+        if (null === $this->backupGlobals && is_bool($backupGlobals)) {
+            $this->backupGlobals = $backupGlobals;
+        }
+    }
+
+    /**
+     * @param bool $backupStaticAttributes
+     */
+    public function setBackupStaticAttributes($backupStaticAttributes): void
+    {
+        if (null === $this->backupStaticAttributes && is_bool($backupStaticAttributes)) {
+            $this->backupStaticAttributes = $backupStaticAttributes;
+        }
+    }
+
+    /**
+     * Returns an iterator for this test suite.
+     */
+    public function getIterator(): Iterator
+    {
+        $iterator = new TestSuiteIterator($this);
+
+        if ($this->iteratorFilter !== null) {
+            $iterator = $this->iteratorFilter->factory($iterator, $this);
+        }
+
+        return $iterator;
+    }
+
+    public function injectFilter(Factory $filter): void
+    {
+        $this->iteratorFilter = $filter;
+
+        foreach ($this as $test) {
+            if ($test instanceof self) {
+                $test->injectFilter($filter);
+            }
+        }
+    }
+
+    /**
+     * @psalm-return array<int,string>
+     */
+    public function warnings(): array
+    {
+        return array_unique($this->warnings);
+    }
+
+    /**
+     * @return list<ExecutionOrderDependency>
+     */
+    public function provides(): array
+    {
+        if ($this->providedTests === null) {
+            $this->providedTests = [];
+
+            if (is_callable($this->sortId(), true)) {
+                $this->providedTests[] = new ExecutionOrderDependency($this->sortId());
+            }
+
+            foreach ($this->tests as $test) {
+                if (!($test instanceof Reorderable)) {
+                    // @codeCoverageIgnoreStart
+                    continue;
+                    // @codeCoverageIgnoreEnd
+                }
+                $this->providedTests = ExecutionOrderDependency::mergeUnique($this->providedTests, $test->provides());
+            }
+        }
+
+        return $this->providedTests;
+    }
+
+    /**
+     * @return list<ExecutionOrderDependency>
+     */
+    public function requires(): array
+    {
+        if ($this->requiredTests === null) {
+            $this->requiredTests = [];
+
+            foreach ($this->tests as $test) {
+                if (!($test instanceof Reorderable)) {
+                    // @codeCoverageIgnoreStart
+                    continue;
+                    // @codeCoverageIgnoreEnd
+                }
+                $this->requiredTests = ExecutionOrderDependency::mergeUnique(
+                    ExecutionOrderDependency::filterInvalid($this->requiredTests),
+                    $test->requires()
+                );
+            }
+
+            $this->requiredTests = ExecutionOrderDependency::diff($this->requiredTests, $this->provides());
+        }
+
+        return $this->requiredTests;
+    }
+
+    public function sortId(): string
+    {
+        return $this->getName() . '::class';
+    }
+
+    /**
+     * Creates a default TestResult object.
+     */
+    protected function createResult(): TestResult
+    {
+        return new TestResult;
+    }
+
+    /**
+     * @throws Exception
+     */
+    protected function addTestMethod(ReflectionClass $class, ReflectionMethod $method): void
+    {
+        $methodName = $method->getName();
+
+        $test = (new TestBuilder)->build($class, $methodName);
+
+        if ($test instanceof TestCase || $test instanceof DataProviderTestSuite) {
+            $test->setDependencies(
+                TestUtil::getDependencies($class->getName(), $methodName)
+            );
+        }
+
+        $this->addTest(
+            $test,
+            TestUtil::getGroups($class->getName(), $methodName)
+        );
+    }
+
+    private function clearCaches(): void
+    {
+        $this->numTests      = -1;
+        $this->providedTests = null;
+        $this->requiredTests = null;
+    }
+
+    private function containsOnlyVirtualGroups(array $groups): bool
+    {
+        foreach ($groups as $group) {
+            if (strpos($group, '__phpunit_') !== 0) {
+                return false;
+            }
+        }
+
+        return true;
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/TestSuiteIterator.php b/vendor/phpunit/phpunit/src/Framework/TestSuiteIterator.php
new file mode 100644
index 0000000000000000000000000000000000000000..e351622f39c6b2c1bed27f6c38665f31421c2767
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/TestSuiteIterator.php
@@ -0,0 +1,83 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework;
+
+use function assert;
+use function count;
+use RecursiveIterator;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class TestSuiteIterator implements RecursiveIterator
+{
+    /**
+     * @var int
+     */
+    private $position = 0;
+
+    /**
+     * @var Test[]
+     */
+    private $tests;
+
+    public function __construct(TestSuite $testSuite)
+    {
+        $this->tests = $testSuite->tests();
+    }
+
+    public function rewind(): void
+    {
+        $this->position = 0;
+    }
+
+    public function valid(): bool
+    {
+        return $this->position < count($this->tests);
+    }
+
+    public function key(): int
+    {
+        return $this->position;
+    }
+
+    public function current(): Test
+    {
+        return $this->tests[$this->position];
+    }
+
+    public function next(): void
+    {
+        $this->position++;
+    }
+
+    /**
+     * @throws NoChildTestSuiteException
+     */
+    public function getChildren(): self
+    {
+        if (!$this->hasChildren()) {
+            throw new NoChildTestSuiteException(
+                'The current item is not a TestSuite instance and therefore does not have any children.'
+            );
+        }
+
+        $current = $this->current();
+
+        assert($current instanceof TestSuite);
+
+        return new self($current);
+    }
+
+    public function hasChildren(): bool
+    {
+        return $this->valid() && $this->current() instanceof TestSuite;
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Framework/WarningTestCase.php b/vendor/phpunit/phpunit/src/Framework/WarningTestCase.php
new file mode 100644
index 0000000000000000000000000000000000000000..e1e41bc44b902de72069d409a9c44cc6ac68c565
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Framework/WarningTestCase.php
@@ -0,0 +1,66 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Framework;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class WarningTestCase extends TestCase
+{
+    /**
+     * @var bool
+     */
+    protected $backupGlobals = false;
+
+    /**
+     * @var bool
+     */
+    protected $backupStaticAttributes = false;
+
+    /**
+     * @var bool
+     */
+    protected $runTestInSeparateProcess = false;
+
+    /**
+     * @var string
+     */
+    private $message;
+
+    public function __construct(string $message = '')
+    {
+        $this->message = $message;
+
+        parent::__construct('Warning');
+    }
+
+    public function getMessage(): string
+    {
+        return $this->message;
+    }
+
+    /**
+     * Returns a string representation of the test case.
+     */
+    public function toString(): string
+    {
+        return 'Warning';
+    }
+
+    /**
+     * @throws Exception
+     *
+     * @psalm-return never-return
+     */
+    protected function runTest(): void
+    {
+        throw new Warning($this->message);
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Runner/BaseTestRunner.php b/vendor/phpunit/phpunit/src/Runner/BaseTestRunner.php
new file mode 100644
index 0000000000000000000000000000000000000000..75a70ca5fcc7d2f124c931fd8b8401ba5802de45
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Runner/BaseTestRunner.php
@@ -0,0 +1,161 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Runner;
+
+use function is_dir;
+use function is_file;
+use function substr;
+use PHPUnit\Framework\Exception;
+use PHPUnit\Framework\TestSuite;
+use ReflectionClass;
+use ReflectionException;
+use SebastianBergmann\FileIterator\Facade as FileIteratorFacade;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+abstract class BaseTestRunner
+{
+    /**
+     * @var int
+     */
+    public const STATUS_UNKNOWN = -1;
+
+    /**
+     * @var int
+     */
+    public const STATUS_PASSED = 0;
+
+    /**
+     * @var int
+     */
+    public const STATUS_SKIPPED = 1;
+
+    /**
+     * @var int
+     */
+    public const STATUS_INCOMPLETE = 2;
+
+    /**
+     * @var int
+     */
+    public const STATUS_FAILURE = 3;
+
+    /**
+     * @var int
+     */
+    public const STATUS_ERROR = 4;
+
+    /**
+     * @var int
+     */
+    public const STATUS_RISKY = 5;
+
+    /**
+     * @var int
+     */
+    public const STATUS_WARNING = 6;
+
+    /**
+     * @var string
+     */
+    public const SUITE_METHODNAME = 'suite';
+
+    /**
+     * Returns the loader to be used.
+     */
+    public function getLoader(): TestSuiteLoader
+    {
+        return new StandardTestSuiteLoader;
+    }
+
+    /**
+     * Returns the Test corresponding to the given suite.
+     * This is a template method, subclasses override
+     * the runFailed() and clearStatus() methods.
+     *
+     * @param string|string[] $suffixes
+     *
+     * @throws Exception
+     */
+    public function getTest(string $suiteClassFile, $suffixes = ''): ?TestSuite
+    {
+        if (is_dir($suiteClassFile)) {
+            /** @var string[] $files */
+            $files = (new FileIteratorFacade)->getFilesAsArray(
+                $suiteClassFile,
+                $suffixes
+            );
+
+            $suite = new TestSuite($suiteClassFile);
+            $suite->addTestFiles($files);
+
+            return $suite;
+        }
+
+        if (is_file($suiteClassFile) && substr($suiteClassFile, -5, 5) === '.phpt') {
+            $suite = new TestSuite;
+            $suite->addTestFile($suiteClassFile);
+
+            return $suite;
+        }
+
+        try {
+            $testClass = $this->loadSuiteClass(
+                $suiteClassFile
+            );
+        } catch (\PHPUnit\Exception $e) {
+            $this->runFailed($e->getMessage());
+
+            return null;
+        }
+
+        try {
+            $suiteMethod = $testClass->getMethod(self::SUITE_METHODNAME);
+
+            if (!$suiteMethod->isStatic()) {
+                $this->runFailed(
+                    'suite() method must be static.'
+                );
+
+                return null;
+            }
+
+            $test = $suiteMethod->invoke(null, $testClass->getName());
+        } catch (ReflectionException $e) {
+            $test = new TestSuite($testClass);
+        }
+
+        $this->clearStatus();
+
+        return $test;
+    }
+
+    /**
+     * Returns the loaded ReflectionClass for a suite name.
+     */
+    protected function loadSuiteClass(string $suiteClassFile): ReflectionClass
+    {
+        return $this->getLoader()->load($suiteClassFile);
+    }
+
+    /**
+     * Clears the status message.
+     */
+    protected function clearStatus(): void
+    {
+    }
+
+    /**
+     * Override to define how to handle a failed loading of
+     * a test suite.
+     */
+    abstract protected function runFailed(string $message): void;
+}
diff --git a/vendor/phpunit/phpunit/src/Runner/DefaultTestResultCache.php b/vendor/phpunit/phpunit/src/Runner/DefaultTestResultCache.php
new file mode 100644
index 0000000000000000000000000000000000000000..906a28f6d5aaab55e37fa4bf6b5ccfb9bf2e930a
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Runner/DefaultTestResultCache.php
@@ -0,0 +1,233 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Runner;
+
+use const DIRECTORY_SEPARATOR;
+use function assert;
+use function defined;
+use function dirname;
+use function file_get_contents;
+use function file_put_contents;
+use function in_array;
+use function is_dir;
+use function is_file;
+use function is_float;
+use function is_int;
+use function is_string;
+use function serialize;
+use function sprintf;
+use function unserialize;
+use PHPUnit\Util\ErrorHandler;
+use PHPUnit\Util\Filesystem;
+use Serializable;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class DefaultTestResultCache implements Serializable, TestResultCache
+{
+    /**
+     * @var string
+     */
+    public const DEFAULT_RESULT_CACHE_FILENAME = '.phpunit.result.cache';
+
+    /**
+     * Provide extra protection against incomplete or corrupt caches.
+     *
+     * @var int[]
+     */
+    private const ALLOWED_CACHE_TEST_STATUSES = [
+        BaseTestRunner::STATUS_SKIPPED,
+        BaseTestRunner::STATUS_INCOMPLETE,
+        BaseTestRunner::STATUS_FAILURE,
+        BaseTestRunner::STATUS_ERROR,
+        BaseTestRunner::STATUS_RISKY,
+        BaseTestRunner::STATUS_WARNING,
+    ];
+
+    /**
+     * Path and filename for result cache file.
+     *
+     * @var string
+     */
+    private $cacheFilename;
+
+    /**
+     * The list of defective tests.
+     *
+     * <code>
+     * // Mark a test skipped
+     * $this->defects[$testName] = BaseTestRunner::TEST_SKIPPED;
+     * </code>
+     *
+     * @var array<string, int>
+     */
+    private $defects = [];
+
+    /**
+     * The list of execution duration of suites and tests (in seconds).
+     *
+     * <code>
+     * // Record running time for test
+     * $this->times[$testName] = 1.234;
+     * </code>
+     *
+     * @var array<string, float>
+     */
+    private $times = [];
+
+    public function __construct(?string $filepath = null)
+    {
+        if ($filepath !== null && is_dir($filepath)) {
+            // cache path provided, use default cache filename in that location
+            $filepath .= DIRECTORY_SEPARATOR . self::DEFAULT_RESULT_CACHE_FILENAME;
+        }
+
+        $this->cacheFilename = $filepath ?? $_ENV['PHPUNIT_RESULT_CACHE'] ?? self::DEFAULT_RESULT_CACHE_FILENAME;
+    }
+
+    /**
+     * @throws Exception
+     */
+    public function persist(): void
+    {
+        $this->saveToFile();
+    }
+
+    /**
+     * @throws Exception
+     */
+    public function saveToFile(): void
+    {
+        if (defined('PHPUNIT_TESTSUITE_RESULTCACHE')) {
+            return;
+        }
+
+        if (!Filesystem::createDirectory(dirname($this->cacheFilename))) {
+            throw new Exception(
+                sprintf(
+                    'Cannot create directory "%s" for result cache file',
+                    $this->cacheFilename
+                )
+            );
+        }
+
+        file_put_contents(
+            $this->cacheFilename,
+            serialize($this)
+        );
+    }
+
+    public function setState(string $testName, int $state): void
+    {
+        if ($state !== BaseTestRunner::STATUS_PASSED) {
+            $this->defects[$testName] = $state;
+        }
+    }
+
+    public function getState(string $testName): int
+    {
+        return $this->defects[$testName] ?? BaseTestRunner::STATUS_UNKNOWN;
+    }
+
+    public function setTime(string $testName, float $time): void
+    {
+        $this->times[$testName] = $time;
+    }
+
+    public function getTime(string $testName): float
+    {
+        return $this->times[$testName] ?? 0.0;
+    }
+
+    public function load(): void
+    {
+        $this->clear();
+
+        if (!is_file($this->cacheFilename)) {
+            return;
+        }
+
+        $cacheData = @file_get_contents($this->cacheFilename);
+
+        // @codeCoverageIgnoreStart
+        if ($cacheData === false) {
+            return;
+        }
+        // @codeCoverageIgnoreEnd
+
+        $cache = ErrorHandler::invokeIgnoringWarnings(
+            static function () use ($cacheData) {
+                return @unserialize($cacheData, ['allowed_classes' => [self::class]]);
+            }
+        );
+
+        if ($cache === false) {
+            return;
+        }
+
+        if ($cache instanceof self) {
+            /* @var DefaultTestResultCache $cache */
+            $cache->copyStateToCache($this);
+        }
+    }
+
+    public function copyStateToCache(self $targetCache): void
+    {
+        foreach ($this->defects as $name => $state) {
+            $targetCache->setState($name, $state);
+        }
+
+        foreach ($this->times as $name => $time) {
+            $targetCache->setTime($name, $time);
+        }
+    }
+
+    public function clear(): void
+    {
+        $this->defects = [];
+        $this->times   = [];
+    }
+
+    public function serialize(): string
+    {
+        return serialize([
+            'defects' => $this->defects,
+            'times'   => $this->times,
+        ]);
+    }
+
+    /**
+     * @param string $serialized
+     */
+    public function unserialize($serialized): void
+    {
+        $data = unserialize($serialized);
+
+        if (isset($data['times'])) {
+            foreach ($data['times'] as $testName => $testTime) {
+                assert(is_string($testName));
+                assert(is_float($testTime));
+                $this->times[$testName] = $testTime;
+            }
+        }
+
+        if (isset($data['defects'])) {
+            foreach ($data['defects'] as $testName => $testResult) {
+                assert(is_string($testName));
+                assert(is_int($testResult));
+
+                if (in_array($testResult, self::ALLOWED_CACHE_TEST_STATUSES, true)) {
+                    $this->defects[$testName] = $testResult;
+                }
+            }
+        }
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Runner/Exception.php b/vendor/phpunit/phpunit/src/Runner/Exception.php
new file mode 100644
index 0000000000000000000000000000000000000000..adcd1155806cb869a9182030214e062f485cf3a7
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Runner/Exception.php
@@ -0,0 +1,19 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Runner;
+
+use RuntimeException;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class Exception extends RuntimeException implements \PHPUnit\Exception
+{
+}
diff --git a/vendor/phpunit/phpunit/src/Runner/Extension/ExtensionHandler.php b/vendor/phpunit/phpunit/src/Runner/Extension/ExtensionHandler.php
new file mode 100644
index 0000000000000000000000000000000000000000..286f717ee07a8b44587628771c8180713a61b02f
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Runner/Extension/ExtensionHandler.php
@@ -0,0 +1,117 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Runner\Extension;
+
+use function class_exists;
+use function sprintf;
+use PHPUnit\Framework\TestListener;
+use PHPUnit\Runner\Exception;
+use PHPUnit\Runner\Hook;
+use PHPUnit\TextUI\TestRunner;
+use PHPUnit\TextUI\XmlConfiguration\Extension;
+use ReflectionClass;
+use ReflectionException;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class ExtensionHandler
+{
+    /**
+     * @throws Exception
+     */
+    public function registerExtension(Extension $extensionConfiguration, TestRunner $runner): void
+    {
+        $extension = $this->createInstance($extensionConfiguration);
+
+        if (!$extension instanceof Hook) {
+            throw new Exception(
+                sprintf(
+                    'Class "%s" does not implement a PHPUnit\Runner\Hook interface',
+                    $extensionConfiguration->className()
+                )
+            );
+        }
+
+        $runner->addExtension($extension);
+    }
+
+    /**
+     * @throws Exception
+     *
+     * @deprecated
+     */
+    public function createTestListenerInstance(Extension $listenerConfiguration): TestListener
+    {
+        $listener = $this->createInstance($listenerConfiguration);
+
+        if (!$listener instanceof TestListener) {
+            throw new Exception(
+                sprintf(
+                    'Class "%s" does not implement the PHPUnit\Framework\TestListener interface',
+                    $listenerConfiguration->className()
+                )
+            );
+        }
+
+        return $listener;
+    }
+
+    /**
+     * @throws Exception
+     */
+    private function createInstance(Extension $extensionConfiguration): object
+    {
+        $this->ensureClassExists($extensionConfiguration);
+
+        try {
+            $reflector = new ReflectionClass($extensionConfiguration->className());
+        } catch (ReflectionException $e) {
+            throw new Exception(
+                $e->getMessage(),
+                (int) $e->getCode(),
+                $e
+            );
+        }
+
+        if (!$extensionConfiguration->hasArguments()) {
+            return $reflector->newInstance();
+        }
+
+        return $reflector->newInstanceArgs($extensionConfiguration->arguments());
+    }
+
+    /**
+     * @throws Exception
+     */
+    private function ensureClassExists(Extension $extensionConfiguration): void
+    {
+        if (class_exists($extensionConfiguration->className(), false)) {
+            return;
+        }
+
+        if ($extensionConfiguration->hasSourceFile()) {
+            /**
+             * @noinspection PhpIncludeInspection
+             * @psalm-suppress UnresolvableInclude
+             */
+            require_once $extensionConfiguration->sourceFile();
+        }
+
+        if (!class_exists($extensionConfiguration->className())) {
+            throw new Exception(
+                sprintf(
+                    'Class "%s" does not exist',
+                    $extensionConfiguration->className()
+                )
+            );
+        }
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Runner/Extension/PharLoader.php b/vendor/phpunit/phpunit/src/Runner/Extension/PharLoader.php
new file mode 100644
index 0000000000000000000000000000000000000000..adc4cd77c7169c8e1e3c128f2cb4785d8a9a94b7
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Runner/Extension/PharLoader.php
@@ -0,0 +1,75 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Runner\Extension;
+
+use PharIo\Manifest\ApplicationName;
+use PharIo\Manifest\Exception as ManifestException;
+use PharIo\Manifest\ManifestLoader;
+use PharIo\Version\Version as PharIoVersion;
+use PHPUnit\Runner\Version;
+use SebastianBergmann\FileIterator\Facade as FileIteratorFacade;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class PharLoader
+{
+    /**
+     * @psalm-return array{loadedExtensions: list<string>, notLoadedExtensions: list<string>}
+     */
+    public function loadPharExtensionsInDirectory(string $directory): array
+    {
+        $loadedExtensions    = [];
+        $notLoadedExtensions = [];
+
+        foreach ((new FileIteratorFacade)->getFilesAsArray($directory, '.phar') as $file) {
+            if (!is_file('phar://' . $file . '/manifest.xml')) {
+                $notLoadedExtensions[] = $file . ' is not an extension for PHPUnit';
+
+                continue;
+            }
+
+            try {
+                $applicationName = new ApplicationName('phpunit/phpunit');
+                $version         = new PharIoVersion(Version::series());
+                $manifest        = ManifestLoader::fromFile('phar://' . $file . '/manifest.xml');
+
+                if (!$manifest->isExtensionFor($applicationName)) {
+                    $notLoadedExtensions[] = $file . ' is not an extension for PHPUnit';
+
+                    continue;
+                }
+
+                if (!$manifest->isExtensionFor($applicationName, $version)) {
+                    $notLoadedExtensions[] = $file . ' is not compatible with this version of PHPUnit';
+
+                    continue;
+                }
+            } catch (ManifestException $e) {
+                $notLoadedExtensions[] = $file . ': ' . $e->getMessage();
+
+                continue;
+            }
+
+            /**
+             * @noinspection PhpIncludeInspection
+             * @psalm-suppress UnresolvableInclude
+             */
+            require $file;
+
+            $loadedExtensions[] = $manifest->getName()->asString() . ' ' . $manifest->getVersion()->getVersionString();
+        }
+
+        return [
+            'loadedExtensions'    => $loadedExtensions,
+            'notLoadedExtensions' => $notLoadedExtensions,
+        ];
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Runner/Filter/ExcludeGroupFilterIterator.php b/vendor/phpunit/phpunit/src/Runner/Filter/ExcludeGroupFilterIterator.php
new file mode 100644
index 0000000000000000000000000000000000000000..4b26e5716e97ef4dfeaecdbbdc670f8a143e0ab1
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Runner/Filter/ExcludeGroupFilterIterator.php
@@ -0,0 +1,23 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Runner\Filter;
+
+use function in_array;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class ExcludeGroupFilterIterator extends GroupFilterIterator
+{
+    protected function doAccept(string $hash): bool
+    {
+        return !in_array($hash, $this->groupTests, true);
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Runner/Filter/Factory.php b/vendor/phpunit/phpunit/src/Runner/Filter/Factory.php
new file mode 100644
index 0000000000000000000000000000000000000000..3f79da5412296e21a67e93b13477e6bd048132b0
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Runner/Filter/Factory.php
@@ -0,0 +1,61 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Runner\Filter;
+
+use function assert;
+use function sprintf;
+use FilterIterator;
+use Iterator;
+use PHPUnit\Framework\TestSuite;
+use PHPUnit\Runner\Exception;
+use RecursiveFilterIterator;
+use ReflectionClass;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class Factory
+{
+    /**
+     * @psalm-var array<int,array{0: \ReflectionClass, 1: array|string}>
+     */
+    private $filters = [];
+
+    /**
+     * @param array|string $args
+     *
+     * @throws Exception
+     */
+    public function addFilter(ReflectionClass $filter, $args): void
+    {
+        if (!$filter->isSubclassOf(RecursiveFilterIterator::class)) {
+            throw new Exception(
+                sprintf(
+                    'Class "%s" does not extend RecursiveFilterIterator',
+                    $filter->name
+                )
+            );
+        }
+
+        $this->filters[] = [$filter, $args];
+    }
+
+    public function factory(Iterator $iterator, TestSuite $suite): FilterIterator
+    {
+        foreach ($this->filters as $filter) {
+            [$class, $args] = $filter;
+            $iterator       = $class->newInstance($iterator, $args, $suite);
+        }
+
+        assert($iterator instanceof FilterIterator);
+
+        return $iterator;
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Runner/Filter/GroupFilterIterator.php b/vendor/phpunit/phpunit/src/Runner/Filter/GroupFilterIterator.php
new file mode 100644
index 0000000000000000000000000000000000000000..42ca77a38124c8d8662ae27f2aa57e7525605076
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Runner/Filter/GroupFilterIterator.php
@@ -0,0 +1,58 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Runner\Filter;
+
+use function array_map;
+use function array_merge;
+use function in_array;
+use function spl_object_hash;
+use PHPUnit\Framework\TestSuite;
+use RecursiveFilterIterator;
+use RecursiveIterator;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+abstract class GroupFilterIterator extends RecursiveFilterIterator
+{
+    /**
+     * @var string[]
+     */
+    protected $groupTests = [];
+
+    public function __construct(RecursiveIterator $iterator, array $groups, TestSuite $suite)
+    {
+        parent::__construct($iterator);
+
+        foreach ($suite->getGroupDetails() as $group => $tests) {
+            if (in_array((string) $group, $groups, true)) {
+                $testHashes = array_map(
+                    'spl_object_hash',
+                    $tests
+                );
+
+                $this->groupTests = array_merge($this->groupTests, $testHashes);
+            }
+        }
+    }
+
+    public function accept(): bool
+    {
+        $test = $this->getInnerIterator()->current();
+
+        if ($test instanceof TestSuite) {
+            return true;
+        }
+
+        return $this->doAccept(spl_object_hash($test));
+    }
+
+    abstract protected function doAccept(string $hash);
+}
diff --git a/vendor/phpunit/phpunit/src/Runner/Filter/IncludeGroupFilterIterator.php b/vendor/phpunit/phpunit/src/Runner/Filter/IncludeGroupFilterIterator.php
new file mode 100644
index 0000000000000000000000000000000000000000..0346c60131afdaa78b2af9daf3ab7c94356e7da0
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Runner/Filter/IncludeGroupFilterIterator.php
@@ -0,0 +1,23 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Runner\Filter;
+
+use function in_array;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class IncludeGroupFilterIterator extends GroupFilterIterator
+{
+    protected function doAccept(string $hash): bool
+    {
+        return in_array($hash, $this->groupTests, true);
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Runner/Filter/NameFilterIterator.php b/vendor/phpunit/phpunit/src/Runner/Filter/NameFilterIterator.php
new file mode 100644
index 0000000000000000000000000000000000000000..7057e1c470e0d0a14069761abe02fa29770f22be
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Runner/Filter/NameFilterIterator.php
@@ -0,0 +1,136 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Runner\Filter;
+
+use function end;
+use function implode;
+use function preg_match;
+use function sprintf;
+use function str_replace;
+use Exception;
+use PHPUnit\Framework\ErrorTestCase;
+use PHPUnit\Framework\TestSuite;
+use PHPUnit\Framework\WarningTestCase;
+use PHPUnit\Util\RegularExpression;
+use RecursiveFilterIterator;
+use RecursiveIterator;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class NameFilterIterator extends RecursiveFilterIterator
+{
+    /**
+     * @var string
+     */
+    private $filter;
+
+    /**
+     * @var int
+     */
+    private $filterMin;
+
+    /**
+     * @var int
+     */
+    private $filterMax;
+
+    /**
+     * @throws Exception
+     */
+    public function __construct(RecursiveIterator $iterator, string $filter)
+    {
+        parent::__construct($iterator);
+
+        $this->setFilter($filter);
+    }
+
+    /**
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     */
+    public function accept(): bool
+    {
+        $test = $this->getInnerIterator()->current();
+
+        if ($test instanceof TestSuite) {
+            return true;
+        }
+
+        $tmp = \PHPUnit\Util\Test::describe($test);
+
+        if ($test instanceof ErrorTestCase || $test instanceof WarningTestCase) {
+            $name = $test->getMessage();
+        } elseif ($tmp[0] !== '') {
+            $name = implode('::', $tmp);
+        } else {
+            $name = $tmp[1];
+        }
+
+        $accepted = @preg_match($this->filter, $name, $matches);
+
+        if ($accepted && isset($this->filterMax)) {
+            $set      = end($matches);
+            $accepted = $set >= $this->filterMin && $set <= $this->filterMax;
+        }
+
+        return (bool) $accepted;
+    }
+
+    /**
+     * @throws Exception
+     */
+    private function setFilter(string $filter): void
+    {
+        if (RegularExpression::safeMatch($filter, '') === false) {
+            // Handles:
+            //  * testAssertEqualsSucceeds#4
+            //  * testAssertEqualsSucceeds#4-8
+            if (preg_match('/^(.*?)#(\d+)(?:-(\d+))?$/', $filter, $matches)) {
+                if (isset($matches[3]) && $matches[2] < $matches[3]) {
+                    $filter = sprintf(
+                        '%s.*with data set #(\d+)$',
+                        $matches[1]
+                    );
+
+                    $this->filterMin = (int) $matches[2];
+                    $this->filterMax = (int) $matches[3];
+                } else {
+                    $filter = sprintf(
+                        '%s.*with data set #%s$',
+                        $matches[1],
+                        $matches[2]
+                    );
+                }
+            } // Handles:
+            //  * testDetermineJsonError@JSON_ERROR_NONE
+            //  * testDetermineJsonError@JSON.*
+            elseif (preg_match('/^(.*?)@(.+)$/', $filter, $matches)) {
+                $filter = sprintf(
+                    '%s.*with data set "%s"$',
+                    $matches[1],
+                    $matches[2]
+                );
+            }
+
+            // Escape delimiters in regular expression. Do NOT use preg_quote,
+            // to keep magic characters.
+            $filter = sprintf(
+                '/%s/i',
+                str_replace(
+                    '/',
+                    '\\/',
+                    $filter
+                )
+            );
+        }
+
+        $this->filter = $filter;
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Runner/Hook/AfterIncompleteTestHook.php b/vendor/phpunit/phpunit/src/Runner/Hook/AfterIncompleteTestHook.php
new file mode 100644
index 0000000000000000000000000000000000000000..48441e6a22e0577f6bb70f1e432bf2631cfd9c70
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Runner/Hook/AfterIncompleteTestHook.php
@@ -0,0 +1,18 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Runner;
+
+/**
+ * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+ */
+interface AfterIncompleteTestHook extends TestHook
+{
+    public function executeAfterIncompleteTest(string $test, string $message, float $time): void;
+}
diff --git a/vendor/phpunit/phpunit/src/Runner/Hook/AfterLastTestHook.php b/vendor/phpunit/phpunit/src/Runner/Hook/AfterLastTestHook.php
new file mode 100644
index 0000000000000000000000000000000000000000..29997b7522e8655ccef04882fe857998330355a8
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Runner/Hook/AfterLastTestHook.php
@@ -0,0 +1,18 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Runner;
+
+/**
+ * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+ */
+interface AfterLastTestHook extends Hook
+{
+    public function executeAfterLastTest(): void;
+}
diff --git a/vendor/phpunit/phpunit/src/Runner/Hook/AfterRiskyTestHook.php b/vendor/phpunit/phpunit/src/Runner/Hook/AfterRiskyTestHook.php
new file mode 100644
index 0000000000000000000000000000000000000000..b45c77d2ad004755992f3aa871f147d48c037d26
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Runner/Hook/AfterRiskyTestHook.php
@@ -0,0 +1,18 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Runner;
+
+/**
+ * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+ */
+interface AfterRiskyTestHook extends TestHook
+{
+    public function executeAfterRiskyTest(string $test, string $message, float $time): void;
+}
diff --git a/vendor/phpunit/phpunit/src/Runner/Hook/AfterSkippedTestHook.php b/vendor/phpunit/phpunit/src/Runner/Hook/AfterSkippedTestHook.php
new file mode 100644
index 0000000000000000000000000000000000000000..17b202531620dd07aea12593bade8bdf396285b8
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Runner/Hook/AfterSkippedTestHook.php
@@ -0,0 +1,18 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Runner;
+
+/**
+ * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+ */
+interface AfterSkippedTestHook extends TestHook
+{
+    public function executeAfterSkippedTest(string $test, string $message, float $time): void;
+}
diff --git a/vendor/phpunit/phpunit/src/Runner/Hook/AfterSuccessfulTestHook.php b/vendor/phpunit/phpunit/src/Runner/Hook/AfterSuccessfulTestHook.php
new file mode 100644
index 0000000000000000000000000000000000000000..7ceb30f1596ebc5cafd659fafe4114efad024726
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Runner/Hook/AfterSuccessfulTestHook.php
@@ -0,0 +1,18 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Runner;
+
+/**
+ * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+ */
+interface AfterSuccessfulTestHook extends TestHook
+{
+    public function executeAfterSuccessfulTest(string $test, float $time): void;
+}
diff --git a/vendor/phpunit/phpunit/src/Runner/Hook/AfterTestErrorHook.php b/vendor/phpunit/phpunit/src/Runner/Hook/AfterTestErrorHook.php
new file mode 100644
index 0000000000000000000000000000000000000000..5e21ce6adfb3ddc0b59fb1cb09ec7dc636c5b36f
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Runner/Hook/AfterTestErrorHook.php
@@ -0,0 +1,18 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Runner;
+
+/**
+ * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+ */
+interface AfterTestErrorHook extends TestHook
+{
+    public function executeAfterTestError(string $test, string $message, float $time): void;
+}
diff --git a/vendor/phpunit/phpunit/src/Runner/Hook/AfterTestFailureHook.php b/vendor/phpunit/phpunit/src/Runner/Hook/AfterTestFailureHook.php
new file mode 100644
index 0000000000000000000000000000000000000000..011cca426341a8a76e798b1be953474bb04fe241
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Runner/Hook/AfterTestFailureHook.php
@@ -0,0 +1,18 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Runner;
+
+/**
+ * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+ */
+interface AfterTestFailureHook extends TestHook
+{
+    public function executeAfterTestFailure(string $test, string $message, float $time): void;
+}
diff --git a/vendor/phpunit/phpunit/src/Runner/Hook/AfterTestHook.php b/vendor/phpunit/phpunit/src/Runner/Hook/AfterTestHook.php
new file mode 100644
index 0000000000000000000000000000000000000000..451510ecf120b93281a5b869c31e771fd3ad1955
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Runner/Hook/AfterTestHook.php
@@ -0,0 +1,24 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Runner;
+
+/**
+ * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+ */
+interface AfterTestHook extends TestHook
+{
+    /**
+     * This hook will fire after any test, regardless of the result.
+     *
+     * For more fine grained control, have a look at the other hooks
+     * that extend PHPUnit\Runner\Hook.
+     */
+    public function executeAfterTest(string $test, float $time): void;
+}
diff --git a/vendor/phpunit/phpunit/src/Runner/Hook/AfterTestWarningHook.php b/vendor/phpunit/phpunit/src/Runner/Hook/AfterTestWarningHook.php
new file mode 100644
index 0000000000000000000000000000000000000000..0b782939d4e5f4fa65c052946bab5d3e1f25b0d3
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Runner/Hook/AfterTestWarningHook.php
@@ -0,0 +1,18 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Runner;
+
+/**
+ * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+ */
+interface AfterTestWarningHook extends TestHook
+{
+    public function executeAfterTestWarning(string $test, string $message, float $time): void;
+}
diff --git a/vendor/phpunit/phpunit/src/Runner/Hook/BeforeFirstTestHook.php b/vendor/phpunit/phpunit/src/Runner/Hook/BeforeFirstTestHook.php
new file mode 100644
index 0000000000000000000000000000000000000000..b4ffdbd05f38229a8f338a8e303e77a51efd762e
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Runner/Hook/BeforeFirstTestHook.php
@@ -0,0 +1,18 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Runner;
+
+/**
+ * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+ */
+interface BeforeFirstTestHook extends Hook
+{
+    public function executeBeforeFirstTest(): void;
+}
diff --git a/vendor/phpunit/phpunit/src/Runner/Hook/BeforeTestHook.php b/vendor/phpunit/phpunit/src/Runner/Hook/BeforeTestHook.php
new file mode 100644
index 0000000000000000000000000000000000000000..381a6558f21446a7968dd2e05de50e76504a4f4d
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Runner/Hook/BeforeTestHook.php
@@ -0,0 +1,18 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Runner;
+
+/**
+ * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+ */
+interface BeforeTestHook extends TestHook
+{
+    public function executeBeforeTest(string $test): void;
+}
diff --git a/vendor/phpunit/phpunit/src/Runner/Hook/Hook.php b/vendor/phpunit/phpunit/src/Runner/Hook/Hook.php
new file mode 100644
index 0000000000000000000000000000000000000000..9a957ce63d0e5a373219b227dea73ee7e3c65892
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Runner/Hook/Hook.php
@@ -0,0 +1,17 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Runner;
+
+/**
+ * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+ */
+interface Hook
+{
+}
diff --git a/vendor/phpunit/phpunit/src/Runner/Hook/TestHook.php b/vendor/phpunit/phpunit/src/Runner/Hook/TestHook.php
new file mode 100644
index 0000000000000000000000000000000000000000..f3387b4c8a88dbff51a4f88faab0f13fada55dc1
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Runner/Hook/TestHook.php
@@ -0,0 +1,17 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Runner;
+
+/**
+ * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+ */
+interface TestHook extends Hook
+{
+}
diff --git a/vendor/phpunit/phpunit/src/Runner/Hook/TestListenerAdapter.php b/vendor/phpunit/phpunit/src/Runner/Hook/TestListenerAdapter.php
new file mode 100644
index 0000000000000000000000000000000000000000..60fbfba3187f61c9dd8467c2258a04faa9596de6
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Runner/Hook/TestListenerAdapter.php
@@ -0,0 +1,141 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Runner;
+
+use PHPUnit\Framework\AssertionFailedError;
+use PHPUnit\Framework\Test;
+use PHPUnit\Framework\TestListener;
+use PHPUnit\Framework\TestSuite;
+use PHPUnit\Framework\Warning;
+use PHPUnit\Util\Test as TestUtil;
+use Throwable;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class TestListenerAdapter implements TestListener
+{
+    /**
+     * @var TestHook[]
+     */
+    private $hooks = [];
+
+    /**
+     * @var bool
+     */
+    private $lastTestWasNotSuccessful;
+
+    public function add(TestHook $hook): void
+    {
+        $this->hooks[] = $hook;
+    }
+
+    public function startTest(Test $test): void
+    {
+        foreach ($this->hooks as $hook) {
+            if ($hook instanceof BeforeTestHook) {
+                $hook->executeBeforeTest(TestUtil::describeAsString($test));
+            }
+        }
+
+        $this->lastTestWasNotSuccessful = false;
+    }
+
+    public function addError(Test $test, Throwable $t, float $time): void
+    {
+        foreach ($this->hooks as $hook) {
+            if ($hook instanceof AfterTestErrorHook) {
+                $hook->executeAfterTestError(TestUtil::describeAsString($test), $t->getMessage(), $time);
+            }
+        }
+
+        $this->lastTestWasNotSuccessful = true;
+    }
+
+    public function addWarning(Test $test, Warning $e, float $time): void
+    {
+        foreach ($this->hooks as $hook) {
+            if ($hook instanceof AfterTestWarningHook) {
+                $hook->executeAfterTestWarning(TestUtil::describeAsString($test), $e->getMessage(), $time);
+            }
+        }
+
+        $this->lastTestWasNotSuccessful = true;
+    }
+
+    public function addFailure(Test $test, AssertionFailedError $e, float $time): void
+    {
+        foreach ($this->hooks as $hook) {
+            if ($hook instanceof AfterTestFailureHook) {
+                $hook->executeAfterTestFailure(TestUtil::describeAsString($test), $e->getMessage(), $time);
+            }
+        }
+
+        $this->lastTestWasNotSuccessful = true;
+    }
+
+    public function addIncompleteTest(Test $test, Throwable $t, float $time): void
+    {
+        foreach ($this->hooks as $hook) {
+            if ($hook instanceof AfterIncompleteTestHook) {
+                $hook->executeAfterIncompleteTest(TestUtil::describeAsString($test), $t->getMessage(), $time);
+            }
+        }
+
+        $this->lastTestWasNotSuccessful = true;
+    }
+
+    public function addRiskyTest(Test $test, Throwable $t, float $time): void
+    {
+        foreach ($this->hooks as $hook) {
+            if ($hook instanceof AfterRiskyTestHook) {
+                $hook->executeAfterRiskyTest(TestUtil::describeAsString($test), $t->getMessage(), $time);
+            }
+        }
+
+        $this->lastTestWasNotSuccessful = true;
+    }
+
+    public function addSkippedTest(Test $test, Throwable $t, float $time): void
+    {
+        foreach ($this->hooks as $hook) {
+            if ($hook instanceof AfterSkippedTestHook) {
+                $hook->executeAfterSkippedTest(TestUtil::describeAsString($test), $t->getMessage(), $time);
+            }
+        }
+
+        $this->lastTestWasNotSuccessful = true;
+    }
+
+    public function endTest(Test $test, float $time): void
+    {
+        if (!$this->lastTestWasNotSuccessful) {
+            foreach ($this->hooks as $hook) {
+                if ($hook instanceof AfterSuccessfulTestHook) {
+                    $hook->executeAfterSuccessfulTest(TestUtil::describeAsString($test), $time);
+                }
+            }
+        }
+
+        foreach ($this->hooks as $hook) {
+            if ($hook instanceof AfterTestHook) {
+                $hook->executeAfterTest(TestUtil::describeAsString($test), $time);
+            }
+        }
+    }
+
+    public function startTestSuite(TestSuite $suite): void
+    {
+    }
+
+    public function endTestSuite(TestSuite $suite): void
+    {
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Runner/NullTestResultCache.php b/vendor/phpunit/phpunit/src/Runner/NullTestResultCache.php
new file mode 100644
index 0000000000000000000000000000000000000000..2aa86534a9c1113de918efcc35bb11317d7a8477
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Runner/NullTestResultCache.php
@@ -0,0 +1,42 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Runner;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class NullTestResultCache implements TestResultCache
+{
+    public function setState(string $testName, int $state): void
+    {
+    }
+
+    public function getState(string $testName): int
+    {
+        return BaseTestRunner::STATUS_UNKNOWN;
+    }
+
+    public function setTime(string $testName, float $time): void
+    {
+    }
+
+    public function getTime(string $testName): float
+    {
+        return 0;
+    }
+
+    public function load(): void
+    {
+    }
+
+    public function persist(): void
+    {
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Runner/PhptTestCase.php b/vendor/phpunit/phpunit/src/Runner/PhptTestCase.php
new file mode 100644
index 0000000000000000000000000000000000000000..bdd3e97db505215c97171a270844c701fc802d86
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Runner/PhptTestCase.php
@@ -0,0 +1,864 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Runner;
+
+use const DEBUG_BACKTRACE_IGNORE_ARGS;
+use const DIRECTORY_SEPARATOR;
+use function array_merge;
+use function basename;
+use function debug_backtrace;
+use function defined;
+use function dirname;
+use function explode;
+use function extension_loaded;
+use function file;
+use function file_get_contents;
+use function file_put_contents;
+use function is_array;
+use function is_file;
+use function is_readable;
+use function is_string;
+use function ltrim;
+use function phpversion;
+use function preg_match;
+use function preg_replace;
+use function preg_split;
+use function realpath;
+use function rtrim;
+use function sprintf;
+use function str_replace;
+use function strncasecmp;
+use function strpos;
+use function substr;
+use function trim;
+use function unlink;
+use function unserialize;
+use function var_export;
+use function version_compare;
+use PHPUnit\Framework\Assert;
+use PHPUnit\Framework\AssertionFailedError;
+use PHPUnit\Framework\ExecutionOrderDependency;
+use PHPUnit\Framework\ExpectationFailedException;
+use PHPUnit\Framework\IncompleteTestError;
+use PHPUnit\Framework\PHPTAssertionFailedError;
+use PHPUnit\Framework\Reorderable;
+use PHPUnit\Framework\SelfDescribing;
+use PHPUnit\Framework\SkippedTestError;
+use PHPUnit\Framework\SyntheticSkippedError;
+use PHPUnit\Framework\Test;
+use PHPUnit\Framework\TestResult;
+use PHPUnit\Util\PHP\AbstractPhpProcess;
+use SebastianBergmann\CodeCoverage\RawCodeCoverageData;
+use SebastianBergmann\Template\Template;
+use SebastianBergmann\Timer\Timer;
+use Throwable;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class PhptTestCase implements Reorderable, SelfDescribing, Test
+{
+    /**
+     * @var string
+     */
+    private $filename;
+
+    /**
+     * @var AbstractPhpProcess
+     */
+    private $phpUtil;
+
+    /**
+     * @var string
+     */
+    private $output = '';
+
+    /**
+     * Constructs a test case with the given filename.
+     *
+     * @throws Exception
+     */
+    public function __construct(string $filename, AbstractPhpProcess $phpUtil = null)
+    {
+        if (!is_file($filename)) {
+            throw new Exception(
+                sprintf(
+                    'File "%s" does not exist.',
+                    $filename
+                )
+            );
+        }
+
+        $this->filename = $filename;
+        $this->phpUtil  = $phpUtil ?: AbstractPhpProcess::factory();
+    }
+
+    /**
+     * Counts the number of test cases executed by run(TestResult result).
+     */
+    public function count(): int
+    {
+        return 1;
+    }
+
+    /**
+     * Runs a test and collects its result in a TestResult instance.
+     *
+     * @throws \SebastianBergmann\CodeCoverage\InvalidArgumentException
+     * @throws \SebastianBergmann\CodeCoverage\UnintentionallyCoveredCodeException
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws Exception
+     */
+    public function run(TestResult $result = null): TestResult
+    {
+        if ($result === null) {
+            $result = new TestResult;
+        }
+
+        try {
+            $sections = $this->parse();
+        } catch (Exception $e) {
+            $result->startTest($this);
+            $result->addFailure($this, new SkippedTestError($e->getMessage()), 0);
+            $result->endTest($this, 0);
+
+            return $result;
+        }
+
+        $code     = $this->render($sections['FILE']);
+        $xfail    = false;
+        $settings = $this->parseIniSection($this->settings($result->getCollectCodeCoverageInformation()));
+
+        $result->startTest($this);
+
+        if (isset($sections['INI'])) {
+            $settings = $this->parseIniSection($sections['INI'], $settings);
+        }
+
+        if (isset($sections['ENV'])) {
+            $env = $this->parseEnvSection($sections['ENV']);
+            $this->phpUtil->setEnv($env);
+        }
+
+        $this->phpUtil->setUseStderrRedirection(true);
+
+        if ($result->enforcesTimeLimit()) {
+            $this->phpUtil->setTimeout($result->getTimeoutForLargeTests());
+        }
+
+        $skip = $this->runSkip($sections, $result, $settings);
+
+        if ($skip) {
+            return $result;
+        }
+
+        if (isset($sections['XFAIL'])) {
+            $xfail = trim($sections['XFAIL']);
+        }
+
+        if (isset($sections['STDIN'])) {
+            $this->phpUtil->setStdin($sections['STDIN']);
+        }
+
+        if (isset($sections['ARGS'])) {
+            $this->phpUtil->setArgs($sections['ARGS']);
+        }
+
+        if ($result->getCollectCodeCoverageInformation()) {
+            $codeCoverageCacheDirectory = null;
+            $pathCoverage               = false;
+
+            $codeCoverage = $result->getCodeCoverage();
+
+            if ($codeCoverage) {
+                if ($codeCoverage->cachesStaticAnalysis()) {
+                    $codeCoverageCacheDirectory = $codeCoverage->cacheDirectory();
+                }
+
+                $pathCoverage = $codeCoverage->collectsBranchAndPathCoverage();
+            }
+
+            $this->renderForCoverage($code, $pathCoverage, $codeCoverageCacheDirectory);
+        }
+
+        $timer = new Timer;
+        $timer->start();
+
+        $jobResult    = $this->phpUtil->runJob($code, $this->stringifyIni($settings));
+        $time         = $timer->stop()->asSeconds();
+        $this->output = $jobResult['stdout'] ?? '';
+
+        if (isset($codeCoverage) && ($coverage = $this->cleanupForCoverage())) {
+            $codeCoverage->append($coverage, $this, true, [], []);
+        }
+
+        try {
+            $this->assertPhptExpectation($sections, $this->output);
+        } catch (AssertionFailedError $e) {
+            $failure = $e;
+
+            if ($xfail !== false) {
+                $failure = new IncompleteTestError($xfail, 0, $e);
+            } elseif ($e instanceof ExpectationFailedException) {
+                $comparisonFailure = $e->getComparisonFailure();
+
+                if ($comparisonFailure) {
+                    $diff = $comparisonFailure->getDiff();
+                } else {
+                    $diff = $e->getMessage();
+                }
+
+                $hint    = $this->getLocationHintFromDiff($diff, $sections);
+                $trace   = array_merge($hint, debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS));
+                $failure = new PHPTAssertionFailedError(
+                    $e->getMessage(),
+                    0,
+                    $trace[0]['file'],
+                    $trace[0]['line'],
+                    $trace,
+                    $comparisonFailure ? $diff : ''
+                );
+            }
+
+            $result->addFailure($this, $failure, $time);
+        } catch (Throwable $t) {
+            $result->addError($this, $t, $time);
+        }
+
+        if ($xfail !== false && $result->allCompletelyImplemented()) {
+            $result->addFailure($this, new IncompleteTestError('XFAIL section but test passes'), $time);
+        }
+
+        $this->runClean($sections, $result->getCollectCodeCoverageInformation());
+
+        $result->endTest($this, $time);
+
+        return $result;
+    }
+
+    /**
+     * Returns the name of the test case.
+     */
+    public function getName(): string
+    {
+        return $this->toString();
+    }
+
+    /**
+     * Returns a string representation of the test case.
+     */
+    public function toString(): string
+    {
+        return $this->filename;
+    }
+
+    public function usesDataProvider(): bool
+    {
+        return false;
+    }
+
+    public function getNumAssertions(): int
+    {
+        return 1;
+    }
+
+    public function getActualOutput(): string
+    {
+        return $this->output;
+    }
+
+    public function hasOutput(): bool
+    {
+        return !empty($this->output);
+    }
+
+    public function sortId(): string
+    {
+        return $this->filename;
+    }
+
+    /**
+     * @return list<ExecutionOrderDependency>
+     */
+    public function provides(): array
+    {
+        return [];
+    }
+
+    /**
+     * @return list<ExecutionOrderDependency>
+     */
+    public function requires(): array
+    {
+        return [];
+    }
+
+    /**
+     * Parse --INI-- section key value pairs and return as array.
+     *
+     * @param array|string $content
+     */
+    private function parseIniSection($content, array $ini = []): array
+    {
+        if (is_string($content)) {
+            $content = explode("\n", trim($content));
+        }
+
+        foreach ($content as $setting) {
+            if (strpos($setting, '=') === false) {
+                continue;
+            }
+
+            $setting = explode('=', $setting, 2);
+            $name    = trim($setting[0]);
+            $value   = trim($setting[1]);
+
+            if ($name === 'extension' || $name === 'zend_extension') {
+                if (!isset($ini[$name])) {
+                    $ini[$name] = [];
+                }
+
+                $ini[$name][] = $value;
+
+                continue;
+            }
+
+            $ini[$name] = $value;
+        }
+
+        return $ini;
+    }
+
+    private function parseEnvSection(string $content): array
+    {
+        $env = [];
+
+        foreach (explode("\n", trim($content)) as $e) {
+            $e = explode('=', trim($e), 2);
+
+            if (!empty($e[0]) && isset($e[1])) {
+                $env[$e[0]] = $e[1];
+            }
+        }
+
+        return $env;
+    }
+
+    /**
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws Exception
+     * @throws ExpectationFailedException
+     */
+    private function assertPhptExpectation(array $sections, string $output): void
+    {
+        $assertions = [
+            'EXPECT'      => 'assertEquals',
+            'EXPECTF'     => 'assertStringMatchesFormat',
+            'EXPECTREGEX' => 'assertMatchesRegularExpression',
+        ];
+
+        $actual = preg_replace('/\r\n/', "\n", trim($output));
+
+        foreach ($assertions as $sectionName => $sectionAssertion) {
+            if (isset($sections[$sectionName])) {
+                $sectionContent = preg_replace('/\r\n/', "\n", trim($sections[$sectionName]));
+                $expected       = $sectionName === 'EXPECTREGEX' ? "/{$sectionContent}/" : $sectionContent;
+
+                if ($expected === '') {
+                    throw new Exception('No PHPT expectation found');
+                }
+
+                Assert::$sectionAssertion($expected, $actual);
+
+                return;
+            }
+        }
+
+        throw new Exception('No PHPT assertion found');
+    }
+
+    /**
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     */
+    private function runSkip(array &$sections, TestResult $result, array $settings): bool
+    {
+        if (!isset($sections['SKIPIF'])) {
+            return false;
+        }
+
+        $skipif    = $this->render($sections['SKIPIF']);
+        $jobResult = $this->phpUtil->runJob($skipif, $this->stringifyIni($settings));
+
+        if (!strncasecmp('skip', ltrim($jobResult['stdout']), 4)) {
+            $message = '';
+
+            if (preg_match('/^\s*skip\s*(.+)\s*/i', $jobResult['stdout'], $skipMatch)) {
+                $message = substr($skipMatch[1], 2);
+            }
+
+            $hint  = $this->getLocationHint($message, $sections, 'SKIPIF');
+            $trace = array_merge($hint, debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS));
+            $result->addFailure(
+                $this,
+                new SyntheticSkippedError($message, 0, $trace[0]['file'], $trace[0]['line'], $trace),
+                0
+            );
+            $result->endTest($this, 0);
+
+            return true;
+        }
+
+        return false;
+    }
+
+    private function runClean(array &$sections, bool $collectCoverage): void
+    {
+        $this->phpUtil->setStdin('');
+        $this->phpUtil->setArgs('');
+
+        if (isset($sections['CLEAN'])) {
+            $cleanCode = $this->render($sections['CLEAN']);
+
+            $this->phpUtil->runJob($cleanCode, $this->settings($collectCoverage));
+        }
+    }
+
+    /**
+     * @throws Exception
+     */
+    private function parse(): array
+    {
+        $sections = [];
+        $section  = '';
+
+        $unsupportedSections = [
+            'CGI',
+            'COOKIE',
+            'DEFLATE_POST',
+            'EXPECTHEADERS',
+            'EXTENSIONS',
+            'GET',
+            'GZIP_POST',
+            'HEADERS',
+            'PHPDBG',
+            'POST',
+            'POST_RAW',
+            'PUT',
+            'REDIRECTTEST',
+            'REQUEST',
+        ];
+
+        $lineNr = 0;
+
+        foreach (file($this->filename) as $line) {
+            $lineNr++;
+
+            if (preg_match('/^--([_A-Z]+)--/', $line, $result)) {
+                $section                        = $result[1];
+                $sections[$section]             = '';
+                $sections[$section . '_offset'] = $lineNr;
+
+                continue;
+            }
+
+            if (empty($section)) {
+                throw new Exception('Invalid PHPT file: empty section header');
+            }
+
+            $sections[$section] .= $line;
+        }
+
+        if (isset($sections['FILEEOF'])) {
+            $sections['FILE'] = rtrim($sections['FILEEOF'], "\r\n");
+            unset($sections['FILEEOF']);
+        }
+
+        $this->parseExternal($sections);
+
+        if (!$this->validate($sections)) {
+            throw new Exception('Invalid PHPT file');
+        }
+
+        foreach ($unsupportedSections as $section) {
+            if (isset($sections[$section])) {
+                throw new Exception(
+                    "PHPUnit does not support PHPT {$section} sections"
+                );
+            }
+        }
+
+        return $sections;
+    }
+
+    /**
+     * @throws Exception
+     */
+    private function parseExternal(array &$sections): void
+    {
+        $allowSections = [
+            'FILE',
+            'EXPECT',
+            'EXPECTF',
+            'EXPECTREGEX',
+        ];
+        $testDirectory = dirname($this->filename) . DIRECTORY_SEPARATOR;
+
+        foreach ($allowSections as $section) {
+            if (isset($sections[$section . '_EXTERNAL'])) {
+                $externalFilename = trim($sections[$section . '_EXTERNAL']);
+
+                if (!is_file($testDirectory . $externalFilename) ||
+                    !is_readable($testDirectory . $externalFilename)) {
+                    throw new Exception(
+                        sprintf(
+                            'Could not load --%s-- %s for PHPT file',
+                            $section . '_EXTERNAL',
+                            $testDirectory . $externalFilename
+                        )
+                    );
+                }
+
+                $sections[$section] = file_get_contents($testDirectory . $externalFilename);
+            }
+        }
+    }
+
+    private function validate(array &$sections): bool
+    {
+        $requiredSections = [
+            'FILE',
+            [
+                'EXPECT',
+                'EXPECTF',
+                'EXPECTREGEX',
+            ],
+        ];
+
+        foreach ($requiredSections as $section) {
+            if (is_array($section)) {
+                $foundSection = false;
+
+                foreach ($section as $anySection) {
+                    if (isset($sections[$anySection])) {
+                        $foundSection = true;
+
+                        break;
+                    }
+                }
+
+                if (!$foundSection) {
+                    return false;
+                }
+
+                continue;
+            }
+
+            if (!isset($sections[$section])) {
+                return false;
+            }
+        }
+
+        return true;
+    }
+
+    private function render(string $code): string
+    {
+        return str_replace(
+            [
+                '__DIR__',
+                '__FILE__',
+            ],
+            [
+                "'" . dirname($this->filename) . "'",
+                "'" . $this->filename . "'",
+            ],
+            $code
+        );
+    }
+
+    private function getCoverageFiles(): array
+    {
+        $baseDir  = dirname(realpath($this->filename)) . DIRECTORY_SEPARATOR;
+        $basename = basename($this->filename, 'phpt');
+
+        return [
+            'coverage' => $baseDir . $basename . 'coverage',
+            'job'      => $baseDir . $basename . 'php',
+        ];
+    }
+
+    private function renderForCoverage(string &$job, bool $pathCoverage, ?string $codeCoverageCacheDirectory): void
+    {
+        $files = $this->getCoverageFiles();
+
+        $template = new Template(
+            __DIR__ . '/../Util/PHP/Template/PhptTestCase.tpl'
+        );
+
+        $composerAutoload = '\'\'';
+
+        if (defined('PHPUNIT_COMPOSER_INSTALL') && !defined('PHPUNIT_TESTSUITE')) {
+            $composerAutoload = var_export(PHPUNIT_COMPOSER_INSTALL, true);
+        }
+
+        $phar = '\'\'';
+
+        if (defined('__PHPUNIT_PHAR__')) {
+            $phar = var_export(__PHPUNIT_PHAR__, true);
+        }
+
+        $globals = '';
+
+        if (!empty($GLOBALS['__PHPUNIT_BOOTSTRAP'])) {
+            $globals = '$GLOBALS[\'__PHPUNIT_BOOTSTRAP\'] = ' . var_export(
+                $GLOBALS['__PHPUNIT_BOOTSTRAP'],
+                true
+            ) . ";\n";
+        }
+
+        if ($codeCoverageCacheDirectory === null) {
+            $codeCoverageCacheDirectory = 'null';
+        } else {
+            $codeCoverageCacheDirectory = "'" . $codeCoverageCacheDirectory . "'";
+        }
+
+        $template->setVar(
+            [
+                'composerAutoload'           => $composerAutoload,
+                'phar'                       => $phar,
+                'globals'                    => $globals,
+                'job'                        => $files['job'],
+                'coverageFile'               => $files['coverage'],
+                'driverMethod'               => $pathCoverage ? 'forLineAndPathCoverage' : 'forLineCoverage',
+                'codeCoverageCacheDirectory' => $codeCoverageCacheDirectory,
+            ]
+        );
+
+        file_put_contents($files['job'], $job);
+
+        $job = $template->render();
+    }
+
+    private function cleanupForCoverage(): RawCodeCoverageData
+    {
+        $coverage = RawCodeCoverageData::fromXdebugWithoutPathCoverage([]);
+        $files    = $this->getCoverageFiles();
+
+        if (is_file($files['coverage'])) {
+            $buffer = @file_get_contents($files['coverage']);
+
+            if ($buffer !== false) {
+                $coverage = @unserialize($buffer);
+
+                if ($coverage === false) {
+                    $coverage = RawCodeCoverageData::fromXdebugWithoutPathCoverage([]);
+                }
+            }
+        }
+
+        foreach ($files as $file) {
+            @unlink($file);
+        }
+
+        return $coverage;
+    }
+
+    private function stringifyIni(array $ini): array
+    {
+        $settings = [];
+
+        foreach ($ini as $key => $value) {
+            if (is_array($value)) {
+                foreach ($value as $val) {
+                    $settings[] = $key . '=' . $val;
+                }
+
+                continue;
+            }
+
+            $settings[] = $key . '=' . $value;
+        }
+
+        return $settings;
+    }
+
+    private function getLocationHintFromDiff(string $message, array $sections): array
+    {
+        $needle       = '';
+        $previousLine = '';
+        $block        = 'message';
+
+        foreach (preg_split('/\r\n|\r|\n/', $message) as $line) {
+            $line = trim($line);
+
+            if ($block === 'message' && $line === '--- Expected') {
+                $block = 'expected';
+            }
+
+            if ($block === 'expected' && $line === '@@ @@') {
+                $block = 'diff';
+            }
+
+            if ($block === 'diff') {
+                if (strpos($line, '+') === 0) {
+                    $needle = $this->getCleanDiffLine($previousLine);
+
+                    break;
+                }
+
+                if (strpos($line, '-') === 0) {
+                    $needle = $this->getCleanDiffLine($line);
+
+                    break;
+                }
+            }
+
+            if (!empty($line)) {
+                $previousLine = $line;
+            }
+        }
+
+        return $this->getLocationHint($needle, $sections);
+    }
+
+    private function getCleanDiffLine(string $line): string
+    {
+        if (preg_match('/^[\-+]([\'\"]?)(.*)\1$/', $line, $matches)) {
+            $line = $matches[2];
+        }
+
+        return $line;
+    }
+
+    private function getLocationHint(string $needle, array $sections, ?string $sectionName = null): array
+    {
+        $needle = trim($needle);
+
+        if (empty($needle)) {
+            return [[
+                'file' => realpath($this->filename),
+                'line' => 1,
+            ]];
+        }
+
+        if ($sectionName) {
+            $search = [$sectionName];
+        } else {
+            $search = [
+                // 'FILE',
+                'EXPECT',
+                'EXPECTF',
+                'EXPECTREGEX',
+            ];
+        }
+
+        $sectionOffset = null;
+
+        foreach ($search as $section) {
+            if (!isset($sections[$section])) {
+                continue;
+            }
+
+            if (isset($sections[$section . '_EXTERNAL'])) {
+                $externalFile = trim($sections[$section . '_EXTERNAL']);
+
+                return [
+                    [
+                        'file' => realpath(dirname($this->filename) . DIRECTORY_SEPARATOR . $externalFile),
+                        'line' => 1,
+                    ],
+                    [
+                        'file' => realpath($this->filename),
+                        'line' => ($sections[$section . '_EXTERNAL_offset'] ?? 0) + 1,
+                    ],
+                ];
+            }
+
+            $sectionOffset = $sections[$section . '_offset'] ?? 0;
+            $offset        = $sectionOffset + 1;
+
+            foreach (preg_split('/\r\n|\r|\n/', $sections[$section]) as $line) {
+                if (strpos($line, $needle) !== false) {
+                    return [[
+                        'file' => realpath($this->filename),
+                        'line' => $offset,
+                    ]];
+                }
+                $offset++;
+            }
+        }
+
+        if ($sectionName) {
+            // String not found in specified section, show user the start of the named section
+            return [[
+                'file' => realpath($this->filename),
+                'line' => $sectionOffset,
+            ]];
+        }
+
+        // No section specified, show user start of code
+        return [[
+            'file' => realpath($this->filename),
+            'line' => 1,
+        ]];
+    }
+
+    /**
+     * @psalm-return list<string>
+     */
+    private function settings(bool $collectCoverage): array
+    {
+        $settings = [
+            'allow_url_fopen=1',
+            'auto_append_file=',
+            'auto_prepend_file=',
+            'disable_functions=',
+            'display_errors=1',
+            'docref_ext=.html',
+            'docref_root=',
+            'error_append_string=',
+            'error_prepend_string=',
+            'error_reporting=-1',
+            'html_errors=0',
+            'log_errors=0',
+            'open_basedir=',
+            'output_buffering=Off',
+            'output_handler=',
+            'report_memleaks=0',
+            'report_zend_debug=0',
+        ];
+
+        if (extension_loaded('pcov')) {
+            if ($collectCoverage) {
+                $settings[] = 'pcov.enabled=1';
+            } else {
+                $settings[] = 'pcov.enabled=0';
+            }
+        }
+
+        if (extension_loaded('xdebug')) {
+            if (version_compare(phpversion('xdebug'), '3', '>=')) {
+                if ($collectCoverage) {
+                    $settings[] = 'xdebug.mode=coverage';
+                } else {
+                    $settings[] = 'xdebug.mode=off';
+                }
+            } else {
+                $settings[] = 'xdebug.default_enable=0';
+
+                if ($collectCoverage) {
+                    $settings[] = 'xdebug.coverage_enable=1';
+                }
+            }
+        }
+
+        return $settings;
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Runner/ResultCacheExtension.php b/vendor/phpunit/phpunit/src/Runner/ResultCacheExtension.php
new file mode 100644
index 0000000000000000000000000000000000000000..31d7610e2bc6bad3a2723097db126aedb12a2cec
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Runner/ResultCacheExtension.php
@@ -0,0 +1,110 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Runner;
+
+use function preg_match;
+use function round;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class ResultCacheExtension implements AfterIncompleteTestHook, AfterLastTestHook, AfterRiskyTestHook, AfterSkippedTestHook, AfterSuccessfulTestHook, AfterTestErrorHook, AfterTestFailureHook, AfterTestWarningHook
+{
+    /**
+     * @var TestResultCache
+     */
+    private $cache;
+
+    public function __construct(TestResultCache $cache)
+    {
+        $this->cache = $cache;
+    }
+
+    public function flush(): void
+    {
+        $this->cache->persist();
+    }
+
+    public function executeAfterSuccessfulTest(string $test, float $time): void
+    {
+        $testName = $this->getTestName($test);
+
+        $this->cache->setTime($testName, round($time, 3));
+    }
+
+    public function executeAfterIncompleteTest(string $test, string $message, float $time): void
+    {
+        $testName = $this->getTestName($test);
+
+        $this->cache->setTime($testName, round($time, 3));
+        $this->cache->setState($testName, BaseTestRunner::STATUS_INCOMPLETE);
+    }
+
+    public function executeAfterRiskyTest(string $test, string $message, float $time): void
+    {
+        $testName = $this->getTestName($test);
+
+        $this->cache->setTime($testName, round($time, 3));
+        $this->cache->setState($testName, BaseTestRunner::STATUS_RISKY);
+    }
+
+    public function executeAfterSkippedTest(string $test, string $message, float $time): void
+    {
+        $testName = $this->getTestName($test);
+
+        $this->cache->setTime($testName, round($time, 3));
+        $this->cache->setState($testName, BaseTestRunner::STATUS_SKIPPED);
+    }
+
+    public function executeAfterTestError(string $test, string $message, float $time): void
+    {
+        $testName = $this->getTestName($test);
+
+        $this->cache->setTime($testName, round($time, 3));
+        $this->cache->setState($testName, BaseTestRunner::STATUS_ERROR);
+    }
+
+    public function executeAfterTestFailure(string $test, string $message, float $time): void
+    {
+        $testName = $this->getTestName($test);
+
+        $this->cache->setTime($testName, round($time, 3));
+        $this->cache->setState($testName, BaseTestRunner::STATUS_FAILURE);
+    }
+
+    public function executeAfterTestWarning(string $test, string $message, float $time): void
+    {
+        $testName = $this->getTestName($test);
+
+        $this->cache->setTime($testName, round($time, 3));
+        $this->cache->setState($testName, BaseTestRunner::STATUS_WARNING);
+    }
+
+    public function executeAfterLastTest(): void
+    {
+        $this->flush();
+    }
+
+    /**
+     * @param string $test A long description format of the current test
+     *
+     * @return string The test name without TestSuiteClassName:: and @dataprovider details
+     */
+    private function getTestName(string $test): string
+    {
+        $matches = [];
+
+        if (preg_match('/^(?<name>\S+::\S+)(?:(?<dataname> with data set (?:#\d+|"[^"]+"))\s\()?/', $test, $matches)) {
+            $test = $matches['name'] . ($matches['dataname'] ?? '');
+        }
+
+        return $test;
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Runner/StandardTestSuiteLoader.php b/vendor/phpunit/phpunit/src/Runner/StandardTestSuiteLoader.php
new file mode 100644
index 0000000000000000000000000000000000000000..f6de4e9370b70b249c3756a9a1df2a6f06bc08b2
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Runner/StandardTestSuiteLoader.php
@@ -0,0 +1,123 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Runner;
+
+use function array_diff;
+use function array_values;
+use function basename;
+use function class_exists;
+use function get_declared_classes;
+use function sprintf;
+use function stripos;
+use function strlen;
+use function substr;
+use PHPUnit\Framework\TestCase;
+use PHPUnit\Util\FileLoader;
+use ReflectionClass;
+use ReflectionException;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ *
+ * @deprecated see https://github.com/sebastianbergmann/phpunit/issues/4039
+ */
+final class StandardTestSuiteLoader implements TestSuiteLoader
+{
+    /**
+     * @throws Exception
+     */
+    public function load(string $suiteClassFile): ReflectionClass
+    {
+        $suiteClassName = basename($suiteClassFile, '.php');
+        $loadedClasses  = get_declared_classes();
+
+        if (!class_exists($suiteClassName, false)) {
+            /* @noinspection UnusedFunctionResultInspection */
+            FileLoader::checkAndLoad($suiteClassFile);
+
+            $loadedClasses = array_values(
+                array_diff(get_declared_classes(), $loadedClasses)
+            );
+
+            if (empty($loadedClasses)) {
+                throw $this->exceptionFor($suiteClassName, $suiteClassFile);
+            }
+        }
+
+        if (!class_exists($suiteClassName, false)) {
+            // this block will handle namespaced classes
+            $offset = 0 - strlen($suiteClassName);
+
+            foreach ($loadedClasses as $loadedClass) {
+                if (stripos(substr($loadedClass, $offset - 1), '\\' . $suiteClassName) === 0) {
+                    $suiteClassName = $loadedClass;
+
+                    break;
+                }
+            }
+        }
+
+        if (!class_exists($suiteClassName, false)) {
+            throw $this->exceptionFor($suiteClassName, $suiteClassFile);
+        }
+
+        try {
+            $class = new ReflectionClass($suiteClassName);
+            // @codeCoverageIgnoreStart
+        } catch (ReflectionException $e) {
+            throw new Exception(
+                $e->getMessage(),
+                (int) $e->getCode(),
+                $e
+            );
+        }
+        // @codeCoverageIgnoreEnd
+
+        if ($class->isSubclassOf(TestCase::class) && !$class->isAbstract()) {
+            return $class;
+        }
+
+        if ($class->hasMethod('suite')) {
+            try {
+                $method = $class->getMethod('suite');
+                // @codeCoverageIgnoreStart
+            } catch (ReflectionException $e) {
+                throw new Exception(
+                    $e->getMessage(),
+                    (int) $e->getCode(),
+                    $e
+                );
+            }
+            // @codeCoverageIgnoreEnd
+
+            if (!$method->isAbstract() && $method->isPublic() && $method->isStatic()) {
+                return $class;
+            }
+        }
+
+        throw $this->exceptionFor($suiteClassName, $suiteClassFile);
+    }
+
+    public function reload(ReflectionClass $aClass): ReflectionClass
+    {
+        return $aClass;
+    }
+
+    private function exceptionFor(string $className, string $filename): Exception
+    {
+        return new Exception(
+            sprintf(
+                "Class '%s' could not be found in '%s'.",
+                $className,
+                $filename
+            )
+        );
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Runner/TestResultCache.php b/vendor/phpunit/phpunit/src/Runner/TestResultCache.php
new file mode 100644
index 0000000000000000000000000000000000000000..69e62828911b83e8b2221d43fc12609032e65782
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Runner/TestResultCache.php
@@ -0,0 +1,28 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Runner;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+interface TestResultCache
+{
+    public function setState(string $testName, int $state): void;
+
+    public function getState(string $testName): int;
+
+    public function setTime(string $testName, float $time): void;
+
+    public function getTime(string $testName): float;
+
+    public function load(): void;
+
+    public function persist(): void;
+}
diff --git a/vendor/phpunit/phpunit/src/Runner/TestSuiteLoader.php b/vendor/phpunit/phpunit/src/Runner/TestSuiteLoader.php
new file mode 100644
index 0000000000000000000000000000000000000000..c9d8e01b153cbe9ba446b87998d18f5ab8b7f52a
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Runner/TestSuiteLoader.php
@@ -0,0 +1,24 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Runner;
+
+use ReflectionClass;
+
+/**
+ * @deprecated see https://github.com/sebastianbergmann/phpunit/issues/4039
+ *
+ * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+ */
+interface TestSuiteLoader
+{
+    public function load(string $suiteClassFile): ReflectionClass;
+
+    public function reload(ReflectionClass $aClass): ReflectionClass;
+}
diff --git a/vendor/phpunit/phpunit/src/Runner/TestSuiteSorter.php b/vendor/phpunit/phpunit/src/Runner/TestSuiteSorter.php
new file mode 100644
index 0000000000000000000000000000000000000000..fcf2cdbb4c23f62f7731e7970019f40f7a53d472
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Runner/TestSuiteSorter.php
@@ -0,0 +1,391 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Runner;
+
+use function array_diff;
+use function array_merge;
+use function array_reverse;
+use function array_splice;
+use function count;
+use function in_array;
+use function max;
+use function shuffle;
+use function usort;
+use PHPUnit\Framework\DataProviderTestSuite;
+use PHPUnit\Framework\Reorderable;
+use PHPUnit\Framework\Test;
+use PHPUnit\Framework\TestCase;
+use PHPUnit\Framework\TestSuite;
+use PHPUnit\Util\Test as TestUtil;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class TestSuiteSorter
+{
+    /**
+     * @var int
+     */
+    public const ORDER_DEFAULT = 0;
+
+    /**
+     * @var int
+     */
+    public const ORDER_RANDOMIZED = 1;
+
+    /**
+     * @var int
+     */
+    public const ORDER_REVERSED = 2;
+
+    /**
+     * @var int
+     */
+    public const ORDER_DEFECTS_FIRST = 3;
+
+    /**
+     * @var int
+     */
+    public const ORDER_DURATION = 4;
+
+    /**
+     * Order tests by @size annotation 'small', 'medium', 'large'.
+     *
+     * @var int
+     */
+    public const ORDER_SIZE = 5;
+
+    /**
+     * List of sorting weights for all test result codes. A higher number gives higher priority.
+     */
+    private const DEFECT_SORT_WEIGHT = [
+        BaseTestRunner::STATUS_ERROR      => 6,
+        BaseTestRunner::STATUS_FAILURE    => 5,
+        BaseTestRunner::STATUS_WARNING    => 4,
+        BaseTestRunner::STATUS_INCOMPLETE => 3,
+        BaseTestRunner::STATUS_RISKY      => 2,
+        BaseTestRunner::STATUS_SKIPPED    => 1,
+        BaseTestRunner::STATUS_UNKNOWN    => 0,
+    ];
+
+    private const SIZE_SORT_WEIGHT = [
+        TestUtil::SMALL   => 1,
+        TestUtil::MEDIUM  => 2,
+        TestUtil::LARGE   => 3,
+        TestUtil::UNKNOWN => 4,
+    ];
+
+    /**
+     * @var array<string, int> Associative array of (string => DEFECT_SORT_WEIGHT) elements
+     */
+    private $defectSortOrder = [];
+
+    /**
+     * @var TestResultCache
+     */
+    private $cache;
+
+    /**
+     * @var array<string> A list of normalized names of tests before reordering
+     */
+    private $originalExecutionOrder = [];
+
+    /**
+     * @var array<string> A list of normalized names of tests affected by reordering
+     */
+    private $executionOrder = [];
+
+    public function __construct(?TestResultCache $cache = null)
+    {
+        $this->cache = $cache ?? new NullTestResultCache;
+    }
+
+    /**
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     * @throws Exception
+     */
+    public function reorderTestsInSuite(Test $suite, int $order, bool $resolveDependencies, int $orderDefects, bool $isRootTestSuite = true): void
+    {
+        $allowedOrders = [
+            self::ORDER_DEFAULT,
+            self::ORDER_REVERSED,
+            self::ORDER_RANDOMIZED,
+            self::ORDER_DURATION,
+            self::ORDER_SIZE,
+        ];
+
+        if (!in_array($order, $allowedOrders, true)) {
+            throw new Exception(
+                '$order must be one of TestSuiteSorter::ORDER_[DEFAULT|REVERSED|RANDOMIZED|DURATION|SIZE]'
+            );
+        }
+
+        $allowedOrderDefects = [
+            self::ORDER_DEFAULT,
+            self::ORDER_DEFECTS_FIRST,
+        ];
+
+        if (!in_array($orderDefects, $allowedOrderDefects, true)) {
+            throw new Exception(
+                '$orderDefects must be one of TestSuiteSorter::ORDER_DEFAULT, TestSuiteSorter::ORDER_DEFECTS_FIRST'
+            );
+        }
+
+        if ($isRootTestSuite) {
+            $this->originalExecutionOrder = $this->calculateTestExecutionOrder($suite);
+        }
+
+        if ($suite instanceof TestSuite) {
+            foreach ($suite as $_suite) {
+                $this->reorderTestsInSuite($_suite, $order, $resolveDependencies, $orderDefects, false);
+            }
+
+            if ($orderDefects === self::ORDER_DEFECTS_FIRST) {
+                $this->addSuiteToDefectSortOrder($suite);
+            }
+
+            $this->sort($suite, $order, $resolveDependencies, $orderDefects);
+        }
+
+        if ($isRootTestSuite) {
+            $this->executionOrder = $this->calculateTestExecutionOrder($suite);
+        }
+    }
+
+    public function getOriginalExecutionOrder(): array
+    {
+        return $this->originalExecutionOrder;
+    }
+
+    public function getExecutionOrder(): array
+    {
+        return $this->executionOrder;
+    }
+
+    private function sort(TestSuite $suite, int $order, bool $resolveDependencies, int $orderDefects): void
+    {
+        if (empty($suite->tests())) {
+            return;
+        }
+
+        if ($order === self::ORDER_REVERSED) {
+            $suite->setTests($this->reverse($suite->tests()));
+        } elseif ($order === self::ORDER_RANDOMIZED) {
+            $suite->setTests($this->randomize($suite->tests()));
+        } elseif ($order === self::ORDER_DURATION && $this->cache !== null) {
+            $suite->setTests($this->sortByDuration($suite->tests()));
+        } elseif ($order === self::ORDER_SIZE) {
+            $suite->setTests($this->sortBySize($suite->tests()));
+        }
+
+        if ($orderDefects === self::ORDER_DEFECTS_FIRST && $this->cache !== null) {
+            $suite->setTests($this->sortDefectsFirst($suite->tests()));
+        }
+
+        if ($resolveDependencies && !($suite instanceof DataProviderTestSuite)) {
+            /** @var TestCase[] $tests */
+            $tests = $suite->tests();
+
+            $suite->setTests($this->resolveDependencies($tests));
+        }
+    }
+
+    /**
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     */
+    private function addSuiteToDefectSortOrder(TestSuite $suite): void
+    {
+        $max = 0;
+
+        foreach ($suite->tests() as $test) {
+            if (!$test instanceof Reorderable) {
+                continue;
+            }
+
+            if (!isset($this->defectSortOrder[$test->sortId()])) {
+                $this->defectSortOrder[$test->sortId()] = self::DEFECT_SORT_WEIGHT[$this->cache->getState($test->sortId())];
+                $max                                    = max($max, $this->defectSortOrder[$test->sortId()]);
+            }
+        }
+
+        $this->defectSortOrder[$suite->sortId()] = $max;
+    }
+
+    private function reverse(array $tests): array
+    {
+        return array_reverse($tests);
+    }
+
+    private function randomize(array $tests): array
+    {
+        shuffle($tests);
+
+        return $tests;
+    }
+
+    private function sortDefectsFirst(array $tests): array
+    {
+        usort(
+            $tests,
+            /**
+             * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+             */
+            function ($left, $right) {
+                return $this->cmpDefectPriorityAndTime($left, $right);
+            }
+        );
+
+        return $tests;
+    }
+
+    private function sortByDuration(array $tests): array
+    {
+        usort(
+            $tests,
+            /**
+             * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+             */
+            function ($left, $right) {
+                return $this->cmpDuration($left, $right);
+            }
+        );
+
+        return $tests;
+    }
+
+    private function sortBySize(array $tests): array
+    {
+        usort(
+            $tests,
+            /**
+             * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+             */
+            function ($left, $right) {
+                return $this->cmpSize($left, $right);
+            }
+        );
+
+        return $tests;
+    }
+
+    /**
+     * Comparator callback function to sort tests for "reach failure as fast as possible".
+     *
+     * 1. sort tests by defect weight defined in self::DEFECT_SORT_WEIGHT
+     * 2. when tests are equally defective, sort the fastest to the front
+     * 3. do not reorder successful tests
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     */
+    private function cmpDefectPriorityAndTime(Test $a, Test $b): int
+    {
+        if (!($a instanceof Reorderable && $b instanceof Reorderable)) {
+            return 0;
+        }
+
+        $priorityA = $this->defectSortOrder[$a->sortId()] ?? 0;
+        $priorityB = $this->defectSortOrder[$b->sortId()] ?? 0;
+
+        if ($priorityB <=> $priorityA) {
+            // Sort defect weight descending
+            return $priorityB <=> $priorityA;
+        }
+
+        if ($priorityA || $priorityB) {
+            return $this->cmpDuration($a, $b);
+        }
+
+        // do not change execution order
+        return 0;
+    }
+
+    /**
+     * Compares test duration for sorting tests by duration ascending.
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     */
+    private function cmpDuration(Test $a, Test $b): int
+    {
+        if (!($a instanceof Reorderable && $b instanceof Reorderable)) {
+            return 0;
+        }
+
+        return $this->cache->getTime($a->sortId()) <=> $this->cache->getTime($b->sortId());
+    }
+
+    /**
+     * Compares test size for sorting tests small->medium->large->unknown.
+     */
+    private function cmpSize(Test $a, Test $b): int
+    {
+        $sizeA = ($a instanceof TestCase || $a instanceof DataProviderTestSuite)
+            ? $a->getSize()
+            : TestUtil::UNKNOWN;
+        $sizeB = ($b instanceof TestCase || $b instanceof DataProviderTestSuite)
+            ? $b->getSize()
+            : TestUtil::UNKNOWN;
+
+        return self::SIZE_SORT_WEIGHT[$sizeA] <=> self::SIZE_SORT_WEIGHT[$sizeB];
+    }
+
+    /**
+     * Reorder Tests within a TestCase in such a way as to resolve as many dependencies as possible.
+     * The algorithm will leave the tests in original running order when it can.
+     * For more details see the documentation for test dependencies.
+     *
+     * Short description of algorithm:
+     * 1. Pick the next Test from remaining tests to be checked for dependencies.
+     * 2. If the test has no dependencies: mark done, start again from the top
+     * 3. If the test has dependencies but none left to do: mark done, start again from the top
+     * 4. When we reach the end add any leftover tests to the end. These will be marked 'skipped' during execution.
+     *
+     * @param array<DataProviderTestSuite|TestCase> $tests
+     *
+     * @return array<DataProviderTestSuite|TestCase>
+     */
+    private function resolveDependencies(array $tests): array
+    {
+        $newTestOrder = [];
+        $i            = 0;
+        $provided     = [];
+
+        do {
+            if ([] === array_diff($tests[$i]->requires(), $provided)) {
+                $provided     = array_merge($provided, $tests[$i]->provides());
+                $newTestOrder = array_merge($newTestOrder, array_splice($tests, $i, 1));
+                $i            = 0;
+            } else {
+                $i++;
+            }
+        } while (!empty($tests) && ($i < count($tests)));
+
+        return array_merge($newTestOrder, $tests);
+    }
+
+    /**
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     */
+    private function calculateTestExecutionOrder(Test $suite): array
+    {
+        $tests = [];
+
+        if ($suite instanceof TestSuite) {
+            foreach ($suite->tests() as $test) {
+                if (!$test instanceof TestSuite && $test instanceof Reorderable) {
+                    $tests[] = $test->sortId();
+                } else {
+                    $tests = array_merge($tests, $this->calculateTestExecutionOrder($test));
+                }
+            }
+        }
+
+        return $tests;
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Runner/Version.php b/vendor/phpunit/phpunit/src/Runner/Version.php
new file mode 100644
index 0000000000000000000000000000000000000000..f012d19c1b9520a2e44caec64d5652353ceb99d8
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Runner/Version.php
@@ -0,0 +1,65 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Runner;
+
+use function array_slice;
+use function dirname;
+use function explode;
+use function implode;
+use function strpos;
+use SebastianBergmann\Version as VersionId;
+
+/**
+ * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+ */
+final class Version
+{
+    /**
+     * @var string
+     */
+    private static $pharVersion = '';
+
+    /**
+     * @var string
+     */
+    private static $version = '';
+
+    /**
+     * Returns the current version of PHPUnit.
+     */
+    public static function id(): string
+    {
+        if (self::$pharVersion !== '') {
+            return self::$pharVersion;
+        }
+
+        if (self::$version === '') {
+            self::$version = (new VersionId('9.5.3', dirname(__DIR__, 2)))->getVersion();
+        }
+
+        return self::$version;
+    }
+
+    public static function series(): string
+    {
+        if (strpos(self::id(), '-')) {
+            $version = explode('-', self::id())[0];
+        } else {
+            $version = self::id();
+        }
+
+        return implode('.', array_slice(explode('.', $version), 0, 2));
+    }
+
+    public static function getVersionString(): string
+    {
+        return 'PHPUnit ' . self::id() . ' by Sebastian Bergmann and contributors.';
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/TextUI/CliArguments/Builder.php b/vendor/phpunit/phpunit/src/TextUI/CliArguments/Builder.php
new file mode 100644
index 0000000000000000000000000000000000000000..7d5e1b5b40def3c630815292ed2ee8a359dda5c9
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/TextUI/CliArguments/Builder.php
@@ -0,0 +1,887 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\TextUI\CliArguments;
+
+use function array_map;
+use function array_merge;
+use function class_exists;
+use function explode;
+use function is_numeric;
+use function str_replace;
+use PHPUnit\Runner\TestSuiteSorter;
+use PHPUnit\TextUI\DefaultResultPrinter;
+use PHPUnit\TextUI\XmlConfiguration\Extension;
+use PHPUnit\Util\Log\TeamCity;
+use PHPUnit\Util\TestDox\CliTestDoxPrinter;
+use SebastianBergmann\CliParser\Exception as CliParserException;
+use SebastianBergmann\CliParser\Parser as CliParser;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class Builder
+{
+    private const LONG_OPTIONS = [
+        'atleast-version=',
+        'prepend=',
+        'bootstrap=',
+        'cache-result',
+        'do-not-cache-result',
+        'cache-result-file=',
+        'check-version',
+        'colors==',
+        'columns=',
+        'configuration=',
+        'coverage-cache=',
+        'warm-coverage-cache',
+        'coverage-filter=',
+        'coverage-clover=',
+        'coverage-cobertura=',
+        'coverage-crap4j=',
+        'coverage-html=',
+        'coverage-php=',
+        'coverage-text==',
+        'coverage-xml=',
+        'path-coverage',
+        'debug',
+        'disallow-test-output',
+        'disallow-resource-usage',
+        'disallow-todo-tests',
+        'default-time-limit=',
+        'enforce-time-limit',
+        'exclude-group=',
+        'extensions=',
+        'filter=',
+        'generate-configuration',
+        'globals-backup',
+        'group=',
+        'covers=',
+        'uses=',
+        'help',
+        'resolve-dependencies',
+        'ignore-dependencies',
+        'include-path=',
+        'list-groups',
+        'list-suites',
+        'list-tests',
+        'list-tests-xml=',
+        'loader=',
+        'log-junit=',
+        'log-teamcity=',
+        'migrate-configuration',
+        'no-configuration',
+        'no-coverage',
+        'no-logging',
+        'no-interaction',
+        'no-extensions',
+        'order-by=',
+        'printer=',
+        'process-isolation',
+        'repeat=',
+        'dont-report-useless-tests',
+        'random-order',
+        'random-order-seed=',
+        'reverse-order',
+        'reverse-list',
+        'static-backup',
+        'stderr',
+        'stop-on-defect',
+        'stop-on-error',
+        'stop-on-failure',
+        'stop-on-warning',
+        'stop-on-incomplete',
+        'stop-on-risky',
+        'stop-on-skipped',
+        'fail-on-empty-test-suite',
+        'fail-on-incomplete',
+        'fail-on-risky',
+        'fail-on-skipped',
+        'fail-on-warning',
+        'strict-coverage',
+        'disable-coverage-ignore',
+        'strict-global-state',
+        'teamcity',
+        'testdox',
+        'testdox-group=',
+        'testdox-exclude-group=',
+        'testdox-html=',
+        'testdox-text=',
+        'testdox-xml=',
+        'test-suffix=',
+        'testsuite=',
+        'verbose',
+        'version',
+        'whitelist=',
+        'dump-xdebug-filter=',
+    ];
+
+    private const SHORT_OPTIONS = 'd:c:hv';
+
+    public function fromParameters(array $parameters, array $additionalLongOptions): Configuration
+    {
+        try {
+            $options = (new CliParser)->parse(
+                $parameters,
+                self::SHORT_OPTIONS,
+                array_merge(self::LONG_OPTIONS, $additionalLongOptions)
+            );
+        } catch (CliParserException $e) {
+            throw new Exception(
+                $e->getMessage(),
+                (int) $e->getCode(),
+                $e
+            );
+        }
+
+        $argument                                   = null;
+        $atLeastVersion                             = null;
+        $backupGlobals                              = null;
+        $backupStaticAttributes                     = null;
+        $beStrictAboutChangesToGlobalState          = null;
+        $beStrictAboutResourceUsageDuringSmallTests = null;
+        $bootstrap                                  = null;
+        $cacheResult                                = null;
+        $cacheResultFile                            = null;
+        $checkVersion                               = null;
+        $colors                                     = null;
+        $columns                                    = null;
+        $configuration                              = null;
+        $coverageCacheDirectory                     = null;
+        $warmCoverageCache                          = null;
+        $coverageFilter                             = null;
+        $coverageClover                             = null;
+        $coverageCobertura                          = null;
+        $coverageCrap4J                             = null;
+        $coverageHtml                               = null;
+        $coveragePhp                                = null;
+        $coverageText                               = null;
+        $coverageTextShowUncoveredFiles             = null;
+        $coverageTextShowOnlySummary                = null;
+        $coverageXml                                = null;
+        $pathCoverage                               = null;
+        $debug                                      = null;
+        $defaultTimeLimit                           = null;
+        $disableCodeCoverageIgnore                  = null;
+        $disallowTestOutput                         = null;
+        $disallowTodoAnnotatedTests                 = null;
+        $enforceTimeLimit                           = null;
+        $excludeGroups                              = null;
+        $executionOrder                             = null;
+        $executionOrderDefects                      = null;
+        $extensions                                 = [];
+        $unavailableExtensions                      = [];
+        $failOnEmptyTestSuite                       = null;
+        $failOnIncomplete                           = null;
+        $failOnRisky                                = null;
+        $failOnSkipped                              = null;
+        $failOnWarning                              = null;
+        $filter                                     = null;
+        $generateConfiguration                      = null;
+        $migrateConfiguration                       = null;
+        $groups                                     = null;
+        $testsCovering                              = null;
+        $testsUsing                                 = null;
+        $help                                       = null;
+        $includePath                                = null;
+        $iniSettings                                = [];
+        $junitLogfile                               = null;
+        $listGroups                                 = null;
+        $listSuites                                 = null;
+        $listTests                                  = null;
+        $listTestsXml                               = null;
+        $loader                                     = null;
+        $noCoverage                                 = null;
+        $noExtensions                               = null;
+        $noInteraction                              = null;
+        $noLogging                                  = null;
+        $printer                                    = null;
+        $processIsolation                           = null;
+        $randomOrderSeed                            = null;
+        $repeat                                     = null;
+        $reportUselessTests                         = null;
+        $resolveDependencies                        = null;
+        $reverseList                                = null;
+        $stderr                                     = null;
+        $strictCoverage                             = null;
+        $stopOnDefect                               = null;
+        $stopOnError                                = null;
+        $stopOnFailure                              = null;
+        $stopOnIncomplete                           = null;
+        $stopOnRisky                                = null;
+        $stopOnSkipped                              = null;
+        $stopOnWarning                              = null;
+        $teamcityLogfile                            = null;
+        $testdoxExcludeGroups                       = null;
+        $testdoxGroups                              = null;
+        $testdoxHtmlFile                            = null;
+        $testdoxTextFile                            = null;
+        $testdoxXmlFile                             = null;
+        $testSuffixes                               = null;
+        $testSuite                                  = null;
+        $unrecognizedOptions                        = [];
+        $unrecognizedOrderBy                        = null;
+        $useDefaultConfiguration                    = null;
+        $verbose                                    = null;
+        $version                                    = null;
+        $xdebugFilterFile                           = null;
+
+        if (isset($options[1][0])) {
+            $argument = $options[1][0];
+        }
+
+        foreach ($options[0] as $option) {
+            switch ($option[0]) {
+                case '--colors':
+                    $colors = $option[1] ?: DefaultResultPrinter::COLOR_AUTO;
+
+                    break;
+
+                case '--bootstrap':
+                    $bootstrap = $option[1];
+
+                    break;
+
+                case '--cache-result':
+                    $cacheResult = true;
+
+                    break;
+
+                case '--do-not-cache-result':
+                    $cacheResult = false;
+
+                    break;
+
+                case '--cache-result-file':
+                    $cacheResultFile = $option[1];
+
+                    break;
+
+                case '--columns':
+                    if (is_numeric($option[1])) {
+                        $columns = (int) $option[1];
+                    } elseif ($option[1] === 'max') {
+                        $columns = 'max';
+                    }
+
+                    break;
+
+                case 'c':
+                case '--configuration':
+                    $configuration = $option[1];
+
+                    break;
+
+                case '--coverage-cache':
+                    $coverageCacheDirectory = $option[1];
+
+                    break;
+
+                case '--warm-coverage-cache':
+                    $warmCoverageCache = true;
+
+                    break;
+
+                case '--coverage-clover':
+                    $coverageClover = $option[1];
+
+                    break;
+
+                case '--coverage-cobertura':
+                    $coverageCobertura = $option[1];
+
+                    break;
+
+                case '--coverage-crap4j':
+                    $coverageCrap4J = $option[1];
+
+                    break;
+
+                case '--coverage-html':
+                    $coverageHtml = $option[1];
+
+                    break;
+
+                case '--coverage-php':
+                    $coveragePhp = $option[1];
+
+                    break;
+
+                case '--coverage-text':
+                    if ($option[1] === null) {
+                        $option[1] = 'php://stdout';
+                    }
+
+                    $coverageText                   = $option[1];
+                    $coverageTextShowUncoveredFiles = false;
+                    $coverageTextShowOnlySummary    = false;
+
+                    break;
+
+                case '--coverage-xml':
+                    $coverageXml = $option[1];
+
+                    break;
+
+                case '--path-coverage':
+                    $pathCoverage = true;
+
+                    break;
+
+                case 'd':
+                    $tmp = explode('=', $option[1]);
+
+                    if (isset($tmp[0])) {
+                        if (isset($tmp[1])) {
+                            $iniSettings[$tmp[0]] = $tmp[1];
+                        } else {
+                            $iniSettings[$tmp[0]] = '1';
+                        }
+                    }
+
+                    break;
+
+                case '--debug':
+                    $debug = true;
+
+                    break;
+
+                case 'h':
+                case '--help':
+                    $help = true;
+
+                    break;
+
+                case '--filter':
+                    $filter = $option[1];
+
+                    break;
+
+                case '--testsuite':
+                    $testSuite = $option[1];
+
+                    break;
+
+                case '--generate-configuration':
+                    $generateConfiguration = true;
+
+                    break;
+
+                case '--migrate-configuration':
+                    $migrateConfiguration = true;
+
+                    break;
+
+                case '--group':
+                    $groups = explode(',', $option[1]);
+
+                    break;
+
+                case '--exclude-group':
+                    $excludeGroups = explode(',', $option[1]);
+
+                    break;
+
+                case '--covers':
+                    $testsCovering = array_map('strtolower', explode(',', $option[1]));
+
+                    break;
+
+                case '--uses':
+                    $testsUsing = array_map('strtolower', explode(',', $option[1]));
+
+                    break;
+
+                case '--test-suffix':
+                    $testSuffixes = explode(',', $option[1]);
+
+                    break;
+
+                case '--include-path':
+                    $includePath = $option[1];
+
+                    break;
+
+                case '--list-groups':
+                    $listGroups = true;
+
+                    break;
+
+                case '--list-suites':
+                    $listSuites = true;
+
+                    break;
+
+                case '--list-tests':
+                    $listTests = true;
+
+                    break;
+
+                case '--list-tests-xml':
+                    $listTestsXml = $option[1];
+
+                    break;
+
+                case '--printer':
+                    $printer = $option[1];
+
+                    break;
+
+                case '--loader':
+                    $loader = $option[1];
+
+                    break;
+
+                case '--log-junit':
+                    $junitLogfile = $option[1];
+
+                    break;
+
+                case '--log-teamcity':
+                    $teamcityLogfile = $option[1];
+
+                    break;
+
+                case '--order-by':
+                    foreach (explode(',', $option[1]) as $order) {
+                        switch ($order) {
+                            case 'default':
+                                $executionOrder        = TestSuiteSorter::ORDER_DEFAULT;
+                                $executionOrderDefects = TestSuiteSorter::ORDER_DEFAULT;
+                                $resolveDependencies   = true;
+
+                                break;
+
+                            case 'defects':
+                                $executionOrderDefects = TestSuiteSorter::ORDER_DEFECTS_FIRST;
+
+                                break;
+
+                            case 'depends':
+                                $resolveDependencies = true;
+
+                                break;
+
+                            case 'duration':
+                                $executionOrder = TestSuiteSorter::ORDER_DURATION;
+
+                                break;
+
+                            case 'no-depends':
+                                $resolveDependencies = false;
+
+                                break;
+
+                            case 'random':
+                                $executionOrder = TestSuiteSorter::ORDER_RANDOMIZED;
+
+                                break;
+
+                            case 'reverse':
+                                $executionOrder = TestSuiteSorter::ORDER_REVERSED;
+
+                                break;
+
+                            case 'size':
+                                $executionOrder = TestSuiteSorter::ORDER_SIZE;
+
+                                break;
+
+                            default:
+                                $unrecognizedOrderBy = $order;
+                        }
+                    }
+
+                    break;
+
+                case '--process-isolation':
+                    $processIsolation = true;
+
+                    break;
+
+                case '--repeat':
+                    $repeat = (int) $option[1];
+
+                    break;
+
+                case '--stderr':
+                    $stderr = true;
+
+                    break;
+
+                case '--stop-on-defect':
+                    $stopOnDefect = true;
+
+                    break;
+
+                case '--stop-on-error':
+                    $stopOnError = true;
+
+                    break;
+
+                case '--stop-on-failure':
+                    $stopOnFailure = true;
+
+                    break;
+
+                case '--stop-on-warning':
+                    $stopOnWarning = true;
+
+                    break;
+
+                case '--stop-on-incomplete':
+                    $stopOnIncomplete = true;
+
+                    break;
+
+                case '--stop-on-risky':
+                    $stopOnRisky = true;
+
+                    break;
+
+                case '--stop-on-skipped':
+                    $stopOnSkipped = true;
+
+                    break;
+
+                case '--fail-on-empty-test-suite':
+                    $failOnEmptyTestSuite = true;
+
+                    break;
+
+                case '--fail-on-incomplete':
+                    $failOnIncomplete = true;
+
+                    break;
+
+                case '--fail-on-risky':
+                    $failOnRisky = true;
+
+                    break;
+
+                case '--fail-on-skipped':
+                    $failOnSkipped = true;
+
+                    break;
+
+                case '--fail-on-warning':
+                    $failOnWarning = true;
+
+                    break;
+
+                case '--teamcity':
+                    $printer = TeamCity::class;
+
+                    break;
+
+                case '--testdox':
+                    $printer = CliTestDoxPrinter::class;
+
+                    break;
+
+                case '--testdox-group':
+                    $testdoxGroups = explode(',', $option[1]);
+
+                    break;
+
+                case '--testdox-exclude-group':
+                    $testdoxExcludeGroups = explode(',', $option[1]);
+
+                    break;
+
+                case '--testdox-html':
+                    $testdoxHtmlFile = $option[1];
+
+                    break;
+
+                case '--testdox-text':
+                    $testdoxTextFile = $option[1];
+
+                    break;
+
+                case '--testdox-xml':
+                    $testdoxXmlFile = $option[1];
+
+                    break;
+
+                case '--no-configuration':
+                    $useDefaultConfiguration = false;
+
+                    break;
+
+                case '--extensions':
+                    foreach (explode(',', $option[1]) as $extensionClass) {
+                        if (!class_exists($extensionClass)) {
+                            $unavailableExtensions[] = $extensionClass;
+
+                            continue;
+                        }
+
+                        $extensions[] = new Extension($extensionClass, '', []);
+                    }
+
+                    break;
+
+                case '--no-extensions':
+                    $noExtensions = true;
+
+                    break;
+
+                case '--no-coverage':
+                    $noCoverage = true;
+
+                    break;
+
+                case '--no-logging':
+                    $noLogging = true;
+
+                    break;
+
+                case '--no-interaction':
+                    $noInteraction = true;
+
+                    break;
+
+                case '--globals-backup':
+                    $backupGlobals = true;
+
+                    break;
+
+                case '--static-backup':
+                    $backupStaticAttributes = true;
+
+                    break;
+
+                case 'v':
+                case '--verbose':
+                    $verbose = true;
+
+                    break;
+
+                case '--atleast-version':
+                    $atLeastVersion = $option[1];
+
+                    break;
+
+                case '--version':
+                    $version = true;
+
+                    break;
+
+                case '--dont-report-useless-tests':
+                    $reportUselessTests = false;
+
+                    break;
+
+                case '--strict-coverage':
+                    $strictCoverage = true;
+
+                    break;
+
+                case '--disable-coverage-ignore':
+                    $disableCodeCoverageIgnore = true;
+
+                    break;
+
+                case '--strict-global-state':
+                    $beStrictAboutChangesToGlobalState = true;
+
+                    break;
+
+                case '--disallow-test-output':
+                    $disallowTestOutput = true;
+
+                    break;
+
+                case '--disallow-resource-usage':
+                    $beStrictAboutResourceUsageDuringSmallTests = true;
+
+                    break;
+
+                case '--default-time-limit':
+                    $defaultTimeLimit = (int) $option[1];
+
+                    break;
+
+                case '--enforce-time-limit':
+                    $enforceTimeLimit = true;
+
+                    break;
+
+                case '--disallow-todo-tests':
+                    $disallowTodoAnnotatedTests = true;
+
+                    break;
+
+                case '--reverse-list':
+                    $reverseList = true;
+
+                    break;
+
+                case '--check-version':
+                    $checkVersion = true;
+
+                    break;
+
+                case '--coverage-filter':
+                case '--whitelist':
+                    if ($coverageFilter === null) {
+                        $coverageFilter = [];
+                    }
+
+                    $coverageFilter[] = $option[1];
+
+                    break;
+
+                case '--random-order':
+                    $executionOrder = TestSuiteSorter::ORDER_RANDOMIZED;
+
+                    break;
+
+                case '--random-order-seed':
+                    $randomOrderSeed = (int) $option[1];
+
+                    break;
+
+                case '--resolve-dependencies':
+                    $resolveDependencies = true;
+
+                    break;
+
+                case '--ignore-dependencies':
+                    $resolveDependencies = false;
+
+                    break;
+
+                case '--reverse-order':
+                    $executionOrder = TestSuiteSorter::ORDER_REVERSED;
+
+                    break;
+
+                case '--dump-xdebug-filter':
+                    $xdebugFilterFile = $option[1];
+
+                    break;
+
+                default:
+                    $unrecognizedOptions[str_replace('--', '', $option[0])] = $option[1];
+            }
+        }
+
+        if (empty($extensions)) {
+            $extensions = null;
+        }
+
+        if (empty($unavailableExtensions)) {
+            $unavailableExtensions = null;
+        }
+
+        if (empty($iniSettings)) {
+            $iniSettings = null;
+        }
+
+        if (empty($coverageFilter)) {
+            $coverageFilter = null;
+        }
+
+        return new Configuration(
+            $argument,
+            $atLeastVersion,
+            $backupGlobals,
+            $backupStaticAttributes,
+            $beStrictAboutChangesToGlobalState,
+            $beStrictAboutResourceUsageDuringSmallTests,
+            $bootstrap,
+            $cacheResult,
+            $cacheResultFile,
+            $checkVersion,
+            $colors,
+            $columns,
+            $configuration,
+            $coverageClover,
+            $coverageCobertura,
+            $coverageCrap4J,
+            $coverageHtml,
+            $coveragePhp,
+            $coverageText,
+            $coverageTextShowUncoveredFiles,
+            $coverageTextShowOnlySummary,
+            $coverageXml,
+            $pathCoverage,
+            $coverageCacheDirectory,
+            $warmCoverageCache,
+            $debug,
+            $defaultTimeLimit,
+            $disableCodeCoverageIgnore,
+            $disallowTestOutput,
+            $disallowTodoAnnotatedTests,
+            $enforceTimeLimit,
+            $excludeGroups,
+            $executionOrder,
+            $executionOrderDefects,
+            $extensions,
+            $unavailableExtensions,
+            $failOnEmptyTestSuite,
+            $failOnIncomplete,
+            $failOnRisky,
+            $failOnSkipped,
+            $failOnWarning,
+            $filter,
+            $generateConfiguration,
+            $migrateConfiguration,
+            $groups,
+            $testsCovering,
+            $testsUsing,
+            $help,
+            $includePath,
+            $iniSettings,
+            $junitLogfile,
+            $listGroups,
+            $listSuites,
+            $listTests,
+            $listTestsXml,
+            $loader,
+            $noCoverage,
+            $noExtensions,
+            $noInteraction,
+            $noLogging,
+            $printer,
+            $processIsolation,
+            $randomOrderSeed,
+            $repeat,
+            $reportUselessTests,
+            $resolveDependencies,
+            $reverseList,
+            $stderr,
+            $strictCoverage,
+            $stopOnDefect,
+            $stopOnError,
+            $stopOnFailure,
+            $stopOnIncomplete,
+            $stopOnRisky,
+            $stopOnSkipped,
+            $stopOnWarning,
+            $teamcityLogfile,
+            $testdoxExcludeGroups,
+            $testdoxGroups,
+            $testdoxHtmlFile,
+            $testdoxTextFile,
+            $testdoxXmlFile,
+            $testSuffixes,
+            $testSuite,
+            $unrecognizedOptions,
+            $unrecognizedOrderBy,
+            $useDefaultConfiguration,
+            $verbose,
+            $version,
+            $coverageFilter,
+            $xdebugFilterFile
+        );
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/TextUI/CliArguments/Configuration.php b/vendor/phpunit/phpunit/src/TextUI/CliArguments/Configuration.php
new file mode 100644
index 0000000000000000000000000000000000000000..b220dd7aaa6d157eea8634eb27eae308cd2a7ae0
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/TextUI/CliArguments/Configuration.php
@@ -0,0 +1,2107 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\TextUI\CliArguments;
+
+use PHPUnit\TextUI\XmlConfiguration\Extension;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ * @psalm-immutable
+ */
+final class Configuration
+{
+    /**
+     * @var ?string
+     */
+    private $argument;
+
+    /**
+     * @var ?string
+     */
+    private $atLeastVersion;
+
+    /**
+     * @var ?bool
+     */
+    private $backupGlobals;
+
+    /**
+     * @var ?bool
+     */
+    private $backupStaticAttributes;
+
+    /**
+     * @var ?bool
+     */
+    private $beStrictAboutChangesToGlobalState;
+
+    /**
+     * @var ?bool
+     */
+    private $beStrictAboutResourceUsageDuringSmallTests;
+
+    /**
+     * @var ?string
+     */
+    private $bootstrap;
+
+    /**
+     * @var ?bool
+     */
+    private $cacheResult;
+
+    /**
+     * @var ?string
+     */
+    private $cacheResultFile;
+
+    /**
+     * @var ?bool
+     */
+    private $checkVersion;
+
+    /**
+     * @var ?string
+     */
+    private $colors;
+
+    /**
+     * @var null|int|string
+     */
+    private $columns;
+
+    /**
+     * @var ?string
+     */
+    private $configuration;
+
+    /**
+     * @var null|string[]
+     */
+    private $coverageFilter;
+
+    /**
+     * @var ?string
+     */
+    private $coverageClover;
+
+    /**
+     * @var ?string
+     */
+    private $coverageCobertura;
+
+    /**
+     * @var ?string
+     */
+    private $coverageCrap4J;
+
+    /**
+     * @var ?string
+     */
+    private $coverageHtml;
+
+    /**
+     * @var ?string
+     */
+    private $coveragePhp;
+
+    /**
+     * @var ?string
+     */
+    private $coverageText;
+
+    /**
+     * @var ?bool
+     */
+    private $coverageTextShowUncoveredFiles;
+
+    /**
+     * @var ?bool
+     */
+    private $coverageTextShowOnlySummary;
+
+    /**
+     * @var ?string
+     */
+    private $coverageXml;
+
+    /**
+     * @var ?bool
+     */
+    private $pathCoverage;
+
+    /**
+     * @var ?string
+     */
+    private $coverageCacheDirectory;
+
+    /**
+     * @var ?bool
+     */
+    private $warmCoverageCache;
+
+    /**
+     * @var ?bool
+     */
+    private $debug;
+
+    /**
+     * @var ?int
+     */
+    private $defaultTimeLimit;
+
+    /**
+     * @var ?bool
+     */
+    private $disableCodeCoverageIgnore;
+
+    /**
+     * @var ?bool
+     */
+    private $disallowTestOutput;
+
+    /**
+     * @var ?bool
+     */
+    private $disallowTodoAnnotatedTests;
+
+    /**
+     * @var ?bool
+     */
+    private $enforceTimeLimit;
+
+    /**
+     * @var null|string[]
+     */
+    private $excludeGroups;
+
+    /**
+     * @var ?int
+     */
+    private $executionOrder;
+
+    /**
+     * @var ?int
+     */
+    private $executionOrderDefects;
+
+    /**
+     * @var null|Extension[]
+     */
+    private $extensions;
+
+    /**
+     * @var null|string[]
+     */
+    private $unavailableExtensions;
+
+    /**
+     * @var ?bool
+     */
+    private $failOnEmptyTestSuite;
+
+    /**
+     * @var ?bool
+     */
+    private $failOnIncomplete;
+
+    /**
+     * @var ?bool
+     */
+    private $failOnRisky;
+
+    /**
+     * @var ?bool
+     */
+    private $failOnSkipped;
+
+    /**
+     * @var ?bool
+     */
+    private $failOnWarning;
+
+    /**
+     * @var ?string
+     */
+    private $filter;
+
+    /**
+     * @var ?bool
+     */
+    private $generateConfiguration;
+
+    /**
+     * @var ?bool
+     */
+    private $migrateConfiguration;
+
+    /**
+     * @var null|string[]
+     */
+    private $groups;
+
+    /**
+     * @var null|string[]
+     */
+    private $testsCovering;
+
+    /**
+     * @var null|string[]
+     */
+    private $testsUsing;
+
+    /**
+     * @var ?bool
+     */
+    private $help;
+
+    /**
+     * @var ?string
+     */
+    private $includePath;
+
+    /**
+     * @var null|string[]
+     */
+    private $iniSettings;
+
+    /**
+     * @var ?string
+     */
+    private $junitLogfile;
+
+    /**
+     * @var ?bool
+     */
+    private $listGroups;
+
+    /**
+     * @var ?bool
+     */
+    private $listSuites;
+
+    /**
+     * @var ?bool
+     */
+    private $listTests;
+
+    /**
+     * @var ?string
+     */
+    private $listTestsXml;
+
+    /**
+     * @var ?string
+     */
+    private $loader;
+
+    /**
+     * @var ?bool
+     */
+    private $noCoverage;
+
+    /**
+     * @var ?bool
+     */
+    private $noExtensions;
+
+    /**
+     * @var ?bool
+     */
+    private $noInteraction;
+
+    /**
+     * @var ?bool
+     */
+    private $noLogging;
+
+    /**
+     * @var ?string
+     */
+    private $printer;
+
+    /**
+     * @var ?bool
+     */
+    private $processIsolation;
+
+    /**
+     * @var ?int
+     */
+    private $randomOrderSeed;
+
+    /**
+     * @var ?int
+     */
+    private $repeat;
+
+    /**
+     * @var ?bool
+     */
+    private $reportUselessTests;
+
+    /**
+     * @var ?bool
+     */
+    private $resolveDependencies;
+
+    /**
+     * @var ?bool
+     */
+    private $reverseList;
+
+    /**
+     * @var ?bool
+     */
+    private $stderr;
+
+    /**
+     * @var ?bool
+     */
+    private $strictCoverage;
+
+    /**
+     * @var ?bool
+     */
+    private $stopOnDefect;
+
+    /**
+     * @var ?bool
+     */
+    private $stopOnError;
+
+    /**
+     * @var ?bool
+     */
+    private $stopOnFailure;
+
+    /**
+     * @var ?bool
+     */
+    private $stopOnIncomplete;
+
+    /**
+     * @var ?bool
+     */
+    private $stopOnRisky;
+
+    /**
+     * @var ?bool
+     */
+    private $stopOnSkipped;
+
+    /**
+     * @var ?bool
+     */
+    private $stopOnWarning;
+
+    /**
+     * @var ?string
+     */
+    private $teamcityLogfile;
+
+    /**
+     * @var null|string[]
+     */
+    private $testdoxExcludeGroups;
+
+    /**
+     * @var null|string[]
+     */
+    private $testdoxGroups;
+
+    /**
+     * @var ?string
+     */
+    private $testdoxHtmlFile;
+
+    /**
+     * @var ?string
+     */
+    private $testdoxTextFile;
+
+    /**
+     * @var ?string
+     */
+    private $testdoxXmlFile;
+
+    /**
+     * @var null|string[]
+     */
+    private $testSuffixes;
+
+    /**
+     * @var ?string
+     */
+    private $testSuite;
+
+    /**
+     * @var string[]
+     */
+    private $unrecognizedOptions;
+
+    /**
+     * @var ?string
+     */
+    private $unrecognizedOrderBy;
+
+    /**
+     * @var ?bool
+     */
+    private $useDefaultConfiguration;
+
+    /**
+     * @var ?bool
+     */
+    private $verbose;
+
+    /**
+     * @var ?bool
+     */
+    private $version;
+
+    /**
+     * @var ?string
+     */
+    private $xdebugFilterFile;
+
+    /**
+     * @param null|int|string $columns
+     */
+    public function __construct(?string $argument, ?string $atLeastVersion, ?bool $backupGlobals, ?bool $backupStaticAttributes, ?bool $beStrictAboutChangesToGlobalState, ?bool $beStrictAboutResourceUsageDuringSmallTests, ?string $bootstrap, ?bool $cacheResult, ?string $cacheResultFile, ?bool $checkVersion, ?string $colors, $columns, ?string $configuration, ?string $coverageClover, ?string $coverageCobertura, ?string $coverageCrap4J, ?string $coverageHtml, ?string $coveragePhp, ?string $coverageText, ?bool $coverageTextShowUncoveredFiles, ?bool $coverageTextShowOnlySummary, ?string $coverageXml, ?bool $pathCoverage, ?string $coverageCacheDirectory, ?bool $warmCoverageCache, ?bool $debug, ?int $defaultTimeLimit, ?bool $disableCodeCoverageIgnore, ?bool $disallowTestOutput, ?bool $disallowTodoAnnotatedTests, ?bool $enforceTimeLimit, ?array $excludeGroups, ?int $executionOrder, ?int $executionOrderDefects, ?array $extensions, ?array $unavailableExtensions, ?bool $failOnEmptyTestSuite, ?bool $failOnIncomplete, ?bool $failOnRisky, ?bool $failOnSkipped, ?bool $failOnWarning, ?string $filter, ?bool $generateConfiguration, ?bool $migrateConfiguration, ?array $groups, ?array $testsCovering, ?array $testsUsing, ?bool $help, ?string $includePath, ?array $iniSettings, ?string $junitLogfile, ?bool $listGroups, ?bool $listSuites, ?bool $listTests, ?string $listTestsXml, ?string $loader, ?bool $noCoverage, ?bool $noExtensions, ?bool $noInteraction, ?bool $noLogging, ?string $printer, ?bool $processIsolation, ?int $randomOrderSeed, ?int $repeat, ?bool $reportUselessTests, ?bool $resolveDependencies, ?bool $reverseList, ?bool $stderr, ?bool $strictCoverage, ?bool $stopOnDefect, ?bool $stopOnError, ?bool $stopOnFailure, ?bool $stopOnIncomplete, ?bool $stopOnRisky, ?bool $stopOnSkipped, ?bool $stopOnWarning, ?string $teamcityLogfile, ?array $testdoxExcludeGroups, ?array $testdoxGroups, ?string $testdoxHtmlFile, ?string $testdoxTextFile, ?string $testdoxXmlFile, ?array $testSuffixes, ?string $testSuite, array $unrecognizedOptions, ?string $unrecognizedOrderBy, ?bool $useDefaultConfiguration, ?bool $verbose, ?bool $version, ?array $coverageFilter, ?string $xdebugFilterFile)
+    {
+        $this->argument                                   = $argument;
+        $this->atLeastVersion                             = $atLeastVersion;
+        $this->backupGlobals                              = $backupGlobals;
+        $this->backupStaticAttributes                     = $backupStaticAttributes;
+        $this->beStrictAboutChangesToGlobalState          = $beStrictAboutChangesToGlobalState;
+        $this->beStrictAboutResourceUsageDuringSmallTests = $beStrictAboutResourceUsageDuringSmallTests;
+        $this->bootstrap                                  = $bootstrap;
+        $this->cacheResult                                = $cacheResult;
+        $this->cacheResultFile                            = $cacheResultFile;
+        $this->checkVersion                               = $checkVersion;
+        $this->colors                                     = $colors;
+        $this->columns                                    = $columns;
+        $this->configuration                              = $configuration;
+        $this->coverageFilter                             = $coverageFilter;
+        $this->coverageClover                             = $coverageClover;
+        $this->coverageCobertura                          = $coverageCobertura;
+        $this->coverageCrap4J                             = $coverageCrap4J;
+        $this->coverageHtml                               = $coverageHtml;
+        $this->coveragePhp                                = $coveragePhp;
+        $this->coverageText                               = $coverageText;
+        $this->coverageTextShowUncoveredFiles             = $coverageTextShowUncoveredFiles;
+        $this->coverageTextShowOnlySummary                = $coverageTextShowOnlySummary;
+        $this->coverageXml                                = $coverageXml;
+        $this->pathCoverage                               = $pathCoverage;
+        $this->coverageCacheDirectory                     = $coverageCacheDirectory;
+        $this->warmCoverageCache                          = $warmCoverageCache;
+        $this->debug                                      = $debug;
+        $this->defaultTimeLimit                           = $defaultTimeLimit;
+        $this->disableCodeCoverageIgnore                  = $disableCodeCoverageIgnore;
+        $this->disallowTestOutput                         = $disallowTestOutput;
+        $this->disallowTodoAnnotatedTests                 = $disallowTodoAnnotatedTests;
+        $this->enforceTimeLimit                           = $enforceTimeLimit;
+        $this->excludeGroups                              = $excludeGroups;
+        $this->executionOrder                             = $executionOrder;
+        $this->executionOrderDefects                      = $executionOrderDefects;
+        $this->extensions                                 = $extensions;
+        $this->unavailableExtensions                      = $unavailableExtensions;
+        $this->failOnEmptyTestSuite                       = $failOnEmptyTestSuite;
+        $this->failOnIncomplete                           = $failOnIncomplete;
+        $this->failOnRisky                                = $failOnRisky;
+        $this->failOnSkipped                              = $failOnSkipped;
+        $this->failOnWarning                              = $failOnWarning;
+        $this->filter                                     = $filter;
+        $this->generateConfiguration                      = $generateConfiguration;
+        $this->migrateConfiguration                       = $migrateConfiguration;
+        $this->groups                                     = $groups;
+        $this->testsCovering                              = $testsCovering;
+        $this->testsUsing                                 = $testsUsing;
+        $this->help                                       = $help;
+        $this->includePath                                = $includePath;
+        $this->iniSettings                                = $iniSettings;
+        $this->junitLogfile                               = $junitLogfile;
+        $this->listGroups                                 = $listGroups;
+        $this->listSuites                                 = $listSuites;
+        $this->listTests                                  = $listTests;
+        $this->listTestsXml                               = $listTestsXml;
+        $this->loader                                     = $loader;
+        $this->noCoverage                                 = $noCoverage;
+        $this->noExtensions                               = $noExtensions;
+        $this->noInteraction                              = $noInteraction;
+        $this->noLogging                                  = $noLogging;
+        $this->printer                                    = $printer;
+        $this->processIsolation                           = $processIsolation;
+        $this->randomOrderSeed                            = $randomOrderSeed;
+        $this->repeat                                     = $repeat;
+        $this->reportUselessTests                         = $reportUselessTests;
+        $this->resolveDependencies                        = $resolveDependencies;
+        $this->reverseList                                = $reverseList;
+        $this->stderr                                     = $stderr;
+        $this->strictCoverage                             = $strictCoverage;
+        $this->stopOnDefect                               = $stopOnDefect;
+        $this->stopOnError                                = $stopOnError;
+        $this->stopOnFailure                              = $stopOnFailure;
+        $this->stopOnIncomplete                           = $stopOnIncomplete;
+        $this->stopOnRisky                                = $stopOnRisky;
+        $this->stopOnSkipped                              = $stopOnSkipped;
+        $this->stopOnWarning                              = $stopOnWarning;
+        $this->teamcityLogfile                            = $teamcityLogfile;
+        $this->testdoxExcludeGroups                       = $testdoxExcludeGroups;
+        $this->testdoxGroups                              = $testdoxGroups;
+        $this->testdoxHtmlFile                            = $testdoxHtmlFile;
+        $this->testdoxTextFile                            = $testdoxTextFile;
+        $this->testdoxXmlFile                             = $testdoxXmlFile;
+        $this->testSuffixes                               = $testSuffixes;
+        $this->testSuite                                  = $testSuite;
+        $this->unrecognizedOptions                        = $unrecognizedOptions;
+        $this->unrecognizedOrderBy                        = $unrecognizedOrderBy;
+        $this->useDefaultConfiguration                    = $useDefaultConfiguration;
+        $this->verbose                                    = $verbose;
+        $this->version                                    = $version;
+        $this->xdebugFilterFile                           = $xdebugFilterFile;
+    }
+
+    public function hasArgument(): bool
+    {
+        return $this->argument !== null;
+    }
+
+    /**
+     * @throws Exception
+     */
+    public function argument(): string
+    {
+        if ($this->argument === null) {
+            throw new Exception;
+        }
+
+        return $this->argument;
+    }
+
+    public function hasAtLeastVersion(): bool
+    {
+        return $this->atLeastVersion !== null;
+    }
+
+    /**
+     * @throws Exception
+     */
+    public function atLeastVersion(): string
+    {
+        if ($this->atLeastVersion === null) {
+            throw new Exception;
+        }
+
+        return $this->atLeastVersion;
+    }
+
+    public function hasBackupGlobals(): bool
+    {
+        return $this->backupGlobals !== null;
+    }
+
+    /**
+     * @throws Exception
+     */
+    public function backupGlobals(): bool
+    {
+        if ($this->backupGlobals === null) {
+            throw new Exception;
+        }
+
+        return $this->backupGlobals;
+    }
+
+    public function hasBackupStaticAttributes(): bool
+    {
+        return $this->backupStaticAttributes !== null;
+    }
+
+    /**
+     * @throws Exception
+     */
+    public function backupStaticAttributes(): bool
+    {
+        if ($this->backupStaticAttributes === null) {
+            throw new Exception;
+        }
+
+        return $this->backupStaticAttributes;
+    }
+
+    public function hasBeStrictAboutChangesToGlobalState(): bool
+    {
+        return $this->beStrictAboutChangesToGlobalState !== null;
+    }
+
+    /**
+     * @throws Exception
+     */
+    public function beStrictAboutChangesToGlobalState(): bool
+    {
+        if ($this->beStrictAboutChangesToGlobalState === null) {
+            throw new Exception;
+        }
+
+        return $this->beStrictAboutChangesToGlobalState;
+    }
+
+    public function hasBeStrictAboutResourceUsageDuringSmallTests(): bool
+    {
+        return $this->beStrictAboutResourceUsageDuringSmallTests !== null;
+    }
+
+    /**
+     * @throws Exception
+     */
+    public function beStrictAboutResourceUsageDuringSmallTests(): bool
+    {
+        if ($this->beStrictAboutResourceUsageDuringSmallTests === null) {
+            throw new Exception;
+        }
+
+        return $this->beStrictAboutResourceUsageDuringSmallTests;
+    }
+
+    public function hasBootstrap(): bool
+    {
+        return $this->bootstrap !== null;
+    }
+
+    /**
+     * @throws Exception
+     */
+    public function bootstrap(): string
+    {
+        if ($this->bootstrap === null) {
+            throw new Exception;
+        }
+
+        return $this->bootstrap;
+    }
+
+    public function hasCacheResult(): bool
+    {
+        return $this->cacheResult !== null;
+    }
+
+    /**
+     * @throws Exception
+     */
+    public function cacheResult(): bool
+    {
+        if ($this->cacheResult === null) {
+            throw new Exception;
+        }
+
+        return $this->cacheResult;
+    }
+
+    public function hasCacheResultFile(): bool
+    {
+        return $this->cacheResultFile !== null;
+    }
+
+    /**
+     * @throws Exception
+     */
+    public function cacheResultFile(): string
+    {
+        if ($this->cacheResultFile === null) {
+            throw new Exception;
+        }
+
+        return $this->cacheResultFile;
+    }
+
+    public function hasCheckVersion(): bool
+    {
+        return $this->checkVersion !== null;
+    }
+
+    /**
+     * @throws Exception
+     */
+    public function checkVersion(): bool
+    {
+        if ($this->checkVersion === null) {
+            throw new Exception;
+        }
+
+        return $this->checkVersion;
+    }
+
+    public function hasColors(): bool
+    {
+        return $this->colors !== null;
+    }
+
+    /**
+     * @throws Exception
+     */
+    public function colors(): string
+    {
+        if ($this->colors === null) {
+            throw new Exception;
+        }
+
+        return $this->colors;
+    }
+
+    public function hasColumns(): bool
+    {
+        return $this->columns !== null;
+    }
+
+    /**
+     * @throws Exception
+     */
+    public function columns()
+    {
+        if ($this->columns === null) {
+            throw new Exception;
+        }
+
+        return $this->columns;
+    }
+
+    public function hasConfiguration(): bool
+    {
+        return $this->configuration !== null;
+    }
+
+    /**
+     * @throws Exception
+     */
+    public function configuration(): string
+    {
+        if ($this->configuration === null) {
+            throw new Exception;
+        }
+
+        return $this->configuration;
+    }
+
+    public function hasCoverageFilter(): bool
+    {
+        return $this->coverageFilter !== null;
+    }
+
+    /**
+     * @throws Exception
+     */
+    public function coverageFilter(): array
+    {
+        if ($this->coverageFilter === null) {
+            throw new Exception;
+        }
+
+        return $this->coverageFilter;
+    }
+
+    public function hasCoverageClover(): bool
+    {
+        return $this->coverageClover !== null;
+    }
+
+    /**
+     * @throws Exception
+     */
+    public function coverageClover(): string
+    {
+        if ($this->coverageClover === null) {
+            throw new Exception;
+        }
+
+        return $this->coverageClover;
+    }
+
+    public function hasCoverageCobertura(): bool
+    {
+        return $this->coverageCobertura !== null;
+    }
+
+    /**
+     * @throws Exception
+     */
+    public function coverageCobertura(): string
+    {
+        if ($this->coverageCobertura === null) {
+            throw new Exception;
+        }
+
+        return $this->coverageCobertura;
+    }
+
+    public function hasCoverageCrap4J(): bool
+    {
+        return $this->coverageCrap4J !== null;
+    }
+
+    /**
+     * @throws Exception
+     */
+    public function coverageCrap4J(): string
+    {
+        if ($this->coverageCrap4J === null) {
+            throw new Exception;
+        }
+
+        return $this->coverageCrap4J;
+    }
+
+    public function hasCoverageHtml(): bool
+    {
+        return $this->coverageHtml !== null;
+    }
+
+    /**
+     * @throws Exception
+     */
+    public function coverageHtml(): string
+    {
+        if ($this->coverageHtml === null) {
+            throw new Exception;
+        }
+
+        return $this->coverageHtml;
+    }
+
+    public function hasCoveragePhp(): bool
+    {
+        return $this->coveragePhp !== null;
+    }
+
+    /**
+     * @throws Exception
+     */
+    public function coveragePhp(): string
+    {
+        if ($this->coveragePhp === null) {
+            throw new Exception;
+        }
+
+        return $this->coveragePhp;
+    }
+
+    public function hasCoverageText(): bool
+    {
+        return $this->coverageText !== null;
+    }
+
+    /**
+     * @throws Exception
+     */
+    public function coverageText(): string
+    {
+        if ($this->coverageText === null) {
+            throw new Exception;
+        }
+
+        return $this->coverageText;
+    }
+
+    public function hasCoverageTextShowUncoveredFiles(): bool
+    {
+        return $this->coverageTextShowUncoveredFiles !== null;
+    }
+
+    /**
+     * @throws Exception
+     */
+    public function coverageTextShowUncoveredFiles(): bool
+    {
+        if ($this->coverageTextShowUncoveredFiles === null) {
+            throw new Exception;
+        }
+
+        return $this->coverageTextShowUncoveredFiles;
+    }
+
+    public function hasCoverageTextShowOnlySummary(): bool
+    {
+        return $this->coverageTextShowOnlySummary !== null;
+    }
+
+    /**
+     * @throws Exception
+     */
+    public function coverageTextShowOnlySummary(): bool
+    {
+        if ($this->coverageTextShowOnlySummary === null) {
+            throw new Exception;
+        }
+
+        return $this->coverageTextShowOnlySummary;
+    }
+
+    public function hasCoverageXml(): bool
+    {
+        return $this->coverageXml !== null;
+    }
+
+    /**
+     * @throws Exception
+     */
+    public function coverageXml(): string
+    {
+        if ($this->coverageXml === null) {
+            throw new Exception;
+        }
+
+        return $this->coverageXml;
+    }
+
+    public function hasPathCoverage(): bool
+    {
+        return $this->pathCoverage !== null;
+    }
+
+    /**
+     * @throws Exception
+     */
+    public function pathCoverage(): bool
+    {
+        if ($this->pathCoverage === null) {
+            throw new Exception;
+        }
+
+        return $this->pathCoverage;
+    }
+
+    public function hasCoverageCacheDirectory(): bool
+    {
+        return $this->coverageCacheDirectory !== null;
+    }
+
+    /**
+     * @throws Exception
+     */
+    public function coverageCacheDirectory(): string
+    {
+        if ($this->coverageCacheDirectory === null) {
+            throw new Exception;
+        }
+
+        return $this->coverageCacheDirectory;
+    }
+
+    public function hasWarmCoverageCache(): bool
+    {
+        return $this->warmCoverageCache !== null;
+    }
+
+    /**
+     * @throws Exception
+     */
+    public function warmCoverageCache(): bool
+    {
+        if ($this->warmCoverageCache === null) {
+            throw new Exception;
+        }
+
+        return $this->warmCoverageCache;
+    }
+
+    public function hasDebug(): bool
+    {
+        return $this->debug !== null;
+    }
+
+    /**
+     * @throws Exception
+     */
+    public function debug(): bool
+    {
+        if ($this->debug === null) {
+            throw new Exception;
+        }
+
+        return $this->debug;
+    }
+
+    public function hasDefaultTimeLimit(): bool
+    {
+        return $this->defaultTimeLimit !== null;
+    }
+
+    /**
+     * @throws Exception
+     */
+    public function defaultTimeLimit(): int
+    {
+        if ($this->defaultTimeLimit === null) {
+            throw new Exception;
+        }
+
+        return $this->defaultTimeLimit;
+    }
+
+    public function hasDisableCodeCoverageIgnore(): bool
+    {
+        return $this->disableCodeCoverageIgnore !== null;
+    }
+
+    /**
+     * @throws Exception
+     */
+    public function disableCodeCoverageIgnore(): bool
+    {
+        if ($this->disableCodeCoverageIgnore === null) {
+            throw new Exception;
+        }
+
+        return $this->disableCodeCoverageIgnore;
+    }
+
+    public function hasDisallowTestOutput(): bool
+    {
+        return $this->disallowTestOutput !== null;
+    }
+
+    /**
+     * @throws Exception
+     */
+    public function disallowTestOutput(): bool
+    {
+        if ($this->disallowTestOutput === null) {
+            throw new Exception;
+        }
+
+        return $this->disallowTestOutput;
+    }
+
+    public function hasDisallowTodoAnnotatedTests(): bool
+    {
+        return $this->disallowTodoAnnotatedTests !== null;
+    }
+
+    /**
+     * @throws Exception
+     */
+    public function disallowTodoAnnotatedTests(): bool
+    {
+        if ($this->disallowTodoAnnotatedTests === null) {
+            throw new Exception;
+        }
+
+        return $this->disallowTodoAnnotatedTests;
+    }
+
+    public function hasEnforceTimeLimit(): bool
+    {
+        return $this->enforceTimeLimit !== null;
+    }
+
+    /**
+     * @throws Exception
+     */
+    public function enforceTimeLimit(): bool
+    {
+        if ($this->enforceTimeLimit === null) {
+            throw new Exception;
+        }
+
+        return $this->enforceTimeLimit;
+    }
+
+    public function hasExcludeGroups(): bool
+    {
+        return $this->excludeGroups !== null;
+    }
+
+    /**
+     * @throws Exception
+     */
+    public function excludeGroups(): array
+    {
+        if ($this->excludeGroups === null) {
+            throw new Exception;
+        }
+
+        return $this->excludeGroups;
+    }
+
+    public function hasExecutionOrder(): bool
+    {
+        return $this->executionOrder !== null;
+    }
+
+    /**
+     * @throws Exception
+     */
+    public function executionOrder(): int
+    {
+        if ($this->executionOrder === null) {
+            throw new Exception;
+        }
+
+        return $this->executionOrder;
+    }
+
+    public function hasExecutionOrderDefects(): bool
+    {
+        return $this->executionOrderDefects !== null;
+    }
+
+    /**
+     * @throws Exception
+     */
+    public function executionOrderDefects(): int
+    {
+        if ($this->executionOrderDefects === null) {
+            throw new Exception;
+        }
+
+        return $this->executionOrderDefects;
+    }
+
+    public function hasFailOnEmptyTestSuite(): bool
+    {
+        return $this->failOnEmptyTestSuite !== null;
+    }
+
+    /**
+     * @throws Exception
+     */
+    public function failOnEmptyTestSuite(): bool
+    {
+        if ($this->failOnEmptyTestSuite === null) {
+            throw new Exception;
+        }
+
+        return $this->failOnEmptyTestSuite;
+    }
+
+    public function hasFailOnIncomplete(): bool
+    {
+        return $this->failOnIncomplete !== null;
+    }
+
+    /**
+     * @throws Exception
+     */
+    public function failOnIncomplete(): bool
+    {
+        if ($this->failOnIncomplete === null) {
+            throw new Exception;
+        }
+
+        return $this->failOnIncomplete;
+    }
+
+    public function hasFailOnRisky(): bool
+    {
+        return $this->failOnRisky !== null;
+    }
+
+    /**
+     * @throws Exception
+     */
+    public function failOnRisky(): bool
+    {
+        if ($this->failOnRisky === null) {
+            throw new Exception;
+        }
+
+        return $this->failOnRisky;
+    }
+
+    public function hasFailOnSkipped(): bool
+    {
+        return $this->failOnSkipped !== null;
+    }
+
+    /**
+     * @throws Exception
+     */
+    public function failOnSkipped(): bool
+    {
+        if ($this->failOnSkipped === null) {
+            throw new Exception;
+        }
+
+        return $this->failOnSkipped;
+    }
+
+    public function hasFailOnWarning(): bool
+    {
+        return $this->failOnWarning !== null;
+    }
+
+    /**
+     * @throws Exception
+     */
+    public function failOnWarning(): bool
+    {
+        if ($this->failOnWarning === null) {
+            throw new Exception;
+        }
+
+        return $this->failOnWarning;
+    }
+
+    public function hasFilter(): bool
+    {
+        return $this->filter !== null;
+    }
+
+    /**
+     * @throws Exception
+     */
+    public function filter(): string
+    {
+        if ($this->filter === null) {
+            throw new Exception;
+        }
+
+        return $this->filter;
+    }
+
+    public function hasGenerateConfiguration(): bool
+    {
+        return $this->generateConfiguration !== null;
+    }
+
+    /**
+     * @throws Exception
+     */
+    public function generateConfiguration(): bool
+    {
+        if ($this->generateConfiguration === null) {
+            throw new Exception;
+        }
+
+        return $this->generateConfiguration;
+    }
+
+    public function hasMigrateConfiguration(): bool
+    {
+        return $this->migrateConfiguration !== null;
+    }
+
+    /**
+     * @throws Exception
+     */
+    public function migrateConfiguration(): bool
+    {
+        if ($this->migrateConfiguration === null) {
+            throw new Exception;
+        }
+
+        return $this->migrateConfiguration;
+    }
+
+    public function hasGroups(): bool
+    {
+        return $this->groups !== null;
+    }
+
+    /**
+     * @throws Exception
+     */
+    public function groups(): array
+    {
+        if ($this->groups === null) {
+            throw new Exception;
+        }
+
+        return $this->groups;
+    }
+
+    public function hasTestsCovering(): bool
+    {
+        return $this->testsCovering !== null;
+    }
+
+    /**
+     * @throws Exception
+     */
+    public function testsCovering(): array
+    {
+        if ($this->testsCovering === null) {
+            throw new Exception;
+        }
+
+        return $this->testsCovering;
+    }
+
+    public function hasTestsUsing(): bool
+    {
+        return $this->testsUsing !== null;
+    }
+
+    /**
+     * @throws Exception
+     */
+    public function testsUsing(): array
+    {
+        if ($this->testsUsing === null) {
+            throw new Exception;
+        }
+
+        return $this->testsUsing;
+    }
+
+    public function hasHelp(): bool
+    {
+        return $this->help !== null;
+    }
+
+    /**
+     * @throws Exception
+     */
+    public function help(): bool
+    {
+        if ($this->help === null) {
+            throw new Exception;
+        }
+
+        return $this->help;
+    }
+
+    public function hasIncludePath(): bool
+    {
+        return $this->includePath !== null;
+    }
+
+    /**
+     * @throws Exception
+     */
+    public function includePath(): string
+    {
+        if ($this->includePath === null) {
+            throw new Exception;
+        }
+
+        return $this->includePath;
+    }
+
+    public function hasIniSettings(): bool
+    {
+        return $this->iniSettings !== null;
+    }
+
+    /**
+     * @throws Exception
+     */
+    public function iniSettings(): array
+    {
+        if ($this->iniSettings === null) {
+            throw new Exception;
+        }
+
+        return $this->iniSettings;
+    }
+
+    public function hasJunitLogfile(): bool
+    {
+        return $this->junitLogfile !== null;
+    }
+
+    /**
+     * @throws Exception
+     */
+    public function junitLogfile(): string
+    {
+        if ($this->junitLogfile === null) {
+            throw new Exception;
+        }
+
+        return $this->junitLogfile;
+    }
+
+    public function hasListGroups(): bool
+    {
+        return $this->listGroups !== null;
+    }
+
+    /**
+     * @throws Exception
+     */
+    public function listGroups(): bool
+    {
+        if ($this->listGroups === null) {
+            throw new Exception;
+        }
+
+        return $this->listGroups;
+    }
+
+    public function hasListSuites(): bool
+    {
+        return $this->listSuites !== null;
+    }
+
+    /**
+     * @throws Exception
+     */
+    public function listSuites(): bool
+    {
+        if ($this->listSuites === null) {
+            throw new Exception;
+        }
+
+        return $this->listSuites;
+    }
+
+    public function hasListTests(): bool
+    {
+        return $this->listTests !== null;
+    }
+
+    /**
+     * @throws Exception
+     */
+    public function listTests(): bool
+    {
+        if ($this->listTests === null) {
+            throw new Exception;
+        }
+
+        return $this->listTests;
+    }
+
+    public function hasListTestsXml(): bool
+    {
+        return $this->listTestsXml !== null;
+    }
+
+    /**
+     * @throws Exception
+     */
+    public function listTestsXml(): string
+    {
+        if ($this->listTestsXml === null) {
+            throw new Exception;
+        }
+
+        return $this->listTestsXml;
+    }
+
+    public function hasLoader(): bool
+    {
+        return $this->loader !== null;
+    }
+
+    /**
+     * @throws Exception
+     */
+    public function loader(): string
+    {
+        if ($this->loader === null) {
+            throw new Exception;
+        }
+
+        return $this->loader;
+    }
+
+    public function hasNoCoverage(): bool
+    {
+        return $this->noCoverage !== null;
+    }
+
+    /**
+     * @throws Exception
+     */
+    public function noCoverage(): bool
+    {
+        if ($this->noCoverage === null) {
+            throw new Exception;
+        }
+
+        return $this->noCoverage;
+    }
+
+    public function hasNoExtensions(): bool
+    {
+        return $this->noExtensions !== null;
+    }
+
+    /**
+     * @throws Exception
+     */
+    public function noExtensions(): bool
+    {
+        if ($this->noExtensions === null) {
+            throw new Exception;
+        }
+
+        return $this->noExtensions;
+    }
+
+    public function hasExtensions(): bool
+    {
+        return $this->extensions !== null;
+    }
+
+    /**
+     * @throws Exception
+     */
+    public function extensions(): array
+    {
+        if ($this->extensions === null) {
+            throw new Exception;
+        }
+
+        return $this->extensions;
+    }
+
+    public function hasUnavailableExtensions(): bool
+    {
+        return $this->unavailableExtensions !== null;
+    }
+
+    /**
+     * @throws Exception
+     */
+    public function unavailableExtensions(): array
+    {
+        if ($this->unavailableExtensions === null) {
+            throw new Exception;
+        }
+
+        return $this->unavailableExtensions;
+    }
+
+    public function hasNoInteraction(): bool
+    {
+        return $this->noInteraction !== null;
+    }
+
+    /**
+     * @throws Exception
+     */
+    public function noInteraction(): bool
+    {
+        if ($this->noInteraction === null) {
+            throw new Exception;
+        }
+
+        return $this->noInteraction;
+    }
+
+    public function hasNoLogging(): bool
+    {
+        return $this->noLogging !== null;
+    }
+
+    /**
+     * @throws Exception
+     */
+    public function noLogging(): bool
+    {
+        if ($this->noLogging === null) {
+            throw new Exception;
+        }
+
+        return $this->noLogging;
+    }
+
+    public function hasPrinter(): bool
+    {
+        return $this->printer !== null;
+    }
+
+    /**
+     * @throws Exception
+     */
+    public function printer(): string
+    {
+        if ($this->printer === null) {
+            throw new Exception;
+        }
+
+        return $this->printer;
+    }
+
+    public function hasProcessIsolation(): bool
+    {
+        return $this->processIsolation !== null;
+    }
+
+    /**
+     * @throws Exception
+     */
+    public function processIsolation(): bool
+    {
+        if ($this->processIsolation === null) {
+            throw new Exception;
+        }
+
+        return $this->processIsolation;
+    }
+
+    public function hasRandomOrderSeed(): bool
+    {
+        return $this->randomOrderSeed !== null;
+    }
+
+    /**
+     * @throws Exception
+     */
+    public function randomOrderSeed(): int
+    {
+        if ($this->randomOrderSeed === null) {
+            throw new Exception;
+        }
+
+        return $this->randomOrderSeed;
+    }
+
+    public function hasRepeat(): bool
+    {
+        return $this->repeat !== null;
+    }
+
+    /**
+     * @throws Exception
+     */
+    public function repeat(): int
+    {
+        if ($this->repeat === null) {
+            throw new Exception;
+        }
+
+        return $this->repeat;
+    }
+
+    public function hasReportUselessTests(): bool
+    {
+        return $this->reportUselessTests !== null;
+    }
+
+    /**
+     * @throws Exception
+     */
+    public function reportUselessTests(): bool
+    {
+        if ($this->reportUselessTests === null) {
+            throw new Exception;
+        }
+
+        return $this->reportUselessTests;
+    }
+
+    public function hasResolveDependencies(): bool
+    {
+        return $this->resolveDependencies !== null;
+    }
+
+    /**
+     * @throws Exception
+     */
+    public function resolveDependencies(): bool
+    {
+        if ($this->resolveDependencies === null) {
+            throw new Exception;
+        }
+
+        return $this->resolveDependencies;
+    }
+
+    public function hasReverseList(): bool
+    {
+        return $this->reverseList !== null;
+    }
+
+    /**
+     * @throws Exception
+     */
+    public function reverseList(): bool
+    {
+        if ($this->reverseList === null) {
+            throw new Exception;
+        }
+
+        return $this->reverseList;
+    }
+
+    public function hasStderr(): bool
+    {
+        return $this->stderr !== null;
+    }
+
+    /**
+     * @throws Exception
+     */
+    public function stderr(): bool
+    {
+        if ($this->stderr === null) {
+            throw new Exception;
+        }
+
+        return $this->stderr;
+    }
+
+    public function hasStrictCoverage(): bool
+    {
+        return $this->strictCoverage !== null;
+    }
+
+    /**
+     * @throws Exception
+     */
+    public function strictCoverage(): bool
+    {
+        if ($this->strictCoverage === null) {
+            throw new Exception;
+        }
+
+        return $this->strictCoverage;
+    }
+
+    public function hasStopOnDefect(): bool
+    {
+        return $this->stopOnDefect !== null;
+    }
+
+    /**
+     * @throws Exception
+     */
+    public function stopOnDefect(): bool
+    {
+        if ($this->stopOnDefect === null) {
+            throw new Exception;
+        }
+
+        return $this->stopOnDefect;
+    }
+
+    public function hasStopOnError(): bool
+    {
+        return $this->stopOnError !== null;
+    }
+
+    /**
+     * @throws Exception
+     */
+    public function stopOnError(): bool
+    {
+        if ($this->stopOnError === null) {
+            throw new Exception;
+        }
+
+        return $this->stopOnError;
+    }
+
+    public function hasStopOnFailure(): bool
+    {
+        return $this->stopOnFailure !== null;
+    }
+
+    /**
+     * @throws Exception
+     */
+    public function stopOnFailure(): bool
+    {
+        if ($this->stopOnFailure === null) {
+            throw new Exception;
+        }
+
+        return $this->stopOnFailure;
+    }
+
+    public function hasStopOnIncomplete(): bool
+    {
+        return $this->stopOnIncomplete !== null;
+    }
+
+    /**
+     * @throws Exception
+     */
+    public function stopOnIncomplete(): bool
+    {
+        if ($this->stopOnIncomplete === null) {
+            throw new Exception;
+        }
+
+        return $this->stopOnIncomplete;
+    }
+
+    public function hasStopOnRisky(): bool
+    {
+        return $this->stopOnRisky !== null;
+    }
+
+    /**
+     * @throws Exception
+     */
+    public function stopOnRisky(): bool
+    {
+        if ($this->stopOnRisky === null) {
+            throw new Exception;
+        }
+
+        return $this->stopOnRisky;
+    }
+
+    public function hasStopOnSkipped(): bool
+    {
+        return $this->stopOnSkipped !== null;
+    }
+
+    /**
+     * @throws Exception
+     */
+    public function stopOnSkipped(): bool
+    {
+        if ($this->stopOnSkipped === null) {
+            throw new Exception;
+        }
+
+        return $this->stopOnSkipped;
+    }
+
+    public function hasStopOnWarning(): bool
+    {
+        return $this->stopOnWarning !== null;
+    }
+
+    /**
+     * @throws Exception
+     */
+    public function stopOnWarning(): bool
+    {
+        if ($this->stopOnWarning === null) {
+            throw new Exception;
+        }
+
+        return $this->stopOnWarning;
+    }
+
+    public function hasTeamcityLogfile(): bool
+    {
+        return $this->teamcityLogfile !== null;
+    }
+
+    /**
+     * @throws Exception
+     */
+    public function teamcityLogfile(): string
+    {
+        if ($this->teamcityLogfile === null) {
+            throw new Exception;
+        }
+
+        return $this->teamcityLogfile;
+    }
+
+    public function hasTestdoxExcludeGroups(): bool
+    {
+        return $this->testdoxExcludeGroups !== null;
+    }
+
+    /**
+     * @throws Exception
+     */
+    public function testdoxExcludeGroups(): array
+    {
+        if ($this->testdoxExcludeGroups === null) {
+            throw new Exception;
+        }
+
+        return $this->testdoxExcludeGroups;
+    }
+
+    public function hasTestdoxGroups(): bool
+    {
+        return $this->testdoxGroups !== null;
+    }
+
+    /**
+     * @throws Exception
+     */
+    public function testdoxGroups(): array
+    {
+        if ($this->testdoxGroups === null) {
+            throw new Exception;
+        }
+
+        return $this->testdoxGroups;
+    }
+
+    public function hasTestdoxHtmlFile(): bool
+    {
+        return $this->testdoxHtmlFile !== null;
+    }
+
+    /**
+     * @throws Exception
+     */
+    public function testdoxHtmlFile(): string
+    {
+        if ($this->testdoxHtmlFile === null) {
+            throw new Exception;
+        }
+
+        return $this->testdoxHtmlFile;
+    }
+
+    public function hasTestdoxTextFile(): bool
+    {
+        return $this->testdoxTextFile !== null;
+    }
+
+    /**
+     * @throws Exception
+     */
+    public function testdoxTextFile(): string
+    {
+        if ($this->testdoxTextFile === null) {
+            throw new Exception;
+        }
+
+        return $this->testdoxTextFile;
+    }
+
+    public function hasTestdoxXmlFile(): bool
+    {
+        return $this->testdoxXmlFile !== null;
+    }
+
+    /**
+     * @throws Exception
+     */
+    public function testdoxXmlFile(): string
+    {
+        if ($this->testdoxXmlFile === null) {
+            throw new Exception;
+        }
+
+        return $this->testdoxXmlFile;
+    }
+
+    public function hasTestSuffixes(): bool
+    {
+        return $this->testSuffixes !== null;
+    }
+
+    /**
+     * @throws Exception
+     */
+    public function testSuffixes(): array
+    {
+        if ($this->testSuffixes === null) {
+            throw new Exception;
+        }
+
+        return $this->testSuffixes;
+    }
+
+    public function hasTestSuite(): bool
+    {
+        return $this->testSuite !== null;
+    }
+
+    /**
+     * @throws Exception
+     */
+    public function testSuite(): string
+    {
+        if ($this->testSuite === null) {
+            throw new Exception;
+        }
+
+        return $this->testSuite;
+    }
+
+    public function unrecognizedOptions(): array
+    {
+        return $this->unrecognizedOptions;
+    }
+
+    public function hasUnrecognizedOrderBy(): bool
+    {
+        return $this->unrecognizedOrderBy !== null;
+    }
+
+    /**
+     * @throws Exception
+     */
+    public function unrecognizedOrderBy(): string
+    {
+        if ($this->unrecognizedOrderBy === null) {
+            throw new Exception;
+        }
+
+        return $this->unrecognizedOrderBy;
+    }
+
+    public function hasUseDefaultConfiguration(): bool
+    {
+        return $this->useDefaultConfiguration !== null;
+    }
+
+    /**
+     * @throws Exception
+     */
+    public function useDefaultConfiguration(): bool
+    {
+        if ($this->useDefaultConfiguration === null) {
+            throw new Exception;
+        }
+
+        return $this->useDefaultConfiguration;
+    }
+
+    public function hasVerbose(): bool
+    {
+        return $this->verbose !== null;
+    }
+
+    /**
+     * @throws Exception
+     */
+    public function verbose(): bool
+    {
+        if ($this->verbose === null) {
+            throw new Exception;
+        }
+
+        return $this->verbose;
+    }
+
+    public function hasVersion(): bool
+    {
+        return $this->version !== null;
+    }
+
+    /**
+     * @throws Exception
+     */
+    public function version(): bool
+    {
+        if ($this->version === null) {
+            throw new Exception;
+        }
+
+        return $this->version;
+    }
+
+    public function hasXdebugFilterFile(): bool
+    {
+        return $this->xdebugFilterFile !== null;
+    }
+
+    /**
+     * @throws Exception
+     */
+    public function xdebugFilterFile(): string
+    {
+        if ($this->xdebugFilterFile === null) {
+            throw new Exception;
+        }
+
+        return $this->xdebugFilterFile;
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/TextUI/CliArguments/Exception.php b/vendor/phpunit/phpunit/src/TextUI/CliArguments/Exception.php
new file mode 100644
index 0000000000000000000000000000000000000000..dd5536eaa5023b9abbb8ca776c7aaf69a6fcb412
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/TextUI/CliArguments/Exception.php
@@ -0,0 +1,19 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\TextUI\CliArguments;
+
+use RuntimeException;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class Exception extends RuntimeException implements \PHPUnit\Exception
+{
+}
diff --git a/vendor/phpunit/phpunit/src/TextUI/CliArguments/Mapper.php b/vendor/phpunit/phpunit/src/TextUI/CliArguments/Mapper.php
new file mode 100644
index 0000000000000000000000000000000000000000..9ceb8ab472832c32915dd4c54792fd7ef4e3e2a1
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/TextUI/CliArguments/Mapper.php
@@ -0,0 +1,365 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\TextUI\CliArguments;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class Mapper
+{
+    /**
+     * @throws Exception
+     */
+    public function mapToLegacyArray(Configuration $arguments): array
+    {
+        $result = [
+            'extensions'              => [],
+            'listGroups'              => false,
+            'listSuites'              => false,
+            'listTests'               => false,
+            'listTestsXml'            => false,
+            'loader'                  => null,
+            'useDefaultConfiguration' => true,
+            'loadedExtensions'        => [],
+            'unavailableExtensions'   => [],
+            'notLoadedExtensions'     => [],
+        ];
+
+        if ($arguments->hasColors()) {
+            $result['colors'] = $arguments->colors();
+        }
+
+        if ($arguments->hasBootstrap()) {
+            $result['bootstrap'] = $arguments->bootstrap();
+        }
+
+        if ($arguments->hasCacheResult()) {
+            $result['cacheResult'] = $arguments->cacheResult();
+        }
+
+        if ($arguments->hasCacheResultFile()) {
+            $result['cacheResultFile'] = $arguments->cacheResultFile();
+        }
+
+        if ($arguments->hasColumns()) {
+            $result['columns'] = $arguments->columns();
+        }
+
+        if ($arguments->hasConfiguration()) {
+            $result['configuration'] = $arguments->configuration();
+        }
+
+        if ($arguments->hasCoverageCacheDirectory()) {
+            $result['coverageCacheDirectory'] = $arguments->coverageCacheDirectory();
+        }
+
+        if ($arguments->hasWarmCoverageCache()) {
+            $result['warmCoverageCache'] = $arguments->warmCoverageCache();
+        }
+
+        if ($arguments->hasCoverageClover()) {
+            $result['coverageClover'] = $arguments->coverageClover();
+        }
+
+        if ($arguments->hasCoverageCobertura()) {
+            $result['coverageCobertura'] = $arguments->coverageCobertura();
+        }
+
+        if ($arguments->hasCoverageCrap4J()) {
+            $result['coverageCrap4J'] = $arguments->coverageCrap4J();
+        }
+
+        if ($arguments->hasCoverageHtml()) {
+            $result['coverageHtml'] = $arguments->coverageHtml();
+        }
+
+        if ($arguments->hasCoveragePhp()) {
+            $result['coveragePHP'] = $arguments->coveragePhp();
+        }
+
+        if ($arguments->hasCoverageText()) {
+            $result['coverageText'] = $arguments->coverageText();
+        }
+
+        if ($arguments->hasCoverageTextShowUncoveredFiles()) {
+            $result['coverageTextShowUncoveredFiles'] = $arguments->hasCoverageTextShowUncoveredFiles();
+        }
+
+        if ($arguments->hasCoverageTextShowOnlySummary()) {
+            $result['coverageTextShowOnlySummary'] = $arguments->coverageTextShowOnlySummary();
+        }
+
+        if ($arguments->hasCoverageXml()) {
+            $result['coverageXml'] = $arguments->coverageXml();
+        }
+
+        if ($arguments->hasPathCoverage()) {
+            $result['pathCoverage'] = $arguments->pathCoverage();
+        }
+
+        if ($arguments->hasDebug()) {
+            $result['debug'] = $arguments->debug();
+        }
+
+        if ($arguments->hasHelp()) {
+            $result['help'] = $arguments->help();
+        }
+
+        if ($arguments->hasFilter()) {
+            $result['filter'] = $arguments->filter();
+        }
+
+        if ($arguments->hasTestSuite()) {
+            $result['testsuite'] = $arguments->testSuite();
+        }
+
+        if ($arguments->hasGroups()) {
+            $result['groups'] = $arguments->groups();
+        }
+
+        if ($arguments->hasExcludeGroups()) {
+            $result['excludeGroups'] = $arguments->excludeGroups();
+        }
+
+        if ($arguments->hasTestsCovering()) {
+            $result['testsCovering'] = $arguments->testsCovering();
+        }
+
+        if ($arguments->hasTestsUsing()) {
+            $result['testsUsing'] = $arguments->testsUsing();
+        }
+
+        if ($arguments->hasTestSuffixes()) {
+            $result['testSuffixes'] = $arguments->testSuffixes();
+        }
+
+        if ($arguments->hasIncludePath()) {
+            $result['includePath'] = $arguments->includePath();
+        }
+
+        if ($arguments->hasListGroups()) {
+            $result['listGroups'] = $arguments->listGroups();
+        }
+
+        if ($arguments->hasListSuites()) {
+            $result['listSuites'] = $arguments->listSuites();
+        }
+
+        if ($arguments->hasListTests()) {
+            $result['listTests'] = $arguments->listTests();
+        }
+
+        if ($arguments->hasListTestsXml()) {
+            $result['listTestsXml'] = $arguments->listTestsXml();
+        }
+
+        if ($arguments->hasPrinter()) {
+            $result['printer'] = $arguments->printer();
+        }
+
+        if ($arguments->hasLoader()) {
+            $result['loader'] = $arguments->loader();
+        }
+
+        if ($arguments->hasJunitLogfile()) {
+            $result['junitLogfile'] = $arguments->junitLogfile();
+        }
+
+        if ($arguments->hasTeamcityLogfile()) {
+            $result['teamcityLogfile'] = $arguments->teamcityLogfile();
+        }
+
+        if ($arguments->hasExecutionOrder()) {
+            $result['executionOrder'] = $arguments->executionOrder();
+        }
+
+        if ($arguments->hasExecutionOrderDefects()) {
+            $result['executionOrderDefects'] = $arguments->executionOrderDefects();
+        }
+
+        if ($arguments->hasExtensions()) {
+            $result['extensions'] = $arguments->extensions();
+        }
+
+        if ($arguments->hasUnavailableExtensions()) {
+            $result['unavailableExtensions'] = $arguments->unavailableExtensions();
+        }
+
+        if ($arguments->hasResolveDependencies()) {
+            $result['resolveDependencies'] = $arguments->resolveDependencies();
+        }
+
+        if ($arguments->hasProcessIsolation()) {
+            $result['processIsolation'] = $arguments->processIsolation();
+        }
+
+        if ($arguments->hasRepeat()) {
+            $result['repeat'] = $arguments->repeat();
+        }
+
+        if ($arguments->hasStderr()) {
+            $result['stderr'] = $arguments->stderr();
+        }
+
+        if ($arguments->hasStopOnDefect()) {
+            $result['stopOnDefect'] = $arguments->stopOnDefect();
+        }
+
+        if ($arguments->hasStopOnError()) {
+            $result['stopOnError'] = $arguments->stopOnError();
+        }
+
+        if ($arguments->hasStopOnFailure()) {
+            $result['stopOnFailure'] = $arguments->stopOnFailure();
+        }
+
+        if ($arguments->hasStopOnWarning()) {
+            $result['stopOnWarning'] = $arguments->stopOnWarning();
+        }
+
+        if ($arguments->hasStopOnIncomplete()) {
+            $result['stopOnIncomplete'] = $arguments->stopOnIncomplete();
+        }
+
+        if ($arguments->hasStopOnRisky()) {
+            $result['stopOnRisky'] = $arguments->stopOnRisky();
+        }
+
+        if ($arguments->hasStopOnSkipped()) {
+            $result['stopOnSkipped'] = $arguments->stopOnSkipped();
+        }
+
+        if ($arguments->hasFailOnEmptyTestSuite()) {
+            $result['failOnEmptyTestSuite'] = $arguments->failOnEmptyTestSuite();
+        }
+
+        if ($arguments->hasFailOnIncomplete()) {
+            $result['failOnIncomplete'] = $arguments->failOnIncomplete();
+        }
+
+        if ($arguments->hasFailOnRisky()) {
+            $result['failOnRisky'] = $arguments->failOnRisky();
+        }
+
+        if ($arguments->hasFailOnSkipped()) {
+            $result['failOnSkipped'] = $arguments->failOnSkipped();
+        }
+
+        if ($arguments->hasFailOnWarning()) {
+            $result['failOnWarning'] = $arguments->failOnWarning();
+        }
+
+        if ($arguments->hasTestdoxGroups()) {
+            $result['testdoxGroups'] = $arguments->testdoxGroups();
+        }
+
+        if ($arguments->hasTestdoxExcludeGroups()) {
+            $result['testdoxExcludeGroups'] = $arguments->testdoxExcludeGroups();
+        }
+
+        if ($arguments->hasTestdoxHtmlFile()) {
+            $result['testdoxHTMLFile'] = $arguments->testdoxHtmlFile();
+        }
+
+        if ($arguments->hasTestdoxTextFile()) {
+            $result['testdoxTextFile'] = $arguments->testdoxTextFile();
+        }
+
+        if ($arguments->hasTestdoxXmlFile()) {
+            $result['testdoxXMLFile'] = $arguments->testdoxXmlFile();
+        }
+
+        if ($arguments->hasUseDefaultConfiguration()) {
+            $result['useDefaultConfiguration'] = $arguments->useDefaultConfiguration();
+        }
+
+        if ($arguments->hasNoExtensions()) {
+            $result['noExtensions'] = $arguments->noExtensions();
+        }
+
+        if ($arguments->hasNoCoverage()) {
+            $result['noCoverage'] = $arguments->noCoverage();
+        }
+
+        if ($arguments->hasNoLogging()) {
+            $result['noLogging'] = $arguments->noLogging();
+        }
+
+        if ($arguments->hasNoInteraction()) {
+            $result['noInteraction'] = $arguments->noInteraction();
+        }
+
+        if ($arguments->hasBackupGlobals()) {
+            $result['backupGlobals'] = $arguments->backupGlobals();
+        }
+
+        if ($arguments->hasBackupStaticAttributes()) {
+            $result['backupStaticAttributes'] = $arguments->backupStaticAttributes();
+        }
+
+        if ($arguments->hasVerbose()) {
+            $result['verbose'] = $arguments->verbose();
+        }
+
+        if ($arguments->hasReportUselessTests()) {
+            $result['reportUselessTests'] = $arguments->reportUselessTests();
+        }
+
+        if ($arguments->hasStrictCoverage()) {
+            $result['strictCoverage'] = $arguments->strictCoverage();
+        }
+
+        if ($arguments->hasDisableCodeCoverageIgnore()) {
+            $result['disableCodeCoverageIgnore'] = $arguments->disableCodeCoverageIgnore();
+        }
+
+        if ($arguments->hasBeStrictAboutChangesToGlobalState()) {
+            $result['beStrictAboutChangesToGlobalState'] = $arguments->beStrictAboutChangesToGlobalState();
+        }
+
+        if ($arguments->hasDisallowTestOutput()) {
+            $result['disallowTestOutput'] = $arguments->disallowTestOutput();
+        }
+
+        if ($arguments->hasBeStrictAboutResourceUsageDuringSmallTests()) {
+            $result['beStrictAboutResourceUsageDuringSmallTests'] = $arguments->beStrictAboutResourceUsageDuringSmallTests();
+        }
+
+        if ($arguments->hasDefaultTimeLimit()) {
+            $result['defaultTimeLimit'] = $arguments->defaultTimeLimit();
+        }
+
+        if ($arguments->hasEnforceTimeLimit()) {
+            $result['enforceTimeLimit'] = $arguments->enforceTimeLimit();
+        }
+
+        if ($arguments->hasDisallowTodoAnnotatedTests()) {
+            $result['disallowTodoAnnotatedTests'] = $arguments->disallowTodoAnnotatedTests();
+        }
+
+        if ($arguments->hasReverseList()) {
+            $result['reverseList'] = $arguments->reverseList();
+        }
+
+        if ($arguments->hasCoverageFilter()) {
+            $result['coverageFilter'] = $arguments->coverageFilter();
+        }
+
+        if ($arguments->hasRandomOrderSeed()) {
+            $result['randomOrderSeed'] = $arguments->randomOrderSeed();
+        }
+
+        if ($arguments->hasXdebugFilterFile()) {
+            $result['xdebugFilterFile'] = $arguments->xdebugFilterFile();
+        }
+
+        return $result;
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/TextUI/Command.php b/vendor/phpunit/phpunit/src/TextUI/Command.php
new file mode 100644
index 0000000000000000000000000000000000000000..e5dd7a01d0844fbc139fdf44c51365262af8c054
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/TextUI/Command.php
@@ -0,0 +1,903 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\TextUI;
+
+use const PATH_SEPARATOR;
+use const PHP_EOL;
+use const STDIN;
+use function array_keys;
+use function assert;
+use function class_exists;
+use function copy;
+use function extension_loaded;
+use function fgets;
+use function file_get_contents;
+use function file_put_contents;
+use function get_class;
+use function getcwd;
+use function ini_get;
+use function ini_set;
+use function is_callable;
+use function is_dir;
+use function is_file;
+use function is_string;
+use function printf;
+use function realpath;
+use function sort;
+use function sprintf;
+use function stream_resolve_include_path;
+use function strpos;
+use function trim;
+use function version_compare;
+use PHPUnit\Framework\TestSuite;
+use PHPUnit\Runner\Extension\PharLoader;
+use PHPUnit\Runner\StandardTestSuiteLoader;
+use PHPUnit\Runner\TestSuiteLoader;
+use PHPUnit\Runner\Version;
+use PHPUnit\TextUI\CliArguments\Builder;
+use PHPUnit\TextUI\CliArguments\Configuration;
+use PHPUnit\TextUI\CliArguments\Exception as ArgumentsException;
+use PHPUnit\TextUI\CliArguments\Mapper;
+use PHPUnit\TextUI\XmlConfiguration\CodeCoverage\FilterMapper;
+use PHPUnit\TextUI\XmlConfiguration\Generator;
+use PHPUnit\TextUI\XmlConfiguration\Loader;
+use PHPUnit\TextUI\XmlConfiguration\Migrator;
+use PHPUnit\TextUI\XmlConfiguration\PhpHandler;
+use PHPUnit\Util\FileLoader;
+use PHPUnit\Util\Filesystem;
+use PHPUnit\Util\Printer;
+use PHPUnit\Util\TextTestListRenderer;
+use PHPUnit\Util\Xml\SchemaDetector;
+use PHPUnit\Util\XmlTestListRenderer;
+use ReflectionClass;
+use SebastianBergmann\CodeCoverage\Filter;
+use SebastianBergmann\CodeCoverage\StaticAnalysis\CacheWarmer;
+use SebastianBergmann\Timer\Timer;
+use Throwable;
+
+/**
+ * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+ */
+class Command
+{
+    /**
+     * @var array<string,mixed>
+     */
+    protected $arguments = [];
+
+    /**
+     * @var array<string,mixed>
+     */
+    protected $longOptions = [];
+
+    /**
+     * @var bool
+     */
+    private $versionStringPrinted = false;
+
+    /**
+     * @psalm-var list<string>
+     */
+    private $warnings = [];
+
+    /**
+     * @throws Exception
+     */
+    public static function main(bool $exit = true): int
+    {
+        try {
+            return (new static)->run($_SERVER['argv'], $exit);
+        } catch (Throwable $t) {
+            throw new RuntimeException(
+                $t->getMessage(),
+                (int) $t->getCode(),
+                $t
+            );
+        }
+    }
+
+    /**
+     * @throws Exception
+     */
+    public function run(array $argv, bool $exit = true): int
+    {
+        $this->handleArguments($argv);
+
+        $runner = $this->createRunner();
+
+        if ($this->arguments['test'] instanceof TestSuite) {
+            $suite = $this->arguments['test'];
+        } else {
+            $suite = $runner->getTest(
+                $this->arguments['test'],
+                $this->arguments['testSuffixes']
+            );
+        }
+
+        if ($this->arguments['listGroups']) {
+            return $this->handleListGroups($suite, $exit);
+        }
+
+        if ($this->arguments['listSuites']) {
+            return $this->handleListSuites($exit);
+        }
+
+        if ($this->arguments['listTests']) {
+            return $this->handleListTests($suite, $exit);
+        }
+
+        if ($this->arguments['listTestsXml']) {
+            return $this->handleListTestsXml($suite, $this->arguments['listTestsXml'], $exit);
+        }
+
+        unset($this->arguments['test'], $this->arguments['testFile']);
+
+        try {
+            $result = $runner->run($suite, $this->arguments, $this->warnings, $exit);
+        } catch (Throwable $t) {
+            print $t->getMessage() . PHP_EOL;
+        }
+
+        $return = TestRunner::FAILURE_EXIT;
+
+        if (isset($result) && $result->wasSuccessful()) {
+            $return = TestRunner::SUCCESS_EXIT;
+        } elseif (!isset($result) || $result->errorCount() > 0) {
+            $return = TestRunner::EXCEPTION_EXIT;
+        }
+
+        if ($exit) {
+            exit($return);
+        }
+
+        return $return;
+    }
+
+    /**
+     * Create a TestRunner, override in subclasses.
+     */
+    protected function createRunner(): TestRunner
+    {
+        return new TestRunner($this->arguments['loader']);
+    }
+
+    /**
+     * Handles the command-line arguments.
+     *
+     * A child class of PHPUnit\TextUI\Command can hook into the argument
+     * parsing by adding the switch(es) to the $longOptions array and point to a
+     * callback method that handles the switch(es) in the child class like this
+     *
+     * <code>
+     * <?php
+     * class MyCommand extends PHPUnit\TextUI\Command
+     * {
+     *     public function __construct()
+     *     {
+     *         // my-switch won't accept a value, it's an on/off
+     *         $this->longOptions['my-switch'] = 'myHandler';
+     *         // my-secondswitch will accept a value - note the equals sign
+     *         $this->longOptions['my-secondswitch='] = 'myOtherHandler';
+     *     }
+     *
+     *     // --my-switch  -> myHandler()
+     *     protected function myHandler()
+     *     {
+     *     }
+     *
+     *     // --my-secondswitch foo -> myOtherHandler('foo')
+     *     protected function myOtherHandler ($value)
+     *     {
+     *     }
+     *
+     *     // You will also need this - the static keyword in the
+     *     // PHPUnit\TextUI\Command will mean that it'll be
+     *     // PHPUnit\TextUI\Command that gets instantiated,
+     *     // not MyCommand
+     *     public static function main($exit = true)
+     *     {
+     *         $command = new static;
+     *
+     *         return $command->run($_SERVER['argv'], $exit);
+     *     }
+     *
+     * }
+     * </code>
+     *
+     * @throws Exception
+     */
+    protected function handleArguments(array $argv): void
+    {
+        try {
+            $arguments = (new Builder)->fromParameters($argv, array_keys($this->longOptions));
+        } catch (ArgumentsException $e) {
+            $this->exitWithErrorMessage($e->getMessage());
+        }
+
+        assert(isset($arguments) && $arguments instanceof Configuration);
+
+        if ($arguments->hasGenerateConfiguration() && $arguments->generateConfiguration()) {
+            $this->generateConfiguration();
+        }
+
+        if ($arguments->hasAtLeastVersion()) {
+            if (version_compare(Version::id(), $arguments->atLeastVersion(), '>=')) {
+                exit(TestRunner::SUCCESS_EXIT);
+            }
+
+            exit(TestRunner::FAILURE_EXIT);
+        }
+
+        if ($arguments->hasVersion() && $arguments->version()) {
+            $this->printVersionString();
+
+            exit(TestRunner::SUCCESS_EXIT);
+        }
+
+        if ($arguments->hasCheckVersion() && $arguments->checkVersion()) {
+            $this->handleVersionCheck();
+        }
+
+        if ($arguments->hasHelp()) {
+            $this->showHelp();
+
+            exit(TestRunner::SUCCESS_EXIT);
+        }
+
+        if ($arguments->hasUnrecognizedOrderBy()) {
+            $this->exitWithErrorMessage(
+                sprintf(
+                    'unrecognized --order-by option: %s',
+                    $arguments->unrecognizedOrderBy()
+                )
+            );
+        }
+
+        if ($arguments->hasIniSettings()) {
+            foreach ($arguments->iniSettings() as $name => $value) {
+                ini_set($name, $value);
+            }
+        }
+
+        if ($arguments->hasIncludePath()) {
+            ini_set(
+                'include_path',
+                $arguments->includePath() . PATH_SEPARATOR . ini_get('include_path')
+            );
+        }
+
+        $this->arguments = (new Mapper)->mapToLegacyArray($arguments);
+
+        $this->handleCustomOptions($arguments->unrecognizedOptions());
+        $this->handleCustomTestSuite();
+
+        if (!isset($this->arguments['testSuffixes'])) {
+            $this->arguments['testSuffixes'] = ['Test.php', '.phpt'];
+        }
+
+        if (!isset($this->arguments['test']) && $arguments->hasArgument()) {
+            $this->arguments['test'] = realpath($arguments->argument());
+
+            if ($this->arguments['test'] === false) {
+                $this->exitWithErrorMessage(
+                    sprintf(
+                        'Cannot open file "%s".',
+                        $arguments->argument()
+                    )
+                );
+            }
+        }
+
+        if ($this->arguments['loader'] !== null) {
+            $this->arguments['loader'] = $this->handleLoader($this->arguments['loader']);
+        }
+
+        if (isset($this->arguments['configuration'])) {
+            if (is_dir($this->arguments['configuration'])) {
+                $candidate = $this->configurationFileInDirectory($this->arguments['configuration']);
+
+                if ($candidate !== null) {
+                    $this->arguments['configuration'] = $candidate;
+                }
+            }
+        } elseif ($this->arguments['useDefaultConfiguration']) {
+            $candidate = $this->configurationFileInDirectory(getcwd());
+
+            if ($candidate !== null) {
+                $this->arguments['configuration'] = $candidate;
+            }
+        }
+
+        if ($arguments->hasMigrateConfiguration() && $arguments->migrateConfiguration()) {
+            if (!isset($this->arguments['configuration'])) {
+                print 'No configuration file found to migrate.' . PHP_EOL;
+
+                exit(TestRunner::EXCEPTION_EXIT);
+            }
+
+            $this->migrateConfiguration(realpath($this->arguments['configuration']));
+        }
+
+        if (isset($this->arguments['configuration'])) {
+            try {
+                $this->arguments['configurationObject'] = (new Loader)->load($this->arguments['configuration']);
+            } catch (Throwable $e) {
+                print $e->getMessage() . PHP_EOL;
+
+                exit(TestRunner::FAILURE_EXIT);
+            }
+
+            $phpunitConfiguration = $this->arguments['configurationObject']->phpunit();
+
+            (new PhpHandler)->handle($this->arguments['configurationObject']->php());
+
+            if (isset($this->arguments['bootstrap'])) {
+                $this->handleBootstrap($this->arguments['bootstrap']);
+            } elseif ($phpunitConfiguration->hasBootstrap()) {
+                $this->handleBootstrap($phpunitConfiguration->bootstrap());
+            }
+
+            if (!isset($this->arguments['stderr'])) {
+                $this->arguments['stderr'] = $phpunitConfiguration->stderr();
+            }
+
+            if (!isset($this->arguments['noExtensions']) && $phpunitConfiguration->hasExtensionsDirectory() && extension_loaded('phar')) {
+                $result = (new PharLoader)->loadPharExtensionsInDirectory($phpunitConfiguration->extensionsDirectory());
+
+                $this->arguments['loadedExtensions']    = $result['loadedExtensions'];
+                $this->arguments['notLoadedExtensions'] = $result['notLoadedExtensions'];
+
+                unset($result);
+            }
+
+            if (!isset($this->arguments['columns'])) {
+                $this->arguments['columns'] = $phpunitConfiguration->columns();
+            }
+
+            if (!isset($this->arguments['printer']) && $phpunitConfiguration->hasPrinterClass()) {
+                $file = $phpunitConfiguration->hasPrinterFile() ? $phpunitConfiguration->printerFile() : '';
+
+                $this->arguments['printer'] = $this->handlePrinter(
+                    $phpunitConfiguration->printerClass(),
+                    $file
+                );
+            }
+
+            if ($phpunitConfiguration->hasTestSuiteLoaderClass()) {
+                $file = $phpunitConfiguration->hasTestSuiteLoaderFile() ? $phpunitConfiguration->testSuiteLoaderFile() : '';
+
+                $this->arguments['loader'] = $this->handleLoader(
+                    $phpunitConfiguration->testSuiteLoaderClass(),
+                    $file
+                );
+            }
+
+            if (!isset($this->arguments['testsuite']) && $phpunitConfiguration->hasDefaultTestSuite()) {
+                $this->arguments['testsuite'] = $phpunitConfiguration->defaultTestSuite();
+            }
+
+            if (!isset($this->arguments['test'])) {
+                try {
+                    $this->arguments['test'] = (new TestSuiteMapper)->map(
+                        $this->arguments['configurationObject']->testSuite(),
+                        $this->arguments['testsuite'] ?? ''
+                    );
+                } catch (Exception $e) {
+                    $this->printVersionString();
+
+                    print $e->getMessage() . PHP_EOL;
+
+                    exit(TestRunner::EXCEPTION_EXIT);
+                }
+            }
+        } elseif (isset($this->arguments['bootstrap'])) {
+            $this->handleBootstrap($this->arguments['bootstrap']);
+        }
+
+        if (isset($this->arguments['printer']) && is_string($this->arguments['printer'])) {
+            $this->arguments['printer'] = $this->handlePrinter($this->arguments['printer']);
+        }
+
+        if (isset($this->arguments['configurationObject'], $this->arguments['warmCoverageCache'])) {
+            $this->handleWarmCoverageCache($this->arguments['configurationObject']);
+        }
+
+        if (!isset($this->arguments['test'])) {
+            $this->showHelp();
+
+            exit(TestRunner::EXCEPTION_EXIT);
+        }
+    }
+
+    /**
+     * Handles the loading of the PHPUnit\Runner\TestSuiteLoader implementation.
+     *
+     * @deprecated see https://github.com/sebastianbergmann/phpunit/issues/4039
+     */
+    protected function handleLoader(string $loaderClass, string $loaderFile = ''): ?TestSuiteLoader
+    {
+        $this->warnings[] = 'Using a custom test suite loader is deprecated';
+
+        if (!class_exists($loaderClass, false)) {
+            if ($loaderFile == '') {
+                $loaderFile = Filesystem::classNameToFilename(
+                    $loaderClass
+                );
+            }
+
+            $loaderFile = stream_resolve_include_path($loaderFile);
+
+            if ($loaderFile) {
+                /**
+                 * @noinspection PhpIncludeInspection
+                 * @psalm-suppress UnresolvableInclude
+                 */
+                require $loaderFile;
+            }
+        }
+
+        if (class_exists($loaderClass, false)) {
+            try {
+                $class = new ReflectionClass($loaderClass);
+                // @codeCoverageIgnoreStart
+            } catch (\ReflectionException $e) {
+                throw new ReflectionException(
+                    $e->getMessage(),
+                    (int) $e->getCode(),
+                    $e
+                );
+            }
+            // @codeCoverageIgnoreEnd
+
+            if ($class->implementsInterface(TestSuiteLoader::class) && $class->isInstantiable()) {
+                $object = $class->newInstance();
+
+                assert($object instanceof TestSuiteLoader);
+
+                return $object;
+            }
+        }
+
+        if ($loaderClass == StandardTestSuiteLoader::class) {
+            return null;
+        }
+
+        $this->exitWithErrorMessage(
+            sprintf(
+                'Could not use "%s" as loader.',
+                $loaderClass
+            )
+        );
+
+        return null;
+    }
+
+    /**
+     * Handles the loading of the PHPUnit\Util\Printer implementation.
+     *
+     * @return null|Printer|string
+     */
+    protected function handlePrinter(string $printerClass, string $printerFile = '')
+    {
+        if (!class_exists($printerClass, false)) {
+            if ($printerFile === '') {
+                $printerFile = Filesystem::classNameToFilename(
+                    $printerClass
+                );
+            }
+
+            $printerFile = stream_resolve_include_path($printerFile);
+
+            if ($printerFile) {
+                /**
+                 * @noinspection PhpIncludeInspection
+                 * @psalm-suppress UnresolvableInclude
+                 */
+                require $printerFile;
+            }
+        }
+
+        if (!class_exists($printerClass)) {
+            $this->exitWithErrorMessage(
+                sprintf(
+                    'Could not use "%s" as printer: class does not exist',
+                    $printerClass
+                )
+            );
+        }
+
+        try {
+            $class = new ReflectionClass($printerClass);
+            // @codeCoverageIgnoreStart
+        } catch (\ReflectionException $e) {
+            throw new ReflectionException(
+                $e->getMessage(),
+                (int) $e->getCode(),
+                $e
+            );
+            // @codeCoverageIgnoreEnd
+        }
+
+        if (!$class->implementsInterface(ResultPrinter::class)) {
+            $this->exitWithErrorMessage(
+                sprintf(
+                    'Could not use "%s" as printer: class does not implement %s',
+                    $printerClass,
+                    ResultPrinter::class
+                )
+            );
+        }
+
+        if (!$class->isInstantiable()) {
+            $this->exitWithErrorMessage(
+                sprintf(
+                    'Could not use "%s" as printer: class cannot be instantiated',
+                    $printerClass
+                )
+            );
+        }
+
+        if ($class->isSubclassOf(ResultPrinter::class)) {
+            return $printerClass;
+        }
+
+        $outputStream = isset($this->arguments['stderr']) ? 'php://stderr' : null;
+
+        return $class->newInstance($outputStream);
+    }
+
+    /**
+     * Loads a bootstrap file.
+     */
+    protected function handleBootstrap(string $filename): void
+    {
+        try {
+            FileLoader::checkAndLoad($filename);
+        } catch (Throwable $t) {
+            if ($t instanceof \PHPUnit\Exception) {
+                $this->exitWithErrorMessage($t->getMessage());
+            }
+
+            $this->exitWithErrorMessage(
+                sprintf(
+                    'Error in bootstrap script: %s:%s%s',
+                    get_class($t),
+                    PHP_EOL,
+                    $t->getMessage()
+                )
+            );
+        }
+    }
+
+    protected function handleVersionCheck(): void
+    {
+        $this->printVersionString();
+
+        $latestVersion = file_get_contents('https://phar.phpunit.de/latest-version-of/phpunit');
+        $isOutdated    = version_compare($latestVersion, Version::id(), '>');
+
+        if ($isOutdated) {
+            printf(
+                'You are not using the latest version of PHPUnit.' . PHP_EOL .
+                'The latest version is PHPUnit %s.' . PHP_EOL,
+                $latestVersion
+            );
+        } else {
+            print 'You are using the latest version of PHPUnit.' . PHP_EOL;
+        }
+
+        exit(TestRunner::SUCCESS_EXIT);
+    }
+
+    /**
+     * Show the help message.
+     */
+    protected function showHelp(): void
+    {
+        $this->printVersionString();
+        (new Help)->writeToConsole();
+    }
+
+    /**
+     * Custom callback for test suite discovery.
+     */
+    protected function handleCustomTestSuite(): void
+    {
+    }
+
+    private function printVersionString(): void
+    {
+        if ($this->versionStringPrinted) {
+            return;
+        }
+
+        print Version::getVersionString() . PHP_EOL . PHP_EOL;
+
+        $this->versionStringPrinted = true;
+    }
+
+    private function exitWithErrorMessage(string $message): void
+    {
+        $this->printVersionString();
+
+        print $message . PHP_EOL;
+
+        exit(TestRunner::FAILURE_EXIT);
+    }
+
+    private function handleListGroups(TestSuite $suite, bool $exit): int
+    {
+        $this->printVersionString();
+
+        print 'Available test group(s):' . PHP_EOL;
+
+        $groups = $suite->getGroups();
+        sort($groups);
+
+        foreach ($groups as $group) {
+            if (strpos($group, '__phpunit_') === 0) {
+                continue;
+            }
+
+            printf(
+                ' - %s' . PHP_EOL,
+                $group
+            );
+        }
+
+        if ($exit) {
+            exit(TestRunner::SUCCESS_EXIT);
+        }
+
+        return TestRunner::SUCCESS_EXIT;
+    }
+
+    /**
+     * @throws \PHPUnit\Framework\Exception
+     * @throws \PHPUnit\TextUI\XmlConfiguration\Exception
+     */
+    private function handleListSuites(bool $exit): int
+    {
+        $this->printVersionString();
+
+        print 'Available test suite(s):' . PHP_EOL;
+
+        foreach ($this->arguments['configurationObject']->testSuite() as $testSuite) {
+            printf(
+                ' - %s' . PHP_EOL,
+                $testSuite->name()
+            );
+        }
+
+        if ($exit) {
+            exit(TestRunner::SUCCESS_EXIT);
+        }
+
+        return TestRunner::SUCCESS_EXIT;
+    }
+
+    /**
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     */
+    private function handleListTests(TestSuite $suite, bool $exit): int
+    {
+        $this->printVersionString();
+
+        $renderer = new TextTestListRenderer;
+
+        print $renderer->render($suite);
+
+        if ($exit) {
+            exit(TestRunner::SUCCESS_EXIT);
+        }
+
+        return TestRunner::SUCCESS_EXIT;
+    }
+
+    /**
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     */
+    private function handleListTestsXml(TestSuite $suite, string $target, bool $exit): int
+    {
+        $this->printVersionString();
+
+        $renderer = new XmlTestListRenderer;
+
+        file_put_contents($target, $renderer->render($suite));
+
+        printf(
+            'Wrote list of tests that would have been run to %s' . PHP_EOL,
+            $target
+        );
+
+        if ($exit) {
+            exit(TestRunner::SUCCESS_EXIT);
+        }
+
+        return TestRunner::SUCCESS_EXIT;
+    }
+
+    private function generateConfiguration(): void
+    {
+        $this->printVersionString();
+
+        print 'Generating phpunit.xml in ' . getcwd() . PHP_EOL . PHP_EOL;
+        print 'Bootstrap script (relative to path shown above; default: vendor/autoload.php): ';
+
+        $bootstrapScript = trim(fgets(STDIN));
+
+        print 'Tests directory (relative to path shown above; default: tests): ';
+
+        $testsDirectory = trim(fgets(STDIN));
+
+        print 'Source directory (relative to path shown above; default: src): ';
+
+        $src = trim(fgets(STDIN));
+
+        print 'Cache directory (relative to path shown above; default: .phpunit.cache): ';
+
+        $cacheDirectory = trim(fgets(STDIN));
+
+        if ($bootstrapScript === '') {
+            $bootstrapScript = 'vendor/autoload.php';
+        }
+
+        if ($testsDirectory === '') {
+            $testsDirectory = 'tests';
+        }
+
+        if ($src === '') {
+            $src = 'src';
+        }
+
+        if ($cacheDirectory === '') {
+            $cacheDirectory = '.phpunit.cache';
+        }
+
+        $generator = new Generator;
+
+        file_put_contents(
+            'phpunit.xml',
+            $generator->generateDefaultConfiguration(
+                Version::series(),
+                $bootstrapScript,
+                $testsDirectory,
+                $src,
+                $cacheDirectory
+            )
+        );
+
+        print PHP_EOL . 'Generated phpunit.xml in ' . getcwd() . '.' . PHP_EOL;
+        print 'Make sure to exclude the ' . $cacheDirectory . ' directory from version control.' . PHP_EOL;
+
+        exit(TestRunner::SUCCESS_EXIT);
+    }
+
+    private function migrateConfiguration(string $filename): void
+    {
+        $this->printVersionString();
+
+        if (!(new SchemaDetector)->detect($filename)->detected()) {
+            print $filename . ' does not need to be migrated.' . PHP_EOL;
+
+            exit(TestRunner::EXCEPTION_EXIT);
+        }
+
+        copy($filename, $filename . '.bak');
+
+        print 'Created backup:         ' . $filename . '.bak' . PHP_EOL;
+
+        try {
+            file_put_contents(
+                $filename,
+                (new Migrator)->migrate($filename)
+            );
+
+            print 'Migrated configuration: ' . $filename . PHP_EOL;
+        } catch (Throwable $t) {
+            print 'Migration failed: ' . $t->getMessage() . PHP_EOL;
+
+            exit(TestRunner::EXCEPTION_EXIT);
+        }
+
+        exit(TestRunner::SUCCESS_EXIT);
+    }
+
+    private function handleCustomOptions(array $unrecognizedOptions): void
+    {
+        foreach ($unrecognizedOptions as $name => $value) {
+            if (isset($this->longOptions[$name])) {
+                $handler = $this->longOptions[$name];
+            }
+
+            $name .= '=';
+
+            if (isset($this->longOptions[$name])) {
+                $handler = $this->longOptions[$name];
+            }
+
+            if (isset($handler) && is_callable([$this, $handler])) {
+                $this->{$handler}($value);
+
+                unset($handler);
+            }
+        }
+    }
+
+    private function handleWarmCoverageCache(XmlConfiguration\Configuration $configuration): void
+    {
+        $this->printVersionString();
+
+        if (isset($this->arguments['coverageCacheDirectory'])) {
+            $cacheDirectory = $this->arguments['coverageCacheDirectory'];
+        } elseif ($configuration->codeCoverage()->hasCacheDirectory()) {
+            $cacheDirectory = $configuration->codeCoverage()->cacheDirectory()->path();
+        } else {
+            print 'Cache for static analysis has not been configured' . PHP_EOL;
+
+            exit(TestRunner::EXCEPTION_EXIT);
+        }
+
+        $filter = new Filter;
+
+        if ($configuration->codeCoverage()->hasNonEmptyListOfFilesToBeIncludedInCodeCoverageReport()) {
+            (new FilterMapper)->map(
+                $filter,
+                $configuration->codeCoverage()
+            );
+        } elseif (isset($this->arguments['coverageFilter'])) {
+            if (!is_array($this->arguments['coverageFilter'])) {
+                $coverageFilterDirectories = [$this->arguments['coverageFilter']];
+            } else {
+                $coverageFilterDirectories = $this->arguments['coverageFilter'];
+            }
+
+            foreach ($coverageFilterDirectories as $coverageFilterDirectory) {
+                $filter->includeDirectory($coverageFilterDirectory);
+            }
+        } else {
+            print 'Filter for code coverage has not been configured' . PHP_EOL;
+
+            exit(TestRunner::EXCEPTION_EXIT);
+        }
+
+        $timer = new Timer;
+        $timer->start();
+
+        print 'Warming cache for static analysis ... ';
+
+        (new CacheWarmer)->warmCache(
+            $cacheDirectory,
+            !$configuration->codeCoverage()->disableCodeCoverageIgnore(),
+            $configuration->codeCoverage()->ignoreDeprecatedCodeUnits(),
+            $filter
+        );
+
+        print 'done [' . $timer->stop()->asString() . ']' . PHP_EOL;
+
+        exit(TestRunner::SUCCESS_EXIT);
+    }
+
+    private function configurationFileInDirectory(string $directory): ?string
+    {
+        $candidates = [
+            $directory . '/phpunit.xml',
+            $directory . '/phpunit.xml.dist',
+        ];
+
+        foreach ($candidates as $candidate) {
+            if (is_file($candidate)) {
+                return realpath($candidate);
+            }
+        }
+
+        return null;
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/TextUI/DefaultResultPrinter.php b/vendor/phpunit/phpunit/src/TextUI/DefaultResultPrinter.php
new file mode 100644
index 0000000000000000000000000000000000000000..6a0ad2c796de0cf649ed51f49b76d5a84112693b
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/TextUI/DefaultResultPrinter.php
@@ -0,0 +1,592 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\TextUI;
+
+use const PHP_EOL;
+use function array_map;
+use function array_reverse;
+use function count;
+use function floor;
+use function implode;
+use function in_array;
+use function is_int;
+use function max;
+use function preg_split;
+use function sprintf;
+use function str_pad;
+use function str_repeat;
+use function strlen;
+use function vsprintf;
+use PHPUnit\Framework\AssertionFailedError;
+use PHPUnit\Framework\Exception;
+use PHPUnit\Framework\InvalidArgumentException;
+use PHPUnit\Framework\Test;
+use PHPUnit\Framework\TestCase;
+use PHPUnit\Framework\TestFailure;
+use PHPUnit\Framework\TestResult;
+use PHPUnit\Framework\TestSuite;
+use PHPUnit\Framework\Warning;
+use PHPUnit\Runner\PhptTestCase;
+use PHPUnit\Util\Color;
+use PHPUnit\Util\Printer;
+use SebastianBergmann\Environment\Console;
+use SebastianBergmann\Timer\ResourceUsageFormatter;
+use SebastianBergmann\Timer\Timer;
+use Throwable;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+class DefaultResultPrinter extends Printer implements ResultPrinter
+{
+    public const EVENT_TEST_START = 0;
+
+    public const EVENT_TEST_END = 1;
+
+    public const EVENT_TESTSUITE_START = 2;
+
+    public const EVENT_TESTSUITE_END = 3;
+
+    public const COLOR_NEVER = 'never';
+
+    public const COLOR_AUTO = 'auto';
+
+    public const COLOR_ALWAYS = 'always';
+
+    public const COLOR_DEFAULT = self::COLOR_NEVER;
+
+    private const AVAILABLE_COLORS = [self::COLOR_NEVER, self::COLOR_AUTO, self::COLOR_ALWAYS];
+
+    /**
+     * @var int
+     */
+    protected $column = 0;
+
+    /**
+     * @var int
+     */
+    protected $maxColumn;
+
+    /**
+     * @var bool
+     */
+    protected $lastTestFailed = false;
+
+    /**
+     * @var int
+     */
+    protected $numAssertions = 0;
+
+    /**
+     * @var int
+     */
+    protected $numTests = -1;
+
+    /**
+     * @var int
+     */
+    protected $numTestsRun = 0;
+
+    /**
+     * @var int
+     */
+    protected $numTestsWidth;
+
+    /**
+     * @var bool
+     */
+    protected $colors = false;
+
+    /**
+     * @var bool
+     */
+    protected $debug = false;
+
+    /**
+     * @var bool
+     */
+    protected $verbose = false;
+
+    /**
+     * @var int
+     */
+    private $numberOfColumns;
+
+    /**
+     * @var bool
+     */
+    private $reverse;
+
+    /**
+     * @var bool
+     */
+    private $defectListPrinted = false;
+
+    /**
+     * @var Timer
+     */
+    private $timer;
+
+    /**
+     * Constructor.
+     *
+     * @param null|resource|string $out
+     * @param int|string           $numberOfColumns
+     *
+     * @throws Exception
+     */
+    public function __construct($out = null, bool $verbose = false, string $colors = self::COLOR_DEFAULT, bool $debug = false, $numberOfColumns = 80, bool $reverse = false)
+    {
+        parent::__construct($out);
+
+        if (!in_array($colors, self::AVAILABLE_COLORS, true)) {
+            throw InvalidArgumentException::create(
+                3,
+                vsprintf('value from "%s", "%s" or "%s"', self::AVAILABLE_COLORS)
+            );
+        }
+
+        if (!is_int($numberOfColumns) && $numberOfColumns !== 'max') {
+            throw InvalidArgumentException::create(5, 'integer or "max"');
+        }
+
+        $console            = new Console;
+        $maxNumberOfColumns = $console->getNumberOfColumns();
+
+        if ($numberOfColumns === 'max' || ($numberOfColumns !== 80 && $numberOfColumns > $maxNumberOfColumns)) {
+            $numberOfColumns = $maxNumberOfColumns;
+        }
+
+        $this->numberOfColumns = $numberOfColumns;
+        $this->verbose         = $verbose;
+        $this->debug           = $debug;
+        $this->reverse         = $reverse;
+
+        if ($colors === self::COLOR_AUTO && $console->hasColorSupport()) {
+            $this->colors = true;
+        } else {
+            $this->colors = (self::COLOR_ALWAYS === $colors);
+        }
+
+        $this->timer = new Timer;
+
+        $this->timer->start();
+    }
+
+    public function printResult(TestResult $result): void
+    {
+        $this->printHeader($result);
+        $this->printErrors($result);
+        $this->printWarnings($result);
+        $this->printFailures($result);
+        $this->printRisky($result);
+
+        if ($this->verbose) {
+            $this->printIncompletes($result);
+            $this->printSkipped($result);
+        }
+
+        $this->printFooter($result);
+    }
+
+    /**
+     * An error occurred.
+     */
+    public function addError(Test $test, Throwable $t, float $time): void
+    {
+        $this->writeProgressWithColor('fg-red, bold', 'E');
+        $this->lastTestFailed = true;
+    }
+
+    /**
+     * A failure occurred.
+     */
+    public function addFailure(Test $test, AssertionFailedError $e, float $time): void
+    {
+        $this->writeProgressWithColor('bg-red, fg-white', 'F');
+        $this->lastTestFailed = true;
+    }
+
+    /**
+     * A warning occurred.
+     */
+    public function addWarning(Test $test, Warning $e, float $time): void
+    {
+        $this->writeProgressWithColor('fg-yellow, bold', 'W');
+        $this->lastTestFailed = true;
+    }
+
+    /**
+     * Incomplete test.
+     */
+    public function addIncompleteTest(Test $test, Throwable $t, float $time): void
+    {
+        $this->writeProgressWithColor('fg-yellow, bold', 'I');
+        $this->lastTestFailed = true;
+    }
+
+    /**
+     * Risky test.
+     */
+    public function addRiskyTest(Test $test, Throwable $t, float $time): void
+    {
+        $this->writeProgressWithColor('fg-yellow, bold', 'R');
+        $this->lastTestFailed = true;
+    }
+
+    /**
+     * Skipped test.
+     */
+    public function addSkippedTest(Test $test, Throwable $t, float $time): void
+    {
+        $this->writeProgressWithColor('fg-cyan, bold', 'S');
+        $this->lastTestFailed = true;
+    }
+
+    /**
+     * A testsuite started.
+     */
+    public function startTestSuite(TestSuite $suite): void
+    {
+        if ($this->numTests == -1) {
+            $this->numTests      = count($suite);
+            $this->numTestsWidth = strlen((string) $this->numTests);
+            $this->maxColumn     = $this->numberOfColumns - strlen('  /  (XXX%)') - (2 * $this->numTestsWidth);
+        }
+    }
+
+    /**
+     * A testsuite ended.
+     */
+    public function endTestSuite(TestSuite $suite): void
+    {
+    }
+
+    /**
+     * A test started.
+     */
+    public function startTest(Test $test): void
+    {
+        if ($this->debug) {
+            $this->write(
+                sprintf(
+                    "Test '%s' started\n",
+                    \PHPUnit\Util\Test::describeAsString($test)
+                )
+            );
+        }
+    }
+
+    /**
+     * A test ended.
+     */
+    public function endTest(Test $test, float $time): void
+    {
+        if ($this->debug) {
+            $this->write(
+                sprintf(
+                    "Test '%s' ended\n",
+                    \PHPUnit\Util\Test::describeAsString($test)
+                )
+            );
+        }
+
+        if (!$this->lastTestFailed) {
+            $this->writeProgress('.');
+        }
+
+        if ($test instanceof TestCase) {
+            $this->numAssertions += $test->getNumAssertions();
+        } elseif ($test instanceof PhptTestCase) {
+            $this->numAssertions++;
+        }
+
+        $this->lastTestFailed = false;
+
+        if ($test instanceof TestCase && !$test->hasExpectationOnOutput()) {
+            $this->write($test->getActualOutput());
+        }
+    }
+
+    protected function printDefects(array $defects, string $type): void
+    {
+        $count = count($defects);
+
+        if ($count == 0) {
+            return;
+        }
+
+        if ($this->defectListPrinted) {
+            $this->write("\n--\n\n");
+        }
+
+        $this->write(
+            sprintf(
+                "There %s %d %s%s:\n",
+                ($count == 1) ? 'was' : 'were',
+                $count,
+                $type,
+                ($count == 1) ? '' : 's'
+            )
+        );
+
+        $i = 1;
+
+        if ($this->reverse) {
+            $defects = array_reverse($defects);
+        }
+
+        foreach ($defects as $defect) {
+            $this->printDefect($defect, $i++);
+        }
+
+        $this->defectListPrinted = true;
+    }
+
+    protected function printDefect(TestFailure $defect, int $count): void
+    {
+        $this->printDefectHeader($defect, $count);
+        $this->printDefectTrace($defect);
+    }
+
+    protected function printDefectHeader(TestFailure $defect, int $count): void
+    {
+        $this->write(
+            sprintf(
+                "\n%d) %s\n",
+                $count,
+                $defect->getTestName()
+            )
+        );
+    }
+
+    protected function printDefectTrace(TestFailure $defect): void
+    {
+        $e = $defect->thrownException();
+
+        $this->write((string) $e);
+
+        while ($e = $e->getPrevious()) {
+            $this->write("\nCaused by\n" . $e);
+        }
+    }
+
+    protected function printErrors(TestResult $result): void
+    {
+        $this->printDefects($result->errors(), 'error');
+    }
+
+    protected function printFailures(TestResult $result): void
+    {
+        $this->printDefects($result->failures(), 'failure');
+    }
+
+    protected function printWarnings(TestResult $result): void
+    {
+        $this->printDefects($result->warnings(), 'warning');
+    }
+
+    protected function printIncompletes(TestResult $result): void
+    {
+        $this->printDefects($result->notImplemented(), 'incomplete test');
+    }
+
+    protected function printRisky(TestResult $result): void
+    {
+        $this->printDefects($result->risky(), 'risky test');
+    }
+
+    protected function printSkipped(TestResult $result): void
+    {
+        $this->printDefects($result->skipped(), 'skipped test');
+    }
+
+    protected function printHeader(TestResult $result): void
+    {
+        if (count($result) > 0) {
+            $this->write(PHP_EOL . PHP_EOL . (new ResourceUsageFormatter)->resourceUsage($this->timer->stop()) . PHP_EOL . PHP_EOL);
+        }
+    }
+
+    protected function printFooter(TestResult $result): void
+    {
+        if (count($result) === 0) {
+            $this->writeWithColor(
+                'fg-black, bg-yellow',
+                'No tests executed!'
+            );
+
+            return;
+        }
+
+        if ($result->wasSuccessfulAndNoTestIsRiskyOrSkippedOrIncomplete()) {
+            $this->writeWithColor(
+                'fg-black, bg-green',
+                sprintf(
+                    'OK (%d test%s, %d assertion%s)',
+                    count($result),
+                    (count($result) === 1) ? '' : 's',
+                    $this->numAssertions,
+                    ($this->numAssertions === 1) ? '' : 's'
+                )
+            );
+
+            return;
+        }
+
+        $color = 'fg-black, bg-yellow';
+
+        if ($result->wasSuccessful()) {
+            if ($this->verbose || !$result->allHarmless()) {
+                $this->write("\n");
+            }
+
+            $this->writeWithColor(
+                $color,
+                'OK, but incomplete, skipped, or risky tests!'
+            );
+        } else {
+            $this->write("\n");
+
+            if ($result->errorCount()) {
+                $color = 'fg-white, bg-red';
+
+                $this->writeWithColor(
+                    $color,
+                    'ERRORS!'
+                );
+            } elseif ($result->failureCount()) {
+                $color = 'fg-white, bg-red';
+
+                $this->writeWithColor(
+                    $color,
+                    'FAILURES!'
+                );
+            } elseif ($result->warningCount()) {
+                $color = 'fg-black, bg-yellow';
+
+                $this->writeWithColor(
+                    $color,
+                    'WARNINGS!'
+                );
+            }
+        }
+
+        $this->writeCountString(count($result), 'Tests', $color, true);
+        $this->writeCountString($this->numAssertions, 'Assertions', $color, true);
+        $this->writeCountString($result->errorCount(), 'Errors', $color);
+        $this->writeCountString($result->failureCount(), 'Failures', $color);
+        $this->writeCountString($result->warningCount(), 'Warnings', $color);
+        $this->writeCountString($result->skippedCount(), 'Skipped', $color);
+        $this->writeCountString($result->notImplementedCount(), 'Incomplete', $color);
+        $this->writeCountString($result->riskyCount(), 'Risky', $color);
+        $this->writeWithColor($color, '.');
+    }
+
+    protected function writeProgress(string $progress): void
+    {
+        if ($this->debug) {
+            return;
+        }
+
+        $this->write($progress);
+        $this->column++;
+        $this->numTestsRun++;
+
+        if ($this->column == $this->maxColumn || $this->numTestsRun == $this->numTests) {
+            if ($this->numTestsRun == $this->numTests) {
+                $this->write(str_repeat(' ', $this->maxColumn - $this->column));
+            }
+
+            $this->write(
+                sprintf(
+                    ' %' . $this->numTestsWidth . 'd / %' .
+                    $this->numTestsWidth . 'd (%3s%%)',
+                    $this->numTestsRun,
+                    $this->numTests,
+                    floor(($this->numTestsRun / $this->numTests) * 100)
+                )
+            );
+
+            if ($this->column == $this->maxColumn) {
+                $this->writeNewLine();
+            }
+        }
+    }
+
+    protected function writeNewLine(): void
+    {
+        $this->column = 0;
+        $this->write("\n");
+    }
+
+    /**
+     * Formats a buffer with a specified ANSI color sequence if colors are
+     * enabled.
+     */
+    protected function colorizeTextBox(string $color, string $buffer): string
+    {
+        if (!$this->colors) {
+            return $buffer;
+        }
+
+        $lines   = preg_split('/\r\n|\r|\n/', $buffer);
+        $padding = max(array_map('\strlen', $lines));
+
+        $styledLines = [];
+
+        foreach ($lines as $line) {
+            $styledLines[] = Color::colorize($color, str_pad($line, $padding));
+        }
+
+        return implode(PHP_EOL, $styledLines);
+    }
+
+    /**
+     * Writes a buffer out with a color sequence if colors are enabled.
+     */
+    protected function writeWithColor(string $color, string $buffer, bool $lf = true): void
+    {
+        $this->write($this->colorizeTextBox($color, $buffer));
+
+        if ($lf) {
+            $this->write(PHP_EOL);
+        }
+    }
+
+    /**
+     * Writes progress with a color sequence if colors are enabled.
+     */
+    protected function writeProgressWithColor(string $color, string $buffer): void
+    {
+        $buffer = $this->colorizeTextBox($color, $buffer);
+        $this->writeProgress($buffer);
+    }
+
+    private function writeCountString(int $count, string $name, string $color, bool $always = false): void
+    {
+        static $first = true;
+
+        if ($always || $count > 0) {
+            $this->writeWithColor(
+                $color,
+                sprintf(
+                    '%s%s: %d',
+                    !$first ? ', ' : '',
+                    $name,
+                    $count
+                ),
+                false
+            );
+
+            $first = false;
+        }
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/TextUI/Exception/Exception.php b/vendor/phpunit/phpunit/src/TextUI/Exception/Exception.php
new file mode 100644
index 0000000000000000000000000000000000000000..ee2ae4ffa90841b0539c33f20c9936ddfcdccf7b
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/TextUI/Exception/Exception.php
@@ -0,0 +1,19 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\TextUI;
+
+use Throwable;
+
+/**
+ * @internal This interface is not covered by the backward compatibility promise for PHPUnit
+ */
+interface Exception extends Throwable
+{
+}
diff --git a/vendor/phpunit/phpunit/src/TextUI/Exception/ReflectionException.php b/vendor/phpunit/phpunit/src/TextUI/Exception/ReflectionException.php
new file mode 100644
index 0000000000000000000000000000000000000000..74e9d25ddd5b2c1935423364afa841dabc80a101
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/TextUI/Exception/ReflectionException.php
@@ -0,0 +1,19 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\TextUI;
+
+use RuntimeException;
+
+/**
+ * @internal This interface is not covered by the backward compatibility promise for PHPUnit
+ */
+final class ReflectionException extends RuntimeException implements Exception
+{
+}
diff --git a/vendor/phpunit/phpunit/src/TextUI/Exception/RuntimeException.php b/vendor/phpunit/phpunit/src/TextUI/Exception/RuntimeException.php
new file mode 100644
index 0000000000000000000000000000000000000000..790a84634fe85d39c95be0c19b9e23e2ac6e5e02
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/TextUI/Exception/RuntimeException.php
@@ -0,0 +1,17 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\TextUI;
+
+/**
+ * @internal This interface is not covered by the backward compatibility promise for PHPUnit
+ */
+final class RuntimeException extends \RuntimeException implements Exception
+{
+}
diff --git a/vendor/phpunit/phpunit/src/TextUI/Exception/TestDirectoryNotFoundException.php b/vendor/phpunit/phpunit/src/TextUI/Exception/TestDirectoryNotFoundException.php
new file mode 100644
index 0000000000000000000000000000000000000000..770ad8742934eb74d79d5fe06bce506e870b7697
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/TextUI/Exception/TestDirectoryNotFoundException.php
@@ -0,0 +1,29 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\TextUI;
+
+use function sprintf;
+use RuntimeException;
+
+/**
+ * @internal This interface is not covered by the backward compatibility promise for PHPUnit
+ */
+final class TestDirectoryNotFoundException extends RuntimeException implements Exception
+{
+    public function __construct(string $path)
+    {
+        parent::__construct(
+            sprintf(
+                'Test directory "%s" not found',
+                $path
+            )
+        );
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/TextUI/Exception/TestFileNotFoundException.php b/vendor/phpunit/phpunit/src/TextUI/Exception/TestFileNotFoundException.php
new file mode 100644
index 0000000000000000000000000000000000000000..7ffd2c78c062a2a716892fd2d5797d4ed06cd1d7
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/TextUI/Exception/TestFileNotFoundException.php
@@ -0,0 +1,29 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\TextUI;
+
+use function sprintf;
+use RuntimeException;
+
+/**
+ * @internal This interface is not covered by the backward compatibility promise for PHPUnit
+ */
+final class TestFileNotFoundException extends RuntimeException implements Exception
+{
+    public function __construct(string $path)
+    {
+        parent::__construct(
+            sprintf(
+                'Test file "%s" not found',
+                $path
+            )
+        );
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/TextUI/Help.php b/vendor/phpunit/phpunit/src/TextUI/Help.php
new file mode 100644
index 0000000000000000000000000000000000000000..7c5d51c79d72aa2ff73dfb9c4e8fc912c8da99d2
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/TextUI/Help.php
@@ -0,0 +1,264 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\TextUI;
+
+use const PHP_EOL;
+use function count;
+use function explode;
+use function max;
+use function preg_replace_callback;
+use function str_pad;
+use function str_repeat;
+use function strlen;
+use function wordwrap;
+use PHPUnit\Util\Color;
+use SebastianBergmann\Environment\Console;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class Help
+{
+    private const LEFT_MARGIN = '  ';
+
+    private const HELP_TEXT = [
+        'Usage' => [
+            ['text' => 'phpunit [options] UnitTest.php'],
+            ['text' => 'phpunit [options] <directory>'],
+        ],
+
+        'Code Coverage Options' => [
+            ['arg' => '--coverage-clover <file>', 'desc' => 'Generate code coverage report in Clover XML format'],
+            ['arg' => '--coverage-cobertura <file>', 'desc' => 'Generate code coverage report in Cobertura XML format'],
+            ['arg' => '--coverage-crap4j <file>', 'desc' => 'Generate code coverage report in Crap4J XML format'],
+            ['arg' => '--coverage-html <dir>', 'desc' => 'Generate code coverage report in HTML format'],
+            ['arg' => '--coverage-php <file>', 'desc' => 'Export PHP_CodeCoverage object to file'],
+            ['arg' => '--coverage-text=<file>', 'desc' => 'Generate code coverage report in text format [default: standard output]'],
+            ['arg' => '--coverage-xml <dir>', 'desc' => 'Generate code coverage report in PHPUnit XML format'],
+            ['arg' => '--coverage-cache <dir>', 'desc' => 'Cache static analysis results'],
+            ['arg' => '--warm-coverage-cache', 'desc' => 'Warm static analysis cache'],
+            ['arg' => '--coverage-filter <dir>', 'desc' => 'Include <dir> in code coverage analysis'],
+            ['arg' => '--path-coverage', 'desc' => 'Perform path coverage analysis'],
+            ['arg' => '--disable-coverage-ignore', 'desc' => 'Disable annotations for ignoring code coverage'],
+            ['arg' => '--no-coverage', 'desc' => 'Ignore code coverage configuration'],
+        ],
+
+        'Logging Options' => [
+            ['arg' => '--log-junit <file>', 'desc' => 'Log test execution in JUnit XML format to file'],
+            ['arg' => '--log-teamcity <file>', 'desc' => 'Log test execution in TeamCity format to file'],
+            ['arg' => '--testdox-html <file>', 'desc' => 'Write agile documentation in HTML format to file'],
+            ['arg' => '--testdox-text <file>', 'desc' => 'Write agile documentation in Text format to file'],
+            ['arg' => '--testdox-xml <file>', 'desc' => 'Write agile documentation in XML format to file'],
+            ['arg' => '--reverse-list', 'desc' => 'Print defects in reverse order'],
+            ['arg' => '--no-logging', 'desc' => 'Ignore logging configuration'],
+        ],
+
+        'Test Selection Options' => [
+            ['arg' => '--list-suites', 'desc' => 'List available test suites'],
+            ['arg' => '--testsuite <name>', 'desc' => 'Filter which testsuite to run'],
+            ['arg' => '--list-groups', 'desc' => 'List available test groups'],
+            ['arg' => '--group <name>', 'desc' => 'Only runs tests from the specified group(s)'],
+            ['arg' => '--exclude-group <name>', 'desc' => 'Exclude tests from the specified group(s)'],
+            ['arg' => '--covers <name>', 'desc' => 'Only runs tests annotated with "@covers <name>"'],
+            ['arg' => '--uses <name>', 'desc' => 'Only runs tests annotated with "@uses <name>"'],
+            ['arg' => '--list-tests', 'desc' => 'List available tests'],
+            ['arg' => '--list-tests-xml <file>', 'desc' => 'List available tests in XML format'],
+            ['arg' => '--filter <pattern>', 'desc' => 'Filter which tests to run'],
+            ['arg' => '--test-suffix <suffixes>', 'desc' => 'Only search for test in files with specified suffix(es). Default: Test.php,.phpt'],
+        ],
+
+        'Test Execution Options' => [
+            ['arg' => '--dont-report-useless-tests', 'desc' => 'Do not report tests that do not test anything'],
+            ['arg'    => '--strict-coverage', 'desc' => 'Be strict about @covers annotation usage'],
+            ['arg'    => '--strict-global-state', 'desc' => 'Be strict about changes to global state'],
+            ['arg'    => '--disallow-test-output', 'desc' => 'Be strict about output during tests'],
+            ['arg'    => '--disallow-resource-usage', 'desc' => 'Be strict about resource usage during small tests'],
+            ['arg'    => '--enforce-time-limit', 'desc' => 'Enforce time limit based on test size'],
+            ['arg'    => '--default-time-limit <sec>', 'desc' => 'Timeout in seconds for tests without @small, @medium or @large'],
+            ['arg'    => '--disallow-todo-tests', 'desc' => 'Disallow @todo-annotated tests'],
+            ['spacer' => ''],
+
+            ['arg'    => '--process-isolation', 'desc' => 'Run each test in a separate PHP process'],
+            ['arg'    => '--globals-backup', 'desc' => 'Backup and restore $GLOBALS for each test'],
+            ['arg'    => '--static-backup', 'desc' => 'Backup and restore static attributes for each test'],
+            ['spacer' => ''],
+
+            ['arg'    => '--colors <flag>', 'desc' => 'Use colors in output ("never", "auto" or "always")'],
+            ['arg'    => '--columns <n>', 'desc' => 'Number of columns to use for progress output'],
+            ['arg'    => '--columns max', 'desc' => 'Use maximum number of columns for progress output'],
+            ['arg'    => '--stderr', 'desc' => 'Write to STDERR instead of STDOUT'],
+            ['arg'    => '--stop-on-defect', 'desc' => 'Stop execution upon first not-passed test'],
+            ['arg'    => '--stop-on-error', 'desc' => 'Stop execution upon first error'],
+            ['arg'    => '--stop-on-failure', 'desc' => 'Stop execution upon first error or failure'],
+            ['arg'    => '--stop-on-warning', 'desc' => 'Stop execution upon first warning'],
+            ['arg'    => '--stop-on-risky', 'desc' => 'Stop execution upon first risky test'],
+            ['arg'    => '--stop-on-skipped', 'desc' => 'Stop execution upon first skipped test'],
+            ['arg'    => '--stop-on-incomplete', 'desc' => 'Stop execution upon first incomplete test'],
+            ['arg'    => '--fail-on-incomplete', 'desc' => 'Treat incomplete tests as failures'],
+            ['arg'    => '--fail-on-risky', 'desc' => 'Treat risky tests as failures'],
+            ['arg'    => '--fail-on-skipped', 'desc' => 'Treat skipped tests as failures'],
+            ['arg'    => '--fail-on-warning', 'desc' => 'Treat tests with warnings as failures'],
+            ['arg'    => '-v|--verbose', 'desc' => 'Output more verbose information'],
+            ['arg'    => '--debug', 'desc' => 'Display debugging information'],
+            ['spacer' => ''],
+
+            ['arg'    => '--repeat <times>', 'desc' => 'Runs the test(s) repeatedly'],
+            ['arg'    => '--teamcity', 'desc' => 'Report test execution progress in TeamCity format'],
+            ['arg'    => '--testdox', 'desc' => 'Report test execution progress in TestDox format'],
+            ['arg'    => '--testdox-group', 'desc' => 'Only include tests from the specified group(s)'],
+            ['arg'    => '--testdox-exclude-group', 'desc' => 'Exclude tests from the specified group(s)'],
+            ['arg'    => '--no-interaction', 'desc' => 'Disable TestDox progress animation'],
+            ['arg'    => '--printer <printer>', 'desc' => 'TestListener implementation to use'],
+            ['spacer' => ''],
+
+            ['arg' => '--order-by <order>', 'desc' => 'Run tests in order: default|defects|duration|no-depends|random|reverse|size'],
+            ['arg' => '--random-order-seed <N>', 'desc' => 'Use a specific random seed <N> for random order'],
+            ['arg' => '--cache-result', 'desc' => 'Write test results to cache file'],
+            ['arg' => '--do-not-cache-result', 'desc' => 'Do not write test results to cache file'],
+        ],
+
+        'Configuration Options' => [
+            ['arg' => '--prepend <file>', 'desc' => 'A PHP script that is included as early as possible'],
+            ['arg' => '--bootstrap <file>', 'desc' => 'A PHP script that is included before the tests run'],
+            ['arg' => '-c|--configuration <file>', 'desc' => 'Read configuration from XML file'],
+            ['arg' => '--no-configuration', 'desc' => 'Ignore default configuration file (phpunit.xml)'],
+            ['arg' => '--extensions <extensions>', 'desc' => 'A comma separated list of PHPUnit extensions to load'],
+            ['arg' => '--no-extensions', 'desc' => 'Do not load PHPUnit extensions'],
+            ['arg' => '--include-path <path(s)>', 'desc' => 'Prepend PHP\'s include_path with given path(s)'],
+            ['arg' => '-d <key[=value]>', 'desc' => 'Sets a php.ini value'],
+            ['arg' => '--cache-result-file <file>', 'desc' => 'Specify result cache path and filename'],
+            ['arg' => '--generate-configuration', 'desc' => 'Generate configuration file with suggested settings'],
+            ['arg' => '--migrate-configuration', 'desc' => 'Migrate configuration file to current format'],
+        ],
+
+        'Miscellaneous Options' => [
+            ['arg' => '-h|--help', 'desc' => 'Prints this usage information'],
+            ['arg' => '--version', 'desc' => 'Prints the version and exits'],
+            ['arg' => '--atleast-version <min>', 'desc' => 'Checks that version is greater than min and exits'],
+            ['arg' => '--check-version', 'desc' => 'Check whether PHPUnit is the latest version'],
+        ],
+
+    ];
+
+    /**
+     * @var int Number of columns required to write the longest option name to the console
+     */
+    private $maxArgLength = 0;
+
+    /**
+     * @var int Number of columns left for the description field after padding and option
+     */
+    private $maxDescLength;
+
+    /**
+     * @var bool Use color highlights for sections, options and parameters
+     */
+    private $hasColor = false;
+
+    public function __construct(?int $width = null, ?bool $withColor = null)
+    {
+        if ($width === null) {
+            $width = (new Console)->getNumberOfColumns();
+        }
+
+        if ($withColor === null) {
+            $this->hasColor = (new Console)->hasColorSupport();
+        } else {
+            $this->hasColor = $withColor;
+        }
+
+        foreach (self::HELP_TEXT as $options) {
+            foreach ($options as $option) {
+                if (isset($option['arg'])) {
+                    $this->maxArgLength = max($this->maxArgLength, isset($option['arg']) ? strlen($option['arg']) : 0);
+                }
+            }
+        }
+
+        $this->maxDescLength = $width - $this->maxArgLength - 4;
+    }
+
+    /**
+     * Write the help file to the CLI, adapting width and colors to the console.
+     */
+    public function writeToConsole(): void
+    {
+        if ($this->hasColor) {
+            $this->writeWithColor();
+        } else {
+            $this->writePlaintext();
+        }
+    }
+
+    private function writePlaintext(): void
+    {
+        foreach (self::HELP_TEXT as $section => $options) {
+            print "{$section}:" . PHP_EOL;
+
+            if ($section !== 'Usage') {
+                print PHP_EOL;
+            }
+
+            foreach ($options as $option) {
+                if (isset($option['spacer'])) {
+                    print PHP_EOL;
+                }
+
+                if (isset($option['text'])) {
+                    print self::LEFT_MARGIN . $option['text'] . PHP_EOL;
+                }
+
+                if (isset($option['arg'])) {
+                    $arg = str_pad($option['arg'], $this->maxArgLength);
+                    print self::LEFT_MARGIN . $arg . ' ' . $option['desc'] . PHP_EOL;
+                }
+            }
+
+            print PHP_EOL;
+        }
+    }
+
+    private function writeWithColor(): void
+    {
+        foreach (self::HELP_TEXT as $section => $options) {
+            print Color::colorize('fg-yellow', "{$section}:") . PHP_EOL;
+
+            foreach ($options as $option) {
+                if (isset($option['spacer'])) {
+                    print PHP_EOL;
+                }
+
+                if (isset($option['text'])) {
+                    print self::LEFT_MARGIN . $option['text'] . PHP_EOL;
+                }
+
+                if (isset($option['arg'])) {
+                    $arg = Color::colorize('fg-green', str_pad($option['arg'], $this->maxArgLength));
+                    $arg = preg_replace_callback(
+                        '/(<[^>]+>)/',
+                        static function ($matches) {
+                            return Color::colorize('fg-cyan', $matches[0]);
+                        },
+                        $arg
+                    );
+                    $desc = explode(PHP_EOL, wordwrap($option['desc'], $this->maxDescLength, PHP_EOL));
+
+                    print self::LEFT_MARGIN . $arg . ' ' . $desc[0] . PHP_EOL;
+
+                    for ($i = 1; $i < count($desc); $i++) {
+                        print str_repeat(' ', $this->maxArgLength + 3) . $desc[$i] . PHP_EOL;
+                    }
+                }
+            }
+
+            print PHP_EOL;
+        }
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/TextUI/ResultPrinter.php b/vendor/phpunit/phpunit/src/TextUI/ResultPrinter.php
new file mode 100644
index 0000000000000000000000000000000000000000..ec89f6006566ce29eea4ca8dd09c769ad39b64b8
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/TextUI/ResultPrinter.php
@@ -0,0 +1,23 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\TextUI;
+
+use PHPUnit\Framework\TestListener;
+use PHPUnit\Framework\TestResult;
+
+/**
+ * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+ */
+interface ResultPrinter extends TestListener
+{
+    public function printResult(TestResult $result): void;
+
+    public function write(string $buffer): void;
+}
diff --git a/vendor/phpunit/phpunit/src/TextUI/TestRunner.php b/vendor/phpunit/phpunit/src/TextUI/TestRunner.php
new file mode 100644
index 0000000000000000000000000000000000000000..d8dc0581b5cd8e223d6e6bc2df53ce765ec76094
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/TextUI/TestRunner.php
@@ -0,0 +1,1265 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\TextUI;
+
+use const PHP_EOL;
+use const PHP_SAPI;
+use const PHP_VERSION;
+use function array_diff;
+use function array_map;
+use function assert;
+use function class_exists;
+use function count;
+use function dirname;
+use function file_put_contents;
+use function htmlspecialchars;
+use function is_array;
+use function is_int;
+use function is_string;
+use function mt_srand;
+use function range;
+use function realpath;
+use function sprintf;
+use function time;
+use PHPUnit\Framework\Exception;
+use PHPUnit\Framework\TestResult;
+use PHPUnit\Framework\TestSuite;
+use PHPUnit\Runner\AfterLastTestHook;
+use PHPUnit\Runner\BaseTestRunner;
+use PHPUnit\Runner\BeforeFirstTestHook;
+use PHPUnit\Runner\DefaultTestResultCache;
+use PHPUnit\Runner\Extension\ExtensionHandler;
+use PHPUnit\Runner\Filter\ExcludeGroupFilterIterator;
+use PHPUnit\Runner\Filter\Factory;
+use PHPUnit\Runner\Filter\IncludeGroupFilterIterator;
+use PHPUnit\Runner\Filter\NameFilterIterator;
+use PHPUnit\Runner\Hook;
+use PHPUnit\Runner\NullTestResultCache;
+use PHPUnit\Runner\ResultCacheExtension;
+use PHPUnit\Runner\StandardTestSuiteLoader;
+use PHPUnit\Runner\TestHook;
+use PHPUnit\Runner\TestListenerAdapter;
+use PHPUnit\Runner\TestSuiteLoader;
+use PHPUnit\Runner\TestSuiteSorter;
+use PHPUnit\Runner\Version;
+use PHPUnit\TextUI\XmlConfiguration\CodeCoverage\FilterMapper;
+use PHPUnit\TextUI\XmlConfiguration\Configuration;
+use PHPUnit\TextUI\XmlConfiguration\Loader;
+use PHPUnit\TextUI\XmlConfiguration\PhpHandler;
+use PHPUnit\Util\Filesystem;
+use PHPUnit\Util\Log\JUnit;
+use PHPUnit\Util\Log\TeamCity;
+use PHPUnit\Util\Printer;
+use PHPUnit\Util\TestDox\CliTestDoxPrinter;
+use PHPUnit\Util\TestDox\HtmlResultPrinter;
+use PHPUnit\Util\TestDox\TextResultPrinter;
+use PHPUnit\Util\TestDox\XmlResultPrinter;
+use PHPUnit\Util\XdebugFilterScriptGenerator;
+use PHPUnit\Util\Xml\SchemaDetector;
+use ReflectionClass;
+use ReflectionException;
+use SebastianBergmann\CodeCoverage\CodeCoverage;
+use SebastianBergmann\CodeCoverage\Driver\Selector;
+use SebastianBergmann\CodeCoverage\Exception as CodeCoverageException;
+use SebastianBergmann\CodeCoverage\Filter as CodeCoverageFilter;
+use SebastianBergmann\CodeCoverage\Report\Clover as CloverReport;
+use SebastianBergmann\CodeCoverage\Report\Cobertura as CoberturaReport;
+use SebastianBergmann\CodeCoverage\Report\Crap4j as Crap4jReport;
+use SebastianBergmann\CodeCoverage\Report\Html\Facade as HtmlReport;
+use SebastianBergmann\CodeCoverage\Report\PHP as PhpReport;
+use SebastianBergmann\CodeCoverage\Report\Text as TextReport;
+use SebastianBergmann\CodeCoverage\Report\Xml\Facade as XmlReport;
+use SebastianBergmann\Comparator\Comparator;
+use SebastianBergmann\Environment\Runtime;
+use SebastianBergmann\Invoker\Invoker;
+use SebastianBergmann\Timer\Timer;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class TestRunner extends BaseTestRunner
+{
+    public const SUCCESS_EXIT = 0;
+
+    public const FAILURE_EXIT = 1;
+
+    public const EXCEPTION_EXIT = 2;
+
+    /**
+     * @var bool
+     */
+    private static $versionStringPrinted = false;
+
+    /**
+     * @var CodeCoverageFilter
+     */
+    private $codeCoverageFilter;
+
+    /**
+     * @var TestSuiteLoader
+     */
+    private $loader;
+
+    /**
+     * @var ResultPrinter
+     */
+    private $printer;
+
+    /**
+     * @var bool
+     */
+    private $messagePrinted = false;
+
+    /**
+     * @var Hook[]
+     */
+    private $extensions = [];
+
+    /**
+     * @var Timer
+     */
+    private $timer;
+
+    public function __construct(TestSuiteLoader $loader = null, CodeCoverageFilter $filter = null)
+    {
+        if ($filter === null) {
+            $filter = new CodeCoverageFilter;
+        }
+
+        $this->codeCoverageFilter = $filter;
+        $this->loader             = $loader;
+        $this->timer              = new Timer;
+    }
+
+    /**
+     * @throws \PHPUnit\Runner\Exception
+     * @throws \PHPUnit\TextUI\XmlConfiguration\Exception
+     * @throws Exception
+     */
+    public function run(TestSuite $suite, array $arguments = [], array $warnings = [], bool $exit = true): TestResult
+    {
+        if (isset($arguments['configuration'])) {
+            $GLOBALS['__PHPUNIT_CONFIGURATION_FILE'] = $arguments['configuration'];
+        }
+
+        $this->handleConfiguration($arguments);
+
+        if (is_int($arguments['columns']) && $arguments['columns'] < 16) {
+            $arguments['columns']   = 16;
+            $tooFewColumnsRequested = true;
+        }
+
+        if (isset($arguments['bootstrap'])) {
+            $GLOBALS['__PHPUNIT_BOOTSTRAP'] = $arguments['bootstrap'];
+        }
+
+        if ($arguments['backupGlobals'] === true) {
+            $suite->setBackupGlobals(true);
+        }
+
+        if ($arguments['backupStaticAttributes'] === true) {
+            $suite->setBackupStaticAttributes(true);
+        }
+
+        if ($arguments['beStrictAboutChangesToGlobalState'] === true) {
+            $suite->setBeStrictAboutChangesToGlobalState(true);
+        }
+
+        if ($arguments['executionOrder'] === TestSuiteSorter::ORDER_RANDOMIZED) {
+            mt_srand($arguments['randomOrderSeed']);
+        }
+
+        if ($arguments['cacheResult']) {
+            if (!isset($arguments['cacheResultFile'])) {
+                if (isset($arguments['configurationObject'])) {
+                    assert($arguments['configurationObject'] instanceof Configuration);
+
+                    $cacheLocation = $arguments['configurationObject']->filename();
+                } else {
+                    $cacheLocation = $_SERVER['PHP_SELF'];
+                }
+
+                $arguments['cacheResultFile'] = null;
+
+                $cacheResultFile = realpath($cacheLocation);
+
+                if ($cacheResultFile !== false) {
+                    $arguments['cacheResultFile'] = dirname($cacheResultFile);
+                }
+            }
+
+            $cache = new DefaultTestResultCache($arguments['cacheResultFile']);
+
+            $this->addExtension(new ResultCacheExtension($cache));
+        }
+
+        if ($arguments['executionOrder'] !== TestSuiteSorter::ORDER_DEFAULT || $arguments['executionOrderDefects'] !== TestSuiteSorter::ORDER_DEFAULT || $arguments['resolveDependencies']) {
+            $cache = $cache ?? new NullTestResultCache;
+
+            $cache->load();
+
+            $sorter = new TestSuiteSorter($cache);
+
+            $sorter->reorderTestsInSuite($suite, $arguments['executionOrder'], $arguments['resolveDependencies'], $arguments['executionOrderDefects']);
+            $originalExecutionOrder = $sorter->getOriginalExecutionOrder();
+
+            unset($sorter);
+        }
+
+        if (is_int($arguments['repeat']) && $arguments['repeat'] > 0) {
+            $_suite = new TestSuite;
+
+            /* @noinspection PhpUnusedLocalVariableInspection */
+            foreach (range(1, $arguments['repeat']) as $step) {
+                $_suite->addTest($suite);
+            }
+
+            $suite = $_suite;
+
+            unset($_suite);
+        }
+
+        $result = $this->createTestResult();
+
+        $listener       = new TestListenerAdapter;
+        $listenerNeeded = false;
+
+        foreach ($this->extensions as $extension) {
+            if ($extension instanceof TestHook) {
+                $listener->add($extension);
+
+                $listenerNeeded = true;
+            }
+        }
+
+        if ($listenerNeeded) {
+            $result->addListener($listener);
+        }
+
+        unset($listener, $listenerNeeded);
+
+        if (!$arguments['convertDeprecationsToExceptions']) {
+            $result->convertDeprecationsToExceptions(false);
+        }
+
+        if (!$arguments['convertErrorsToExceptions']) {
+            $result->convertErrorsToExceptions(false);
+        }
+
+        if (!$arguments['convertNoticesToExceptions']) {
+            $result->convertNoticesToExceptions(false);
+        }
+
+        if (!$arguments['convertWarningsToExceptions']) {
+            $result->convertWarningsToExceptions(false);
+        }
+
+        if ($arguments['stopOnError']) {
+            $result->stopOnError(true);
+        }
+
+        if ($arguments['stopOnFailure']) {
+            $result->stopOnFailure(true);
+        }
+
+        if ($arguments['stopOnWarning']) {
+            $result->stopOnWarning(true);
+        }
+
+        if ($arguments['stopOnIncomplete']) {
+            $result->stopOnIncomplete(true);
+        }
+
+        if ($arguments['stopOnRisky']) {
+            $result->stopOnRisky(true);
+        }
+
+        if ($arguments['stopOnSkipped']) {
+            $result->stopOnSkipped(true);
+        }
+
+        if ($arguments['stopOnDefect']) {
+            $result->stopOnDefect(true);
+        }
+
+        if ($arguments['registerMockObjectsFromTestArgumentsRecursively']) {
+            $result->setRegisterMockObjectsFromTestArgumentsRecursively(true);
+        }
+
+        if ($this->printer === null) {
+            if (isset($arguments['printer'])) {
+                if ($arguments['printer'] instanceof ResultPrinter) {
+                    $this->printer = $arguments['printer'];
+                } elseif (is_string($arguments['printer']) && class_exists($arguments['printer'], false)) {
+                    try {
+                        $reflector = new ReflectionClass($arguments['printer']);
+
+                        if ($reflector->implementsInterface(ResultPrinter::class)) {
+                            $this->printer = $this->createPrinter($arguments['printer'], $arguments);
+                        }
+
+                        // @codeCoverageIgnoreStart
+                    } catch (ReflectionException $e) {
+                        throw new Exception(
+                            $e->getMessage(),
+                            (int) $e->getCode(),
+                            $e
+                        );
+                    }
+                    // @codeCoverageIgnoreEnd
+                }
+            } else {
+                $this->printer = $this->createPrinter(DefaultResultPrinter::class, $arguments);
+            }
+        }
+
+        if (isset($originalExecutionOrder) && $this->printer instanceof CliTestDoxPrinter) {
+            assert($this->printer instanceof CliTestDoxPrinter);
+
+            $this->printer->setOriginalExecutionOrder($originalExecutionOrder);
+            $this->printer->setShowProgressAnimation(!$arguments['noInteraction']);
+        }
+
+        $this->printer->write(
+            Version::getVersionString() . "\n"
+        );
+
+        self::$versionStringPrinted = true;
+
+        foreach ($arguments['listeners'] as $listener) {
+            $result->addListener($listener);
+        }
+
+        $result->addListener($this->printer);
+
+        $coverageFilterFromConfigurationFile = false;
+        $coverageFilterFromOption            = false;
+        $codeCoverageReports                 = 0;
+
+        if (isset($arguments['testdoxHTMLFile'])) {
+            $result->addListener(
+                new HtmlResultPrinter(
+                    $arguments['testdoxHTMLFile'],
+                    $arguments['testdoxGroups'],
+                    $arguments['testdoxExcludeGroups']
+                )
+            );
+        }
+
+        if (isset($arguments['testdoxTextFile'])) {
+            $result->addListener(
+                new TextResultPrinter(
+                    $arguments['testdoxTextFile'],
+                    $arguments['testdoxGroups'],
+                    $arguments['testdoxExcludeGroups']
+                )
+            );
+        }
+
+        if (isset($arguments['testdoxXMLFile'])) {
+            $result->addListener(
+                new XmlResultPrinter(
+                    $arguments['testdoxXMLFile']
+                )
+            );
+        }
+
+        if (isset($arguments['teamcityLogfile'])) {
+            $result->addListener(
+                new TeamCity($arguments['teamcityLogfile'])
+            );
+        }
+
+        if (isset($arguments['junitLogfile'])) {
+            $result->addListener(
+                new JUnit(
+                    $arguments['junitLogfile'],
+                    $arguments['reportUselessTests']
+                )
+            );
+        }
+
+        if (isset($arguments['coverageClover'])) {
+            $codeCoverageReports++;
+        }
+
+        if (isset($arguments['coverageCobertura'])) {
+            $codeCoverageReports++;
+        }
+
+        if (isset($arguments['coverageCrap4J'])) {
+            $codeCoverageReports++;
+        }
+
+        if (isset($arguments['coverageHtml'])) {
+            $codeCoverageReports++;
+        }
+
+        if (isset($arguments['coveragePHP'])) {
+            $codeCoverageReports++;
+        }
+
+        if (isset($arguments['coverageText'])) {
+            $codeCoverageReports++;
+        }
+
+        if (isset($arguments['coverageXml'])) {
+            $codeCoverageReports++;
+        }
+
+        if ($codeCoverageReports > 0 || isset($arguments['xdebugFilterFile'])) {
+            if (isset($arguments['coverageFilter'])) {
+                if (!is_array($arguments['coverageFilter'])) {
+                    $coverageFilterDirectories = [$arguments['coverageFilter']];
+                } else {
+                    $coverageFilterDirectories = $arguments['coverageFilter'];
+                }
+
+                foreach ($coverageFilterDirectories as $coverageFilterDirectory) {
+                    $this->codeCoverageFilter->includeDirectory($coverageFilterDirectory);
+                }
+
+                $coverageFilterFromOption = true;
+            }
+
+            if (isset($arguments['configurationObject'])) {
+                assert($arguments['configurationObject'] instanceof Configuration);
+
+                $codeCoverageConfiguration = $arguments['configurationObject']->codeCoverage();
+
+                if ($codeCoverageConfiguration->hasNonEmptyListOfFilesToBeIncludedInCodeCoverageReport()) {
+                    $coverageFilterFromConfigurationFile = true;
+
+                    (new FilterMapper)->map(
+                        $this->codeCoverageFilter,
+                        $codeCoverageConfiguration
+                    );
+                }
+            }
+        }
+
+        if ($codeCoverageReports > 0) {
+            try {
+                if (isset($codeCoverageConfiguration) &&
+                    ($codeCoverageConfiguration->pathCoverage() || (isset($arguments['pathCoverage']) && $arguments['pathCoverage'] === true))) {
+                    $codeCoverageDriver = (new Selector)->forLineAndPathCoverage($this->codeCoverageFilter);
+                } else {
+                    $codeCoverageDriver = (new Selector)->forLineCoverage($this->codeCoverageFilter);
+                }
+
+                $codeCoverage = new CodeCoverage(
+                    $codeCoverageDriver,
+                    $this->codeCoverageFilter
+                );
+
+                if (isset($codeCoverageConfiguration) && $codeCoverageConfiguration->hasCacheDirectory()) {
+                    $codeCoverage->cacheStaticAnalysis($codeCoverageConfiguration->cacheDirectory()->path());
+                }
+
+                if (isset($arguments['coverageCacheDirectory'])) {
+                    $codeCoverage->cacheStaticAnalysis($arguments['coverageCacheDirectory']);
+                }
+
+                $codeCoverage->excludeSubclassesOfThisClassFromUnintentionallyCoveredCodeCheck(Comparator::class);
+
+                if ($arguments['strictCoverage']) {
+                    $codeCoverage->enableCheckForUnintentionallyCoveredCode();
+                }
+
+                if (isset($arguments['ignoreDeprecatedCodeUnitsFromCodeCoverage'])) {
+                    if ($arguments['ignoreDeprecatedCodeUnitsFromCodeCoverage']) {
+                        $codeCoverage->ignoreDeprecatedCode();
+                    } else {
+                        $codeCoverage->doNotIgnoreDeprecatedCode();
+                    }
+                }
+
+                if (isset($arguments['disableCodeCoverageIgnore'])) {
+                    if ($arguments['disableCodeCoverageIgnore']) {
+                        $codeCoverage->disableAnnotationsForIgnoringCode();
+                    } else {
+                        $codeCoverage->enableAnnotationsForIgnoringCode();
+                    }
+                }
+
+                if (isset($arguments['configurationObject'])) {
+                    $codeCoverageConfiguration = $arguments['configurationObject']->codeCoverage();
+
+                    if ($codeCoverageConfiguration->hasNonEmptyListOfFilesToBeIncludedInCodeCoverageReport()) {
+                        if ($codeCoverageConfiguration->includeUncoveredFiles()) {
+                            $codeCoverage->includeUncoveredFiles();
+                        } else {
+                            $codeCoverage->excludeUncoveredFiles();
+                        }
+
+                        if ($codeCoverageConfiguration->processUncoveredFiles()) {
+                            $codeCoverage->processUncoveredFiles();
+                        } else {
+                            $codeCoverage->doNotProcessUncoveredFiles();
+                        }
+                    }
+                }
+
+                if ($this->codeCoverageFilter->isEmpty()) {
+                    if (!$coverageFilterFromConfigurationFile && !$coverageFilterFromOption) {
+                        $warnings[] = 'No filter is configured, code coverage will not be processed';
+                    } else {
+                        $warnings[] = 'Incorrect filter configuration, code coverage will not be processed';
+                    }
+
+                    unset($codeCoverage);
+                }
+            } catch (CodeCoverageException $e) {
+                $warnings[] = $e->getMessage();
+            }
+        }
+
+        if ($arguments['verbose']) {
+            if (PHP_SAPI === 'phpdbg') {
+                $this->writeMessage('Runtime', 'PHPDBG ' . PHP_VERSION);
+            } else {
+                $runtime = 'PHP ' . PHP_VERSION;
+
+                if (isset($codeCoverageDriver)) {
+                    $runtime .= ' with ' . $codeCoverageDriver->nameAndVersion();
+                }
+
+                $this->writeMessage('Runtime', $runtime);
+            }
+
+            if (isset($arguments['configurationObject'])) {
+                assert($arguments['configurationObject'] instanceof Configuration);
+
+                $this->writeMessage(
+                    'Configuration',
+                    $arguments['configurationObject']->filename()
+                );
+            }
+
+            foreach ($arguments['loadedExtensions'] as $extension) {
+                $this->writeMessage(
+                    'Extension',
+                    $extension
+                );
+            }
+
+            foreach ($arguments['notLoadedExtensions'] as $extension) {
+                $this->writeMessage(
+                    'Extension',
+                    $extension
+                );
+            }
+        }
+
+        if ($arguments['executionOrder'] === TestSuiteSorter::ORDER_RANDOMIZED) {
+            $this->writeMessage(
+                'Random Seed',
+                (string) $arguments['randomOrderSeed']
+            );
+        }
+
+        if (isset($tooFewColumnsRequested)) {
+            $warnings[] = 'Less than 16 columns requested, number of columns set to 16';
+        }
+
+        if ((new Runtime)->discardsComments()) {
+            $warnings[] = 'opcache.save_comments=0 set; annotations will not work';
+        }
+
+        if (isset($arguments['conflictBetweenPrinterClassAndTestdox'])) {
+            $warnings[] = 'Directives printerClass and testdox are mutually exclusive';
+        }
+
+        foreach ($warnings as $warning) {
+            $this->writeMessage('Warning', $warning);
+        }
+
+        if (isset($arguments['configurationObject'])) {
+            assert($arguments['configurationObject'] instanceof Configuration);
+
+            if ($arguments['configurationObject']->hasValidationErrors()) {
+                if ((new SchemaDetector)->detect($arguments['configurationObject']->filename())->detected()) {
+                    $this->writeMessage('Warning', 'Your XML configuration validates against a deprecated schema.');
+                    $this->writeMessage('Suggestion', 'Migrate your XML configuration using "--migrate-configuration"!');
+                } else {
+                    $this->write(
+                        "\n  Warning - The configuration file did not pass validation!\n  The following problems have been detected:\n"
+                    );
+
+                    $this->write($arguments['configurationObject']->validationErrors());
+
+                    $this->write("\n  Test results may not be as expected.\n\n");
+                }
+            }
+        }
+
+        if (isset($arguments['xdebugFilterFile'], $codeCoverageConfiguration)) {
+            $this->write(PHP_EOL . 'Please note that --dump-xdebug-filter and --prepend are deprecated and will be removed in PHPUnit 10.' . PHP_EOL);
+
+            $script = (new XdebugFilterScriptGenerator)->generate($codeCoverageConfiguration);
+
+            if ($arguments['xdebugFilterFile'] !== 'php://stdout' && $arguments['xdebugFilterFile'] !== 'php://stderr' && !Filesystem::createDirectory(dirname($arguments['xdebugFilterFile']))) {
+                $this->write(sprintf('Cannot write Xdebug filter script to %s ' . PHP_EOL, $arguments['xdebugFilterFile']));
+
+                exit(self::EXCEPTION_EXIT);
+            }
+
+            file_put_contents($arguments['xdebugFilterFile'], $script);
+
+            $this->write(sprintf('Wrote Xdebug filter script to %s ' . PHP_EOL . PHP_EOL, $arguments['xdebugFilterFile']));
+
+            exit(self::SUCCESS_EXIT);
+        }
+
+        $this->printer->write("\n");
+
+        if (isset($codeCoverage)) {
+            $result->setCodeCoverage($codeCoverage);
+        }
+
+        $result->beStrictAboutTestsThatDoNotTestAnything($arguments['reportUselessTests']);
+        $result->beStrictAboutOutputDuringTests($arguments['disallowTestOutput']);
+        $result->beStrictAboutTodoAnnotatedTests($arguments['disallowTodoAnnotatedTests']);
+        $result->beStrictAboutResourceUsageDuringSmallTests($arguments['beStrictAboutResourceUsageDuringSmallTests']);
+
+        if ($arguments['enforceTimeLimit'] === true && !(new Invoker)->canInvokeWithTimeout()) {
+            $this->writeMessage('Error', 'PHP extension pcntl is required for enforcing time limits');
+        }
+
+        $result->enforceTimeLimit($arguments['enforceTimeLimit']);
+        $result->setDefaultTimeLimit($arguments['defaultTimeLimit']);
+        $result->setTimeoutForSmallTests($arguments['timeoutForSmallTests']);
+        $result->setTimeoutForMediumTests($arguments['timeoutForMediumTests']);
+        $result->setTimeoutForLargeTests($arguments['timeoutForLargeTests']);
+
+        if (isset($arguments['forceCoversAnnotation']) && $arguments['forceCoversAnnotation'] === true) {
+            $result->forceCoversAnnotation();
+        }
+
+        $this->processSuiteFilters($suite, $arguments);
+        $suite->setRunTestInSeparateProcess($arguments['processIsolation']);
+
+        foreach ($this->extensions as $extension) {
+            if ($extension instanceof BeforeFirstTestHook) {
+                $extension->executeBeforeFirstTest();
+            }
+        }
+
+        $testSuiteWarningsPrinted = false;
+
+        foreach ($suite->warnings() as $warning) {
+            $this->writeMessage('Warning', $warning);
+
+            $testSuiteWarningsPrinted = true;
+        }
+
+        if ($testSuiteWarningsPrinted) {
+            $this->write(PHP_EOL);
+        }
+
+        $suite->run($result);
+
+        foreach ($this->extensions as $extension) {
+            if ($extension instanceof AfterLastTestHook) {
+                $extension->executeAfterLastTest();
+            }
+        }
+
+        $result->flushListeners();
+        $this->printer->printResult($result);
+
+        if (isset($codeCoverage)) {
+            if (isset($arguments['coverageClover'])) {
+                $this->codeCoverageGenerationStart('Clover XML');
+
+                try {
+                    $writer = new CloverReport;
+                    $writer->process($codeCoverage, $arguments['coverageClover']);
+
+                    $this->codeCoverageGenerationSucceeded();
+
+                    unset($writer);
+                } catch (CodeCoverageException $e) {
+                    $this->codeCoverageGenerationFailed($e);
+                }
+            }
+
+            if (isset($arguments['coverageCobertura'])) {
+                $this->codeCoverageGenerationStart('Cobertura XML');
+
+                try {
+                    $writer = new CoberturaReport;
+                    $writer->process($codeCoverage, $arguments['coverageCobertura']);
+
+                    $this->codeCoverageGenerationSucceeded();
+
+                    unset($writer);
+                } catch (CodeCoverageException $e) {
+                    $this->codeCoverageGenerationFailed($e);
+                }
+            }
+
+            if (isset($arguments['coverageCrap4J'])) {
+                $this->codeCoverageGenerationStart('Crap4J XML');
+
+                try {
+                    $writer = new Crap4jReport($arguments['crap4jThreshold']);
+                    $writer->process($codeCoverage, $arguments['coverageCrap4J']);
+
+                    $this->codeCoverageGenerationSucceeded();
+
+                    unset($writer);
+                } catch (CodeCoverageException $e) {
+                    $this->codeCoverageGenerationFailed($e);
+                }
+            }
+
+            if (isset($arguments['coverageHtml'])) {
+                $this->codeCoverageGenerationStart('HTML');
+
+                try {
+                    $writer = new HtmlReport(
+                        $arguments['reportLowUpperBound'],
+                        $arguments['reportHighLowerBound'],
+                        sprintf(
+                            ' and <a href="https://phpunit.de/">PHPUnit %s</a>',
+                            Version::id()
+                        )
+                    );
+
+                    $writer->process($codeCoverage, $arguments['coverageHtml']);
+
+                    $this->codeCoverageGenerationSucceeded();
+
+                    unset($writer);
+                } catch (CodeCoverageException $e) {
+                    $this->codeCoverageGenerationFailed($e);
+                }
+            }
+
+            if (isset($arguments['coveragePHP'])) {
+                $this->codeCoverageGenerationStart('PHP');
+
+                try {
+                    $writer = new PhpReport;
+                    $writer->process($codeCoverage, $arguments['coveragePHP']);
+
+                    $this->codeCoverageGenerationSucceeded();
+
+                    unset($writer);
+                } catch (CodeCoverageException $e) {
+                    $this->codeCoverageGenerationFailed($e);
+                }
+            }
+
+            if (isset($arguments['coverageText'])) {
+                if ($arguments['coverageText'] === 'php://stdout') {
+                    $outputStream = $this->printer;
+                    $colors       = $arguments['colors'] && $arguments['colors'] !== DefaultResultPrinter::COLOR_NEVER;
+                } else {
+                    $outputStream = new Printer($arguments['coverageText']);
+                    $colors       = false;
+                }
+
+                $processor = new TextReport(
+                    $arguments['reportLowUpperBound'],
+                    $arguments['reportHighLowerBound'],
+                    $arguments['coverageTextShowUncoveredFiles'],
+                    $arguments['coverageTextShowOnlySummary']
+                );
+
+                $outputStream->write(
+                    $processor->process($codeCoverage, $colors)
+                );
+            }
+
+            if (isset($arguments['coverageXml'])) {
+                $this->codeCoverageGenerationStart('PHPUnit XML');
+
+                try {
+                    $writer = new XmlReport(Version::id());
+                    $writer->process($codeCoverage, $arguments['coverageXml']);
+
+                    $this->codeCoverageGenerationSucceeded();
+
+                    unset($writer);
+                } catch (CodeCoverageException $e) {
+                    $this->codeCoverageGenerationFailed($e);
+                }
+            }
+        }
+
+        if ($exit) {
+            if (isset($arguments['failOnEmptyTestSuite']) && $arguments['failOnEmptyTestSuite'] === true && count($result) === 0) {
+                exit(self::FAILURE_EXIT);
+            }
+
+            if ($result->wasSuccessfulIgnoringWarnings()) {
+                if ($arguments['failOnRisky'] && !$result->allHarmless()) {
+                    exit(self::FAILURE_EXIT);
+                }
+
+                if ($arguments['failOnWarning'] && $result->warningCount() > 0) {
+                    exit(self::FAILURE_EXIT);
+                }
+
+                if ($arguments['failOnIncomplete'] && $result->notImplementedCount() > 0) {
+                    exit(self::FAILURE_EXIT);
+                }
+
+                if ($arguments['failOnSkipped'] && $result->skippedCount() > 0) {
+                    exit(self::FAILURE_EXIT);
+                }
+
+                exit(self::SUCCESS_EXIT);
+            }
+
+            if ($result->errorCount() > 0) {
+                exit(self::EXCEPTION_EXIT);
+            }
+
+            if ($result->failureCount() > 0) {
+                exit(self::FAILURE_EXIT);
+            }
+        }
+
+        return $result;
+    }
+
+    /**
+     * Returns the loader to be used.
+     */
+    public function getLoader(): TestSuiteLoader
+    {
+        if ($this->loader === null) {
+            $this->loader = new StandardTestSuiteLoader;
+        }
+
+        return $this->loader;
+    }
+
+    public function addExtension(Hook $extension): void
+    {
+        $this->extensions[] = $extension;
+    }
+
+    /**
+     * Override to define how to handle a failed loading of
+     * a test suite.
+     */
+    protected function runFailed(string $message): void
+    {
+        $this->write($message . PHP_EOL);
+
+        exit(self::FAILURE_EXIT);
+    }
+
+    private function createTestResult(): TestResult
+    {
+        return new TestResult;
+    }
+
+    private function write(string $buffer): void
+    {
+        if (PHP_SAPI !== 'cli' && PHP_SAPI !== 'phpdbg') {
+            $buffer = htmlspecialchars($buffer);
+        }
+
+        if ($this->printer !== null) {
+            $this->printer->write($buffer);
+        } else {
+            print $buffer;
+        }
+    }
+
+    /**
+     * @throws \PHPUnit\TextUI\XmlConfiguration\Exception
+     * @throws Exception
+     */
+    private function handleConfiguration(array &$arguments): void
+    {
+        if (!isset($arguments['configurationObject']) && isset($arguments['configuration'])) {
+            $arguments['configurationObject'] = (new Loader)->load($arguments['configuration']);
+        }
+
+        $arguments['debug']     = $arguments['debug'] ?? false;
+        $arguments['filter']    = $arguments['filter'] ?? false;
+        $arguments['listeners'] = $arguments['listeners'] ?? [];
+
+        if (isset($arguments['configurationObject'])) {
+            (new PhpHandler)->handle($arguments['configurationObject']->php());
+
+            $codeCoverageConfiguration = $arguments['configurationObject']->codeCoverage();
+
+            if (!isset($arguments['noCoverage'])) {
+                if (!isset($arguments['coverageClover']) && $codeCoverageConfiguration->hasClover()) {
+                    $arguments['coverageClover'] = $codeCoverageConfiguration->clover()->target()->path();
+                }
+
+                if (!isset($arguments['coverageCobertura']) && $codeCoverageConfiguration->hasCobertura()) {
+                    $arguments['coverageCobertura'] = $codeCoverageConfiguration->cobertura()->target()->path();
+                }
+
+                if (!isset($arguments['coverageCrap4J']) && $codeCoverageConfiguration->hasCrap4j()) {
+                    $arguments['coverageCrap4J'] = $codeCoverageConfiguration->crap4j()->target()->path();
+
+                    if (!isset($arguments['crap4jThreshold'])) {
+                        $arguments['crap4jThreshold'] = $codeCoverageConfiguration->crap4j()->threshold();
+                    }
+                }
+
+                if (!isset($arguments['coverageHtml']) && $codeCoverageConfiguration->hasHtml()) {
+                    $arguments['coverageHtml'] = $codeCoverageConfiguration->html()->target()->path();
+
+                    if (!isset($arguments['reportLowUpperBound'])) {
+                        $arguments['reportLowUpperBound'] = $codeCoverageConfiguration->html()->lowUpperBound();
+                    }
+
+                    if (!isset($arguments['reportHighLowerBound'])) {
+                        $arguments['reportHighLowerBound'] = $codeCoverageConfiguration->html()->highLowerBound();
+                    }
+                }
+
+                if (!isset($arguments['coveragePHP']) && $codeCoverageConfiguration->hasPhp()) {
+                    $arguments['coveragePHP'] = $codeCoverageConfiguration->php()->target()->path();
+                }
+
+                if (!isset($arguments['coverageText']) && $codeCoverageConfiguration->hasText()) {
+                    $arguments['coverageText']                   = $codeCoverageConfiguration->text()->target()->path();
+                    $arguments['coverageTextShowUncoveredFiles'] = $codeCoverageConfiguration->text()->showUncoveredFiles();
+                    $arguments['coverageTextShowOnlySummary']    = $codeCoverageConfiguration->text()->showOnlySummary();
+                }
+
+                if (!isset($arguments['coverageXml']) && $codeCoverageConfiguration->hasXml()) {
+                    $arguments['coverageXml'] = $codeCoverageConfiguration->xml()->target()->path();
+                }
+            }
+
+            $phpunitConfiguration = $arguments['configurationObject']->phpunit();
+
+            $arguments['backupGlobals']                                   = $arguments['backupGlobals'] ?? $phpunitConfiguration->backupGlobals();
+            $arguments['backupStaticAttributes']                          = $arguments['backupStaticAttributes'] ?? $phpunitConfiguration->backupStaticAttributes();
+            $arguments['beStrictAboutChangesToGlobalState']               = $arguments['beStrictAboutChangesToGlobalState'] ?? $phpunitConfiguration->beStrictAboutChangesToGlobalState();
+            $arguments['cacheResult']                                     = $arguments['cacheResult'] ?? $phpunitConfiguration->cacheResult();
+            $arguments['colors']                                          = $arguments['colors'] ?? $phpunitConfiguration->colors();
+            $arguments['convertDeprecationsToExceptions']                 = $arguments['convertDeprecationsToExceptions'] ?? $phpunitConfiguration->convertDeprecationsToExceptions();
+            $arguments['convertErrorsToExceptions']                       = $arguments['convertErrorsToExceptions'] ?? $phpunitConfiguration->convertErrorsToExceptions();
+            $arguments['convertNoticesToExceptions']                      = $arguments['convertNoticesToExceptions'] ?? $phpunitConfiguration->convertNoticesToExceptions();
+            $arguments['convertWarningsToExceptions']                     = $arguments['convertWarningsToExceptions'] ?? $phpunitConfiguration->convertWarningsToExceptions();
+            $arguments['processIsolation']                                = $arguments['processIsolation'] ?? $phpunitConfiguration->processIsolation();
+            $arguments['stopOnDefect']                                    = $arguments['stopOnDefect'] ?? $phpunitConfiguration->stopOnDefect();
+            $arguments['stopOnError']                                     = $arguments['stopOnError'] ?? $phpunitConfiguration->stopOnError();
+            $arguments['stopOnFailure']                                   = $arguments['stopOnFailure'] ?? $phpunitConfiguration->stopOnFailure();
+            $arguments['stopOnWarning']                                   = $arguments['stopOnWarning'] ?? $phpunitConfiguration->stopOnWarning();
+            $arguments['stopOnIncomplete']                                = $arguments['stopOnIncomplete'] ?? $phpunitConfiguration->stopOnIncomplete();
+            $arguments['stopOnRisky']                                     = $arguments['stopOnRisky'] ?? $phpunitConfiguration->stopOnRisky();
+            $arguments['stopOnSkipped']                                   = $arguments['stopOnSkipped'] ?? $phpunitConfiguration->stopOnSkipped();
+            $arguments['failOnEmptyTestSuite']                            = $arguments['failOnEmptyTestSuite'] ?? $phpunitConfiguration->failOnEmptyTestSuite();
+            $arguments['failOnIncomplete']                                = $arguments['failOnIncomplete'] ?? $phpunitConfiguration->failOnIncomplete();
+            $arguments['failOnRisky']                                     = $arguments['failOnRisky'] ?? $phpunitConfiguration->failOnRisky();
+            $arguments['failOnSkipped']                                   = $arguments['failOnSkipped'] ?? $phpunitConfiguration->failOnSkipped();
+            $arguments['failOnWarning']                                   = $arguments['failOnWarning'] ?? $phpunitConfiguration->failOnWarning();
+            $arguments['enforceTimeLimit']                                = $arguments['enforceTimeLimit'] ?? $phpunitConfiguration->enforceTimeLimit();
+            $arguments['defaultTimeLimit']                                = $arguments['defaultTimeLimit'] ?? $phpunitConfiguration->defaultTimeLimit();
+            $arguments['timeoutForSmallTests']                            = $arguments['timeoutForSmallTests'] ?? $phpunitConfiguration->timeoutForSmallTests();
+            $arguments['timeoutForMediumTests']                           = $arguments['timeoutForMediumTests'] ?? $phpunitConfiguration->timeoutForMediumTests();
+            $arguments['timeoutForLargeTests']                            = $arguments['timeoutForLargeTests'] ?? $phpunitConfiguration->timeoutForLargeTests();
+            $arguments['reportUselessTests']                              = $arguments['reportUselessTests'] ?? $phpunitConfiguration->beStrictAboutTestsThatDoNotTestAnything();
+            $arguments['strictCoverage']                                  = $arguments['strictCoverage'] ?? $phpunitConfiguration->beStrictAboutCoversAnnotation();
+            $arguments['ignoreDeprecatedCodeUnitsFromCodeCoverage']       = $arguments['ignoreDeprecatedCodeUnitsFromCodeCoverage'] ?? $codeCoverageConfiguration->ignoreDeprecatedCodeUnits();
+            $arguments['disallowTestOutput']                              = $arguments['disallowTestOutput'] ?? $phpunitConfiguration->beStrictAboutOutputDuringTests();
+            $arguments['disallowTodoAnnotatedTests']                      = $arguments['disallowTodoAnnotatedTests'] ?? $phpunitConfiguration->beStrictAboutTodoAnnotatedTests();
+            $arguments['beStrictAboutResourceUsageDuringSmallTests']      = $arguments['beStrictAboutResourceUsageDuringSmallTests'] ?? $phpunitConfiguration->beStrictAboutResourceUsageDuringSmallTests();
+            $arguments['verbose']                                         = $arguments['verbose'] ?? $phpunitConfiguration->verbose();
+            $arguments['reverseDefectList']                               = $arguments['reverseDefectList'] ?? $phpunitConfiguration->reverseDefectList();
+            $arguments['forceCoversAnnotation']                           = $arguments['forceCoversAnnotation'] ?? $phpunitConfiguration->forceCoversAnnotation();
+            $arguments['disableCodeCoverageIgnore']                       = $arguments['disableCodeCoverageIgnore'] ?? $codeCoverageConfiguration->disableCodeCoverageIgnore();
+            $arguments['registerMockObjectsFromTestArgumentsRecursively'] = $arguments['registerMockObjectsFromTestArgumentsRecursively'] ?? $phpunitConfiguration->registerMockObjectsFromTestArgumentsRecursively();
+            $arguments['noInteraction']                                   = $arguments['noInteraction'] ?? $phpunitConfiguration->noInteraction();
+            $arguments['executionOrder']                                  = $arguments['executionOrder'] ?? $phpunitConfiguration->executionOrder();
+            $arguments['resolveDependencies']                             = $arguments['resolveDependencies'] ?? $phpunitConfiguration->resolveDependencies();
+
+            if (!isset($arguments['bootstrap']) && $phpunitConfiguration->hasBootstrap()) {
+                $arguments['bootstrap'] = $phpunitConfiguration->bootstrap();
+            }
+
+            if (!isset($arguments['cacheResultFile']) && $phpunitConfiguration->hasCacheResultFile()) {
+                $arguments['cacheResultFile'] = $phpunitConfiguration->cacheResultFile();
+            }
+
+            if (!isset($arguments['executionOrderDefects'])) {
+                $arguments['executionOrderDefects'] = $phpunitConfiguration->defectsFirst() ? TestSuiteSorter::ORDER_DEFECTS_FIRST : TestSuiteSorter::ORDER_DEFAULT;
+            }
+
+            if ($phpunitConfiguration->conflictBetweenPrinterClassAndTestdox()) {
+                $arguments['conflictBetweenPrinterClassAndTestdox'] = true;
+            }
+
+            $groupCliArgs = [];
+
+            if (!empty($arguments['groups'])) {
+                $groupCliArgs = $arguments['groups'];
+            }
+
+            $groupConfiguration = $arguments['configurationObject']->groups();
+
+            if (!isset($arguments['groups']) && $groupConfiguration->hasInclude()) {
+                $arguments['groups'] = $groupConfiguration->include()->asArrayOfStrings();
+            }
+
+            if (!isset($arguments['excludeGroups']) && $groupConfiguration->hasExclude()) {
+                $arguments['excludeGroups'] = array_diff($groupConfiguration->exclude()->asArrayOfStrings(), $groupCliArgs);
+            }
+
+            $extensionHandler = new ExtensionHandler;
+
+            foreach ($arguments['configurationObject']->extensions() as $extension) {
+                $extensionHandler->registerExtension($extension, $this);
+            }
+
+            foreach ($arguments['configurationObject']->listeners() as $listener) {
+                $arguments['listeners'][] = $extensionHandler->createTestListenerInstance($listener);
+            }
+
+            unset($extensionHandler);
+
+            foreach ($arguments['unavailableExtensions'] as $extension) {
+                $arguments['warnings'][] = sprintf(
+                    'Extension "%s" is not available',
+                    $extension
+                );
+            }
+
+            $loggingConfiguration = $arguments['configurationObject']->logging();
+
+            if (!isset($arguments['noLogging'])) {
+                if ($loggingConfiguration->hasText()) {
+                    $arguments['listeners'][] = new DefaultResultPrinter(
+                        $loggingConfiguration->text()->target()->path(),
+                        true
+                    );
+                }
+
+                if (!isset($arguments['teamcityLogfile']) && $loggingConfiguration->hasTeamCity()) {
+                    $arguments['teamcityLogfile'] = $loggingConfiguration->teamCity()->target()->path();
+                }
+
+                if (!isset($arguments['junitLogfile']) && $loggingConfiguration->hasJunit()) {
+                    $arguments['junitLogfile'] = $loggingConfiguration->junit()->target()->path();
+                }
+
+                if (!isset($arguments['testdoxHTMLFile']) && $loggingConfiguration->hasTestDoxHtml()) {
+                    $arguments['testdoxHTMLFile'] = $loggingConfiguration->testDoxHtml()->target()->path();
+                }
+
+                if (!isset($arguments['testdoxTextFile']) && $loggingConfiguration->hasTestDoxText()) {
+                    $arguments['testdoxTextFile'] = $loggingConfiguration->testDoxText()->target()->path();
+                }
+
+                if (!isset($arguments['testdoxXMLFile']) && $loggingConfiguration->hasTestDoxXml()) {
+                    $arguments['testdoxXMLFile'] = $loggingConfiguration->testDoxXml()->target()->path();
+                }
+            }
+
+            $testdoxGroupConfiguration = $arguments['configurationObject']->testdoxGroups();
+
+            if (!isset($arguments['testdoxGroups']) && $testdoxGroupConfiguration->hasInclude()) {
+                $arguments['testdoxGroups'] = $testdoxGroupConfiguration->include()->asArrayOfStrings();
+            }
+
+            if (!isset($arguments['testdoxExcludeGroups']) && $testdoxGroupConfiguration->hasExclude()) {
+                $arguments['testdoxExcludeGroups'] = $testdoxGroupConfiguration->exclude()->asArrayOfStrings();
+            }
+        }
+
+        $extensionHandler = new ExtensionHandler;
+
+        foreach ($arguments['extensions'] as $extension) {
+            $extensionHandler->registerExtension($extension, $this);
+        }
+
+        unset($extensionHandler);
+
+        $arguments['backupGlobals']                                   = $arguments['backupGlobals'] ?? null;
+        $arguments['backupStaticAttributes']                          = $arguments['backupStaticAttributes'] ?? null;
+        $arguments['beStrictAboutChangesToGlobalState']               = $arguments['beStrictAboutChangesToGlobalState'] ?? null;
+        $arguments['beStrictAboutResourceUsageDuringSmallTests']      = $arguments['beStrictAboutResourceUsageDuringSmallTests'] ?? false;
+        $arguments['cacheResult']                                     = $arguments['cacheResult'] ?? true;
+        $arguments['colors']                                          = $arguments['colors'] ?? DefaultResultPrinter::COLOR_DEFAULT;
+        $arguments['columns']                                         = $arguments['columns'] ?? 80;
+        $arguments['convertDeprecationsToExceptions']                 = $arguments['convertDeprecationsToExceptions'] ?? true;
+        $arguments['convertErrorsToExceptions']                       = $arguments['convertErrorsToExceptions'] ?? true;
+        $arguments['convertNoticesToExceptions']                      = $arguments['convertNoticesToExceptions'] ?? true;
+        $arguments['convertWarningsToExceptions']                     = $arguments['convertWarningsToExceptions'] ?? true;
+        $arguments['crap4jThreshold']                                 = $arguments['crap4jThreshold'] ?? 30;
+        $arguments['disallowTestOutput']                              = $arguments['disallowTestOutput'] ?? false;
+        $arguments['disallowTodoAnnotatedTests']                      = $arguments['disallowTodoAnnotatedTests'] ?? false;
+        $arguments['defaultTimeLimit']                                = $arguments['defaultTimeLimit'] ?? 0;
+        $arguments['enforceTimeLimit']                                = $arguments['enforceTimeLimit'] ?? false;
+        $arguments['excludeGroups']                                   = $arguments['excludeGroups'] ?? [];
+        $arguments['executionOrder']                                  = $arguments['executionOrder'] ?? TestSuiteSorter::ORDER_DEFAULT;
+        $arguments['executionOrderDefects']                           = $arguments['executionOrderDefects'] ?? TestSuiteSorter::ORDER_DEFAULT;
+        $arguments['failOnIncomplete']                                = $arguments['failOnIncomplete'] ?? false;
+        $arguments['failOnRisky']                                     = $arguments['failOnRisky'] ?? false;
+        $arguments['failOnSkipped']                                   = $arguments['failOnSkipped'] ?? false;
+        $arguments['failOnWarning']                                   = $arguments['failOnWarning'] ?? false;
+        $arguments['groups']                                          = $arguments['groups'] ?? [];
+        $arguments['noInteraction']                                   = $arguments['noInteraction'] ?? false;
+        $arguments['processIsolation']                                = $arguments['processIsolation'] ?? false;
+        $arguments['randomOrderSeed']                                 = $arguments['randomOrderSeed'] ?? time();
+        $arguments['registerMockObjectsFromTestArgumentsRecursively'] = $arguments['registerMockObjectsFromTestArgumentsRecursively'] ?? false;
+        $arguments['repeat']                                          = $arguments['repeat'] ?? false;
+        $arguments['reportHighLowerBound']                            = $arguments['reportHighLowerBound'] ?? 90;
+        $arguments['reportLowUpperBound']                             = $arguments['reportLowUpperBound'] ?? 50;
+        $arguments['reportUselessTests']                              = $arguments['reportUselessTests'] ?? true;
+        $arguments['reverseList']                                     = $arguments['reverseList'] ?? false;
+        $arguments['resolveDependencies']                             = $arguments['resolveDependencies'] ?? true;
+        $arguments['stopOnError']                                     = $arguments['stopOnError'] ?? false;
+        $arguments['stopOnFailure']                                   = $arguments['stopOnFailure'] ?? false;
+        $arguments['stopOnIncomplete']                                = $arguments['stopOnIncomplete'] ?? false;
+        $arguments['stopOnRisky']                                     = $arguments['stopOnRisky'] ?? false;
+        $arguments['stopOnSkipped']                                   = $arguments['stopOnSkipped'] ?? false;
+        $arguments['stopOnWarning']                                   = $arguments['stopOnWarning'] ?? false;
+        $arguments['stopOnDefect']                                    = $arguments['stopOnDefect'] ?? false;
+        $arguments['strictCoverage']                                  = $arguments['strictCoverage'] ?? false;
+        $arguments['testdoxExcludeGroups']                            = $arguments['testdoxExcludeGroups'] ?? [];
+        $arguments['testdoxGroups']                                   = $arguments['testdoxGroups'] ?? [];
+        $arguments['timeoutForLargeTests']                            = $arguments['timeoutForLargeTests'] ?? 60;
+        $arguments['timeoutForMediumTests']                           = $arguments['timeoutForMediumTests'] ?? 10;
+        $arguments['timeoutForSmallTests']                            = $arguments['timeoutForSmallTests'] ?? 1;
+        $arguments['verbose']                                         = $arguments['verbose'] ?? false;
+    }
+
+    private function processSuiteFilters(TestSuite $suite, array $arguments): void
+    {
+        if (!$arguments['filter'] &&
+            empty($arguments['groups']) &&
+            empty($arguments['excludeGroups']) &&
+            empty($arguments['testsCovering']) &&
+            empty($arguments['testsUsing'])) {
+            return;
+        }
+
+        $filterFactory = new Factory;
+
+        if (!empty($arguments['excludeGroups'])) {
+            $filterFactory->addFilter(
+                new ReflectionClass(ExcludeGroupFilterIterator::class),
+                $arguments['excludeGroups']
+            );
+        }
+
+        if (!empty($arguments['groups'])) {
+            $filterFactory->addFilter(
+                new ReflectionClass(IncludeGroupFilterIterator::class),
+                $arguments['groups']
+            );
+        }
+
+        if (!empty($arguments['testsCovering'])) {
+            $filterFactory->addFilter(
+                new ReflectionClass(IncludeGroupFilterIterator::class),
+                array_map(
+                    static function (string $name): string {
+                        return '__phpunit_covers_' . $name;
+                    },
+                    $arguments['testsCovering']
+                )
+            );
+        }
+
+        if (!empty($arguments['testsUsing'])) {
+            $filterFactory->addFilter(
+                new ReflectionClass(IncludeGroupFilterIterator::class),
+                array_map(
+                    static function (string $name): string {
+                        return '__phpunit_uses_' . $name;
+                    },
+                    $arguments['testsUsing']
+                )
+            );
+        }
+
+        if ($arguments['filter']) {
+            $filterFactory->addFilter(
+                new ReflectionClass(NameFilterIterator::class),
+                $arguments['filter']
+            );
+        }
+
+        $suite->injectFilter($filterFactory);
+    }
+
+    private function writeMessage(string $type, string $message): void
+    {
+        if (!$this->messagePrinted) {
+            $this->write("\n");
+        }
+
+        $this->write(
+            sprintf(
+                "%-15s%s\n",
+                $type . ':',
+                $message
+            )
+        );
+
+        $this->messagePrinted = true;
+    }
+
+    private function createPrinter(string $class, array $arguments): ResultPrinter
+    {
+        $object = new $class(
+            (isset($arguments['stderr']) && $arguments['stderr'] === true) ? 'php://stderr' : null,
+            $arguments['verbose'],
+            $arguments['colors'],
+            $arguments['debug'],
+            $arguments['columns'],
+            $arguments['reverseList']
+        );
+
+        assert($object instanceof ResultPrinter);
+
+        return $object;
+    }
+
+    private function codeCoverageGenerationStart(string $format): void
+    {
+        $this->printer->write(
+            sprintf(
+                "\nGenerating code coverage report in %s format ... ",
+                $format
+            )
+        );
+
+        $this->timer->start();
+    }
+
+    private function codeCoverageGenerationSucceeded(): void
+    {
+        $this->printer->write(
+            sprintf(
+                "done [%s]\n",
+                $this->timer->stop()->asString()
+            )
+        );
+    }
+
+    private function codeCoverageGenerationFailed(\Exception $e): void
+    {
+        $this->printer->write(
+            sprintf(
+                "failed [%s]\n%s\n",
+                $this->timer->stop()->asString(),
+                $e->getMessage()
+            )
+        );
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/TextUI/TestSuiteMapper.php b/vendor/phpunit/phpunit/src/TextUI/TestSuiteMapper.php
new file mode 100644
index 0000000000000000000000000000000000000000..8a703aeeab55df0fe37779df918a4ca27af0e98d
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/TextUI/TestSuiteMapper.php
@@ -0,0 +1,103 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\TextUI;
+
+use const PHP_VERSION;
+use function explode;
+use function in_array;
+use function is_dir;
+use function is_file;
+use function strpos;
+use function version_compare;
+use PHPUnit\Framework\Exception as FrameworkException;
+use PHPUnit\Framework\TestSuite as TestSuiteObject;
+use PHPUnit\TextUI\XmlConfiguration\TestSuiteCollection;
+use SebastianBergmann\FileIterator\Facade;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class TestSuiteMapper
+{
+    /**
+     * @throws RuntimeException
+     * @throws TestDirectoryNotFoundException
+     * @throws TestFileNotFoundException
+     */
+    public function map(TestSuiteCollection $configuration, string $filter): TestSuiteObject
+    {
+        try {
+            $filterAsArray = $filter ? explode(',', $filter) : [];
+            $result        = new TestSuiteObject;
+
+            foreach ($configuration as $testSuiteConfiguration) {
+                if (!empty($filterAsArray) && !in_array($testSuiteConfiguration->name(), $filterAsArray, true)) {
+                    continue;
+                }
+
+                $testSuite      = new TestSuiteObject($testSuiteConfiguration->name());
+                $testSuiteEmpty = true;
+
+                foreach ($testSuiteConfiguration->directories() as $directory) {
+                    if (!version_compare(PHP_VERSION, $directory->phpVersion(), $directory->phpVersionOperator()->asString())) {
+                        continue;
+                    }
+
+                    $exclude = [];
+
+                    foreach ($testSuiteConfiguration->exclude()->asArray() as $file) {
+                        $exclude[] = $file->path();
+                    }
+
+                    $files = (new Facade)->getFilesAsArray(
+                        $directory->path(),
+                        $directory->suffix(),
+                        $directory->prefix(),
+                        $exclude
+                    );
+
+                    if (!empty($files)) {
+                        $testSuite->addTestFiles($files);
+
+                        $testSuiteEmpty = false;
+                    } elseif (strpos($directory->path(), '*') === false && !is_dir($directory->path())) {
+                        throw new TestDirectoryNotFoundException($directory->path());
+                    }
+                }
+
+                foreach ($testSuiteConfiguration->files() as $file) {
+                    if (!is_file($file->path())) {
+                        throw new TestFileNotFoundException($file->path());
+                    }
+
+                    if (!version_compare(PHP_VERSION, $file->phpVersion(), $file->phpVersionOperator()->asString())) {
+                        continue;
+                    }
+
+                    $testSuite->addTestFile($file->path());
+
+                    $testSuiteEmpty = false;
+                }
+
+                if (!$testSuiteEmpty) {
+                    $result->addTest($testSuite);
+                }
+            }
+
+            return $result;
+        } catch (FrameworkException $e) {
+            throw new RuntimeException(
+                $e->getMessage(),
+                (int) $e->getCode(),
+                $e
+            );
+        }
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/CodeCoverage/CodeCoverage.php b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/CodeCoverage/CodeCoverage.php
new file mode 100644
index 0000000000000000000000000000000000000000..33cbea3213a62f3f4ec1510cd46bc36266297992
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/CodeCoverage/CodeCoverage.php
@@ -0,0 +1,362 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\TextUI\XmlConfiguration\CodeCoverage;
+
+use function count;
+use PHPUnit\TextUI\XmlConfiguration\CodeCoverage\Filter\DirectoryCollection;
+use PHPUnit\TextUI\XmlConfiguration\CodeCoverage\Report\Clover;
+use PHPUnit\TextUI\XmlConfiguration\CodeCoverage\Report\Cobertura;
+use PHPUnit\TextUI\XmlConfiguration\CodeCoverage\Report\Crap4j;
+use PHPUnit\TextUI\XmlConfiguration\CodeCoverage\Report\Html;
+use PHPUnit\TextUI\XmlConfiguration\CodeCoverage\Report\Php;
+use PHPUnit\TextUI\XmlConfiguration\CodeCoverage\Report\Text;
+use PHPUnit\TextUI\XmlConfiguration\CodeCoverage\Report\Xml;
+use PHPUnit\TextUI\XmlConfiguration\Directory;
+use PHPUnit\TextUI\XmlConfiguration\Exception;
+use PHPUnit\TextUI\XmlConfiguration\FileCollection;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ * @psalm-immutable
+ */
+final class CodeCoverage
+{
+    /**
+     * @var ?Directory
+     */
+    private $cacheDirectory;
+
+    /**
+     * @var DirectoryCollection
+     */
+    private $directories;
+
+    /**
+     * @var FileCollection
+     */
+    private $files;
+
+    /**
+     * @var DirectoryCollection
+     */
+    private $excludeDirectories;
+
+    /**
+     * @var FileCollection
+     */
+    private $excludeFiles;
+
+    /**
+     * @var bool
+     */
+    private $pathCoverage;
+
+    /**
+     * @var bool
+     */
+    private $includeUncoveredFiles;
+
+    /**
+     * @var bool
+     */
+    private $processUncoveredFiles;
+
+    /**
+     * @var bool
+     */
+    private $ignoreDeprecatedCodeUnits;
+
+    /**
+     * @var bool
+     */
+    private $disableCodeCoverageIgnore;
+
+    /**
+     * @var ?Clover
+     */
+    private $clover;
+
+    /**
+     * @var ?Cobertura
+     */
+    private $cobertura;
+
+    /**
+     * @var ?Crap4j
+     */
+    private $crap4j;
+
+    /**
+     * @var ?Html
+     */
+    private $html;
+
+    /**
+     * @var ?Php
+     */
+    private $php;
+
+    /**
+     * @var ?Text
+     */
+    private $text;
+
+    /**
+     * @var ?Xml
+     */
+    private $xml;
+
+    public function __construct(?Directory $cacheDirectory, DirectoryCollection $directories, FileCollection $files, DirectoryCollection $excludeDirectories, FileCollection $excludeFiles, bool $pathCoverage, bool $includeUncoveredFiles, bool $processUncoveredFiles, bool $ignoreDeprecatedCodeUnits, bool $disableCodeCoverageIgnore, ?Clover $clover, ?Cobertura $cobertura, ?Crap4j $crap4j, ?Html $html, ?Php $php, ?Text $text, ?Xml $xml)
+    {
+        $this->cacheDirectory            = $cacheDirectory;
+        $this->directories               = $directories;
+        $this->files                     = $files;
+        $this->excludeDirectories        = $excludeDirectories;
+        $this->excludeFiles              = $excludeFiles;
+        $this->pathCoverage              = $pathCoverage;
+        $this->includeUncoveredFiles     = $includeUncoveredFiles;
+        $this->processUncoveredFiles     = $processUncoveredFiles;
+        $this->ignoreDeprecatedCodeUnits = $ignoreDeprecatedCodeUnits;
+        $this->disableCodeCoverageIgnore = $disableCodeCoverageIgnore;
+        $this->clover                    = $clover;
+        $this->cobertura                 = $cobertura;
+        $this->crap4j                    = $crap4j;
+        $this->html                      = $html;
+        $this->php                       = $php;
+        $this->text                      = $text;
+        $this->xml                       = $xml;
+    }
+
+    /**
+     * @psalm-assert-if-true !null $this->cacheDirectory
+     */
+    public function hasCacheDirectory(): bool
+    {
+        return $this->cacheDirectory !== null;
+    }
+
+    /**
+     * @throws Exception
+     */
+    public function cacheDirectory(): Directory
+    {
+        if (!$this->hasCacheDirectory()) {
+            throw new Exception(
+                'No cache directory has been configured'
+            );
+        }
+
+        return $this->cacheDirectory;
+    }
+
+    public function hasNonEmptyListOfFilesToBeIncludedInCodeCoverageReport(): bool
+    {
+        return count($this->directories) > 0 || count($this->files) > 0;
+    }
+
+    public function directories(): DirectoryCollection
+    {
+        return $this->directories;
+    }
+
+    public function files(): FileCollection
+    {
+        return $this->files;
+    }
+
+    public function excludeDirectories(): DirectoryCollection
+    {
+        return $this->excludeDirectories;
+    }
+
+    public function excludeFiles(): FileCollection
+    {
+        return $this->excludeFiles;
+    }
+
+    public function pathCoverage(): bool
+    {
+        return $this->pathCoverage;
+    }
+
+    public function includeUncoveredFiles(): bool
+    {
+        return $this->includeUncoveredFiles;
+    }
+
+    public function ignoreDeprecatedCodeUnits(): bool
+    {
+        return $this->ignoreDeprecatedCodeUnits;
+    }
+
+    public function disableCodeCoverageIgnore(): bool
+    {
+        return $this->disableCodeCoverageIgnore;
+    }
+
+    public function processUncoveredFiles(): bool
+    {
+        return $this->processUncoveredFiles;
+    }
+
+    /**
+     * @psalm-assert-if-true !null $this->clover
+     */
+    public function hasClover(): bool
+    {
+        return $this->clover !== null;
+    }
+
+    /**
+     * @throws Exception
+     */
+    public function clover(): Clover
+    {
+        if (!$this->hasClover()) {
+            throw new Exception(
+                'Code Coverage report "Clover XML" has not been configured'
+            );
+        }
+
+        return $this->clover;
+    }
+
+    /**
+     * @psalm-assert-if-true !null $this->cobertura
+     */
+    public function hasCobertura(): bool
+    {
+        return $this->cobertura !== null;
+    }
+
+    /**
+     * @throws Exception
+     */
+    public function cobertura(): Cobertura
+    {
+        if (!$this->hasCobertura()) {
+            throw new Exception(
+                'Code Coverage report "Cobertura XML" has not been configured'
+            );
+        }
+
+        return $this->cobertura;
+    }
+
+    /**
+     * @psalm-assert-if-true !null $this->crap4j
+     */
+    public function hasCrap4j(): bool
+    {
+        return $this->crap4j !== null;
+    }
+
+    /**
+     * @throws Exception
+     */
+    public function crap4j(): Crap4j
+    {
+        if (!$this->hasCrap4j()) {
+            throw new Exception(
+                'Code Coverage report "Crap4J" has not been configured'
+            );
+        }
+
+        return $this->crap4j;
+    }
+
+    /**
+     * @psalm-assert-if-true !null $this->html
+     */
+    public function hasHtml(): bool
+    {
+        return $this->html !== null;
+    }
+
+    /**
+     * @throws Exception
+     */
+    public function html(): Html
+    {
+        if (!$this->hasHtml()) {
+            throw new Exception(
+                'Code Coverage report "HTML" has not been configured'
+            );
+        }
+
+        return $this->html;
+    }
+
+    /**
+     * @psalm-assert-if-true !null $this->php
+     */
+    public function hasPhp(): bool
+    {
+        return $this->php !== null;
+    }
+
+    /**
+     * @throws Exception
+     */
+    public function php(): Php
+    {
+        if (!$this->hasPhp()) {
+            throw new Exception(
+                'Code Coverage report "PHP" has not been configured'
+            );
+        }
+
+        return $this->php;
+    }
+
+    /**
+     * @psalm-assert-if-true !null $this->text
+     */
+    public function hasText(): bool
+    {
+        return $this->text !== null;
+    }
+
+    /**
+     * @throws Exception
+     */
+    public function text(): Text
+    {
+        if (!$this->hasText()) {
+            throw new Exception(
+                'Code Coverage report "Text" has not been configured'
+            );
+        }
+
+        return $this->text;
+    }
+
+    /**
+     * @psalm-assert-if-true !null $this->xml
+     */
+    public function hasXml(): bool
+    {
+        return $this->xml !== null;
+    }
+
+    /**
+     * @throws Exception
+     */
+    public function xml(): Xml
+    {
+        if (!$this->hasXml()) {
+            throw new Exception(
+                'Code Coverage report "XML" has not been configured'
+            );
+        }
+
+        return $this->xml;
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/CodeCoverage/Filter/Directory.php b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/CodeCoverage/Filter/Directory.php
new file mode 100644
index 0000000000000000000000000000000000000000..3bf99c39dbd9b7efc38cdc680a4c1d6c09366f62
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/CodeCoverage/Filter/Directory.php
@@ -0,0 +1,65 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\TextUI\XmlConfiguration\CodeCoverage\Filter;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ * @psalm-immutable
+ */
+final class Directory
+{
+    /**
+     * @var string
+     */
+    private $path;
+
+    /**
+     * @var string
+     */
+    private $prefix;
+
+    /**
+     * @var string
+     */
+    private $suffix;
+
+    /**
+     * @var string
+     */
+    private $group;
+
+    public function __construct(string $path, string $prefix, string $suffix, string $group)
+    {
+        $this->path   = $path;
+        $this->prefix = $prefix;
+        $this->suffix = $suffix;
+        $this->group  = $group;
+    }
+
+    public function path(): string
+    {
+        return $this->path;
+    }
+
+    public function prefix(): string
+    {
+        return $this->prefix;
+    }
+
+    public function suffix(): string
+    {
+        return $this->suffix;
+    }
+
+    public function group(): string
+    {
+        return $this->group;
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/CodeCoverage/Filter/DirectoryCollection.php b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/CodeCoverage/Filter/DirectoryCollection.php
new file mode 100644
index 0000000000000000000000000000000000000000..803ccda20af7745581016178bc4b2186c24c9813
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/CodeCoverage/Filter/DirectoryCollection.php
@@ -0,0 +1,57 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\TextUI\XmlConfiguration\CodeCoverage\Filter;
+
+use function count;
+use Countable;
+use IteratorAggregate;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ * @psalm-immutable
+ */
+final class DirectoryCollection implements Countable, IteratorAggregate
+{
+    /**
+     * @var Directory[]
+     */
+    private $directories;
+
+    /**
+     * @param Directory[] $directories
+     */
+    public static function fromArray(array $directories): self
+    {
+        return new self(...$directories);
+    }
+
+    private function __construct(Directory ...$directories)
+    {
+        $this->directories = $directories;
+    }
+
+    /**
+     * @return Directory[]
+     */
+    public function asArray(): array
+    {
+        return $this->directories;
+    }
+
+    public function count(): int
+    {
+        return count($this->directories);
+    }
+
+    public function getIterator(): DirectoryCollectionIterator
+    {
+        return new DirectoryCollectionIterator($this);
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/CodeCoverage/Filter/DirectoryCollectionIterator.php b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/CodeCoverage/Filter/DirectoryCollectionIterator.php
new file mode 100644
index 0000000000000000000000000000000000000000..c59a3ba998d715a4e581cd1bbacb2aa364ebcbf8
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/CodeCoverage/Filter/DirectoryCollectionIterator.php
@@ -0,0 +1,66 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\TextUI\XmlConfiguration\CodeCoverage\Filter;
+
+use function count;
+use function iterator_count;
+use Countable;
+use Iterator;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class DirectoryCollectionIterator implements Countable, Iterator
+{
+    /**
+     * @var Directory[]
+     */
+    private $directories;
+
+    /**
+     * @var int
+     */
+    private $position;
+
+    public function __construct(DirectoryCollection $directories)
+    {
+        $this->directories = $directories->asArray();
+    }
+
+    public function count(): int
+    {
+        return iterator_count($this);
+    }
+
+    public function rewind(): void
+    {
+        $this->position = 0;
+    }
+
+    public function valid(): bool
+    {
+        return $this->position < count($this->directories);
+    }
+
+    public function key(): int
+    {
+        return $this->position;
+    }
+
+    public function current(): Directory
+    {
+        return $this->directories[$this->position];
+    }
+
+    public function next(): void
+    {
+        $this->position++;
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/CodeCoverage/FilterMapper.php b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/CodeCoverage/FilterMapper.php
new file mode 100644
index 0000000000000000000000000000000000000000..102c96ebc604c69f2965c4dba5c9f7ac9cd33624
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/CodeCoverage/FilterMapper.php
@@ -0,0 +1,45 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\TextUI\XmlConfiguration\CodeCoverage;
+
+use SebastianBergmann\CodeCoverage\Filter;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class FilterMapper
+{
+    public function map(Filter $filter, CodeCoverage $configuration): void
+    {
+        foreach ($configuration->directories() as $directory) {
+            $filter->includeDirectory(
+                $directory->path(),
+                $directory->suffix(),
+                $directory->prefix()
+            );
+        }
+
+        foreach ($configuration->files() as $file) {
+            $filter->includeFile($file->path());
+        }
+
+        foreach ($configuration->excludeDirectories() as $directory) {
+            $filter->excludeDirectory(
+                $directory->path(),
+                $directory->suffix(),
+                $directory->prefix()
+            );
+        }
+
+        foreach ($configuration->excludeFiles() as $file) {
+            $filter->excludeFile($file->path());
+        }
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/CodeCoverage/Report/Clover.php b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/CodeCoverage/Report/Clover.php
new file mode 100644
index 0000000000000000000000000000000000000000..e7ff407bee54d3792bf7a2d0f6de627d7dd37cd8
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/CodeCoverage/Report/Clover.php
@@ -0,0 +1,34 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\TextUI\XmlConfiguration\CodeCoverage\Report;
+
+use PHPUnit\TextUI\XmlConfiguration\File;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ * @psalm-immutable
+ */
+final class Clover
+{
+    /**
+     * @var File
+     */
+    private $target;
+
+    public function __construct(File $target)
+    {
+        $this->target = $target;
+    }
+
+    public function target(): File
+    {
+        return $this->target;
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/CodeCoverage/Report/Cobertura.php b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/CodeCoverage/Report/Cobertura.php
new file mode 100644
index 0000000000000000000000000000000000000000..e6ee7c9f620a024167ad6c621766fade26ec31a1
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/CodeCoverage/Report/Cobertura.php
@@ -0,0 +1,34 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\TextUI\XmlConfiguration\CodeCoverage\Report;
+
+use PHPUnit\TextUI\XmlConfiguration\File;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ * @psalm-immutable
+ */
+final class Cobertura
+{
+    /**
+     * @var File
+     */
+    private $target;
+
+    public function __construct(File $target)
+    {
+        $this->target = $target;
+    }
+
+    public function target(): File
+    {
+        return $this->target;
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/CodeCoverage/Report/Crap4j.php b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/CodeCoverage/Report/Crap4j.php
new file mode 100644
index 0000000000000000000000000000000000000000..fd4d42912f04e4c3c08ff7cac1f1515926dd91c1
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/CodeCoverage/Report/Crap4j.php
@@ -0,0 +1,45 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\TextUI\XmlConfiguration\CodeCoverage\Report;
+
+use PHPUnit\TextUI\XmlConfiguration\File;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ * @psalm-immutable
+ */
+final class Crap4j
+{
+    /**
+     * @var File
+     */
+    private $target;
+
+    /**
+     * @var int
+     */
+    private $threshold;
+
+    public function __construct(File $target, int $threshold)
+    {
+        $this->target    = $target;
+        $this->threshold = $threshold;
+    }
+
+    public function target(): File
+    {
+        return $this->target;
+    }
+
+    public function threshold(): int
+    {
+        return $this->threshold;
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/CodeCoverage/Report/Html.php b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/CodeCoverage/Report/Html.php
new file mode 100644
index 0000000000000000000000000000000000000000..7084ffe5e29c4abde5972d916549637cc21ce0cc
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/CodeCoverage/Report/Html.php
@@ -0,0 +1,56 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\TextUI\XmlConfiguration\CodeCoverage\Report;
+
+use PHPUnit\TextUI\XmlConfiguration\Directory;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ * @psalm-immutable
+ */
+final class Html
+{
+    /**
+     * @var Directory
+     */
+    private $target;
+
+    /**
+     * @var int
+     */
+    private $lowUpperBound;
+
+    /**
+     * @var int
+     */
+    private $highLowerBound;
+
+    public function __construct(Directory $target, int $lowUpperBound, int $highLowerBound)
+    {
+        $this->target         = $target;
+        $this->lowUpperBound  = $lowUpperBound;
+        $this->highLowerBound = $highLowerBound;
+    }
+
+    public function target(): Directory
+    {
+        return $this->target;
+    }
+
+    public function lowUpperBound(): int
+    {
+        return $this->lowUpperBound;
+    }
+
+    public function highLowerBound(): int
+    {
+        return $this->highLowerBound;
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/CodeCoverage/Report/Php.php b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/CodeCoverage/Report/Php.php
new file mode 100644
index 0000000000000000000000000000000000000000..d86b66216a2d320e2bb2643bdfcf129b4bcef647
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/CodeCoverage/Report/Php.php
@@ -0,0 +1,34 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\TextUI\XmlConfiguration\CodeCoverage\Report;
+
+use PHPUnit\TextUI\XmlConfiguration\File;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ * @psalm-immutable
+ */
+final class Php
+{
+    /**
+     * @var File
+     */
+    private $target;
+
+    public function __construct(File $target)
+    {
+        $this->target = $target;
+    }
+
+    public function target(): File
+    {
+        return $this->target;
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/CodeCoverage/Report/Text.php b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/CodeCoverage/Report/Text.php
new file mode 100644
index 0000000000000000000000000000000000000000..b7e9f3da3e782a9aa4fb0c8780838c94ec754d10
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/CodeCoverage/Report/Text.php
@@ -0,0 +1,56 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\TextUI\XmlConfiguration\CodeCoverage\Report;
+
+use PHPUnit\TextUI\XmlConfiguration\File;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ * @psalm-immutable
+ */
+final class Text
+{
+    /**
+     * @var File
+     */
+    private $target;
+
+    /**
+     * @var bool
+     */
+    private $showUncoveredFiles;
+
+    /**
+     * @var bool
+     */
+    private $showOnlySummary;
+
+    public function __construct(File $target, bool $showUncoveredFiles, bool $showOnlySummary)
+    {
+        $this->target             = $target;
+        $this->showUncoveredFiles = $showUncoveredFiles;
+        $this->showOnlySummary    = $showOnlySummary;
+    }
+
+    public function target(): File
+    {
+        return $this->target;
+    }
+
+    public function showUncoveredFiles(): bool
+    {
+        return $this->showUncoveredFiles;
+    }
+
+    public function showOnlySummary(): bool
+    {
+        return $this->showOnlySummary;
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/CodeCoverage/Report/Xml.php b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/CodeCoverage/Report/Xml.php
new file mode 100644
index 0000000000000000000000000000000000000000..977685c46973c90791b400c233b84fa71c6fe669
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/CodeCoverage/Report/Xml.php
@@ -0,0 +1,34 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\TextUI\XmlConfiguration\CodeCoverage\Report;
+
+use PHPUnit\TextUI\XmlConfiguration\Directory;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ * @psalm-immutable
+ */
+final class Xml
+{
+    /**
+     * @var Directory
+     */
+    private $target;
+
+    public function __construct(Directory $target)
+    {
+        $this->target = $target;
+    }
+
+    public function target(): Directory
+    {
+        return $this->target;
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Configuration.php b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Configuration.php
new file mode 100644
index 0000000000000000000000000000000000000000..8f102e3bae4aeba1c0a772c6251d5c7e624abf85
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Configuration.php
@@ -0,0 +1,151 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\TextUI\XmlConfiguration;
+
+use PHPUnit\TextUI\XmlConfiguration\CodeCoverage\CodeCoverage;
+use PHPUnit\TextUI\XmlConfiguration\Logging\Logging;
+use PHPUnit\Util\Xml\ValidationResult;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ * @psalm-immutable
+ */
+final class Configuration
+{
+    /**
+     * @var string
+     */
+    private $filename;
+
+    /**
+     * @var ValidationResult
+     */
+    private $validationResult;
+
+    /**
+     * @var ExtensionCollection
+     */
+    private $extensions;
+
+    /**
+     * @var CodeCoverage
+     */
+    private $codeCoverage;
+
+    /**
+     * @var Groups
+     */
+    private $groups;
+
+    /**
+     * @var Groups
+     */
+    private $testdoxGroups;
+
+    /**
+     * @var ExtensionCollection
+     */
+    private $listeners;
+
+    /**
+     * @var Logging
+     */
+    private $logging;
+
+    /**
+     * @var Php
+     */
+    private $php;
+
+    /**
+     * @var PHPUnit
+     */
+    private $phpunit;
+
+    /**
+     * @var TestSuiteCollection
+     */
+    private $testSuite;
+
+    public function __construct(string $filename, ValidationResult $validationResult, ExtensionCollection $extensions, CodeCoverage $codeCoverage, Groups $groups, Groups $testdoxGroups, ExtensionCollection $listeners, Logging $logging, Php $php, PHPUnit $phpunit, TestSuiteCollection $testSuite)
+    {
+        $this->filename         = $filename;
+        $this->validationResult = $validationResult;
+        $this->extensions       = $extensions;
+        $this->codeCoverage     = $codeCoverage;
+        $this->groups           = $groups;
+        $this->testdoxGroups    = $testdoxGroups;
+        $this->listeners        = $listeners;
+        $this->logging          = $logging;
+        $this->php              = $php;
+        $this->phpunit          = $phpunit;
+        $this->testSuite        = $testSuite;
+    }
+
+    public function filename(): string
+    {
+        return $this->filename;
+    }
+
+    public function hasValidationErrors(): bool
+    {
+        return $this->validationResult->hasValidationErrors();
+    }
+
+    public function validationErrors(): string
+    {
+        return $this->validationResult->asString();
+    }
+
+    public function extensions(): ExtensionCollection
+    {
+        return $this->extensions;
+    }
+
+    public function codeCoverage(): CodeCoverage
+    {
+        return $this->codeCoverage;
+    }
+
+    public function groups(): Groups
+    {
+        return $this->groups;
+    }
+
+    public function testdoxGroups(): Groups
+    {
+        return $this->testdoxGroups;
+    }
+
+    public function listeners(): ExtensionCollection
+    {
+        return $this->listeners;
+    }
+
+    public function logging(): Logging
+    {
+        return $this->logging;
+    }
+
+    public function php(): Php
+    {
+        return $this->php;
+    }
+
+    public function phpunit(): PHPUnit
+    {
+        return $this->phpunit;
+    }
+
+    public function testSuite(): TestSuiteCollection
+    {
+        return $this->testSuite;
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Exception.php b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Exception.php
new file mode 100644
index 0000000000000000000000000000000000000000..162b37e88149b0fe3f672b3267b636e847ebedbb
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Exception.php
@@ -0,0 +1,19 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\TextUI\XmlConfiguration;
+
+use RuntimeException;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class Exception extends RuntimeException implements \PHPUnit\Exception
+{
+}
diff --git a/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Filesystem/Directory.php b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Filesystem/Directory.php
new file mode 100644
index 0000000000000000000000000000000000000000..1629603b704cd37c26549c848880cb464edbaf8e
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Filesystem/Directory.php
@@ -0,0 +1,32 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\TextUI\XmlConfiguration;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ * @psalm-immutable
+ */
+final class Directory
+{
+    /**
+     * @var string
+     */
+    private $path;
+
+    public function __construct(string $path)
+    {
+        $this->path = $path;
+    }
+
+    public function path(): string
+    {
+        return $this->path;
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Filesystem/DirectoryCollection.php b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Filesystem/DirectoryCollection.php
new file mode 100644
index 0000000000000000000000000000000000000000..c8ae596416a871739c8799edeec917fbe5269725
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Filesystem/DirectoryCollection.php
@@ -0,0 +1,62 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\TextUI\XmlConfiguration;
+
+use function count;
+use Countable;
+use IteratorAggregate;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ * @psalm-immutable
+ */
+final class DirectoryCollection implements Countable, IteratorAggregate
+{
+    /**
+     * @var Directory[]
+     */
+    private $directories;
+
+    /**
+     * @param Directory[] $directories
+     */
+    public static function fromArray(array $directories): self
+    {
+        return new self(...$directories);
+    }
+
+    private function __construct(Directory ...$directories)
+    {
+        $this->directories = $directories;
+    }
+
+    /**
+     * @return Directory[]
+     */
+    public function asArray(): array
+    {
+        return $this->directories;
+    }
+
+    public function count(): int
+    {
+        return count($this->directories);
+    }
+
+    public function getIterator(): DirectoryCollectionIterator
+    {
+        return new DirectoryCollectionIterator($this);
+    }
+
+    public function isEmpty(): bool
+    {
+        return $this->count() === 0;
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Filesystem/DirectoryCollectionIterator.php b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Filesystem/DirectoryCollectionIterator.php
new file mode 100644
index 0000000000000000000000000000000000000000..7f354eea5bd793e35efd5e23473708a3f5287822
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Filesystem/DirectoryCollectionIterator.php
@@ -0,0 +1,66 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\TextUI\XmlConfiguration;
+
+use function count;
+use function iterator_count;
+use Countable;
+use Iterator;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class DirectoryCollectionIterator implements Countable, Iterator
+{
+    /**
+     * @var Directory[]
+     */
+    private $directories;
+
+    /**
+     * @var int
+     */
+    private $position;
+
+    public function __construct(DirectoryCollection $directories)
+    {
+        $this->directories = $directories->asArray();
+    }
+
+    public function count(): int
+    {
+        return iterator_count($this);
+    }
+
+    public function rewind(): void
+    {
+        $this->position = 0;
+    }
+
+    public function valid(): bool
+    {
+        return $this->position < count($this->directories);
+    }
+
+    public function key(): int
+    {
+        return $this->position;
+    }
+
+    public function current(): Directory
+    {
+        return $this->directories[$this->position];
+    }
+
+    public function next(): void
+    {
+        $this->position++;
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Filesystem/File.php b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Filesystem/File.php
new file mode 100644
index 0000000000000000000000000000000000000000..0af5000d1bfbf4c5bac0df54243f10c815dedc52
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Filesystem/File.php
@@ -0,0 +1,32 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\TextUI\XmlConfiguration;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ * @psalm-immutable
+ */
+final class File
+{
+    /**
+     * @var string
+     */
+    private $path;
+
+    public function __construct(string $path)
+    {
+        $this->path = $path;
+    }
+
+    public function path(): string
+    {
+        return $this->path;
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Filesystem/FileCollection.php b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Filesystem/FileCollection.php
new file mode 100644
index 0000000000000000000000000000000000000000..bfc1e33e4c76765c1f8f4b9843bbb9a41317f3aa
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Filesystem/FileCollection.php
@@ -0,0 +1,62 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\TextUI\XmlConfiguration;
+
+use function count;
+use Countable;
+use IteratorAggregate;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ * @psalm-immutable
+ */
+final class FileCollection implements Countable, IteratorAggregate
+{
+    /**
+     * @var File[]
+     */
+    private $files;
+
+    /**
+     * @param File[] $files
+     */
+    public static function fromArray(array $files): self
+    {
+        return new self(...$files);
+    }
+
+    private function __construct(File ...$files)
+    {
+        $this->files = $files;
+    }
+
+    /**
+     * @return File[]
+     */
+    public function asArray(): array
+    {
+        return $this->files;
+    }
+
+    public function count(): int
+    {
+        return count($this->files);
+    }
+
+    public function getIterator(): FileCollectionIterator
+    {
+        return new FileCollectionIterator($this);
+    }
+
+    public function isEmpty(): bool
+    {
+        return $this->count() === 0;
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Filesystem/FileCollectionIterator.php b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Filesystem/FileCollectionIterator.php
new file mode 100644
index 0000000000000000000000000000000000000000..d9bab1f8ba145a0e42145e1becfac11794957518
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Filesystem/FileCollectionIterator.php
@@ -0,0 +1,66 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\TextUI\XmlConfiguration;
+
+use function count;
+use function iterator_count;
+use Countable;
+use Iterator;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class FileCollectionIterator implements Countable, Iterator
+{
+    /**
+     * @var File[]
+     */
+    private $files;
+
+    /**
+     * @var int
+     */
+    private $position;
+
+    public function __construct(FileCollection $files)
+    {
+        $this->files = $files->asArray();
+    }
+
+    public function count(): int
+    {
+        return iterator_count($this);
+    }
+
+    public function rewind(): void
+    {
+        $this->position = 0;
+    }
+
+    public function valid(): bool
+    {
+        return $this->position < count($this->files);
+    }
+
+    public function key(): int
+    {
+        return $this->position;
+    }
+
+    public function current(): File
+    {
+        return $this->files[$this->position];
+    }
+
+    public function next(): void
+    {
+        $this->position++;
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Generator.php b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Generator.php
new file mode 100644
index 0000000000000000000000000000000000000000..478a51bf70a3af422544fad77a50d051b33953d7
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Generator.php
@@ -0,0 +1,72 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\TextUI\XmlConfiguration;
+
+use function str_replace;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class Generator
+{
+    /**
+     * @var string
+     */
+    private const TEMPLATE = <<<'EOT'
+<?xml version="1.0" encoding="UTF-8"?>
+<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/{phpunit_version}/phpunit.xsd"
+         bootstrap="{bootstrap_script}"
+         cacheResultFile="{cache_directory}/test-results"
+         executionOrder="depends,defects"
+         forceCoversAnnotation="true"
+         beStrictAboutCoversAnnotation="true"
+         beStrictAboutOutputDuringTests="true"
+         beStrictAboutTodoAnnotatedTests="true"
+         failOnRisky="true"
+         failOnWarning="true"
+         verbose="true">
+    <testsuites>
+        <testsuite name="default">
+            <directory suffix="Test.php">{tests_directory}</directory>
+        </testsuite>
+    </testsuites>
+
+    <coverage cacheDirectory="{cache_directory}/code-coverage"
+              processUncoveredFiles="true">
+        <include>
+            <directory suffix=".php">{src_directory}</directory>
+        </include>
+    </coverage>
+</phpunit>
+
+EOT;
+
+    public function generateDefaultConfiguration(string $phpunitVersion, string $bootstrapScript, string $testsDirectory, string $srcDirectory, string $cacheDirectory): string
+    {
+        return str_replace(
+            [
+                '{phpunit_version}',
+                '{bootstrap_script}',
+                '{tests_directory}',
+                '{src_directory}',
+                '{cache_directory}',
+            ],
+            [
+                $phpunitVersion,
+                $bootstrapScript,
+                $testsDirectory,
+                $srcDirectory,
+                $cacheDirectory,
+            ],
+            self::TEMPLATE
+        );
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Group/Group.php b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Group/Group.php
new file mode 100644
index 0000000000000000000000000000000000000000..e59844053f0422806aff88b4f0adf37a9ac3b823
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Group/Group.php
@@ -0,0 +1,32 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\TextUI\XmlConfiguration;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ * @psalm-immutable
+ */
+final class Group
+{
+    /**
+     * @var string
+     */
+    private $name;
+
+    public function __construct(string $name)
+    {
+        $this->name = $name;
+    }
+
+    public function name(): string
+    {
+        return $this->name;
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Group/GroupCollection.php b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Group/GroupCollection.php
new file mode 100644
index 0000000000000000000000000000000000000000..2ad9fef683514dab94113aecc17e24e1e117a128
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Group/GroupCollection.php
@@ -0,0 +1,69 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\TextUI\XmlConfiguration;
+
+use IteratorAggregate;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ * @psalm-immutable
+ */
+final class GroupCollection implements IteratorAggregate
+{
+    /**
+     * @var Group[]
+     */
+    private $groups;
+
+    /**
+     * @param Group[] $groups
+     */
+    public static function fromArray(array $groups): self
+    {
+        return new self(...$groups);
+    }
+
+    private function __construct(Group ...$groups)
+    {
+        $this->groups = $groups;
+    }
+
+    /**
+     * @return Group[]
+     */
+    public function asArray(): array
+    {
+        return $this->groups;
+    }
+
+    /**
+     * @return string[]
+     */
+    public function asArrayOfStrings(): array
+    {
+        $result = [];
+
+        foreach ($this->groups as $group) {
+            $result[] = $group->name();
+        }
+
+        return $result;
+    }
+
+    public function isEmpty(): bool
+    {
+        return empty($this->groups);
+    }
+
+    public function getIterator(): GroupCollectionIterator
+    {
+        return new GroupCollectionIterator($this);
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Group/GroupCollectionIterator.php b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Group/GroupCollectionIterator.php
new file mode 100644
index 0000000000000000000000000000000000000000..0755fdac4e3a2bf325ea70857e75aff8613d76fc
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Group/GroupCollectionIterator.php
@@ -0,0 +1,66 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\TextUI\XmlConfiguration;
+
+use function count;
+use function iterator_count;
+use Countable;
+use Iterator;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class GroupCollectionIterator implements Countable, Iterator
+{
+    /**
+     * @var Group[]
+     */
+    private $groups;
+
+    /**
+     * @var int
+     */
+    private $position;
+
+    public function __construct(GroupCollection $groups)
+    {
+        $this->groups = $groups->asArray();
+    }
+
+    public function count(): int
+    {
+        return iterator_count($this);
+    }
+
+    public function rewind(): void
+    {
+        $this->position = 0;
+    }
+
+    public function valid(): bool
+    {
+        return $this->position < count($this->groups);
+    }
+
+    public function key(): int
+    {
+        return $this->position;
+    }
+
+    public function current(): Group
+    {
+        return $this->groups[$this->position];
+    }
+
+    public function next(): void
+    {
+        $this->position++;
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Group/Groups.php b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Group/Groups.php
new file mode 100644
index 0000000000000000000000000000000000000000..9004fe43bf4e8e9fc5cd5b9f8d61a804cd72e827
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Group/Groups.php
@@ -0,0 +1,53 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\TextUI\XmlConfiguration;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ * @psalm-immutable
+ */
+final class Groups
+{
+    /**
+     * @var GroupCollection
+     */
+    private $include;
+
+    /**
+     * @var GroupCollection
+     */
+    private $exclude;
+
+    public function __construct(GroupCollection $include, GroupCollection $exclude)
+    {
+        $this->include = $include;
+        $this->exclude = $exclude;
+    }
+
+    public function hasInclude(): bool
+    {
+        return !$this->include->isEmpty();
+    }
+
+    public function include(): GroupCollection
+    {
+        return $this->include;
+    }
+
+    public function hasExclude(): bool
+    {
+        return !$this->exclude->isEmpty();
+    }
+
+    public function exclude(): GroupCollection
+    {
+        return $this->exclude;
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Loader.php b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Loader.php
new file mode 100644
index 0000000000000000000000000000000000000000..63e20bd858c2cbf79eda2bcf8b4154a5d291a80a
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Loader.php
@@ -0,0 +1,1264 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\TextUI\XmlConfiguration;
+
+use const DIRECTORY_SEPARATOR;
+use const PHP_VERSION;
+use function assert;
+use function defined;
+use function dirname;
+use function explode;
+use function is_file;
+use function is_numeric;
+use function preg_match;
+use function stream_resolve_include_path;
+use function strlen;
+use function strpos;
+use function strtolower;
+use function substr;
+use function trim;
+use DOMDocument;
+use DOMElement;
+use DOMNodeList;
+use DOMXPath;
+use PHPUnit\Runner\TestSuiteSorter;
+use PHPUnit\Runner\Version;
+use PHPUnit\TextUI\DefaultResultPrinter;
+use PHPUnit\TextUI\XmlConfiguration\CodeCoverage\CodeCoverage;
+use PHPUnit\TextUI\XmlConfiguration\CodeCoverage\Filter\Directory as FilterDirectory;
+use PHPUnit\TextUI\XmlConfiguration\CodeCoverage\Filter\DirectoryCollection as FilterDirectoryCollection;
+use PHPUnit\TextUI\XmlConfiguration\CodeCoverage\Report\Clover;
+use PHPUnit\TextUI\XmlConfiguration\CodeCoverage\Report\Cobertura;
+use PHPUnit\TextUI\XmlConfiguration\CodeCoverage\Report\Crap4j;
+use PHPUnit\TextUI\XmlConfiguration\CodeCoverage\Report\Html as CodeCoverageHtml;
+use PHPUnit\TextUI\XmlConfiguration\CodeCoverage\Report\Php as CodeCoveragePhp;
+use PHPUnit\TextUI\XmlConfiguration\CodeCoverage\Report\Text as CodeCoverageText;
+use PHPUnit\TextUI\XmlConfiguration\CodeCoverage\Report\Xml as CodeCoverageXml;
+use PHPUnit\TextUI\XmlConfiguration\Logging\Junit;
+use PHPUnit\TextUI\XmlConfiguration\Logging\Logging;
+use PHPUnit\TextUI\XmlConfiguration\Logging\TeamCity;
+use PHPUnit\TextUI\XmlConfiguration\Logging\TestDox\Html as TestDoxHtml;
+use PHPUnit\TextUI\XmlConfiguration\Logging\TestDox\Text as TestDoxText;
+use PHPUnit\TextUI\XmlConfiguration\Logging\TestDox\Xml as TestDoxXml;
+use PHPUnit\TextUI\XmlConfiguration\Logging\Text;
+use PHPUnit\TextUI\XmlConfiguration\TestSuite as TestSuiteConfiguration;
+use PHPUnit\Util\TestDox\CliTestDoxPrinter;
+use PHPUnit\Util\VersionComparisonOperator;
+use PHPUnit\Util\Xml;
+use PHPUnit\Util\Xml\Exception as XmlException;
+use PHPUnit\Util\Xml\Loader as XmlLoader;
+use PHPUnit\Util\Xml\SchemaFinder;
+use PHPUnit\Util\Xml\Validator;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class Loader
+{
+    /**
+     * @throws Exception
+     */
+    public function load(string $filename): Configuration
+    {
+        try {
+            $document = (new XmlLoader)->loadFile($filename, false, true, true);
+        } catch (XmlException $e) {
+            throw new Exception(
+                $e->getMessage(),
+                (int) $e->getCode(),
+                $e
+            );
+        }
+
+        $xpath = new DOMXPath($document);
+
+        try {
+            $xsdFilename = (new SchemaFinder)->find(Version::series());
+        } catch (XmlException $e) {
+            throw new Exception(
+                $e->getMessage(),
+                (int) $e->getCode(),
+                $e
+            );
+        }
+
+        return new Configuration(
+            $filename,
+            (new Validator)->validate($document, $xsdFilename),
+            $this->extensions($filename, $xpath),
+            $this->codeCoverage($filename, $xpath, $document),
+            $this->groups($xpath),
+            $this->testdoxGroups($xpath),
+            $this->listeners($filename, $xpath),
+            $this->logging($filename, $xpath),
+            $this->php($filename, $xpath),
+            $this->phpunit($filename, $document),
+            $this->testSuite($filename, $xpath)
+        );
+    }
+
+    public function logging(string $filename, DOMXPath $xpath): Logging
+    {
+        if ($xpath->query('logging/log')->length !== 0) {
+            return $this->legacyLogging($filename, $xpath);
+        }
+
+        $junit   = null;
+        $element = $this->element($xpath, 'logging/junit');
+
+        if ($element) {
+            $junit = new Junit(
+                new File(
+                    $this->toAbsolutePath(
+                        $filename,
+                        (string) $this->getStringAttribute($element, 'outputFile')
+                    )
+                )
+            );
+        }
+
+        $text    = null;
+        $element = $this->element($xpath, 'logging/text');
+
+        if ($element) {
+            $text = new Text(
+                new File(
+                    $this->toAbsolutePath(
+                        $filename,
+                        (string) $this->getStringAttribute($element, 'outputFile')
+                    )
+                )
+            );
+        }
+
+        $teamCity = null;
+        $element  = $this->element($xpath, 'logging/teamcity');
+
+        if ($element) {
+            $teamCity = new TeamCity(
+                new File(
+                    $this->toAbsolutePath(
+                        $filename,
+                        (string) $this->getStringAttribute($element, 'outputFile')
+                    )
+                )
+            );
+        }
+
+        $testDoxHtml = null;
+        $element     = $this->element($xpath, 'logging/testdoxHtml');
+
+        if ($element) {
+            $testDoxHtml = new TestDoxHtml(
+                new File(
+                    $this->toAbsolutePath(
+                        $filename,
+                        (string) $this->getStringAttribute($element, 'outputFile')
+                    )
+                )
+            );
+        }
+
+        $testDoxText = null;
+        $element     = $this->element($xpath, 'logging/testdoxText');
+
+        if ($element) {
+            $testDoxText = new TestDoxText(
+                new File(
+                    $this->toAbsolutePath(
+                        $filename,
+                        (string) $this->getStringAttribute($element, 'outputFile')
+                    )
+                )
+            );
+        }
+
+        $testDoxXml = null;
+        $element    = $this->element($xpath, 'logging/testdoxXml');
+
+        if ($element) {
+            $testDoxXml = new TestDoxXml(
+                new File(
+                    $this->toAbsolutePath(
+                        $filename,
+                        (string) $this->getStringAttribute($element, 'outputFile')
+                    )
+                )
+            );
+        }
+
+        return new Logging(
+            $junit,
+            $text,
+            $teamCity,
+            $testDoxHtml,
+            $testDoxText,
+            $testDoxXml
+        );
+    }
+
+    public function legacyLogging(string $filename, DOMXPath $xpath): Logging
+    {
+        $junit       = null;
+        $teamCity    = null;
+        $testDoxHtml = null;
+        $testDoxText = null;
+        $testDoxXml  = null;
+        $text        = null;
+
+        foreach ($xpath->query('logging/log') as $log) {
+            assert($log instanceof DOMElement);
+
+            $type   = (string) $log->getAttribute('type');
+            $target = (string) $log->getAttribute('target');
+
+            if (!$target) {
+                continue;
+            }
+
+            $target = $this->toAbsolutePath($filename, $target);
+
+            switch ($type) {
+                case 'plain':
+                    $text = new Text(
+                        new File($target)
+                    );
+
+                    break;
+
+                case 'junit':
+                    $junit = new Junit(
+                        new File($target)
+                    );
+
+                    break;
+
+                case 'teamcity':
+                    $teamCity = new TeamCity(
+                        new File($target)
+                    );
+
+                    break;
+
+                case 'testdox-html':
+                    $testDoxHtml = new TestDoxHtml(
+                        new File($target)
+                    );
+
+                    break;
+
+                case 'testdox-text':
+                    $testDoxText = new TestDoxText(
+                        new File($target)
+                    );
+
+                    break;
+
+                case 'testdox-xml':
+                    $testDoxXml = new TestDoxXml(
+                        new File($target)
+                    );
+
+                    break;
+            }
+        }
+
+        return new Logging(
+            $junit,
+            $text,
+            $teamCity,
+            $testDoxHtml,
+            $testDoxText,
+            $testDoxXml
+        );
+    }
+
+    private function extensions(string $filename, DOMXPath $xpath): ExtensionCollection
+    {
+        $extensions = [];
+
+        foreach ($xpath->query('extensions/extension') as $extension) {
+            assert($extension instanceof DOMElement);
+
+            $extensions[] = $this->getElementConfigurationParameters($filename, $extension);
+        }
+
+        return ExtensionCollection::fromArray($extensions);
+    }
+
+    private function getElementConfigurationParameters(string $filename, DOMElement $element): Extension
+    {
+        /** @psalm-var class-string $class */
+        $class     = (string) $element->getAttribute('class');
+        $file      = '';
+        $arguments = $this->getConfigurationArguments($filename, $element->childNodes);
+
+        if ($element->getAttribute('file')) {
+            $file = $this->toAbsolutePath(
+                $filename,
+                (string) $element->getAttribute('file'),
+                true
+            );
+        }
+
+        return new Extension($class, $file, $arguments);
+    }
+
+    private function toAbsolutePath(string $filename, string $path, bool $useIncludePath = false): string
+    {
+        $path = trim($path);
+
+        if (strpos($path, '/') === 0) {
+            return $path;
+        }
+
+        // Matches the following on Windows:
+        //  - \\NetworkComputer\Path
+        //  - \\.\D:
+        //  - \\.\c:
+        //  - C:\Windows
+        //  - C:\windows
+        //  - C:/windows
+        //  - c:/windows
+        if (defined('PHP_WINDOWS_VERSION_BUILD') &&
+            ($path[0] === '\\' || (strlen($path) >= 3 && preg_match('#^[A-Z]\:[/\\\]#i', substr($path, 0, 3))))) {
+            return $path;
+        }
+
+        if (strpos($path, '://') !== false) {
+            return $path;
+        }
+
+        $file = dirname($filename) . DIRECTORY_SEPARATOR . $path;
+
+        if ($useIncludePath && !is_file($file)) {
+            $includePathFile = stream_resolve_include_path($path);
+
+            if ($includePathFile) {
+                $file = $includePathFile;
+            }
+        }
+
+        return $file;
+    }
+
+    private function getConfigurationArguments(string $filename, DOMNodeList $nodes): array
+    {
+        $arguments = [];
+
+        if ($nodes->length === 0) {
+            return $arguments;
+        }
+
+        foreach ($nodes as $node) {
+            if (!$node instanceof DOMElement) {
+                continue;
+            }
+
+            if ($node->tagName !== 'arguments') {
+                continue;
+            }
+
+            foreach ($node->childNodes as $argument) {
+                if (!$argument instanceof DOMElement) {
+                    continue;
+                }
+
+                if ($argument->tagName === 'file' || $argument->tagName === 'directory') {
+                    $arguments[] = $this->toAbsolutePath($filename, (string) $argument->textContent);
+                } else {
+                    $arguments[] = Xml::xmlToVariable($argument);
+                }
+            }
+        }
+
+        return $arguments;
+    }
+
+    private function codeCoverage(string $filename, DOMXPath $xpath, DOMDocument $document): CodeCoverage
+    {
+        if ($xpath->query('filter/whitelist')->length !== 0) {
+            return $this->legacyCodeCoverage($filename, $xpath, $document);
+        }
+
+        $cacheDirectory            = null;
+        $pathCoverage              = false;
+        $includeUncoveredFiles     = true;
+        $processUncoveredFiles     = false;
+        $ignoreDeprecatedCodeUnits = false;
+        $disableCodeCoverageIgnore = false;
+
+        $element = $this->element($xpath, 'coverage');
+
+        if ($element) {
+            $cacheDirectory = $this->getStringAttribute($element, 'cacheDirectory');
+
+            if ($cacheDirectory !== null) {
+                $cacheDirectory = new Directory(
+                    $this->toAbsolutePath($filename, $cacheDirectory)
+                );
+            }
+
+            $pathCoverage = $this->getBooleanAttribute(
+                $element,
+                'pathCoverage',
+                false
+            );
+
+            $includeUncoveredFiles = $this->getBooleanAttribute(
+                $element,
+                'includeUncoveredFiles',
+                true
+            );
+
+            $processUncoveredFiles = $this->getBooleanAttribute(
+                $element,
+                'processUncoveredFiles',
+                false
+            );
+
+            $ignoreDeprecatedCodeUnits = $this->getBooleanAttribute(
+                $element,
+                'ignoreDeprecatedCodeUnits',
+                false
+            );
+
+            $disableCodeCoverageIgnore = $this->getBooleanAttribute(
+                $element,
+                'disableCodeCoverageIgnore',
+                false
+            );
+        }
+
+        $clover  = null;
+        $element = $this->element($xpath, 'coverage/report/clover');
+
+        if ($element) {
+            $clover = new Clover(
+                new File(
+                    $this->toAbsolutePath(
+                        $filename,
+                        (string) $this->getStringAttribute($element, 'outputFile')
+                    )
+                )
+            );
+        }
+
+        $cobertura = null;
+        $element   = $this->element($xpath, 'coverage/report/cobertura');
+
+        if ($element) {
+            $cobertura = new Cobertura(
+                new File(
+                    $this->toAbsolutePath(
+                        $filename,
+                        (string) $this->getStringAttribute($element, 'outputFile')
+                    )
+                )
+            );
+        }
+
+        $crap4j  = null;
+        $element = $this->element($xpath, 'coverage/report/crap4j');
+
+        if ($element) {
+            $crap4j = new Crap4j(
+                new File(
+                    $this->toAbsolutePath(
+                        $filename,
+                        (string) $this->getStringAttribute($element, 'outputFile')
+                    )
+                ),
+                $this->getIntegerAttribute($element, 'threshold', 30)
+            );
+        }
+
+        $html    = null;
+        $element = $this->element($xpath, 'coverage/report/html');
+
+        if ($element) {
+            $html = new CodeCoverageHtml(
+                new Directory(
+                    $this->toAbsolutePath(
+                        $filename,
+                        (string) $this->getStringAttribute($element, 'outputDirectory')
+                    )
+                ),
+                $this->getIntegerAttribute($element, 'lowUpperBound', 50),
+                $this->getIntegerAttribute($element, 'highLowerBound', 90)
+            );
+        }
+
+        $php     = null;
+        $element = $this->element($xpath, 'coverage/report/php');
+
+        if ($element) {
+            $php = new CodeCoveragePhp(
+                new File(
+                    $this->toAbsolutePath(
+                        $filename,
+                        (string) $this->getStringAttribute($element, 'outputFile')
+                    )
+                )
+            );
+        }
+
+        $text    = null;
+        $element = $this->element($xpath, 'coverage/report/text');
+
+        if ($element) {
+            $text = new CodeCoverageText(
+                new File(
+                    $this->toAbsolutePath(
+                        $filename,
+                        (string) $this->getStringAttribute($element, 'outputFile')
+                    )
+                ),
+                $this->getBooleanAttribute($element, 'showUncoveredFiles', false),
+                $this->getBooleanAttribute($element, 'showOnlySummary', false)
+            );
+        }
+
+        $xml     = null;
+        $element = $this->element($xpath, 'coverage/report/xml');
+
+        if ($element) {
+            $xml = new CodeCoverageXml(
+                new Directory(
+                    $this->toAbsolutePath(
+                        $filename,
+                        (string) $this->getStringAttribute($element, 'outputDirectory')
+                    )
+                )
+            );
+        }
+
+        return new CodeCoverage(
+            $cacheDirectory,
+            $this->readFilterDirectories($filename, $xpath, 'coverage/include/directory'),
+            $this->readFilterFiles($filename, $xpath, 'coverage/include/file'),
+            $this->readFilterDirectories($filename, $xpath, 'coverage/exclude/directory'),
+            $this->readFilterFiles($filename, $xpath, 'coverage/exclude/file'),
+            $pathCoverage,
+            $includeUncoveredFiles,
+            $processUncoveredFiles,
+            $ignoreDeprecatedCodeUnits,
+            $disableCodeCoverageIgnore,
+            $clover,
+            $cobertura,
+            $crap4j,
+            $html,
+            $php,
+            $text,
+            $xml
+        );
+    }
+
+    /**
+     * @deprecated
+     */
+    private function legacyCodeCoverage(string $filename, DOMXPath $xpath, DOMDocument $document): CodeCoverage
+    {
+        $ignoreDeprecatedCodeUnits = $this->getBooleanAttribute(
+            $document->documentElement,
+            'ignoreDeprecatedCodeUnitsFromCodeCoverage',
+            false
+        );
+
+        $disableCodeCoverageIgnore = $this->getBooleanAttribute(
+            $document->documentElement,
+            'disableCodeCoverageIgnore',
+            false
+        );
+
+        $includeUncoveredFiles = true;
+        $processUncoveredFiles = false;
+
+        $element = $this->element($xpath, 'filter/whitelist');
+
+        if ($element) {
+            if ($element->hasAttribute('addUncoveredFilesFromWhitelist')) {
+                $includeUncoveredFiles = (bool) $this->getBoolean(
+                    (string) $element->getAttribute('addUncoveredFilesFromWhitelist'),
+                    true
+                );
+            }
+
+            if ($element->hasAttribute('processUncoveredFilesFromWhitelist')) {
+                $processUncoveredFiles = (bool) $this->getBoolean(
+                    (string) $element->getAttribute('processUncoveredFilesFromWhitelist'),
+                    false
+                );
+            }
+        }
+
+        $clover    = null;
+        $cobertura = null;
+        $crap4j    = null;
+        $html      = null;
+        $php       = null;
+        $text      = null;
+        $xml       = null;
+
+        foreach ($xpath->query('logging/log') as $log) {
+            assert($log instanceof DOMElement);
+
+            $type   = (string) $log->getAttribute('type');
+            $target = (string) $log->getAttribute('target');
+
+            if (!$target) {
+                continue;
+            }
+
+            $target = $this->toAbsolutePath($filename, $target);
+
+            switch ($type) {
+                case 'coverage-clover':
+                    $clover = new Clover(
+                        new File($target)
+                    );
+
+                    break;
+
+                case 'coverage-cobertura':
+                    $cobertura = new Cobertura(
+                        new File($target)
+                    );
+
+                    break;
+
+                case 'coverage-crap4j':
+                    $crap4j = new Crap4j(
+                        new File($target),
+                        $this->getIntegerAttribute($log, 'threshold', 30)
+                    );
+
+                    break;
+
+                case 'coverage-html':
+                    $html = new CodeCoverageHtml(
+                        new Directory($target),
+                        $this->getIntegerAttribute($log, 'lowUpperBound', 50),
+                        $this->getIntegerAttribute($log, 'highLowerBound', 90)
+                    );
+
+                    break;
+
+                case 'coverage-php':
+                    $php = new CodeCoveragePhp(
+                        new File($target)
+                    );
+
+                    break;
+
+                case 'coverage-text':
+                    $text = new CodeCoverageText(
+                        new File($target),
+                        $this->getBooleanAttribute($log, 'showUncoveredFiles', false),
+                        $this->getBooleanAttribute($log, 'showOnlySummary', false)
+                    );
+
+                    break;
+
+                case 'coverage-xml':
+                    $xml = new CodeCoverageXml(
+                        new Directory($target)
+                    );
+
+                    break;
+            }
+        }
+
+        return new CodeCoverage(
+            null,
+            $this->readFilterDirectories($filename, $xpath, 'filter/whitelist/directory'),
+            $this->readFilterFiles($filename, $xpath, 'filter/whitelist/file'),
+            $this->readFilterDirectories($filename, $xpath, 'filter/whitelist/exclude/directory'),
+            $this->readFilterFiles($filename, $xpath, 'filter/whitelist/exclude/file'),
+            false,
+            $includeUncoveredFiles,
+            $processUncoveredFiles,
+            $ignoreDeprecatedCodeUnits,
+            $disableCodeCoverageIgnore,
+            $clover,
+            $cobertura,
+            $crap4j,
+            $html,
+            $php,
+            $text,
+            $xml
+        );
+    }
+
+    /**
+     * If $value is 'false' or 'true', this returns the value that $value represents.
+     * Otherwise, returns $default, which may be a string in rare cases.
+     *
+     * @see \PHPUnit\TextUI\XmlConfigurationTest::testPHPConfigurationIsReadCorrectly
+     *
+     * @param bool|string $default
+     *
+     * @return bool|string
+     */
+    private function getBoolean(string $value, $default)
+    {
+        if (strtolower($value) === 'false') {
+            return false;
+        }
+
+        if (strtolower($value) === 'true') {
+            return true;
+        }
+
+        return $default;
+    }
+
+    private function readFilterDirectories(string $filename, DOMXPath $xpath, string $query): FilterDirectoryCollection
+    {
+        $directories = [];
+
+        foreach ($xpath->query($query) as $directoryNode) {
+            assert($directoryNode instanceof DOMElement);
+
+            $directoryPath = (string) $directoryNode->textContent;
+
+            if (!$directoryPath) {
+                continue;
+            }
+
+            $directories[] = new FilterDirectory(
+                $this->toAbsolutePath($filename, $directoryPath),
+                $directoryNode->hasAttribute('prefix') ? (string) $directoryNode->getAttribute('prefix') : '',
+                $directoryNode->hasAttribute('suffix') ? (string) $directoryNode->getAttribute('suffix') : '.php',
+                $directoryNode->hasAttribute('group') ? (string) $directoryNode->getAttribute('group') : 'DEFAULT'
+            );
+        }
+
+        return FilterDirectoryCollection::fromArray($directories);
+    }
+
+    private function readFilterFiles(string $filename, DOMXPath $xpath, string $query): FileCollection
+    {
+        $files = [];
+
+        foreach ($xpath->query($query) as $file) {
+            $filePath = (string) $file->textContent;
+
+            if ($filePath) {
+                $files[] = new File($this->toAbsolutePath($filename, $filePath));
+            }
+        }
+
+        return FileCollection::fromArray($files);
+    }
+
+    private function groups(DOMXPath $xpath): Groups
+    {
+        return $this->parseGroupConfiguration($xpath, 'groups');
+    }
+
+    private function testdoxGroups(DOMXPath $xpath): Groups
+    {
+        return $this->parseGroupConfiguration($xpath, 'testdoxGroups');
+    }
+
+    private function parseGroupConfiguration(DOMXPath $xpath, string $root): Groups
+    {
+        $include = [];
+        $exclude = [];
+
+        foreach ($xpath->query($root . '/include/group') as $group) {
+            $include[] = new Group((string) $group->textContent);
+        }
+
+        foreach ($xpath->query($root . '/exclude/group') as $group) {
+            $exclude[] = new Group((string) $group->textContent);
+        }
+
+        return new Groups(
+            GroupCollection::fromArray($include),
+            GroupCollection::fromArray($exclude)
+        );
+    }
+
+    private function listeners(string $filename, DOMXPath $xpath): ExtensionCollection
+    {
+        $listeners = [];
+
+        foreach ($xpath->query('listeners/listener') as $listener) {
+            assert($listener instanceof DOMElement);
+
+            $listeners[] = $this->getElementConfigurationParameters($filename, $listener);
+        }
+
+        return ExtensionCollection::fromArray($listeners);
+    }
+
+    private function getBooleanAttribute(DOMElement $element, string $attribute, bool $default): bool
+    {
+        if (!$element->hasAttribute($attribute)) {
+            return $default;
+        }
+
+        return (bool) $this->getBoolean(
+            (string) $element->getAttribute($attribute),
+            false
+        );
+    }
+
+    private function getIntegerAttribute(DOMElement $element, string $attribute, int $default): int
+    {
+        if (!$element->hasAttribute($attribute)) {
+            return $default;
+        }
+
+        return $this->getInteger(
+            (string) $element->getAttribute($attribute),
+            $default
+        );
+    }
+
+    private function getStringAttribute(DOMElement $element, string $attribute): ?string
+    {
+        if (!$element->hasAttribute($attribute)) {
+            return null;
+        }
+
+        return (string) $element->getAttribute($attribute);
+    }
+
+    private function getInteger(string $value, int $default): int
+    {
+        if (is_numeric($value)) {
+            return (int) $value;
+        }
+
+        return $default;
+    }
+
+    private function php(string $filename, DOMXPath $xpath): Php
+    {
+        $includePaths = [];
+
+        foreach ($xpath->query('php/includePath') as $includePath) {
+            $path = (string) $includePath->textContent;
+
+            if ($path) {
+                $includePaths[] = new Directory($this->toAbsolutePath($filename, $path));
+            }
+        }
+
+        $iniSettings = [];
+
+        foreach ($xpath->query('php/ini') as $ini) {
+            assert($ini instanceof DOMElement);
+
+            $iniSettings[] = new IniSetting(
+                (string) $ini->getAttribute('name'),
+                (string) $ini->getAttribute('value')
+            );
+        }
+
+        $constants = [];
+
+        foreach ($xpath->query('php/const') as $const) {
+            assert($const instanceof DOMElement);
+
+            $value = (string) $const->getAttribute('value');
+
+            $constants[] = new Constant(
+                (string) $const->getAttribute('name'),
+                $this->getBoolean($value, $value)
+            );
+        }
+
+        $variables = [
+            'var'     => [],
+            'env'     => [],
+            'post'    => [],
+            'get'     => [],
+            'cookie'  => [],
+            'server'  => [],
+            'files'   => [],
+            'request' => [],
+        ];
+
+        foreach (['var', 'env', 'post', 'get', 'cookie', 'server', 'files', 'request'] as $array) {
+            foreach ($xpath->query('php/' . $array) as $var) {
+                assert($var instanceof DOMElement);
+
+                $name     = (string) $var->getAttribute('name');
+                $value    = (string) $var->getAttribute('value');
+                $force    = false;
+                $verbatim = false;
+
+                if ($var->hasAttribute('force')) {
+                    $force = (bool) $this->getBoolean($var->getAttribute('force'), false);
+                }
+
+                if ($var->hasAttribute('verbatim')) {
+                    $verbatim = $this->getBoolean($var->getAttribute('verbatim'), false);
+                }
+
+                if (!$verbatim) {
+                    $value = $this->getBoolean($value, $value);
+                }
+
+                $variables[$array][] = new Variable($name, $value, $force);
+            }
+        }
+
+        return new Php(
+            DirectoryCollection::fromArray($includePaths),
+            IniSettingCollection::fromArray($iniSettings),
+            ConstantCollection::fromArray($constants),
+            VariableCollection::fromArray($variables['var']),
+            VariableCollection::fromArray($variables['env']),
+            VariableCollection::fromArray($variables['post']),
+            VariableCollection::fromArray($variables['get']),
+            VariableCollection::fromArray($variables['cookie']),
+            VariableCollection::fromArray($variables['server']),
+            VariableCollection::fromArray($variables['files']),
+            VariableCollection::fromArray($variables['request']),
+        );
+    }
+
+    private function phpunit(string $filename, DOMDocument $document): PHPUnit
+    {
+        $executionOrder      = TestSuiteSorter::ORDER_DEFAULT;
+        $defectsFirst        = false;
+        $resolveDependencies = $this->getBooleanAttribute($document->documentElement, 'resolveDependencies', true);
+
+        if ($document->documentElement->hasAttribute('executionOrder')) {
+            foreach (explode(',', $document->documentElement->getAttribute('executionOrder')) as $order) {
+                switch ($order) {
+                    case 'default':
+                        $executionOrder      = TestSuiteSorter::ORDER_DEFAULT;
+                        $defectsFirst        = false;
+                        $resolveDependencies = true;
+
+                        break;
+
+                    case 'depends':
+                        $resolveDependencies = true;
+
+                        break;
+
+                    case 'no-depends':
+                        $resolveDependencies = false;
+
+                        break;
+
+                    case 'defects':
+                        $defectsFirst = true;
+
+                        break;
+
+                    case 'duration':
+                        $executionOrder = TestSuiteSorter::ORDER_DURATION;
+
+                        break;
+
+                    case 'random':
+                        $executionOrder = TestSuiteSorter::ORDER_RANDOMIZED;
+
+                        break;
+
+                    case 'reverse':
+                        $executionOrder = TestSuiteSorter::ORDER_REVERSED;
+
+                        break;
+
+                    case 'size':
+                        $executionOrder = TestSuiteSorter::ORDER_SIZE;
+
+                        break;
+                }
+            }
+        }
+
+        $printerClass                          = $this->getStringAttribute($document->documentElement, 'printerClass');
+        $testdox                               = $this->getBooleanAttribute($document->documentElement, 'testdox', false);
+        $conflictBetweenPrinterClassAndTestdox = false;
+
+        if ($testdox) {
+            if ($printerClass !== null) {
+                $conflictBetweenPrinterClassAndTestdox = true;
+            }
+
+            $printerClass = CliTestDoxPrinter::class;
+        }
+
+        $cacheResultFile = $this->getStringAttribute($document->documentElement, 'cacheResultFile');
+
+        if ($cacheResultFile !== null) {
+            $cacheResultFile = $this->toAbsolutePath($filename, $cacheResultFile);
+        }
+
+        $bootstrap = $this->getStringAttribute($document->documentElement, 'bootstrap');
+
+        if ($bootstrap !== null) {
+            $bootstrap = $this->toAbsolutePath($filename, $bootstrap);
+        }
+
+        $extensionsDirectory = $this->getStringAttribute($document->documentElement, 'extensionsDirectory');
+
+        if ($extensionsDirectory !== null) {
+            $extensionsDirectory = $this->toAbsolutePath($filename, $extensionsDirectory);
+        }
+
+        $testSuiteLoaderFile = $this->getStringAttribute($document->documentElement, 'testSuiteLoaderFile');
+
+        if ($testSuiteLoaderFile !== null) {
+            $testSuiteLoaderFile = $this->toAbsolutePath($filename, $testSuiteLoaderFile);
+        }
+
+        $printerFile = $this->getStringAttribute($document->documentElement, 'printerFile');
+
+        if ($printerFile !== null) {
+            $printerFile = $this->toAbsolutePath($filename, $printerFile);
+        }
+
+        return new PHPUnit(
+            $this->getBooleanAttribute($document->documentElement, 'cacheResult', true),
+            $cacheResultFile,
+            $this->getColumns($document),
+            $this->getColors($document),
+            $this->getBooleanAttribute($document->documentElement, 'stderr', false),
+            $this->getBooleanAttribute($document->documentElement, 'noInteraction', false),
+            $this->getBooleanAttribute($document->documentElement, 'verbose', false),
+            $this->getBooleanAttribute($document->documentElement, 'reverseDefectList', false),
+            $this->getBooleanAttribute($document->documentElement, 'convertDeprecationsToExceptions', true),
+            $this->getBooleanAttribute($document->documentElement, 'convertErrorsToExceptions', true),
+            $this->getBooleanAttribute($document->documentElement, 'convertNoticesToExceptions', true),
+            $this->getBooleanAttribute($document->documentElement, 'convertWarningsToExceptions', true),
+            $this->getBooleanAttribute($document->documentElement, 'forceCoversAnnotation', false),
+            $bootstrap,
+            $this->getBooleanAttribute($document->documentElement, 'processIsolation', false),
+            $this->getBooleanAttribute($document->documentElement, 'failOnEmptyTestSuite', false),
+            $this->getBooleanAttribute($document->documentElement, 'failOnIncomplete', false),
+            $this->getBooleanAttribute($document->documentElement, 'failOnRisky', false),
+            $this->getBooleanAttribute($document->documentElement, 'failOnSkipped', false),
+            $this->getBooleanAttribute($document->documentElement, 'failOnWarning', false),
+            $this->getBooleanAttribute($document->documentElement, 'stopOnDefect', false),
+            $this->getBooleanAttribute($document->documentElement, 'stopOnError', false),
+            $this->getBooleanAttribute($document->documentElement, 'stopOnFailure', false),
+            $this->getBooleanAttribute($document->documentElement, 'stopOnWarning', false),
+            $this->getBooleanAttribute($document->documentElement, 'stopOnIncomplete', false),
+            $this->getBooleanAttribute($document->documentElement, 'stopOnRisky', false),
+            $this->getBooleanAttribute($document->documentElement, 'stopOnSkipped', false),
+            $extensionsDirectory,
+            $this->getStringAttribute($document->documentElement, 'testSuiteLoaderClass'),
+            $testSuiteLoaderFile,
+            $printerClass,
+            $printerFile,
+            $this->getBooleanAttribute($document->documentElement, 'beStrictAboutChangesToGlobalState', false),
+            $this->getBooleanAttribute($document->documentElement, 'beStrictAboutOutputDuringTests', false),
+            $this->getBooleanAttribute($document->documentElement, 'beStrictAboutResourceUsageDuringSmallTests', false),
+            $this->getBooleanAttribute($document->documentElement, 'beStrictAboutTestsThatDoNotTestAnything', true),
+            $this->getBooleanAttribute($document->documentElement, 'beStrictAboutTodoAnnotatedTests', false),
+            $this->getBooleanAttribute($document->documentElement, 'beStrictAboutCoversAnnotation', false),
+            $this->getBooleanAttribute($document->documentElement, 'enforceTimeLimit', false),
+            $this->getIntegerAttribute($document->documentElement, 'defaultTimeLimit', 1),
+            $this->getIntegerAttribute($document->documentElement, 'timeoutForSmallTests', 1),
+            $this->getIntegerAttribute($document->documentElement, 'timeoutForMediumTests', 10),
+            $this->getIntegerAttribute($document->documentElement, 'timeoutForLargeTests', 60),
+            $this->getStringAttribute($document->documentElement, 'defaultTestSuite'),
+            $executionOrder,
+            $resolveDependencies,
+            $defectsFirst,
+            $this->getBooleanAttribute($document->documentElement, 'backupGlobals', false),
+            $this->getBooleanAttribute($document->documentElement, 'backupStaticAttributes', false),
+            $this->getBooleanAttribute($document->documentElement, 'registerMockObjectsFromTestArgumentsRecursively', false),
+            $conflictBetweenPrinterClassAndTestdox
+        );
+    }
+
+    private function getColors(DOMDocument $document): string
+    {
+        $colors = DefaultResultPrinter::COLOR_DEFAULT;
+
+        if ($document->documentElement->hasAttribute('colors')) {
+            /* only allow boolean for compatibility with previous versions
+              'always' only allowed from command line */
+            if ($this->getBoolean($document->documentElement->getAttribute('colors'), false)) {
+                $colors = DefaultResultPrinter::COLOR_AUTO;
+            } else {
+                $colors = DefaultResultPrinter::COLOR_NEVER;
+            }
+        }
+
+        return $colors;
+    }
+
+    /**
+     * @return int|string
+     */
+    private function getColumns(DOMDocument $document)
+    {
+        $columns = 80;
+
+        if ($document->documentElement->hasAttribute('columns')) {
+            $columns = (string) $document->documentElement->getAttribute('columns');
+
+            if ($columns !== 'max') {
+                $columns = $this->getInteger($columns, 80);
+            }
+        }
+
+        return $columns;
+    }
+
+    private function testSuite(string $filename, DOMXPath $xpath): TestSuiteCollection
+    {
+        $testSuites = [];
+
+        foreach ($this->getTestSuiteElements($xpath) as $element) {
+            $exclude = [];
+
+            foreach ($element->getElementsByTagName('exclude') as $excludeNode) {
+                $excludeFile = (string) $excludeNode->textContent;
+
+                if ($excludeFile) {
+                    $exclude[] = new File($this->toAbsolutePath($filename, $excludeFile));
+                }
+            }
+
+            $directories = [];
+
+            foreach ($element->getElementsByTagName('directory') as $directoryNode) {
+                assert($directoryNode instanceof DOMElement);
+
+                $directory = (string) $directoryNode->textContent;
+
+                if (empty($directory)) {
+                    continue;
+                }
+
+                $prefix = '';
+
+                if ($directoryNode->hasAttribute('prefix')) {
+                    $prefix = (string) $directoryNode->getAttribute('prefix');
+                }
+
+                $suffix = 'Test.php';
+
+                if ($directoryNode->hasAttribute('suffix')) {
+                    $suffix = (string) $directoryNode->getAttribute('suffix');
+                }
+
+                $phpVersion = PHP_VERSION;
+
+                if ($directoryNode->hasAttribute('phpVersion')) {
+                    $phpVersion = (string) $directoryNode->getAttribute('phpVersion');
+                }
+
+                $phpVersionOperator = new VersionComparisonOperator('>=');
+
+                if ($directoryNode->hasAttribute('phpVersionOperator')) {
+                    $phpVersionOperator = new VersionComparisonOperator((string) $directoryNode->getAttribute('phpVersionOperator'));
+                }
+
+                $directories[] = new TestDirectory(
+                    $this->toAbsolutePath($filename, $directory),
+                    $prefix,
+                    $suffix,
+                    $phpVersion,
+                    $phpVersionOperator
+                );
+            }
+
+            $files = [];
+
+            foreach ($element->getElementsByTagName('file') as $fileNode) {
+                assert($fileNode instanceof DOMElement);
+
+                $file = (string) $fileNode->textContent;
+
+                if (empty($file)) {
+                    continue;
+                }
+
+                $phpVersion = PHP_VERSION;
+
+                if ($fileNode->hasAttribute('phpVersion')) {
+                    $phpVersion = (string) $fileNode->getAttribute('phpVersion');
+                }
+
+                $phpVersionOperator = new VersionComparisonOperator('>=');
+
+                if ($fileNode->hasAttribute('phpVersionOperator')) {
+                    $phpVersionOperator = new VersionComparisonOperator((string) $fileNode->getAttribute('phpVersionOperator'));
+                }
+
+                $files[] = new TestFile(
+                    $this->toAbsolutePath($filename, $file),
+                    $phpVersion,
+                    $phpVersionOperator
+                );
+            }
+
+            $testSuites[] = new TestSuiteConfiguration(
+                (string) $element->getAttribute('name'),
+                TestDirectoryCollection::fromArray($directories),
+                TestFileCollection::fromArray($files),
+                FileCollection::fromArray($exclude)
+            );
+        }
+
+        return TestSuiteCollection::fromArray($testSuites);
+    }
+
+    /**
+     * @return DOMElement[]
+     */
+    private function getTestSuiteElements(DOMXPath $xpath): array
+    {
+        /** @var DOMElement[] $elements */
+        $elements = [];
+
+        $testSuiteNodes = $xpath->query('testsuites/testsuite');
+
+        if ($testSuiteNodes->length === 0) {
+            $testSuiteNodes = $xpath->query('testsuite');
+        }
+
+        if ($testSuiteNodes->length === 1) {
+            $element = $testSuiteNodes->item(0);
+
+            assert($element instanceof DOMElement);
+
+            $elements[] = $element;
+        } else {
+            foreach ($testSuiteNodes as $testSuiteNode) {
+                assert($testSuiteNode instanceof DOMElement);
+
+                $elements[] = $testSuiteNode;
+            }
+        }
+
+        return $elements;
+    }
+
+    private function element(DOMXPath $xpath, string $element): ?DOMElement
+    {
+        $nodes = $xpath->query($element);
+
+        if ($nodes->length === 1) {
+            $node = $nodes->item(0);
+
+            assert($node instanceof DOMElement);
+
+            return $node;
+        }
+
+        return null;
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Logging/Junit.php b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Logging/Junit.php
new file mode 100644
index 0000000000000000000000000000000000000000..efde962d936c24b4089a5d71d52c08e3d48cc6fd
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Logging/Junit.php
@@ -0,0 +1,34 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\TextUI\XmlConfiguration\Logging;
+
+use PHPUnit\TextUI\XmlConfiguration\File;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ * @psalm-immutable
+ */
+final class Junit
+{
+    /**
+     * @var File
+     */
+    private $target;
+
+    public function __construct(File $target)
+    {
+        $this->target = $target;
+    }
+
+    public function target(): File
+    {
+        return $this->target;
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Logging/Logging.php b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Logging/Logging.php
new file mode 100644
index 0000000000000000000000000000000000000000..cdceced5007d61bbf47e5b262a3db8c5852d709c
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Logging/Logging.php
@@ -0,0 +1,146 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\TextUI\XmlConfiguration\Logging;
+
+use PHPUnit\TextUI\XmlConfiguration\Exception;
+use PHPUnit\TextUI\XmlConfiguration\Logging\TestDox\Html as TestDoxHtml;
+use PHPUnit\TextUI\XmlConfiguration\Logging\TestDox\Text as TestDoxText;
+use PHPUnit\TextUI\XmlConfiguration\Logging\TestDox\Xml as TestDoxXml;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ * @psalm-immutable
+ */
+final class Logging
+{
+    /**
+     * @var ?Junit
+     */
+    private $junit;
+
+    /**
+     * @var ?Text
+     */
+    private $text;
+
+    /**
+     * @var ?TeamCity
+     */
+    private $teamCity;
+
+    /**
+     * @var ?TestDoxHtml
+     */
+    private $testDoxHtml;
+
+    /**
+     * @var ?TestDoxText
+     */
+    private $testDoxText;
+
+    /**
+     * @var ?TestDoxXml
+     */
+    private $testDoxXml;
+
+    public function __construct(?Junit $junit, ?Text $text, ?TeamCity $teamCity, ?TestDoxHtml $testDoxHtml, ?TestDoxText $testDoxText, ?TestDoxXml $testDoxXml)
+    {
+        $this->junit       = $junit;
+        $this->text        = $text;
+        $this->teamCity    = $teamCity;
+        $this->testDoxHtml = $testDoxHtml;
+        $this->testDoxText = $testDoxText;
+        $this->testDoxXml  = $testDoxXml;
+    }
+
+    public function hasJunit(): bool
+    {
+        return $this->junit !== null;
+    }
+
+    public function junit(): Junit
+    {
+        if ($this->junit === null) {
+            throw new Exception('Logger "JUnit XML" is not configured');
+        }
+
+        return $this->junit;
+    }
+
+    public function hasText(): bool
+    {
+        return $this->text !== null;
+    }
+
+    public function text(): Text
+    {
+        if ($this->text === null) {
+            throw new Exception('Logger "Text" is not configured');
+        }
+
+        return $this->text;
+    }
+
+    public function hasTeamCity(): bool
+    {
+        return $this->teamCity !== null;
+    }
+
+    public function teamCity(): TeamCity
+    {
+        if ($this->teamCity === null) {
+            throw new Exception('Logger "Team City" is not configured');
+        }
+
+        return $this->teamCity;
+    }
+
+    public function hasTestDoxHtml(): bool
+    {
+        return $this->testDoxHtml !== null;
+    }
+
+    public function testDoxHtml(): TestDoxHtml
+    {
+        if ($this->testDoxHtml === null) {
+            throw new Exception('Logger "TestDox HTML" is not configured');
+        }
+
+        return $this->testDoxHtml;
+    }
+
+    public function hasTestDoxText(): bool
+    {
+        return $this->testDoxText !== null;
+    }
+
+    public function testDoxText(): TestDoxText
+    {
+        if ($this->testDoxText === null) {
+            throw new Exception('Logger "TestDox Text" is not configured');
+        }
+
+        return $this->testDoxText;
+    }
+
+    public function hasTestDoxXml(): bool
+    {
+        return $this->testDoxXml !== null;
+    }
+
+    public function testDoxXml(): TestDoxXml
+    {
+        if ($this->testDoxXml === null) {
+            throw new Exception('Logger "TestDox XML" is not configured');
+        }
+
+        return $this->testDoxXml;
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Logging/TeamCity.php b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Logging/TeamCity.php
new file mode 100644
index 0000000000000000000000000000000000000000..03b2b56a9cc4e65b18f15a0731756b76de75f7f7
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Logging/TeamCity.php
@@ -0,0 +1,34 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\TextUI\XmlConfiguration\Logging;
+
+use PHPUnit\TextUI\XmlConfiguration\File;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ * @psalm-immutable
+ */
+final class TeamCity
+{
+    /**
+     * @var File
+     */
+    private $target;
+
+    public function __construct(File $target)
+    {
+        $this->target = $target;
+    }
+
+    public function target(): File
+    {
+        return $this->target;
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Logging/TestDox/Html.php b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Logging/TestDox/Html.php
new file mode 100644
index 0000000000000000000000000000000000000000..310040b2e5514de295bb81f88b7caf62f8f8f59f
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Logging/TestDox/Html.php
@@ -0,0 +1,34 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\TextUI\XmlConfiguration\Logging\TestDox;
+
+use PHPUnit\TextUI\XmlConfiguration\File;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ * @psalm-immutable
+ */
+final class Html
+{
+    /**
+     * @var File
+     */
+    private $target;
+
+    public function __construct(File $target)
+    {
+        $this->target = $target;
+    }
+
+    public function target(): File
+    {
+        return $this->target;
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Logging/TestDox/Text.php b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Logging/TestDox/Text.php
new file mode 100644
index 0000000000000000000000000000000000000000..59d37e9b230acc414a3f2a9efa2236ece072d156
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Logging/TestDox/Text.php
@@ -0,0 +1,34 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\TextUI\XmlConfiguration\Logging\TestDox;
+
+use PHPUnit\TextUI\XmlConfiguration\File;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ * @psalm-immutable
+ */
+final class Text
+{
+    /**
+     * @var File
+     */
+    private $target;
+
+    public function __construct(File $target)
+    {
+        $this->target = $target;
+    }
+
+    public function target(): File
+    {
+        return $this->target;
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Logging/TestDox/Xml.php b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Logging/TestDox/Xml.php
new file mode 100644
index 0000000000000000000000000000000000000000..b8c1576c169c4c21c593d5b59ba41129dc217128
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Logging/TestDox/Xml.php
@@ -0,0 +1,34 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\TextUI\XmlConfiguration\Logging\TestDox;
+
+use PHPUnit\TextUI\XmlConfiguration\File;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ * @psalm-immutable
+ */
+final class Xml
+{
+    /**
+     * @var File
+     */
+    private $target;
+
+    public function __construct(File $target)
+    {
+        $this->target = $target;
+    }
+
+    public function target(): File
+    {
+        return $this->target;
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Logging/Text.php b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Logging/Text.php
new file mode 100644
index 0000000000000000000000000000000000000000..2769ec96726ff9f122d899aae1896a075c412aba
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Logging/Text.php
@@ -0,0 +1,34 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\TextUI\XmlConfiguration\Logging;
+
+use PHPUnit\TextUI\XmlConfiguration\File;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ * @psalm-immutable
+ */
+final class Text
+{
+    /**
+     * @var File
+     */
+    private $target;
+
+    public function __construct(File $target)
+    {
+        $this->target = $target;
+    }
+
+    public function target(): File
+    {
+        return $this->target;
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/MigrationBuilder.php b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/MigrationBuilder.php
new file mode 100644
index 0000000000000000000000000000000000000000..abef49f10c3bc2f963904560c78a46db13cc8cbf
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/MigrationBuilder.php
@@ -0,0 +1,73 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\TextUI\XmlConfiguration;
+
+use function array_key_exists;
+use function sprintf;
+use function version_compare;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class MigrationBuilder
+{
+    private const AVAILABLE_MIGRATIONS = [
+        '8.5' => [
+            RemoveLogTypes::class,
+        ],
+
+        '9.2' => [
+            RemoveCacheTokensAttribute::class,
+            IntroduceCoverageElement::class,
+            MoveAttributesFromRootToCoverage::class,
+            MoveAttributesFromFilterWhitelistToCoverage::class,
+            MoveWhitelistDirectoriesToCoverage::class,
+            MoveWhitelistExcludesToCoverage::class,
+            RemoveEmptyFilter::class,
+            CoverageCloverToReport::class,
+            CoverageCrap4jToReport::class,
+            CoverageHtmlToReport::class,
+            CoveragePhpToReport::class,
+            CoverageTextToReport::class,
+            CoverageXmlToReport::class,
+            ConvertLogTypes::class,
+            UpdateSchemaLocationTo93::class,
+        ],
+    ];
+
+    /**
+     * @throws MigrationBuilderException
+     */
+    public function build(string $fromVersion): array
+    {
+        if (!array_key_exists($fromVersion, self::AVAILABLE_MIGRATIONS)) {
+            throw new MigrationBuilderException(
+                sprintf(
+                    'Migration from schema version %s is not supported',
+                    $fromVersion
+                )
+            );
+        }
+
+        $stack = [];
+
+        foreach (self::AVAILABLE_MIGRATIONS as $version => $migrations) {
+            if (version_compare($version, $fromVersion, '<')) {
+                continue;
+            }
+
+            foreach ($migrations as $migration) {
+                $stack[] = new $migration;
+            }
+        }
+
+        return $stack;
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/MigrationBuilderException.php b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/MigrationBuilderException.php
new file mode 100644
index 0000000000000000000000000000000000000000..3d3c767af508502d87648694c7180436e2232845
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/MigrationBuilderException.php
@@ -0,0 +1,19 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\TextUI\XmlConfiguration;
+
+use RuntimeException;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class MigrationBuilderException extends RuntimeException implements \PHPUnit\Exception
+{
+}
diff --git a/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/MigrationException.php b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/MigrationException.php
new file mode 100644
index 0000000000000000000000000000000000000000..f92b2db3035bc7b97382326fa05f852977e42888
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/MigrationException.php
@@ -0,0 +1,19 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\TextUI\XmlConfiguration;
+
+use RuntimeException;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class MigrationException extends RuntimeException implements \PHPUnit\Exception
+{
+}
diff --git a/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/ConvertLogTypes.php b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/ConvertLogTypes.php
new file mode 100644
index 0000000000000000000000000000000000000000..697bbe082cb17a137da521cbf3c8a38bf11968fe
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/ConvertLogTypes.php
@@ -0,0 +1,53 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\TextUI\XmlConfiguration;
+
+use DOMDocument;
+use DOMElement;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class ConvertLogTypes implements Migration
+{
+    public function migrate(DOMDocument $document): void
+    {
+        $logging = $document->getElementsByTagName('logging')->item(0);
+
+        if (!$logging instanceof DOMElement) {
+            return;
+        }
+        $types = [
+            'junit'        => 'junit',
+            'teamcity'     => 'teamcity',
+            'testdox-html' => 'testdoxHtml',
+            'testdox-text' => 'testdoxText',
+            'testdox-xml'  => 'testdoxXml',
+            'plain'        => 'text',
+        ];
+
+        $logNodes = [];
+
+        foreach ($logging->getElementsByTagName('log') as $logNode) {
+            if (!isset($types[$logNode->getAttribute('type')])) {
+                continue;
+            }
+
+            $logNodes[] = $logNode;
+        }
+
+        foreach ($logNodes as $oldNode) {
+            $newLogNode = $document->createElement($types[$oldNode->getAttribute('type')]);
+            $newLogNode->setAttribute('outputFile', $oldNode->getAttribute('target'));
+
+            $logging->replaceChild($newLogNode, $oldNode);
+        }
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/CoverageCloverToReport.php b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/CoverageCloverToReport.php
new file mode 100644
index 0000000000000000000000000000000000000000..5f1522b9c59b724e861ede59701d1839f8f7af70
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/CoverageCloverToReport.php
@@ -0,0 +1,31 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\TextUI\XmlConfiguration;
+
+use DOMElement;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class CoverageCloverToReport extends LogToReportMigration
+{
+    protected function forType(): string
+    {
+        return 'coverage-clover';
+    }
+
+    protected function toReportFormat(DOMElement $logNode): DOMElement
+    {
+        $clover = $logNode->ownerDocument->createElement('clover');
+        $clover->setAttribute('outputFile', $logNode->getAttribute('target'));
+
+        return $clover;
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/CoverageCrap4jToReport.php b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/CoverageCrap4jToReport.php
new file mode 100644
index 0000000000000000000000000000000000000000..afbaaec181a4948bb58032247e3b6e2ff61e76c2
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/CoverageCrap4jToReport.php
@@ -0,0 +1,33 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\TextUI\XmlConfiguration;
+
+use DOMElement;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class CoverageCrap4jToReport extends LogToReportMigration
+{
+    protected function forType(): string
+    {
+        return 'coverage-crap4j';
+    }
+
+    protected function toReportFormat(DOMElement $logNode): DOMElement
+    {
+        $crap4j = $logNode->ownerDocument->createElement('crap4j');
+        $crap4j->setAttribute('outputFile', $logNode->getAttribute('target'));
+
+        $this->migrateAttributes($logNode, $crap4j, ['threshold']);
+
+        return $crap4j;
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/CoverageHtmlToReport.php b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/CoverageHtmlToReport.php
new file mode 100644
index 0000000000000000000000000000000000000000..7e12095b4cac2d083002b2f3245b76ede944ed97
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/CoverageHtmlToReport.php
@@ -0,0 +1,33 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\TextUI\XmlConfiguration;
+
+use DOMElement;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class CoverageHtmlToReport extends LogToReportMigration
+{
+    protected function forType(): string
+    {
+        return 'coverage-html';
+    }
+
+    protected function toReportFormat(DOMElement $logNode): DOMElement
+    {
+        $html = $logNode->ownerDocument->createElement('html');
+        $html->setAttribute('outputDirectory', $logNode->getAttribute('target'));
+
+        $this->migrateAttributes($logNode, $html, ['lowUpperBound', 'highLowerBound']);
+
+        return $html;
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/CoveragePhpToReport.php b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/CoveragePhpToReport.php
new file mode 100644
index 0000000000000000000000000000000000000000..bfa10030b1b97b2fcbbccd6c6d95724295c843eb
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/CoveragePhpToReport.php
@@ -0,0 +1,31 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\TextUI\XmlConfiguration;
+
+use DOMElement;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class CoveragePhpToReport extends LogToReportMigration
+{
+    protected function forType(): string
+    {
+        return 'coverage-php';
+    }
+
+    protected function toReportFormat(DOMElement $logNode): DOMElement
+    {
+        $php = $logNode->ownerDocument->createElement('php');
+        $php->setAttribute('outputFile', $logNode->getAttribute('target'));
+
+        return $php;
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/CoverageTextToReport.php b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/CoverageTextToReport.php
new file mode 100644
index 0000000000000000000000000000000000000000..063d8df0c439c65e56f24314ef1fcc45080b25c2
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/CoverageTextToReport.php
@@ -0,0 +1,33 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\TextUI\XmlConfiguration;
+
+use DOMElement;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class CoverageTextToReport extends LogToReportMigration
+{
+    protected function forType(): string
+    {
+        return 'coverage-text';
+    }
+
+    protected function toReportFormat(DOMElement $logNode): DOMElement
+    {
+        $text = $logNode->ownerDocument->createElement('text');
+        $text->setAttribute('outputFile', $logNode->getAttribute('target'));
+
+        $this->migrateAttributes($logNode, $text, ['showUncoveredFiles', 'showOnlySummary']);
+
+        return $text;
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/CoverageXmlToReport.php b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/CoverageXmlToReport.php
new file mode 100644
index 0000000000000000000000000000000000000000..480d7777e3dcfe947b7bdfffc96d3e8f40fc0fa7
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/CoverageXmlToReport.php
@@ -0,0 +1,31 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\TextUI\XmlConfiguration;
+
+use DOMElement;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class CoverageXmlToReport extends LogToReportMigration
+{
+    protected function forType(): string
+    {
+        return 'coverage-xml';
+    }
+
+    protected function toReportFormat(DOMElement $logNode): DOMElement
+    {
+        $xml = $logNode->ownerDocument->createElement('xml');
+        $xml->setAttribute('outputDirectory', $logNode->getAttribute('target'));
+
+        return $xml;
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/IntroduceCoverageElement.php b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/IntroduceCoverageElement.php
new file mode 100644
index 0000000000000000000000000000000000000000..867a84417091d0b9dfbb7ec1c13d8756bcb06d40
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/IntroduceCoverageElement.php
@@ -0,0 +1,28 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\TextUI\XmlConfiguration;
+
+use DOMDocument;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class IntroduceCoverageElement implements Migration
+{
+    public function migrate(DOMDocument $document): void
+    {
+        $coverage = $document->createElement('coverage');
+
+        $document->documentElement->insertBefore(
+            $coverage,
+            $document->documentElement->firstChild
+        );
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/LogToReportMigration.php b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/LogToReportMigration.php
new file mode 100644
index 0000000000000000000000000000000000000000..e987308b73faaa170a698f1e6288107bbb1904f6
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/LogToReportMigration.php
@@ -0,0 +1,79 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\TextUI\XmlConfiguration;
+
+use function sprintf;
+use DOMDocument;
+use DOMElement;
+use DOMXPath;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+abstract class LogToReportMigration implements Migration
+{
+    /**
+     * @throws MigrationException
+     */
+    public function migrate(DOMDocument $document): void
+    {
+        $coverage = $document->getElementsByTagName('coverage')->item(0);
+
+        if (!$coverage instanceof DOMElement) {
+            throw new MigrationException('Unexpected state - No coverage element');
+        }
+
+        $logNode = $this->findLogNode($document);
+
+        if ($logNode === null) {
+            return;
+        }
+
+        $reportChild = $this->toReportFormat($logNode);
+
+        $report = $coverage->getElementsByTagName('report')->item(0);
+
+        if ($report === null) {
+            $report = $coverage->appendChild($document->createElement('report'));
+        }
+
+        $report->appendChild($reportChild);
+        $logNode->parentNode->removeChild($logNode);
+    }
+
+    protected function migrateAttributes(DOMElement $src, DOMElement $dest, array $attributes): void
+    {
+        foreach ($attributes as $attr) {
+            if (!$src->hasAttribute($attr)) {
+                continue;
+            }
+
+            $dest->setAttribute($attr, $src->getAttribute($attr));
+            $src->removeAttribute($attr);
+        }
+    }
+
+    abstract protected function forType(): string;
+
+    abstract protected function toReportFormat(DOMElement $logNode): DOMElement;
+
+    private function findLogNode(DOMDocument $document): ?DOMElement
+    {
+        $logNode = (new DOMXPath($document))->query(
+            sprintf('//logging/log[@type="%s"]', $this->forType())
+        )->item(0);
+
+        if (!$logNode instanceof DOMElement) {
+            return null;
+        }
+
+        return $logNode;
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/Migration.php b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/Migration.php
new file mode 100644
index 0000000000000000000000000000000000000000..fa4092a9fe77d6dbf87e49e0e8393cf416691928
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/Migration.php
@@ -0,0 +1,20 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\TextUI\XmlConfiguration;
+
+use DOMDocument;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+interface Migration
+{
+    public function migrate(DOMDocument $document): void;
+}
diff --git a/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/MoveAttributesFromFilterWhitelistToCoverage.php b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/MoveAttributesFromFilterWhitelistToCoverage.php
new file mode 100644
index 0000000000000000000000000000000000000000..a7aab5e511c60e9100a2b62a0eb423d80fdbebdf
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/MoveAttributesFromFilterWhitelistToCoverage.php
@@ -0,0 +1,51 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\TextUI\XmlConfiguration;
+
+use DOMDocument;
+use DOMElement;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class MoveAttributesFromFilterWhitelistToCoverage implements Migration
+{
+    /**
+     * @throws MigrationException
+     */
+    public function migrate(DOMDocument $document): void
+    {
+        $whitelist = $document->getElementsByTagName('whitelist')->item(0);
+
+        if (!$whitelist) {
+            return;
+        }
+
+        $coverage = $document->getElementsByTagName('coverage')->item(0);
+
+        if (!$coverage instanceof DOMElement) {
+            throw new MigrationException('Unexpected state - No coverage element');
+        }
+
+        $map = [
+            'addUncoveredFilesFromWhitelist'     => 'includeUncoveredFiles',
+            'processUncoveredFilesFromWhitelist' => 'processUncoveredFiles',
+        ];
+
+        foreach ($map as $old => $new) {
+            if (!$whitelist->hasAttribute($old)) {
+                continue;
+            }
+
+            $coverage->setAttribute($new, $whitelist->getAttribute($old));
+            $whitelist->removeAttribute($old);
+        }
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/MoveAttributesFromRootToCoverage.php b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/MoveAttributesFromRootToCoverage.php
new file mode 100644
index 0000000000000000000000000000000000000000..b86b259c34efca9acc566beff87d8771d51e8275
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/MoveAttributesFromRootToCoverage.php
@@ -0,0 +1,47 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\TextUI\XmlConfiguration;
+
+use DOMDocument;
+use DOMElement;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class MoveAttributesFromRootToCoverage implements Migration
+{
+    /**
+     * @throws MigrationException
+     */
+    public function migrate(DOMDocument $document): void
+    {
+        $map = [
+            'disableCodeCoverageIgnore'                 => 'disableCodeCoverageIgnore',
+            'ignoreDeprecatedCodeUnitsFromCodeCoverage' => 'ignoreDeprecatedCodeUnits',
+        ];
+
+        $root = $document->documentElement;
+
+        $coverage = $document->getElementsByTagName('coverage')->item(0);
+
+        if (!$coverage instanceof DOMElement) {
+            throw new MigrationException('Unexpected state - No coverage element');
+        }
+
+        foreach ($map as $old => $new) {
+            if (!$root->hasAttribute($old)) {
+                continue;
+            }
+
+            $coverage->setAttribute($new, $root->getAttribute($old));
+            $root->removeAttribute($old);
+        }
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/MoveWhitelistDirectoriesToCoverage.php b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/MoveWhitelistDirectoriesToCoverage.php
new file mode 100644
index 0000000000000000000000000000000000000000..14e6cec83a0cf1078f629aff17b308784047112c
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/MoveWhitelistDirectoriesToCoverage.php
@@ -0,0 +1,49 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\TextUI\XmlConfiguration;
+
+use DOMDocument;
+use DOMElement;
+use PHPUnit\Util\Xml\SnapshotNodeList;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class MoveWhitelistDirectoriesToCoverage implements Migration
+{
+    /**
+     * @throws MigrationException
+     */
+    public function migrate(DOMDocument $document): void
+    {
+        $whitelist = $document->getElementsByTagName('whitelist')->item(0);
+
+        if ($whitelist === null) {
+            return;
+        }
+
+        $coverage = $document->getElementsByTagName('coverage')->item(0);
+
+        if (!$coverage instanceof DOMElement) {
+            throw new MigrationException('Unexpected state - No coverage element');
+        }
+
+        $include = $document->createElement('include');
+        $coverage->appendChild($include);
+
+        foreach (SnapshotNodeList::fromNodeList($whitelist->childNodes) as $child) {
+            if (!$child instanceof DOMElement || $child->nodeName !== 'directory') {
+                continue;
+            }
+
+            $include->appendChild($child);
+        }
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/MoveWhitelistExcludesToCoverage.php b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/MoveWhitelistExcludesToCoverage.php
new file mode 100644
index 0000000000000000000000000000000000000000..d8958cf4ef4c9104cf96625bf8c4ff6013e8e0c7
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/MoveWhitelistExcludesToCoverage.php
@@ -0,0 +1,70 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\TextUI\XmlConfiguration;
+
+use DOMDocument;
+use DOMElement;
+use PHPUnit\Util\Xml\SnapshotNodeList;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class MoveWhitelistExcludesToCoverage implements Migration
+{
+    /**
+     * @throws MigrationException
+     */
+    public function migrate(DOMDocument $document): void
+    {
+        $whitelist = $document->getElementsByTagName('whitelist')->item(0);
+
+        if ($whitelist === null) {
+            return;
+        }
+
+        $excludeNodes = SnapshotNodeList::fromNodeList($whitelist->getElementsByTagName('exclude'));
+
+        if ($excludeNodes->count() === 0) {
+            return;
+        }
+
+        $coverage = $document->getElementsByTagName('coverage')->item(0);
+
+        if (!$coverage instanceof DOMElement) {
+            throw new MigrationException('Unexpected state - No coverage element');
+        }
+
+        $targetExclude = $coverage->getElementsByTagName('exclude')->item(0);
+
+        if ($targetExclude === null) {
+            $targetExclude = $coverage->appendChild(
+                $document->createElement('exclude')
+            );
+        }
+
+        foreach ($excludeNodes as $excludeNode) {
+            assert($excludeNode instanceof DOMElement);
+
+            foreach (SnapshotNodeList::fromNodeList($excludeNode->childNodes) as $child) {
+                if (!$child instanceof DOMElement || !in_array($child->nodeName, ['directory', 'file'], true)) {
+                    continue;
+                }
+
+                $targetExclude->appendChild($child);
+            }
+
+            if ($excludeNode->getElementsByTagName('*')->count() !== 0) {
+                throw new MigrationException('Dangling child elements in exclude found.');
+            }
+
+            $whitelist->removeChild($excludeNode);
+        }
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/RemoveCacheTokensAttribute.php b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/RemoveCacheTokensAttribute.php
new file mode 100644
index 0000000000000000000000000000000000000000..0eec12ac17e5513e310560bfa09aee46efd9c1f5
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/RemoveCacheTokensAttribute.php
@@ -0,0 +1,27 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\TextUI\XmlConfiguration;
+
+use DOMDocument;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class RemoveCacheTokensAttribute implements Migration
+{
+    public function migrate(DOMDocument $document): void
+    {
+        $root = $document->documentElement;
+
+        if ($root->hasAttribute('cacheTokens')) {
+            $root->removeAttribute('cacheTokens');
+        }
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/RemoveEmptyFilter.php b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/RemoveEmptyFilter.php
new file mode 100644
index 0000000000000000000000000000000000000000..8f1a6d5471ccd99ad713295718cbd79920073d9c
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/RemoveEmptyFilter.php
@@ -0,0 +1,54 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\TextUI\XmlConfiguration;
+
+use function sprintf;
+use DOMDocument;
+use DOMElement;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class RemoveEmptyFilter implements Migration
+{
+    /**
+     * @throws MigrationException
+     */
+    public function migrate(DOMDocument $document): void
+    {
+        $whitelist = $document->getElementsByTagName('whitelist')->item(0);
+
+        if ($whitelist instanceof DOMElement) {
+            $this->ensureEmpty($whitelist);
+            $whitelist->parentNode->removeChild($whitelist);
+        }
+
+        $filter = $document->getElementsByTagName('filter')->item(0);
+
+        if ($filter instanceof DOMElement) {
+            $this->ensureEmpty($filter);
+            $filter->parentNode->removeChild($filter);
+        }
+    }
+
+    /**
+     * @throws MigrationException
+     */
+    private function ensureEmpty(DOMElement $element): void
+    {
+        if ($element->attributes->length > 0) {
+            throw new MigrationException(sprintf('%s element has unexpected attributes', $element->nodeName));
+        }
+
+        if ($element->getElementsByTagName('*')->length > 0) {
+            throw new MigrationException(sprintf('%s element has unexpected children', $element->nodeName));
+        }
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/RemoveLogTypes.php b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/RemoveLogTypes.php
new file mode 100644
index 0000000000000000000000000000000000000000..99a762b18f82a43a79a96dad056f3e7981c7be93
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/RemoveLogTypes.php
@@ -0,0 +1,37 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\TextUI\XmlConfiguration;
+
+use DOMDocument;
+use DOMElement;
+use PHPUnit\Util\Xml\SnapshotNodeList;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class RemoveLogTypes implements Migration
+{
+    public function migrate(DOMDocument $document): void
+    {
+        $logging = $document->getElementsByTagName('logging')->item(0);
+
+        if (!$logging instanceof DOMElement) {
+            return;
+        }
+
+        foreach (SnapshotNodeList::fromNodeList($logging->getElementsByTagName('log')) as $logNode) {
+            switch ($logNode->getAttribute('type')) {
+                case 'json':
+                case 'tap':
+                    $logging->removeChild($logNode);
+            }
+        }
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/UpdateSchemaLocationTo93.php b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/UpdateSchemaLocationTo93.php
new file mode 100644
index 0000000000000000000000000000000000000000..2e86ab6e9fa91f38a75efb7b38b9e7d67b1ca58f
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/UpdateSchemaLocationTo93.php
@@ -0,0 +1,27 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\TextUI\XmlConfiguration;
+
+use DOMDocument;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class UpdateSchemaLocationTo93 implements Migration
+{
+    public function migrate(DOMDocument $document): void
+    {
+        $document->documentElement->setAttributeNS(
+            'http://www.w3.org/2001/XMLSchema-instance',
+            'xsi:noNamespaceSchemaLocation',
+            'https://schema.phpunit.de/9.3/phpunit.xsd'
+        );
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrator.php b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrator.php
new file mode 100644
index 0000000000000000000000000000000000000000..d173e7af24b02aced5712758914424e4bbae266e
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrator.php
@@ -0,0 +1,57 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\TextUI\XmlConfiguration;
+
+use function sprintf;
+use PHPUnit\Util\Xml\Exception as XmlException;
+use PHPUnit\Util\Xml\Loader as XmlLoader;
+use PHPUnit\Util\Xml\SchemaDetector;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class Migrator
+{
+    /**
+     * @throws Exception
+     * @throws MigrationBuilderException
+     * @throws MigrationException
+     * @throws XmlException
+     */
+    public function migrate(string $filename): string
+    {
+        $origin = (new SchemaDetector)->detect($filename);
+
+        if (!$origin->detected()) {
+            throw new Exception(
+                sprintf(
+                    '"%s" is not a valid PHPUnit XML configuration file that can be migrated',
+                    $filename,
+                )
+            );
+        }
+
+        $configurationDocument = (new XmlLoader)->loadFile(
+            $filename,
+            false,
+            true,
+            true
+        );
+
+        foreach ((new MigrationBuilder)->build($origin->version()) as $migration) {
+            $migration->migrate($configurationDocument);
+        }
+
+        $configurationDocument->formatOutput       = true;
+        $configurationDocument->preserveWhiteSpace = false;
+
+        return $configurationDocument->saveXML();
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/PHP/Constant.php b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/PHP/Constant.php
new file mode 100644
index 0000000000000000000000000000000000000000..e9b28b9e89de64447597800e081a67739b6d730c
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/PHP/Constant.php
@@ -0,0 +1,43 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\TextUI\XmlConfiguration;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ * @psalm-immutable
+ */
+final class Constant
+{
+    /**
+     * @var string
+     */
+    private $name;
+
+    /**
+     * @var mixed
+     */
+    private $value;
+
+    public function __construct(string $name, $value)
+    {
+        $this->name  = $name;
+        $this->value = $value;
+    }
+
+    public function name(): string
+    {
+        return $this->name;
+    }
+
+    public function value()
+    {
+        return $this->value;
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/PHP/ConstantCollection.php b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/PHP/ConstantCollection.php
new file mode 100644
index 0000000000000000000000000000000000000000..51c14715fc242db216f2ed7b81a4ad464628e297
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/PHP/ConstantCollection.php
@@ -0,0 +1,57 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\TextUI\XmlConfiguration;
+
+use function count;
+use Countable;
+use IteratorAggregate;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ * @psalm-immutable
+ */
+final class ConstantCollection implements Countable, IteratorAggregate
+{
+    /**
+     * @var Constant[]
+     */
+    private $constants;
+
+    /**
+     * @param Constant[] $constants
+     */
+    public static function fromArray(array $constants): self
+    {
+        return new self(...$constants);
+    }
+
+    private function __construct(Constant ...$constants)
+    {
+        $this->constants = $constants;
+    }
+
+    /**
+     * @return Constant[]
+     */
+    public function asArray(): array
+    {
+        return $this->constants;
+    }
+
+    public function count(): int
+    {
+        return count($this->constants);
+    }
+
+    public function getIterator(): ConstantCollectionIterator
+    {
+        return new ConstantCollectionIterator($this);
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/PHP/ConstantCollectionIterator.php b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/PHP/ConstantCollectionIterator.php
new file mode 100644
index 0000000000000000000000000000000000000000..c1c8d834bae3251edf914293bbd2c1dd72fbd94d
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/PHP/ConstantCollectionIterator.php
@@ -0,0 +1,66 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\TextUI\XmlConfiguration;
+
+use function count;
+use function iterator_count;
+use Countable;
+use Iterator;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class ConstantCollectionIterator implements Countable, Iterator
+{
+    /**
+     * @var Constant[]
+     */
+    private $constants;
+
+    /**
+     * @var int
+     */
+    private $position;
+
+    public function __construct(ConstantCollection $constants)
+    {
+        $this->constants = $constants->asArray();
+    }
+
+    public function count(): int
+    {
+        return iterator_count($this);
+    }
+
+    public function rewind(): void
+    {
+        $this->position = 0;
+    }
+
+    public function valid(): bool
+    {
+        return $this->position < count($this->constants);
+    }
+
+    public function key(): int
+    {
+        return $this->position;
+    }
+
+    public function current(): Constant
+    {
+        return $this->constants[$this->position];
+    }
+
+    public function next(): void
+    {
+        $this->position++;
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/PHP/IniSetting.php b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/PHP/IniSetting.php
new file mode 100644
index 0000000000000000000000000000000000000000..58cf735b09135e4784ababe083d8cf5c7884420d
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/PHP/IniSetting.php
@@ -0,0 +1,43 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\TextUI\XmlConfiguration;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ * @psalm-immutable
+ */
+final class IniSetting
+{
+    /**
+     * @var string
+     */
+    private $name;
+
+    /**
+     * @var string
+     */
+    private $value;
+
+    public function __construct(string $name, string $value)
+    {
+        $this->name  = $name;
+        $this->value = $value;
+    }
+
+    public function name(): string
+    {
+        return $this->name;
+    }
+
+    public function value(): string
+    {
+        return $this->value;
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/PHP/IniSettingCollection.php b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/PHP/IniSettingCollection.php
new file mode 100644
index 0000000000000000000000000000000000000000..216d85aeced65812fa0b10fa7e7c2e9945d236a1
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/PHP/IniSettingCollection.php
@@ -0,0 +1,57 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\TextUI\XmlConfiguration;
+
+use function count;
+use Countable;
+use IteratorAggregate;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ * @psalm-immutable
+ */
+final class IniSettingCollection implements Countable, IteratorAggregate
+{
+    /**
+     * @var IniSetting[]
+     */
+    private $iniSettings;
+
+    /**
+     * @param IniSetting[] $iniSettings
+     */
+    public static function fromArray(array $iniSettings): self
+    {
+        return new self(...$iniSettings);
+    }
+
+    private function __construct(IniSetting ...$iniSettings)
+    {
+        $this->iniSettings = $iniSettings;
+    }
+
+    /**
+     * @return IniSetting[]
+     */
+    public function asArray(): array
+    {
+        return $this->iniSettings;
+    }
+
+    public function count(): int
+    {
+        return count($this->iniSettings);
+    }
+
+    public function getIterator(): IniSettingCollectionIterator
+    {
+        return new IniSettingCollectionIterator($this);
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/PHP/IniSettingCollectionIterator.php b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/PHP/IniSettingCollectionIterator.php
new file mode 100644
index 0000000000000000000000000000000000000000..f31225e8f681bc06b5ac571bbd89fa0bfbb4a39e
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/PHP/IniSettingCollectionIterator.php
@@ -0,0 +1,66 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\TextUI\XmlConfiguration;
+
+use function count;
+use function iterator_count;
+use Countable;
+use Iterator;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class IniSettingCollectionIterator implements Countable, Iterator
+{
+    /**
+     * @var IniSetting[]
+     */
+    private $iniSettings;
+
+    /**
+     * @var int
+     */
+    private $position;
+
+    public function __construct(IniSettingCollection $iniSettings)
+    {
+        $this->iniSettings = $iniSettings->asArray();
+    }
+
+    public function count(): int
+    {
+        return iterator_count($this);
+    }
+
+    public function rewind(): void
+    {
+        $this->position = 0;
+    }
+
+    public function valid(): bool
+    {
+        return $this->position < count($this->iniSettings);
+    }
+
+    public function key(): int
+    {
+        return $this->position;
+    }
+
+    public function current(): IniSetting
+    {
+        return $this->iniSettings[$this->position];
+    }
+
+    public function next(): void
+    {
+        $this->position++;
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/PHP/Php.php b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/PHP/Php.php
new file mode 100644
index 0000000000000000000000000000000000000000..26897e3593feaef4bd8350490c75a5e5b55ff3a6
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/PHP/Php.php
@@ -0,0 +1,142 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\TextUI\XmlConfiguration;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ * @psalm-immutable
+ */
+final class Php
+{
+    /**
+     * @var DirectoryCollection
+     */
+    private $includePaths;
+
+    /**
+     * @var IniSettingCollection
+     */
+    private $iniSettings;
+
+    /**
+     * @var ConstantCollection
+     */
+    private $constants;
+
+    /**
+     * @var VariableCollection
+     */
+    private $globalVariables;
+
+    /**
+     * @var VariableCollection
+     */
+    private $envVariables;
+
+    /**
+     * @var VariableCollection
+     */
+    private $postVariables;
+
+    /**
+     * @var VariableCollection
+     */
+    private $getVariables;
+
+    /**
+     * @var VariableCollection
+     */
+    private $cookieVariables;
+
+    /**
+     * @var VariableCollection
+     */
+    private $serverVariables;
+
+    /**
+     * @var VariableCollection
+     */
+    private $filesVariables;
+
+    /**
+     * @var VariableCollection
+     */
+    private $requestVariables;
+
+    public function __construct(DirectoryCollection $includePaths, IniSettingCollection $iniSettings, ConstantCollection $constants, VariableCollection $globalVariables, VariableCollection $envVariables, VariableCollection $postVariables, VariableCollection $getVariables, VariableCollection $cookieVariables, VariableCollection $serverVariables, VariableCollection $filesVariables, VariableCollection $requestVariables)
+    {
+        $this->includePaths     = $includePaths;
+        $this->iniSettings      = $iniSettings;
+        $this->constants        = $constants;
+        $this->globalVariables  = $globalVariables;
+        $this->envVariables     = $envVariables;
+        $this->postVariables    = $postVariables;
+        $this->getVariables     = $getVariables;
+        $this->cookieVariables  = $cookieVariables;
+        $this->serverVariables  = $serverVariables;
+        $this->filesVariables   = $filesVariables;
+        $this->requestVariables = $requestVariables;
+    }
+
+    public function includePaths(): DirectoryCollection
+    {
+        return $this->includePaths;
+    }
+
+    public function iniSettings(): IniSettingCollection
+    {
+        return $this->iniSettings;
+    }
+
+    public function constants(): ConstantCollection
+    {
+        return $this->constants;
+    }
+
+    public function globalVariables(): VariableCollection
+    {
+        return $this->globalVariables;
+    }
+
+    public function envVariables(): VariableCollection
+    {
+        return $this->envVariables;
+    }
+
+    public function postVariables(): VariableCollection
+    {
+        return $this->postVariables;
+    }
+
+    public function getVariables(): VariableCollection
+    {
+        return $this->getVariables;
+    }
+
+    public function cookieVariables(): VariableCollection
+    {
+        return $this->cookieVariables;
+    }
+
+    public function serverVariables(): VariableCollection
+    {
+        return $this->serverVariables;
+    }
+
+    public function filesVariables(): VariableCollection
+    {
+        return $this->filesVariables;
+    }
+
+    public function requestVariables(): VariableCollection
+    {
+        return $this->requestVariables;
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/PHP/PhpHandler.php b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/PHP/PhpHandler.php
new file mode 100644
index 0000000000000000000000000000000000000000..5fb0c72b21c726c97cd658935fe61a8cf103f707
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/PHP/PhpHandler.php
@@ -0,0 +1,121 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\TextUI\XmlConfiguration;
+
+use const PATH_SEPARATOR;
+use function constant;
+use function define;
+use function defined;
+use function getenv;
+use function implode;
+use function ini_get;
+use function ini_set;
+use function putenv;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class PhpHandler
+{
+    public function handle(Php $configuration): void
+    {
+        $this->handleIncludePaths($configuration->includePaths());
+        $this->handleIniSettings($configuration->iniSettings());
+        $this->handleConstants($configuration->constants());
+        $this->handleGlobalVariables($configuration->globalVariables());
+        $this->handleServerVariables($configuration->serverVariables());
+        $this->handleEnvVariables($configuration->envVariables());
+        $this->handleVariables('_POST', $configuration->postVariables());
+        $this->handleVariables('_GET', $configuration->getVariables());
+        $this->handleVariables('_COOKIE', $configuration->cookieVariables());
+        $this->handleVariables('_FILES', $configuration->filesVariables());
+        $this->handleVariables('_REQUEST', $configuration->requestVariables());
+    }
+
+    private function handleIncludePaths(DirectoryCollection $includePaths): void
+    {
+        if (!$includePaths->isEmpty()) {
+            $includePathsAsStrings = [];
+
+            foreach ($includePaths as $includePath) {
+                $includePathsAsStrings[] = $includePath->path();
+            }
+
+            ini_set(
+                'include_path',
+                implode(PATH_SEPARATOR, $includePathsAsStrings) .
+                PATH_SEPARATOR .
+                ini_get('include_path')
+            );
+        }
+    }
+
+    private function handleIniSettings(IniSettingCollection $iniSettings): void
+    {
+        foreach ($iniSettings as $iniSetting) {
+            $value = $iniSetting->value();
+
+            if (defined($value)) {
+                $value = (string) constant($value);
+            }
+
+            ini_set($iniSetting->name(), $value);
+        }
+    }
+
+    private function handleConstants(ConstantCollection $constants): void
+    {
+        foreach ($constants as $constant) {
+            if (!defined($constant->name())) {
+                define($constant->name(), $constant->value());
+            }
+        }
+    }
+
+    private function handleGlobalVariables(VariableCollection $variables): void
+    {
+        foreach ($variables as $variable) {
+            $GLOBALS[$variable->name()] = $variable->value();
+        }
+    }
+
+    private function handleServerVariables(VariableCollection $variables): void
+    {
+        foreach ($variables as $variable) {
+            $_SERVER[$variable->name()] = $variable->value();
+        }
+    }
+
+    private function handleVariables(string $target, VariableCollection $variables): void
+    {
+        foreach ($variables as $variable) {
+            $GLOBALS[$target][$variable->name()] = $variable->value();
+        }
+    }
+
+    private function handleEnvVariables(VariableCollection $variables): void
+    {
+        foreach ($variables as $variable) {
+            $name  = $variable->name();
+            $value = $variable->value();
+            $force = $variable->force();
+
+            if ($force || getenv($name) === false) {
+                putenv("{$name}={$value}");
+            }
+
+            $value = getenv($name);
+
+            if ($force || !isset($_ENV[$name])) {
+                $_ENV[$name] = $value;
+            }
+        }
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/PHP/Variable.php b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/PHP/Variable.php
new file mode 100644
index 0000000000000000000000000000000000000000..c2684e28f630859b2f0e3166b9b189bb4f80b327
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/PHP/Variable.php
@@ -0,0 +1,54 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\TextUI\XmlConfiguration;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ * @psalm-immutable
+ */
+final class Variable
+{
+    /**
+     * @var string
+     */
+    private $name;
+
+    /**
+     * @var mixed
+     */
+    private $value;
+
+    /**
+     * @var bool
+     */
+    private $force;
+
+    public function __construct(string $name, $value, bool $force)
+    {
+        $this->name  = $name;
+        $this->value = $value;
+        $this->force = $force;
+    }
+
+    public function name(): string
+    {
+        return $this->name;
+    }
+
+    public function value()
+    {
+        return $this->value;
+    }
+
+    public function force(): bool
+    {
+        return $this->force;
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/PHP/VariableCollection.php b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/PHP/VariableCollection.php
new file mode 100644
index 0000000000000000000000000000000000000000..e84992168f6482eebe0824e1120a085a25766880
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/PHP/VariableCollection.php
@@ -0,0 +1,57 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\TextUI\XmlConfiguration;
+
+use function count;
+use Countable;
+use IteratorAggregate;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ * @psalm-immutable
+ */
+final class VariableCollection implements Countable, IteratorAggregate
+{
+    /**
+     * @var Variable[]
+     */
+    private $variables;
+
+    /**
+     * @param Variable[] $variables
+     */
+    public static function fromArray(array $variables): self
+    {
+        return new self(...$variables);
+    }
+
+    private function __construct(Variable ...$variables)
+    {
+        $this->variables = $variables;
+    }
+
+    /**
+     * @return Variable[]
+     */
+    public function asArray(): array
+    {
+        return $this->variables;
+    }
+
+    public function count(): int
+    {
+        return count($this->variables);
+    }
+
+    public function getIterator(): VariableCollectionIterator
+    {
+        return new VariableCollectionIterator($this);
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/PHP/VariableCollectionIterator.php b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/PHP/VariableCollectionIterator.php
new file mode 100644
index 0000000000000000000000000000000000000000..3d594c1ee58caf9f25b2f9f2d135b746e72fa854
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/PHP/VariableCollectionIterator.php
@@ -0,0 +1,66 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\TextUI\XmlConfiguration;
+
+use function count;
+use function iterator_count;
+use Countable;
+use Iterator;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class VariableCollectionIterator implements Countable, Iterator
+{
+    /**
+     * @var Variable[]
+     */
+    private $variables;
+
+    /**
+     * @var int
+     */
+    private $position;
+
+    public function __construct(VariableCollection $variables)
+    {
+        $this->variables = $variables->asArray();
+    }
+
+    public function count(): int
+    {
+        return iterator_count($this);
+    }
+
+    public function rewind(): void
+    {
+        $this->position = 0;
+    }
+
+    public function valid(): bool
+    {
+        return $this->position < count($this->variables);
+    }
+
+    public function key(): int
+    {
+        return $this->position;
+    }
+
+    public function current(): Variable
+    {
+        return $this->variables[$this->position];
+    }
+
+    public function next(): void
+    {
+        $this->position++;
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/PHPUnit/Extension.php b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/PHPUnit/Extension.php
new file mode 100644
index 0000000000000000000000000000000000000000..77c5b2d0d644494f9182be7438cd08154a515dea
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/PHPUnit/Extension.php
@@ -0,0 +1,71 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\TextUI\XmlConfiguration;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ * @psalm-immutable
+ */
+final class Extension
+{
+    /**
+     * @var string
+     * @psalm-var class-string
+     */
+    private $className;
+
+    /**
+     * @var string
+     */
+    private $sourceFile;
+
+    /**
+     * @var array
+     */
+    private $arguments;
+
+    /**
+     * @psalm-param class-string $className
+     */
+    public function __construct(string $className, string $sourceFile, array $arguments)
+    {
+        $this->className  = $className;
+        $this->sourceFile = $sourceFile;
+        $this->arguments  = $arguments;
+    }
+
+    /**
+     * @psalm-return class-string
+     */
+    public function className(): string
+    {
+        return $this->className;
+    }
+
+    public function hasSourceFile(): bool
+    {
+        return $this->sourceFile !== '';
+    }
+
+    public function sourceFile(): string
+    {
+        return $this->sourceFile;
+    }
+
+    public function hasArguments(): bool
+    {
+        return !empty($this->arguments);
+    }
+
+    public function arguments(): array
+    {
+        return $this->arguments;
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/PHPUnit/ExtensionCollection.php b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/PHPUnit/ExtensionCollection.php
new file mode 100644
index 0000000000000000000000000000000000000000..45be2eeebc72a797f7b227d213875bc1bcfb846b
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/PHPUnit/ExtensionCollection.php
@@ -0,0 +1,50 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\TextUI\XmlConfiguration;
+
+use IteratorAggregate;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ * @psalm-immutable
+ */
+final class ExtensionCollection implements IteratorAggregate
+{
+    /**
+     * @var Extension[]
+     */
+    private $extensions;
+
+    /**
+     * @param Extension[] $extensions
+     */
+    public static function fromArray(array $extensions): self
+    {
+        return new self(...$extensions);
+    }
+
+    private function __construct(Extension ...$extensions)
+    {
+        $this->extensions = $extensions;
+    }
+
+    /**
+     * @return Extension[]
+     */
+    public function asArray(): array
+    {
+        return $this->extensions;
+    }
+
+    public function getIterator(): ExtensionCollectionIterator
+    {
+        return new ExtensionCollectionIterator($this);
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/PHPUnit/ExtensionCollectionIterator.php b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/PHPUnit/ExtensionCollectionIterator.php
new file mode 100644
index 0000000000000000000000000000000000000000..4bd54be4943e0b07847c6a0a1cbbf311a57cc98b
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/PHPUnit/ExtensionCollectionIterator.php
@@ -0,0 +1,66 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\TextUI\XmlConfiguration;
+
+use function count;
+use function iterator_count;
+use Countable;
+use Iterator;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class ExtensionCollectionIterator implements Countable, Iterator
+{
+    /**
+     * @var Extension[]
+     */
+    private $extensions;
+
+    /**
+     * @var int
+     */
+    private $position;
+
+    public function __construct(ExtensionCollection $extensions)
+    {
+        $this->extensions = $extensions->asArray();
+    }
+
+    public function count(): int
+    {
+        return iterator_count($this);
+    }
+
+    public function rewind(): void
+    {
+        $this->position = 0;
+    }
+
+    public function valid(): bool
+    {
+        return $this->position < count($this->extensions);
+    }
+
+    public function key(): int
+    {
+        return $this->position;
+    }
+
+    public function current(): Extension
+    {
+        return $this->extensions[$this->position];
+    }
+
+    public function next(): void
+    {
+        $this->position++;
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/PHPUnit/PHPUnit.php b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/PHPUnit/PHPUnit.php
new file mode 100644
index 0000000000000000000000000000000000000000..edf298dd5ce4163c9b94dea943fef0ca2b548415
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/PHPUnit/PHPUnit.php
@@ -0,0 +1,714 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\TextUI\XmlConfiguration;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ * @psalm-immutable
+ */
+final class PHPUnit
+{
+    /**
+     * @var bool
+     */
+    private $cacheResult;
+
+    /**
+     * @var ?string
+     */
+    private $cacheResultFile;
+
+    /**
+     * @var int|string
+     */
+    private $columns;
+
+    /**
+     * @var string
+     */
+    private $colors;
+
+    /**
+     * @var bool
+     */
+    private $stderr;
+
+    /**
+     * @var bool
+     */
+    private $noInteraction;
+
+    /**
+     * @var bool
+     */
+    private $verbose;
+
+    /**
+     * @var bool
+     */
+    private $reverseDefectList;
+
+    /**
+     * @var bool
+     */
+    private $convertDeprecationsToExceptions;
+
+    /**
+     * @var bool
+     */
+    private $convertErrorsToExceptions;
+
+    /**
+     * @var bool
+     */
+    private $convertNoticesToExceptions;
+
+    /**
+     * @var bool
+     */
+    private $convertWarningsToExceptions;
+
+    /**
+     * @var bool
+     */
+    private $forceCoversAnnotation;
+
+    /**
+     * @var ?string
+     */
+    private $bootstrap;
+
+    /**
+     * @var bool
+     */
+    private $processIsolation;
+
+    /**
+     * @var bool
+     */
+    private $failOnEmptyTestSuite;
+
+    /**
+     * @var bool
+     */
+    private $failOnIncomplete;
+
+    /**
+     * @var bool
+     */
+    private $failOnRisky;
+
+    /**
+     * @var bool
+     */
+    private $failOnSkipped;
+
+    /**
+     * @var bool
+     */
+    private $failOnWarning;
+
+    /**
+     * @var bool
+     */
+    private $stopOnDefect;
+
+    /**
+     * @var bool
+     */
+    private $stopOnError;
+
+    /**
+     * @var bool
+     */
+    private $stopOnFailure;
+
+    /**
+     * @var bool
+     */
+    private $stopOnWarning;
+
+    /**
+     * @var bool
+     */
+    private $stopOnIncomplete;
+
+    /**
+     * @var bool
+     */
+    private $stopOnRisky;
+
+    /**
+     * @var bool
+     */
+    private $stopOnSkipped;
+
+    /**
+     * @var ?string
+     */
+    private $extensionsDirectory;
+
+    /**
+     * @var ?string
+     *
+     * @deprecated see https://github.com/sebastianbergmann/phpunit/issues/4039
+     */
+    private $testSuiteLoaderClass;
+
+    /**
+     * @var ?string
+     *
+     * @deprecated see https://github.com/sebastianbergmann/phpunit/issues/4039
+     */
+    private $testSuiteLoaderFile;
+
+    /**
+     * @var ?string
+     */
+    private $printerClass;
+
+    /**
+     * @var ?string
+     */
+    private $printerFile;
+
+    /**
+     * @var bool
+     */
+    private $beStrictAboutChangesToGlobalState;
+
+    /**
+     * @var bool
+     */
+    private $beStrictAboutOutputDuringTests;
+
+    /**
+     * @var bool
+     */
+    private $beStrictAboutResourceUsageDuringSmallTests;
+
+    /**
+     * @var bool
+     */
+    private $beStrictAboutTestsThatDoNotTestAnything;
+
+    /**
+     * @var bool
+     */
+    private $beStrictAboutTodoAnnotatedTests;
+
+    /**
+     * @var bool
+     */
+    private $beStrictAboutCoversAnnotation;
+
+    /**
+     * @var bool
+     */
+    private $enforceTimeLimit;
+
+    /**
+     * @var int
+     */
+    private $defaultTimeLimit;
+
+    /**
+     * @var int
+     */
+    private $timeoutForSmallTests;
+
+    /**
+     * @var int
+     */
+    private $timeoutForMediumTests;
+
+    /**
+     * @var int
+     */
+    private $timeoutForLargeTests;
+
+    /**
+     * @var ?string
+     */
+    private $defaultTestSuite;
+
+    /**
+     * @var int
+     */
+    private $executionOrder;
+
+    /**
+     * @var bool
+     */
+    private $resolveDependencies;
+
+    /**
+     * @var bool
+     */
+    private $defectsFirst;
+
+    /**
+     * @var bool
+     */
+    private $backupGlobals;
+
+    /**
+     * @var bool
+     */
+    private $backupStaticAttributes;
+
+    /**
+     * @var bool
+     */
+    private $registerMockObjectsFromTestArgumentsRecursively;
+
+    /**
+     * @var bool
+     */
+    private $conflictBetweenPrinterClassAndTestdox;
+
+    public function __construct(bool $cacheResult, ?string $cacheResultFile, $columns, string $colors, bool $stderr, bool $noInteraction, bool $verbose, bool $reverseDefectList, bool $convertDeprecationsToExceptions, bool $convertErrorsToExceptions, bool $convertNoticesToExceptions, bool $convertWarningsToExceptions, bool $forceCoversAnnotation, ?string $bootstrap, bool $processIsolation, bool $failOnEmptyTestSuite, bool $failOnIncomplete, bool $failOnRisky, bool $failOnSkipped, bool $failOnWarning, bool $stopOnDefect, bool $stopOnError, bool $stopOnFailure, bool $stopOnWarning, bool $stopOnIncomplete, bool $stopOnRisky, bool $stopOnSkipped, ?string $extensionsDirectory, ?string $testSuiteLoaderClass, ?string $testSuiteLoaderFile, ?string $printerClass, ?string $printerFile, bool $beStrictAboutChangesToGlobalState, bool $beStrictAboutOutputDuringTests, bool $beStrictAboutResourceUsageDuringSmallTests, bool $beStrictAboutTestsThatDoNotTestAnything, bool $beStrictAboutTodoAnnotatedTests, bool $beStrictAboutCoversAnnotation, bool $enforceTimeLimit, int $defaultTimeLimit, int $timeoutForSmallTests, int $timeoutForMediumTests, int $timeoutForLargeTests, ?string $defaultTestSuite, int $executionOrder, bool $resolveDependencies, bool $defectsFirst, bool $backupGlobals, bool $backupStaticAttributes, bool $registerMockObjectsFromTestArgumentsRecursively, bool $conflictBetweenPrinterClassAndTestdox)
+    {
+        $this->cacheResult                                     = $cacheResult;
+        $this->cacheResultFile                                 = $cacheResultFile;
+        $this->columns                                         = $columns;
+        $this->colors                                          = $colors;
+        $this->stderr                                          = $stderr;
+        $this->noInteraction                                   = $noInteraction;
+        $this->verbose                                         = $verbose;
+        $this->reverseDefectList                               = $reverseDefectList;
+        $this->convertDeprecationsToExceptions                 = $convertDeprecationsToExceptions;
+        $this->convertErrorsToExceptions                       = $convertErrorsToExceptions;
+        $this->convertNoticesToExceptions                      = $convertNoticesToExceptions;
+        $this->convertWarningsToExceptions                     = $convertWarningsToExceptions;
+        $this->forceCoversAnnotation                           = $forceCoversAnnotation;
+        $this->bootstrap                                       = $bootstrap;
+        $this->processIsolation                                = $processIsolation;
+        $this->failOnEmptyTestSuite                            = $failOnEmptyTestSuite;
+        $this->failOnIncomplete                                = $failOnIncomplete;
+        $this->failOnRisky                                     = $failOnRisky;
+        $this->failOnSkipped                                   = $failOnSkipped;
+        $this->failOnWarning                                   = $failOnWarning;
+        $this->stopOnDefect                                    = $stopOnDefect;
+        $this->stopOnError                                     = $stopOnError;
+        $this->stopOnFailure                                   = $stopOnFailure;
+        $this->stopOnWarning                                   = $stopOnWarning;
+        $this->stopOnIncomplete                                = $stopOnIncomplete;
+        $this->stopOnRisky                                     = $stopOnRisky;
+        $this->stopOnSkipped                                   = $stopOnSkipped;
+        $this->extensionsDirectory                             = $extensionsDirectory;
+        $this->testSuiteLoaderClass                            = $testSuiteLoaderClass;
+        $this->testSuiteLoaderFile                             = $testSuiteLoaderFile;
+        $this->printerClass                                    = $printerClass;
+        $this->printerFile                                     = $printerFile;
+        $this->beStrictAboutChangesToGlobalState               = $beStrictAboutChangesToGlobalState;
+        $this->beStrictAboutOutputDuringTests                  = $beStrictAboutOutputDuringTests;
+        $this->beStrictAboutResourceUsageDuringSmallTests      = $beStrictAboutResourceUsageDuringSmallTests;
+        $this->beStrictAboutTestsThatDoNotTestAnything         = $beStrictAboutTestsThatDoNotTestAnything;
+        $this->beStrictAboutTodoAnnotatedTests                 = $beStrictAboutTodoAnnotatedTests;
+        $this->beStrictAboutCoversAnnotation                   = $beStrictAboutCoversAnnotation;
+        $this->enforceTimeLimit                                = $enforceTimeLimit;
+        $this->defaultTimeLimit                                = $defaultTimeLimit;
+        $this->timeoutForSmallTests                            = $timeoutForSmallTests;
+        $this->timeoutForMediumTests                           = $timeoutForMediumTests;
+        $this->timeoutForLargeTests                            = $timeoutForLargeTests;
+        $this->defaultTestSuite                                = $defaultTestSuite;
+        $this->executionOrder                                  = $executionOrder;
+        $this->resolveDependencies                             = $resolveDependencies;
+        $this->defectsFirst                                    = $defectsFirst;
+        $this->backupGlobals                                   = $backupGlobals;
+        $this->backupStaticAttributes                          = $backupStaticAttributes;
+        $this->registerMockObjectsFromTestArgumentsRecursively = $registerMockObjectsFromTestArgumentsRecursively;
+        $this->conflictBetweenPrinterClassAndTestdox           = $conflictBetweenPrinterClassAndTestdox;
+    }
+
+    public function cacheResult(): bool
+    {
+        return $this->cacheResult;
+    }
+
+    /**
+     * @psalm-assert-if-true !null $this->cacheResultFile
+     */
+    public function hasCacheResultFile(): bool
+    {
+        return $this->cacheResultFile !== null;
+    }
+
+    /**
+     * @throws Exception
+     */
+    public function cacheResultFile(): string
+    {
+        if (!$this->hasCacheResultFile()) {
+            throw new Exception('Cache result file is not configured');
+        }
+
+        return (string) $this->cacheResultFile;
+    }
+
+    public function columns()
+    {
+        return $this->columns;
+    }
+
+    public function colors(): string
+    {
+        return $this->colors;
+    }
+
+    public function stderr(): bool
+    {
+        return $this->stderr;
+    }
+
+    public function noInteraction(): bool
+    {
+        return $this->noInteraction;
+    }
+
+    public function verbose(): bool
+    {
+        return $this->verbose;
+    }
+
+    public function reverseDefectList(): bool
+    {
+        return $this->reverseDefectList;
+    }
+
+    public function convertDeprecationsToExceptions(): bool
+    {
+        return $this->convertDeprecationsToExceptions;
+    }
+
+    public function convertErrorsToExceptions(): bool
+    {
+        return $this->convertErrorsToExceptions;
+    }
+
+    public function convertNoticesToExceptions(): bool
+    {
+        return $this->convertNoticesToExceptions;
+    }
+
+    public function convertWarningsToExceptions(): bool
+    {
+        return $this->convertWarningsToExceptions;
+    }
+
+    public function forceCoversAnnotation(): bool
+    {
+        return $this->forceCoversAnnotation;
+    }
+
+    /**
+     * @psalm-assert-if-true !null $this->bootstrap
+     */
+    public function hasBootstrap(): bool
+    {
+        return $this->bootstrap !== null;
+    }
+
+    /**
+     * @throws Exception
+     */
+    public function bootstrap(): string
+    {
+        if (!$this->hasBootstrap()) {
+            throw new Exception('Bootstrap script is not configured');
+        }
+
+        return (string) $this->bootstrap;
+    }
+
+    public function processIsolation(): bool
+    {
+        return $this->processIsolation;
+    }
+
+    public function failOnEmptyTestSuite(): bool
+    {
+        return $this->failOnEmptyTestSuite;
+    }
+
+    public function failOnIncomplete(): bool
+    {
+        return $this->failOnIncomplete;
+    }
+
+    public function failOnRisky(): bool
+    {
+        return $this->failOnRisky;
+    }
+
+    public function failOnSkipped(): bool
+    {
+        return $this->failOnSkipped;
+    }
+
+    public function failOnWarning(): bool
+    {
+        return $this->failOnWarning;
+    }
+
+    public function stopOnDefect(): bool
+    {
+        return $this->stopOnDefect;
+    }
+
+    public function stopOnError(): bool
+    {
+        return $this->stopOnError;
+    }
+
+    public function stopOnFailure(): bool
+    {
+        return $this->stopOnFailure;
+    }
+
+    public function stopOnWarning(): bool
+    {
+        return $this->stopOnWarning;
+    }
+
+    public function stopOnIncomplete(): bool
+    {
+        return $this->stopOnIncomplete;
+    }
+
+    public function stopOnRisky(): bool
+    {
+        return $this->stopOnRisky;
+    }
+
+    public function stopOnSkipped(): bool
+    {
+        return $this->stopOnSkipped;
+    }
+
+    /**
+     * @psalm-assert-if-true !null $this->extensionsDirectory
+     */
+    public function hasExtensionsDirectory(): bool
+    {
+        return $this->extensionsDirectory !== null;
+    }
+
+    /**
+     * @throws Exception
+     */
+    public function extensionsDirectory(): string
+    {
+        if (!$this->hasExtensionsDirectory()) {
+            throw new Exception('Extensions directory is not configured');
+        }
+
+        return (string) $this->extensionsDirectory;
+    }
+
+    /**
+     * @psalm-assert-if-true !null $this->testSuiteLoaderClass
+     *
+     * @deprecated see https://github.com/sebastianbergmann/phpunit/issues/4039
+     */
+    public function hasTestSuiteLoaderClass(): bool
+    {
+        return $this->testSuiteLoaderClass !== null;
+    }
+
+    /**
+     * @throws Exception
+     *
+     * @deprecated see https://github.com/sebastianbergmann/phpunit/issues/4039
+     */
+    public function testSuiteLoaderClass(): string
+    {
+        if (!$this->hasTestSuiteLoaderClass()) {
+            throw new Exception('TestSuiteLoader class is not configured');
+        }
+
+        return (string) $this->testSuiteLoaderClass;
+    }
+
+    /**
+     * @psalm-assert-if-true !null $this->testSuiteLoaderFile
+     *
+     * @deprecated see https://github.com/sebastianbergmann/phpunit/issues/4039
+     */
+    public function hasTestSuiteLoaderFile(): bool
+    {
+        return $this->testSuiteLoaderFile !== null;
+    }
+
+    /**
+     * @throws Exception
+     *
+     * @deprecated see https://github.com/sebastianbergmann/phpunit/issues/4039
+     */
+    public function testSuiteLoaderFile(): string
+    {
+        if (!$this->hasTestSuiteLoaderFile()) {
+            throw new Exception('TestSuiteLoader sourcecode file is not configured');
+        }
+
+        return (string) $this->testSuiteLoaderFile;
+    }
+
+    /**
+     * @psalm-assert-if-true !null $this->printerClass
+     */
+    public function hasPrinterClass(): bool
+    {
+        return $this->printerClass !== null;
+    }
+
+    /**
+     * @throws Exception
+     */
+    public function printerClass(): string
+    {
+        if (!$this->hasPrinterClass()) {
+            throw new Exception('ResultPrinter class is not configured');
+        }
+
+        return (string) $this->printerClass;
+    }
+
+    /**
+     * @psalm-assert-if-true !null $this->printerFile
+     */
+    public function hasPrinterFile(): bool
+    {
+        return $this->printerFile !== null;
+    }
+
+    /**
+     * @throws Exception
+     */
+    public function printerFile(): string
+    {
+        if (!$this->hasPrinterFile()) {
+            throw new Exception('ResultPrinter sourcecode file is not configured');
+        }
+
+        return (string) $this->printerFile;
+    }
+
+    public function beStrictAboutChangesToGlobalState(): bool
+    {
+        return $this->beStrictAboutChangesToGlobalState;
+    }
+
+    public function beStrictAboutOutputDuringTests(): bool
+    {
+        return $this->beStrictAboutOutputDuringTests;
+    }
+
+    public function beStrictAboutResourceUsageDuringSmallTests(): bool
+    {
+        return $this->beStrictAboutResourceUsageDuringSmallTests;
+    }
+
+    public function beStrictAboutTestsThatDoNotTestAnything(): bool
+    {
+        return $this->beStrictAboutTestsThatDoNotTestAnything;
+    }
+
+    public function beStrictAboutTodoAnnotatedTests(): bool
+    {
+        return $this->beStrictAboutTodoAnnotatedTests;
+    }
+
+    public function beStrictAboutCoversAnnotation(): bool
+    {
+        return $this->beStrictAboutCoversAnnotation;
+    }
+
+    public function enforceTimeLimit(): bool
+    {
+        return $this->enforceTimeLimit;
+    }
+
+    public function defaultTimeLimit(): int
+    {
+        return $this->defaultTimeLimit;
+    }
+
+    public function timeoutForSmallTests(): int
+    {
+        return $this->timeoutForSmallTests;
+    }
+
+    public function timeoutForMediumTests(): int
+    {
+        return $this->timeoutForMediumTests;
+    }
+
+    public function timeoutForLargeTests(): int
+    {
+        return $this->timeoutForLargeTests;
+    }
+
+    /**
+     * @psalm-assert-if-true !null $this->defaultTestSuite
+     */
+    public function hasDefaultTestSuite(): bool
+    {
+        return $this->defaultTestSuite !== null;
+    }
+
+    /**
+     * @throws Exception
+     */
+    public function defaultTestSuite(): string
+    {
+        if (!$this->hasDefaultTestSuite()) {
+            throw new Exception('Default test suite is not configured');
+        }
+
+        return (string) $this->defaultTestSuite;
+    }
+
+    public function executionOrder(): int
+    {
+        return $this->executionOrder;
+    }
+
+    public function resolveDependencies(): bool
+    {
+        return $this->resolveDependencies;
+    }
+
+    public function defectsFirst(): bool
+    {
+        return $this->defectsFirst;
+    }
+
+    public function backupGlobals(): bool
+    {
+        return $this->backupGlobals;
+    }
+
+    public function backupStaticAttributes(): bool
+    {
+        return $this->backupStaticAttributes;
+    }
+
+    public function registerMockObjectsFromTestArgumentsRecursively(): bool
+    {
+        return $this->registerMockObjectsFromTestArgumentsRecursively;
+    }
+
+    public function conflictBetweenPrinterClassAndTestdox(): bool
+    {
+        return $this->conflictBetweenPrinterClassAndTestdox;
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/TestSuite/TestDirectory.php b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/TestSuite/TestDirectory.php
new file mode 100644
index 0000000000000000000000000000000000000000..263d02ea946fe391d9b19a3ab4e57e6d2cfe1d6b
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/TestSuite/TestDirectory.php
@@ -0,0 +1,78 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\TextUI\XmlConfiguration;
+
+use PHPUnit\Util\VersionComparisonOperator;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ * @psalm-immutable
+ */
+final class TestDirectory
+{
+    /**
+     * @var string
+     */
+    private $path;
+
+    /**
+     * @var string
+     */
+    private $prefix;
+
+    /**
+     * @var string
+     */
+    private $suffix;
+
+    /**
+     * @var string
+     */
+    private $phpVersion;
+
+    /**
+     * @var VersionComparisonOperator
+     */
+    private $phpVersionOperator;
+
+    public function __construct(string $path, string $prefix, string $suffix, string $phpVersion, VersionComparisonOperator $phpVersionOperator)
+    {
+        $this->path               = $path;
+        $this->prefix             = $prefix;
+        $this->suffix             = $suffix;
+        $this->phpVersion         = $phpVersion;
+        $this->phpVersionOperator = $phpVersionOperator;
+    }
+
+    public function path(): string
+    {
+        return $this->path;
+    }
+
+    public function prefix(): string
+    {
+        return $this->prefix;
+    }
+
+    public function suffix(): string
+    {
+        return $this->suffix;
+    }
+
+    public function phpVersion(): string
+    {
+        return $this->phpVersion;
+    }
+
+    public function phpVersionOperator(): VersionComparisonOperator
+    {
+        return $this->phpVersionOperator;
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/TestSuite/TestDirectoryCollection.php b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/TestSuite/TestDirectoryCollection.php
new file mode 100644
index 0000000000000000000000000000000000000000..10111af0598325e8cf57ec877bc1f19a454c6d80
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/TestSuite/TestDirectoryCollection.php
@@ -0,0 +1,62 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\TextUI\XmlConfiguration;
+
+use function count;
+use Countable;
+use IteratorAggregate;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ * @psalm-immutable
+ */
+final class TestDirectoryCollection implements Countable, IteratorAggregate
+{
+    /**
+     * @var TestDirectory[]
+     */
+    private $directories;
+
+    /**
+     * @param TestDirectory[] $directories
+     */
+    public static function fromArray(array $directories): self
+    {
+        return new self(...$directories);
+    }
+
+    private function __construct(TestDirectory ...$directories)
+    {
+        $this->directories = $directories;
+    }
+
+    /**
+     * @return TestDirectory[]
+     */
+    public function asArray(): array
+    {
+        return $this->directories;
+    }
+
+    public function count(): int
+    {
+        return count($this->directories);
+    }
+
+    public function getIterator(): TestDirectoryCollectionIterator
+    {
+        return new TestDirectoryCollectionIterator($this);
+    }
+
+    public function isEmpty(): bool
+    {
+        return $this->count() === 0;
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/TestSuite/TestDirectoryCollectionIterator.php b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/TestSuite/TestDirectoryCollectionIterator.php
new file mode 100644
index 0000000000000000000000000000000000000000..11a48a2476db1a34cedb1354942f52906af58fc6
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/TestSuite/TestDirectoryCollectionIterator.php
@@ -0,0 +1,66 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\TextUI\XmlConfiguration;
+
+use function count;
+use function iterator_count;
+use Countable;
+use Iterator;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class TestDirectoryCollectionIterator implements Countable, Iterator
+{
+    /**
+     * @var TestDirectory[]
+     */
+    private $directories;
+
+    /**
+     * @var int
+     */
+    private $position;
+
+    public function __construct(TestDirectoryCollection $directories)
+    {
+        $this->directories = $directories->asArray();
+    }
+
+    public function count(): int
+    {
+        return iterator_count($this);
+    }
+
+    public function rewind(): void
+    {
+        $this->position = 0;
+    }
+
+    public function valid(): bool
+    {
+        return $this->position < count($this->directories);
+    }
+
+    public function key(): int
+    {
+        return $this->position;
+    }
+
+    public function current(): TestDirectory
+    {
+        return $this->directories[$this->position];
+    }
+
+    public function next(): void
+    {
+        $this->position++;
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/TestSuite/TestFile.php b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/TestSuite/TestFile.php
new file mode 100644
index 0000000000000000000000000000000000000000..2e69450c1ba9afa7403d961b3e4fefe9c05a33e4
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/TestSuite/TestFile.php
@@ -0,0 +1,56 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\TextUI\XmlConfiguration;
+
+use PHPUnit\Util\VersionComparisonOperator;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ * @psalm-immutable
+ */
+final class TestFile
+{
+    /**
+     * @var string
+     */
+    private $path;
+
+    /**
+     * @var string
+     */
+    private $phpVersion;
+
+    /**
+     * @var VersionComparisonOperator
+     */
+    private $phpVersionOperator;
+
+    public function __construct(string $path, string $phpVersion, VersionComparisonOperator $phpVersionOperator)
+    {
+        $this->path               = $path;
+        $this->phpVersion         = $phpVersion;
+        $this->phpVersionOperator = $phpVersionOperator;
+    }
+
+    public function path(): string
+    {
+        return $this->path;
+    }
+
+    public function phpVersion(): string
+    {
+        return $this->phpVersion;
+    }
+
+    public function phpVersionOperator(): VersionComparisonOperator
+    {
+        return $this->phpVersionOperator;
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/TestSuite/TestFileCollection.php b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/TestSuite/TestFileCollection.php
new file mode 100644
index 0000000000000000000000000000000000000000..791ddf7180a4bad8563c9057399316f2691bb1c2
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/TestSuite/TestFileCollection.php
@@ -0,0 +1,62 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\TextUI\XmlConfiguration;
+
+use function count;
+use Countable;
+use IteratorAggregate;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ * @psalm-immutable
+ */
+final class TestFileCollection implements Countable, IteratorAggregate
+{
+    /**
+     * @var TestFile[]
+     */
+    private $files;
+
+    /**
+     * @param TestFile[] $files
+     */
+    public static function fromArray(array $files): self
+    {
+        return new self(...$files);
+    }
+
+    private function __construct(TestFile ...$files)
+    {
+        $this->files = $files;
+    }
+
+    /**
+     * @return TestFile[]
+     */
+    public function asArray(): array
+    {
+        return $this->files;
+    }
+
+    public function count(): int
+    {
+        return count($this->files);
+    }
+
+    public function getIterator(): TestFileCollectionIterator
+    {
+        return new TestFileCollectionIterator($this);
+    }
+
+    public function isEmpty(): bool
+    {
+        return $this->count() === 0;
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/TestSuite/TestFileCollectionIterator.php b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/TestSuite/TestFileCollectionIterator.php
new file mode 100644
index 0000000000000000000000000000000000000000..b44c368948f3d4a5d7168369d94b186e4c4ed171
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/TestSuite/TestFileCollectionIterator.php
@@ -0,0 +1,66 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\TextUI\XmlConfiguration;
+
+use function count;
+use function iterator_count;
+use Countable;
+use Iterator;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class TestFileCollectionIterator implements Countable, Iterator
+{
+    /**
+     * @var TestFile[]
+     */
+    private $files;
+
+    /**
+     * @var int
+     */
+    private $position;
+
+    public function __construct(TestFileCollection $files)
+    {
+        $this->files = $files->asArray();
+    }
+
+    public function count(): int
+    {
+        return iterator_count($this);
+    }
+
+    public function rewind(): void
+    {
+        $this->position = 0;
+    }
+
+    public function valid(): bool
+    {
+        return $this->position < count($this->files);
+    }
+
+    public function key(): int
+    {
+        return $this->position;
+    }
+
+    public function current(): TestFile
+    {
+        return $this->files[$this->position];
+    }
+
+    public function next(): void
+    {
+        $this->position++;
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/TestSuite/TestSuite.php b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/TestSuite/TestSuite.php
new file mode 100644
index 0000000000000000000000000000000000000000..4a60982157a9fb8073a2d0d0ce3399c561e72da4
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/TestSuite/TestSuite.php
@@ -0,0 +1,65 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\TextUI\XmlConfiguration;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ * @psalm-immutable
+ */
+final class TestSuite
+{
+    /**
+     * @var string
+     */
+    private $name;
+
+    /**
+     * @var TestDirectoryCollection
+     */
+    private $directories;
+
+    /**
+     * @var TestFileCollection
+     */
+    private $files;
+
+    /**
+     * @var FileCollection
+     */
+    private $exclude;
+
+    public function __construct(string $name, TestDirectoryCollection $directories, TestFileCollection $files, FileCollection $exclude)
+    {
+        $this->name        = $name;
+        $this->directories = $directories;
+        $this->files       = $files;
+        $this->exclude     = $exclude;
+    }
+
+    public function name(): string
+    {
+        return $this->name;
+    }
+
+    public function directories(): TestDirectoryCollection
+    {
+        return $this->directories;
+    }
+
+    public function files(): TestFileCollection
+    {
+        return $this->files;
+    }
+
+    public function exclude(): FileCollection
+    {
+        return $this->exclude;
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/TestSuite/TestSuiteCollection.php b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/TestSuite/TestSuiteCollection.php
new file mode 100644
index 0000000000000000000000000000000000000000..124609d74e3f2b058787bd093d0cf558c5cf6eb1
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/TestSuite/TestSuiteCollection.php
@@ -0,0 +1,62 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\TextUI\XmlConfiguration;
+
+use function count;
+use Countable;
+use IteratorAggregate;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ * @psalm-immutable
+ */
+final class TestSuiteCollection implements Countable, IteratorAggregate
+{
+    /**
+     * @var TestSuite[]
+     */
+    private $testSuites;
+
+    /**
+     * @param TestSuite[] $testSuites
+     */
+    public static function fromArray(array $testSuites): self
+    {
+        return new self(...$testSuites);
+    }
+
+    private function __construct(TestSuite ...$testSuites)
+    {
+        $this->testSuites = $testSuites;
+    }
+
+    /**
+     * @return TestSuite[]
+     */
+    public function asArray(): array
+    {
+        return $this->testSuites;
+    }
+
+    public function count(): int
+    {
+        return count($this->testSuites);
+    }
+
+    public function getIterator(): TestSuiteCollectionIterator
+    {
+        return new TestSuiteCollectionIterator($this);
+    }
+
+    public function isEmpty(): bool
+    {
+        return $this->count() === 0;
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/TestSuite/TestSuiteCollectionIterator.php b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/TestSuite/TestSuiteCollectionIterator.php
new file mode 100644
index 0000000000000000000000000000000000000000..33b0f8495737415d3c80ba1a616fb084178dab02
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/TestSuite/TestSuiteCollectionIterator.php
@@ -0,0 +1,66 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\TextUI\XmlConfiguration;
+
+use function count;
+use function iterator_count;
+use Countable;
+use Iterator;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class TestSuiteCollectionIterator implements Countable, Iterator
+{
+    /**
+     * @var TestSuite[]
+     */
+    private $testSuites;
+
+    /**
+     * @var int
+     */
+    private $position;
+
+    public function __construct(TestSuiteCollection $testSuites)
+    {
+        $this->testSuites = $testSuites->asArray();
+    }
+
+    public function count(): int
+    {
+        return iterator_count($this);
+    }
+
+    public function rewind(): void
+    {
+        $this->position = 0;
+    }
+
+    public function valid(): bool
+    {
+        return $this->position < count($this->testSuites);
+    }
+
+    public function key(): int
+    {
+        return $this->position;
+    }
+
+    public function current(): TestSuite
+    {
+        return $this->testSuites[$this->position];
+    }
+
+    public function next(): void
+    {
+        $this->position++;
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Util/Annotation/DocBlock.php b/vendor/phpunit/phpunit/src/Util/Annotation/DocBlock.php
new file mode 100644
index 0000000000000000000000000000000000000000..83d741e6bd45278d47d2369dc70b817be6bb0654
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Util/Annotation/DocBlock.php
@@ -0,0 +1,550 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Util\Annotation;
+
+use const JSON_ERROR_NONE;
+use const PREG_OFFSET_CAPTURE;
+use function array_filter;
+use function array_key_exists;
+use function array_map;
+use function array_merge;
+use function array_pop;
+use function array_slice;
+use function array_values;
+use function count;
+use function explode;
+use function file;
+use function implode;
+use function is_array;
+use function is_int;
+use function json_decode;
+use function json_last_error;
+use function json_last_error_msg;
+use function preg_match;
+use function preg_match_all;
+use function preg_replace;
+use function preg_split;
+use function realpath;
+use function rtrim;
+use function sprintf;
+use function str_replace;
+use function strlen;
+use function strpos;
+use function strtolower;
+use function substr;
+use function trim;
+use PharIo\Version\VersionConstraintParser;
+use PHPUnit\Framework\InvalidDataProviderException;
+use PHPUnit\Framework\SkippedTestError;
+use PHPUnit\Framework\Warning;
+use PHPUnit\Util\Exception;
+use PHPUnit\Util\InvalidDataSetException;
+use ReflectionClass;
+use ReflectionException;
+use ReflectionFunctionAbstract;
+use ReflectionMethod;
+use Reflector;
+use Traversable;
+
+/**
+ * This is an abstraction around a PHPUnit-specific docBlock,
+ * allowing us to ask meaningful questions about a specific
+ * reflection symbol.
+ *
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class DocBlock
+{
+    /**
+     * @todo This constant should be private (it's public because of TestTest::testGetProvidedDataRegEx)
+     */
+    public const REGEX_DATA_PROVIDER = '/@dataProvider\s+([a-zA-Z0-9._:-\\\\x7f-\xff]+)/';
+
+    private const REGEX_REQUIRES_VERSION = '/@requires\s+(?P<name>PHP(?:Unit)?)\s+(?P<operator>[<>=!]{0,2})\s*(?P<version>[\d\.-]+(dev|(RC|alpha|beta)[\d\.])?)[ \t]*\r?$/m';
+
+    private const REGEX_REQUIRES_VERSION_CONSTRAINT = '/@requires\s+(?P<name>PHP(?:Unit)?)\s+(?P<constraint>[\d\t \-.|~^]+)[ \t]*\r?$/m';
+
+    private const REGEX_REQUIRES_OS = '/@requires\s+(?P<name>OS(?:FAMILY)?)\s+(?P<value>.+?)[ \t]*\r?$/m';
+
+    private const REGEX_REQUIRES_SETTING = '/@requires\s+(?P<name>setting)\s+(?P<setting>([^ ]+?))\s*(?P<value>[\w\.-]+[\w\.]?)?[ \t]*\r?$/m';
+
+    private const REGEX_REQUIRES = '/@requires\s+(?P<name>function|extension)\s+(?P<value>([^\s<>=!]+))\s*(?P<operator>[<>=!]{0,2})\s*(?P<version>[\d\.-]+[\d\.]?)?[ \t]*\r?$/m';
+
+    private const REGEX_TEST_WITH = '/@testWith\s+/';
+
+    /** @var string */
+    private $docComment;
+
+    /** @var bool */
+    private $isMethod;
+
+    /** @var array<string, array<int, string>> pre-parsed annotations indexed by name and occurrence index */
+    private $symbolAnnotations;
+
+    /**
+     * @var null|array<string, mixed>
+     *
+     * @psalm-var null|(array{
+     *   __OFFSET: array<string, int>&array{__FILE: string},
+     *   setting?: array<string, string>,
+     *   extension_versions?: array<string, array{version: string, operator: string}>
+     * }&array<
+     *   string,
+     *   string|array{version: string, operator: string}|array{constraint: string}|array<int|string, string>
+     * >)
+     */
+    private $parsedRequirements;
+
+    /** @var int */
+    private $startLine;
+
+    /** @var int */
+    private $endLine;
+
+    /** @var string */
+    private $fileName;
+
+    /** @var string */
+    private $name;
+
+    /**
+     * @var string
+     *
+     * @psalm-var class-string
+     */
+    private $className;
+
+    public static function ofClass(ReflectionClass $class): self
+    {
+        $className = $class->getName();
+
+        return new self(
+            (string) $class->getDocComment(),
+            false,
+            self::extractAnnotationsFromReflector($class),
+            $class->getStartLine(),
+            $class->getEndLine(),
+            $class->getFileName(),
+            $className,
+            $className
+        );
+    }
+
+    /**
+     * @psalm-param class-string $classNameInHierarchy
+     */
+    public static function ofMethod(ReflectionMethod $method, string $classNameInHierarchy): self
+    {
+        return new self(
+            (string) $method->getDocComment(),
+            true,
+            self::extractAnnotationsFromReflector($method),
+            $method->getStartLine(),
+            $method->getEndLine(),
+            $method->getFileName(),
+            $method->getName(),
+            $classNameInHierarchy
+        );
+    }
+
+    /**
+     * Note: we do not preserve an instance of the reflection object, since it cannot be safely (de-)serialized.
+     *
+     * @param array<string, array<int, string>> $symbolAnnotations
+     *
+     * @psalm-param class-string $className
+     */
+    private function __construct(string $docComment, bool $isMethod, array $symbolAnnotations, int $startLine, int $endLine, string $fileName, string $name, string $className)
+    {
+        $this->docComment        = $docComment;
+        $this->isMethod          = $isMethod;
+        $this->symbolAnnotations = $symbolAnnotations;
+        $this->startLine         = $startLine;
+        $this->endLine           = $endLine;
+        $this->fileName          = $fileName;
+        $this->name              = $name;
+        $this->className         = $className;
+    }
+
+    /**
+     * @psalm-return array{
+     *   __OFFSET: array<string, int>&array{__FILE: string},
+     *   setting?: array<string, string>,
+     *   extension_versions?: array<string, array{version: string, operator: string}>
+     * }&array<
+     *   string,
+     *   string|array{version: string, operator: string}|array{constraint: string}|array<int|string, string>
+     * >
+     *
+     * @throws Warning if the requirements version constraint is not well-formed
+     */
+    public function requirements(): array
+    {
+        if ($this->parsedRequirements !== null) {
+            return $this->parsedRequirements;
+        }
+
+        $offset            = $this->startLine;
+        $requires          = [];
+        $recordedSettings  = [];
+        $extensionVersions = [];
+        $recordedOffsets   = [
+            '__FILE' => realpath($this->fileName),
+        ];
+
+        // Split docblock into lines and rewind offset to start of docblock
+        $lines = preg_split('/\r\n|\r|\n/', $this->docComment);
+        $offset -= count($lines);
+
+        foreach ($lines as $line) {
+            if (preg_match(self::REGEX_REQUIRES_OS, $line, $matches)) {
+                $requires[$matches['name']]        = $matches['value'];
+                $recordedOffsets[$matches['name']] = $offset;
+            }
+
+            if (preg_match(self::REGEX_REQUIRES_VERSION, $line, $matches)) {
+                $requires[$matches['name']] = [
+                    'version'  => $matches['version'],
+                    'operator' => $matches['operator'],
+                ];
+                $recordedOffsets[$matches['name']] = $offset;
+            }
+
+            if (preg_match(self::REGEX_REQUIRES_VERSION_CONSTRAINT, $line, $matches)) {
+                if (!empty($requires[$matches['name']])) {
+                    $offset++;
+
+                    continue;
+                }
+
+                try {
+                    $versionConstraintParser = new VersionConstraintParser;
+
+                    $requires[$matches['name'] . '_constraint'] = [
+                        'constraint' => $versionConstraintParser->parse(trim($matches['constraint'])),
+                    ];
+                    $recordedOffsets[$matches['name'] . '_constraint'] = $offset;
+                } catch (\PharIo\Version\Exception $e) {
+                    throw new Warning($e->getMessage(), $e->getCode(), $e);
+                }
+            }
+
+            if (preg_match(self::REGEX_REQUIRES_SETTING, $line, $matches)) {
+                $recordedSettings[$matches['setting']]               = $matches['value'];
+                $recordedOffsets['__SETTING_' . $matches['setting']] = $offset;
+            }
+
+            if (preg_match(self::REGEX_REQUIRES, $line, $matches)) {
+                $name = $matches['name'] . 's';
+
+                if (!isset($requires[$name])) {
+                    $requires[$name] = [];
+                }
+
+                $requires[$name][]                                           = $matches['value'];
+                $recordedOffsets[$matches['name'] . '_' . $matches['value']] = $offset;
+
+                if ($name === 'extensions' && !empty($matches['version'])) {
+                    $extensionVersions[$matches['value']] = [
+                        'version'  => $matches['version'],
+                        'operator' => $matches['operator'],
+                    ];
+                }
+            }
+
+            $offset++;
+        }
+
+        return $this->parsedRequirements = array_merge(
+            $requires,
+            ['__OFFSET' => $recordedOffsets],
+            array_filter([
+                'setting'            => $recordedSettings,
+                'extension_versions' => $extensionVersions,
+            ])
+        );
+    }
+
+    /**
+     * Returns the provided data for a method.
+     *
+     * @throws Exception
+     */
+    public function getProvidedData(): ?array
+    {
+        /** @noinspection SuspiciousBinaryOperationInspection */
+        $data = $this->getDataFromDataProviderAnnotation($this->docComment) ?? $this->getDataFromTestWithAnnotation($this->docComment);
+
+        if ($data === null) {
+            return null;
+        }
+
+        if ($data === []) {
+            throw new SkippedTestError;
+        }
+
+        foreach ($data as $key => $value) {
+            if (!is_array($value)) {
+                throw new InvalidDataSetException(
+                    sprintf(
+                        'Data set %s is invalid.',
+                        is_int($key) ? '#' . $key : '"' . $key . '"'
+                    )
+                );
+            }
+        }
+
+        return $data;
+    }
+
+    /**
+     * @psalm-return array<string, array{line: int, value: string}>
+     */
+    public function getInlineAnnotations(): array
+    {
+        $code        = file($this->fileName);
+        $lineNumber  = $this->startLine;
+        $startLine   = $this->startLine - 1;
+        $endLine     = $this->endLine - 1;
+        $codeLines   = array_slice($code, $startLine, $endLine - $startLine + 1);
+        $annotations = [];
+
+        foreach ($codeLines as $line) {
+            if (preg_match('#/\*\*?\s*@(?P<name>[A-Za-z_-]+)(?:[ \t]+(?P<value>.*?))?[ \t]*\r?\*/$#m', $line, $matches)) {
+                $annotations[strtolower($matches['name'])] = [
+                    'line'  => $lineNumber,
+                    'value' => $matches['value'],
+                ];
+            }
+
+            $lineNumber++;
+        }
+
+        return $annotations;
+    }
+
+    public function symbolAnnotations(): array
+    {
+        return $this->symbolAnnotations;
+    }
+
+    public function isHookToBeExecutedBeforeClass(): bool
+    {
+        return $this->isMethod &&
+            false !== strpos($this->docComment, '@beforeClass');
+    }
+
+    public function isHookToBeExecutedAfterClass(): bool
+    {
+        return $this->isMethod &&
+            false !== strpos($this->docComment, '@afterClass');
+    }
+
+    public function isToBeExecutedBeforeTest(): bool
+    {
+        return 1 === preg_match('/@before\b/', $this->docComment);
+    }
+
+    public function isToBeExecutedAfterTest(): bool
+    {
+        return 1 === preg_match('/@after\b/', $this->docComment);
+    }
+
+    public function isToBeExecutedAsPreCondition(): bool
+    {
+        return 1 === preg_match('/@preCondition\b/', $this->docComment);
+    }
+
+    public function isToBeExecutedAsPostCondition(): bool
+    {
+        return 1 === preg_match('/@postCondition\b/', $this->docComment);
+    }
+
+    private function getDataFromDataProviderAnnotation(string $docComment): ?array
+    {
+        $methodName = null;
+        $className  = $this->className;
+
+        if ($this->isMethod) {
+            $methodName = $this->name;
+        }
+
+        if (!preg_match_all(self::REGEX_DATA_PROVIDER, $docComment, $matches)) {
+            return null;
+        }
+
+        $result = [];
+
+        foreach ($matches[1] as $match) {
+            $dataProviderMethodNameNamespace = explode('\\', $match);
+            $leaf                            = explode('::', array_pop($dataProviderMethodNameNamespace));
+            $dataProviderMethodName          = array_pop($leaf);
+
+            if (empty($dataProviderMethodNameNamespace)) {
+                $dataProviderMethodNameNamespace = '';
+            } else {
+                $dataProviderMethodNameNamespace = implode('\\', $dataProviderMethodNameNamespace) . '\\';
+            }
+
+            if (empty($leaf)) {
+                $dataProviderClassName = $className;
+            } else {
+                /** @psalm-var class-string $dataProviderClassName */
+                $dataProviderClassName = $dataProviderMethodNameNamespace . array_pop($leaf);
+            }
+
+            try {
+                $dataProviderClass = new ReflectionClass($dataProviderClassName);
+
+                $dataProviderMethod = $dataProviderClass->getMethod(
+                    $dataProviderMethodName
+                );
+                // @codeCoverageIgnoreStart
+            } catch (ReflectionException $e) {
+                throw new Exception(
+                    $e->getMessage(),
+                    (int) $e->getCode(),
+                    $e
+                );
+                // @codeCoverageIgnoreEnd
+            }
+
+            if ($dataProviderMethod->isStatic()) {
+                $object = null;
+            } else {
+                $object = $dataProviderClass->newInstance();
+            }
+
+            if ($dataProviderMethod->getNumberOfParameters() === 0) {
+                $data = $dataProviderMethod->invoke($object);
+            } else {
+                $data = $dataProviderMethod->invoke($object, $methodName);
+            }
+
+            if ($data instanceof Traversable) {
+                $origData = $data;
+                $data     = [];
+
+                foreach ($origData as $key => $value) {
+                    if (is_int($key)) {
+                        $data[] = $value;
+                    } elseif (array_key_exists($key, $data)) {
+                        throw new InvalidDataProviderException(
+                            sprintf(
+                                'The key "%s" has already been defined in the data provider "%s".',
+                                $key,
+                                $match
+                            )
+                        );
+                    } else {
+                        $data[$key] = $value;
+                    }
+                }
+            }
+
+            if (is_array($data)) {
+                $result = array_merge($result, $data);
+            }
+        }
+
+        return $result;
+    }
+
+    /**
+     * @throws Exception
+     */
+    private function getDataFromTestWithAnnotation(string $docComment): ?array
+    {
+        $docComment = $this->cleanUpMultiLineAnnotation($docComment);
+
+        if (!preg_match(self::REGEX_TEST_WITH, $docComment, $matches, PREG_OFFSET_CAPTURE)) {
+            return null;
+        }
+
+        $offset            = strlen($matches[0][0]) + $matches[0][1];
+        $annotationContent = substr($docComment, $offset);
+        $data              = [];
+
+        foreach (explode("\n", $annotationContent) as $candidateRow) {
+            $candidateRow = trim($candidateRow);
+
+            if ($candidateRow[0] !== '[') {
+                break;
+            }
+
+            $dataSet = json_decode($candidateRow, true);
+
+            if (json_last_error() !== JSON_ERROR_NONE) {
+                throw new Exception(
+                    'The data set for the @testWith annotation cannot be parsed: ' . json_last_error_msg()
+                );
+            }
+
+            $data[] = $dataSet;
+        }
+
+        if (!$data) {
+            throw new Exception('The data set for the @testWith annotation cannot be parsed.');
+        }
+
+        return $data;
+    }
+
+    private function cleanUpMultiLineAnnotation(string $docComment): string
+    {
+        //removing initial '   * ' for docComment
+        $docComment = str_replace("\r\n", "\n", $docComment);
+        $docComment = preg_replace('/' . '\n' . '\s*' . '\*' . '\s?' . '/', "\n", $docComment);
+        $docComment = (string) substr($docComment, 0, -1);
+
+        return rtrim($docComment, "\n");
+    }
+
+    /** @return array<string, array<int, string>> */
+    private static function parseDocBlock(string $docBlock): array
+    {
+        // Strip away the docblock header and footer to ease parsing of one line annotations
+        $docBlock    = (string) substr($docBlock, 3, -2);
+        $annotations = [];
+
+        if (preg_match_all('/@(?P<name>[A-Za-z_-]+)(?:[ \t]+(?P<value>.*?))?[ \t]*\r?$/m', $docBlock, $matches)) {
+            $numMatches = count($matches[0]);
+
+            for ($i = 0; $i < $numMatches; $i++) {
+                $annotations[$matches['name'][$i]][] = (string) $matches['value'][$i];
+            }
+        }
+
+        return $annotations;
+    }
+
+    /** @param ReflectionClass|ReflectionFunctionAbstract $reflector */
+    private static function extractAnnotationsFromReflector(Reflector $reflector): array
+    {
+        $annotations = [];
+
+        if ($reflector instanceof ReflectionClass) {
+            $annotations = array_merge(
+                $annotations,
+                ...array_map(
+                    static function (ReflectionClass $trait): array {
+                        return self::parseDocBlock((string) $trait->getDocComment());
+                    },
+                    array_values($reflector->getTraits())
+                )
+            );
+        }
+
+        return array_merge(
+            $annotations,
+            self::parseDocBlock((string) $reflector->getDocComment())
+        );
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Util/Annotation/Registry.php b/vendor/phpunit/phpunit/src/Util/Annotation/Registry.php
new file mode 100644
index 0000000000000000000000000000000000000000..8df14cfc0ce85104f7b0c6026f0f4db32615266e
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Util/Annotation/Registry.php
@@ -0,0 +1,93 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Util\Annotation;
+
+use function array_key_exists;
+use PHPUnit\Util\Exception;
+use ReflectionClass;
+use ReflectionException;
+use ReflectionMethod;
+
+/**
+ * Reflection information, and therefore DocBlock information, is static within
+ * a single PHP process. It is therefore okay to use a Singleton registry here.
+ *
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class Registry
+{
+    /** @var null|self */
+    private static $instance;
+
+    /** @var array<string, DocBlock> indexed by class name */
+    private $classDocBlocks = [];
+
+    /** @var array<string, array<string, DocBlock>> indexed by class name and method name */
+    private $methodDocBlocks = [];
+
+    public static function getInstance(): self
+    {
+        return self::$instance ?? self::$instance = new self;
+    }
+
+    private function __construct()
+    {
+    }
+
+    /**
+     * @throws Exception
+     * @psalm-param class-string $class
+     */
+    public function forClassName(string $class): DocBlock
+    {
+        if (array_key_exists($class, $this->classDocBlocks)) {
+            return $this->classDocBlocks[$class];
+        }
+
+        try {
+            $reflection = new ReflectionClass($class);
+            // @codeCoverageIgnoreStart
+        } catch (ReflectionException $e) {
+            throw new Exception(
+                $e->getMessage(),
+                (int) $e->getCode(),
+                $e
+            );
+        }
+        // @codeCoverageIgnoreEnd
+
+        return $this->classDocBlocks[$class] = DocBlock::ofClass($reflection);
+    }
+
+    /**
+     * @throws Exception
+     * @psalm-param class-string $classInHierarchy
+     */
+    public function forMethod(string $classInHierarchy, string $method): DocBlock
+    {
+        if (isset($this->methodDocBlocks[$classInHierarchy][$method])) {
+            return $this->methodDocBlocks[$classInHierarchy][$method];
+        }
+
+        try {
+            $reflection = new ReflectionMethod($classInHierarchy, $method);
+            // @codeCoverageIgnoreStart
+        } catch (ReflectionException $e) {
+            throw new Exception(
+                $e->getMessage(),
+                (int) $e->getCode(),
+                $e
+            );
+        }
+        // @codeCoverageIgnoreEnd
+
+        return $this->methodDocBlocks[$classInHierarchy][$method] = DocBlock::ofMethod($reflection, $classInHierarchy);
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Util/Blacklist.php b/vendor/phpunit/phpunit/src/Util/Blacklist.php
new file mode 100644
index 0000000000000000000000000000000000000000..3b416e142a82b32cf05746ca57685ad652f2b624
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Util/Blacklist.php
@@ -0,0 +1,41 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Util;
+
+/**
+ * @deprecated Use ExcludeList instead
+ *
+ * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+ */
+final class Blacklist
+{
+    public static function addDirectory(string $directory): void
+    {
+        ExcludeList::addDirectory($directory);
+    }
+
+    /**
+     * @throws Exception
+     *
+     * @return string[]
+     */
+    public function getBlacklistedDirectories(): array
+    {
+        return (new ExcludeList)->getExcludedDirectories();
+    }
+
+    /**
+     * @throws Exception
+     */
+    public function isBlacklisted(string $file): bool
+    {
+        return (new ExcludeList)->isExcluded($file);
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Util/Color.php b/vendor/phpunit/phpunit/src/Util/Color.php
new file mode 100644
index 0000000000000000000000000000000000000000..a756953b66eb9632bbc67961b0d482d4920fecef
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Util/Color.php
@@ -0,0 +1,157 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Util;
+
+use const DIRECTORY_SEPARATOR;
+use function array_keys;
+use function array_map;
+use function array_values;
+use function count;
+use function explode;
+use function implode;
+use function min;
+use function preg_replace;
+use function preg_replace_callback;
+use function sprintf;
+use function strtr;
+use function trim;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class Color
+{
+    /**
+     * @var array<string,string>
+     */
+    private const WHITESPACE_MAP = [
+        ' '  => '·',
+        "\t" => '⇥',
+    ];
+
+    /**
+     * @var array<string,string>
+     */
+    private const WHITESPACE_EOL_MAP = [
+        ' '  => '·',
+        "\t" => '⇥',
+        "\n" => '↵',
+        "\r" => '⟵',
+    ];
+
+    /**
+     * @var array<string,string>
+     */
+    private static $ansiCodes = [
+        'reset'      => '0',
+        'bold'       => '1',
+        'dim'        => '2',
+        'dim-reset'  => '22',
+        'underlined' => '4',
+        'fg-default' => '39',
+        'fg-black'   => '30',
+        'fg-red'     => '31',
+        'fg-green'   => '32',
+        'fg-yellow'  => '33',
+        'fg-blue'    => '34',
+        'fg-magenta' => '35',
+        'fg-cyan'    => '36',
+        'fg-white'   => '37',
+        'bg-default' => '49',
+        'bg-black'   => '40',
+        'bg-red'     => '41',
+        'bg-green'   => '42',
+        'bg-yellow'  => '43',
+        'bg-blue'    => '44',
+        'bg-magenta' => '45',
+        'bg-cyan'    => '46',
+        'bg-white'   => '47',
+    ];
+
+    public static function colorize(string $color, string $buffer): string
+    {
+        if (trim($buffer) === '') {
+            return $buffer;
+        }
+
+        $codes  = array_map('\trim', explode(',', $color));
+        $styles = [];
+
+        foreach ($codes as $code) {
+            if (isset(self::$ansiCodes[$code])) {
+                $styles[] = self::$ansiCodes[$code] ?? '';
+            }
+        }
+
+        if (empty($styles)) {
+            return $buffer;
+        }
+
+        return self::optimizeColor(sprintf("\x1b[%sm", implode(';', $styles)) . $buffer . "\x1b[0m");
+    }
+
+    public static function colorizePath(string $path, ?string $prevPath = null, bool $colorizeFilename = false): string
+    {
+        if ($prevPath === null) {
+            $prevPath = '';
+        }
+
+        $path     = explode(DIRECTORY_SEPARATOR, $path);
+        $prevPath = explode(DIRECTORY_SEPARATOR, $prevPath);
+
+        for ($i = 0; $i < min(count($path), count($prevPath)); $i++) {
+            if ($path[$i] == $prevPath[$i]) {
+                $path[$i] = self::dim($path[$i]);
+            }
+        }
+
+        if ($colorizeFilename) {
+            $last        = count($path) - 1;
+            $path[$last] = preg_replace_callback(
+                '/([\-_\.]+|phpt$)/',
+                static function ($matches) {
+                    return self::dim($matches[0]);
+                },
+                $path[$last]
+            );
+        }
+
+        return self::optimizeColor(implode(self::dim(DIRECTORY_SEPARATOR), $path));
+    }
+
+    public static function dim(string $buffer): string
+    {
+        if (trim($buffer) === '') {
+            return $buffer;
+        }
+
+        return "\e[2m{$buffer}\e[22m";
+    }
+
+    public static function visualizeWhitespace(string $buffer, bool $visualizeEOL = false): string
+    {
+        $replaceMap = $visualizeEOL ? self::WHITESPACE_EOL_MAP : self::WHITESPACE_MAP;
+
+        return preg_replace_callback('/\s+/', static function ($matches) use ($replaceMap) {
+            return self::dim(strtr($matches[0], $replaceMap));
+        }, $buffer);
+    }
+
+    private static function optimizeColor(string $buffer): string
+    {
+        $patterns = [
+            "/\e\\[22m\e\\[2m/"                   => '',
+            "/\e\\[([^m]*)m\e\\[([1-9][0-9;]*)m/" => "\e[$1;$2m",
+            "/(\e\\[[^m]*m)+(\e\\[0m)/"           => '$2',
+        ];
+
+        return preg_replace(array_keys($patterns), array_values($patterns), $buffer);
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Util/ErrorHandler.php b/vendor/phpunit/phpunit/src/Util/ErrorHandler.php
new file mode 100644
index 0000000000000000000000000000000000000000..61dbbbc1377fab2cf8866c41452cbb66368074ee
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Util/ErrorHandler.php
@@ -0,0 +1,155 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Util;
+
+use const E_DEPRECATED;
+use const E_NOTICE;
+use const E_STRICT;
+use const E_USER_DEPRECATED;
+use const E_USER_NOTICE;
+use const E_USER_WARNING;
+use const E_WARNING;
+use function error_reporting;
+use function restore_error_handler;
+use function set_error_handler;
+use PHPUnit\Framework\Error\Deprecated;
+use PHPUnit\Framework\Error\Error;
+use PHPUnit\Framework\Error\Notice;
+use PHPUnit\Framework\Error\Warning;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class ErrorHandler
+{
+    /**
+     * @var bool
+     */
+    private $convertDeprecationsToExceptions;
+
+    /**
+     * @var bool
+     */
+    private $convertErrorsToExceptions;
+
+    /**
+     * @var bool
+     */
+    private $convertNoticesToExceptions;
+
+    /**
+     * @var bool
+     */
+    private $convertWarningsToExceptions;
+
+    /**
+     * @var bool
+     */
+    private $registered = false;
+
+    public static function invokeIgnoringWarnings(callable $callable)
+    {
+        set_error_handler(
+            static function ($errorNumber, $errorString) {
+                if ($errorNumber === E_WARNING) {
+                    return;
+                }
+
+                return false;
+            }
+        );
+
+        $result = $callable();
+
+        restore_error_handler();
+
+        return $result;
+    }
+
+    public function __construct(bool $convertDeprecationsToExceptions, bool $convertErrorsToExceptions, bool $convertNoticesToExceptions, bool $convertWarningsToExceptions)
+    {
+        $this->convertDeprecationsToExceptions = $convertDeprecationsToExceptions;
+        $this->convertErrorsToExceptions       = $convertErrorsToExceptions;
+        $this->convertNoticesToExceptions      = $convertNoticesToExceptions;
+        $this->convertWarningsToExceptions     = $convertWarningsToExceptions;
+    }
+
+    public function __invoke(int $errorNumber, string $errorString, string $errorFile, int $errorLine): bool
+    {
+        /*
+         * Do not raise an exception when the error suppression operator (@) was used.
+         *
+         * @see https://github.com/sebastianbergmann/phpunit/issues/3739
+         */
+        if (!($errorNumber & error_reporting())) {
+            return false;
+        }
+
+        switch ($errorNumber) {
+            case E_NOTICE:
+            case E_USER_NOTICE:
+            case E_STRICT:
+                if (!$this->convertNoticesToExceptions) {
+                    return false;
+                }
+
+                throw new Notice($errorString, $errorNumber, $errorFile, $errorLine);
+
+            case E_WARNING:
+            case E_USER_WARNING:
+                if (!$this->convertWarningsToExceptions) {
+                    return false;
+                }
+
+                throw new Warning($errorString, $errorNumber, $errorFile, $errorLine);
+
+            case E_DEPRECATED:
+            case E_USER_DEPRECATED:
+                if (!$this->convertDeprecationsToExceptions) {
+                    return false;
+                }
+
+                throw new Deprecated($errorString, $errorNumber, $errorFile, $errorLine);
+
+            default:
+                if (!$this->convertErrorsToExceptions) {
+                    return false;
+                }
+
+                throw new Error($errorString, $errorNumber, $errorFile, $errorLine);
+        }
+    }
+
+    public function register(): void
+    {
+        if ($this->registered) {
+            return;
+        }
+
+        $oldErrorHandler = set_error_handler($this);
+
+        if ($oldErrorHandler !== null) {
+            restore_error_handler();
+
+            return;
+        }
+
+        $this->registered = true;
+    }
+
+    public function unregister(): void
+    {
+        if (!$this->registered) {
+            return;
+        }
+
+        restore_error_handler();
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Util/Exception.php b/vendor/phpunit/phpunit/src/Util/Exception.php
new file mode 100644
index 0000000000000000000000000000000000000000..6bcb3d140a8b1f3fca9ecd6e786b3ccda1e0dc21
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Util/Exception.php
@@ -0,0 +1,19 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Util;
+
+use RuntimeException;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class Exception extends RuntimeException implements \PHPUnit\Exception
+{
+}
diff --git a/vendor/phpunit/phpunit/src/Util/ExcludeList.php b/vendor/phpunit/phpunit/src/Util/ExcludeList.php
new file mode 100644
index 0000000000000000000000000000000000000000..c7e6704a8f3abfd8a00ea0ba9ff393d169a42183
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Util/ExcludeList.php
@@ -0,0 +1,261 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Util;
+
+use const DIRECTORY_SEPARATOR;
+use function class_exists;
+use function defined;
+use function dirname;
+use function is_dir;
+use function realpath;
+use function sprintf;
+use function strpos;
+use function sys_get_temp_dir;
+use Composer\Autoload\ClassLoader;
+use DeepCopy\DeepCopy;
+use Doctrine\Instantiator\Instantiator;
+use PharIo\Manifest\Manifest;
+use PharIo\Version\Version as PharIoVersion;
+use phpDocumentor\Reflection\DocBlock;
+use phpDocumentor\Reflection\Project;
+use phpDocumentor\Reflection\Type;
+use PhpParser\Parser;
+use PHPUnit\Framework\TestCase;
+use Prophecy\Prophet;
+use ReflectionClass;
+use ReflectionException;
+use SebastianBergmann\CliParser\Parser as CliParser;
+use SebastianBergmann\CodeCoverage\CodeCoverage;
+use SebastianBergmann\CodeUnit\CodeUnit;
+use SebastianBergmann\CodeUnitReverseLookup\Wizard;
+use SebastianBergmann\Comparator\Comparator;
+use SebastianBergmann\Complexity\Calculator;
+use SebastianBergmann\Diff\Diff;
+use SebastianBergmann\Environment\Runtime;
+use SebastianBergmann\Exporter\Exporter;
+use SebastianBergmann\FileIterator\Facade as FileIteratorFacade;
+use SebastianBergmann\GlobalState\Snapshot;
+use SebastianBergmann\Invoker\Invoker;
+use SebastianBergmann\LinesOfCode\Counter;
+use SebastianBergmann\ObjectEnumerator\Enumerator;
+use SebastianBergmann\RecursionContext\Context;
+use SebastianBergmann\ResourceOperations\ResourceOperations;
+use SebastianBergmann\Template\Template;
+use SebastianBergmann\Timer\Timer;
+use SebastianBergmann\Type\TypeName;
+use SebastianBergmann\Version;
+use Symfony\Polyfill\Ctype\Ctype;
+use TheSeer\Tokenizer\Tokenizer;
+use Webmozart\Assert\Assert;
+
+/**
+ * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
+ */
+final class ExcludeList
+{
+    /**
+     * @var array<string,int>
+     */
+    private const EXCLUDED_CLASS_NAMES = [
+        // composer
+        ClassLoader::class => 1,
+
+        // doctrine/instantiator
+        Instantiator::class => 1,
+
+        // myclabs/deepcopy
+        DeepCopy::class => 1,
+
+        // nikic/php-parser
+        Parser::class => 1,
+
+        // phar-io/manifest
+        Manifest::class => 1,
+
+        // phar-io/version
+        PharIoVersion::class => 1,
+
+        // phpdocumentor/reflection-common
+        Project::class => 1,
+
+        // phpdocumentor/reflection-docblock
+        DocBlock::class => 1,
+
+        // phpdocumentor/type-resolver
+        Type::class => 1,
+
+        // phpspec/prophecy
+        Prophet::class => 1,
+
+        // phpunit/phpunit
+        TestCase::class => 2,
+
+        // phpunit/php-code-coverage
+        CodeCoverage::class => 1,
+
+        // phpunit/php-file-iterator
+        FileIteratorFacade::class => 1,
+
+        // phpunit/php-invoker
+        Invoker::class => 1,
+
+        // phpunit/php-text-template
+        Template::class => 1,
+
+        // phpunit/php-timer
+        Timer::class => 1,
+
+        // sebastian/cli-parser
+        CliParser::class => 1,
+
+        // sebastian/code-unit
+        CodeUnit::class => 1,
+
+        // sebastian/code-unit-reverse-lookup
+        Wizard::class => 1,
+
+        // sebastian/comparator
+        Comparator::class => 1,
+
+        // sebastian/complexity
+        Calculator::class => 1,
+
+        // sebastian/diff
+        Diff::class => 1,
+
+        // sebastian/environment
+        Runtime::class => 1,
+
+        // sebastian/exporter
+        Exporter::class => 1,
+
+        // sebastian/global-state
+        Snapshot::class => 1,
+
+        // sebastian/lines-of-code
+        Counter::class => 1,
+
+        // sebastian/object-enumerator
+        Enumerator::class => 1,
+
+        // sebastian/recursion-context
+        Context::class => 1,
+
+        // sebastian/resource-operations
+        ResourceOperations::class => 1,
+
+        // sebastian/type
+        TypeName::class => 1,
+
+        // sebastian/version
+        Version::class => 1,
+
+        // symfony/polyfill-ctype
+        Ctype::class => 1,
+
+        // theseer/tokenizer
+        Tokenizer::class => 1,
+
+        // webmozart/assert
+        Assert::class => 1,
+    ];
+
+    /**
+     * @var string[]
+     */
+    private static $directories;
+
+    public static function addDirectory(string $directory): void
+    {
+        if (!is_dir($directory)) {
+            throw new Exception(
+                sprintf(
+                    '"%s" is not a directory',
+                    $directory
+                )
+            );
+        }
+
+        self::$directories[] = realpath($directory);
+    }
+
+    /**
+     * @throws Exception
+     *
+     * @return string[]
+     */
+    public function getExcludedDirectories(): array
+    {
+        $this->initialize();
+
+        return self::$directories;
+    }
+
+    /**
+     * @throws Exception
+     */
+    public function isExcluded(string $file): bool
+    {
+        if (defined('PHPUNIT_TESTSUITE')) {
+            return false;
+        }
+
+        $this->initialize();
+
+        foreach (self::$directories as $directory) {
+            if (strpos($file, $directory) === 0) {
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+    /**
+     * @throws Exception
+     */
+    private function initialize(): void
+    {
+        if (self::$directories === null) {
+            self::$directories = [];
+
+            foreach (self::EXCLUDED_CLASS_NAMES as $className => $parent) {
+                if (!class_exists($className)) {
+                    continue;
+                }
+
+                try {
+                    $directory = (new ReflectionClass($className))->getFileName();
+                    // @codeCoverageIgnoreStart
+                } catch (ReflectionException $e) {
+                    throw new Exception(
+                        $e->getMessage(),
+                        (int) $e->getCode(),
+                        $e
+                    );
+                }
+                // @codeCoverageIgnoreEnd
+
+                for ($i = 0; $i < $parent; $i++) {
+                    $directory = dirname($directory);
+                }
+
+                self::$directories[] = $directory;
+            }
+
+            // Hide process isolation workaround on Windows.
+            if (DIRECTORY_SEPARATOR === '\\') {
+                // tempnam() prefix is limited to first 3 chars.
+                // @see https://php.net/manual/en/function.tempnam.php
+                self::$directories[] = sys_get_temp_dir() . '\\PHP';
+            }
+        }
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Util/FileLoader.php b/vendor/phpunit/phpunit/src/Util/FileLoader.php
new file mode 100644
index 0000000000000000000000000000000000000000..732870723e5beba94e3b145ecec174ec913d9ea7
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Util/FileLoader.php
@@ -0,0 +1,83 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Util;
+
+use const DIRECTORY_SEPARATOR;
+use function array_diff;
+use function array_keys;
+use function fopen;
+use function get_defined_vars;
+use function sprintf;
+use function stream_resolve_include_path;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class FileLoader
+{
+    /**
+     * Checks if a PHP sourcecode file is readable. The sourcecode file is loaded through the load() method.
+     *
+     * As a fallback, PHP looks in the directory of the file executing the stream_resolve_include_path function.
+     * We do not want to load the Test.php file here, so skip it if it found that.
+     * PHP prioritizes the include_path setting, so if the current directory is in there, it will first look in the
+     * current working directory.
+     *
+     * @throws Exception
+     */
+    public static function checkAndLoad(string $filename): string
+    {
+        $includePathFilename = stream_resolve_include_path($filename);
+
+        $localFile = __DIR__ . DIRECTORY_SEPARATOR . $filename;
+
+        if (!$includePathFilename ||
+            $includePathFilename === $localFile ||
+            !self::isReadable($includePathFilename)) {
+            throw new Exception(
+                sprintf('Cannot open file "%s".' . "\n", $filename)
+            );
+        }
+
+        self::load($includePathFilename);
+
+        return $includePathFilename;
+    }
+
+    /**
+     * Loads a PHP sourcefile.
+     */
+    public static function load(string $filename): void
+    {
+        $oldVariableNames = array_keys(get_defined_vars());
+
+        /**
+         * @noinspection PhpIncludeInspection
+         * @psalm-suppress UnresolvableInclude
+         */
+        include_once $filename;
+
+        $newVariables = get_defined_vars();
+
+        foreach (array_diff(array_keys($newVariables), $oldVariableNames) as $variableName) {
+            if ($variableName !== 'oldVariableNames') {
+                $GLOBALS[$variableName] = $newVariables[$variableName];
+            }
+        }
+    }
+
+    /**
+     * @see https://github.com/sebastianbergmann/phpunit/pull/2751
+     */
+    private static function isReadable(string $filename): bool
+    {
+        return @fopen($filename, 'r') !== false;
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Util/Filesystem.php b/vendor/phpunit/phpunit/src/Util/Filesystem.php
new file mode 100644
index 0000000000000000000000000000000000000000..35b2690b12e6c365dcc349cc835f3b91374fdb23
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Util/Filesystem.php
@@ -0,0 +1,41 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Util;
+
+use const DIRECTORY_SEPARATOR;
+use function is_dir;
+use function mkdir;
+use function str_replace;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class Filesystem
+{
+    /**
+     * Maps class names to source file names.
+     *
+     *   - PEAR CS:   Foo_Bar_Baz -> Foo/Bar/Baz.php
+     *   - Namespace: Foo\Bar\Baz -> Foo/Bar/Baz.php
+     */
+    public static function classNameToFilename(string $className): string
+    {
+        return str_replace(
+            ['_', '\\'],
+            DIRECTORY_SEPARATOR,
+            $className
+        ) . '.php';
+    }
+
+    public static function createDirectory(string $directory): bool
+    {
+        return !(!is_dir($directory) && !@mkdir($directory, 0777, true) && !is_dir($directory));
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Util/Filter.php b/vendor/phpunit/phpunit/src/Util/Filter.php
new file mode 100644
index 0000000000000000000000000000000000000000..42563937d75e4c897c031f9c1c83ced8ff5cafd9
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Util/Filter.php
@@ -0,0 +1,115 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Util;
+
+use function array_unshift;
+use function defined;
+use function in_array;
+use function is_file;
+use function realpath;
+use function sprintf;
+use function strpos;
+use PHPUnit\Framework\Exception;
+use PHPUnit\Framework\SyntheticError;
+use Throwable;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class Filter
+{
+    /**
+     * @throws Exception
+     */
+    public static function getFilteredStacktrace(Throwable $t): string
+    {
+        $filteredStacktrace = '';
+
+        if ($t instanceof SyntheticError) {
+            $eTrace = $t->getSyntheticTrace();
+            $eFile  = $t->getSyntheticFile();
+            $eLine  = $t->getSyntheticLine();
+        } elseif ($t instanceof Exception) {
+            $eTrace = $t->getSerializableTrace();
+            $eFile  = $t->getFile();
+            $eLine  = $t->getLine();
+        } else {
+            if ($t->getPrevious()) {
+                $t = $t->getPrevious();
+            }
+
+            $eTrace = $t->getTrace();
+            $eFile  = $t->getFile();
+            $eLine  = $t->getLine();
+        }
+
+        if (!self::frameExists($eTrace, $eFile, $eLine)) {
+            array_unshift(
+                $eTrace,
+                ['file' => $eFile, 'line' => $eLine]
+            );
+        }
+
+        $prefix      = defined('__PHPUNIT_PHAR_ROOT__') ? __PHPUNIT_PHAR_ROOT__ : false;
+        $excludeList = new ExcludeList;
+
+        foreach ($eTrace as $frame) {
+            if (self::shouldPrintFrame($frame, $prefix, $excludeList)) {
+                $filteredStacktrace .= sprintf(
+                    "%s:%s\n",
+                    $frame['file'],
+                    $frame['line'] ?? '?'
+                );
+            }
+        }
+
+        return $filteredStacktrace;
+    }
+
+    private static function shouldPrintFrame(array $frame, $prefix, ExcludeList $excludeList): bool
+    {
+        if (!isset($frame['file'])) {
+            return false;
+        }
+
+        $file              = $frame['file'];
+        $fileIsNotPrefixed = $prefix === false || strpos($file, $prefix) !== 0;
+
+        // @see https://github.com/sebastianbergmann/phpunit/issues/4033
+        if (isset($GLOBALS['_SERVER']['SCRIPT_NAME'])) {
+            $script = realpath($GLOBALS['_SERVER']['SCRIPT_NAME']);
+        } else {
+            $script = '';
+        }
+
+        return is_file($file) &&
+               self::fileIsExcluded($file, $excludeList) &&
+               $fileIsNotPrefixed &&
+               $file !== $script;
+    }
+
+    private static function fileIsExcluded(string $file, ExcludeList $excludeList): bool
+    {
+        return (empty($GLOBALS['__PHPUNIT_ISOLATION_EXCLUDE_LIST']) ||
+                !in_array($file, $GLOBALS['__PHPUNIT_ISOLATION_EXCLUDE_LIST'], true)) &&
+                !$excludeList->isExcluded($file);
+    }
+
+    private static function frameExists(array $trace, string $file, int $line): bool
+    {
+        foreach ($trace as $frame) {
+            if (isset($frame['file'], $frame['line']) && $frame['file'] === $file && $frame['line'] === $line) {
+                return true;
+            }
+        }
+
+        return false;
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Util/GlobalState.php b/vendor/phpunit/phpunit/src/Util/GlobalState.php
new file mode 100644
index 0000000000000000000000000000000000000000..b2110e9caf89258deada1c3118db88cbd1d2f545
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Util/GlobalState.php
@@ -0,0 +1,195 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Util;
+
+use function array_keys;
+use function array_reverse;
+use function defined;
+use function get_defined_constants;
+use function get_included_files;
+use function in_array;
+use function ini_get_all;
+use function is_array;
+use function is_file;
+use function is_scalar;
+use function preg_match;
+use function serialize;
+use function sprintf;
+use function strpos;
+use function var_export;
+use Closure;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class GlobalState
+{
+    /**
+     * @var string[]
+     */
+    private const SUPER_GLOBAL_ARRAYS = [
+        '_ENV',
+        '_POST',
+        '_GET',
+        '_COOKIE',
+        '_SERVER',
+        '_FILES',
+        '_REQUEST',
+    ];
+
+    /**
+     * @throws Exception
+     */
+    public static function getIncludedFilesAsString(): string
+    {
+        return self::processIncludedFilesAsString(get_included_files());
+    }
+
+    /**
+     * @param string[] $files
+     *
+     * @throws Exception
+     */
+    public static function processIncludedFilesAsString(array $files): string
+    {
+        $excludeList = new ExcludeList;
+        $prefix      = false;
+        $result      = '';
+
+        if (defined('__PHPUNIT_PHAR__')) {
+            $prefix = 'phar://' . __PHPUNIT_PHAR__ . '/';
+        }
+
+        // Do not process bootstrap script
+        unset($files[0]);
+
+        foreach (array_reverse($files) as $file) {
+            if (!empty($GLOBALS['__PHPUNIT_ISOLATION_EXCLUDE_LIST']) &&
+                in_array($file, $GLOBALS['__PHPUNIT_ISOLATION_EXCLUDE_LIST'], true)) {
+                continue;
+            }
+
+            if ($prefix !== false && strpos($file, $prefix) === 0) {
+                continue;
+            }
+
+            // Skip virtual file system protocols
+            if (preg_match('/^(vfs|phpvfs[a-z0-9]+):/', $file)) {
+                continue;
+            }
+
+            if (!$excludeList->isExcluded($file) && is_file($file)) {
+                $result = 'require_once \'' . $file . "';\n" . $result;
+            }
+        }
+
+        return $result;
+    }
+
+    public static function getIniSettingsAsString(): string
+    {
+        $result = '';
+
+        foreach (ini_get_all(null, false) as $key => $value) {
+            $result .= sprintf(
+                '@ini_set(%s, %s);' . "\n",
+                self::exportVariable($key),
+                self::exportVariable((string) $value)
+            );
+        }
+
+        return $result;
+    }
+
+    public static function getConstantsAsString(): string
+    {
+        $constants = get_defined_constants(true);
+        $result    = '';
+
+        if (isset($constants['user'])) {
+            foreach ($constants['user'] as $name => $value) {
+                $result .= sprintf(
+                    'if (!defined(\'%s\')) define(\'%s\', %s);' . "\n",
+                    $name,
+                    $name,
+                    self::exportVariable($value)
+                );
+            }
+        }
+
+        return $result;
+    }
+
+    public static function getGlobalsAsString(): string
+    {
+        $result = '';
+
+        foreach (self::SUPER_GLOBAL_ARRAYS as $superGlobalArray) {
+            if (isset($GLOBALS[$superGlobalArray]) && is_array($GLOBALS[$superGlobalArray])) {
+                foreach (array_keys($GLOBALS[$superGlobalArray]) as $key) {
+                    if ($GLOBALS[$superGlobalArray][$key] instanceof Closure) {
+                        continue;
+                    }
+
+                    $result .= sprintf(
+                        '$GLOBALS[\'%s\'][\'%s\'] = %s;' . "\n",
+                        $superGlobalArray,
+                        $key,
+                        self::exportVariable($GLOBALS[$superGlobalArray][$key])
+                    );
+                }
+            }
+        }
+
+        $excludeList   = self::SUPER_GLOBAL_ARRAYS;
+        $excludeList[] = 'GLOBALS';
+
+        foreach (array_keys($GLOBALS) as $key) {
+            if (!$GLOBALS[$key] instanceof Closure && !in_array($key, $excludeList, true)) {
+                $result .= sprintf(
+                    '$GLOBALS[\'%s\'] = %s;' . "\n",
+                    $key,
+                    self::exportVariable($GLOBALS[$key])
+                );
+            }
+        }
+
+        return $result;
+    }
+
+    private static function exportVariable($variable): string
+    {
+        if (is_scalar($variable) || $variable === null ||
+            (is_array($variable) && self::arrayOnlyContainsScalars($variable))) {
+            return var_export($variable, true);
+        }
+
+        return 'unserialize(' . var_export(serialize($variable), true) . ')';
+    }
+
+    private static function arrayOnlyContainsScalars(array $array): bool
+    {
+        $result = true;
+
+        foreach ($array as $element) {
+            if (is_array($element)) {
+                $result = self::arrayOnlyContainsScalars($element);
+            } elseif (!is_scalar($element) && $element !== null) {
+                $result = false;
+            }
+
+            if (!$result) {
+                break;
+            }
+        }
+
+        return $result;
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Util/InvalidDataSetException.php b/vendor/phpunit/phpunit/src/Util/InvalidDataSetException.php
new file mode 100644
index 0000000000000000000000000000000000000000..3493d113aae24cce83c97f0bd078dd0e7dd6aa0d
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Util/InvalidDataSetException.php
@@ -0,0 +1,19 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Util;
+
+use RuntimeException;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class InvalidDataSetException extends RuntimeException implements \PHPUnit\Exception
+{
+}
diff --git a/vendor/phpunit/phpunit/src/Util/Json.php b/vendor/phpunit/phpunit/src/Util/Json.php
new file mode 100644
index 0000000000000000000000000000000000000000..752c1fd600bb36fcd89c8db7908540f701d3e84b
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Util/Json.php
@@ -0,0 +1,98 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Util;
+
+use const JSON_PRETTY_PRINT;
+use const JSON_UNESCAPED_SLASHES;
+use const JSON_UNESCAPED_UNICODE;
+use function count;
+use function is_array;
+use function is_object;
+use function json_decode;
+use function json_encode;
+use function json_last_error;
+use function ksort;
+use PHPUnit\Framework\Exception;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class Json
+{
+    /**
+     * Prettify json string.
+     *
+     * @throws \PHPUnit\Framework\Exception
+     */
+    public static function prettify(string $json): string
+    {
+        $decodedJson = json_decode($json, false);
+
+        if (json_last_error()) {
+            throw new Exception(
+                'Cannot prettify invalid json'
+            );
+        }
+
+        return json_encode($decodedJson, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
+    }
+
+    /**
+     * To allow comparison of JSON strings, first process them into a consistent
+     * format so that they can be compared as strings.
+     *
+     * @return array ($error, $canonicalized_json)  The $error parameter is used
+     *               to indicate an error decoding the json. This is used to avoid ambiguity
+     *               with JSON strings consisting entirely of 'null' or 'false'.
+     */
+    public static function canonicalize(string $json): array
+    {
+        $decodedJson = json_decode($json);
+
+        if (json_last_error()) {
+            return [true, null];
+        }
+
+        self::recursiveSort($decodedJson);
+
+        $reencodedJson = json_encode($decodedJson);
+
+        return [false, $reencodedJson];
+    }
+
+    /**
+     * JSON object keys are unordered while PHP array keys are ordered.
+     *
+     * Sort all array keys to ensure both the expected and actual values have
+     * their keys in the same order.
+     */
+    private static function recursiveSort(&$json): void
+    {
+        if (!is_array($json)) {
+            // If the object is not empty, change it to an associative array
+            // so we can sort the keys (and we will still re-encode it
+            // correctly, since PHP encodes associative arrays as JSON objects.)
+            // But EMPTY objects MUST remain empty objects. (Otherwise we will
+            // re-encode it as a JSON array rather than a JSON object.)
+            // See #2919.
+            if (is_object($json) && count((array) $json) > 0) {
+                $json = (array) $json;
+            } else {
+                return;
+            }
+        }
+
+        ksort($json);
+
+        foreach ($json as $key => &$value) {
+            self::recursiveSort($value);
+        }
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Util/Log/JUnit.php b/vendor/phpunit/phpunit/src/Util/Log/JUnit.php
new file mode 100644
index 0000000000000000000000000000000000000000..7a97682fc2adffaf8b16d564be13740c36b2dd63
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Util/Log/JUnit.php
@@ -0,0 +1,424 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Util\Log;
+
+use function class_exists;
+use function get_class;
+use function method_exists;
+use function sprintf;
+use function str_replace;
+use function trim;
+use DOMDocument;
+use DOMElement;
+use PHPUnit\Framework\AssertionFailedError;
+use PHPUnit\Framework\ExceptionWrapper;
+use PHPUnit\Framework\SelfDescribing;
+use PHPUnit\Framework\Test;
+use PHPUnit\Framework\TestFailure;
+use PHPUnit\Framework\TestListener;
+use PHPUnit\Framework\TestSuite;
+use PHPUnit\Framework\Warning;
+use PHPUnit\Util\Exception;
+use PHPUnit\Util\Filter;
+use PHPUnit\Util\Printer;
+use PHPUnit\Util\Xml;
+use ReflectionClass;
+use ReflectionException;
+use Throwable;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class JUnit extends Printer implements TestListener
+{
+    /**
+     * @var DOMDocument
+     */
+    private $document;
+
+    /**
+     * @var DOMElement
+     */
+    private $root;
+
+    /**
+     * @var bool
+     */
+    private $reportRiskyTests = false;
+
+    /**
+     * @var DOMElement[]
+     */
+    private $testSuites = [];
+
+    /**
+     * @var int[]
+     */
+    private $testSuiteTests = [0];
+
+    /**
+     * @var int[]
+     */
+    private $testSuiteAssertions = [0];
+
+    /**
+     * @var int[]
+     */
+    private $testSuiteErrors = [0];
+
+    /**
+     * @var int[]
+     */
+    private $testSuiteWarnings = [0];
+
+    /**
+     * @var int[]
+     */
+    private $testSuiteFailures = [0];
+
+    /**
+     * @var int[]
+     */
+    private $testSuiteSkipped = [0];
+
+    /**
+     * @var int[]
+     */
+    private $testSuiteTimes = [0];
+
+    /**
+     * @var int
+     */
+    private $testSuiteLevel = 0;
+
+    /**
+     * @var DOMElement
+     */
+    private $currentTestCase;
+
+    /**
+     * @param null|mixed $out
+     */
+    public function __construct($out = null, bool $reportRiskyTests = false)
+    {
+        $this->document               = new DOMDocument('1.0', 'UTF-8');
+        $this->document->formatOutput = true;
+
+        $this->root = $this->document->createElement('testsuites');
+        $this->document->appendChild($this->root);
+
+        parent::__construct($out);
+
+        $this->reportRiskyTests = $reportRiskyTests;
+    }
+
+    /**
+     * Flush buffer and close output.
+     */
+    public function flush(): void
+    {
+        $this->write($this->getXML());
+
+        parent::flush();
+    }
+
+    /**
+     * An error occurred.
+     */
+    public function addError(Test $test, Throwable $t, float $time): void
+    {
+        $this->doAddFault($test, $t, 'error');
+        $this->testSuiteErrors[$this->testSuiteLevel]++;
+    }
+
+    /**
+     * A warning occurred.
+     */
+    public function addWarning(Test $test, Warning $e, float $time): void
+    {
+        $this->doAddFault($test, $e, 'warning');
+        $this->testSuiteWarnings[$this->testSuiteLevel]++;
+    }
+
+    /**
+     * A failure occurred.
+     */
+    public function addFailure(Test $test, AssertionFailedError $e, float $time): void
+    {
+        $this->doAddFault($test, $e, 'failure');
+        $this->testSuiteFailures[$this->testSuiteLevel]++;
+    }
+
+    /**
+     * Incomplete test.
+     */
+    public function addIncompleteTest(Test $test, Throwable $t, float $time): void
+    {
+        $this->doAddSkipped();
+    }
+
+    /**
+     * Risky test.
+     */
+    public function addRiskyTest(Test $test, Throwable $t, float $time): void
+    {
+        if (!$this->reportRiskyTests) {
+            return;
+        }
+
+        $this->doAddFault($test, $t, 'error');
+        $this->testSuiteErrors[$this->testSuiteLevel]++;
+    }
+
+    /**
+     * Skipped test.
+     */
+    public function addSkippedTest(Test $test, Throwable $t, float $time): void
+    {
+        $this->doAddSkipped();
+    }
+
+    /**
+     * A testsuite started.
+     */
+    public function startTestSuite(TestSuite $suite): void
+    {
+        $testSuite = $this->document->createElement('testsuite');
+        $testSuite->setAttribute('name', $suite->getName());
+
+        if (class_exists($suite->getName(), false)) {
+            try {
+                $class = new ReflectionClass($suite->getName());
+
+                $testSuite->setAttribute('file', $class->getFileName());
+            } catch (ReflectionException $e) {
+            }
+        }
+
+        if ($this->testSuiteLevel > 0) {
+            $this->testSuites[$this->testSuiteLevel]->appendChild($testSuite);
+        } else {
+            $this->root->appendChild($testSuite);
+        }
+
+        $this->testSuiteLevel++;
+        $this->testSuites[$this->testSuiteLevel]          = $testSuite;
+        $this->testSuiteTests[$this->testSuiteLevel]      = 0;
+        $this->testSuiteAssertions[$this->testSuiteLevel] = 0;
+        $this->testSuiteErrors[$this->testSuiteLevel]     = 0;
+        $this->testSuiteWarnings[$this->testSuiteLevel]   = 0;
+        $this->testSuiteFailures[$this->testSuiteLevel]   = 0;
+        $this->testSuiteSkipped[$this->testSuiteLevel]    = 0;
+        $this->testSuiteTimes[$this->testSuiteLevel]      = 0;
+    }
+
+    /**
+     * A testsuite ended.
+     */
+    public function endTestSuite(TestSuite $suite): void
+    {
+        $this->testSuites[$this->testSuiteLevel]->setAttribute(
+            'tests',
+            (string) $this->testSuiteTests[$this->testSuiteLevel]
+        );
+
+        $this->testSuites[$this->testSuiteLevel]->setAttribute(
+            'assertions',
+            (string) $this->testSuiteAssertions[$this->testSuiteLevel]
+        );
+
+        $this->testSuites[$this->testSuiteLevel]->setAttribute(
+            'errors',
+            (string) $this->testSuiteErrors[$this->testSuiteLevel]
+        );
+
+        $this->testSuites[$this->testSuiteLevel]->setAttribute(
+            'warnings',
+            (string) $this->testSuiteWarnings[$this->testSuiteLevel]
+        );
+
+        $this->testSuites[$this->testSuiteLevel]->setAttribute(
+            'failures',
+            (string) $this->testSuiteFailures[$this->testSuiteLevel]
+        );
+
+        $this->testSuites[$this->testSuiteLevel]->setAttribute(
+            'skipped',
+            (string) $this->testSuiteSkipped[$this->testSuiteLevel]
+        );
+
+        $this->testSuites[$this->testSuiteLevel]->setAttribute(
+            'time',
+            sprintf('%F', $this->testSuiteTimes[$this->testSuiteLevel])
+        );
+
+        if ($this->testSuiteLevel > 1) {
+            $this->testSuiteTests[$this->testSuiteLevel - 1] += $this->testSuiteTests[$this->testSuiteLevel];
+            $this->testSuiteAssertions[$this->testSuiteLevel - 1] += $this->testSuiteAssertions[$this->testSuiteLevel];
+            $this->testSuiteErrors[$this->testSuiteLevel - 1] += $this->testSuiteErrors[$this->testSuiteLevel];
+            $this->testSuiteWarnings[$this->testSuiteLevel - 1] += $this->testSuiteWarnings[$this->testSuiteLevel];
+            $this->testSuiteFailures[$this->testSuiteLevel - 1] += $this->testSuiteFailures[$this->testSuiteLevel];
+            $this->testSuiteSkipped[$this->testSuiteLevel - 1] += $this->testSuiteSkipped[$this->testSuiteLevel];
+            $this->testSuiteTimes[$this->testSuiteLevel - 1] += $this->testSuiteTimes[$this->testSuiteLevel];
+        }
+
+        $this->testSuiteLevel--;
+    }
+
+    /**
+     * A test started.
+     */
+    public function startTest(Test $test): void
+    {
+        $usesDataprovider = false;
+
+        if (method_exists($test, 'usesDataProvider')) {
+            $usesDataprovider = $test->usesDataProvider();
+        }
+
+        $testCase = $this->document->createElement('testcase');
+        $testCase->setAttribute('name', $test->getName());
+
+        try {
+            $class = new ReflectionClass($test);
+            // @codeCoverageIgnoreStart
+        } catch (ReflectionException $e) {
+            throw new Exception(
+                $e->getMessage(),
+                (int) $e->getCode(),
+                $e
+            );
+        }
+        // @codeCoverageIgnoreEnd
+
+        $methodName = $test->getName(!$usesDataprovider);
+
+        if ($class->hasMethod($methodName)) {
+            try {
+                $method = $class->getMethod($methodName);
+                // @codeCoverageIgnoreStart
+            } catch (ReflectionException $e) {
+                throw new Exception(
+                    $e->getMessage(),
+                    (int) $e->getCode(),
+                    $e
+                );
+            }
+            // @codeCoverageIgnoreEnd
+
+            $testCase->setAttribute('class', $class->getName());
+            $testCase->setAttribute('classname', str_replace('\\', '.', $class->getName()));
+            $testCase->setAttribute('file', $class->getFileName());
+            $testCase->setAttribute('line', (string) $method->getStartLine());
+        }
+
+        $this->currentTestCase = $testCase;
+    }
+
+    /**
+     * A test ended.
+     */
+    public function endTest(Test $test, float $time): void
+    {
+        $numAssertions = 0;
+
+        if (method_exists($test, 'getNumAssertions')) {
+            $numAssertions = $test->getNumAssertions();
+        }
+
+        $this->testSuiteAssertions[$this->testSuiteLevel] += $numAssertions;
+
+        $this->currentTestCase->setAttribute(
+            'assertions',
+            (string) $numAssertions
+        );
+
+        $this->currentTestCase->setAttribute(
+            'time',
+            sprintf('%F', $time)
+        );
+
+        $this->testSuites[$this->testSuiteLevel]->appendChild(
+            $this->currentTestCase
+        );
+
+        $this->testSuiteTests[$this->testSuiteLevel]++;
+        $this->testSuiteTimes[$this->testSuiteLevel] += $time;
+
+        $testOutput = '';
+
+        if (method_exists($test, 'hasOutput') && method_exists($test, 'getActualOutput')) {
+            $testOutput = $test->hasOutput() ? $test->getActualOutput() : '';
+        }
+
+        if (!empty($testOutput)) {
+            $systemOut = $this->document->createElement(
+                'system-out',
+                Xml::prepareString($testOutput)
+            );
+
+            $this->currentTestCase->appendChild($systemOut);
+        }
+
+        $this->currentTestCase = null;
+    }
+
+    /**
+     * Returns the XML as a string.
+     */
+    public function getXML(): string
+    {
+        return $this->document->saveXML();
+    }
+
+    private function doAddFault(Test $test, Throwable $t, string $type): void
+    {
+        if ($this->currentTestCase === null) {
+            return;
+        }
+
+        if ($test instanceof SelfDescribing) {
+            $buffer = $test->toString() . "\n";
+        } else {
+            $buffer = '';
+        }
+
+        $buffer .= trim(
+            TestFailure::exceptionToString($t) . "\n" .
+            Filter::getFilteredStacktrace($t)
+        );
+
+        $fault = $this->document->createElement(
+            $type,
+            Xml::prepareString($buffer)
+        );
+
+        if ($t instanceof ExceptionWrapper) {
+            $fault->setAttribute('type', $t->getClassName());
+        } else {
+            $fault->setAttribute('type', get_class($t));
+        }
+
+        $this->currentTestCase->appendChild($fault);
+    }
+
+    private function doAddSkipped(): void
+    {
+        if ($this->currentTestCase === null) {
+            return;
+        }
+
+        $skipped = $this->document->createElement('skipped');
+
+        $this->currentTestCase->appendChild($skipped);
+
+        $this->testSuiteSkipped[$this->testSuiteLevel]++;
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Util/Log/TeamCity.php b/vendor/phpunit/phpunit/src/Util/Log/TeamCity.php
new file mode 100644
index 0000000000000000000000000000000000000000..f800ba72dcdec645a5e7ff07571bf9ac07f686a4
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Util/Log/TeamCity.php
@@ -0,0 +1,383 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Util\Log;
+
+use function class_exists;
+use function count;
+use function explode;
+use function get_class;
+use function getmypid;
+use function ini_get;
+use function is_bool;
+use function is_scalar;
+use function method_exists;
+use function print_r;
+use function round;
+use function str_replace;
+use function stripos;
+use PHPUnit\Framework\AssertionFailedError;
+use PHPUnit\Framework\ExceptionWrapper;
+use PHPUnit\Framework\ExpectationFailedException;
+use PHPUnit\Framework\Test;
+use PHPUnit\Framework\TestCase;
+use PHPUnit\Framework\TestFailure;
+use PHPUnit\Framework\TestResult;
+use PHPUnit\Framework\TestSuite;
+use PHPUnit\Framework\Warning;
+use PHPUnit\TextUI\DefaultResultPrinter;
+use PHPUnit\Util\Exception;
+use PHPUnit\Util\Filter;
+use ReflectionClass;
+use ReflectionException;
+use SebastianBergmann\Comparator\ComparisonFailure;
+use Throwable;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class TeamCity extends DefaultResultPrinter
+{
+    /**
+     * @var bool
+     */
+    private $isSummaryTestCountPrinted = false;
+
+    /**
+     * @var string
+     */
+    private $startedTestName;
+
+    /**
+     * @var false|int
+     */
+    private $flowId;
+
+    public function printResult(TestResult $result): void
+    {
+        $this->printHeader($result);
+        $this->printFooter($result);
+    }
+
+    /**
+     * An error occurred.
+     */
+    public function addError(Test $test, Throwable $t, float $time): void
+    {
+        $this->printEvent(
+            'testFailed',
+            [
+                'name'     => $test->getName(),
+                'message'  => self::getMessage($t),
+                'details'  => self::getDetails($t),
+                'duration' => self::toMilliseconds($time),
+            ]
+        );
+    }
+
+    /**
+     * A warning occurred.
+     */
+    public function addWarning(Test $test, Warning $e, float $time): void
+    {
+        $this->write(self::getMessage($e) . PHP_EOL);
+    }
+
+    /**
+     * A failure occurred.
+     */
+    public function addFailure(Test $test, AssertionFailedError $e, float $time): void
+    {
+        $parameters = [
+            'name'     => $test->getName(),
+            'message'  => self::getMessage($e),
+            'details'  => self::getDetails($e),
+            'duration' => self::toMilliseconds($time),
+        ];
+
+        if ($e instanceof ExpectationFailedException) {
+            $comparisonFailure = $e->getComparisonFailure();
+
+            if ($comparisonFailure instanceof ComparisonFailure) {
+                $expectedString = $comparisonFailure->getExpectedAsString();
+
+                if ($expectedString === null || empty($expectedString)) {
+                    $expectedString = self::getPrimitiveValueAsString($comparisonFailure->getExpected());
+                }
+
+                $actualString = $comparisonFailure->getActualAsString();
+
+                if ($actualString === null || empty($actualString)) {
+                    $actualString = self::getPrimitiveValueAsString($comparisonFailure->getActual());
+                }
+
+                if ($actualString !== null && $expectedString !== null) {
+                    $parameters['type']     = 'comparisonFailure';
+                    $parameters['actual']   = $actualString;
+                    $parameters['expected'] = $expectedString;
+                }
+            }
+        }
+
+        $this->printEvent('testFailed', $parameters);
+    }
+
+    /**
+     * Incomplete test.
+     */
+    public function addIncompleteTest(Test $test, Throwable $t, float $time): void
+    {
+        $this->printIgnoredTest($test->getName(), $t, $time);
+    }
+
+    /**
+     * Risky test.
+     */
+    public function addRiskyTest(Test $test, Throwable $t, float $time): void
+    {
+        $this->addError($test, $t, $time);
+    }
+
+    /**
+     * Skipped test.
+     */
+    public function addSkippedTest(Test $test, Throwable $t, float $time): void
+    {
+        $testName = $test->getName();
+
+        if ($this->startedTestName !== $testName) {
+            $this->startTest($test);
+            $this->printIgnoredTest($testName, $t, $time);
+            $this->endTest($test, $time);
+        } else {
+            $this->printIgnoredTest($testName, $t, $time);
+        }
+    }
+
+    public function printIgnoredTest(string $testName, Throwable $t, float $time): void
+    {
+        $this->printEvent(
+            'testIgnored',
+            [
+                'name'     => $testName,
+                'message'  => self::getMessage($t),
+                'details'  => self::getDetails($t),
+                'duration' => self::toMilliseconds($time),
+            ]
+        );
+    }
+
+    /**
+     * A testsuite started.
+     */
+    public function startTestSuite(TestSuite $suite): void
+    {
+        if (stripos(ini_get('disable_functions'), 'getmypid') === false) {
+            $this->flowId = getmypid();
+        } else {
+            $this->flowId = false;
+        }
+
+        if (!$this->isSummaryTestCountPrinted) {
+            $this->isSummaryTestCountPrinted = true;
+
+            $this->printEvent(
+                'testCount',
+                ['count' => count($suite)]
+            );
+        }
+
+        $suiteName = $suite->getName();
+
+        if (empty($suiteName)) {
+            return;
+        }
+
+        $parameters = ['name' => $suiteName];
+
+        if (class_exists($suiteName, false)) {
+            $fileName                   = self::getFileName($suiteName);
+            $parameters['locationHint'] = "php_qn://{$fileName}::\\{$suiteName}";
+        } else {
+            $split = explode('::', $suiteName);
+
+            if (count($split) === 2 && class_exists($split[0]) && method_exists($split[0], $split[1])) {
+                $fileName                   = self::getFileName($split[0]);
+                $parameters['locationHint'] = "php_qn://{$fileName}::\\{$suiteName}";
+                $parameters['name']         = $split[1];
+            }
+        }
+
+        $this->printEvent('testSuiteStarted', $parameters);
+    }
+
+    /**
+     * A testsuite ended.
+     */
+    public function endTestSuite(TestSuite $suite): void
+    {
+        $suiteName = $suite->getName();
+
+        if (empty($suiteName)) {
+            return;
+        }
+
+        $parameters = ['name' => $suiteName];
+
+        if (!class_exists($suiteName, false)) {
+            $split = explode('::', $suiteName);
+
+            if (count($split) === 2 && class_exists($split[0]) && method_exists($split[0], $split[1])) {
+                $parameters['name'] = $split[1];
+            }
+        }
+
+        $this->printEvent('testSuiteFinished', $parameters);
+    }
+
+    /**
+     * A test started.
+     */
+    public function startTest(Test $test): void
+    {
+        $testName              = $test->getName();
+        $this->startedTestName = $testName;
+        $params                = ['name' => $testName];
+
+        if ($test instanceof TestCase) {
+            $className              = get_class($test);
+            $fileName               = self::getFileName($className);
+            $params['locationHint'] = "php_qn://{$fileName}::\\{$className}::{$testName}";
+        }
+
+        $this->printEvent('testStarted', $params);
+    }
+
+    /**
+     * A test ended.
+     */
+    public function endTest(Test $test, float $time): void
+    {
+        parent::endTest($test, $time);
+
+        $this->printEvent(
+            'testFinished',
+            [
+                'name'     => $test->getName(),
+                'duration' => self::toMilliseconds($time),
+            ]
+        );
+    }
+
+    protected function writeProgress(string $progress): void
+    {
+    }
+
+    private function printEvent(string $eventName, array $params = []): void
+    {
+        $this->write("\n##teamcity[{$eventName}");
+
+        if ($this->flowId) {
+            $params['flowId'] = $this->flowId;
+        }
+
+        foreach ($params as $key => $value) {
+            $escapedValue = self::escapeValue((string) $value);
+            $this->write(" {$key}='{$escapedValue}'");
+        }
+
+        $this->write("]\n");
+    }
+
+    private static function getMessage(Throwable $t): string
+    {
+        $message = '';
+
+        if ($t instanceof ExceptionWrapper) {
+            if ($t->getClassName() !== '') {
+                $message .= $t->getClassName();
+            }
+
+            if ($message !== '' && $t->getMessage() !== '') {
+                $message .= ' : ';
+            }
+        }
+
+        return $message . $t->getMessage();
+    }
+
+    private static function getDetails(Throwable $t): string
+    {
+        $stackTrace = Filter::getFilteredStacktrace($t);
+        $previous   = $t instanceof ExceptionWrapper ? $t->getPreviousWrapped() : $t->getPrevious();
+
+        while ($previous) {
+            $stackTrace .= "\nCaused by\n" .
+                TestFailure::exceptionToString($previous) . "\n" .
+                Filter::getFilteredStacktrace($previous);
+
+            $previous = $previous instanceof ExceptionWrapper ?
+                $previous->getPreviousWrapped() : $previous->getPrevious();
+        }
+
+        return ' ' . str_replace("\n", "\n ", $stackTrace);
+    }
+
+    private static function getPrimitiveValueAsString($value): ?string
+    {
+        if ($value === null) {
+            return 'null';
+        }
+
+        if (is_bool($value)) {
+            return $value ? 'true' : 'false';
+        }
+
+        if (is_scalar($value)) {
+            return print_r($value, true);
+        }
+
+        return null;
+    }
+
+    private static function escapeValue(string $text): string
+    {
+        return str_replace(
+            ['|', "'", "\n", "\r", ']', '['],
+            ['||', "|'", '|n', '|r', '|]', '|['],
+            $text
+        );
+    }
+
+    /**
+     * @param string $className
+     */
+    private static function getFileName($className): string
+    {
+        try {
+            return (new ReflectionClass($className))->getFileName();
+            // @codeCoverageIgnoreStart
+        } catch (ReflectionException $e) {
+            throw new Exception(
+                $e->getMessage(),
+                (int) $e->getCode(),
+                $e
+            );
+        }
+        // @codeCoverageIgnoreEnd
+    }
+
+    /**
+     * @param float $time microseconds
+     */
+    private static function toMilliseconds(float $time): int
+    {
+        return (int) round($time * 1000);
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Util/PHP/AbstractPhpProcess.php b/vendor/phpunit/phpunit/src/Util/PHP/AbstractPhpProcess.php
new file mode 100644
index 0000000000000000000000000000000000000000..b5de7144fe29594a21cd4fbeef246c69439c0321
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Util/PHP/AbstractPhpProcess.php
@@ -0,0 +1,415 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Util\PHP;
+
+use const DIRECTORY_SEPARATOR;
+use const PHP_SAPI;
+use function array_keys;
+use function array_merge;
+use function assert;
+use function escapeshellarg;
+use function ini_get_all;
+use function restore_error_handler;
+use function set_error_handler;
+use function sprintf;
+use function str_replace;
+use function strpos;
+use function strrpos;
+use function substr;
+use function trim;
+use function unserialize;
+use __PHP_Incomplete_Class;
+use ErrorException;
+use PHPUnit\Framework\AssertionFailedError;
+use PHPUnit\Framework\Exception;
+use PHPUnit\Framework\SyntheticError;
+use PHPUnit\Framework\Test;
+use PHPUnit\Framework\TestCase;
+use PHPUnit\Framework\TestFailure;
+use PHPUnit\Framework\TestResult;
+use SebastianBergmann\Environment\Runtime;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+abstract class AbstractPhpProcess
+{
+    /**
+     * @var Runtime
+     */
+    protected $runtime;
+
+    /**
+     * @var bool
+     */
+    protected $stderrRedirection = false;
+
+    /**
+     * @var string
+     */
+    protected $stdin = '';
+
+    /**
+     * @var string
+     */
+    protected $args = '';
+
+    /**
+     * @var array<string, string>
+     */
+    protected $env = [];
+
+    /**
+     * @var int
+     */
+    protected $timeout = 0;
+
+    public static function factory(): self
+    {
+        if (DIRECTORY_SEPARATOR === '\\') {
+            return new WindowsPhpProcess;
+        }
+
+        return new DefaultPhpProcess;
+    }
+
+    public function __construct()
+    {
+        $this->runtime = new Runtime;
+    }
+
+    /**
+     * Defines if should use STDERR redirection or not.
+     *
+     * Then $stderrRedirection is TRUE, STDERR is redirected to STDOUT.
+     */
+    public function setUseStderrRedirection(bool $stderrRedirection): void
+    {
+        $this->stderrRedirection = $stderrRedirection;
+    }
+
+    /**
+     * Returns TRUE if uses STDERR redirection or FALSE if not.
+     */
+    public function useStderrRedirection(): bool
+    {
+        return $this->stderrRedirection;
+    }
+
+    /**
+     * Sets the input string to be sent via STDIN.
+     */
+    public function setStdin(string $stdin): void
+    {
+        $this->stdin = $stdin;
+    }
+
+    /**
+     * Returns the input string to be sent via STDIN.
+     */
+    public function getStdin(): string
+    {
+        return $this->stdin;
+    }
+
+    /**
+     * Sets the string of arguments to pass to the php job.
+     */
+    public function setArgs(string $args): void
+    {
+        $this->args = $args;
+    }
+
+    /**
+     * Returns the string of arguments to pass to the php job.
+     */
+    public function getArgs(): string
+    {
+        return $this->args;
+    }
+
+    /**
+     * Sets the array of environment variables to start the child process with.
+     *
+     * @param array<string, string> $env
+     */
+    public function setEnv(array $env): void
+    {
+        $this->env = $env;
+    }
+
+    /**
+     * Returns the array of environment variables to start the child process with.
+     */
+    public function getEnv(): array
+    {
+        return $this->env;
+    }
+
+    /**
+     * Sets the amount of seconds to wait before timing out.
+     */
+    public function setTimeout(int $timeout): void
+    {
+        $this->timeout = $timeout;
+    }
+
+    /**
+     * Returns the amount of seconds to wait before timing out.
+     */
+    public function getTimeout(): int
+    {
+        return $this->timeout;
+    }
+
+    /**
+     * Runs a single test in a separate PHP process.
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     */
+    public function runTestJob(string $job, Test $test, TestResult $result): void
+    {
+        $result->startTest($test);
+
+        $_result = $this->runJob($job);
+
+        $this->processChildResult(
+            $test,
+            $result,
+            $_result['stdout'],
+            $_result['stderr']
+        );
+    }
+
+    /**
+     * Returns the command based into the configurations.
+     */
+    public function getCommand(array $settings, string $file = null): string
+    {
+        $command = $this->runtime->getBinary();
+
+        if ($this->runtime->hasPCOV()) {
+            $settings = array_merge(
+                $settings,
+                $this->runtime->getCurrentSettings(
+                    array_keys(ini_get_all('pcov'))
+                )
+            );
+        } elseif ($this->runtime->hasXdebug()) {
+            $settings = array_merge(
+                $settings,
+                $this->runtime->getCurrentSettings(
+                    array_keys(ini_get_all('xdebug'))
+                )
+            );
+        }
+
+        $command .= $this->settingsToParameters($settings);
+
+        if (PHP_SAPI === 'phpdbg') {
+            $command .= ' -qrr';
+
+            if (!$file) {
+                $command .= 's=';
+            }
+        }
+
+        if ($file) {
+            $command .= ' ' . escapeshellarg($file);
+        }
+
+        if ($this->args) {
+            if (!$file) {
+                $command .= ' --';
+            }
+            $command .= ' ' . $this->args;
+        }
+
+        if ($this->stderrRedirection) {
+            $command .= ' 2>&1';
+        }
+
+        return $command;
+    }
+
+    /**
+     * Runs a single job (PHP code) using a separate PHP process.
+     */
+    abstract public function runJob(string $job, array $settings = []): array;
+
+    protected function settingsToParameters(array $settings): string
+    {
+        $buffer = '';
+
+        foreach ($settings as $setting) {
+            $buffer .= ' -d ' . escapeshellarg($setting);
+        }
+
+        return $buffer;
+    }
+
+    /**
+     * Processes the TestResult object from an isolated process.
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     */
+    private function processChildResult(Test $test, TestResult $result, string $stdout, string $stderr): void
+    {
+        $time = 0;
+
+        if (!empty($stderr)) {
+            $result->addError(
+                $test,
+                new Exception(trim($stderr)),
+                $time
+            );
+        } else {
+            set_error_handler(
+                /**
+                 * @throws ErrorException
+                 */
+                static function ($errno, $errstr, $errfile, $errline): void {
+                    throw new ErrorException($errstr, $errno, $errno, $errfile, $errline);
+                }
+            );
+
+            try {
+                if (strpos($stdout, "#!/usr/bin/env php\n") === 0) {
+                    $stdout = substr($stdout, 19);
+                }
+
+                $childResult = unserialize(str_replace("#!/usr/bin/env php\n", '', $stdout));
+                restore_error_handler();
+
+                if ($childResult === false) {
+                    $result->addFailure(
+                        $test,
+                        new AssertionFailedError('Test was run in child process and ended unexpectedly'),
+                        $time
+                    );
+                }
+            } catch (ErrorException $e) {
+                restore_error_handler();
+                $childResult = false;
+
+                $result->addError(
+                    $test,
+                    new Exception(trim($stdout), 0, $e),
+                    $time
+                );
+            }
+
+            if ($childResult !== false) {
+                if (!empty($childResult['output'])) {
+                    $output = $childResult['output'];
+                }
+
+                /* @var TestCase $test */
+
+                $test->setResult($childResult['testResult']);
+                $test->addToAssertionCount($childResult['numAssertions']);
+
+                $childResult = $childResult['result'];
+                assert($childResult instanceof TestResult);
+
+                if ($result->getCollectCodeCoverageInformation()) {
+                    $result->getCodeCoverage()->merge(
+                        $childResult->getCodeCoverage()
+                    );
+                }
+
+                $time           = $childResult->time();
+                $notImplemented = $childResult->notImplemented();
+                $risky          = $childResult->risky();
+                $skipped        = $childResult->skipped();
+                $errors         = $childResult->errors();
+                $warnings       = $childResult->warnings();
+                $failures       = $childResult->failures();
+
+                if (!empty($notImplemented)) {
+                    $result->addError(
+                        $test,
+                        $this->getException($notImplemented[0]),
+                        $time
+                    );
+                } elseif (!empty($risky)) {
+                    $result->addError(
+                        $test,
+                        $this->getException($risky[0]),
+                        $time
+                    );
+                } elseif (!empty($skipped)) {
+                    $result->addError(
+                        $test,
+                        $this->getException($skipped[0]),
+                        $time
+                    );
+                } elseif (!empty($errors)) {
+                    $result->addError(
+                        $test,
+                        $this->getException($errors[0]),
+                        $time
+                    );
+                } elseif (!empty($warnings)) {
+                    $result->addWarning(
+                        $test,
+                        $this->getException($warnings[0]),
+                        $time
+                    );
+                } elseif (!empty($failures)) {
+                    $result->addFailure(
+                        $test,
+                        $this->getException($failures[0]),
+                        $time
+                    );
+                }
+            }
+        }
+
+        $result->endTest($test, $time);
+
+        if (!empty($output)) {
+            print $output;
+        }
+    }
+
+    /**
+     * Gets the thrown exception from a PHPUnit\Framework\TestFailure.
+     *
+     * @see https://github.com/sebastianbergmann/phpunit/issues/74
+     */
+    private function getException(TestFailure $error): Exception
+    {
+        $exception = $error->thrownException();
+
+        if ($exception instanceof __PHP_Incomplete_Class) {
+            $exceptionArray = [];
+
+            foreach ((array) $exception as $key => $value) {
+                $key                  = substr($key, strrpos($key, "\0") + 1);
+                $exceptionArray[$key] = $value;
+            }
+
+            $exception = new SyntheticError(
+                sprintf(
+                    '%s: %s',
+                    $exceptionArray['_PHP_Incomplete_Class_Name'],
+                    $exceptionArray['message']
+                ),
+                $exceptionArray['code'],
+                $exceptionArray['file'],
+                $exceptionArray['line'],
+                $exceptionArray['trace']
+            );
+        }
+
+        return $exception;
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Util/PHP/DefaultPhpProcess.php b/vendor/phpunit/phpunit/src/Util/PHP/DefaultPhpProcess.php
new file mode 100644
index 0000000000000000000000000000000000000000..c4dc11146a859608b33018b2e837d66dcf4a0d10
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Util/PHP/DefaultPhpProcess.php
@@ -0,0 +1,236 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Util\PHP;
+
+use function array_merge;
+use function fclose;
+use function file_put_contents;
+use function fread;
+use function fwrite;
+use function is_array;
+use function is_resource;
+use function proc_close;
+use function proc_open;
+use function proc_terminate;
+use function rewind;
+use function sprintf;
+use function stream_get_contents;
+use function stream_select;
+use function sys_get_temp_dir;
+use function tempnam;
+use function unlink;
+use PHPUnit\Framework\Exception;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+class DefaultPhpProcess extends AbstractPhpProcess
+{
+    /**
+     * @var string
+     */
+    protected $tempFile;
+
+    /**
+     * Runs a single job (PHP code) using a separate PHP process.
+     *
+     * @throws Exception
+     */
+    public function runJob(string $job, array $settings = []): array
+    {
+        if ($this->stdin || $this->useTemporaryFile()) {
+            if (!($this->tempFile = tempnam(sys_get_temp_dir(), 'PHPUnit')) ||
+                file_put_contents($this->tempFile, $job) === false) {
+                throw new Exception(
+                    'Unable to write temporary file'
+                );
+            }
+
+            $job = $this->stdin;
+        }
+
+        return $this->runProcess($job, $settings);
+    }
+
+    /**
+     * Returns an array of file handles to be used in place of pipes.
+     */
+    protected function getHandles(): array
+    {
+        return [];
+    }
+
+    /**
+     * Handles creating the child process and returning the STDOUT and STDERR.
+     *
+     * @throws Exception
+     */
+    protected function runProcess(string $job, array $settings): array
+    {
+        $handles = $this->getHandles();
+
+        $env = null;
+
+        if ($this->env) {
+            $env = $_SERVER ?? [];
+            unset($env['argv'], $env['argc']);
+            $env = array_merge($env, $this->env);
+
+            foreach ($env as $envKey => $envVar) {
+                if (is_array($envVar)) {
+                    unset($env[$envKey]);
+                }
+            }
+        }
+
+        $pipeSpec = [
+            0 => $handles[0] ?? ['pipe', 'r'],
+            1 => $handles[1] ?? ['pipe', 'w'],
+            2 => $handles[2] ?? ['pipe', 'w'],
+        ];
+
+        $process = proc_open(
+            $this->getCommand($settings, $this->tempFile),
+            $pipeSpec,
+            $pipes,
+            null,
+            $env
+        );
+
+        if (!is_resource($process)) {
+            throw new Exception(
+                'Unable to spawn worker process'
+            );
+        }
+
+        if ($job) {
+            $this->process($pipes[0], $job);
+        }
+
+        fclose($pipes[0]);
+
+        $stderr = $stdout = '';
+
+        if ($this->timeout) {
+            unset($pipes[0]);
+
+            while (true) {
+                $r = $pipes;
+                $w = null;
+                $e = null;
+
+                $n = @stream_select($r, $w, $e, $this->timeout);
+
+                if ($n === false) {
+                    break;
+                }
+
+                if ($n === 0) {
+                    proc_terminate($process, 9);
+
+                    throw new Exception(
+                        sprintf(
+                            'Job execution aborted after %d seconds',
+                            $this->timeout
+                        )
+                    );
+                }
+
+                if ($n > 0) {
+                    foreach ($r as $pipe) {
+                        $pipeOffset = 0;
+
+                        foreach ($pipes as $i => $origPipe) {
+                            if ($pipe === $origPipe) {
+                                $pipeOffset = $i;
+
+                                break;
+                            }
+                        }
+
+                        if (!$pipeOffset) {
+                            break;
+                        }
+
+                        $line = fread($pipe, 8192);
+
+                        if ($line === '' || $line === false) {
+                            fclose($pipes[$pipeOffset]);
+
+                            unset($pipes[$pipeOffset]);
+                        } elseif ($pipeOffset === 1) {
+                            $stdout .= $line;
+                        } else {
+                            $stderr .= $line;
+                        }
+                    }
+
+                    if (empty($pipes)) {
+                        break;
+                    }
+                }
+            }
+        } else {
+            if (isset($pipes[1])) {
+                $stdout = stream_get_contents($pipes[1]);
+
+                fclose($pipes[1]);
+            }
+
+            if (isset($pipes[2])) {
+                $stderr = stream_get_contents($pipes[2]);
+
+                fclose($pipes[2]);
+            }
+        }
+
+        if (isset($handles[1])) {
+            rewind($handles[1]);
+
+            $stdout = stream_get_contents($handles[1]);
+
+            fclose($handles[1]);
+        }
+
+        if (isset($handles[2])) {
+            rewind($handles[2]);
+
+            $stderr = stream_get_contents($handles[2]);
+
+            fclose($handles[2]);
+        }
+
+        proc_close($process);
+
+        $this->cleanup();
+
+        return ['stdout' => $stdout, 'stderr' => $stderr];
+    }
+
+    /**
+     * @param resource $pipe
+     */
+    protected function process($pipe, string $job): void
+    {
+        fwrite($pipe, $job);
+    }
+
+    protected function cleanup(): void
+    {
+        if ($this->tempFile) {
+            unlink($this->tempFile);
+        }
+    }
+
+    protected function useTemporaryFile(): bool
+    {
+        return false;
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Util/PHP/Template/PhptTestCase.tpl b/vendor/phpunit/phpunit/src/Util/PHP/Template/PhptTestCase.tpl
new file mode 100644
index 0000000000000000000000000000000000000000..f23a0d1ae56d2432b1f5d53c3d69d180b65cb605
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Util/PHP/Template/PhptTestCase.tpl
@@ -0,0 +1,57 @@
+<?php
+use SebastianBergmann\CodeCoverage\CodeCoverage;
+use SebastianBergmann\CodeCoverage\Driver\Selector;
+use SebastianBergmann\CodeCoverage\Filter;
+
+$composerAutoload = {composerAutoload};
+$phar             = {phar};
+
+ob_start();
+
+$GLOBALS['__PHPUNIT_ISOLATION_EXCLUDE_LIST'][] = '{job}';
+
+if ($composerAutoload) {
+    require_once $composerAutoload;
+
+    define('PHPUNIT_COMPOSER_INSTALL', $composerAutoload);
+} else if ($phar) {
+    require $phar;
+}
+
+{globals}
+$coverage = null;
+
+if (isset($GLOBALS['__PHPUNIT_BOOTSTRAP'])) {
+    require_once $GLOBALS['__PHPUNIT_BOOTSTRAP'];
+}
+
+if (class_exists('SebastianBergmann\CodeCoverage\CodeCoverage')) {
+    $filter = new Filter;
+
+    $coverage = new CodeCoverage(
+        (new Selector)->{driverMethod}($filter),
+        $filter
+    );
+
+    if ({codeCoverageCacheDirectory}) {
+        $coverage->cacheStaticAnalysis({codeCoverageCacheDirectory});
+    }
+
+    $coverage->start(__FILE__);
+}
+
+register_shutdown_function(
+    function() use ($coverage) {
+        $output = null;
+
+        if ($coverage) {
+            $output = $coverage->stop();
+        }
+
+        file_put_contents('{coverageFile}', serialize($output));
+    }
+);
+
+ob_end_clean();
+
+require '{job}';
diff --git a/vendor/phpunit/phpunit/src/Util/PHP/Template/TestCaseClass.tpl b/vendor/phpunit/phpunit/src/Util/PHP/Template/TestCaseClass.tpl
new file mode 100644
index 0000000000000000000000000000000000000000..95035e50521770ba6b2e68b979140335cc6a6a74
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Util/PHP/Template/TestCaseClass.tpl
@@ -0,0 +1,119 @@
+<?php
+use SebastianBergmann\CodeCoverage\CodeCoverage;
+use SebastianBergmann\CodeCoverage\Driver\Selector;
+use PHPUnit\TextUI\XmlConfiguration\Loader;
+use PHPUnit\TextUI\XmlConfiguration\PhpHandler;
+
+if (!defined('STDOUT')) {
+    // php://stdout does not obey output buffering. Any output would break
+    // unserialization of child process results in the parent process.
+    define('STDOUT', fopen('php://temp', 'w+b'));
+    define('STDERR', fopen('php://stderr', 'wb'));
+}
+
+{iniSettings}
+ini_set('display_errors', 'stderr');
+set_include_path('{include_path}');
+
+$composerAutoload = {composerAutoload};
+$phar             = {phar};
+
+ob_start();
+
+if ($composerAutoload) {
+    require_once $composerAutoload;
+    define('PHPUNIT_COMPOSER_INSTALL', $composerAutoload);
+} else if ($phar) {
+    require $phar;
+}
+
+function __phpunit_run_isolated_test()
+{
+    if (!class_exists('{className}')) {
+        require_once '{filename}';
+    }
+
+    $result = new PHPUnit\Framework\TestResult;
+
+    if ({collectCodeCoverageInformation}) {
+        $filter = unserialize('{codeCoverageFilter}');
+
+        $codeCoverage = new CodeCoverage(
+            (new Selector)->{driverMethod}($filter),
+            $filter
+        );
+
+        if ({cachesStaticAnalysis}) {
+            $codeCoverage->cacheStaticAnalysis(unserialize('{codeCoverageCacheDirectory}'));
+        }
+
+        $result->setCodeCoverage($codeCoverage);
+    }
+
+    $result->beStrictAboutTestsThatDoNotTestAnything({isStrictAboutTestsThatDoNotTestAnything});
+    $result->beStrictAboutOutputDuringTests({isStrictAboutOutputDuringTests});
+    $result->enforceTimeLimit({enforcesTimeLimit});
+    $result->beStrictAboutTodoAnnotatedTests({isStrictAboutTodoAnnotatedTests});
+    $result->beStrictAboutResourceUsageDuringSmallTests({isStrictAboutResourceUsageDuringSmallTests});
+
+    $test = new {className}('{name}', unserialize('{data}'), '{dataName}');
+    $test->setDependencyInput(unserialize('{dependencyInput}'));
+    $test->setInIsolation(TRUE);
+
+    ob_end_clean();
+    $test->run($result);
+    $output = '';
+    if (!$test->hasExpectationOnOutput()) {
+        $output = $test->getActualOutput();
+    }
+
+    ini_set('xdebug.scream', '0');
+    @rewind(STDOUT); /* @ as not every STDOUT target stream is rewindable */
+    if ($stdout = @stream_get_contents(STDOUT)) {
+        $output = $stdout . $output;
+        $streamMetaData = stream_get_meta_data(STDOUT);
+        if (!empty($streamMetaData['stream_type']) && 'STDIO' === $streamMetaData['stream_type']) {
+            @ftruncate(STDOUT, 0);
+            @rewind(STDOUT);
+        }
+    }
+
+    print serialize(
+      [
+        'testResult'    => $test->getResult(),
+        'numAssertions' => $test->getNumAssertions(),
+        'result'        => $result,
+        'output'        => $output
+      ]
+    );
+}
+
+$configurationFilePath = '{configurationFilePath}';
+
+if ('' !== $configurationFilePath) {
+    $configuration = (new Loader)->load($configurationFilePath);
+
+    (new PhpHandler)->handle($configuration->php());
+
+    unset($configuration);
+}
+
+function __phpunit_error_handler($errno, $errstr, $errfile, $errline)
+{
+   return true;
+}
+
+set_error_handler('__phpunit_error_handler');
+
+{constants}
+{included_files}
+{globals}
+
+restore_error_handler();
+
+if (isset($GLOBALS['__PHPUNIT_BOOTSTRAP'])) {
+    require_once $GLOBALS['__PHPUNIT_BOOTSTRAP'];
+    unset($GLOBALS['__PHPUNIT_BOOTSTRAP']);
+}
+
+__phpunit_run_isolated_test();
diff --git a/vendor/phpunit/phpunit/src/Util/PHP/Template/TestCaseMethod.tpl b/vendor/phpunit/phpunit/src/Util/PHP/Template/TestCaseMethod.tpl
new file mode 100644
index 0000000000000000000000000000000000000000..da824e7206e0a06d6fa817c3a3d0f8bc665c0532
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Util/PHP/Template/TestCaseMethod.tpl
@@ -0,0 +1,122 @@
+<?php
+use PHPUnit\Framework\TestCase;
+use SebastianBergmann\CodeCoverage\CodeCoverage;
+use SebastianBergmann\CodeCoverage\Driver\Selector;
+use PHPUnit\TextUI\XmlConfiguration\Loader;
+use PHPUnit\TextUI\XmlConfiguration\PhpHandler;
+
+if (!defined('STDOUT')) {
+    // php://stdout does not obey output buffering. Any output would break
+    // unserialization of child process results in the parent process.
+    define('STDOUT', fopen('php://temp', 'w+b'));
+    define('STDERR', fopen('php://stderr', 'wb'));
+}
+
+{iniSettings}
+ini_set('display_errors', 'stderr');
+set_include_path('{include_path}');
+
+$composerAutoload = {composerAutoload};
+$phar             = {phar};
+
+ob_start();
+
+if ($composerAutoload) {
+    require_once $composerAutoload;
+    define('PHPUNIT_COMPOSER_INSTALL', $composerAutoload);
+} else if ($phar) {
+    require $phar;
+}
+
+function __phpunit_run_isolated_test()
+{
+    if (!class_exists('{className}')) {
+        require_once '{filename}';
+    }
+
+    $result = new PHPUnit\Framework\TestResult;
+
+    if ({collectCodeCoverageInformation}) {
+        $filter = unserialize('{codeCoverageFilter}');
+
+        $codeCoverage = new CodeCoverage(
+            (new Selector)->{driverMethod}($filter),
+            $filter
+        );
+
+        if ({cachesStaticAnalysis}) {
+            $codeCoverage->cacheStaticAnalysis(unserialize('{codeCoverageCacheDirectory}'));
+        }
+
+        $result->setCodeCoverage($codeCoverage);
+    }
+
+    $result->beStrictAboutTestsThatDoNotTestAnything({isStrictAboutTestsThatDoNotTestAnything});
+    $result->beStrictAboutOutputDuringTests({isStrictAboutOutputDuringTests});
+    $result->enforceTimeLimit({enforcesTimeLimit});
+    $result->beStrictAboutTodoAnnotatedTests({isStrictAboutTodoAnnotatedTests});
+    $result->beStrictAboutResourceUsageDuringSmallTests({isStrictAboutResourceUsageDuringSmallTests});
+
+    $test = new {className}('{methodName}', unserialize('{data}'), '{dataName}');
+    \assert($test instanceof TestCase);
+
+    $test->setDependencyInput(unserialize('{dependencyInput}'));
+    $test->setInIsolation(true);
+
+    ob_end_clean();
+    $test->run($result);
+    $output = '';
+    if (!$test->hasExpectationOnOutput()) {
+        $output = $test->getActualOutput();
+    }
+
+    ini_set('xdebug.scream', '0');
+    @rewind(STDOUT); /* @ as not every STDOUT target stream is rewindable */
+    if ($stdout = @stream_get_contents(STDOUT)) {
+        $output = $stdout . $output;
+        $streamMetaData = stream_get_meta_data(STDOUT);
+        if (!empty($streamMetaData['stream_type']) && 'STDIO' === $streamMetaData['stream_type']) {
+            @ftruncate(STDOUT, 0);
+            @rewind(STDOUT);
+        }
+    }
+
+    print serialize(
+      [
+        'testResult'    => $test->getResult(),
+        'numAssertions' => $test->getNumAssertions(),
+        'result'        => $result,
+        'output'        => $output
+      ]
+    );
+}
+
+$configurationFilePath = '{configurationFilePath}';
+
+if ('' !== $configurationFilePath) {
+    $configuration = (new Loader)->load($configurationFilePath);
+
+    (new PhpHandler)->handle($configuration->php());
+
+    unset($configuration);
+}
+
+function __phpunit_error_handler($errno, $errstr, $errfile, $errline)
+{
+   return true;
+}
+
+set_error_handler('__phpunit_error_handler');
+
+{constants}
+{included_files}
+{globals}
+
+restore_error_handler();
+
+if (isset($GLOBALS['__PHPUNIT_BOOTSTRAP'])) {
+    require_once $GLOBALS['__PHPUNIT_BOOTSTRAP'];
+    unset($GLOBALS['__PHPUNIT_BOOTSTRAP']);
+}
+
+__phpunit_run_isolated_test();
diff --git a/vendor/phpunit/phpunit/src/Util/PHP/WindowsPhpProcess.php b/vendor/phpunit/phpunit/src/Util/PHP/WindowsPhpProcess.php
new file mode 100644
index 0000000000000000000000000000000000000000..9ef9255567ff3be2c1b3bafc2f1c376cb9449419
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Util/PHP/WindowsPhpProcess.php
@@ -0,0 +1,52 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Util\PHP;
+
+use const PHP_MAJOR_VERSION;
+use function tmpfile;
+use PHPUnit\Framework\Exception;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ *
+ * @see https://bugs.php.net/bug.php?id=51800
+ */
+final class WindowsPhpProcess extends DefaultPhpProcess
+{
+    public function getCommand(array $settings, string $file = null): string
+    {
+        if (PHP_MAJOR_VERSION < 8) {
+            return '"' . parent::getCommand($settings, $file) . '"';
+        }
+
+        return parent::getCommand($settings, $file);
+    }
+
+    /**
+     * @throws Exception
+     */
+    protected function getHandles(): array
+    {
+        if (false === $stdout_handle = tmpfile()) {
+            throw new Exception(
+                'A temporary file could not be created; verify that your TEMP environment variable is writable'
+            );
+        }
+
+        return [
+            1 => $stdout_handle,
+        ];
+    }
+
+    protected function useTemporaryFile(): bool
+    {
+        return true;
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Util/Printer.php b/vendor/phpunit/phpunit/src/Util/Printer.php
new file mode 100644
index 0000000000000000000000000000000000000000..77b5745ad9dd3eb7d0d0e4a87d99e20965350125
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Util/Printer.php
@@ -0,0 +1,116 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Util;
+
+use const ENT_COMPAT;
+use const ENT_SUBSTITUTE;
+use const PHP_SAPI;
+use function assert;
+use function count;
+use function dirname;
+use function explode;
+use function fclose;
+use function fopen;
+use function fsockopen;
+use function fwrite;
+use function htmlspecialchars;
+use function is_resource;
+use function is_string;
+use function sprintf;
+use function str_replace;
+use function strncmp;
+use function strpos;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+class Printer
+{
+    /**
+     * @psalm-var closed-resource|resource
+     */
+    private $stream;
+
+    /**
+     * @var bool
+     */
+    private $isPhpStream;
+
+    /**
+     * @param null|resource|string $out
+     *
+     * @throws Exception
+     */
+    public function __construct($out = null)
+    {
+        if (is_resource($out)) {
+            $this->stream = $out;
+
+            return;
+        }
+
+        if (!is_string($out)) {
+            return;
+        }
+
+        if (strpos($out, 'socket://') === 0) {
+            $tmp = explode(':', str_replace('socket://', '', $out));
+
+            if (count($tmp) !== 2) {
+                throw new Exception(
+                    sprintf(
+                        '"%s" does not match "socket://hostname:port" format',
+                        $out
+                    )
+                );
+            }
+
+            $this->stream = fsockopen($tmp[0], (int) $tmp[1]);
+
+            return;
+        }
+
+        if (strpos($out, 'php://') === false && !Filesystem::createDirectory(dirname($out))) {
+            throw new Exception(
+                sprintf(
+                    'Directory "%s" was not created',
+                    dirname($out)
+                )
+            );
+        }
+
+        $this->stream      = fopen($out, 'wb');
+        $this->isPhpStream = strncmp($out, 'php://', 6) !== 0;
+    }
+
+    public function write(string $buffer): void
+    {
+        if ($this->stream) {
+            assert(is_resource($this->stream));
+
+            fwrite($this->stream, $buffer);
+        } else {
+            if (PHP_SAPI !== 'cli' && PHP_SAPI !== 'phpdbg') {
+                $buffer = htmlspecialchars($buffer, ENT_COMPAT | ENT_SUBSTITUTE);
+            }
+
+            print $buffer;
+        }
+    }
+
+    public function flush(): void
+    {
+        if ($this->stream && $this->isPhpStream) {
+            assert(is_resource($this->stream));
+
+            fclose($this->stream);
+        }
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Util/RegularExpression.php b/vendor/phpunit/phpunit/src/Util/RegularExpression.php
new file mode 100644
index 0000000000000000000000000000000000000000..167b9215c2c43c5543d266941f36c9e7c16345cb
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Util/RegularExpression.php
@@ -0,0 +1,30 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Util;
+
+use function preg_match;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class RegularExpression
+{
+    /**
+     * @return false|int
+     */
+    public static function safeMatch(string $pattern, string $subject)
+    {
+        return ErrorHandler::invokeIgnoringWarnings(
+            static function () use ($pattern, $subject) {
+                return preg_match($pattern, $subject);
+            }
+        );
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Util/Test.php b/vendor/phpunit/phpunit/src/Util/Test.php
new file mode 100644
index 0000000000000000000000000000000000000000..0778f2f52d163621b6b2fc6fbd71b13fc9585baa
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Util/Test.php
@@ -0,0 +1,784 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Util;
+
+use const PHP_OS;
+use const PHP_VERSION;
+use function addcslashes;
+use function array_flip;
+use function array_key_exists;
+use function array_merge;
+use function array_unique;
+use function array_unshift;
+use function class_exists;
+use function count;
+use function explode;
+use function extension_loaded;
+use function function_exists;
+use function get_class;
+use function ini_get;
+use function interface_exists;
+use function is_array;
+use function is_int;
+use function method_exists;
+use function phpversion;
+use function preg_match;
+use function preg_replace;
+use function sprintf;
+use function strncmp;
+use function strpos;
+use function strtolower;
+use function trim;
+use function version_compare;
+use PHPUnit\Framework\Assert;
+use PHPUnit\Framework\CodeCoverageException;
+use PHPUnit\Framework\ExecutionOrderDependency;
+use PHPUnit\Framework\InvalidCoversTargetException;
+use PHPUnit\Framework\SelfDescribing;
+use PHPUnit\Framework\TestCase;
+use PHPUnit\Framework\Warning;
+use PHPUnit\Runner\Version;
+use PHPUnit\Util\Annotation\Registry;
+use ReflectionClass;
+use ReflectionException;
+use ReflectionMethod;
+use SebastianBergmann\CodeUnit\CodeUnitCollection;
+use SebastianBergmann\CodeUnit\InvalidCodeUnitException;
+use SebastianBergmann\CodeUnit\Mapper;
+use SebastianBergmann\Environment\OperatingSystem;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class Test
+{
+    /**
+     * @var int
+     */
+    public const UNKNOWN = -1;
+
+    /**
+     * @var int
+     */
+    public const SMALL = 0;
+
+    /**
+     * @var int
+     */
+    public const MEDIUM = 1;
+
+    /**
+     * @var int
+     */
+    public const LARGE = 2;
+
+    /**
+     * @var array
+     */
+    private static $hookMethods = [];
+
+    /**
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     */
+    public static function describe(\PHPUnit\Framework\Test $test): array
+    {
+        if ($test instanceof TestCase) {
+            return [get_class($test), $test->getName()];
+        }
+
+        if ($test instanceof SelfDescribing) {
+            return ['', $test->toString()];
+        }
+
+        return ['', get_class($test)];
+    }
+
+    public static function describeAsString(\PHPUnit\Framework\Test $test): string
+    {
+        if ($test instanceof SelfDescribing) {
+            return $test->toString();
+        }
+
+        return get_class($test);
+    }
+
+    /**
+     * @throws CodeCoverageException
+     *
+     * @return array|bool
+     * @psalm-param class-string $className
+     */
+    public static function getLinesToBeCovered(string $className, string $methodName)
+    {
+        $annotations = self::parseTestMethodAnnotations(
+            $className,
+            $methodName
+        );
+
+        if (!self::shouldCoversAnnotationBeUsed($annotations)) {
+            return false;
+        }
+
+        return self::getLinesToBeCoveredOrUsed($className, $methodName, 'covers');
+    }
+
+    /**
+     * Returns lines of code specified with the @uses annotation.
+     *
+     * @throws CodeCoverageException
+     * @psalm-param class-string $className
+     */
+    public static function getLinesToBeUsed(string $className, string $methodName): array
+    {
+        return self::getLinesToBeCoveredOrUsed($className, $methodName, 'uses');
+    }
+
+    public static function requiresCodeCoverageDataCollection(TestCase $test): bool
+    {
+        $annotations = self::parseTestMethodAnnotations(
+            get_class($test),
+            $test->getName(false)
+        );
+
+        // If there is no @covers annotation but a @coversNothing annotation on
+        // the test method then code coverage data does not need to be collected
+        if (isset($annotations['method']['coversNothing'])) {
+            return false;
+        }
+
+        // If there is at least one @covers annotation then
+        // code coverage data needs to be collected
+        if (isset($annotations['method']['covers'])) {
+            return true;
+        }
+
+        // If there is no @covers annotation but a @coversNothing annotation
+        // then code coverage data does not need to be collected
+        if (isset($annotations['class']['coversNothing'])) {
+            return false;
+        }
+
+        // If there is no @coversNothing annotation then
+        // code coverage data may be collected
+        return true;
+    }
+
+    /**
+     * @throws Exception
+     * @psalm-param class-string $className
+     */
+    public static function getRequirements(string $className, string $methodName): array
+    {
+        return self::mergeArraysRecursively(
+            Registry::getInstance()->forClassName($className)->requirements(),
+            Registry::getInstance()->forMethod($className, $methodName)->requirements()
+        );
+    }
+
+    /**
+     * Returns the missing requirements for a test.
+     *
+     * @throws Exception
+     * @throws Warning
+     * @psalm-param class-string $className
+     */
+    public static function getMissingRequirements(string $className, string $methodName): array
+    {
+        $required = self::getRequirements($className, $methodName);
+        $missing  = [];
+        $hint     = null;
+
+        if (!empty($required['PHP'])) {
+            $operator = new VersionComparisonOperator(empty($required['PHP']['operator']) ? '>=' : $required['PHP']['operator']);
+
+            if (!version_compare(PHP_VERSION, $required['PHP']['version'], $operator->asString())) {
+                $missing[] = sprintf('PHP %s %s is required.', $operator->asString(), $required['PHP']['version']);
+                $hint      = 'PHP';
+            }
+        } elseif (!empty($required['PHP_constraint'])) {
+            $version = new \PharIo\Version\Version(self::sanitizeVersionNumber(PHP_VERSION));
+
+            if (!$required['PHP_constraint']['constraint']->complies($version)) {
+                $missing[] = sprintf(
+                    'PHP version does not match the required constraint %s.',
+                    $required['PHP_constraint']['constraint']->asString()
+                );
+
+                $hint = 'PHP_constraint';
+            }
+        }
+
+        if (!empty($required['PHPUnit'])) {
+            $phpunitVersion = Version::id();
+
+            $operator = new VersionComparisonOperator(empty($required['PHPUnit']['operator']) ? '>=' : $required['PHPUnit']['operator']);
+
+            if (!version_compare($phpunitVersion, $required['PHPUnit']['version'], $operator->asString())) {
+                $missing[] = sprintf('PHPUnit %s %s is required.', $operator->asString(), $required['PHPUnit']['version']);
+                $hint      = $hint ?? 'PHPUnit';
+            }
+        } elseif (!empty($required['PHPUnit_constraint'])) {
+            $phpunitVersion = new \PharIo\Version\Version(self::sanitizeVersionNumber(Version::id()));
+
+            if (!$required['PHPUnit_constraint']['constraint']->complies($phpunitVersion)) {
+                $missing[] = sprintf(
+                    'PHPUnit version does not match the required constraint %s.',
+                    $required['PHPUnit_constraint']['constraint']->asString()
+                );
+
+                $hint = $hint ?? 'PHPUnit_constraint';
+            }
+        }
+
+        if (!empty($required['OSFAMILY']) && $required['OSFAMILY'] !== (new OperatingSystem)->getFamily()) {
+            $missing[] = sprintf('Operating system %s is required.', $required['OSFAMILY']);
+            $hint      = $hint ?? 'OSFAMILY';
+        }
+
+        if (!empty($required['OS'])) {
+            $requiredOsPattern = sprintf('/%s/i', addcslashes($required['OS'], '/'));
+
+            if (!preg_match($requiredOsPattern, PHP_OS)) {
+                $missing[] = sprintf('Operating system matching %s is required.', $requiredOsPattern);
+                $hint      = $hint ?? 'OS';
+            }
+        }
+
+        if (!empty($required['functions'])) {
+            foreach ($required['functions'] as $function) {
+                $pieces = explode('::', $function);
+
+                if (count($pieces) === 2 && class_exists($pieces[0]) && method_exists($pieces[0], $pieces[1])) {
+                    continue;
+                }
+
+                if (function_exists($function)) {
+                    continue;
+                }
+
+                $missing[] = sprintf('Function %s is required.', $function);
+                $hint      = $hint ?? 'function_' . $function;
+            }
+        }
+
+        if (!empty($required['setting'])) {
+            foreach ($required['setting'] as $setting => $value) {
+                if (ini_get($setting) !== $value) {
+                    $missing[] = sprintf('Setting "%s" must be "%s".', $setting, $value);
+                    $hint      = $hint ?? '__SETTING_' . $setting;
+                }
+            }
+        }
+
+        if (!empty($required['extensions'])) {
+            foreach ($required['extensions'] as $extension) {
+                if (isset($required['extension_versions'][$extension])) {
+                    continue;
+                }
+
+                if (!extension_loaded($extension)) {
+                    $missing[] = sprintf('Extension %s is required.', $extension);
+                    $hint      = $hint ?? 'extension_' . $extension;
+                }
+            }
+        }
+
+        if (!empty($required['extension_versions'])) {
+            foreach ($required['extension_versions'] as $extension => $req) {
+                $actualVersion = phpversion($extension);
+
+                $operator = new VersionComparisonOperator(empty($req['operator']) ? '>=' : $req['operator']);
+
+                if ($actualVersion === false || !version_compare($actualVersion, $req['version'], $operator->asString())) {
+                    $missing[] = sprintf('Extension %s %s %s is required.', $extension, $operator->asString(), $req['version']);
+                    $hint      = $hint ?? 'extension_' . $extension;
+                }
+            }
+        }
+
+        if ($hint && isset($required['__OFFSET'])) {
+            array_unshift($missing, '__OFFSET_FILE=' . $required['__OFFSET']['__FILE']);
+            array_unshift($missing, '__OFFSET_LINE=' . ($required['__OFFSET'][$hint] ?? 1));
+        }
+
+        return $missing;
+    }
+
+    /**
+     * Returns the provided data for a method.
+     *
+     * @throws Exception
+     * @psalm-param class-string $className
+     */
+    public static function getProvidedData(string $className, string $methodName): ?array
+    {
+        return Registry::getInstance()->forMethod($className, $methodName)->getProvidedData();
+    }
+
+    /**
+     * @psalm-param class-string $className
+     */
+    public static function parseTestMethodAnnotations(string $className, ?string $methodName = ''): array
+    {
+        $registry = Registry::getInstance();
+
+        if ($methodName !== null) {
+            try {
+                return [
+                    'method' => $registry->forMethod($className, $methodName)->symbolAnnotations(),
+                    'class'  => $registry->forClassName($className)->symbolAnnotations(),
+                ];
+            } catch (Exception $methodNotFound) {
+                // ignored
+            }
+        }
+
+        return [
+            'method' => null,
+            'class'  => $registry->forClassName($className)->symbolAnnotations(),
+        ];
+    }
+
+    /**
+     * @psalm-param class-string $className
+     */
+    public static function getInlineAnnotations(string $className, string $methodName): array
+    {
+        return Registry::getInstance()->forMethod($className, $methodName)->getInlineAnnotations();
+    }
+
+    /** @psalm-param class-string $className */
+    public static function getBackupSettings(string $className, string $methodName): array
+    {
+        return [
+            'backupGlobals' => self::getBooleanAnnotationSetting(
+                $className,
+                $methodName,
+                'backupGlobals'
+            ),
+            'backupStaticAttributes' => self::getBooleanAnnotationSetting(
+                $className,
+                $methodName,
+                'backupStaticAttributes'
+            ),
+        ];
+    }
+
+    /**
+     * @psalm-param class-string $className
+     *
+     * @return ExecutionOrderDependency[]
+     */
+    public static function getDependencies(string $className, string $methodName): array
+    {
+        $annotations = self::parseTestMethodAnnotations(
+            $className,
+            $methodName
+        );
+
+        $dependsAnnotations = $annotations['class']['depends'] ?? [];
+
+        if (isset($annotations['method']['depends'])) {
+            $dependsAnnotations = array_merge(
+                $dependsAnnotations,
+                $annotations['method']['depends']
+            );
+        }
+
+        // Normalize dependency name to className::methodName
+        $dependencies = [];
+
+        foreach ($dependsAnnotations as $value) {
+            $dependencies[] = ExecutionOrderDependency::createFromDependsAnnotation($className, $value);
+        }
+
+        return array_unique($dependencies);
+    }
+
+    /** @psalm-param class-string $className */
+    public static function getGroups(string $className, ?string $methodName = ''): array
+    {
+        $annotations = self::parseTestMethodAnnotations(
+            $className,
+            $methodName
+        );
+
+        $groups = [];
+
+        if (isset($annotations['method']['author'])) {
+            $groups[] = $annotations['method']['author'];
+        } elseif (isset($annotations['class']['author'])) {
+            $groups[] = $annotations['class']['author'];
+        }
+
+        if (isset($annotations['class']['group'])) {
+            $groups[] = $annotations['class']['group'];
+        }
+
+        if (isset($annotations['method']['group'])) {
+            $groups[] = $annotations['method']['group'];
+        }
+
+        if (isset($annotations['class']['ticket'])) {
+            $groups[] = $annotations['class']['ticket'];
+        }
+
+        if (isset($annotations['method']['ticket'])) {
+            $groups[] = $annotations['method']['ticket'];
+        }
+
+        foreach (['method', 'class'] as $element) {
+            foreach (['small', 'medium', 'large'] as $size) {
+                if (isset($annotations[$element][$size])) {
+                    $groups[] = [$size];
+
+                    break 2;
+                }
+            }
+        }
+
+        foreach (['method', 'class'] as $element) {
+            if (isset($annotations[$element]['covers'])) {
+                foreach ($annotations[$element]['covers'] as $coversTarget) {
+                    $groups[] = ['__phpunit_covers_' . self::canonicalizeName($coversTarget)];
+                }
+            }
+
+            if (isset($annotations[$element]['uses'])) {
+                foreach ($annotations[$element]['uses'] as $usesTarget) {
+                    $groups[] = ['__phpunit_uses_' . self::canonicalizeName($usesTarget)];
+                }
+            }
+        }
+
+        return array_unique(array_merge([], ...$groups));
+    }
+
+    /** @psalm-param class-string $className */
+    public static function getSize(string $className, ?string $methodName): int
+    {
+        $groups = array_flip(self::getGroups($className, $methodName));
+
+        if (isset($groups['large'])) {
+            return self::LARGE;
+        }
+
+        if (isset($groups['medium'])) {
+            return self::MEDIUM;
+        }
+
+        if (isset($groups['small'])) {
+            return self::SMALL;
+        }
+
+        return self::UNKNOWN;
+    }
+
+    /** @psalm-param class-string $className */
+    public static function getProcessIsolationSettings(string $className, string $methodName): bool
+    {
+        $annotations = self::parseTestMethodAnnotations(
+            $className,
+            $methodName
+        );
+
+        return isset($annotations['class']['runTestsInSeparateProcesses']) || isset($annotations['method']['runInSeparateProcess']);
+    }
+
+    /** @psalm-param class-string $className */
+    public static function getClassProcessIsolationSettings(string $className, string $methodName): bool
+    {
+        $annotations = self::parseTestMethodAnnotations(
+            $className,
+            $methodName
+        );
+
+        return isset($annotations['class']['runClassInSeparateProcess']);
+    }
+
+    /** @psalm-param class-string $className */
+    public static function getPreserveGlobalStateSettings(string $className, string $methodName): ?bool
+    {
+        return self::getBooleanAnnotationSetting(
+            $className,
+            $methodName,
+            'preserveGlobalState'
+        );
+    }
+
+    /** @psalm-param class-string $className */
+    public static function getHookMethods(string $className): array
+    {
+        if (!class_exists($className, false)) {
+            return self::emptyHookMethodsArray();
+        }
+
+        if (!isset(self::$hookMethods[$className])) {
+            self::$hookMethods[$className] = self::emptyHookMethodsArray();
+
+            try {
+                foreach ((new ReflectionClass($className))->getMethods() as $method) {
+                    if ($method->getDeclaringClass()->getName() === Assert::class) {
+                        continue;
+                    }
+
+                    if ($method->getDeclaringClass()->getName() === TestCase::class) {
+                        continue;
+                    }
+
+                    $docBlock = Registry::getInstance()->forMethod($className, $method->getName());
+
+                    if ($method->isStatic()) {
+                        if ($docBlock->isHookToBeExecutedBeforeClass()) {
+                            array_unshift(
+                                self::$hookMethods[$className]['beforeClass'],
+                                $method->getName()
+                            );
+                        }
+
+                        if ($docBlock->isHookToBeExecutedAfterClass()) {
+                            self::$hookMethods[$className]['afterClass'][] = $method->getName();
+                        }
+                    }
+
+                    if ($docBlock->isToBeExecutedBeforeTest()) {
+                        array_unshift(
+                            self::$hookMethods[$className]['before'],
+                            $method->getName()
+                        );
+                    }
+
+                    if ($docBlock->isToBeExecutedAsPreCondition()) {
+                        array_unshift(
+                            self::$hookMethods[$className]['preCondition'],
+                            $method->getName()
+                        );
+                    }
+
+                    if ($docBlock->isToBeExecutedAsPostCondition()) {
+                        self::$hookMethods[$className]['postCondition'][] = $method->getName();
+                    }
+
+                    if ($docBlock->isToBeExecutedAfterTest()) {
+                        self::$hookMethods[$className]['after'][] = $method->getName();
+                    }
+                }
+            } catch (ReflectionException $e) {
+            }
+        }
+
+        return self::$hookMethods[$className];
+    }
+
+    public static function isTestMethod(ReflectionMethod $method): bool
+    {
+        if (!$method->isPublic()) {
+            return false;
+        }
+
+        if (strpos($method->getName(), 'test') === 0) {
+            return true;
+        }
+
+        return array_key_exists(
+            'test',
+            Registry::getInstance()->forMethod(
+                $method->getDeclaringClass()->getName(),
+                $method->getName()
+            )
+            ->symbolAnnotations()
+        );
+    }
+
+    /**
+     * @throws CodeCoverageException
+     * @psalm-param class-string $className
+     */
+    private static function getLinesToBeCoveredOrUsed(string $className, string $methodName, string $mode): array
+    {
+        $annotations = self::parseTestMethodAnnotations(
+            $className,
+            $methodName
+        );
+
+        $classShortcut = null;
+
+        if (!empty($annotations['class'][$mode . 'DefaultClass'])) {
+            if (count($annotations['class'][$mode . 'DefaultClass']) > 1) {
+                throw new CodeCoverageException(
+                    sprintf(
+                        'More than one @%sClass annotation in class or interface "%s".',
+                        $mode,
+                        $className
+                    )
+                );
+            }
+
+            $classShortcut = $annotations['class'][$mode . 'DefaultClass'][0];
+        }
+
+        $list = $annotations['class'][$mode] ?? [];
+
+        if (isset($annotations['method'][$mode])) {
+            $list = array_merge($list, $annotations['method'][$mode]);
+        }
+
+        $codeUnits = CodeUnitCollection::fromArray([]);
+        $mapper    = new Mapper;
+
+        foreach (array_unique($list) as $element) {
+            if ($classShortcut && strncmp($element, '::', 2) === 0) {
+                $element = $classShortcut . $element;
+            }
+
+            $element = preg_replace('/[\s()]+$/', '', $element);
+            $element = explode(' ', $element);
+            $element = $element[0];
+
+            if ($mode === 'covers' && interface_exists($element)) {
+                throw new InvalidCoversTargetException(
+                    sprintf(
+                        'Trying to @cover interface "%s".',
+                        $element
+                    )
+                );
+            }
+
+            try {
+                $codeUnits = $codeUnits->mergeWith($mapper->stringToCodeUnits($element));
+            } catch (InvalidCodeUnitException $e) {
+                throw new InvalidCoversTargetException(
+                    sprintf(
+                        '"@%s %s" is invalid',
+                        $mode,
+                        $element
+                    ),
+                    (int) $e->getCode(),
+                    $e
+                );
+            }
+        }
+
+        return $mapper->codeUnitsToSourceLines($codeUnits);
+    }
+
+    private static function emptyHookMethodsArray(): array
+    {
+        return [
+            'beforeClass'   => ['setUpBeforeClass'],
+            'before'        => ['setUp'],
+            'preCondition'  => ['assertPreConditions'],
+            'postCondition' => ['assertPostConditions'],
+            'after'         => ['tearDown'],
+            'afterClass'    => ['tearDownAfterClass'],
+        ];
+    }
+
+    /** @psalm-param class-string $className */
+    private static function getBooleanAnnotationSetting(string $className, ?string $methodName, string $settingName): ?bool
+    {
+        $annotations = self::parseTestMethodAnnotations(
+            $className,
+            $methodName
+        );
+
+        if (isset($annotations['method'][$settingName])) {
+            if ($annotations['method'][$settingName][0] === 'enabled') {
+                return true;
+            }
+
+            if ($annotations['method'][$settingName][0] === 'disabled') {
+                return false;
+            }
+        }
+
+        if (isset($annotations['class'][$settingName])) {
+            if ($annotations['class'][$settingName][0] === 'enabled') {
+                return true;
+            }
+
+            if ($annotations['class'][$settingName][0] === 'disabled') {
+                return false;
+            }
+        }
+
+        return null;
+    }
+
+    /**
+     * Trims any extensions from version string that follows after
+     * the <major>.<minor>[.<patch>] format.
+     */
+    private static function sanitizeVersionNumber(string $version)
+    {
+        return preg_replace(
+            '/^(\d+\.\d+(?:.\d+)?).*$/',
+            '$1',
+            $version
+        );
+    }
+
+    private static function shouldCoversAnnotationBeUsed(array $annotations): bool
+    {
+        if (isset($annotations['method']['coversNothing'])) {
+            return false;
+        }
+
+        if (isset($annotations['method']['covers'])) {
+            return true;
+        }
+
+        if (isset($annotations['class']['coversNothing'])) {
+            return false;
+        }
+
+        return true;
+    }
+
+    /**
+     * Merge two arrays together.
+     *
+     * If an integer key exists in both arrays and preserveNumericKeys is false, the value
+     * from the second array will be appended to the first array. If both values are arrays, they
+     * are merged together, else the value of the second array overwrites the one of the first array.
+     *
+     * This implementation is copied from https://github.com/zendframework/zend-stdlib/blob/76b653c5e99b40eccf5966e3122c90615134ae46/src/ArrayUtils.php
+     *
+     * Zend Framework (http://framework.zend.com/)
+     *
+     * @see      http://github.com/zendframework/zf2 for the canonical source repository
+     *
+     * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
+     * @license   http://framework.zend.com/license/new-bsd New BSD License
+     */
+    private static function mergeArraysRecursively(array $a, array $b): array
+    {
+        foreach ($b as $key => $value) {
+            if (array_key_exists($key, $a)) {
+                if (is_int($key)) {
+                    $a[] = $value;
+                } elseif (is_array($value) && is_array($a[$key])) {
+                    $a[$key] = self::mergeArraysRecursively($a[$key], $value);
+                } else {
+                    $a[$key] = $value;
+                }
+            } else {
+                $a[$key] = $value;
+            }
+        }
+
+        return $a;
+    }
+
+    private static function canonicalizeName(string $name): string
+    {
+        return strtolower(trim($name, '\\'));
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Util/TestDox/CliTestDoxPrinter.php b/vendor/phpunit/phpunit/src/Util/TestDox/CliTestDoxPrinter.php
new file mode 100644
index 0000000000000000000000000000000000000000..7c0fc11743e59f5e4d0691ef8bd7868989aeca78
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Util/TestDox/CliTestDoxPrinter.php
@@ -0,0 +1,380 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Util\TestDox;
+
+use const PHP_EOL;
+use function array_map;
+use function ceil;
+use function count;
+use function explode;
+use function get_class;
+use function implode;
+use function preg_match;
+use function sprintf;
+use function strlen;
+use function strpos;
+use function trim;
+use PHPUnit\Framework\Test;
+use PHPUnit\Framework\TestCase;
+use PHPUnit\Framework\TestResult;
+use PHPUnit\Runner\BaseTestRunner;
+use PHPUnit\Runner\PhptTestCase;
+use PHPUnit\Util\Color;
+use SebastianBergmann\Timer\ResourceUsageFormatter;
+use SebastianBergmann\Timer\Timer;
+use Throwable;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+class CliTestDoxPrinter extends TestDoxPrinter
+{
+    /**
+     * The default Testdox left margin for messages is a vertical line.
+     */
+    private const PREFIX_SIMPLE = [
+        'default' => '│',
+        'start'   => '│',
+        'message' => '│',
+        'diff'    => '│',
+        'trace'   => '│',
+        'last'    => '│',
+    ];
+
+    /**
+     * Colored Testdox use box-drawing for a more textured map of the message.
+     */
+    private const PREFIX_DECORATED = [
+        'default' => '│',
+        'start'   => '┐',
+        'message' => '├',
+        'diff'    => '┊',
+        'trace'   => '╵',
+        'last'    => 'â”´',
+    ];
+
+    private const SPINNER_ICONS = [
+        " \e[36m◐\e[0m running tests",
+        " \e[36mâ—“\e[0m running tests",
+        " \e[36mâ—‘\e[0m running tests",
+        " \e[36mâ—’\e[0m running tests",
+    ];
+
+    private const STATUS_STYLES = [
+        BaseTestRunner::STATUS_PASSED => [
+            'symbol' => '✔',
+            'color'  => 'fg-green',
+        ],
+        BaseTestRunner::STATUS_ERROR => [
+            'symbol'  => '✘',
+            'color'   => 'fg-yellow',
+            'message' => 'bg-yellow,fg-black',
+        ],
+        BaseTestRunner::STATUS_FAILURE => [
+            'symbol'  => '✘',
+            'color'   => 'fg-red',
+            'message' => 'bg-red,fg-white',
+        ],
+        BaseTestRunner::STATUS_SKIPPED => [
+            'symbol'  => '↩',
+            'color'   => 'fg-cyan',
+            'message' => 'fg-cyan',
+        ],
+        BaseTestRunner::STATUS_RISKY => [
+            'symbol'  => '☢',
+            'color'   => 'fg-yellow',
+            'message' => 'fg-yellow',
+        ],
+        BaseTestRunner::STATUS_INCOMPLETE => [
+            'symbol'  => '∅',
+            'color'   => 'fg-yellow',
+            'message' => 'fg-yellow',
+        ],
+        BaseTestRunner::STATUS_WARNING => [
+            'symbol'  => 'âš ',
+            'color'   => 'fg-yellow',
+            'message' => 'fg-yellow',
+        ],
+        BaseTestRunner::STATUS_UNKNOWN => [
+            'symbol'  => '?',
+            'color'   => 'fg-blue',
+            'message' => 'fg-white,bg-blue',
+        ],
+    ];
+
+    /**
+     * @var int[]
+     */
+    private $nonSuccessfulTestResults = [];
+
+    /**
+     * @var Timer
+     */
+    private $timer;
+
+    /**
+     * @param null|resource|string $out
+     * @param int|string           $numberOfColumns
+     *
+     * @throws \PHPUnit\Framework\Exception
+     */
+    public function __construct($out = null, bool $verbose = false, string $colors = self::COLOR_DEFAULT, bool $debug = false, $numberOfColumns = 80, bool $reverse = false)
+    {
+        parent::__construct($out, $verbose, $colors, $debug, $numberOfColumns, $reverse);
+
+        $this->timer = new Timer;
+
+        $this->timer->start();
+    }
+
+    public function printResult(TestResult $result): void
+    {
+        $this->printHeader($result);
+
+        $this->printNonSuccessfulTestsSummary($result->count());
+
+        $this->printFooter($result);
+    }
+
+    protected function printHeader(TestResult $result): void
+    {
+        $this->write("\n" . (new ResourceUsageFormatter)->resourceUsage($this->timer->stop()) . "\n\n");
+    }
+
+    protected function formatClassName(Test $test): string
+    {
+        if ($test instanceof TestCase) {
+            return $this->prettifier->prettifyTestClass(get_class($test));
+        }
+
+        return get_class($test);
+    }
+
+    /**
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     */
+    protected function registerTestResult(Test $test, ?Throwable $t, int $status, float $time, bool $verbose): void
+    {
+        if ($status !== BaseTestRunner::STATUS_PASSED) {
+            $this->nonSuccessfulTestResults[] = $this->testIndex;
+        }
+
+        parent::registerTestResult($test, $t, $status, $time, $verbose);
+    }
+
+    /**
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     */
+    protected function formatTestName(Test $test): string
+    {
+        if ($test instanceof TestCase) {
+            return $this->prettifier->prettifyTestCase($test);
+        }
+
+        return parent::formatTestName($test);
+    }
+
+    protected function writeTestResult(array $prevResult, array $result): void
+    {
+        // spacer line for new suite headers and after verbose messages
+        if ($prevResult['testName'] !== '' &&
+            (!empty($prevResult['message']) || $prevResult['className'] !== $result['className'])) {
+            $this->write(PHP_EOL);
+        }
+
+        // suite header
+        if ($prevResult['className'] !== $result['className']) {
+            $this->write($this->colorizeTextBox('underlined', $result['className']) . PHP_EOL);
+        }
+
+        // test result line
+        if ($this->colors && $result['className'] === PhptTestCase::class) {
+            $testName = Color::colorizePath($result['testName'], $prevResult['testName'], true);
+        } else {
+            $testName = $result['testMethod'];
+        }
+
+        $style = self::STATUS_STYLES[$result['status']];
+        $line  = sprintf(
+            ' %s %s%s' . PHP_EOL,
+            $this->colorizeTextBox($style['color'], $style['symbol']),
+            $testName,
+            $this->verbose ? ' ' . $this->formatRuntime($result['time'], $style['color']) : ''
+        );
+
+        $this->write($line);
+
+        // additional information when verbose
+        $this->write($result['message']);
+    }
+
+    protected function formatThrowable(Throwable $t, ?int $status = null): string
+    {
+        return trim(\PHPUnit\Framework\TestFailure::exceptionToString($t));
+    }
+
+    protected function colorizeMessageAndDiff(string $style, string $buffer): array
+    {
+        $lines      = $buffer ? array_map('\rtrim', explode(PHP_EOL, $buffer)) : [];
+        $message    = [];
+        $diff       = [];
+        $insideDiff = false;
+
+        foreach ($lines as $line) {
+            if ($line === '--- Expected') {
+                $insideDiff = true;
+            }
+
+            if (!$insideDiff) {
+                $message[] = $line;
+            } else {
+                if (strpos($line, '-') === 0) {
+                    $line = Color::colorize('fg-red', Color::visualizeWhitespace($line, true));
+                } elseif (strpos($line, '+') === 0) {
+                    $line = Color::colorize('fg-green', Color::visualizeWhitespace($line, true));
+                } elseif ($line === '@@ @@') {
+                    $line = Color::colorize('fg-cyan', $line);
+                }
+                $diff[] = $line;
+            }
+        }
+        $diff = implode(PHP_EOL, $diff);
+
+        if (!empty($message)) {
+            $message = $this->colorizeTextBox($style, implode(PHP_EOL, $message));
+        }
+
+        return [$message, $diff];
+    }
+
+    protected function formatStacktrace(Throwable $t): string
+    {
+        $trace = \PHPUnit\Util\Filter::getFilteredStacktrace($t);
+
+        if (!$this->colors) {
+            return $trace;
+        }
+
+        $lines    = [];
+        $prevPath = '';
+
+        foreach (explode(PHP_EOL, $trace) as $line) {
+            if (preg_match('/^(.*):(\d+)$/', $line, $matches)) {
+                $lines[] = Color::colorizePath($matches[1], $prevPath) .
+                    Color::dim(':') .
+                    Color::colorize('fg-blue', $matches[2]) .
+                    "\n";
+                $prevPath = $matches[1];
+            } else {
+                $lines[]  = $line;
+                $prevPath = '';
+            }
+        }
+
+        return implode('', $lines);
+    }
+
+    protected function formatTestResultMessage(Throwable $t, array $result, ?string $prefix = null): string
+    {
+        $message = $this->formatThrowable($t, $result['status']);
+        $diff    = '';
+
+        if (!($this->verbose || $result['verbose'])) {
+            return '';
+        }
+
+        if ($message && $this->colors) {
+            $style            = self::STATUS_STYLES[$result['status']]['message'] ?? '';
+            [$message, $diff] = $this->colorizeMessageAndDiff($style, $message);
+        }
+
+        if ($prefix === null || !$this->colors) {
+            $prefix = self::PREFIX_SIMPLE;
+        }
+
+        if ($this->colors) {
+            $color  = self::STATUS_STYLES[$result['status']]['color'] ?? '';
+            $prefix = array_map(static function ($p) use ($color) {
+                return Color::colorize($color, $p);
+            }, self::PREFIX_DECORATED);
+        }
+
+        $trace = $this->formatStacktrace($t);
+        $out   = $this->prefixLines($prefix['start'], PHP_EOL) . PHP_EOL;
+
+        if ($message) {
+            $out .= $this->prefixLines($prefix['message'], $message . PHP_EOL) . PHP_EOL;
+        }
+
+        if ($diff) {
+            $out .= $this->prefixLines($prefix['diff'], $diff . PHP_EOL) . PHP_EOL;
+        }
+
+        if ($trace) {
+            if ($message || $diff) {
+                $out .= $this->prefixLines($prefix['default'], PHP_EOL) . PHP_EOL;
+            }
+            $out .= $this->prefixLines($prefix['trace'], $trace . PHP_EOL) . PHP_EOL;
+        }
+        $out .= $this->prefixLines($prefix['last'], PHP_EOL) . PHP_EOL;
+
+        return $out;
+    }
+
+    protected function drawSpinner(): void
+    {
+        if ($this->colors) {
+            $id = $this->spinState % count(self::SPINNER_ICONS);
+            $this->write(self::SPINNER_ICONS[$id]);
+        }
+    }
+
+    protected function undrawSpinner(): void
+    {
+        if ($this->colors) {
+            $id = $this->spinState % count(self::SPINNER_ICONS);
+            $this->write("\e[1K\e[" . strlen(self::SPINNER_ICONS[$id]) . 'D');
+        }
+    }
+
+    private function formatRuntime(float $time, string $color = ''): string
+    {
+        if (!$this->colors) {
+            return sprintf('[%.2f ms]', $time * 1000);
+        }
+
+        if ($time > 1) {
+            $color = 'fg-magenta';
+        }
+
+        return Color::colorize($color, ' ' . (int) ceil($time * 1000) . ' ' . Color::dim('ms'));
+    }
+
+    private function printNonSuccessfulTestsSummary(int $numberOfExecutedTests): void
+    {
+        if (empty($this->nonSuccessfulTestResults)) {
+            return;
+        }
+
+        if ((count($this->nonSuccessfulTestResults) / $numberOfExecutedTests) >= 0.7) {
+            return;
+        }
+
+        $this->write("Summary of non-successful tests:\n\n");
+
+        $prevResult = $this->getEmptyTestResult();
+
+        foreach ($this->nonSuccessfulTestResults as $testIndex) {
+            $result = $this->testResults[$testIndex];
+            $this->writeTestResult($prevResult, $result);
+            $prevResult = $result;
+        }
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Util/TestDox/HtmlResultPrinter.php b/vendor/phpunit/phpunit/src/Util/TestDox/HtmlResultPrinter.php
new file mode 100644
index 0000000000000000000000000000000000000000..d2bcbe527c95958a727e9ed4495881cc93afd06c
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Util/TestDox/HtmlResultPrinter.php
@@ -0,0 +1,138 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Util\TestDox;
+
+use function sprintf;
+use PHPUnit\Framework\TestResult;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class HtmlResultPrinter extends ResultPrinter
+{
+    /**
+     * @var string
+     */
+    private const PAGE_HEADER = <<<'EOT'
+<!doctype html>
+<html lang="en">
+    <head>
+        <meta charset="utf-8"/>
+        <title>Test Documentation</title>
+        <style>
+            body {
+                text-rendering: optimizeLegibility;
+                font-variant-ligatures: common-ligatures;
+                font-kerning: normal;
+                margin-left: 2em;
+            }
+
+            body > ul > li {
+                font-family: Source Serif Pro, PT Sans, Trebuchet MS, Helvetica, Arial;
+                font-size: 2em;
+            }
+
+            h2 {
+                font-family: Tahoma, Helvetica, Arial;
+                font-size: 3em;
+            }
+
+            ul {
+                list-style: none;
+                margin-bottom: 1em;
+            }
+        </style>
+    </head>
+    <body>
+EOT;
+
+    /**
+     * @var string
+     */
+    private const CLASS_HEADER = <<<'EOT'
+
+        <h2 id="%s">%s</h2>
+        <ul>
+
+EOT;
+
+    /**
+     * @var string
+     */
+    private const CLASS_FOOTER = <<<'EOT'
+        </ul>
+EOT;
+
+    /**
+     * @var string
+     */
+    private const PAGE_FOOTER = <<<'EOT'
+
+    </body>
+</html>
+EOT;
+
+    public function printResult(TestResult $result): void
+    {
+    }
+
+    /**
+     * Handler for 'start run' event.
+     */
+    protected function startRun(): void
+    {
+        $this->write(self::PAGE_HEADER);
+    }
+
+    /**
+     * Handler for 'start class' event.
+     */
+    protected function startClass(string $name): void
+    {
+        $this->write(
+            sprintf(
+                self::CLASS_HEADER,
+                $name,
+                $this->currentTestClassPrettified
+            )
+        );
+    }
+
+    /**
+     * Handler for 'on test' event.
+     */
+    protected function onTest(string $name, bool $success = true): void
+    {
+        $this->write(
+            sprintf(
+                "            <li style=\"color: %s;\">%s %s</li>\n",
+                $success ? '#555753' : '#ef2929',
+                $success ? '✓' : '❌',
+                $name
+            )
+        );
+    }
+
+    /**
+     * Handler for 'end class' event.
+     */
+    protected function endClass(string $name): void
+    {
+        $this->write(self::CLASS_FOOTER);
+    }
+
+    /**
+     * Handler for 'end run' event.
+     */
+    protected function endRun(): void
+    {
+        $this->write(self::PAGE_FOOTER);
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Util/TestDox/NamePrettifier.php b/vendor/phpunit/phpunit/src/Util/TestDox/NamePrettifier.php
new file mode 100644
index 0000000000000000000000000000000000000000..630bdd82109e03b6d0341c3c2d82bc661ca3a65a
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Util/TestDox/NamePrettifier.php
@@ -0,0 +1,328 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Util\TestDox;
+
+use function array_key_exists;
+use function array_keys;
+use function array_map;
+use function array_pop;
+use function array_values;
+use function explode;
+use function get_class;
+use function gettype;
+use function implode;
+use function in_array;
+use function is_bool;
+use function is_float;
+use function is_int;
+use function is_numeric;
+use function is_object;
+use function is_scalar;
+use function is_string;
+use function mb_strtolower;
+use function ord;
+use function preg_quote;
+use function preg_replace;
+use function range;
+use function sprintf;
+use function str_replace;
+use function strlen;
+use function strpos;
+use function strtolower;
+use function strtoupper;
+use function substr;
+use function trim;
+use PHPUnit\Framework\TestCase;
+use PHPUnit\Util\Color;
+use PHPUnit\Util\Exception as UtilException;
+use PHPUnit\Util\Test;
+use ReflectionException;
+use ReflectionMethod;
+use ReflectionObject;
+use SebastianBergmann\Exporter\Exporter;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class NamePrettifier
+{
+    /**
+     * @var string[]
+     */
+    private $strings = [];
+
+    /**
+     * @var bool
+     */
+    private $useColor;
+
+    public function __construct(bool $useColor = false)
+    {
+        $this->useColor = $useColor;
+    }
+
+    /**
+     * Prettifies the name of a test class.
+     *
+     * @psalm-param class-string $className
+     */
+    public function prettifyTestClass(string $className): string
+    {
+        try {
+            $annotations = Test::parseTestMethodAnnotations($className);
+
+            if (isset($annotations['class']['testdox'][0])) {
+                return $annotations['class']['testdox'][0];
+            }
+        } catch (UtilException $e) {
+            // ignore, determine className by parsing the provided name
+        }
+
+        $parts     = explode('\\', $className);
+        $className = array_pop($parts);
+
+        if (substr($className, -1 * strlen('Test')) === 'Test') {
+            $className = substr($className, 0, strlen($className) - strlen('Test'));
+        }
+
+        if (strpos($className, 'Tests') === 0) {
+            $className = substr($className, strlen('Tests'));
+        } elseif (strpos($className, 'Test') === 0) {
+            $className = substr($className, strlen('Test'));
+        }
+
+        if (empty($className)) {
+            $className = 'UnnamedTests';
+        }
+
+        if (!empty($parts)) {
+            $parts[]            = $className;
+            $fullyQualifiedName = implode('\\', $parts);
+        } else {
+            $fullyQualifiedName = $className;
+        }
+
+        $result       = '';
+        $wasLowerCase = false;
+
+        foreach (range(0, strlen($className) - 1) as $i) {
+            $isLowerCase = mb_strtolower($className[$i], 'UTF-8') === $className[$i];
+
+            if ($wasLowerCase && !$isLowerCase) {
+                $result .= ' ';
+            }
+
+            $result .= $className[$i];
+
+            if ($isLowerCase) {
+                $wasLowerCase = true;
+            } else {
+                $wasLowerCase = false;
+            }
+        }
+
+        if ($fullyQualifiedName !== $className) {
+            return $result . ' (' . $fullyQualifiedName . ')';
+        }
+
+        return $result;
+    }
+
+    /**
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     */
+    public function prettifyTestCase(TestCase $test): string
+    {
+        $annotations = Test::parseTestMethodAnnotations(
+            get_class($test),
+            $test->getName(false)
+        );
+
+        $annotationWithPlaceholders = false;
+
+        $callback = static function (string $variable): string {
+            return sprintf('/%s(?=\b)/', preg_quote($variable, '/'));
+        };
+
+        if (isset($annotations['method']['testdox'][0])) {
+            $result = $annotations['method']['testdox'][0];
+
+            if (strpos($result, '$') !== false) {
+                $annotation   = $annotations['method']['testdox'][0];
+                $providedData = $this->mapTestMethodParameterNamesToProvidedDataValues($test);
+                $variables    = array_map($callback, array_keys($providedData));
+
+                $result = trim(preg_replace($variables, $providedData, $annotation));
+
+                $annotationWithPlaceholders = true;
+            }
+        } else {
+            $result = $this->prettifyTestMethod($test->getName(false));
+        }
+
+        if (!$annotationWithPlaceholders && $test->usesDataProvider()) {
+            $result .= $this->prettifyDataSet($test);
+        }
+
+        return $result;
+    }
+
+    public function prettifyDataSet(TestCase $test): string
+    {
+        if (!$this->useColor) {
+            return $test->getDataSetAsString(false);
+        }
+
+        if (is_int($test->dataName())) {
+            $data = Color::dim(' with data set ') . Color::colorize('fg-cyan', (string) $test->dataName());
+        } else {
+            $data = Color::dim(' with ') . Color::colorize('fg-cyan', Color::visualizeWhitespace((string) $test->dataName()));
+        }
+
+        return $data;
+    }
+
+    /**
+     * Prettifies the name of a test method.
+     */
+    public function prettifyTestMethod(string $name): string
+    {
+        $buffer = '';
+
+        if ($name === '') {
+            return $buffer;
+        }
+
+        $string = (string) preg_replace('#\d+$#', '', $name, -1, $count);
+
+        if (in_array($string, $this->strings, true)) {
+            $name = $string;
+        } elseif ($count === 0) {
+            $this->strings[] = $string;
+        }
+
+        if (strpos($name, 'test_') === 0) {
+            $name = substr($name, 5);
+        } elseif (strpos($name, 'test') === 0) {
+            $name = substr($name, 4);
+        }
+
+        if ($name === '') {
+            return $buffer;
+        }
+
+        $name[0] = strtoupper($name[0]);
+
+        if (strpos($name, '_') !== false) {
+            return trim(str_replace('_', ' ', $name));
+        }
+
+        $wasNumeric = false;
+
+        foreach (range(0, strlen($name) - 1) as $i) {
+            if ($i > 0 && ord($name[$i]) >= 65 && ord($name[$i]) <= 90) {
+                $buffer .= ' ' . strtolower($name[$i]);
+            } else {
+                $isNumeric = is_numeric($name[$i]);
+
+                if (!$wasNumeric && $isNumeric) {
+                    $buffer .= ' ';
+                    $wasNumeric = true;
+                }
+
+                if ($wasNumeric && !$isNumeric) {
+                    $wasNumeric = false;
+                }
+
+                $buffer .= $name[$i];
+            }
+        }
+
+        return $buffer;
+    }
+
+    /**
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     */
+    private function mapTestMethodParameterNamesToProvidedDataValues(TestCase $test): array
+    {
+        try {
+            $reflector = new ReflectionMethod(get_class($test), $test->getName(false));
+            // @codeCoverageIgnoreStart
+        } catch (ReflectionException $e) {
+            throw new UtilException(
+                $e->getMessage(),
+                (int) $e->getCode(),
+                $e
+            );
+        }
+        // @codeCoverageIgnoreEnd
+
+        $providedData       = [];
+        $providedDataValues = array_values($test->getProvidedData());
+        $i                  = 0;
+
+        $providedData['$_dataName'] = $test->dataName();
+
+        foreach ($reflector->getParameters() as $parameter) {
+            if (!array_key_exists($i, $providedDataValues) && $parameter->isDefaultValueAvailable()) {
+                try {
+                    $providedDataValues[$i] = $parameter->getDefaultValue();
+                    // @codeCoverageIgnoreStart
+                } catch (ReflectionException $e) {
+                    throw new UtilException(
+                        $e->getMessage(),
+                        (int) $e->getCode(),
+                        $e
+                    );
+                }
+                // @codeCoverageIgnoreEnd
+            }
+
+            $value = $providedDataValues[$i++] ?? null;
+
+            if (is_object($value)) {
+                $reflector = new ReflectionObject($value);
+
+                if ($reflector->hasMethod('__toString')) {
+                    $value = (string) $value;
+                } else {
+                    $value = get_class($value);
+                }
+            }
+
+            if (!is_scalar($value)) {
+                $value = gettype($value);
+            }
+
+            if (is_bool($value) || is_int($value) || is_float($value)) {
+                $value = (new Exporter)->export($value);
+            }
+
+            if (is_string($value) && $value === '') {
+                if ($this->useColor) {
+                    $value = Color::colorize('dim,underlined', 'empty');
+                } else {
+                    $value = "''";
+                }
+            }
+
+            $providedData['$' . $parameter->getName()] = $value;
+        }
+
+        if ($this->useColor) {
+            $providedData = array_map(static function ($value) {
+                return Color::colorize('fg-cyan', Color::visualizeWhitespace((string) $value, true));
+            }, $providedData);
+        }
+
+        return $providedData;
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Util/TestDox/ResultPrinter.php b/vendor/phpunit/phpunit/src/Util/TestDox/ResultPrinter.php
new file mode 100644
index 0000000000000000000000000000000000000000..c4b63644fa2d4e7333c51e29aac7ffd60e8495eb
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Util/TestDox/ResultPrinter.php
@@ -0,0 +1,343 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Util\TestDox;
+
+use function get_class;
+use function in_array;
+use PHPUnit\Framework\AssertionFailedError;
+use PHPUnit\Framework\ErrorTestCase;
+use PHPUnit\Framework\Test;
+use PHPUnit\Framework\TestCase;
+use PHPUnit\Framework\TestSuite;
+use PHPUnit\Framework\Warning;
+use PHPUnit\Framework\WarningTestCase;
+use PHPUnit\Runner\BaseTestRunner;
+use PHPUnit\TextUI\ResultPrinter as ResultPrinterInterface;
+use PHPUnit\Util\Printer;
+use Throwable;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+abstract class ResultPrinter extends Printer implements ResultPrinterInterface
+{
+    /**
+     * @var NamePrettifier
+     */
+    protected $prettifier;
+
+    /**
+     * @var string
+     */
+    protected $testClass = '';
+
+    /**
+     * @var int
+     */
+    protected $testStatus;
+
+    /**
+     * @var array
+     */
+    protected $tests = [];
+
+    /**
+     * @var int
+     */
+    protected $successful = 0;
+
+    /**
+     * @var int
+     */
+    protected $warned = 0;
+
+    /**
+     * @var int
+     */
+    protected $failed = 0;
+
+    /**
+     * @var int
+     */
+    protected $risky = 0;
+
+    /**
+     * @var int
+     */
+    protected $skipped = 0;
+
+    /**
+     * @var int
+     */
+    protected $incomplete = 0;
+
+    /**
+     * @var null|string
+     */
+    protected $currentTestClassPrettified;
+
+    /**
+     * @var null|string
+     */
+    protected $currentTestMethodPrettified;
+
+    /**
+     * @var array
+     */
+    private $groups;
+
+    /**
+     * @var array
+     */
+    private $excludeGroups;
+
+    /**
+     * @param resource $out
+     *
+     * @throws \PHPUnit\Framework\Exception
+     */
+    public function __construct($out = null, array $groups = [], array $excludeGroups = [])
+    {
+        parent::__construct($out);
+
+        $this->groups        = $groups;
+        $this->excludeGroups = $excludeGroups;
+
+        $this->prettifier = new NamePrettifier;
+        $this->startRun();
+    }
+
+    /**
+     * Flush buffer and close output.
+     */
+    public function flush(): void
+    {
+        $this->doEndClass();
+        $this->endRun();
+
+        parent::flush();
+    }
+
+    /**
+     * An error occurred.
+     */
+    public function addError(Test $test, Throwable $t, float $time): void
+    {
+        if (!$this->isOfInterest($test)) {
+            return;
+        }
+
+        $this->testStatus = BaseTestRunner::STATUS_ERROR;
+        $this->failed++;
+    }
+
+    /**
+     * A warning occurred.
+     */
+    public function addWarning(Test $test, Warning $e, float $time): void
+    {
+        if (!$this->isOfInterest($test)) {
+            return;
+        }
+
+        $this->testStatus = BaseTestRunner::STATUS_WARNING;
+        $this->warned++;
+    }
+
+    /**
+     * A failure occurred.
+     */
+    public function addFailure(Test $test, AssertionFailedError $e, float $time): void
+    {
+        if (!$this->isOfInterest($test)) {
+            return;
+        }
+
+        $this->testStatus = BaseTestRunner::STATUS_FAILURE;
+        $this->failed++;
+    }
+
+    /**
+     * Incomplete test.
+     */
+    public function addIncompleteTest(Test $test, Throwable $t, float $time): void
+    {
+        if (!$this->isOfInterest($test)) {
+            return;
+        }
+
+        $this->testStatus = BaseTestRunner::STATUS_INCOMPLETE;
+        $this->incomplete++;
+    }
+
+    /**
+     * Risky test.
+     */
+    public function addRiskyTest(Test $test, Throwable $t, float $time): void
+    {
+        if (!$this->isOfInterest($test)) {
+            return;
+        }
+
+        $this->testStatus = BaseTestRunner::STATUS_RISKY;
+        $this->risky++;
+    }
+
+    /**
+     * Skipped test.
+     */
+    public function addSkippedTest(Test $test, Throwable $t, float $time): void
+    {
+        if (!$this->isOfInterest($test)) {
+            return;
+        }
+
+        $this->testStatus = BaseTestRunner::STATUS_SKIPPED;
+        $this->skipped++;
+    }
+
+    /**
+     * A testsuite started.
+     */
+    public function startTestSuite(TestSuite $suite): void
+    {
+    }
+
+    /**
+     * A testsuite ended.
+     */
+    public function endTestSuite(TestSuite $suite): void
+    {
+    }
+
+    /**
+     * A test started.
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     */
+    public function startTest(Test $test): void
+    {
+        if (!$this->isOfInterest($test)) {
+            return;
+        }
+
+        $class = get_class($test);
+
+        if ($this->testClass !== $class) {
+            if ($this->testClass !== '') {
+                $this->doEndClass();
+            }
+
+            $this->currentTestClassPrettified = $this->prettifier->prettifyTestClass($class);
+            $this->testClass                  = $class;
+            $this->tests                      = [];
+
+            $this->startClass($class);
+        }
+
+        if ($test instanceof TestCase) {
+            $this->currentTestMethodPrettified = $this->prettifier->prettifyTestCase($test);
+        }
+
+        $this->testStatus = BaseTestRunner::STATUS_PASSED;
+    }
+
+    /**
+     * A test ended.
+     */
+    public function endTest(Test $test, float $time): void
+    {
+        if (!$this->isOfInterest($test)) {
+            return;
+        }
+
+        $this->tests[] = [$this->currentTestMethodPrettified, $this->testStatus];
+
+        $this->currentTestClassPrettified  = null;
+        $this->currentTestMethodPrettified = null;
+    }
+
+    protected function doEndClass(): void
+    {
+        foreach ($this->tests as $test) {
+            $this->onTest($test[0], $test[1] === BaseTestRunner::STATUS_PASSED);
+        }
+
+        $this->endClass($this->testClass);
+    }
+
+    /**
+     * Handler for 'start run' event.
+     */
+    protected function startRun(): void
+    {
+    }
+
+    /**
+     * Handler for 'start class' event.
+     */
+    protected function startClass(string $name): void
+    {
+    }
+
+    /**
+     * Handler for 'on test' event.
+     */
+    protected function onTest(string $name, bool $success = true): void
+    {
+    }
+
+    /**
+     * Handler for 'end class' event.
+     */
+    protected function endClass(string $name): void
+    {
+    }
+
+    /**
+     * Handler for 'end run' event.
+     */
+    protected function endRun(): void
+    {
+    }
+
+    private function isOfInterest(Test $test): bool
+    {
+        if (!$test instanceof TestCase) {
+            return false;
+        }
+
+        if ($test instanceof ErrorTestCase || $test instanceof WarningTestCase) {
+            return false;
+        }
+
+        if (!empty($this->groups)) {
+            foreach ($test->getGroups() as $group) {
+                if (in_array($group, $this->groups, true)) {
+                    return true;
+                }
+            }
+
+            return false;
+        }
+
+        if (!empty($this->excludeGroups)) {
+            foreach ($test->getGroups() as $group) {
+                if (in_array($group, $this->excludeGroups, true)) {
+                    return false;
+                }
+            }
+
+            return true;
+        }
+
+        return true;
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Util/TestDox/TestDoxPrinter.php b/vendor/phpunit/phpunit/src/Util/TestDox/TestDoxPrinter.php
new file mode 100644
index 0000000000000000000000000000000000000000..088c6e018acdb71bb86911ce321b51b1d9fa1fe3
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Util/TestDox/TestDoxPrinter.php
@@ -0,0 +1,386 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Util\TestDox;
+
+use const PHP_EOL;
+use function array_map;
+use function get_class;
+use function implode;
+use function method_exists;
+use function preg_split;
+use function trim;
+use PHPUnit\Framework\AssertionFailedError;
+use PHPUnit\Framework\Reorderable;
+use PHPUnit\Framework\Test;
+use PHPUnit\Framework\TestCase;
+use PHPUnit\Framework\TestResult;
+use PHPUnit\Framework\TestSuite;
+use PHPUnit\Framework\Warning;
+use PHPUnit\Runner\BaseTestRunner;
+use PHPUnit\Runner\PhptTestCase;
+use PHPUnit\TextUI\DefaultResultPrinter;
+use Throwable;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+class TestDoxPrinter extends DefaultResultPrinter
+{
+    /**
+     * @var NamePrettifier
+     */
+    protected $prettifier;
+
+    /**
+     * @var int The number of test results received from the TestRunner
+     */
+    protected $testIndex = 0;
+
+    /**
+     * @var int The number of test results already sent to the output
+     */
+    protected $testFlushIndex = 0;
+
+    /**
+     * @var array<int, array> Buffer for test results
+     */
+    protected $testResults = [];
+
+    /**
+     * @var array<string, int> Lookup table for testname to testResults[index]
+     */
+    protected $testNameResultIndex = [];
+
+    /**
+     * @var bool
+     */
+    protected $enableOutputBuffer = false;
+
+    /**
+     * @var array array<string>
+     */
+    protected $originalExecutionOrder = [];
+
+    /**
+     * @var int
+     */
+    protected $spinState = 0;
+
+    /**
+     * @var bool
+     */
+    protected $showProgress = true;
+
+    /**
+     * @param null|resource|string $out
+     * @param int|string           $numberOfColumns
+     *
+     * @throws \PHPUnit\Framework\Exception
+     */
+    public function __construct($out = null, bool $verbose = false, string $colors = self::COLOR_DEFAULT, bool $debug = false, $numberOfColumns = 80, bool $reverse = false)
+    {
+        parent::__construct($out, $verbose, $colors, $debug, $numberOfColumns, $reverse);
+
+        $this->prettifier = new NamePrettifier($this->colors);
+    }
+
+    public function setOriginalExecutionOrder(array $order): void
+    {
+        $this->originalExecutionOrder = $order;
+        $this->enableOutputBuffer     = !empty($order);
+    }
+
+    public function setShowProgressAnimation(bool $showProgress): void
+    {
+        $this->showProgress = $showProgress;
+    }
+
+    public function printResult(TestResult $result): void
+    {
+    }
+
+    /**
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     */
+    public function endTest(Test $test, float $time): void
+    {
+        if (!$test instanceof TestCase && !$test instanceof PhptTestCase && !$test instanceof TestSuite) {
+            return;
+        }
+
+        if ($this->testHasPassed()) {
+            $this->registerTestResult($test, null, BaseTestRunner::STATUS_PASSED, $time, false);
+        }
+
+        if ($test instanceof TestCase || $test instanceof PhptTestCase) {
+            $this->testIndex++;
+        }
+
+        parent::endTest($test, $time);
+    }
+
+    /**
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     */
+    public function addError(Test $test, Throwable $t, float $time): void
+    {
+        $this->registerTestResult($test, $t, BaseTestRunner::STATUS_ERROR, $time, true);
+    }
+
+    /**
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     */
+    public function addWarning(Test $test, Warning $e, float $time): void
+    {
+        $this->registerTestResult($test, $e, BaseTestRunner::STATUS_WARNING, $time, true);
+    }
+
+    /**
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     */
+    public function addFailure(Test $test, AssertionFailedError $e, float $time): void
+    {
+        $this->registerTestResult($test, $e, BaseTestRunner::STATUS_FAILURE, $time, true);
+    }
+
+    /**
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     */
+    public function addIncompleteTest(Test $test, Throwable $t, float $time): void
+    {
+        $this->registerTestResult($test, $t, BaseTestRunner::STATUS_INCOMPLETE, $time, false);
+    }
+
+    /**
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     */
+    public function addRiskyTest(Test $test, Throwable $t, float $time): void
+    {
+        $this->registerTestResult($test, $t, BaseTestRunner::STATUS_RISKY, $time, false);
+    }
+
+    /**
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     */
+    public function addSkippedTest(Test $test, Throwable $t, float $time): void
+    {
+        $this->registerTestResult($test, $t, BaseTestRunner::STATUS_SKIPPED, $time, false);
+    }
+
+    public function writeProgress(string $progress): void
+    {
+        $this->flushOutputBuffer();
+    }
+
+    public function flush(): void
+    {
+        $this->flushOutputBuffer(true);
+    }
+
+    /**
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     */
+    protected function registerTestResult(Test $test, ?Throwable $t, int $status, float $time, bool $verbose): void
+    {
+        $testName = $test instanceof Reorderable ? $test->sortId() : $test->getName();
+
+        $result = [
+            'className'  => $this->formatClassName($test),
+            'testName'   => $testName,
+            'testMethod' => $this->formatTestName($test),
+            'message'    => '',
+            'status'     => $status,
+            'time'       => $time,
+            'verbose'    => $verbose,
+        ];
+
+        if ($t !== null) {
+            $result['message'] = $this->formatTestResultMessage($t, $result);
+        }
+
+        $this->testResults[$this->testIndex]  = $result;
+        $this->testNameResultIndex[$testName] = $this->testIndex;
+    }
+
+    protected function formatTestName(Test $test): string
+    {
+        return method_exists($test, 'getName') ? $test->getName() : '';
+    }
+
+    protected function formatClassName(Test $test): string
+    {
+        return get_class($test);
+    }
+
+    protected function testHasPassed(): bool
+    {
+        if (!isset($this->testResults[$this->testIndex]['status'])) {
+            return true;
+        }
+
+        if ($this->testResults[$this->testIndex]['status'] === BaseTestRunner::STATUS_PASSED) {
+            return true;
+        }
+
+        return false;
+    }
+
+    protected function flushOutputBuffer(bool $forceFlush = false): void
+    {
+        if ($this->testFlushIndex === $this->testIndex) {
+            return;
+        }
+
+        if ($this->testFlushIndex > 0) {
+            if ($this->enableOutputBuffer) {
+                $prevResult = $this->getTestResultByName($this->originalExecutionOrder[$this->testFlushIndex - 1]);
+            } else {
+                $prevResult = $this->testResults[$this->testFlushIndex - 1];
+            }
+        } else {
+            $prevResult = $this->getEmptyTestResult();
+        }
+
+        if (!$this->enableOutputBuffer) {
+            $this->writeTestResult($prevResult, $this->testResults[$this->testFlushIndex++]);
+        } else {
+            do {
+                $flushed = false;
+
+                if (!$forceFlush && isset($this->originalExecutionOrder[$this->testFlushIndex])) {
+                    $result = $this->getTestResultByName($this->originalExecutionOrder[$this->testFlushIndex]);
+                } else {
+                    // This test(name) cannot found in original execution order,
+                    // flush result to output stream right away
+                    $result = $this->testResults[$this->testFlushIndex];
+                }
+
+                if (!empty($result)) {
+                    $this->hideSpinner();
+                    $this->writeTestResult($prevResult, $result);
+                    $this->testFlushIndex++;
+                    $prevResult = $result;
+                    $flushed    = true;
+                } else {
+                    $this->showSpinner();
+                }
+            } while ($flushed && $this->testFlushIndex < $this->testIndex);
+        }
+    }
+
+    protected function showSpinner(): void
+    {
+        if (!$this->showProgress) {
+            return;
+        }
+
+        if ($this->spinState) {
+            $this->undrawSpinner();
+        }
+
+        $this->spinState++;
+        $this->drawSpinner();
+    }
+
+    protected function hideSpinner(): void
+    {
+        if (!$this->showProgress) {
+            return;
+        }
+
+        if ($this->spinState) {
+            $this->undrawSpinner();
+        }
+
+        $this->spinState = 0;
+    }
+
+    protected function drawSpinner(): void
+    {
+        // optional for CLI printers: show the user a 'buffering output' spinner
+    }
+
+    protected function undrawSpinner(): void
+    {
+        // remove the spinner from the current line
+    }
+
+    protected function writeTestResult(array $prevResult, array $result): void
+    {
+    }
+
+    protected function getEmptyTestResult(): array
+    {
+        return [
+            'className' => '',
+            'testName'  => '',
+            'message'   => '',
+            'failed'    => '',
+            'verbose'   => '',
+        ];
+    }
+
+    protected function getTestResultByName(?string $testName): array
+    {
+        if (isset($this->testNameResultIndex[$testName])) {
+            return $this->testResults[$this->testNameResultIndex[$testName]];
+        }
+
+        return [];
+    }
+
+    protected function formatThrowable(Throwable $t, ?int $status = null): string
+    {
+        $message = trim(\PHPUnit\Framework\TestFailure::exceptionToString($t));
+
+        if ($message) {
+            $message .= PHP_EOL . PHP_EOL . $this->formatStacktrace($t);
+        } else {
+            $message = $this->formatStacktrace($t);
+        }
+
+        return $message;
+    }
+
+    protected function formatStacktrace(Throwable $t): string
+    {
+        return \PHPUnit\Util\Filter::getFilteredStacktrace($t);
+    }
+
+    protected function formatTestResultMessage(Throwable $t, array $result, string $prefix = '│'): string
+    {
+        $message = $this->formatThrowable($t, $result['status']);
+
+        if ($message === '') {
+            return '';
+        }
+
+        if (!($this->verbose || $result['verbose'])) {
+            return '';
+        }
+
+        return $this->prefixLines($prefix, $message);
+    }
+
+    protected function prefixLines(string $prefix, string $message): string
+    {
+        $message = trim($message);
+
+        return implode(
+            PHP_EOL,
+            array_map(
+                static function (string $text) use ($prefix) {
+                    return '   ' . $prefix . ($text ? ' ' . $text : '');
+                },
+                preg_split('/\r\n|\r|\n/', $message)
+            )
+        );
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Util/TestDox/TextResultPrinter.php b/vendor/phpunit/phpunit/src/Util/TestDox/TextResultPrinter.php
new file mode 100644
index 0000000000000000000000000000000000000000..8a1893e55ca2810188845fda2eaca8b51ca3a0ad
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Util/TestDox/TextResultPrinter.php
@@ -0,0 +1,52 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Util\TestDox;
+
+use PHPUnit\Framework\TestResult;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class TextResultPrinter extends ResultPrinter
+{
+    public function printResult(TestResult $result): void
+    {
+    }
+
+    /**
+     * Handler for 'start class' event.
+     */
+    protected function startClass(string $name): void
+    {
+        $this->write($this->currentTestClassPrettified . "\n");
+    }
+
+    /**
+     * Handler for 'on test' event.
+     */
+    protected function onTest(string $name, bool $success = true): void
+    {
+        if ($success) {
+            $this->write(' [x] ');
+        } else {
+            $this->write(' [ ] ');
+        }
+
+        $this->write($name . "\n");
+    }
+
+    /**
+     * Handler for 'end class' event.
+     */
+    protected function endClass(string $name): void
+    {
+        $this->write("\n");
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Util/TestDox/XmlResultPrinter.php b/vendor/phpunit/phpunit/src/Util/TestDox/XmlResultPrinter.php
new file mode 100644
index 0000000000000000000000000000000000000000..e0ac56b4097735b6cf2d84fbf34d0fabb07f15bd
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Util/TestDox/XmlResultPrinter.php
@@ -0,0 +1,259 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Util\TestDox;
+
+use function array_filter;
+use function get_class;
+use function implode;
+use function strpos;
+use DOMDocument;
+use DOMElement;
+use PHPUnit\Framework\AssertionFailedError;
+use PHPUnit\Framework\Exception;
+use PHPUnit\Framework\Test;
+use PHPUnit\Framework\TestCase;
+use PHPUnit\Framework\TestListener;
+use PHPUnit\Framework\TestSuite;
+use PHPUnit\Framework\Warning;
+use PHPUnit\Util\Printer;
+use PHPUnit\Util\Test as TestUtil;
+use ReflectionClass;
+use ReflectionException;
+use Throwable;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class XmlResultPrinter extends Printer implements TestListener
+{
+    /**
+     * @var DOMDocument
+     */
+    private $document;
+
+    /**
+     * @var DOMElement
+     */
+    private $root;
+
+    /**
+     * @var NamePrettifier
+     */
+    private $prettifier;
+
+    /**
+     * @var null|Throwable
+     */
+    private $exception;
+
+    /**
+     * @param resource|string $out
+     *
+     * @throws Exception
+     */
+    public function __construct($out = null)
+    {
+        $this->document               = new DOMDocument('1.0', 'UTF-8');
+        $this->document->formatOutput = true;
+
+        $this->root = $this->document->createElement('tests');
+        $this->document->appendChild($this->root);
+
+        $this->prettifier = new NamePrettifier;
+
+        parent::__construct($out);
+    }
+
+    /**
+     * Flush buffer and close output.
+     */
+    public function flush(): void
+    {
+        $this->write($this->document->saveXML());
+
+        parent::flush();
+    }
+
+    /**
+     * An error occurred.
+     */
+    public function addError(Test $test, Throwable $t, float $time): void
+    {
+        $this->exception = $t;
+    }
+
+    /**
+     * A warning occurred.
+     */
+    public function addWarning(Test $test, Warning $e, float $time): void
+    {
+    }
+
+    /**
+     * A failure occurred.
+     */
+    public function addFailure(Test $test, AssertionFailedError $e, float $time): void
+    {
+        $this->exception = $e;
+    }
+
+    /**
+     * Incomplete test.
+     */
+    public function addIncompleteTest(Test $test, Throwable $t, float $time): void
+    {
+    }
+
+    /**
+     * Risky test.
+     */
+    public function addRiskyTest(Test $test, Throwable $t, float $time): void
+    {
+    }
+
+    /**
+     * Skipped test.
+     */
+    public function addSkippedTest(Test $test, Throwable $t, float $time): void
+    {
+    }
+
+    /**
+     * A test suite started.
+     */
+    public function startTestSuite(TestSuite $suite): void
+    {
+    }
+
+    /**
+     * A test suite ended.
+     */
+    public function endTestSuite(TestSuite $suite): void
+    {
+    }
+
+    /**
+     * A test started.
+     */
+    public function startTest(Test $test): void
+    {
+        $this->exception = null;
+    }
+
+    /**
+     * A test ended.
+     *
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     */
+    public function endTest(Test $test, float $time): void
+    {
+        if (!$test instanceof TestCase) {
+            return;
+        }
+
+        $groups = array_filter(
+            $test->getGroups(),
+            static function ($group) {
+                return !($group === 'small' || $group === 'medium' || $group === 'large' || strpos($group, '__phpunit_') === 0);
+            }
+        );
+
+        $testNode = $this->document->createElement('test');
+
+        $testNode->setAttribute('className', get_class($test));
+        $testNode->setAttribute('methodName', $test->getName());
+        $testNode->setAttribute('prettifiedClassName', $this->prettifier->prettifyTestClass(get_class($test)));
+        $testNode->setAttribute('prettifiedMethodName', $this->prettifier->prettifyTestCase($test));
+        $testNode->setAttribute('status', (string) $test->getStatus());
+        $testNode->setAttribute('time', (string) $time);
+        $testNode->setAttribute('size', (string) $test->getSize());
+        $testNode->setAttribute('groups', implode(',', $groups));
+
+        foreach ($groups as $group) {
+            $groupNode = $this->document->createElement('group');
+
+            $groupNode->setAttribute('name', $group);
+
+            $testNode->appendChild($groupNode);
+        }
+
+        $annotations = TestUtil::parseTestMethodAnnotations(
+            get_class($test),
+            $test->getName(false)
+        );
+
+        foreach (['class', 'method'] as $type) {
+            foreach ($annotations[$type] as $annotation => $values) {
+                if ($annotation !== 'covers' && $annotation !== 'uses') {
+                    continue;
+                }
+
+                foreach ($values as $value) {
+                    $coversNode = $this->document->createElement($annotation);
+
+                    $coversNode->setAttribute('target', $value);
+
+                    $testNode->appendChild($coversNode);
+                }
+            }
+        }
+
+        foreach ($test->doubledTypes() as $doubledType) {
+            $testDoubleNode = $this->document->createElement('testDouble');
+
+            $testDoubleNode->setAttribute('type', $doubledType);
+
+            $testNode->appendChild($testDoubleNode);
+        }
+
+        $inlineAnnotations = \PHPUnit\Util\Test::getInlineAnnotations(get_class($test), $test->getName(false));
+
+        if (isset($inlineAnnotations['given'], $inlineAnnotations['when'], $inlineAnnotations['then'])) {
+            $testNode->setAttribute('given', $inlineAnnotations['given']['value']);
+            $testNode->setAttribute('givenStartLine', (string) $inlineAnnotations['given']['line']);
+            $testNode->setAttribute('when', $inlineAnnotations['when']['value']);
+            $testNode->setAttribute('whenStartLine', (string) $inlineAnnotations['when']['line']);
+            $testNode->setAttribute('then', $inlineAnnotations['then']['value']);
+            $testNode->setAttribute('thenStartLine', (string) $inlineAnnotations['then']['line']);
+        }
+
+        if ($this->exception !== null) {
+            if ($this->exception instanceof Exception) {
+                $steps = $this->exception->getSerializableTrace();
+            } else {
+                $steps = $this->exception->getTrace();
+            }
+
+            try {
+                $file = (new ReflectionClass($test))->getFileName();
+                // @codeCoverageIgnoreStart
+            } catch (ReflectionException $e) {
+                throw new Exception(
+                    $e->getMessage(),
+                    (int) $e->getCode(),
+                    $e
+                );
+            }
+            // @codeCoverageIgnoreEnd
+
+            foreach ($steps as $step) {
+                if (isset($step['file']) && $step['file'] === $file) {
+                    $testNode->setAttribute('exceptionLine', (string) $step['line']);
+
+                    break;
+                }
+            }
+
+            $testNode->setAttribute('exceptionMessage', $this->exception->getMessage());
+        }
+
+        $this->root->appendChild($testNode);
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Util/TextTestListRenderer.php b/vendor/phpunit/phpunit/src/Util/TextTestListRenderer.php
new file mode 100644
index 0000000000000000000000000000000000000000..67168a67f31061611ad18234d160a751ac92713f
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Util/TextTestListRenderer.php
@@ -0,0 +1,54 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Util;
+
+use const PHP_EOL;
+use function get_class;
+use function sprintf;
+use function str_replace;
+use PHPUnit\Framework\TestCase;
+use PHPUnit\Framework\TestSuite;
+use PHPUnit\Runner\PhptTestCase;
+use RecursiveIteratorIterator;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class TextTestListRenderer
+{
+    /**
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     */
+    public function render(TestSuite $suite): string
+    {
+        $buffer = 'Available test(s):' . PHP_EOL;
+
+        foreach (new RecursiveIteratorIterator($suite->getIterator()) as $test) {
+            if ($test instanceof TestCase) {
+                $name = sprintf(
+                    '%s::%s',
+                    get_class($test),
+                    str_replace(' with data set ', '', $test->getName())
+                );
+            } elseif ($test instanceof PhptTestCase) {
+                $name = $test->getName();
+            } else {
+                continue;
+            }
+
+            $buffer .= sprintf(
+                ' - %s' . PHP_EOL,
+                $name
+            );
+        }
+
+        return $buffer;
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Util/Type.php b/vendor/phpunit/phpunit/src/Util/Type.php
new file mode 100644
index 0000000000000000000000000000000000000000..01a6b1931e99820b86b8f1fd2fd66b0aee9e5d2c
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Util/Type.php
@@ -0,0 +1,52 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Util;
+
+use Throwable;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class Type
+{
+    public static function isType(string $type): bool
+    {
+        switch ($type) {
+            case 'numeric':
+            case 'integer':
+            case 'int':
+            case 'iterable':
+            case 'float':
+            case 'string':
+            case 'boolean':
+            case 'bool':
+            case 'null':
+            case 'array':
+            case 'object':
+            case 'resource':
+            case 'scalar':
+                return true;
+
+            default:
+                return false;
+        }
+    }
+
+    public static function isCloneable(object $object): bool
+    {
+        try {
+            $clone = clone $object;
+        } catch (Throwable $t) {
+            return false;
+        }
+
+        return $clone instanceof $object;
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Util/VersionComparisonOperator.php b/vendor/phpunit/phpunit/src/Util/VersionComparisonOperator.php
new file mode 100644
index 0000000000000000000000000000000000000000..ab65dbf359aa78f955612c0ef1c650c0c29774df
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Util/VersionComparisonOperator.php
@@ -0,0 +1,57 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Util;
+
+use function in_array;
+use function sprintf;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ * @psalm-immutable
+ */
+final class VersionComparisonOperator
+{
+    /**
+     * @psalm-var '<'|'lt'|'<='|'le'|'>'|'gt'|'>='|'ge'|'=='|'='|'eq'|'!='|'<>'|'ne'
+     */
+    private $operator;
+
+    public function __construct(string $operator)
+    {
+        $this->ensureOperatorIsValid($operator);
+
+        $this->operator = $operator;
+    }
+
+    /**
+     * @return '<'|'lt'|'<='|'le'|'>'|'gt'|'>='|'ge'|'=='|'='|'eq'|'!='|'<>'|'ne'
+     */
+    public function asString(): string
+    {
+        return $this->operator;
+    }
+
+    /**
+     * @throws Exception
+     *
+     * @psalm-assert '<'|'lt'|'<='|'le'|'>'|'gt'|'>='|'ge'|'=='|'='|'eq'|'!='|'<>'|'ne' $operator
+     */
+    private function ensureOperatorIsValid(string $operator): void
+    {
+        if (!in_array($operator, ['<', 'lt', '<=', 'le', '>', 'gt', '>=', 'ge', '==', '=', 'eq', '!=', '<>', 'ne'], true)) {
+            throw new Exception(
+                sprintf(
+                    '"%s" is not a valid version_compare() operator',
+                    $operator
+                )
+            );
+        }
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Util/XdebugFilterScriptGenerator.php b/vendor/phpunit/phpunit/src/Util/XdebugFilterScriptGenerator.php
new file mode 100644
index 0000000000000000000000000000000000000000..4a57528cc59d6d79b1ad9cf689fc75044f34b02e
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Util/XdebugFilterScriptGenerator.php
@@ -0,0 +1,80 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Util;
+
+use const DIRECTORY_SEPARATOR;
+use function addslashes;
+use function array_map;
+use function implode;
+use function is_string;
+use function realpath;
+use function sprintf;
+use PHPUnit\TextUI\XmlConfiguration\CodeCoverage\CodeCoverage as FilterConfiguration;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ *
+ * @deprecated
+ */
+final class XdebugFilterScriptGenerator
+{
+    public function generate(FilterConfiguration $filter): string
+    {
+        $files = array_map(
+            static function ($item) {
+                return sprintf(
+                    "        '%s'",
+                    $item
+                );
+            },
+            $this->getItems($filter)
+        );
+
+        $files = implode(",\n", $files);
+
+        return <<<EOF
+<?php declare(strict_types=1);
+if (!\\function_exists('xdebug_set_filter')) {
+    return;
+}
+
+\\xdebug_set_filter(
+    \\XDEBUG_FILTER_CODE_COVERAGE,
+    \\XDEBUG_PATH_WHITELIST,
+    [
+{$files}
+    ]
+);
+
+EOF;
+    }
+
+    private function getItems(FilterConfiguration $filter): array
+    {
+        $files = [];
+
+        foreach ($filter->directories() as $directory) {
+            $path = realpath($directory->path());
+
+            if (is_string($path)) {
+                $files[] = sprintf(
+                    addslashes('%s' . DIRECTORY_SEPARATOR),
+                    $path
+                );
+            }
+        }
+
+        foreach ($filter->files() as $file) {
+            $files[] = $file->path();
+        }
+
+        return $files;
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Util/Xml.php b/vendor/phpunit/phpunit/src/Util/Xml.php
new file mode 100644
index 0000000000000000000000000000000000000000..0939e6c5b6b2b768422080f84fc53952911906b2
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Util/Xml.php
@@ -0,0 +1,193 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Util;
+
+use const ENT_QUOTES;
+use function assert;
+use function class_exists;
+use function htmlspecialchars;
+use function mb_convert_encoding;
+use function ord;
+use function preg_replace;
+use function settype;
+use function strlen;
+use DOMCharacterData;
+use DOMDocument;
+use DOMElement;
+use DOMNode;
+use DOMText;
+use ReflectionClass;
+use ReflectionException;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class Xml
+{
+    /**
+     * @deprecated Only used by assertEqualXMLStructure()
+     */
+    public static function import(DOMElement $element): DOMElement
+    {
+        return (new DOMDocument)->importNode($element, true);
+    }
+
+    /**
+     * @deprecated Only used by assertEqualXMLStructure()
+     */
+    public static function removeCharacterDataNodes(DOMNode $node): void
+    {
+        if ($node->hasChildNodes()) {
+            for ($i = $node->childNodes->length - 1; $i >= 0; $i--) {
+                if (($child = $node->childNodes->item($i)) instanceof DOMCharacterData) {
+                    $node->removeChild($child);
+                }
+            }
+        }
+    }
+
+    /**
+     * Escapes a string for the use in XML documents.
+     *
+     * Any Unicode character is allowed, excluding the surrogate blocks, FFFE,
+     * and FFFF (not even as character reference).
+     *
+     * @see https://www.w3.org/TR/xml/#charsets
+     */
+    public static function prepareString(string $string): string
+    {
+        return preg_replace(
+            '/[\\x00-\\x08\\x0b\\x0c\\x0e-\\x1f\\x7f]/',
+            '',
+            htmlspecialchars(
+                self::convertToUtf8($string),
+                ENT_QUOTES
+            )
+        );
+    }
+
+    /**
+     * "Convert" a DOMElement object into a PHP variable.
+     */
+    public static function xmlToVariable(DOMElement $element)
+    {
+        $variable = null;
+
+        switch ($element->tagName) {
+            case 'array':
+                $variable = [];
+
+                foreach ($element->childNodes as $entry) {
+                    if (!$entry instanceof DOMElement || $entry->tagName !== 'element') {
+                        continue;
+                    }
+                    $item = $entry->childNodes->item(0);
+
+                    if ($item instanceof DOMText) {
+                        $item = $entry->childNodes->item(1);
+                    }
+
+                    $value = self::xmlToVariable($item);
+
+                    if ($entry->hasAttribute('key')) {
+                        $variable[(string) $entry->getAttribute('key')] = $value;
+                    } else {
+                        $variable[] = $value;
+                    }
+                }
+
+                break;
+
+            case 'object':
+                $className = $element->getAttribute('class');
+
+                if ($element->hasChildNodes()) {
+                    $arguments       = $element->childNodes->item(0)->childNodes;
+                    $constructorArgs = [];
+
+                    foreach ($arguments as $argument) {
+                        if ($argument instanceof DOMElement) {
+                            $constructorArgs[] = self::xmlToVariable($argument);
+                        }
+                    }
+
+                    try {
+                        assert(class_exists($className));
+
+                        $variable = (new ReflectionClass($className))->newInstanceArgs($constructorArgs);
+                        // @codeCoverageIgnoreStart
+                    } catch (ReflectionException $e) {
+                        throw new Exception(
+                            $e->getMessage(),
+                            (int) $e->getCode(),
+                            $e
+                        );
+                    }
+                    // @codeCoverageIgnoreEnd
+                } else {
+                    $variable = new $className;
+                }
+
+                break;
+
+            case 'boolean':
+                $variable = $element->textContent === 'true';
+
+                break;
+
+            case 'integer':
+            case 'double':
+            case 'string':
+                $variable = $element->textContent;
+
+                settype($variable, $element->tagName);
+
+                break;
+        }
+
+        return $variable;
+    }
+
+    private static function convertToUtf8(string $string): string
+    {
+        if (!self::isUtf8($string)) {
+            $string = mb_convert_encoding($string, 'UTF-8');
+        }
+
+        return $string;
+    }
+
+    private static function isUtf8(string $string): bool
+    {
+        $length = strlen($string);
+
+        for ($i = 0; $i < $length; $i++) {
+            if (ord($string[$i]) < 0x80) {
+                $n = 0;
+            } elseif ((ord($string[$i]) & 0xE0) === 0xC0) {
+                $n = 1;
+            } elseif ((ord($string[$i]) & 0xF0) === 0xE0) {
+                $n = 2;
+            } elseif ((ord($string[$i]) & 0xF0) === 0xF0) {
+                $n = 3;
+            } else {
+                return false;
+            }
+
+            for ($j = 0; $j < $n; $j++) {
+                if ((++$i === $length) || ((ord($string[$i]) & 0xC0) !== 0x80)) {
+                    return false;
+                }
+            }
+        }
+
+        return true;
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Util/Xml/Exception.php b/vendor/phpunit/phpunit/src/Util/Xml/Exception.php
new file mode 100644
index 0000000000000000000000000000000000000000..09b73d8fa1b9e613bdc510ba39b0dc133d971110
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Util/Xml/Exception.php
@@ -0,0 +1,19 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Util\Xml;
+
+use RuntimeException;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class Exception extends RuntimeException implements \PHPUnit\Exception
+{
+}
diff --git a/vendor/phpunit/phpunit/src/Util/Xml/FailedSchemaDetectionResult.php b/vendor/phpunit/phpunit/src/Util/Xml/FailedSchemaDetectionResult.php
new file mode 100644
index 0000000000000000000000000000000000000000..0949f56843b03d4b7df685752c514c3f6bfe9923
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Util/Xml/FailedSchemaDetectionResult.php
@@ -0,0 +1,19 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Util\Xml;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ *
+ * @psalm-immutable
+ */
+final class FailedSchemaDetectionResult extends SchemaDetectionResult
+{
+}
diff --git a/vendor/phpunit/phpunit/src/Util/Xml/Loader.php b/vendor/phpunit/phpunit/src/Util/Xml/Loader.php
new file mode 100644
index 0000000000000000000000000000000000000000..8d43d3278d7ffd61917e4d79c6ab39855eff7684
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Util/Xml/Loader.php
@@ -0,0 +1,117 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Util\Xml;
+
+use function chdir;
+use function dirname;
+use function error_reporting;
+use function file_get_contents;
+use function getcwd;
+use function libxml_get_errors;
+use function libxml_use_internal_errors;
+use function sprintf;
+use DOMDocument;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class Loader
+{
+    /**
+     * @throws Exception
+     */
+    public function loadFile(string $filename, bool $isHtml = false, bool $xinclude = false, bool $strict = false): DOMDocument
+    {
+        $reporting = error_reporting(0);
+        $contents  = file_get_contents($filename);
+
+        error_reporting($reporting);
+
+        if ($contents === false) {
+            throw new Exception(
+                sprintf(
+                    'Could not read "%s".',
+                    $filename
+                )
+            );
+        }
+
+        return $this->load($contents, $isHtml, $filename, $xinclude, $strict);
+    }
+
+    /**
+     * @throws Exception
+     */
+    public function load(string $actual, bool $isHtml = false, string $filename = '', bool $xinclude = false, bool $strict = false): DOMDocument
+    {
+        if ($actual === '') {
+            throw new Exception('Could not load XML from empty string');
+        }
+
+        // Required for XInclude on Windows.
+        if ($xinclude) {
+            $cwd = getcwd();
+            @chdir(dirname($filename));
+        }
+
+        $document                     = new DOMDocument;
+        $document->preserveWhiteSpace = false;
+
+        $internal  = libxml_use_internal_errors(true);
+        $message   = '';
+        $reporting = error_reporting(0);
+
+        if ($filename !== '') {
+            // Required for XInclude
+            $document->documentURI = $filename;
+        }
+
+        if ($isHtml) {
+            $loaded = $document->loadHTML($actual);
+        } else {
+            $loaded = $document->loadXML($actual);
+        }
+
+        if (!$isHtml && $xinclude) {
+            $document->xinclude();
+        }
+
+        foreach (libxml_get_errors() as $error) {
+            $message .= "\n" . $error->message;
+        }
+
+        libxml_use_internal_errors($internal);
+        error_reporting($reporting);
+
+        if (isset($cwd)) {
+            @chdir($cwd);
+        }
+
+        if ($loaded === false || ($strict && $message !== '')) {
+            if ($filename !== '') {
+                throw new Exception(
+                    sprintf(
+                        'Could not load "%s".%s',
+                        $filename,
+                        $message !== '' ? "\n" . $message : ''
+                    )
+                );
+            }
+
+            if ($message === '') {
+                $message = 'Could not load XML for unknown reason';
+            }
+
+            throw new Exception($message);
+        }
+
+        return $document;
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Util/Xml/SchemaDetectionResult.php b/vendor/phpunit/phpunit/src/Util/Xml/SchemaDetectionResult.php
new file mode 100644
index 0000000000000000000000000000000000000000..442aae49cea81cbec1503d52d0daec6002e63887
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Util/Xml/SchemaDetectionResult.php
@@ -0,0 +1,31 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Util\Xml;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ *
+ * @psalm-immutable
+ */
+abstract class SchemaDetectionResult
+{
+    public function detected(): bool
+    {
+        return false;
+    }
+
+    /**
+     * @throws Exception
+     */
+    public function version(): string
+    {
+        throw new Exception('No supported schema was detected');
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Util/Xml/SchemaDetector.php b/vendor/phpunit/phpunit/src/Util/Xml/SchemaDetector.php
new file mode 100644
index 0000000000000000000000000000000000000000..5864695b454016ca936c55061f4e0fd5eb8fadef
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Util/Xml/SchemaDetector.php
@@ -0,0 +1,39 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Util\Xml;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class SchemaDetector
+{
+    /**
+     * @throws Exception
+     */
+    public function detect(string $filename): SchemaDetectionResult
+    {
+        $document = (new Loader)->loadFile(
+            $filename,
+            false,
+            true,
+            true
+        );
+
+        foreach (['9.2', '8.5'] as $candidate) {
+            $schema = (new SchemaFinder)->find($candidate);
+
+            if (!(new Validator)->validate($document, $schema)->hasValidationErrors()) {
+                return new SuccessfulSchemaDetectionResult($candidate);
+            }
+        }
+
+        return new FailedSchemaDetectionResult;
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Util/Xml/SchemaFinder.php b/vendor/phpunit/phpunit/src/Util/Xml/SchemaFinder.php
new file mode 100644
index 0000000000000000000000000000000000000000..1e7b73c59d480ed3a26b81e4a8fb0d05444fdac8
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Util/Xml/SchemaFinder.php
@@ -0,0 +1,53 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Util\Xml;
+
+use function defined;
+use function is_file;
+use function sprintf;
+use PHPUnit\Runner\Version;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class SchemaFinder
+{
+    /**
+     * @throws Exception
+     */
+    public function find(string $version): string
+    {
+        if ($version === Version::series()) {
+            $filename = $this->path() . 'phpunit.xsd';
+        } else {
+            $filename = $this->path() . 'schema/' . $version . '.xsd';
+        }
+
+        if (!is_file($filename)) {
+            throw new Exception(
+                sprintf(
+                    'Schema for PHPUnit %s is not available',
+                    $version
+                )
+            );
+        }
+
+        return $filename;
+    }
+
+    private function path(): string
+    {
+        if (defined('__PHPUNIT_PHAR_ROOT__')) {
+            return __PHPUNIT_PHAR_ROOT__ . '/';
+        }
+
+        return __DIR__ . '/../../../';
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Util/Xml/SnapshotNodeList.php b/vendor/phpunit/phpunit/src/Util/Xml/SnapshotNodeList.php
new file mode 100644
index 0000000000000000000000000000000000000000..fdc95abb875c638dfa469ec66f3afdb7541d9b84
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Util/Xml/SnapshotNodeList.php
@@ -0,0 +1,48 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Util\Xml;
+
+use ArrayIterator;
+use Countable;
+use DOMNode;
+use DOMNodeList;
+use IteratorAggregate;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class SnapshotNodeList implements Countable, IteratorAggregate
+{
+    /**
+     * @var DOMNode[]
+     */
+    private $nodes = [];
+
+    public static function fromNodeList(DOMNodeList $list): self
+    {
+        $snapshot = new self;
+
+        foreach ($list as $node) {
+            $snapshot->nodes[] = $node;
+        }
+
+        return $snapshot;
+    }
+
+    public function count(): int
+    {
+        return count($this->nodes);
+    }
+
+    public function getIterator(): ArrayIterator
+    {
+        return new ArrayIterator($this->nodes);
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Util/Xml/SuccessfulSchemaDetectionResult.php b/vendor/phpunit/phpunit/src/Util/Xml/SuccessfulSchemaDetectionResult.php
new file mode 100644
index 0000000000000000000000000000000000000000..8b517e29ab315ba9bdfdd1753ccae0f3cc90f35e
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Util/Xml/SuccessfulSchemaDetectionResult.php
@@ -0,0 +1,38 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Util\Xml;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ *
+ * @psalm-immutable
+ */
+final class SuccessfulSchemaDetectionResult extends SchemaDetectionResult
+{
+    /**
+     * @var string
+     */
+    private $version;
+
+    public function __construct(string $version)
+    {
+        $this->version = $version;
+    }
+
+    public function detected(): bool
+    {
+        return true;
+    }
+
+    public function version(): string
+    {
+        return $this->version;
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Util/Xml/ValidationResult.php b/vendor/phpunit/phpunit/src/Util/Xml/ValidationResult.php
new file mode 100644
index 0000000000000000000000000000000000000000..3292267bd40298ba72ec6d54a4acd4bb2acba6ae
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Util/Xml/ValidationResult.php
@@ -0,0 +1,69 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Util\Xml;
+
+use function sprintf;
+use function trim;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ *
+ * @psalm-immutable
+ */
+final class ValidationResult
+{
+    /**
+     * @psalm-var array<int,list<string>>
+     */
+    private $validationErrors = [];
+
+    /**
+     * @psalm-param array<int,\LibXMLError> $errors
+     */
+    public static function fromArray(array $errors): self
+    {
+        $validationErrors = [];
+
+        foreach ($errors as $error) {
+            if (!isset($validationErrors[$error->line])) {
+                $validationErrors[$error->line] = [];
+            }
+
+            $validationErrors[$error->line][] = trim($error->message);
+        }
+
+        return new self($validationErrors);
+    }
+
+    private function __construct(array $validationErrors)
+    {
+        $this->validationErrors = $validationErrors;
+    }
+
+    public function hasValidationErrors(): bool
+    {
+        return !empty($this->validationErrors);
+    }
+
+    public function asString(): string
+    {
+        $buffer = '';
+
+        foreach ($this->validationErrors as $line => $validationErrorsOnLine) {
+            $buffer .= sprintf(PHP_EOL . '  Line %d:' . PHP_EOL, $line);
+
+            foreach ($validationErrorsOnLine as $validationError) {
+                $buffer .= sprintf('  - %s' . PHP_EOL, $validationError);
+            }
+        }
+
+        return $buffer;
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Util/Xml/Validator.php b/vendor/phpunit/phpunit/src/Util/Xml/Validator.php
new file mode 100644
index 0000000000000000000000000000000000000000..b3c4e05b11a584521ea0cc9225decfa7421310e2
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Util/Xml/Validator.php
@@ -0,0 +1,35 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Util\Xml;
+
+use function file_get_contents;
+use function libxml_clear_errors;
+use function libxml_get_errors;
+use function libxml_use_internal_errors;
+use DOMDocument;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class Validator
+{
+    public function validate(DOMDocument $document, string $xsdFilename): ValidationResult
+    {
+        $originalErrorHandling = libxml_use_internal_errors(true);
+
+        $document->schemaValidateSource(file_get_contents($xsdFilename));
+
+        $errors = libxml_get_errors();
+        libxml_clear_errors();
+        libxml_use_internal_errors($originalErrorHandling);
+
+        return ValidationResult::fromArray($errors);
+    }
+}
diff --git a/vendor/phpunit/phpunit/src/Util/XmlTestListRenderer.php b/vendor/phpunit/phpunit/src/Util/XmlTestListRenderer.php
new file mode 100644
index 0000000000000000000000000000000000000000..d92e1fe2623985f4c2aa0e0b63a6325c93fb0e68
--- /dev/null
+++ b/vendor/phpunit/phpunit/src/Util/XmlTestListRenderer.php
@@ -0,0 +1,90 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\Util;
+
+use function get_class;
+use function implode;
+use function str_replace;
+use PHPUnit\Framework\TestCase;
+use PHPUnit\Framework\TestSuite;
+use PHPUnit\Runner\PhptTestCase;
+use RecursiveIteratorIterator;
+use XMLWriter;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for PHPUnit
+ */
+final class XmlTestListRenderer
+{
+    /**
+     * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
+     */
+    public function render(TestSuite $suite): string
+    {
+        $writer = new XMLWriter;
+
+        $writer->openMemory();
+        $writer->setIndent(true);
+        $writer->startDocument();
+        $writer->startElement('tests');
+
+        $currentTestCase = null;
+
+        foreach (new RecursiveIteratorIterator($suite->getIterator()) as $test) {
+            if ($test instanceof TestCase) {
+                if (get_class($test) !== $currentTestCase) {
+                    if ($currentTestCase !== null) {
+                        $writer->endElement();
+                    }
+
+                    $writer->startElement('testCaseClass');
+                    $writer->writeAttribute('name', get_class($test));
+
+                    $currentTestCase = get_class($test);
+                }
+
+                $writer->startElement('testCaseMethod');
+                $writer->writeAttribute('name', $test->getName(false));
+                $writer->writeAttribute('groups', implode(',', $test->getGroups()));
+
+                if (!empty($test->getDataSetAsString(false))) {
+                    $writer->writeAttribute(
+                        'dataSet',
+                        str_replace(
+                            ' with data set ',
+                            '',
+                            $test->getDataSetAsString(false)
+                        )
+                    );
+                }
+
+                $writer->endElement();
+            } elseif ($test instanceof PhptTestCase) {
+                if ($currentTestCase !== null) {
+                    $writer->endElement();
+
+                    $currentTestCase = null;
+                }
+
+                $writer->startElement('phptFile');
+                $writer->writeAttribute('path', $test->getName());
+                $writer->endElement();
+            }
+        }
+
+        if ($currentTestCase !== null) {
+            $writer->endElement();
+        }
+
+        $writer->endElement();
+
+        return $writer->outputMemory();
+    }
+}
diff --git a/vendor/pimple/pimple/.php_cs.dist b/vendor/pimple/pimple/.php_cs.dist
new file mode 100644
index 0000000000000000000000000000000000000000..2787bb4070095380703c37f58dbcab1fea152603
--- /dev/null
+++ b/vendor/pimple/pimple/.php_cs.dist
@@ -0,0 +1,20 @@
+<?php
+
+return PhpCsFixer\Config::create()
+    ->setRules([
+        '@Symfony' => true,
+        '@Symfony:risky' => true,
+        '@PHPUnit75Migration:risky' => true,
+        'php_unit_dedicate_assert' => true,
+        'array_syntax' => ['syntax' => 'short'],
+        'php_unit_fqcn_annotation' => true,
+        'no_unreachable_default_argument_value' => false,
+        'braces' => ['allow_single_line_closure' => true],
+        'heredoc_to_nowdoc' => false,
+        'ordered_imports' => true,
+        'phpdoc_types_order' => ['null_adjustment' => 'always_last', 'sort_algorithm' => 'none'],
+        'native_function_invocation' => ['include' => ['@compiler_optimized'], 'scope' => 'all'],
+    ])
+    ->setRiskyAllowed(true)
+    ->setFinder(PhpCsFixer\Finder::create()->in(__DIR__.'/src'))
+;
diff --git a/vendor/pimple/pimple/.travis.yml b/vendor/pimple/pimple/.travis.yml
index 196f7fc190045512d89d888eddac3b4fdc5d2f54..723904a78d67d1af4d4defde1c096d3f4db15391 100644
--- a/vendor/pimple/pimple/.travis.yml
+++ b/vendor/pimple/pimple/.travis.yml
@@ -1,40 +1,17 @@
 language: php
 
 env:
-  matrix:
-    - PIMPLE_EXT=no
-    - PIMPLE_EXT=yes
   global:
     - REPORT_EXIT_STATUS=1
 
 php:
-  - 5.3
-  - 5.4
-  - 5.5
-  - 5.6
-  - 7.0
-  - 7.1
+  - 7.2
+  - 7.3
+  - 7.4
 
 before_script:
   - composer self-update
   - COMPOSER_ROOT_VERSION=dev-master composer install
-  - if [ "$PIMPLE_EXT" == "yes" ]; then sh -c "cd ext/pimple && phpize && ./configure && make && sudo make install"; fi
-  - if [ "$PIMPLE_EXT" == "yes" ]; then echo "extension=pimple.so" >> `php --ini | grep "Loaded Configuration" | sed -e "s|.*:\s*||"`; fi
 
 script:
-  - cd ext/pimple
-  - if [ "$PIMPLE_EXT" == "yes" ]; then yes n | make test | tee output ; grep -E 'Tests failed +. +0' output; fi
-  - if [ "$PIMPLE_EXT" == "yes" ]; then export SYMFONY_DEPRECATIONS_HELPER=weak; fi
-  - cd ../..
   - ./vendor/bin/simple-phpunit
-
-matrix:
-  include:
-    - php: hhvm
-      dist: trusty
-      env: PIMPLE_EXT=no
-  exclude:
-    - php: 7.0
-      env: PIMPLE_EXT=yes
-    - php: 7.1
-      env: PIMPLE_EXT=yes
diff --git a/vendor/pimple/pimple/CHANGELOG b/vendor/pimple/pimple/CHANGELOG
index ba56760c1f593423f98109afd1cb649a1ef0c18d..219895740b08eeebd89701a9171eb41a2662b31f 100644
--- a/vendor/pimple/pimple/CHANGELOG
+++ b/vendor/pimple/pimple/CHANGELOG
@@ -1,6 +1,11 @@
-* 3.2.3 (2017-XX-XX)
+* 3.3.0 (2020-03-03)
 
- * n/a
+ * Drop PHP extension
+ * Bump min PHP version to 7.2.5
+
+* 3.2.3 (2018-01-21)
+
+ * prefixed all function calls with \ for extra speed
 
 * 3.2.2 (2017-07-23)
 
diff --git a/vendor/pimple/pimple/LICENSE b/vendor/pimple/pimple/LICENSE
index e02dc5a78dfa28eb60f5483cfefcaf14426413ba..3e2a9e1e6d226236afa9f5f8fffd78db265cd2b7 100644
--- a/vendor/pimple/pimple/LICENSE
+++ b/vendor/pimple/pimple/LICENSE
@@ -1,4 +1,4 @@
-Copyright (c) 2009-2017 Fabien Potencier
+Copyright (c) 2009-2020 Fabien Potencier
 
 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal
diff --git a/vendor/pimple/pimple/composer.json b/vendor/pimple/pimple/composer.json
index dabf190a9adeee9541b94a66760ccc0e1443f2ff..ef8a83db3d26d45822524cdee39086e11df09000 100644
--- a/vendor/pimple/pimple/composer.json
+++ b/vendor/pimple/pimple/composer.json
@@ -3,7 +3,7 @@
     "type": "library",
     "description": "Pimple, a simple Dependency Injection Container",
     "keywords": ["dependency injection", "container"],
-    "homepage": "http://pimple.sensiolabs.org",
+    "homepage": "https://pimple.symfony.com",
     "license": "MIT",
     "authors": [
         {
@@ -12,18 +12,18 @@
         }
     ],
     "require": {
-        "php": ">=5.3.0",
+        "php": "^7.2.5",
         "psr/container": "^1.0"
     },
     "require-dev": {
-        "symfony/phpunit-bridge": "^3.2"
+        "symfony/phpunit-bridge": "^3.4|^4.4|^5.0"
     },
     "autoload": {
         "psr-0": { "Pimple": "src/" }
     },
     "extra": {
         "branch-alias": {
-            "dev-master": "3.2.x-dev"
+            "dev-master": "3.3.x-dev"
         }
     }
 }
diff --git a/vendor/pimple/pimple/ext/pimple/.gitignore b/vendor/pimple/pimple/ext/pimple/.gitignore
deleted file mode 100644
index 1861088ac1f64d178e0365a926108e05caa42012..0000000000000000000000000000000000000000
--- a/vendor/pimple/pimple/ext/pimple/.gitignore
+++ /dev/null
@@ -1,30 +0,0 @@
-*.sw*
-.deps
-Makefile
-Makefile.fragments
-Makefile.global
-Makefile.objects
-acinclude.m4
-aclocal.m4
-build/
-config.cache
-config.guess
-config.h
-config.h.in
-config.log
-config.nice
-config.status
-config.sub
-configure
-configure.in
-install-sh
-libtool
-ltmain.sh
-missing
-mkinstalldirs
-run-tests.php
-*.loT
-.libs/
-modules/
-*.la
-*.lo
diff --git a/vendor/pimple/pimple/ext/pimple/README.md b/vendor/pimple/pimple/ext/pimple/README.md
deleted file mode 100644
index 7b39eb2929ea03396fcb0f44a66ee97a3b346e6a..0000000000000000000000000000000000000000
--- a/vendor/pimple/pimple/ext/pimple/README.md
+++ /dev/null
@@ -1,12 +0,0 @@
-This is Pimple 2 implemented in C
-
-* PHP >= 5.3
-* Not tested under Windows, might work
-
-Install
-=======
-
-    > phpize
-    > ./configure
-    > make
-    > make install
diff --git a/vendor/pimple/pimple/ext/pimple/config.m4 b/vendor/pimple/pimple/ext/pimple/config.m4
deleted file mode 100644
index 3a6e9aaeb1580a1387ed4e8946ea0d3fd59edfd2..0000000000000000000000000000000000000000
--- a/vendor/pimple/pimple/ext/pimple/config.m4
+++ /dev/null
@@ -1,63 +0,0 @@
-dnl $Id$
-dnl config.m4 for extension pimple
-
-dnl Comments in this file start with the string 'dnl'.
-dnl Remove where necessary. This file will not work
-dnl without editing.
-
-dnl If your extension references something external, use with:
-
-dnl PHP_ARG_WITH(pimple, for pimple support,
-dnl Make sure that the comment is aligned:
-dnl [  --with-pimple             Include pimple support])
-
-dnl Otherwise use enable:
-
-PHP_ARG_ENABLE(pimple, whether to enable pimple support,
-dnl Make sure that the comment is aligned:
-[  --enable-pimple           Enable pimple support])
-
-if test "$PHP_PIMPLE" != "no"; then
-  dnl Write more examples of tests here...
-
-  dnl # --with-pimple -> check with-path
-  dnl SEARCH_PATH="/usr/local /usr"     # you might want to change this
-  dnl SEARCH_FOR="/include/pimple.h"  # you most likely want to change this
-  dnl if test -r $PHP_PIMPLE/$SEARCH_FOR; then # path given as parameter
-  dnl   PIMPLE_DIR=$PHP_PIMPLE
-  dnl else # search default path list
-  dnl   AC_MSG_CHECKING([for pimple files in default path])
-  dnl   for i in $SEARCH_PATH ; do
-  dnl     if test -r $i/$SEARCH_FOR; then
-  dnl       PIMPLE_DIR=$i
-  dnl       AC_MSG_RESULT(found in $i)
-  dnl     fi
-  dnl   done
-  dnl fi
-  dnl
-  dnl if test -z "$PIMPLE_DIR"; then
-  dnl   AC_MSG_RESULT([not found])
-  dnl   AC_MSG_ERROR([Please reinstall the pimple distribution])
-  dnl fi
-
-  dnl # --with-pimple -> add include path
-  dnl PHP_ADD_INCLUDE($PIMPLE_DIR/include)
-
-  dnl # --with-pimple -> check for lib and symbol presence
-  dnl LIBNAME=pimple # you may want to change this
-  dnl LIBSYMBOL=pimple # you most likely want to change this
-
-  dnl PHP_CHECK_LIBRARY($LIBNAME,$LIBSYMBOL,
-  dnl [
-  dnl   PHP_ADD_LIBRARY_WITH_PATH($LIBNAME, $PIMPLE_DIR/lib, PIMPLE_SHARED_LIBADD)
-  dnl   AC_DEFINE(HAVE_PIMPLELIB,1,[ ])
-  dnl ],[
-  dnl   AC_MSG_ERROR([wrong pimple lib version or lib not found])
-  dnl ],[
-  dnl   -L$PIMPLE_DIR/lib -lm
-  dnl ])
-  dnl
-  dnl PHP_SUBST(PIMPLE_SHARED_LIBADD)
-
-  PHP_NEW_EXTENSION(pimple, pimple.c, $ext_shared)
-fi
diff --git a/vendor/pimple/pimple/ext/pimple/config.w32 b/vendor/pimple/pimple/ext/pimple/config.w32
deleted file mode 100644
index 39857b3254be87fe7898be122bb94aa0edd8232b..0000000000000000000000000000000000000000
--- a/vendor/pimple/pimple/ext/pimple/config.w32
+++ /dev/null
@@ -1,13 +0,0 @@
-// $Id$
-// vim:ft=javascript
-
-// If your extension references something external, use ARG_WITH
-// ARG_WITH("pimple", "for pimple support", "no");
-
-// Otherwise, use ARG_ENABLE
-// ARG_ENABLE("pimple", "enable pimple support", "no");
-
-if (PHP_PIMPLE != "no") {
-	EXTENSION("pimple", "pimple.c");
-}
-
diff --git a/vendor/pimple/pimple/ext/pimple/php_pimple.h b/vendor/pimple/pimple/ext/pimple/php_pimple.h
deleted file mode 100644
index eed7c1731d48bd1d0fa2a7c53f099fe2d4613b52..0000000000000000000000000000000000000000
--- a/vendor/pimple/pimple/ext/pimple/php_pimple.h
+++ /dev/null
@@ -1,137 +0,0 @@
-
-/*
- * This file is part of Pimple.
- *
- * Copyright (c) 2014 Fabien Potencier
- *
- * 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.
- */
-
-#ifndef PHP_PIMPLE_H
-#define PHP_PIMPLE_H
-
-extern zend_module_entry pimple_module_entry;
-#define phpext_pimple_ptr &pimple_module_entry
-
-#ifdef PHP_WIN32
-#	define PHP_PIMPLE_API __declspec(dllexport)
-#elif defined(__GNUC__) && __GNUC__ >= 4
-#	define PHP_PIMPLE_API __attribute__ ((visibility("default")))
-#else
-#	define PHP_PIMPLE_API
-#endif
-
-#ifdef ZTS
-#include "TSRM.h"
-#endif
-
-#define PIMPLE_VERSION "3.2.3-DEV"
-
-#define PIMPLE_NS "Pimple"
-#define PSR_CONTAINER_NS "Psr\\Container"
-#define PIMPLE_EXCEPTION_NS "Pimple\\Exception"
-
-#define PIMPLE_DEFAULT_ZVAL_CACHE_NUM   5
-#define PIMPLE_DEFAULT_ZVAL_VALUES_NUM 10
-
-#define PIMPLE_DEPRECATE do { \
-	int er = EG(error_reporting); \
-	EG(error_reporting) = 0;\
-	php_error(E_DEPRECATED, "The Pimple C extension is deprecated since version 3.1 and will be removed in 4.0."); \
-	EG(error_reporting) = er; \
-} while (0);
-
-zend_module_entry *get_module(void);
-
-PHP_MINIT_FUNCTION(pimple);
-PHP_MINFO_FUNCTION(pimple);
-
-PHP_METHOD(FrozenServiceException, __construct);
-PHP_METHOD(InvalidServiceIdentifierException, __construct);
-PHP_METHOD(UnknownIdentifierException, __construct);
-
-PHP_METHOD(Pimple, __construct);
-PHP_METHOD(Pimple, factory);
-PHP_METHOD(Pimple, protect);
-PHP_METHOD(Pimple, raw);
-PHP_METHOD(Pimple, extend);
-PHP_METHOD(Pimple, keys);
-PHP_METHOD(Pimple, register);
-PHP_METHOD(Pimple, offsetSet);
-PHP_METHOD(Pimple, offsetUnset);
-PHP_METHOD(Pimple, offsetGet);
-PHP_METHOD(Pimple, offsetExists);
-
-PHP_METHOD(PimpleClosure, invoker);
-
-typedef struct _pimple_bucket_value {
-	zval *value; /* Must be the first element */
-	zval *raw;
-	zend_object_handle handle_num;
-	enum {
-		PIMPLE_IS_PARAM   = 0,
-		PIMPLE_IS_SERVICE = 2
-	} type;
-	zend_bool initialized;
-	zend_fcall_info_cache fcc;
-} pimple_bucket_value;
-
-typedef struct _pimple_object {
-	zend_object zobj;
-	HashTable values;
-	HashTable factories;
-	HashTable protected;
-} pimple_object;
-
-typedef struct _pimple_closure_object {
-	zend_object zobj;
-	zval *callable;
-	zval *factory;
-} pimple_closure_object;
-
-static const char sensiolabs_logo[] = "<img src=\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAHYAAAAUCAMAAABvRTlyAAAAz1BMVEUAAAAAAAAAAAAsThWB5j4AAACD6T8AAACC6D+C6D6C6D+C6D4AAAAAAACC6D4AAAAAAACC6D8AAAAAAAAAAAAAAAAAAAAAAACC6D4AAAAAAAAAAACC6D4AAAAAAAAAAAAAAAAAAAAAAACC6D8AAACC6D4AAAAAAAAAAAAAAAAAAACC6D8AAACC6D6C6D+B6D+C6D+C6D+C6D8AAACC6D6C6D4AAACC6D/K/2KC6D+B6D6C6D6C6D+C6D8sTxUyWRhEeiEAAACC6D+C5z6B6D7drnEVAAAAQXRSTlMAE3oCNSUuDHFHzxaF9UFsu+irX+zlKzYimaJXktyOSFD6BolxqT7QGMMdarMIpuO28r9EolXKgR16OphfXYd4V14GtB4AAAMpSURBVEjHvVSJctowEF1jjME2RziMwUCoMfd9heZqG4n//6buLpJjkmYm03byZmxJa2nf6u2uQcG2bfhqRN4LoTKBzyGDm68M7mAwcOEdjo4zhA/Rf9Go/CVtTgiRhXfIC3EDH8F/eUX1/9KexRo+QgOdtHDsEe/sM7QT32/+K61Z1LFXcXJxN4pTbu1aTQUzuy2PIA0rDo0/0Aa5XFaJvKaVTrubywXvaa1Wq4Vu/Snr3Y7Aojh4VccwykW2N2oQ8wmjyut6+Q1t5ywIG5Npj1sh5E0B7YOzFDjfuRfaOh3O+MbbVNfTWS9COZk3Obd2su5d0a6IU9KLREbw8gEehWSr1r2sPWciXLG38r5NdW0xu9eioU87omjC9yNaMi5GNf6WppVSOqXCFkmCvMB3p9SROLoYQn5pDgQOujA1xjYvqH+plUdkwnmII8VxR/PKYkrfLLomhVlE3b/LhNbNr7hp0H2JaOc4v8dFB58HSsFTSafaqtY1sT3GO8wsy5rhokYPlRJdjPMajyYqTt1EHF/2uqSWQWmAjCUSmQ1MS3g8Btf1XOsy7YIC0CB1b5Xw1Vhba0zbxiCAQLH9TNPmHJXQUtJAN0KcDsoqLxsNvJrJExa7mKIdp2lRE2WexiS4pqWk/0jROlw6K6bV9YOBDGAuqMJ0bnuUKGB0L27bxgRhGEbzihbhxxXaQC88Vkwq8ldCi86RApWUb0Q+4VDosBCc+1s81lUdnBavH4Zp2mm3O44USwOfvSo9oBiwpFg71lMS1VKJLKljS3j9p+fOTvXXlsSNuEv6YPaZda9uRope0VJfKdo7fPiYfSmvFjXQbkhY0d9hCbBWIktRgEDieDhf1N3wbbkmNNgRy8hyl620yGQat/grV3HMpc2HDKTVmOPFz6ylPCKt/nXcAyV260jaAowwIW0YuBzrOgb/KrddZS9OmJaLgpWK4JX2DDuklcLZSDGcn8Vmx9YDNvT6UsjyBApRyFQVX7Vxm9TGxE16nmfRd8/zQoDmggQOTRh5Hv8pMt9Q/L2JmSwkMCE7dA4BuDjHJwfu0Om4QAhOjrN5XkIatglfiN/bUPdCQFjTYgAAAABJRU5ErkJggg==\">";
-
-static void pimple_exception_call_parent_constructor(zval *this_ptr, const char *format, const char *arg1 TSRMLS_DC);
-
-static int pimple_zval_to_pimpleval(zval *_zval, pimple_bucket_value *_pimple_bucket_value TSRMLS_DC);
-static int pimple_zval_is_valid_callback(zval *_zval, pimple_bucket_value *_pimple_bucket_value TSRMLS_DC);
-
-static void pimple_bucket_dtor(pimple_bucket_value *bucket);
-static void pimple_free_bucket(pimple_bucket_value *bucket);
-
-static zval *pimple_object_read_dimension(zval *object, zval *offset, int type TSRMLS_DC);
-static void pimple_object_write_dimension(zval *object, zval *offset, zval *value TSRMLS_DC);
-static int pimple_object_has_dimension(zval *object, zval *offset, int check_empty TSRMLS_DC);
-static void pimple_object_unset_dimension(zval *object, zval *offset TSRMLS_DC);
-static zend_object_value pimple_object_create(zend_class_entry *ce TSRMLS_DC);
-static void pimple_free_object_storage(pimple_object *obj TSRMLS_DC);
-
-static void pimple_closure_free_object_storage(pimple_closure_object *obj TSRMLS_DC);
-static zend_object_value pimple_closure_object_create(zend_class_entry *ce TSRMLS_DC);
-static zend_function *pimple_closure_get_constructor(zval * TSRMLS_DC);
-static int pimple_closure_get_closure(zval *obj, zend_class_entry **ce_ptr, union _zend_function **fptr_ptr, zval **zobj_ptr TSRMLS_DC);
-
-#ifdef ZTS
-#define PIMPLE_G(v) TSRMG(pimple_globals_id, zend_pimple_globals *, v)
-#else
-#define PIMPLE_G(v) (pimple_globals.v)
-#endif
-
-#endif	/* PHP_PIMPLE_H */
-
diff --git a/vendor/pimple/pimple/ext/pimple/pimple.c b/vendor/pimple/pimple/ext/pimple/pimple.c
deleted file mode 100644
index c80499b3995684eaccfaf1017e662b54b6cd446f..0000000000000000000000000000000000000000
--- a/vendor/pimple/pimple/ext/pimple/pimple.c
+++ /dev/null
@@ -1,1114 +0,0 @@
-
-/*
- * This file is part of Pimple.
- *
- * Copyright (c) 2014 Fabien Potencier
- *
- * 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.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "php.h"
-#include "php_ini.h"
-#include "ext/standard/info.h"
-#include "php_pimple.h"
-#include "pimple_compat.h"
-#include "zend_interfaces.h"
-#include "zend.h"
-#include "Zend/zend_closures.h"
-#include "ext/spl/spl_exceptions.h"
-#include "Zend/zend_exceptions.h"
-#include "main/php_output.h"
-#include "SAPI.h"
-
-static zend_class_entry *pimple_ce_PsrContainerInterface;
-static zend_class_entry *pimple_ce_PsrContainerExceptionInterface;
-static zend_class_entry *pimple_ce_PsrNotFoundExceptionInterface;
-
-static zend_class_entry *pimple_ce_ExpectedInvokableException;
-static zend_class_entry *pimple_ce_FrozenServiceException;
-static zend_class_entry *pimple_ce_InvalidServiceIdentifierException;
-static zend_class_entry *pimple_ce_UnknownIdentifierException;
-
-static zend_class_entry *pimple_ce;
-static zend_object_handlers pimple_object_handlers;
-static zend_class_entry *pimple_closure_ce;
-static zend_class_entry *pimple_serviceprovider_ce;
-static zend_object_handlers pimple_closure_object_handlers;
-static zend_internal_function pimple_closure_invoker_function;
-
-#define FETCH_DIM_HANDLERS_VARS 	pimple_object *pimple_obj = NULL; \
-									ulong index; \
-									pimple_obj = (pimple_object *)zend_object_store_get_object(object TSRMLS_CC); \
-
-#define PIMPLE_OBJECT_HANDLE_INHERITANCE_OBJECT_HANDLERS	do { \
-	if (ce != pimple_ce) { \
-		zend_hash_find(&ce->function_table, ZEND_STRS("offsetget"), (void **)&function); \
-		if (function->common.scope != ce) { /* if the function is not defined in this actual class */ \
-			pimple_object_handlers.read_dimension = pimple_object_read_dimension; /* then overwrite the handler to use custom one */ \
-		} \
-		zend_hash_find(&ce->function_table, ZEND_STRS("offsetset"), (void **)&function); \
-		if (function->common.scope != ce) { \
-			pimple_object_handlers.write_dimension = pimple_object_write_dimension; \
-		} \
-		zend_hash_find(&ce->function_table, ZEND_STRS("offsetexists"), (void **)&function); \
-		if (function->common.scope != ce) { \
-			pimple_object_handlers.has_dimension = pimple_object_has_dimension; \
-		} \
-		zend_hash_find(&ce->function_table, ZEND_STRS("offsetunset"), (void **)&function); \
-		if (function->common.scope != ce) { \
-			pimple_object_handlers.unset_dimension = pimple_object_unset_dimension; \
-		} \
-	} else { \
-		pimple_object_handlers.read_dimension = pimple_object_read_dimension; \
-		pimple_object_handlers.write_dimension = pimple_object_write_dimension; \
-		pimple_object_handlers.has_dimension = pimple_object_has_dimension; \
-		pimple_object_handlers.unset_dimension = pimple_object_unset_dimension; \
-	}\
-											} while(0);
-
-#define PIMPLE_CALL_CB	do { \
-			zend_fcall_info_argn(&fci TSRMLS_CC, 1, &object); \
-			fci.size           = sizeof(fci); \
-			fci.object_ptr     = retval->fcc.object_ptr; \
-			fci.function_name  = retval->value; \
-			fci.no_separation  = 1; \
-			fci.retval_ptr_ptr = &retval_ptr_ptr; \
-\
-			zend_call_function(&fci, &retval->fcc TSRMLS_CC); \
-			efree(fci.params); \
-			if (EG(exception)) { \
-				return EG(uninitialized_zval_ptr); \
-			} \
-						} while(0);
-
-
-/* Psr\Container\ContainerInterface */
-ZEND_BEGIN_ARG_INFO_EX(arginfo_pimple_PsrContainerInterface_get, 0, 0, 1)
-ZEND_ARG_INFO(0, id)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(arginfo_pimple_PsrContainerInterface_has, 0, 0, 1)
-ZEND_ARG_INFO(0, id)
-ZEND_END_ARG_INFO()
-
-static const zend_function_entry pimple_ce_PsrContainerInterface_functions[] = {
-	PHP_ABSTRACT_ME(ContainerInterface, get, arginfo_pimple_PsrContainerInterface_get)
-	PHP_ABSTRACT_ME(ContainerInterface, has, arginfo_pimple_PsrContainerInterface_has)
-	PHP_FE_END
-};
-
-/* Psr\Container\ContainerExceptionInterface */
-static const zend_function_entry pimple_ce_PsrContainerExceptionInterface_functions[] = {
-	PHP_FE_END
-};
-
-/* Psr\Container\NotFoundExceptionInterface */
-static const zend_function_entry pimple_ce_PsrNotFoundExceptionInterface_functions[] = {
-	PHP_FE_END
-};
-
-/* Pimple\Exception\FrozenServiceException */
-ZEND_BEGIN_ARG_INFO_EX(arginfo_FrozenServiceException___construct, 0, 0, 1)
-ZEND_ARG_INFO(0, id)
-ZEND_END_ARG_INFO()
-
-static const zend_function_entry pimple_ce_FrozenServiceException_functions[] = {
-	PHP_ME(FrozenServiceException, __construct, arginfo_FrozenServiceException___construct, ZEND_ACC_PUBLIC)
-	PHP_FE_END
-};
-
-/* Pimple\Exception\InvalidServiceIdentifierException */
-ZEND_BEGIN_ARG_INFO_EX(arginfo_InvalidServiceIdentifierException___construct, 0, 0, 1)
-ZEND_ARG_INFO(0, id)
-ZEND_END_ARG_INFO()
-
-static const zend_function_entry pimple_ce_InvalidServiceIdentifierException_functions[] = {
-	PHP_ME(InvalidServiceIdentifierException, __construct, arginfo_InvalidServiceIdentifierException___construct, ZEND_ACC_PUBLIC)
-	PHP_FE_END
-};
-
-/* Pimple\Exception\UnknownIdentifierException */
-ZEND_BEGIN_ARG_INFO_EX(arginfo_UnknownIdentifierException___construct, 0, 0, 1)
-ZEND_ARG_INFO(0, id)
-ZEND_END_ARG_INFO()
-
-static const zend_function_entry pimple_ce_UnknownIdentifierException_functions[] = {
-	PHP_ME(UnknownIdentifierException, __construct, arginfo_UnknownIdentifierException___construct, ZEND_ACC_PUBLIC)
-	PHP_FE_END
-};
-
-/* Pimple\Container */
-ZEND_BEGIN_ARG_INFO_EX(arginfo___construct, 0, 0, 0)
-ZEND_ARG_ARRAY_INFO(0, value, 0)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(arginfo_offsetset, 0, 0, 2)
-ZEND_ARG_INFO(0, offset)
-ZEND_ARG_INFO(0, value)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(arginfo_offsetget, 0, 0, 1)
-ZEND_ARG_INFO(0, offset)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(arginfo_offsetexists, 0, 0, 1)
-ZEND_ARG_INFO(0, offset)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(arginfo_offsetunset, 0, 0, 1)
-ZEND_ARG_INFO(0, offset)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(arginfo_factory, 0, 0, 1)
-ZEND_ARG_INFO(0, callable)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(arginfo_protect, 0, 0, 1)
-ZEND_ARG_INFO(0, callable)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(arginfo_raw, 0, 0, 1)
-ZEND_ARG_INFO(0, id)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(arginfo_extend, 0, 0, 2)
-ZEND_ARG_INFO(0, id)
-ZEND_ARG_INFO(0, callable)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(arginfo_keys, 0, 0, 0)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(arginfo_register, 0, 0, 1)
-ZEND_ARG_OBJ_INFO(0, provider, Pimple\\ServiceProviderInterface, 0)
-ZEND_ARG_ARRAY_INFO(0, values, 1)
-ZEND_END_ARG_INFO()
-
-static const zend_function_entry pimple_ce_functions[] = {
-	PHP_ME(Pimple, __construct,	arginfo___construct, ZEND_ACC_PUBLIC)
-	PHP_ME(Pimple, factory,         arginfo_factory,         ZEND_ACC_PUBLIC)
-	PHP_ME(Pimple, protect,         arginfo_protect,         ZEND_ACC_PUBLIC)
-	PHP_ME(Pimple, raw,             arginfo_raw,             ZEND_ACC_PUBLIC)
-	PHP_ME(Pimple, extend,          arginfo_extend,          ZEND_ACC_PUBLIC)
-	PHP_ME(Pimple, keys,            arginfo_keys,            ZEND_ACC_PUBLIC)
-	PHP_ME(Pimple, register,		arginfo_register,		 ZEND_ACC_PUBLIC)
-
-	PHP_ME(Pimple, offsetSet,       arginfo_offsetset,       ZEND_ACC_PUBLIC)
-	PHP_ME(Pimple, offsetGet,       arginfo_offsetget,       ZEND_ACC_PUBLIC)
-	PHP_ME(Pimple, offsetExists,    arginfo_offsetexists,    ZEND_ACC_PUBLIC)
-	PHP_ME(Pimple, offsetUnset,     arginfo_offsetunset,     ZEND_ACC_PUBLIC)
-	PHP_FE_END
-};
-
-/* Pimple\ServiceProviderInterface */
-ZEND_BEGIN_ARG_INFO_EX(arginfo_serviceprovider_register, 0, 0, 1)
-ZEND_ARG_OBJ_INFO(0, pimple, Pimple\\Container, 0)
-ZEND_END_ARG_INFO()
-
-static const zend_function_entry pimple_serviceprovider_iface_ce_functions[] = {
-	PHP_ABSTRACT_ME(ServiceProviderInterface, register, arginfo_serviceprovider_register)
-	PHP_FE_END
-};
-
-/* parent::__construct(sprintf("Something with %s", $arg1)) */
-static void pimple_exception_call_parent_constructor(zval *this_ptr, const char *format, const char *arg1 TSRMLS_DC)
-{
-	zend_class_entry *ce = Z_OBJCE_P(this_ptr);
-	char *message = NULL;
-	int message_len;
-	zval *constructor_arg;
-
-	message_len = spprintf(&message, 0, format, arg1);
-	ALLOC_INIT_ZVAL(constructor_arg);
-	ZVAL_STRINGL(constructor_arg, message, message_len, 1);
-
-	zend_call_method_with_1_params(&this_ptr, ce, &ce->parent->constructor, "__construct", NULL, constructor_arg);
-
-	efree(message);
-	zval_ptr_dtor(&constructor_arg);
-}
-
-/**
- * Pass a single string parameter to exception constructor and throw
- */
-static void pimple_throw_exception_string(zend_class_entry *ce, const char *message, zend_uint message_len TSRMLS_DC)
-{
-	zval *exception, *param;
-
-	ALLOC_INIT_ZVAL(exception);
-	object_init_ex(exception, ce);
-
-	ALLOC_INIT_ZVAL(param);
-	ZVAL_STRINGL(param, message, message_len, 1);
-
-	zend_call_method_with_1_params(&exception, ce, &ce->constructor, "__construct", NULL, param);
-
-	zend_throw_exception_object(exception TSRMLS_CC);
-
-	zval_ptr_dtor(&param);
-}
-
-static void pimple_closure_free_object_storage(pimple_closure_object *obj TSRMLS_DC)
-{
-	zend_object_std_dtor(&obj->zobj TSRMLS_CC);
-	if (obj->factory) {
-		zval_ptr_dtor(&obj->factory);
-	}
-	if (obj->callable) {
-		zval_ptr_dtor(&obj->callable);
-	}
-	efree(obj);
-}
-
-static void pimple_free_object_storage(pimple_object *obj TSRMLS_DC)
-{
-	zend_hash_destroy(&obj->factories);
-	zend_hash_destroy(&obj->protected);
-	zend_hash_destroy(&obj->values);
-	zend_object_std_dtor(&obj->zobj TSRMLS_CC);
-	efree(obj);
-}
-
-static void pimple_free_bucket(pimple_bucket_value *bucket)
-{
-	if (bucket->raw) {
-		zval_ptr_dtor(&bucket->raw);
-	}
-}
-
-static zend_object_value pimple_closure_object_create(zend_class_entry *ce TSRMLS_DC)
-{
-	zend_object_value retval;
-	pimple_closure_object *pimple_closure_obj = NULL;
-
-	pimple_closure_obj = ecalloc(1, sizeof(pimple_closure_object));
-	ZEND_OBJ_INIT(&pimple_closure_obj->zobj, ce);
-
-	pimple_closure_object_handlers.get_constructor = pimple_closure_get_constructor;
-	retval.handlers = &pimple_closure_object_handlers;
-	retval.handle   = zend_objects_store_put(pimple_closure_obj, (zend_objects_store_dtor_t) zend_objects_destroy_object, (zend_objects_free_object_storage_t) pimple_closure_free_object_storage, NULL TSRMLS_CC);
-
-	return retval;
-}
-
-static zend_function *pimple_closure_get_constructor(zval *obj TSRMLS_DC)
-{
-	zend_error(E_ERROR, "Pimple\\ContainerClosure is an internal class and cannot be instantiated");
-
-	return NULL;
-}
-
-static int pimple_closure_get_closure(zval *obj, zend_class_entry **ce_ptr, union _zend_function **fptr_ptr, zval **zobj_ptr TSRMLS_DC)
-{
-	*zobj_ptr = obj;
-	*ce_ptr   = Z_OBJCE_P(obj);
-	*fptr_ptr = (zend_function *)&pimple_closure_invoker_function;
-
-	return SUCCESS;
-}
-
-static zend_object_value pimple_object_create(zend_class_entry *ce TSRMLS_DC)
-{
-	zend_object_value retval;
-	pimple_object *pimple_obj  = NULL;
-	zend_function *function    = NULL;
-
-	pimple_obj = emalloc(sizeof(pimple_object));
-	ZEND_OBJ_INIT(&pimple_obj->zobj, ce);
-
-	PIMPLE_OBJECT_HANDLE_INHERITANCE_OBJECT_HANDLERS
-
-	retval.handlers = &pimple_object_handlers;
-	retval.handle   = zend_objects_store_put(pimple_obj, (zend_objects_store_dtor_t) zend_objects_destroy_object, (zend_objects_free_object_storage_t) pimple_free_object_storage, NULL TSRMLS_CC);
-
-	zend_hash_init(&pimple_obj->factories, PIMPLE_DEFAULT_ZVAL_CACHE_NUM, NULL, (dtor_func_t)pimple_bucket_dtor, 0);
-	zend_hash_init(&pimple_obj->protected, PIMPLE_DEFAULT_ZVAL_CACHE_NUM, NULL, (dtor_func_t)pimple_bucket_dtor, 0);
-	zend_hash_init(&pimple_obj->values, PIMPLE_DEFAULT_ZVAL_VALUES_NUM, NULL, (dtor_func_t)pimple_bucket_dtor, 0);
-
-	return retval;
-}
-
-static void pimple_object_write_dimension(zval *object, zval *offset, zval *value TSRMLS_DC)
-{
-	FETCH_DIM_HANDLERS_VARS
-
-	pimple_bucket_value pimple_value = {0}, *found_value = NULL;
-	ulong hash;
-
-	pimple_zval_to_pimpleval(value, &pimple_value TSRMLS_CC);
-
-	if (!offset) {/* $p[] = 'foo' when not overloaded */
-		zend_hash_next_index_insert(&pimple_obj->values, (void *)&pimple_value, sizeof(pimple_bucket_value), NULL);
-		Z_ADDREF_P(value);
-		return;
-	}
-
-	switch (Z_TYPE_P(offset)) {
-	case IS_STRING:
-		hash = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
-		zend_hash_quick_find(&pimple_obj->values, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hash, (void **)&found_value);
-		if (found_value && found_value->type == PIMPLE_IS_SERVICE && found_value->initialized == 1) {
-			pimple_free_bucket(&pimple_value);
-			pimple_throw_exception_string(pimple_ce_FrozenServiceException, Z_STRVAL_P(offset), Z_STRLEN_P(offset) TSRMLS_CC);
-			return;
-		}
-		if (zend_hash_quick_update(&pimple_obj->values, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hash, (void *)&pimple_value, sizeof(pimple_bucket_value), NULL) == FAILURE) {
-			pimple_free_bucket(&pimple_value);
-			return;
-		}
-		Z_ADDREF_P(value);
-	break;
-	case IS_DOUBLE:
-	case IS_BOOL:
-	case IS_LONG:
-		if (Z_TYPE_P(offset) == IS_DOUBLE) {
-			index = (ulong)Z_DVAL_P(offset);
-		} else {
-			index = Z_LVAL_P(offset);
-		}
-		zend_hash_index_find(&pimple_obj->values, index, (void **)&found_value);
-		if (found_value && found_value->type == PIMPLE_IS_SERVICE && found_value->initialized == 1) {
-			pimple_free_bucket(&pimple_value);
-			convert_to_string(offset);
-			pimple_throw_exception_string(pimple_ce_FrozenServiceException, Z_STRVAL_P(offset), Z_STRLEN_P(offset) TSRMLS_CC);
-			return;
-		}
-		if (zend_hash_index_update(&pimple_obj->values, index, (void *)&pimple_value, sizeof(pimple_bucket_value), NULL) == FAILURE) {
-			pimple_free_bucket(&pimple_value);
-			return;
-		}
-		Z_ADDREF_P(value);
-	break;
-	case IS_NULL: /* $p[] = 'foo' when overloaded */
-		zend_hash_next_index_insert(&pimple_obj->values, (void *)&pimple_value, sizeof(pimple_bucket_value), NULL);
-		Z_ADDREF_P(value);
-	break;
-	default:
-		pimple_free_bucket(&pimple_value);
-		zend_error(E_WARNING, "Unsupported offset type");
-	}
-}
-
-static void pimple_object_unset_dimension(zval *object, zval *offset TSRMLS_DC)
-{
-	FETCH_DIM_HANDLERS_VARS
-
-	switch (Z_TYPE_P(offset)) {
-	case IS_STRING:
-		zend_symtable_del(&pimple_obj->values, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
-		zend_symtable_del(&pimple_obj->factories, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
-		zend_symtable_del(&pimple_obj->protected, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
-	break;
-	case IS_DOUBLE:
-	case IS_BOOL:
-	case IS_LONG:
-		if (Z_TYPE_P(offset) == IS_DOUBLE) {
-			index = (ulong)Z_DVAL_P(offset);
-		} else {
-			index = Z_LVAL_P(offset);
-		}
-		zend_hash_index_del(&pimple_obj->values, index);
-		zend_hash_index_del(&pimple_obj->factories, index);
-		zend_hash_index_del(&pimple_obj->protected, index);
-	break;
-	default:
-		zend_error(E_WARNING, "Unsupported offset type");
-	}
-}
-
-static int pimple_object_has_dimension(zval *object, zval *offset, int check_empty TSRMLS_DC)
-{
-	FETCH_DIM_HANDLERS_VARS
-
-	pimple_bucket_value *retval = NULL;
-
-	switch (Z_TYPE_P(offset)) {
-	case IS_STRING:
-		if (zend_symtable_find(&pimple_obj->values, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, (void **)&retval) == SUCCESS) {
-			switch (check_empty) {
-			case 0: /* isset */
-				return 1; /* Differs from PHP behavior (Z_TYPE_P(retval->value) != IS_NULL;) */
-			case 1: /* empty */
-			default:
-				return zend_is_true(retval->value);
-			}
-		}
-		return 0;
-	break;
-	case IS_DOUBLE:
-	case IS_BOOL:
-	case IS_LONG:
-		if (Z_TYPE_P(offset) == IS_DOUBLE) {
-			index = (ulong)Z_DVAL_P(offset);
-		} else {
-			index = Z_LVAL_P(offset);
-		}
-		if (zend_hash_index_find(&pimple_obj->values, index, (void **)&retval) == SUCCESS) {
-			switch (check_empty) {
-				case 0: /* isset */
-					return 1; /* Differs from PHP behavior (Z_TYPE_P(retval->value) != IS_NULL;)*/
-				case 1: /* empty */
-				default:
-					return zend_is_true(retval->value);
-			}
-		}
-		return 0;
-	break;
-	default:
-		zend_error(E_WARNING, "Unsupported offset type");
-		return 0;
-	}
-}
-
-static zval *pimple_object_read_dimension(zval *object, zval *offset, int type TSRMLS_DC)
-{
-	FETCH_DIM_HANDLERS_VARS
-
-	pimple_bucket_value *retval = NULL;
-	zend_fcall_info fci         = {0};
-	zval *retval_ptr_ptr        = NULL;
-
-	switch (Z_TYPE_P(offset)) {
-	case IS_STRING:
-		if (zend_symtable_find(&pimple_obj->values, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, (void **)&retval) == FAILURE) {
-			pimple_throw_exception_string(pimple_ce_UnknownIdentifierException, Z_STRVAL_P(offset), Z_STRLEN_P(offset) TSRMLS_CC);
-
-			return EG(uninitialized_zval_ptr);
-		}
-	break;
-	case IS_DOUBLE:
-	case IS_BOOL:
-	case IS_LONG:
-		if (Z_TYPE_P(offset) == IS_DOUBLE) {
-			index = (ulong)Z_DVAL_P(offset);
-		} else {
-			index = Z_LVAL_P(offset);
-		}
-		if (zend_hash_index_find(&pimple_obj->values, index, (void **)&retval) == FAILURE) {
-			return EG(uninitialized_zval_ptr);
-		}
-	break;
-	case IS_NULL: /* $p[][3] = 'foo' first dim access */
-		return EG(uninitialized_zval_ptr);
-	break;
-	default:
-		zend_error(E_WARNING, "Unsupported offset type");
-		return EG(uninitialized_zval_ptr);
-	}
-
-	if(retval->type == PIMPLE_IS_PARAM) {
-		return retval->value;
-	}
-
-	if (zend_hash_index_exists(&pimple_obj->protected, retval->handle_num)) {
-		/* Service is protected, return the value every time */
-		return retval->value;
-	}
-
-	if (zend_hash_index_exists(&pimple_obj->factories, retval->handle_num)) {
-		/* Service is a factory, call it every time and never cache its result */
-		PIMPLE_CALL_CB
-		Z_DELREF_P(retval_ptr_ptr); /* fetch dim addr will increment refcount */
-		return retval_ptr_ptr;
-	}
-
-	if (retval->initialized == 1) {
-		/* Service has already been called, return its cached value */
-		return retval->value;
-	}
-
-	ALLOC_INIT_ZVAL(retval->raw);
-	MAKE_COPY_ZVAL(&retval->value, retval->raw);
-
-	PIMPLE_CALL_CB
-
-	retval->initialized = 1;
-	zval_ptr_dtor(&retval->value);
-	retval->value = retval_ptr_ptr;
-
-	return retval->value;
-}
-
-static int pimple_zval_is_valid_callback(zval *_zval, pimple_bucket_value *_pimple_bucket_value TSRMLS_DC)
-{
-	if (Z_TYPE_P(_zval) != IS_OBJECT) {
-		return FAILURE;
-	}
-
-	if (_pimple_bucket_value->fcc.called_scope) {
-		return SUCCESS;
-	}
-
-	if (Z_OBJ_HANDLER_P(_zval, get_closure) && Z_OBJ_HANDLER_P(_zval, get_closure)(_zval, &_pimple_bucket_value->fcc.calling_scope, &_pimple_bucket_value->fcc.function_handler, &_pimple_bucket_value->fcc.object_ptr TSRMLS_CC) == SUCCESS) {
-		_pimple_bucket_value->fcc.called_scope = _pimple_bucket_value->fcc.calling_scope;
-		return SUCCESS;
-	} else {
-		return FAILURE;
-	}
-}
-
-static int pimple_zval_to_pimpleval(zval *_zval, pimple_bucket_value *_pimple_bucket_value TSRMLS_DC)
-{
-	_pimple_bucket_value->value = _zval;
-
-	if (Z_TYPE_P(_zval) != IS_OBJECT) {
-		return PIMPLE_IS_PARAM;
-	}
-
-	if (pimple_zval_is_valid_callback(_zval, _pimple_bucket_value TSRMLS_CC) == SUCCESS) {
-		_pimple_bucket_value->type       = PIMPLE_IS_SERVICE;
-		_pimple_bucket_value->handle_num = Z_OBJ_HANDLE_P(_zval);
-	}
-
-	return PIMPLE_IS_SERVICE;
-}
-
-static void pimple_bucket_dtor(pimple_bucket_value *bucket)
-{
-	zval_ptr_dtor(&bucket->value);
-	pimple_free_bucket(bucket);
-}
-
-PHP_METHOD(FrozenServiceException, __construct)
-{
-	char *id = NULL;
-	int id_len;
-
-	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &id, &id_len) == FAILURE) {
-		return;
-	}
-	pimple_exception_call_parent_constructor(getThis(), "Cannot override frozen service \"%s\".", id TSRMLS_CC);
-}
-
-PHP_METHOD(InvalidServiceIdentifierException, __construct)
-{
-	char *id = NULL;
-	int id_len;
-
-	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &id, &id_len) == FAILURE) {
-		return;
-	}
-	pimple_exception_call_parent_constructor(getThis(), "Identifier \"%s\" does not contain an object definition.", id TSRMLS_CC);
-}
-
-PHP_METHOD(UnknownIdentifierException, __construct)
-{
-	char *id = NULL;
-	int id_len;
-
-	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &id, &id_len) == FAILURE) {
-		return;
-	}
-	pimple_exception_call_parent_constructor(getThis(), "Identifier \"%s\" is not defined.", id TSRMLS_CC);
-}
-
-PHP_METHOD(Pimple, protect)
-{
-	zval *protected     = NULL;
-	pimple_object *pobj = NULL;
-	pimple_bucket_value bucket = {0};
-
-	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &protected) == FAILURE) {
-		return;
-	}
-
-	if (pimple_zval_is_valid_callback(protected, &bucket TSRMLS_CC) == FAILURE) {
-		pimple_free_bucket(&bucket);
-		zend_throw_exception(pimple_ce_ExpectedInvokableException, "Callable is not a Closure or invokable object.", 0 TSRMLS_CC);
-		return;
-	}
-
-	pimple_zval_to_pimpleval(protected, &bucket TSRMLS_CC);
-	pobj = (pimple_object *)zend_object_store_get_object(getThis() TSRMLS_CC);
-
-	if (zend_hash_index_update(&pobj->protected, bucket.handle_num, (void *)&bucket, sizeof(pimple_bucket_value), NULL) == SUCCESS) {
-		Z_ADDREF_P(protected);
-		RETURN_ZVAL(protected, 1 , 0);
-	} else {
-		pimple_free_bucket(&bucket);
-	}
-	RETURN_FALSE;
-}
-
-PHP_METHOD(Pimple, raw)
-{
-	zval *offset = NULL;
-	pimple_object *pobj        = NULL;
-	pimple_bucket_value *value = NULL;
-	ulong index;
-
-	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &offset) == FAILURE) {
-		return;
-	}
-
-	pobj = zend_object_store_get_object(getThis() TSRMLS_CC);
-
-	switch (Z_TYPE_P(offset)) {
-		case IS_STRING:
-			if (zend_symtable_find(&pobj->values, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, (void *)&value) == FAILURE) {
-				pimple_throw_exception_string(pimple_ce_UnknownIdentifierException, Z_STRVAL_P(offset), Z_STRLEN_P(offset) TSRMLS_CC);
-				RETURN_NULL();
-			}
-		break;
-		case IS_DOUBLE:
-		case IS_BOOL:
-		case IS_LONG:
-			if (Z_TYPE_P(offset) == IS_DOUBLE) {
-				index = (ulong)Z_DVAL_P(offset);
-			} else {
-				index = Z_LVAL_P(offset);
-			}
-			if (zend_hash_index_find(&pobj->values, index, (void *)&value) == FAILURE) {
-				RETURN_NULL();
-			}
-		break;
-		case IS_NULL:
-		default:
-			zend_error(E_WARNING, "Unsupported offset type");
-	}
-
-	if (value->raw) {
-		RETVAL_ZVAL(value->raw, 1, 0);
-	} else {
-		RETVAL_ZVAL(value->value, 1, 0);
-	}
-}
-
-PHP_METHOD(Pimple, extend)
-{
-	zval *offset = NULL, *callable = NULL, *pimple_closure_obj = NULL;
-	pimple_bucket_value bucket = {0}, *value = NULL;
-	pimple_object *pobj          = NULL;
-	pimple_closure_object *pcobj = NULL;
-	ulong index;
-
-	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zz", &offset, &callable) == FAILURE) {
-		return;
-	}
-
-	pobj = zend_object_store_get_object(getThis() TSRMLS_CC);
-
-	switch (Z_TYPE_P(offset)) {
-		case IS_STRING:
-			if (zend_symtable_find(&pobj->values, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, (void *)&value) == FAILURE) {
-				pimple_throw_exception_string(pimple_ce_UnknownIdentifierException, Z_STRVAL_P(offset), Z_STRLEN_P(offset) TSRMLS_CC);
-				RETURN_NULL();
-			}
-
-			if (value->type != PIMPLE_IS_SERVICE) {
-				pimple_throw_exception_string(pimple_ce_InvalidServiceIdentifierException, Z_STRVAL_P(offset), Z_STRLEN_P(offset) TSRMLS_CC);
-				RETURN_NULL();
-			}
-			if (zend_hash_index_exists(&pobj->protected, value->handle_num)) {
-				int er = EG(error_reporting);
-				EG(error_reporting) = 0;
-				php_error(E_DEPRECATED, "How Pimple behaves when extending protected closures will be fixed in Pimple 4. Are you sure \"%s\" should be protected?", Z_STRVAL_P(offset));
-				EG(error_reporting) = er;
-			}
-		break;
-		case IS_DOUBLE:
-		case IS_BOOL:
-		case IS_LONG:
-			if (Z_TYPE_P(offset) == IS_DOUBLE) {
-				index = (ulong)Z_DVAL_P(offset);
-			} else {
-				index = Z_LVAL_P(offset);
-			}
-			if (zend_hash_index_find(&pobj->values, index, (void *)&value) == FAILURE) {
-				convert_to_string(offset);
-				pimple_throw_exception_string(pimple_ce_UnknownIdentifierException, Z_STRVAL_P(offset), Z_STRLEN_P(offset) TSRMLS_CC);
-				RETURN_NULL();
-			}
-			if (value->type != PIMPLE_IS_SERVICE) {
-				convert_to_string(offset);
-				pimple_throw_exception_string(pimple_ce_InvalidServiceIdentifierException, Z_STRVAL_P(offset), Z_STRLEN_P(offset) TSRMLS_CC);
-				RETURN_NULL();
-			}
-			if (zend_hash_index_exists(&pobj->protected, value->handle_num)) {
-				int er = EG(error_reporting);
-				EG(error_reporting) = 0;
-				php_error(E_DEPRECATED, "How Pimple behaves when extending protected closures will be fixed in Pimple 4. Are you sure \"%ld\" should be protected?", index);
-				EG(error_reporting) = er;
-			}
-		break;
-		case IS_NULL:
-		default:
-			zend_error(E_WARNING, "Unsupported offset type");
-	}
-
-	if (pimple_zval_is_valid_callback(callable, &bucket TSRMLS_CC) == FAILURE) {
-		pimple_free_bucket(&bucket);
-		zend_throw_exception(pimple_ce_ExpectedInvokableException, "Extension service definition is not a Closure or invokable object.", 0 TSRMLS_CC);
-		RETURN_NULL();
-	}
-	pimple_free_bucket(&bucket);
-
-	ALLOC_INIT_ZVAL(pimple_closure_obj);
-	object_init_ex(pimple_closure_obj, pimple_closure_ce);
-
-	pcobj = zend_object_store_get_object(pimple_closure_obj TSRMLS_CC);
-	pcobj->callable = callable;
-	pcobj->factory  = value->value;
-	Z_ADDREF_P(callable);
-	Z_ADDREF_P(value->value);
-
-	if (zend_hash_index_exists(&pobj->factories, value->handle_num)) {
-		pimple_zval_to_pimpleval(pimple_closure_obj, &bucket TSRMLS_CC);
-		zend_hash_index_del(&pobj->factories, value->handle_num);
-		zend_hash_index_update(&pobj->factories, bucket.handle_num, (void *)&bucket, sizeof(pimple_bucket_value), NULL);
-		Z_ADDREF_P(pimple_closure_obj);
-	}
-
-	pimple_object_write_dimension(getThis(), offset, pimple_closure_obj TSRMLS_CC);
-
-	RETVAL_ZVAL(pimple_closure_obj, 1, 1);
-}
-
-PHP_METHOD(Pimple, keys)
-{
-	HashPosition pos;
-	pimple_object *pobj = NULL;
-	zval **value        = NULL;
-	zval *endval        = NULL;
-	char *str_index     = NULL;
-	int str_len;
-	ulong num_index;
-
-	if (zend_parse_parameters_none() == FAILURE) {
-		return;
-	}
-
-	pobj = zend_object_store_get_object(getThis() TSRMLS_CC);
-	array_init_size(return_value, zend_hash_num_elements(&pobj->values));
-
-	zend_hash_internal_pointer_reset_ex(&pobj->values, &pos);
-
-	while(zend_hash_get_current_data_ex(&pobj->values, (void **)&value, &pos) == SUCCESS) {
-		MAKE_STD_ZVAL(endval);
-		switch (zend_hash_get_current_key_ex(&pobj->values, &str_index, (uint *)&str_len, &num_index, 0, &pos)) {
-			case HASH_KEY_IS_STRING:
-				ZVAL_STRINGL(endval, str_index, str_len - 1, 1);
-				zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &endval, sizeof(zval *), NULL);
-			break;
-			case HASH_KEY_IS_LONG:
-				ZVAL_LONG(endval, num_index);
-				zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &endval, sizeof(zval *), NULL);
-			break;
-		}
-	zend_hash_move_forward_ex(&pobj->values, &pos);
-	}
-}
-
-PHP_METHOD(Pimple, factory)
-{
-	zval *factory       = NULL;
-	pimple_object *pobj = NULL;
-	pimple_bucket_value bucket = {0};
-
-	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &factory) == FAILURE) {
-		return;
-	}
-
-	if (pimple_zval_is_valid_callback(factory, &bucket TSRMLS_CC) == FAILURE) {
-		pimple_free_bucket(&bucket);
-		zend_throw_exception(pimple_ce_ExpectedInvokableException, "Service definition is not a Closure or invokable object.", 0 TSRMLS_CC);
-		return;
-	}
-
-	pimple_zval_to_pimpleval(factory, &bucket TSRMLS_CC);
-	pobj = (pimple_object *)zend_object_store_get_object(getThis() TSRMLS_CC);
-
-	if (zend_hash_index_update(&pobj->factories, bucket.handle_num, (void *)&bucket, sizeof(pimple_bucket_value), NULL) == SUCCESS) {
-		Z_ADDREF_P(factory);
-		RETURN_ZVAL(factory, 1 , 0);
-	} else {
-		pimple_free_bucket(&bucket);
-	}
-
-	RETURN_FALSE;
-}
-
-PHP_METHOD(Pimple, offsetSet)
-{
-	zval *offset = NULL, *value = NULL;
-
-	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zz", &offset, &value) == FAILURE) {
-		return;
-	}
-
-	pimple_object_write_dimension(getThis(), offset, value TSRMLS_CC);
-}
-
-PHP_METHOD(Pimple, offsetGet)
-{
-	zval *offset = NULL, *retval = NULL;
-
-	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &offset) == FAILURE) {
-		return;
-	}
-
-	retval = pimple_object_read_dimension(getThis(), offset, 0 TSRMLS_CC);
-
-	RETVAL_ZVAL(retval, 1, 0);
-}
-
-PHP_METHOD(Pimple, offsetUnset)
-{
-	zval *offset = NULL;
-
-	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &offset) == FAILURE) {
-		return;
-	}
-
-	pimple_object_unset_dimension(getThis(), offset TSRMLS_CC);
-}
-
-PHP_METHOD(Pimple, offsetExists)
-{
-	zval *offset = NULL;
-
-	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &offset) == FAILURE) {
-		return;
-	}
-
-	RETVAL_BOOL(pimple_object_has_dimension(getThis(), offset, 1 TSRMLS_CC));
-}
-
-PHP_METHOD(Pimple, register)
-{
-	zval *provider;
-	zval **data;
-	zval *retval = NULL;
-	zval key;
-
-	HashTable *array = NULL;
-	HashPosition pos;
-
-	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O|h", &provider, pimple_serviceprovider_ce, &array) == FAILURE) {
-		return;
-	}
-
-	RETVAL_ZVAL(getThis(), 1, 0);
-
-	zend_call_method_with_1_params(&provider, Z_OBJCE_P(provider), NULL, "register", &retval, getThis());
-
-	if (retval) {
-		zval_ptr_dtor(&retval);
-	}
-
-	if (!array) {
-		return;
-	}
-
-	zend_hash_internal_pointer_reset_ex(array, &pos);
-
-	while(zend_hash_get_current_data_ex(array, (void **)&data, &pos) == SUCCESS) {
-		zend_hash_get_current_key_zval_ex(array, &key, &pos);
-		pimple_object_write_dimension(getThis(), &key, *data TSRMLS_CC);
-		zend_hash_move_forward_ex(array, &pos);
-	}
-}
-
-PHP_METHOD(Pimple, __construct)
-{
-	zval *values = NULL, **pData = NULL, offset;
-	HashPosition pos;
-	char *str_index = NULL;
-	zend_uint str_length;
-	ulong num_index;
-
-	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|a!", &values) == FAILURE) {
-		return;
-	}
-
-	PIMPLE_DEPRECATE
-
-	if (!values) {
-		return;
-	}
-
-	zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(values), &pos);
-	while (zend_hash_has_more_elements_ex(Z_ARRVAL_P(values), &pos) == SUCCESS) {
-			zend_hash_get_current_data_ex(Z_ARRVAL_P(values), (void **)&pData, &pos);
-			zend_hash_get_current_key_ex(Z_ARRVAL_P(values), &str_index, &str_length, &num_index, 0, &pos);
-			INIT_ZVAL(offset);
-			if (zend_hash_get_current_key_type_ex(Z_ARRVAL_P(values), &pos) == HASH_KEY_IS_LONG) {
-				ZVAL_LONG(&offset, num_index);
-			} else {
-				ZVAL_STRINGL(&offset, str_index, (str_length - 1), 0);
-			}
-		pimple_object_write_dimension(getThis(), &offset, *pData TSRMLS_CC);
-		zend_hash_move_forward_ex(Z_ARRVAL_P(values), &pos);
-	}
-}
-
-/*
- * This is PHP code snippet handling extend()s calls :
-
-  $extended = function ($c) use ($callable, $factory) {
-      return $callable($factory($c), $c);
-  };
-
- */
-PHP_METHOD(PimpleClosure, invoker)
-{
-	pimple_closure_object *pcobj = NULL;
-	zval *arg = NULL, *retval = NULL, *newretval = NULL;
-	zend_fcall_info fci        = {0};
-	zval **args[2];
-
-	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &arg) == FAILURE) {
-		return;
-	}
-
-	pcobj = zend_object_store_get_object(getThis() TSRMLS_CC);
-
-	fci.function_name = pcobj->factory;
-	args[0] = &arg;
-	zend_fcall_info_argp(&fci TSRMLS_CC, 1, args);
-	fci.retval_ptr_ptr = &retval;
-	fci.size = sizeof(fci);
-
-	if (zend_call_function(&fci, NULL TSRMLS_CC) == FAILURE || EG(exception)) {
-		efree(fci.params);
-		return; /* Should here return default zval */
-	}
-
-	efree(fci.params);
-	memset(&fci, 0, sizeof(fci));
-	fci.size = sizeof(fci);
-
-	fci.function_name = pcobj->callable;
-	args[0] = &retval;
-	args[1] = &arg;
-	zend_fcall_info_argp(&fci TSRMLS_CC, 2, args);
-	fci.retval_ptr_ptr = &newretval;
-
-	if (zend_call_function(&fci, NULL TSRMLS_CC) == FAILURE || EG(exception)) {
-		efree(fci.params);
-		zval_ptr_dtor(&retval);
-		return;
-	}
-
-	efree(fci.params);
-	zval_ptr_dtor(&retval);
-
-	RETVAL_ZVAL(newretval, 1 ,1);
-}
-
-PHP_MINIT_FUNCTION(pimple)
-{
-	zend_class_entry tmp_ce_PsrContainerInterface, tmp_ce_PsrContainerExceptionInterface, tmp_ce_PsrNotFoundExceptionInterface;
-	zend_class_entry tmp_ce_ExpectedInvokableException, tmp_ce_FrozenServiceException, tmp_ce_InvalidServiceIdentifierException, tmp_ce_UnknownIdentifierException;
-	zend_class_entry tmp_pimple_ce, tmp_pimple_closure_ce, tmp_pimple_serviceprovider_iface_ce;
-
-	/* Psr\Container namespace */
-	INIT_NS_CLASS_ENTRY(tmp_ce_PsrContainerInterface,          PSR_CONTAINER_NS, "ContainerInterface",           pimple_ce_PsrContainerInterface_functions);
-	INIT_NS_CLASS_ENTRY(tmp_ce_PsrContainerExceptionInterface, PSR_CONTAINER_NS, "ContainerExceptionInterface", pimple_ce_PsrContainerExceptionInterface_functions);
-	INIT_NS_CLASS_ENTRY(tmp_ce_PsrNotFoundExceptionInterface,  PSR_CONTAINER_NS, "NotFoundExceptionInterface",  pimple_ce_PsrNotFoundExceptionInterface_functions);
-
-	pimple_ce_PsrContainerInterface          = zend_register_internal_interface(&tmp_ce_PsrContainerInterface TSRMLS_CC);
-	pimple_ce_PsrContainerExceptionInterface = zend_register_internal_interface(&tmp_ce_PsrContainerExceptionInterface TSRMLS_CC);
-	pimple_ce_PsrNotFoundExceptionInterface  = zend_register_internal_interface(&tmp_ce_PsrNotFoundExceptionInterface TSRMLS_CC);
-
-	zend_class_implements(pimple_ce_PsrNotFoundExceptionInterface TSRMLS_CC, 1, pimple_ce_PsrContainerExceptionInterface);
-
-	/* Pimple\Exception namespace */
-	INIT_NS_CLASS_ENTRY(tmp_ce_ExpectedInvokableException,        PIMPLE_EXCEPTION_NS, "ExpectedInvokableException",         NULL);
-	INIT_NS_CLASS_ENTRY(tmp_ce_FrozenServiceException,            PIMPLE_EXCEPTION_NS, "FrozenServiceException",             pimple_ce_FrozenServiceException_functions);
-	INIT_NS_CLASS_ENTRY(tmp_ce_InvalidServiceIdentifierException, PIMPLE_EXCEPTION_NS, "InvalidServiceIdentifierException", pimple_ce_InvalidServiceIdentifierException_functions);
-	INIT_NS_CLASS_ENTRY(tmp_ce_UnknownIdentifierException,        PIMPLE_EXCEPTION_NS, "UnknownIdentifierException",         pimple_ce_UnknownIdentifierException_functions);
-
-	pimple_ce_ExpectedInvokableException        = zend_register_internal_class_ex(&tmp_ce_ExpectedInvokableException, spl_ce_InvalidArgumentException, NULL TSRMLS_CC);
-	pimple_ce_FrozenServiceException            = zend_register_internal_class_ex(&tmp_ce_FrozenServiceException, spl_ce_RuntimeException, NULL TSRMLS_CC);
-	pimple_ce_InvalidServiceIdentifierException = zend_register_internal_class_ex(&tmp_ce_InvalidServiceIdentifierException, spl_ce_InvalidArgumentException, NULL TSRMLS_CC);
-	pimple_ce_UnknownIdentifierException        = zend_register_internal_class_ex(&tmp_ce_UnknownIdentifierException, spl_ce_InvalidArgumentException, NULL TSRMLS_CC);
-
-	zend_class_implements(pimple_ce_ExpectedInvokableException TSRMLS_CC,        1, pimple_ce_PsrContainerExceptionInterface);
-	zend_class_implements(pimple_ce_FrozenServiceException TSRMLS_CC,            1, pimple_ce_PsrContainerExceptionInterface);
-	zend_class_implements(pimple_ce_InvalidServiceIdentifierException TSRMLS_CC, 1, pimple_ce_PsrContainerExceptionInterface);
-	zend_class_implements(pimple_ce_UnknownIdentifierException TSRMLS_CC,        1, pimple_ce_PsrNotFoundExceptionInterface);
-
-    /* Pimple namespace */
-	INIT_NS_CLASS_ENTRY(tmp_pimple_ce, PIMPLE_NS, "Container", pimple_ce_functions);
-	INIT_NS_CLASS_ENTRY(tmp_pimple_closure_ce, PIMPLE_NS, "ContainerClosure", NULL);
-	INIT_NS_CLASS_ENTRY(tmp_pimple_serviceprovider_iface_ce, PIMPLE_NS, "ServiceProviderInterface", pimple_serviceprovider_iface_ce_functions);
-
-	tmp_pimple_ce.create_object         = pimple_object_create;
-	tmp_pimple_closure_ce.create_object = pimple_closure_object_create;
-
-	pimple_ce = zend_register_internal_class(&tmp_pimple_ce TSRMLS_CC);
-	zend_class_implements(pimple_ce TSRMLS_CC, 1, zend_ce_arrayaccess);
-
-	pimple_closure_ce = zend_register_internal_class(&tmp_pimple_closure_ce TSRMLS_CC);
-	pimple_closure_ce->ce_flags |= ZEND_ACC_FINAL_CLASS;
-
-	pimple_serviceprovider_ce = zend_register_internal_interface(&tmp_pimple_serviceprovider_iface_ce TSRMLS_CC);
-
-	memcpy(&pimple_closure_object_handlers, zend_get_std_object_handlers(), sizeof(*zend_get_std_object_handlers()));
-	pimple_object_handlers                     = std_object_handlers;
-	pimple_closure_object_handlers.get_closure = pimple_closure_get_closure;
-
-	pimple_closure_invoker_function.function_name     = "Pimple closure internal invoker";
-	pimple_closure_invoker_function.fn_flags         |= ZEND_ACC_CLOSURE;
-	pimple_closure_invoker_function.handler           = ZEND_MN(PimpleClosure_invoker);
-	pimple_closure_invoker_function.num_args          = 1;
-	pimple_closure_invoker_function.required_num_args = 1;
-	pimple_closure_invoker_function.scope             = pimple_closure_ce;
-	pimple_closure_invoker_function.type              = ZEND_INTERNAL_FUNCTION;
-	pimple_closure_invoker_function.module            = &pimple_module_entry;
-
-	return SUCCESS;
-}
-
-PHP_MINFO_FUNCTION(pimple)
-{
-	php_info_print_table_start();
-	php_info_print_table_header(2, "SensioLabs Pimple C support", "enabled");
-	php_info_print_table_row(2, "Pimple supported version", PIMPLE_VERSION);
-	php_info_print_table_end();
-
-	php_info_print_box_start(0);
-	php_write((void *)ZEND_STRL("SensioLabs Pimple C support developed by Julien Pauli") TSRMLS_CC);
-	if (!sapi_module.phpinfo_as_text) {
-		php_write((void *)ZEND_STRL(sensiolabs_logo) TSRMLS_CC);
-	}
-	php_info_print_box_end();
-}
-
-zend_module_entry pimple_module_entry = {
-	STANDARD_MODULE_HEADER,
-	"pimple",
-	NULL,
-	PHP_MINIT(pimple),
-	NULL,
-	NULL,
-	NULL,
-	PHP_MINFO(pimple),
-	PIMPLE_VERSION,
-	STANDARD_MODULE_PROPERTIES
-};
-
-#ifdef COMPILE_DL_PIMPLE
-ZEND_GET_MODULE(pimple)
-#endif
diff --git a/vendor/pimple/pimple/ext/pimple/pimple_compat.h b/vendor/pimple/pimple/ext/pimple/pimple_compat.h
deleted file mode 100644
index d234e174d0aa7e31d855af634a8ffb6ebc9c4877..0000000000000000000000000000000000000000
--- a/vendor/pimple/pimple/ext/pimple/pimple_compat.h
+++ /dev/null
@@ -1,81 +0,0 @@
-
-/*
- * This file is part of Pimple.
- *
- * Copyright (c) 2014 Fabien Potencier
- *
- * 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.
- */
-
-#ifndef PIMPLE_COMPAT_H_
-#define PIMPLE_COMPAT_H_
-
-#include "Zend/zend_extensions.h" /* for ZEND_EXTENSION_API_NO */
-
-#define PHP_5_0_X_API_NO		220040412
-#define PHP_5_1_X_API_NO		220051025
-#define PHP_5_2_X_API_NO		220060519
-#define PHP_5_3_X_API_NO		220090626
-#define PHP_5_4_X_API_NO		220100525
-#define PHP_5_5_X_API_NO		220121212
-#define PHP_5_6_X_API_NO		220131226
-
-#define IS_PHP_56 ZEND_EXTENSION_API_NO == PHP_5_6_X_API_NO
-#define IS_AT_LEAST_PHP_56 ZEND_EXTENSION_API_NO >= PHP_5_6_X_API_NO
-
-#define IS_PHP_55 ZEND_EXTENSION_API_NO == PHP_5_5_X_API_NO
-#define IS_AT_LEAST_PHP_55 ZEND_EXTENSION_API_NO >= PHP_5_5_X_API_NO
-
-#define IS_PHP_54 ZEND_EXTENSION_API_NO == PHP_5_4_X_API_NO
-#define IS_AT_LEAST_PHP_54 ZEND_EXTENSION_API_NO >= PHP_5_4_X_API_NO
-
-#define IS_PHP_53 ZEND_EXTENSION_API_NO == PHP_5_3_X_API_NO
-#define IS_AT_LEAST_PHP_53 ZEND_EXTENSION_API_NO >= PHP_5_3_X_API_NO
-
-#if IS_PHP_53
-#define object_properties_init(obj, ce) do { \
-		 zend_hash_copy(obj->properties, &ce->default_properties, zval_copy_property_ctor(ce), NULL, sizeof(zval *)); \
-		} while (0);
-#endif
-
-#define ZEND_OBJ_INIT(obj, ce) do { \
-		zend_object_std_init(obj, ce TSRMLS_CC); \
-		object_properties_init((obj), (ce)); \
-	} while(0);
-
-#if IS_PHP_53 || IS_PHP_54
-static void zend_hash_get_current_key_zval_ex(const HashTable *ht, zval *key, HashPosition *pos) {
-    Bucket *p;
-
-    p = pos ? (*pos) : ht->pInternalPointer;
-
-    if (!p) {
-        Z_TYPE_P(key) = IS_NULL;
-    } else if (p->nKeyLength) {
-        Z_TYPE_P(key) = IS_STRING;
-        Z_STRVAL_P(key) = estrndup(p->arKey, p->nKeyLength - 1);
-        Z_STRLEN_P(key) = p->nKeyLength - 1;
-    } else {
-        Z_TYPE_P(key) = IS_LONG;
-        Z_LVAL_P(key) = p->h;
-    }
-}
-#endif
-
-#endif /* PIMPLE_COMPAT_H_ */
diff --git a/vendor/pimple/pimple/ext/pimple/tests/001.phpt b/vendor/pimple/pimple/ext/pimple/tests/001.phpt
deleted file mode 100644
index 0809ea232b66d332697df24816d1a050030d7e6f..0000000000000000000000000000000000000000
--- a/vendor/pimple/pimple/ext/pimple/tests/001.phpt
+++ /dev/null
@@ -1,45 +0,0 @@
---TEST--
-Test for read_dim/write_dim handlers
---SKIPIF--
-<?php if (!extension_loaded("pimple")) print "skip"; ?>
---FILE--
-<?php 
-$p = new Pimple\Container();
-$p[42] = 'foo';
-$p['foo'] = 42;
-
-echo $p[42];
-echo "\n";
-echo $p['foo'];
-echo "\n";
-try {
-	var_dump($p['nonexistant']);
-	echo "Exception excpected";
-} catch (InvalidArgumentException $e) { }
-
-$p[54.2] = 'foo2';
-echo $p[54];
-echo "\n";
-$p[242.99] = 'foo99';
-echo $p[242];
-
-echo "\n";
-
-$p[5] = 'bar';
-$p[5] = 'baz';
-echo $p[5];
-
-echo "\n";
-
-$p['str'] = 'str';
-$p['str'] = 'strstr';
-echo $p['str'];
-?>
-
---EXPECTF--
-foo
-42
-foo2
-foo99
-baz
-strstr
\ No newline at end of file
diff --git a/vendor/pimple/pimple/ext/pimple/tests/002.phpt b/vendor/pimple/pimple/ext/pimple/tests/002.phpt
deleted file mode 100644
index 7b56d2c1fe8bbfcb0d93b1faa65f8fff4e363762..0000000000000000000000000000000000000000
--- a/vendor/pimple/pimple/ext/pimple/tests/002.phpt
+++ /dev/null
@@ -1,15 +0,0 @@
---TEST--
-Test for constructor
---SKIPIF--
-<?php if (!extension_loaded("pimple")) print "skip"; ?>
---FILE--
-<?php 
-$p = new Pimple\Container();
-var_dump($p[42]);
-
-$p = new Pimple\Container(array(42=>'foo'));
-var_dump($p[42]);
-?>
---EXPECT--
-NULL
-string(3) "foo"
diff --git a/vendor/pimple/pimple/ext/pimple/tests/003.phpt b/vendor/pimple/pimple/ext/pimple/tests/003.phpt
deleted file mode 100644
index a22cfa352ea61f2edfbd659e1d5152eaf2d6b422..0000000000000000000000000000000000000000
--- a/vendor/pimple/pimple/ext/pimple/tests/003.phpt
+++ /dev/null
@@ -1,16 +0,0 @@
---TEST--
-Test empty dimensions
---SKIPIF--
-<?php if (!extension_loaded("pimple")) print "skip"; ?>
---FILE--
-<?php 
-$p = new Pimple\Container();
-$p[] = 42;
-var_dump($p[0]);
-$p[41] = 'foo';
-$p[] = 'bar';
-var_dump($p[42]);
-?>
---EXPECT--
-int(42)
-string(3) "bar"
\ No newline at end of file
diff --git a/vendor/pimple/pimple/ext/pimple/tests/004.phpt b/vendor/pimple/pimple/ext/pimple/tests/004.phpt
deleted file mode 100644
index 1e1d251367928dccd004c0b8df07119acbe2b9e9..0000000000000000000000000000000000000000
--- a/vendor/pimple/pimple/ext/pimple/tests/004.phpt
+++ /dev/null
@@ -1,30 +0,0 @@
---TEST--
-Test has/unset dim handlers
---SKIPIF--
-<?php if (!extension_loaded("pimple")) print "skip"; ?>
---FILE--
-<?php 
-$p = new Pimple\Container();
-$p[] = 42;
-var_dump($p[0]);
-unset($p[0]);
-var_dump($p[0]);
-$p['foo'] = 'bar';
-var_dump(isset($p['foo']));
-unset($p['foo']);
-try {
-	var_dump($p['foo']);
-	echo "Excpected exception";
-} catch (InvalidArgumentException $e) { }
-var_dump(isset($p['bar']));
-$p['bar'] = NULL;
-var_dump(isset($p['bar']));
-var_dump(empty($p['bar']));
-?>
---EXPECT--
-int(42)
-NULL
-bool(true)
-bool(false)
-bool(true)
-bool(true)
\ No newline at end of file
diff --git a/vendor/pimple/pimple/ext/pimple/tests/005.phpt b/vendor/pimple/pimple/ext/pimple/tests/005.phpt
deleted file mode 100644
index 0479ee055deda89a5b0a811e2c2aefec1ca7c38e..0000000000000000000000000000000000000000
--- a/vendor/pimple/pimple/ext/pimple/tests/005.phpt
+++ /dev/null
@@ -1,27 +0,0 @@
---TEST--
-Test simple class inheritance
---SKIPIF--
-<?php if (!extension_loaded("pimple")) print "skip"; ?>
---FILE--
-<?php 
-class MyPimple extends Pimple\Container
-{
-	public $someAttr = 'fooAttr';
-
-    public function offsetget($o)
-    {
-        var_dump("hit");
-        return parent::offsetget($o);
-    }
-}
-
-$p = new MyPimple;
-$p[42] = 'foo';
-echo $p[42];
-echo "\n";
-echo $p->someAttr;
-?>
---EXPECT--
-string(3) "hit"
-foo
-fooAttr
\ No newline at end of file
diff --git a/vendor/pimple/pimple/ext/pimple/tests/006.phpt b/vendor/pimple/pimple/ext/pimple/tests/006.phpt
deleted file mode 100644
index cfe8a119e63a5a778890b0b21efe871a7f2fa437..0000000000000000000000000000000000000000
--- a/vendor/pimple/pimple/ext/pimple/tests/006.phpt
+++ /dev/null
@@ -1,51 +0,0 @@
---TEST--
-Test complex class inheritance
---SKIPIF--
-<?php if (!extension_loaded("pimple")) print "skip"; ?>
---FILE--
-<?php 
-class MyPimple extends Pimple\Container
-{
-    public function offsetget($o)
-    {
-        var_dump("hit offsetget in " . __CLASS__);
-        return parent::offsetget($o);
-    }
-}
-
-class TestPimple extends MyPimple
-{
-    public function __construct($values)
-    {
-        array_shift($values);
-        parent::__construct($values);
-    }
-    
-    public function offsetget($o)
-    {
-        var_dump('hit offsetget in ' . __CLASS__);
-        return parent::offsetget($o);
-    }
-    
-    public function offsetset($o, $v)
-    {
-        var_dump('hit offsetset');
-        return parent::offsetset($o, $v);
-    }
-}
-
-$defaultValues = array('foo' => 'bar', 88 => 'baz');
-
-$p = new TestPimple($defaultValues);
-$p[42] = 'foo';
-var_dump($p[42]);
-var_dump($p[0]);
-?>
---EXPECT--
-string(13) "hit offsetset"
-string(27) "hit offsetget in TestPimple"
-string(25) "hit offsetget in MyPimple"
-string(3) "foo"
-string(27) "hit offsetget in TestPimple"
-string(25) "hit offsetget in MyPimple"
-string(3) "baz"
\ No newline at end of file
diff --git a/vendor/pimple/pimple/ext/pimple/tests/007.phpt b/vendor/pimple/pimple/ext/pimple/tests/007.phpt
deleted file mode 100644
index 5aac6838064303ede671cf8c4504472296c1bb80..0000000000000000000000000000000000000000
--- a/vendor/pimple/pimple/ext/pimple/tests/007.phpt
+++ /dev/null
@@ -1,22 +0,0 @@
---TEST--
-Test for read_dim/write_dim handlers
---SKIPIF--
-<?php if (!extension_loaded("pimple")) print "skip"; ?>
---FILE--
-<?php 
-$p = new Pimple\Container();
-$p[42] = 'foo';
-$p['foo'] = 42;
-
-echo $p[42];
-echo "\n";
-echo $p['foo'];
-echo "\n";
-try {
-	var_dump($p['nonexistant']);
-	echo "Exception excpected";
-} catch (InvalidArgumentException $e) { }
-?>
---EXPECTF--
-foo
-42
\ No newline at end of file
diff --git a/vendor/pimple/pimple/ext/pimple/tests/008.phpt b/vendor/pimple/pimple/ext/pimple/tests/008.phpt
deleted file mode 100644
index db7eeec4a11315c3c7c200424c5ca1b3ac218cb4..0000000000000000000000000000000000000000
--- a/vendor/pimple/pimple/ext/pimple/tests/008.phpt
+++ /dev/null
@@ -1,29 +0,0 @@
---TEST--
-Test frozen services
---SKIPIF--
-<?php if (!extension_loaded("pimple")) print "skip"; ?>
---FILE--
-<?php 
-$p = new Pimple\Container();
-$p[42] = 'foo';
-$p[42] = 'bar';
-
-$p['foo'] = function () { };
-$p['foo'] = function () { };
-
-$a = $p['foo'];
-
-try {
-	$p['foo'] = function () { };
-	echo "Exception excpected";
-} catch (RuntimeException $e) { }
-
-$p[42] = function() { };
-$a = $p[42];
-
-try {
-	$p[42] = function () { };
-	echo "Exception excpected";
-} catch (RuntimeException $e) { }
-?>
---EXPECTF--
diff --git a/vendor/pimple/pimple/ext/pimple/tests/009.phpt b/vendor/pimple/pimple/ext/pimple/tests/009.phpt
deleted file mode 100644
index bb05ea296485b81727eb2155ffe641f1810c4a33..0000000000000000000000000000000000000000
--- a/vendor/pimple/pimple/ext/pimple/tests/009.phpt
+++ /dev/null
@@ -1,13 +0,0 @@
---TEST--
-Test service is called as callback, and only once
---SKIPIF--
-<?php if (!extension_loaded("pimple")) print "skip"; ?>
---FILE--
-<?php 
-$p = new Pimple\Container();
-$p['foo'] = function($arg) use ($p) { var_dump($p === $arg); };
-$a = $p['foo'];
-$b = $p['foo']; /* should return not calling the callback */
-?>
---EXPECTF--
-bool(true)
\ No newline at end of file
diff --git a/vendor/pimple/pimple/ext/pimple/tests/010.phpt b/vendor/pimple/pimple/ext/pimple/tests/010.phpt
deleted file mode 100644
index badce0146a910be411dacb8fcaa9b763205e468b..0000000000000000000000000000000000000000
--- a/vendor/pimple/pimple/ext/pimple/tests/010.phpt
+++ /dev/null
@@ -1,45 +0,0 @@
---TEST--
-Test service is called as callback for every callback type
---SKIPIF--
-<?php if (!extension_loaded("pimple")) print "skip"; ?>
---FILE--
-<?php
-function callme()
-{
-    return 'called';
-}
-
-$a = function() { return 'called'; };
-
-class Foo
-{
-    public static function bar()
-    {
-        return 'called';
-    }
-}
- 
-$p = new Pimple\Container();
-$p['foo'] = 'callme';
-echo $p['foo'] . "\n";
-
-$p['bar'] = $a;
-echo $p['bar'] . "\n";
-
-$p['baz'] = "Foo::bar";
-echo $p['baz'] . "\n";
-
-$p['foobar'] = array('Foo', 'bar');
-var_dump($p['foobar']);
-
-?>
---EXPECTF--
-callme
-called
-Foo::bar
-array(2) {
-  [0]=>
-  string(3) "Foo"
-  [1]=>
-  string(3) "bar"
-}
\ No newline at end of file
diff --git a/vendor/pimple/pimple/ext/pimple/tests/011.phpt b/vendor/pimple/pimple/ext/pimple/tests/011.phpt
deleted file mode 100644
index 6682ab8ebdbc83657f157c8d2ddc5e4e87065c52..0000000000000000000000000000000000000000
--- a/vendor/pimple/pimple/ext/pimple/tests/011.phpt
+++ /dev/null
@@ -1,19 +0,0 @@
---TEST--
-Test service callback throwing an exception
---SKIPIF--
-<?php if (!extension_loaded("pimple")) print "skip"; ?>
---FILE--
-<?php
-class CallBackException extends RuntimeException { }
-
-$p = new Pimple\Container();
-$p['foo'] = function () { throw new CallBackException; };
-try {
-	echo $p['foo'] . "\n";
-	echo "should not come here";
-} catch (CallBackException $e) {
-	echo "all right!";
-}
-?>
---EXPECTF--
-all right!
\ No newline at end of file
diff --git a/vendor/pimple/pimple/ext/pimple/tests/012.phpt b/vendor/pimple/pimple/ext/pimple/tests/012.phpt
deleted file mode 100644
index 4c6ac486dc743bdbbcf4b551bfa9b5787d91707b..0000000000000000000000000000000000000000
--- a/vendor/pimple/pimple/ext/pimple/tests/012.phpt
+++ /dev/null
@@ -1,28 +0,0 @@
---TEST--
-Test service factory
---SKIPIF--
-<?php if (!extension_loaded("pimple")) print "skip"; ?>
---FILE--
-<?php
-
-$p = new Pimple\Container();
-
-$p->factory($f = function() { var_dump('called-1'); return 'ret-1';});
-
-$p[] = $f;
-
-$p[] = function () { var_dump('called-2'); return 'ret-2'; };
-
-var_dump($p[0]);
-var_dump($p[0]);
-var_dump($p[1]);
-var_dump($p[1]);
-?>
---EXPECTF--
-string(8) "called-1"
-string(5) "ret-1"
-string(8) "called-1"
-string(5) "ret-1"
-string(8) "called-2"
-string(5) "ret-2"
-string(5) "ret-2"
\ No newline at end of file
diff --git a/vendor/pimple/pimple/ext/pimple/tests/013.phpt b/vendor/pimple/pimple/ext/pimple/tests/013.phpt
deleted file mode 100644
index f419958c5fa5d45c5c61bd8771bd791b8cc68e76..0000000000000000000000000000000000000000
--- a/vendor/pimple/pimple/ext/pimple/tests/013.phpt
+++ /dev/null
@@ -1,33 +0,0 @@
---TEST--
-Test keys()
---SKIPIF--
-<?php if (!extension_loaded("pimple")) print "skip"; ?>
---FILE--
-<?php
-
-$p = new Pimple\Container();
-
-var_dump($p->keys());
-
-$p['foo'] = 'bar';
-$p[] = 'foo';
-
-var_dump($p->keys());
-
-unset($p['foo']);
-
-var_dump($p->keys());
-?>
---EXPECTF--
-array(0) {
-}
-array(2) {
-  [0]=>
-  string(3) "foo"
-  [1]=>
-  int(0)
-}
-array(1) {
-  [0]=>
-  int(0)
-}
\ No newline at end of file
diff --git a/vendor/pimple/pimple/ext/pimple/tests/014.phpt b/vendor/pimple/pimple/ext/pimple/tests/014.phpt
deleted file mode 100644
index ac937213ac0bccbf0c3f0b54bb4048aa9f19e310..0000000000000000000000000000000000000000
--- a/vendor/pimple/pimple/ext/pimple/tests/014.phpt
+++ /dev/null
@@ -1,30 +0,0 @@
---TEST--
-Test raw()
---SKIPIF--
-<?php if (!extension_loaded("pimple")) print "skip"; ?>
---FILE--
-<?php
-
-$p = new Pimple\Container();
-$f = function () { var_dump('called-2'); return 'ret-2'; };
-
-$p['foo'] = $f;
-$p[42]    = $f;
-
-var_dump($p['foo']);
-var_dump($p->raw('foo'));
-var_dump($p[42]);
-
-unset($p['foo']);
-
-try {
-	$p->raw('foo');
-	echo "expected exception";
-} catch (InvalidArgumentException $e) { }
---EXPECTF--
-string(8) "called-2"
-string(5) "ret-2"
-object(Closure)#%i (0) {
-}
-string(8) "called-2"
-string(5) "ret-2"
\ No newline at end of file
diff --git a/vendor/pimple/pimple/ext/pimple/tests/015.phpt b/vendor/pimple/pimple/ext/pimple/tests/015.phpt
deleted file mode 100644
index 314f008ac1bb1e95b3175c3025dec18cd248c81b..0000000000000000000000000000000000000000
--- a/vendor/pimple/pimple/ext/pimple/tests/015.phpt
+++ /dev/null
@@ -1,17 +0,0 @@
---TEST--
-Test protect()
---SKIPIF--
-<?php if (!extension_loaded("pimple")) print "skip"; ?>
---FILE--
-<?php
-
-$p = new Pimple\Container();
-$f = function () { return 'foo'; };
-$p['foo'] = $f;
-
-$p->protect($f);
-
-var_dump($p['foo']);
---EXPECTF--
-object(Closure)#%i (0) {
-}
\ No newline at end of file
diff --git a/vendor/pimple/pimple/ext/pimple/tests/016.phpt b/vendor/pimple/pimple/ext/pimple/tests/016.phpt
deleted file mode 100644
index e55edb0a7a1310e2386c1b11356e9c62742e4fcf..0000000000000000000000000000000000000000
--- a/vendor/pimple/pimple/ext/pimple/tests/016.phpt
+++ /dev/null
@@ -1,24 +0,0 @@
---TEST--
-Test extend()
---SKIPIF--
-<?php if (!extension_loaded("pimple")) print "skip"; ?>
---FILE--
-<?php
-/*
- This is part of Pimple::extend() code :
-
-          $extended = function ($c) use ($callable, $factory) {
-             return $callable($factory($c), $c);
-          };
-*/
-
-$p = new Pimple\Container();
-$p[12] = function ($v) { var_dump($v); return 'foo';}; /* $factory in code above */
-
-$c = $p->extend(12, function ($w) { var_dump($w); return 'bar'; }); /* $callable in code above */
-
-var_dump($c('param'));
---EXPECTF--
-string(5) "param"
-string(3) "foo"
-string(3) "bar"
\ No newline at end of file
diff --git a/vendor/pimple/pimple/ext/pimple/tests/017.phpt b/vendor/pimple/pimple/ext/pimple/tests/017.phpt
deleted file mode 100644
index bac23ce09a91a8a76c05e7f5fe91f70d8c0fdf89..0000000000000000000000000000000000000000
--- a/vendor/pimple/pimple/ext/pimple/tests/017.phpt
+++ /dev/null
@@ -1,17 +0,0 @@
---TEST--
-Test extend() with exception in service extension
---SKIPIF--
-<?php if (!extension_loaded("pimple")) print "skip"; ?>
---FILE--
-<?php
-
-$p = new Pimple\Container();
-$p[12] = function ($v) { return 'foo';};
-
-$c = $p->extend(12, function ($w) { throw new BadMethodCallException; });
-
-try {
-	$p[12];
-	echo "Exception expected";
-} catch (BadMethodCallException $e) { }
---EXPECTF--
diff --git a/vendor/pimple/pimple/ext/pimple/tests/017_1.phpt b/vendor/pimple/pimple/ext/pimple/tests/017_1.phpt
deleted file mode 100644
index 8f881d6ebf82d852cea6eee020c9f7387a7fdce4..0000000000000000000000000000000000000000
--- a/vendor/pimple/pimple/ext/pimple/tests/017_1.phpt
+++ /dev/null
@@ -1,17 +0,0 @@
---TEST--
-Test extend() with exception in service factory
---SKIPIF--
-<?php if (!extension_loaded("pimple")) print "skip"; ?>
---FILE--
-<?php
-
-$p = new Pimple\Container();
-$p[12] = function ($v) { throw new BadMethodCallException; };
-
-$c = $p->extend(12, function ($w) { return 'foobar'; });
-
-try {
-	$p[12];
-	echo "Exception expected";
-} catch (BadMethodCallException $e) { }
---EXPECTF--
diff --git a/vendor/pimple/pimple/ext/pimple/tests/018.phpt b/vendor/pimple/pimple/ext/pimple/tests/018.phpt
deleted file mode 100644
index 27c12a14e79e26b609b61258d5612c34b45d37ae..0000000000000000000000000000000000000000
--- a/vendor/pimple/pimple/ext/pimple/tests/018.phpt
+++ /dev/null
@@ -1,23 +0,0 @@
---TEST--
-Test register()
---SKIPIF--
-<?php if (!extension_loaded("pimple")) print "skip"; ?>
---FILE--
-<?php
-
-class Foo implements Pimple\ServiceProviderInterface
-{
-    public function register(Pimple\Container $p)
-    {
-        var_dump($p);
-    }
-}
-
-$p = new Pimple\Container();
-$p->register(new Foo, array(42 => 'bar'));
-
-var_dump($p[42]);
---EXPECTF--
-object(Pimple\Container)#1 (0) {
-}
-string(3) "bar"
\ No newline at end of file
diff --git a/vendor/pimple/pimple/ext/pimple/tests/019.phpt b/vendor/pimple/pimple/ext/pimple/tests/019.phpt
deleted file mode 100644
index 28a9aecac7f0e611400bb01b356c736fe771ca3b..0000000000000000000000000000000000000000
--- a/vendor/pimple/pimple/ext/pimple/tests/019.phpt
+++ /dev/null
@@ -1,18 +0,0 @@
---TEST--
-Test register() returns static and is a fluent interface
---SKIPIF--
-<?php if (!extension_loaded("pimple")) print "skip"; ?>
---FILE--
-<?php
-
-class Foo implements Pimple\ServiceProviderInterface
-{
-    public function register(Pimple\Container $p)
-    {
-    }
-}
-
-$p = new Pimple\Container();
-var_dump($p === $p->register(new Foo));
---EXPECTF--
-bool(true)
diff --git a/vendor/pimple/pimple/ext/pimple/tests/bench.phpb b/vendor/pimple/pimple/ext/pimple/tests/bench.phpb
deleted file mode 100644
index 8f983e656b525a6dbe7871087b5899a413e84e54..0000000000000000000000000000000000000000
--- a/vendor/pimple/pimple/ext/pimple/tests/bench.phpb
+++ /dev/null
@@ -1,51 +0,0 @@
-<?php
-
-if (!class_exists('Pimple\Container')) {
-    require_once __DIR__ . '/../../../src/Pimple/Container.php';
-} else {
-    echo "pimple-c extension detected, using...\n\n";
-}
-
-$time = microtime(true);
-
-function foo() { }
-$factory = function () { };
-
-for ($i=0; $i<10000; $i++) {
-
-$p = new Pimple\Container;
-
-$p['foo'] = 'bar';
-
-if (!isset($p[3])) {
-    $p[3] = $p['foo'];
-    $p[]  = 'bar';
-}
-
-$p[2] = 42;
-
-if (isset($p[2])) {
-	unset($p[2]);
-}
-
-$p[42] = $p['foo'];
-
-$p['cb'] = function($arg) { };
-
-$p[] = $p['cb'];
-
-echo $p['cb'];
-echo $p['cb'];
-echo $p['cb'];
-
-//$p->factory($factory);
-
-$p['factory'] = $factory;
-
-echo $p['factory'];
-echo $p['factory'];
-echo $p['factory'];
-
-}
-
-echo microtime(true)  - $time;
diff --git a/vendor/pimple/pimple/ext/pimple/tests/bench_shared.phpb b/vendor/pimple/pimple/ext/pimple/tests/bench_shared.phpb
deleted file mode 100644
index aec541f0bc8bee3b584f450e44d1e84a355100d1..0000000000000000000000000000000000000000
--- a/vendor/pimple/pimple/ext/pimple/tests/bench_shared.phpb
+++ /dev/null
@@ -1,25 +0,0 @@
-<?php
-
-if (!class_exists('Pimple\Container')) {
-    require_once __DIR__ . '/../../../src/Pimple/Container.php';
-} else {
-    echo "pimple-c extension detected, using...\n\n";
-}
-
-$time = microtime(true);
-
-
-$service = function ($arg) { return "I'm a service"; };
-
-for ($i=0; $i<10000; $i++) {
-
-$p = new Pimple\Container;
-$p['my_service'] = $service;
-
-$a = $p['my_service'];
-$b = $p['my_service'];
-
-}
-
-echo microtime(true) - $time;
-?>
diff --git a/vendor/pimple/pimple/phpunit.xml.dist b/vendor/pimple/pimple/phpunit.xml.dist
index 5c8d487fea9a98f2d22c51e80c5618060bcdd8cb..89902022a0eeb5d0bf9345423c69459d6a1b098c 100644
--- a/vendor/pimple/pimple/phpunit.xml.dist
+++ b/vendor/pimple/pimple/phpunit.xml.dist
@@ -11,4 +11,8 @@
             <directory>./src/Pimple/Tests</directory>
         </testsuite>
     </testsuites>
+
+    <listeners>
+        <listener class="Symfony\Bridge\PhpUnit\SymfonyTestsListener" />
+    </listeners>
 </phpunit>
diff --git a/vendor/pimple/pimple/src/Pimple/Container.php b/vendor/pimple/pimple/src/Pimple/Container.php
index 707b92b82c131fa736e2ed7a86b40cfe35df3096..1234f0bdc0dbab9760677ef1b3f2f405da9edbf6 100644
--- a/vendor/pimple/pimple/src/Pimple/Container.php
+++ b/vendor/pimple/pimple/src/Pimple/Container.php
@@ -38,12 +38,12 @@ use Pimple\Exception\UnknownIdentifierException;
  */
 class Container implements \ArrayAccess
 {
-    private $values = array();
+    private $values = [];
     private $factories;
     private $protected;
-    private $frozen = array();
-    private $raw = array();
-    private $keys = array();
+    private $frozen = [];
+    private $raw = [];
+    private $keys = [];
 
     /**
      * Instantiates the container.
@@ -52,7 +52,7 @@ class Container implements \ArrayAccess
      *
      * @param array $values The parameters or objects
      */
-    public function __construct(array $values = array())
+    public function __construct(array $values = [])
     {
         $this->factories = new \SplObjectStorage();
         $this->protected = new \SplObjectStorage();
@@ -246,7 +246,7 @@ class Container implements \ArrayAccess
         }
 
         if (isset($this->protected[$this->values[$id]])) {
-            @\trigger_error(\sprintf('How Pimple behaves when extending protected closures will be fixed in Pimple 4. Are you sure "%s" should be protected?', $id), \E_USER_DEPRECATED);
+            @\trigger_error(\sprintf('How Pimple behaves when extending protected closures will be fixed in Pimple 4. Are you sure "%s" should be protected?', $id), E_USER_DEPRECATED);
         }
 
         if (!\is_object($callable) || !\method_exists($callable, '__invoke')) {
@@ -285,7 +285,7 @@ class Container implements \ArrayAccess
      *
      * @return static
      */
-    public function register(ServiceProviderInterface $provider, array $values = array())
+    public function register(ServiceProviderInterface $provider, array $values = [])
     {
         $provider->register($this);
 
diff --git a/vendor/pimple/pimple/src/Pimple/Psr11/ServiceLocator.php b/vendor/pimple/pimple/src/Pimple/Psr11/ServiceLocator.php
index 3361c6f1970a201d2916e6a43febfb88232a991a..f10727cca2673895b9dd9f536dd81312f95acaed 100644
--- a/vendor/pimple/pimple/src/Pimple/Psr11/ServiceLocator.php
+++ b/vendor/pimple/pimple/src/Pimple/Psr11/ServiceLocator.php
@@ -38,7 +38,7 @@ use Psr\Container\ContainerInterface;
 class ServiceLocator implements ContainerInterface
 {
     private $container;
-    private $aliases = array();
+    private $aliases = [];
 
     /**
      * @param PimpleContainer $container The Container instance used to locate services
diff --git a/vendor/pimple/pimple/src/Pimple/Tests/PimpleServiceProviderInterfaceTest.php b/vendor/pimple/pimple/src/Pimple/Tests/PimpleServiceProviderInterfaceTest.php
index 8e5c4c73deb07d0abaf3979fe59fc9cedb224714..097a7fd96f6ec896a4d771cd02582b821b2dca29 100644
--- a/vendor/pimple/pimple/src/Pimple/Tests/PimpleServiceProviderInterfaceTest.php
+++ b/vendor/pimple/pimple/src/Pimple/Tests/PimpleServiceProviderInterfaceTest.php
@@ -26,12 +26,13 @@
 
 namespace Pimple\Tests;
 
+use PHPUnit\Framework\TestCase;
 use Pimple\Container;
 
 /**
- * @author  Dominik Zogg <dominik.zogg@gmail.com>
+ * @author Dominik Zogg <dominik.zogg@gmail.com>
  */
-class PimpleServiceProviderInterfaceTest extends \PHPUnit_Framework_TestCase
+class PimpleServiceProviderInterfaceTest extends TestCase
 {
     public function testProvider()
     {
@@ -56,9 +57,9 @@ class PimpleServiceProviderInterfaceTest extends \PHPUnit_Framework_TestCase
     {
         $pimple = new Container();
 
-        $pimple->register(new Fixtures\PimpleServiceProvider(), array(
+        $pimple->register(new Fixtures\PimpleServiceProvider(), [
             'anotherParameter' => 'anotherValue',
-        ));
+        ]);
 
         $this->assertEquals('value', $pimple['param']);
         $this->assertEquals('anotherValue', $pimple['anotherParameter']);
diff --git a/vendor/pimple/pimple/src/Pimple/Tests/PimpleTest.php b/vendor/pimple/pimple/src/Pimple/Tests/PimpleTest.php
index acb66e000261fd76e151cd2f2de3ad69dfc33ebf..ffa50a6a74dbc4c1f547a68c8994cadff786a5ec 100644
--- a/vendor/pimple/pimple/src/Pimple/Tests/PimpleTest.php
+++ b/vendor/pimple/pimple/src/Pimple/Tests/PimpleTest.php
@@ -26,12 +26,13 @@
 
 namespace Pimple\Tests;
 
+use PHPUnit\Framework\TestCase;
 use Pimple\Container;
 
 /**
  * @author Igor Wiedler <igor@wiedler.ch>
  */
-class PimpleTest extends \PHPUnit_Framework_TestCase
+class PimpleTest extends TestCase
 {
     public function testWithString()
     {
@@ -99,29 +100,29 @@ class PimpleTest extends \PHPUnit_Framework_TestCase
 
     public function testConstructorInjection()
     {
-        $params = array('param' => 'value');
+        $params = ['param' => 'value'];
         $pimple = new Container($params);
 
         $this->assertSame($params['param'], $pimple['param']);
     }
 
-    /**
-     * @expectedException \Pimple\Exception\UnknownIdentifierException
-     * @expectedExceptionMessage Identifier "foo" is not defined.
-     */
     public function testOffsetGetValidatesKeyIsPresent()
     {
+        $this->expectException(\Pimple\Exception\UnknownIdentifierException::class);
+        $this->expectExceptionMessage('Identifier "foo" is not defined.');
+
         $pimple = new Container();
         echo $pimple['foo'];
     }
 
     /**
      * @group legacy
-     * @expectedException \InvalidArgumentException
-     * @expectedExceptionMessage Identifier "foo" is not defined.
      */
     public function testLegacyOffsetGetValidatesKeyIsPresent()
     {
+        $this->expectException(\InvalidArgumentException::class);
+        $this->expectExceptionMessage('Identifier "foo" is not defined.');
+
         $pimple = new Container();
         echo $pimple['foo'];
     }
@@ -184,7 +185,9 @@ class PimpleTest extends \PHPUnit_Framework_TestCase
     public function testRaw()
     {
         $pimple = new Container();
-        $pimple['service'] = $definition = $pimple->factory(function () { return 'foo'; });
+        $pimple['service'] = $definition = $pimple->factory(function () {
+            return 'foo';
+        });
         $this->assertSame($definition, $pimple->raw('service'));
     }
 
@@ -201,23 +204,23 @@ class PimpleTest extends \PHPUnit_Framework_TestCase
         $this->assertSame($pimple, $pimple->register($this->getMockBuilder('Pimple\ServiceProviderInterface')->getMock()));
     }
 
-    /**
-     * @expectedException \Pimple\Exception\UnknownIdentifierException
-     * @expectedExceptionMessage Identifier "foo" is not defined.
-     */
     public function testRawValidatesKeyIsPresent()
     {
+        $this->expectException(\Pimple\Exception\UnknownIdentifierException::class);
+        $this->expectExceptionMessage('Identifier "foo" is not defined.');
+
         $pimple = new Container();
         $pimple->raw('foo');
     }
 
     /**
      * @group legacy
-     * @expectedException \InvalidArgumentException
-     * @expectedExceptionMessage Identifier "foo" is not defined.
      */
     public function testLegacyRawValidatesKeyIsPresent()
     {
+        $this->expectException(\InvalidArgumentException::class);
+        $this->expectExceptionMessage('Identifier "foo" is not defined.');
+
         $pimple = new Container();
         $pimple->raw('foo');
     }
@@ -254,13 +257,17 @@ class PimpleTest extends \PHPUnit_Framework_TestCase
 
     public function testExtendDoesNotLeakWithFactories()
     {
-        if (extension_loaded('pimple')) {
+        if (\extension_loaded('pimple')) {
             $this->markTestSkipped('Pimple extension does not support this test');
         }
         $pimple = new Container();
 
-        $pimple['foo'] = $pimple->factory(function () { return; });
-        $pimple['foo'] = $pimple->extend('foo', function ($foo, $pimple) { return; });
+        $pimple['foo'] = $pimple->factory(function () {
+            return;
+        });
+        $pimple['foo'] = $pimple->extend('foo', function ($foo, $pimple) {
+            return;
+        });
         unset($pimple['foo']);
 
         $p = new \ReflectionProperty($pimple, 'values');
@@ -272,25 +279,27 @@ class PimpleTest extends \PHPUnit_Framework_TestCase
         $this->assertCount(0, $p->getValue($pimple));
     }
 
-    /**
-     * @expectedException \Pimple\Exception\UnknownIdentifierException
-     * @expectedExceptionMessage Identifier "foo" is not defined.
-     */
     public function testExtendValidatesKeyIsPresent()
     {
+        $this->expectException(\Pimple\Exception\UnknownIdentifierException::class);
+        $this->expectExceptionMessage('Identifier "foo" is not defined.');
+
         $pimple = new Container();
-        $pimple->extend('foo', function () {});
+        $pimple->extend('foo', function () {
+        });
     }
 
     /**
      * @group legacy
-     * @expectedException \InvalidArgumentException
-     * @expectedExceptionMessage Identifier "foo" is not defined.
      */
     public function testLegacyExtendValidatesKeyIsPresent()
     {
+        $this->expectException(\InvalidArgumentException::class);
+        $this->expectExceptionMessage('Identifier "foo" is not defined.');
+
         $pimple = new Container();
-        $pimple->extend('foo', function () {});
+        $pimple->extend('foo', function () {
+        });
     }
 
     public function testKeys()
@@ -299,7 +308,7 @@ class PimpleTest extends \PHPUnit_Framework_TestCase
         $pimple['foo'] = 123;
         $pimple['bar'] = 123;
 
-        $this->assertEquals(array('foo', 'bar'), $pimple->keys());
+        $this->assertEquals(['foo', 'bar'], $pimple->keys());
     }
 
     /** @test */
@@ -322,11 +331,12 @@ class PimpleTest extends \PHPUnit_Framework_TestCase
 
     /**
      * @dataProvider badServiceDefinitionProvider
-     * @expectedException \Pimple\Exception\ExpectedInvokableException
-     * @expectedExceptionMessage Service definition is not a Closure or invokable object.
      */
     public function testFactoryFailsForInvalidServiceDefinitions($service)
     {
+        $this->expectException(\Pimple\Exception\ExpectedInvokableException::class);
+        $this->expectExceptionMessage('Service definition is not a Closure or invokable object.');
+
         $pimple = new Container();
         $pimple->factory($service);
     }
@@ -334,22 +344,24 @@ class PimpleTest extends \PHPUnit_Framework_TestCase
     /**
      * @group legacy
      * @dataProvider badServiceDefinitionProvider
-     * @expectedException \InvalidArgumentException
-     * @expectedExceptionMessage Service definition is not a Closure or invokable object.
      */
     public function testLegacyFactoryFailsForInvalidServiceDefinitions($service)
     {
+        $this->expectException(\InvalidArgumentException::class);
+        $this->expectExceptionMessage('Service definition is not a Closure or invokable object.');
+
         $pimple = new Container();
         $pimple->factory($service);
     }
 
     /**
      * @dataProvider badServiceDefinitionProvider
-     * @expectedException \Pimple\Exception\ExpectedInvokableException
-     * @expectedExceptionMessage Callable is not a Closure or invokable object.
      */
     public function testProtectFailsForInvalidServiceDefinitions($service)
     {
+        $this->expectException(\Pimple\Exception\ExpectedInvokableException::class);
+        $this->expectExceptionMessage('Callable is not a Closure or invokable object.');
+
         $pimple = new Container();
         $pimple->protect($service);
     }
@@ -357,38 +369,43 @@ class PimpleTest extends \PHPUnit_Framework_TestCase
     /**
      * @group legacy
      * @dataProvider badServiceDefinitionProvider
-     * @expectedException \InvalidArgumentException
-     * @expectedExceptionMessage Callable is not a Closure or invokable object.
      */
     public function testLegacyProtectFailsForInvalidServiceDefinitions($service)
     {
+        $this->expectException(\InvalidArgumentException::class);
+        $this->expectExceptionMessage('Callable is not a Closure or invokable object.');
+
         $pimple = new Container();
         $pimple->protect($service);
     }
 
     /**
      * @dataProvider badServiceDefinitionProvider
-     * @expectedException \Pimple\Exception\InvalidServiceIdentifierException
-     * @expectedExceptionMessage Identifier "foo" does not contain an object definition.
      */
     public function testExtendFailsForKeysNotContainingServiceDefinitions($service)
     {
+        $this->expectException(\Pimple\Exception\InvalidServiceIdentifierException::class);
+        $this->expectExceptionMessage('Identifier "foo" does not contain an object definition.');
+
         $pimple = new Container();
         $pimple['foo'] = $service;
-        $pimple->extend('foo', function () {});
+        $pimple->extend('foo', function () {
+        });
     }
 
     /**
      * @group legacy
      * @dataProvider badServiceDefinitionProvider
-     * @expectedException \InvalidArgumentException
-     * @expectedExceptionMessage Identifier "foo" does not contain an object definition.
      */
     public function testLegacyExtendFailsForKeysNotContainingServiceDefinitions($service)
     {
+        $this->expectException(\InvalidArgumentException::class);
+        $this->expectExceptionMessage('Identifier "foo" does not contain an object definition.');
+
         $pimple = new Container();
         $pimple['foo'] = $service;
-        $pimple->extend('foo', function () {});
+        $pimple->extend('foo', function () {
+        });
     }
 
     /**
@@ -411,57 +428,61 @@ class PimpleTest extends \PHPUnit_Framework_TestCase
 
     /**
      * @dataProvider badServiceDefinitionProvider
-     * @expectedException \Pimple\Exception\ExpectedInvokableException
-     * @expectedExceptionMessage Extension service definition is not a Closure or invokable object.
      */
     public function testExtendFailsForInvalidServiceDefinitions($service)
     {
+        $this->expectException(\Pimple\Exception\ExpectedInvokableException::class);
+        $this->expectExceptionMessage('Extension service definition is not a Closure or invokable object.');
+
         $pimple = new Container();
-        $pimple['foo'] = function () {};
+        $pimple['foo'] = function () {
+        };
         $pimple->extend('foo', $service);
     }
 
     /**
      * @group legacy
      * @dataProvider badServiceDefinitionProvider
-     * @expectedException \InvalidArgumentException
-     * @expectedExceptionMessage Extension service definition is not a Closure or invokable object.
      */
     public function testLegacyExtendFailsForInvalidServiceDefinitions($service)
     {
+        $this->expectException(\InvalidArgumentException::class);
+        $this->expectExceptionMessage('Extension service definition is not a Closure or invokable object.');
+
         $pimple = new Container();
-        $pimple['foo'] = function () {};
+        $pimple['foo'] = function () {
+        };
         $pimple->extend('foo', $service);
     }
 
-    /**
-     * @expectedException \Pimple\Exception\FrozenServiceException
-     * @expectedExceptionMessage Cannot override frozen service "foo".
-     */
     public function testExtendFailsIfFrozenServiceIsNonInvokable()
     {
+        $this->expectException(\Pimple\Exception\FrozenServiceException::class);
+        $this->expectExceptionMessage('Cannot override frozen service "foo".');
+
         $pimple = new Container();
         $pimple['foo'] = function () {
             return new Fixtures\NonInvokable();
         };
         $foo = $pimple['foo'];
 
-        $pimple->extend('foo', function () {});
+        $pimple->extend('foo', function () {
+        });
     }
 
-    /**
-     * @expectedException \Pimple\Exception\FrozenServiceException
-     * @expectedExceptionMessage Cannot override frozen service "foo".
-     */
     public function testExtendFailsIfFrozenServiceIsInvokable()
     {
+        $this->expectException(\Pimple\Exception\FrozenServiceException::class);
+        $this->expectExceptionMessage('Cannot override frozen service "foo".');
+
         $pimple = new Container();
         $pimple['foo'] = function () {
             return new Fixtures\Invokable();
         };
         $foo = $pimple['foo'];
 
-        $pimple->extend('foo', function () {});
+        $pimple->extend('foo', function () {
+        });
     }
 
     /**
@@ -469,10 +490,10 @@ class PimpleTest extends \PHPUnit_Framework_TestCase
      */
     public function badServiceDefinitionProvider()
     {
-        return array(
-          array(123),
-          array(new Fixtures\NonInvokable()),
-        );
+        return [
+          [123],
+          [new Fixtures\NonInvokable()],
+        ];
     }
 
     /**
@@ -480,15 +501,15 @@ class PimpleTest extends \PHPUnit_Framework_TestCase
      */
     public function serviceDefinitionProvider()
     {
-        return array(
-            array(function ($value) {
+        return [
+            [function ($value) {
                 $service = new Fixtures\Service();
                 $service->value = $value;
 
                 return $service;
-            }),
-            array(new Fixtures\Invokable()),
-        );
+            }],
+            [new Fixtures\Invokable()],
+        ];
     }
 
     public function testDefiningNewServiceAfterFreeze()
@@ -505,12 +526,11 @@ class PimpleTest extends \PHPUnit_Framework_TestCase
         $this->assertSame('bar', $pimple['bar']);
     }
 
-    /**
-     * @expectedException \Pimple\Exception\FrozenServiceException
-     * @expectedExceptionMessage Cannot override frozen service "foo".
-     */
     public function testOverridingServiceAfterFreeze()
     {
+        $this->expectException(\Pimple\Exception\FrozenServiceException::class);
+        $this->expectExceptionMessage('Cannot override frozen service "foo".');
+
         $pimple = new Container();
         $pimple['foo'] = function () {
             return 'foo';
@@ -524,11 +544,12 @@ class PimpleTest extends \PHPUnit_Framework_TestCase
 
     /**
      * @group legacy
-     * @expectedException \RuntimeException
-     * @expectedExceptionMessage Cannot override frozen service "foo".
      */
     public function testLegacyOverridingServiceAfterFreeze()
     {
+        $this->expectException(\RuntimeException::class);
+        $this->expectExceptionMessage('Cannot override frozen service "foo".');
+
         $pimple = new Container();
         $pimple['foo'] = function () {
             return 'foo';
diff --git a/vendor/pimple/pimple/src/Pimple/Tests/Psr11/ContainerTest.php b/vendor/pimple/pimple/src/Pimple/Tests/Psr11/ContainerTest.php
index 7ca2d7fffbadab893ae91d24b4ace852a129d2dc..d47b9c3f009e0a84627056595ced557a9efbdf99 100644
--- a/vendor/pimple/pimple/src/Pimple/Tests/Psr11/ContainerTest.php
+++ b/vendor/pimple/pimple/src/Pimple/Tests/Psr11/ContainerTest.php
@@ -44,12 +44,11 @@ class ContainerTest extends TestCase
         $this->assertSame($pimple['service'], $psr->get('service'));
     }
 
-    /**
-     * @expectedException \Psr\Container\NotFoundExceptionInterface
-     * @expectedExceptionMessage Identifier "service" is not defined.
-     */
     public function testGetThrowsExceptionIfServiceIsNotFound()
     {
+        $this->expectException(\Psr\Container\NotFoundExceptionInterface::class);
+        $this->expectExceptionMessage('Identifier "service" is not defined.');
+
         $pimple = new Container();
         $psr = new PsrContainer($pimple);
 
diff --git a/vendor/pimple/pimple/src/Pimple/Tests/Psr11/ServiceLocatorTest.php b/vendor/pimple/pimple/src/Pimple/Tests/Psr11/ServiceLocatorTest.php
index c9a0812591b519ded083bd9131bd75803e472179..bd2d335be67374063cb6b270936c556832cf2a92 100644
--- a/vendor/pimple/pimple/src/Pimple/Tests/Psr11/ServiceLocatorTest.php
+++ b/vendor/pimple/pimple/src/Pimple/Tests/Psr11/ServiceLocatorTest.php
@@ -44,7 +44,7 @@ class ServiceLocatorTest extends TestCase
         $pimple['service'] = function () {
             return new Fixtures\Service();
         };
-        $locator = new ServiceLocator($pimple, array('service'));
+        $locator = new ServiceLocator($pimple, ['service']);
 
         $this->assertSame($pimple['service'], $locator->get('service'));
     }
@@ -55,52 +55,49 @@ class ServiceLocatorTest extends TestCase
         $pimple['service'] = function () {
             return new Fixtures\Service();
         };
-        $locator = new ServiceLocator($pimple, array('alias' => 'service'));
+        $locator = new ServiceLocator($pimple, ['alias' => 'service']);
 
         $this->assertSame($pimple['service'], $locator->get('alias'));
     }
 
-    /**
-     * @expectedException \Pimple\Exception\UnknownIdentifierException
-     * @expectedExceptionMessage Identifier "service" is not defined.
-     */
     public function testCannotAccessAliasedServiceUsingRealIdentifier()
     {
+        $this->expectException(\Pimple\Exception\UnknownIdentifierException::class);
+        $this->expectExceptionMessage('Identifier "service" is not defined.');
+
         $pimple = new Container();
         $pimple['service'] = function () {
             return new Fixtures\Service();
         };
-        $locator = new ServiceLocator($pimple, array('alias' => 'service'));
+        $locator = new ServiceLocator($pimple, ['alias' => 'service']);
 
         $service = $locator->get('service');
     }
 
-    /**
-     * @expectedException \Pimple\Exception\UnknownIdentifierException
-     * @expectedExceptionMessage Identifier "foo" is not defined.
-     */
     public function testGetValidatesServiceCanBeLocated()
     {
+        $this->expectException(\Pimple\Exception\UnknownIdentifierException::class);
+        $this->expectExceptionMessage('Identifier "foo" is not defined.');
+
         $pimple = new Container();
         $pimple['service'] = function () {
             return new Fixtures\Service();
         };
-        $locator = new ServiceLocator($pimple, array('alias' => 'service'));
+        $locator = new ServiceLocator($pimple, ['alias' => 'service']);
 
         $service = $locator->get('foo');
     }
 
-    /**
-     * @expectedException \Pimple\Exception\UnknownIdentifierException
-     * @expectedExceptionMessage Identifier "invalid" is not defined.
-     */
     public function testGetValidatesTargetServiceExists()
     {
+        $this->expectException(\Pimple\Exception\UnknownIdentifierException::class);
+        $this->expectExceptionMessage('Identifier "invalid" is not defined.');
+
         $pimple = new Container();
         $pimple['service'] = function () {
             return new Fixtures\Service();
         };
-        $locator = new ServiceLocator($pimple, array('alias' => 'invalid'));
+        $locator = new ServiceLocator($pimple, ['alias' => 'invalid']);
 
         $service = $locator->get('alias');
     }
@@ -114,7 +111,7 @@ class ServiceLocatorTest extends TestCase
         $pimple['service2'] = function () {
             return new Fixtures\Service();
         };
-        $locator = new ServiceLocator($pimple, array('service1'));
+        $locator = new ServiceLocator($pimple, ['service1']);
 
         $this->assertTrue($locator->has('service1'));
         $this->assertFalse($locator->has('service2'));
@@ -126,7 +123,7 @@ class ServiceLocatorTest extends TestCase
         $pimple['service'] = function () {
             return new Fixtures\Service();
         };
-        $locator = new ServiceLocator($pimple, array('foo' => 'service', 'bar' => 'invalid'));
+        $locator = new ServiceLocator($pimple, ['foo' => 'service', 'bar' => 'invalid']);
 
         $this->assertTrue($locator->has('foo'));
         $this->assertFalse($locator->has('bar'));
diff --git a/vendor/pimple/pimple/src/Pimple/Tests/ServiceIteratorTest.php b/vendor/pimple/pimple/src/Pimple/Tests/ServiceIteratorTest.php
index 5dd52f0d9819b1da9fc313cb09b134be3d781c8b..2bb935f312ab09545cc2faba242e7634531b8e71 100644
--- a/vendor/pimple/pimple/src/Pimple/Tests/ServiceIteratorTest.php
+++ b/vendor/pimple/pimple/src/Pimple/Tests/ServiceIteratorTest.php
@@ -45,8 +45,8 @@ class ServiceIteratorTest extends TestCase
         $pimple['service3'] = function () {
             return new Service();
         };
-        $iterator = new ServiceIterator($pimple, array('service1', 'service2'));
+        $iterator = new ServiceIterator($pimple, ['service1', 'service2']);
 
-        $this->assertSame(array('service1' => $pimple['service1'], 'service2' => $pimple['service2']), iterator_to_array($iterator));
+        $this->assertSame(['service1' => $pimple['service1'], 'service2' => $pimple['service2']], iterator_to_array($iterator));
     }
 }
diff --git a/vendor/respect/validation/.travis.yml b/vendor/respect/validation/.travis.yml
index c0ce5b6cfb42f157236c9a3b10c2c13cccbd57dd..817053a7f9b9f8f8c84e14faae29f6ab653d3015 100644
--- a/vendor/respect/validation/.travis.yml
+++ b/vendor/respect/validation/.travis.yml
@@ -1,30 +1,32 @@
-sudo:
-  false
+sudo: false
 
-language:
-  php
+language: php
 
-php:
-  - 5.4
-  - 5.5
-  - 5.6
-  - 7.0
-  - 7.1
-  - hhvm
+matrix:
+  include:
+    - php: 5.4
+      env: COMPOSER_ARGUMENTS="--prefer-lowest --prefer-stable"
+    - php: 5.4
+    - php: 5.5
+    - php: 5.6
+    - php: 7.1
+    - php: 7.2
+      env: PHPUNIT_COVERAGE_ARGUMENT="--coverage-clover=coverage.clover"
+    - php: 7.3
+    - php: nightly
+  allow_failures:
+    - php: nightly
+  fast_finish: true
 
 before_script:
-  - composer self-update
-  - composer install --no-interaction --prefer-source
+  - composer update --prefer-dist ${COMPOSER_ARGUMENTS}
 
 script:
-  - vendor/bin/phpunit --configuration phpunit.xml.dist --colors --coverage-clover=coverage.clover
+  - vendor/bin/phpunit --configuration phpunit.xml.dist --verbose --colors ${PHPUNIT_COVERAGE_ARGUMENT}
 
 after_script:
-  - test "5.6" == "${TRAVIS_PHP_VERSION}" && wget https://scrutinizer-ci.com/ocular.phar
-  - test -f ocular.phar && php ocular.phar code-coverage:upload --format=php-clover coverage.clover
-
-notifications:
-  irc:
-    channels:
-      - "irc.freenode.org#php-respect"
-    use_notice: true
+  - |
+    if [[ ! -z "${PHPUNIT_COVERAGE_ARGUMENT}" ]]; then
+      wget https://scrutinizer-ci.com/ocular.phar
+      php ocular.phar code-coverage:upload --format=php-clover coverage.clover
+    fi
diff --git a/vendor/respect/validation/README.md b/vendor/respect/validation/README.md
index 6e026234f7e57b6e036a141fa768fa991f74b6d7..3076e117f5f79d8ae8d057b5ea9ebdbf7f0b2bd5 100644
--- a/vendor/respect/validation/README.md
+++ b/vendor/respect/validation/README.md
@@ -13,7 +13,7 @@
 - Granularity control for advanced reporting.
 - More than 100 (fully tested) validators.
 - A concrete API for non fluent usage.
-- Works on PHP 5.4+ or HHVM 3.3+
+- Works on PHP 5.4+
 
 ## Documentation
 
diff --git a/vendor/respect/validation/bin/update-currency-codes b/vendor/respect/validation/bin/update-currency-codes
new file mode 100755
index 0000000000000000000000000000000000000000..e6879bef31720916905674dc6b4bdfc782caae10
--- /dev/null
+++ b/vendor/respect/validation/bin/update-currency-codes
@@ -0,0 +1,40 @@
+#!/usr/bin/env bash
+# Usage: {script} TLD_FILENAME
+# Update list of TLD
+
+set -euo pipefail
+
+declare -r IFS=$'\n'
+declare -r URL="https://www.currency-iso.org/dam/downloads/lists/list_one.xml"
+declare -r RULE="${1}"
+declare -r TEMPORARY_XML=$(mktemp)
+
+download_list()
+{
+  echo "Downloading list from '${URL}'"
+  curl --silent --location "${1}" --output "${2}"
+}
+
+update_currency_codes()
+{
+  local -r filename_rule="${1}"
+  local -r filename_xml="${2}"
+  local -r number_of_items=$(grep "<CcyNtry>" "${filename_xml}" | wc --lines)
+  local -r temporary_rule=$(mktemp)
+
+  echo "Updating list in '${filename_rule}'"
+  {
+    sed -n '/^</,/    private/p' "${filename_rule}"
+    for index in $(seq 1 ${number_of_items}); do
+      local name=$(xml sel -t -v "//CcyNtry[${index}]/CcyNm" < "${filename_xml}")
+      local code=$(xml sel -t -v "//CcyNtry[${index}]/Ccy" < "${filename_xml}")
+      echo "        '${code}', // ${name}"
+    done
+    sed -n '/^    ]/,/^}/p' "${filename_rule}"
+  } > "${temporary_rule}"
+
+  mv "${temporary_rule}" "${filename_rule}"
+}
+
+download_list "${URL}" "${TEMPORARY_XML}"
+update_currency_codes "${RULE}" "${TEMPORARY_XML}"
diff --git a/vendor/respect/validation/bin/update-iso-codes b/vendor/respect/validation/bin/update-iso-codes
new file mode 100755
index 0000000000000000000000000000000000000000..725d36ed706118f19b9526278b2caa338f0f32aa
--- /dev/null
+++ b/vendor/respect/validation/bin/update-iso-codes
@@ -0,0 +1,98 @@
+#!/usr/bin/env bash
+# Usage: {script} TLD_FILENAME
+# Update list of TLD
+
+set -euo pipefail
+
+declare -r IFS=$'\n'
+declare -r REPOSITORY_URL="https://salsa.debian.org/iso-codes-team/iso-codes.git"
+declare -r REPOSITORY_DIRECTORY=$(mktemp --directory)
+declare -r LIBRARY_DIRECTORY="${1}"
+
+clone_repository()
+{
+  echo "Cloning repository ${REPOSITORY_URL}"
+  git clone --quiet "${REPOSITORY_URL}" "${REPOSITORY_DIRECTORY}"
+}
+
+list_iso_3166()
+{
+  local -r number_of_items=${1}
+  local -r filename=${2}
+
+  for index in $(seq 0 ${number_of_items}); do
+    local json=$(jq ".[][${index}]" < "${filename}")
+    local alpha_2=$(jq ".alpha_2" <<< "${json}" | tr '"' "'")
+    local alpha_3=$(jq ".alpha_3" <<< "${json}" | tr '"' "'")
+    local numeric=$(jq ".numeric" <<< "${json}" | tr '"' "'")
+    local name=$(jq -r ".name" <<< "${json}")
+    echo "        [${alpha_2}, ${alpha_3}, ${numeric}], // ${name}"
+  done
+}
+
+update_country_codes()
+{
+  local -r iso_3166_1_filename="${REPOSITORY_DIRECTORY}/data/iso_3166-1.json"
+  local -r iso_3166_1_count=$(grep "alpha_3" "${iso_3166_1_filename}" | wc --lines)
+  local -r iso_3166_3_filename="${REPOSITORY_DIRECTORY}/data/iso_3166-3.json"
+  local -r iso_3166_3_count=$(grep "alpha_3" "${iso_3166_3_filename}" | wc --lines)
+  local -r temporary_filename=$(mktemp)
+  local -r country_rule_filename="${LIBRARY_DIRECTORY}/Rules/CountryCode.php"
+
+  echo "Updating country codes using ISO 3166-1 and ISO 3166-3"
+  {
+    sed -n '/^</,/    protected/p' "${country_rule_filename}"
+    {
+      list_iso_3166 $[iso_3166_1_count - 1] ${iso_3166_1_filename}
+      list_iso_3166 $[iso_3166_3_count - 1] ${iso_3166_3_filename}
+    } | sort
+    sed -n '/^    ]/,/^}/p' "${country_rule_filename}"
+  } > "${temporary_filename}"
+  mv "${temporary_filename}" "${country_rule_filename}"
+}
+
+rule_from_country_code()
+{
+  local country_code=${1,,}
+
+  echo "${LIBRARY_DIRECTORY}/Rules/SubdivisionCode/${country_code^}SubdivisionCode.php"
+}
+
+update_subdivision_codes()
+{
+  local -r iso_3166_2_filename="${REPOSITORY_DIRECTORY}/data/iso_3166-2.json"
+  local -r iso_3166_2_count=$(grep --word-regexp "code" "${iso_3166_2_filename}" | wc --lines)
+  local -r temporary_filename=$(mktemp)
+  local last_country_code=""
+  local last_country_rule=""
+
+  echo "Updating subdivision codes using ISO 3166-2"
+
+  for index in $(seq 0 $[iso_3166_2_count - 1]); do
+    local json=$(jq ".[][${index}]" < "${iso_3166_2_filename}")
+    local code=$(jq -r ".code" <<< "${json}")
+    local name=$(jq -r ".name" <<< "${json}")
+
+    local current_country_code=$(cut --delimiter "-" --fields 1 <<< "${code}")
+    local current_country_rule=$(rule_from_country_code ${current_country_code})
+
+    if [[ ${last_country_code} != ${current_country_code} ]] && [[ ! -z "${last_country_code}" ]]; then
+      sed -n '/^    \]/,/^}/p' "${last_country_rule}" >> "${temporary_filename}"
+      cat "${temporary_filename}" > "${last_country_rule}"
+    fi
+
+    if [[ ${last_country_code} != ${current_country_code} ]]; then
+      echo "- Updating ${current_country_code}"
+      sed -n '/^</,/public \$haystack = \[/p' "${current_country_rule}" > "${temporary_filename}"
+    fi
+
+    echo "        '$(cut --delimiter "-" --fields 2 <<<  ${code})', // ${name}" >> "${temporary_filename}"
+
+    last_country_code=${current_country_code}
+    last_country_rule=${current_country_rule}
+  done
+}
+
+clone_repository
+update_country_codes
+update_subdivision_codes
diff --git a/vendor/respect/validation/bin/update-language-codes b/vendor/respect/validation/bin/update-language-codes
new file mode 100755
index 0000000000000000000000000000000000000000..b8e4328612251aa6b8b10b99dc1a5f111213e0d4
--- /dev/null
+++ b/vendor/respect/validation/bin/update-language-codes
@@ -0,0 +1,40 @@
+#!/usr/bin/env bash
+# Usage: {script} RULE_FILENAME
+# Update list of language codes (ISO-639-2)
+
+set -euo pipefail
+
+declare -r IFS=$'\n'
+declare -r URL="http://www.loc.gov/standards/iso639-2/ISO-639-2_utf-8.txt"
+declare -r RULE_FILENAME="${1}"
+declare -r TEMPORARY_LIST=$(mktemp)
+
+download_list()
+{
+  echo "Downloading list from '${URL}'"
+  curl --silent --location "${1}" --output "${2}"
+}
+
+update_currency_codes()
+{
+  local -r filename_rule="${1}"
+  local -r filename_list="${2}"
+  local -r temporary_rule=$(mktemp)
+
+  echo "Updating list in '${filename_rule}'"
+  {
+    sed -n '/^</,/    protected/p' "${filename_rule}"
+    while read line; do
+      local alpha_3=$(cut --delimiter '|' --fields 1 <<< "${line}" | tr -cd '[a-z]' | tr '[a-z]' '[A-Z]')
+      local alpha_2=$(cut --delimiter '|' --fields 3 <<< "${line}" | tr '[a-z]' '[A-Z]')
+      local name=$(cut --delimiter '|' --fields 4 <<< "${line}")
+      echo "        ['${alpha_2}', '${alpha_3}'], // ${name}"
+    done < "${filename_list}"
+    sed -n '/^    ]/,/^}/p' "${filename_rule}"
+  } > "${temporary_rule}"
+
+  mv "${temporary_rule}" "${filename_rule}"
+}
+
+download_list "${URL}" "${TEMPORARY_LIST}"
+update_currency_codes "${RULE_FILENAME}" "${TEMPORARY_LIST}"
diff --git a/vendor/respect/validation/bin/update-tld b/vendor/respect/validation/bin/update-tld
new file mode 100755
index 0000000000000000000000000000000000000000..5ef21ecd02cec580f83ab1b843366e692bdebdb0
--- /dev/null
+++ b/vendor/respect/validation/bin/update-tld
@@ -0,0 +1,34 @@
+#!/usr/bin/env bash
+# Usage: {script} TLD_FILENAME
+# Update list of TLD
+
+set -euo pipefail
+
+declare -r IFS=$'\n'
+declare -r URL="https://data.iana.org/TLD/tlds-alpha-by-domain.txt"
+declare -r TEMPORARY_LIST_FILE=$(mktemp)
+declare -r TEMPORARY_RULE_FILE=$(mktemp)
+declare -r TLD_FILENAME="${1}"
+
+echo "Downloading '${URL}'"
+curl -s -L "${URL}" -o "${TEMPORARY_LIST_FILE}"
+
+echo "Updating '${TLD_FILENAME}'"
+{
+  sed -nE '/^</,/^\{/p' "${TLD_FILENAME}"
+  echo "    // List extracted from ${URL}"
+  grep '^#' "${TEMPORARY_LIST_FILE}" | sed 's,#,    //,'
+  echo "    protected \$tldList = ["
+  grep -v '^#' "${TEMPORARY_LIST_FILE}" |
+    tr '[A-Z]' '[a-z]' |
+    sed -E "s,^,',; s/$/', /" |
+    tr -d '\n' |
+    fold -w 72 -s |
+    sed 's,^,        ,g; s, $,,g'
+  echo
+  echo "    ];"
+  echo
+  sed -nE '/^    public function/,/^}/p' "${TLD_FILENAME}"
+} > "${TEMPORARY_RULE_FILE}"
+
+mv "${TEMPORARY_RULE_FILE}" "${TLD_FILENAME}"
diff --git a/vendor/respect/validation/composer.json b/vendor/respect/validation/composer.json
index 398dafe4d94711662e32d6c1779c0972c9733cc8..eebc960cbce66f3bbdbd8bd9df5da332664116bc 100644
--- a/vendor/respect/validation/composer.json
+++ b/vendor/respect/validation/composer.json
@@ -18,7 +18,7 @@
     "require-dev": {
         "egulias/email-validator": "~1.2 || ~2.1",
         "mikey179/vfsStream": "^1.5",
-        "phpunit/phpunit": "~4.0",
+        "phpunit/phpunit": "~4.0 || ~5.0",
         "symfony/validator": "~2.6.9",
         "zendframework/zend-validator": "~2.3"
     },
diff --git a/vendor/respect/validation/docs/feature-guide.md b/vendor/respect/validation/docs/feature-guide.md
index 5d96e007909c98625bbe10fb9f04f61a5ed98535..1d0d6d4f6f994f41a1913461b360b459391d815d 100644
--- a/vendor/respect/validation/docs/feature-guide.md
+++ b/vendor/respect/validation/docs/feature-guide.md
@@ -41,7 +41,7 @@ $user->birthdate = '1987-07-01';
 Is possible to validate its attributes in a single chain:
 
 ```php
-$userValidator = v::attribute('name', v::stringType()->length(1,32))
+$userValidator = v::attribute('name', v::stringType()->length(1, 32))
                   ->attribute('birthdate', v::date()->age(18));
 
 $userValidator->validate($user); // true
@@ -260,6 +260,30 @@ v::with('My\\Validation\\Rules', true);
 v::alnum(); // Try to use "My\Validation\Rules\Alnum" if any
 ```
 
+If you're using the `assert()` or `check()` methods you also need to create an
+Exception to declare the messages returned:
+
+```php
+namespace My\Validation\Exceptions;
+
+use Respect\Validation\Exceptions\ValidationException;
+
+class MyRuleException extends ValidationException
+{
+    public static $defaultTemplates = [
+        self::MODE_DEFAULT => [
+            self::STANDARD => '{{name}} must pass my rules',
+        ],
+        self::MODE_NEGATIVE => [
+            self::STANDARD => '{{name}} must not pass my rules',
+        ]
+    ];
+}
+```
+
+Notice that while the namespace of the rule is `My\Validation\Rules` the
+namespace of the exception is `My\Validation\Exceptions`.
+
 ## Validator name
 
 On `v::attribute()` and `v::key()`, `{{name}}` is the attribute/key name. For others,
diff --git a/vendor/respect/validation/docs/index.md b/vendor/respect/validation/docs/index.md
index 433d433767db92c9f6814383afef5107525557e9..53ff13f5a1f6c2a5805ba17332fcae3df030d4ca 100644
--- a/vendor/respect/validation/docs/index.md
+++ b/vendor/respect/validation/docs/index.md
@@ -13,4 +13,4 @@
 - [Granularity control](feature-guide.md#validation-methods) for advanced reporting.
 - More than 100 (fully tested) validators.
 - [A concrete API](concrete-api.md) for non fluent usage.
-- Works on PHP 5.4+ or HHVM 3.3+
+- Works on PHP 5.4+
diff --git a/vendor/respect/validation/docs/rules/Age.md b/vendor/respect/validation/docs/rules/Age.md
index 740d7279b676e08c6062a1fdae87bc675fc6bbbc..07284bc11d11b0ebe7974efd7fd545c833547f8d 100644
--- a/vendor/respect/validation/docs/rules/Age.md
+++ b/vendor/respect/validation/docs/rules/Age.md
@@ -44,3 +44,4 @@ See also:
   * [Date](Date.md)
   * [Max](Max.md)
   * [Min](Min.md)
+  * [MinimumAge](MinimumAge.md)
diff --git a/vendor/respect/validation/docs/rules/AllOf.md b/vendor/respect/validation/docs/rules/AllOf.md
index 7bd2ecf0203be63de28fd5a27c59f0eb7dbe8ddc..0f1a29371eaab921115960f2446677d90c513df5 100644
--- a/vendor/respect/validation/docs/rules/AllOf.md
+++ b/vendor/respect/validation/docs/rules/AllOf.md
@@ -25,6 +25,6 @@ v::allOf(
 ***
 See also:
 
-  * [OneOf](OneOf.md)
   * [NoneOf](NoneOf.md)
+  * [OneOf](OneOf.md)
   * [When](When.md)
diff --git a/vendor/respect/validation/docs/rules/Alnum.md b/vendor/respect/validation/docs/rules/Alnum.md
index 184c1e2cfb64c88fc4ee5340077c6a22e8a3710c..fb5d7e1037e527732458be319950387cbc2abffe 100644
--- a/vendor/respect/validation/docs/rules/Alnum.md
+++ b/vendor/respect/validation/docs/rules/Alnum.md
@@ -39,6 +39,12 @@ the string of extra chars passed as the parameter.
 See also:
 
   * [Alpha](Alpha.md)
-  * [Digit](Digit.md)
+  * [Charset](Charset.md)
+  * [Cntrl](Cntrl.md)
   * [Consonant](Consonant.md)
+  * [Digit](Digit.md)
+  * [NoWhitespace](NoWhitespace.md)
+  * [Regex](Regex.md)
+  * [StringType](StringType.md)
   * [Vowel](Vowel.md)
+  * [Xdigit](Xdigit.md)
diff --git a/vendor/respect/validation/docs/rules/Alpha.md b/vendor/respect/validation/docs/rules/Alpha.md
index 44f4dc3714c3ebfd64c46a9da17bfa8a91c091f4..9dd24c4e3fee5fe130503c20de3908aa1ee1da79 100644
--- a/vendor/respect/validation/docs/rules/Alpha.md
+++ b/vendor/respect/validation/docs/rules/Alpha.md
@@ -9,6 +9,9 @@ This is similar to `v::alnum()`, but it doesn't allow numbers.
 See also:
 
   * [Alnum](Alnum.md)
-  * [Digit](Digit.md)
+  * [Charset](Charset.md)
   * [Consonant](Consonant.md)
+  * [Digit](Digit.md)
+  * [NoWhitespace](NoWhitespace.md)
+  * [Regex](Regex.md)
   * [Vowel](Vowel.md)
diff --git a/vendor/respect/validation/docs/rules/AlwaysInvalid.md b/vendor/respect/validation/docs/rules/AlwaysInvalid.md
index 34b364deb352ea110706b05ade042e04f0ee079f..b7b0bbaebbb5a77a60a6e5ecc0c536292e8e3be1 100644
--- a/vendor/respect/validation/docs/rules/AlwaysInvalid.md
+++ b/vendor/respect/validation/docs/rules/AlwaysInvalid.md
@@ -12,3 +12,4 @@ v::alwaysInvalid()->validate($whatever); // false
 See also:
 
   * [AlwaysValid](AlwaysValid.md)
+  * [When](When.md)
diff --git a/vendor/respect/validation/docs/rules/ArrayVal.md b/vendor/respect/validation/docs/rules/ArrayVal.md
index ec9eaf066a3b42a0ea67dd7351b818bf828f0cd6..34eb1969715e16e0b79a500488a71ec68adcefd3 100644
--- a/vendor/respect/validation/docs/rules/ArrayVal.md
+++ b/vendor/respect/validation/docs/rules/ArrayVal.md
@@ -20,3 +20,4 @@ See also:
   * [Key](Key.md)
   * [KeySet](KeySet.md)
   * [KeyValue](KeyValue.md)
+  * [Type](Type.md)
diff --git a/vendor/respect/validation/docs/rules/Attribute.md b/vendor/respect/validation/docs/rules/Attribute.md
index e48b6b664bb2c58027149a4870bacf6468659b4a..2b636cf118db08e0a585a1e821e5d6e8c36410b1 100644
--- a/vendor/respect/validation/docs/rules/Attribute.md
+++ b/vendor/respect/validation/docs/rules/Attribute.md
@@ -31,3 +31,5 @@ The name of this validator is automatically set to the attribute name.
 See also:
 
   * [Key](Key.md)
+  * [KeyNested](KeyNested.md)
+  * [ObjectType](ObjectType.md)
diff --git a/vendor/respect/validation/docs/rules/Bank.md b/vendor/respect/validation/docs/rules/Bank.md
index 028d71985d50b871bffeb9a9889c0cd8d81b27f2..0b04140cb174c4223c2863e4fe902af0bde77268 100644
--- a/vendor/respect/validation/docs/rules/Bank.md
+++ b/vendor/respect/validation/docs/rules/Bank.md
@@ -18,3 +18,5 @@ See also:
 
   * [BankAccount](BankAccount.md)
   * [Bic](Bic.md)
+  * [CreditCard](CreditCard.md)
+  * [IdentityCard](IdentityCard.md)
diff --git a/vendor/respect/validation/docs/rules/BankAccount.md b/vendor/respect/validation/docs/rules/BankAccount.md
index f9d319d7f82c2ba7d6d681ab7f33ed43df3abfa4..f2b4d17dc20c62bfba7dfabe9923b1cda32630ab 100644
--- a/vendor/respect/validation/docs/rules/BankAccount.md
+++ b/vendor/respect/validation/docs/rules/BankAccount.md
@@ -18,3 +18,4 @@ See also:
 
   * [Bank](Bank.md)
   * [Bic](Bic.md)
+  * [CreditCard](CreditCard.md)
diff --git a/vendor/respect/validation/docs/rules/Between.md b/vendor/respect/validation/docs/rules/Between.md
index 5c0204afc9aed1fb1834d82d0050cb274b060152..5cdfef0dd12a0aa7e92a6d0d600327fdcc37997d 100644
--- a/vendor/respect/validation/docs/rules/Between.md
+++ b/vendor/respect/validation/docs/rules/Between.md
@@ -39,6 +39,8 @@ Message template for this validator includes `{{minValue}}` and `{{maxValue}}`.
 ***
 See also:
 
+  * [Age](Age.md)
+  * [Date](Date.md)
   * [Length](Length.md)
-  * [Min](Min.md)
   * [Max](Max.md)
+  * [Min](Min.md)
diff --git a/vendor/respect/validation/docs/rules/Bic.md b/vendor/respect/validation/docs/rules/Bic.md
index 82c67e8810a5caaadcd36cf798b35969935b1567..e49b48655eab592ece24f7b6d7508d990c70bcd6 100644
--- a/vendor/respect/validation/docs/rules/Bic.md
+++ b/vendor/respect/validation/docs/rules/Bic.md
@@ -18,3 +18,4 @@ See also:
 
   * [Bank](Bank.md)
   * [BankAccount](BankAccount.md)
+  * [CreditCard](CreditCard.md)
diff --git a/vendor/respect/validation/docs/rules/BoolType.md b/vendor/respect/validation/docs/rules/BoolType.md
index 979562189815b5d858b03e316120796971063de5..54eb0e72e551ec7df1bca4994510079bc5f72dfd 100644
--- a/vendor/respect/validation/docs/rules/BoolType.md
+++ b/vendor/respect/validation/docs/rules/BoolType.md
@@ -13,6 +13,7 @@ v::boolType()->validate(false); // true
 See also:
 
   * [ArrayType](ArrayType.md)
+  * [BoolVal](BoolVal.md)
   * [CallableType](CallableType.md)
   * [FloatType](FloatType.md)
   * [FloatVal](FloatVal.md)
diff --git a/vendor/respect/validation/docs/rules/Bsn.md b/vendor/respect/validation/docs/rules/Bsn.md
index e67f55e70d22aeddfe110578ff0cd57ff05fb2e3..56af647c906787aac7c42aa2aa1578064b102a7d 100644
--- a/vendor/respect/validation/docs/rules/Bsn.md
+++ b/vendor/respect/validation/docs/rules/Bsn.md
@@ -14,3 +14,4 @@ See also:
   * [Cnh](Cnh.md)
   * [Cnpj](Cnpj.md)
   * [Cpf](Cpf.md)
+  * [Imei](Imei.md)
diff --git a/vendor/respect/validation/docs/rules/CallableType.md b/vendor/respect/validation/docs/rules/CallableType.md
index 7f24dca7b0dfcbb4ae4591061d75f75793d35709..98250a8972f984ce734e6d3d1da5d4bc522421a5 100644
--- a/vendor/respect/validation/docs/rules/CallableType.md
+++ b/vendor/respect/validation/docs/rules/CallableType.md
@@ -15,6 +15,7 @@ See also:
 
   * [ArrayType](ArrayType.md)
   * [BoolType](BoolType.md)
+  * [BoolVal](BoolVal.md)
   * [Callback](Callback.md)
   * [FloatType](FloatType.md)
   * [IntType](IntType.md)
diff --git a/vendor/respect/validation/docs/rules/Charset.md b/vendor/respect/validation/docs/rules/Charset.md
index 43d889bdc687c4221eb82510f6fada2b39db8048..658aa1045c997ee3fa8eb040d1913438b37dd940 100644
--- a/vendor/respect/validation/docs/rules/Charset.md
+++ b/vendor/respect/validation/docs/rules/Charset.md
@@ -17,3 +17,4 @@ See also:
 
   * [Alnum](Alnum.md)
   * [Alpha](Alpha.md)
+  * [PhpLabel](PhpLabel.md)
diff --git a/vendor/respect/validation/docs/rules/Cnh.md b/vendor/respect/validation/docs/rules/Cnh.md
index 6815929a3910d537c8e5131828dd68fd176d9d29..e4c6b239ce50a71df871fd5ade3b6c3effd2ef1e 100644
--- a/vendor/respect/validation/docs/rules/Cnh.md
+++ b/vendor/respect/validation/docs/rules/Cnh.md
@@ -11,5 +11,8 @@ v::cnh()->validate('02650306461'); // true
 ***
 See also:
 
+  * [Bsn](Bsn.md)
   * [Cnpj](Cnpj.md)
   * [Cpf](Cpf.md)
+  * [Imei](Imei.md)
+  * [NfeAccessKey](NfeAccessKey.md)
diff --git a/vendor/respect/validation/docs/rules/Cnpj.md b/vendor/respect/validation/docs/rules/Cnpj.md
index 846d391762c2523cc527c61829c227ea3909f502..97b5d5f67dd1773b3c2da824a059d6d3917126e3 100644
--- a/vendor/respect/validation/docs/rules/Cnpj.md
+++ b/vendor/respect/validation/docs/rules/Cnpj.md
@@ -8,5 +8,8 @@ use `->digit()` if needed.
 ***
 See also:
 
-  * [Cpf](Cpf.md)
+  * [Bsn](Bsn.md)
   * [Cnh](Cnh.md)
+  * [Cpf](Cpf.md)
+  * [Imei](Imei.md)
+  * [NfeAccessKey](NfeAccessKey.md)
diff --git a/vendor/respect/validation/docs/rules/Cntrl.md b/vendor/respect/validation/docs/rules/Cntrl.md
index 7a6552aa8e0529dcbc08cd4017f9bd65434a1dc2..5a4dbfbe76795cc4e4c03aadf38c249fd0384e45 100644
--- a/vendor/respect/validation/docs/rules/Cntrl.md
+++ b/vendor/respect/validation/docs/rules/Cntrl.md
@@ -14,4 +14,5 @@ See also:
 
   * [Alnum](Alnum.md)
   * [Prnt](Prnt.md)
+  * [Punct](Punct.md)
   * [Space](Space.md)
diff --git a/vendor/respect/validation/docs/rules/Consonant.md b/vendor/respect/validation/docs/rules/Consonant.md
index fac1fe53319d7ba5afe0f39aef44f4116a1b6c71..eede069e1a201a203ae4401ed72243407a842ec5 100644
--- a/vendor/respect/validation/docs/rules/Consonant.md
+++ b/vendor/respect/validation/docs/rules/Consonant.md
@@ -13,6 +13,6 @@ v::consonant()->validate('xkcd'); // true
 See also:
 
   * [Alnum](Alnum.md)
-  * [Digit](Digit.md)
   * [Alpha](Alpha.md)
+  * [Digit](Digit.md)
   * [Vowel](Vowel.md)
diff --git a/vendor/respect/validation/docs/rules/Contains.md b/vendor/respect/validation/docs/rules/Contains.md
index 6036494fe43cbbb06015a2e7edcc9fd4871d6d00..1e4a0c82f9641323a75495cc864e50b03b2dd70b 100644
--- a/vendor/respect/validation/docs/rules/Contains.md
+++ b/vendor/respect/validation/docs/rules/Contains.md
@@ -23,6 +23,9 @@ Message template for this validator includes `{{containsValue}}`.
 ***
 See also:
 
-  * [StartsWith](StartsWith.md)
   * [EndsWith](EndsWith.md)
+  * [Equals](Equals.md)
+  * [Identical](Identical.md)
   * [In](In.md)
+  * [Regex](Regex.md)
+  * [StartsWith](StartsWith.md)
diff --git a/vendor/respect/validation/docs/rules/Countable.md b/vendor/respect/validation/docs/rules/Countable.md
index 0353de4d7a748ed9f490149b8f07d1343f084036..5aaf53b6309c7d3d63e7c402886bab8a2dd002d3 100644
--- a/vendor/respect/validation/docs/rules/Countable.md
+++ b/vendor/respect/validation/docs/rules/Countable.md
@@ -14,6 +14,7 @@ v::countable()->validate('string'); // false
 ***
 See also:
 
+  * [ArrayType](ArrayType.md)
   * [ArrayVal](ArrayVal.md)
   * [Instance](Instance.md)
   * [IterableType](IterableType.md)
diff --git a/vendor/respect/validation/docs/rules/CountryCode.md b/vendor/respect/validation/docs/rules/CountryCode.md
index 469313db2dcb66a7306d53510b54c136afa758a8..c6c532a3e60fb8db0e038a61890839b1b4fb02f6 100644
--- a/vendor/respect/validation/docs/rules/CountryCode.md
+++ b/vendor/respect/validation/docs/rules/CountryCode.md
@@ -8,7 +8,16 @@ Validates an ISO country code like US or BR.
 v::countryCode()->validate('BR'); // true
 ```
 
+This rules uses data from [iso-codes][].
+
 ***
 See also:
 
+  * [CurrencyCode](CurrencyCode.md)
+  * [LanguageCode](LanguageCode.md)
+  * [PostalCode](PostalCode.md)
+  * [SubdivisionCode](SubdivisionCode.md)
   * [Tld](Tld.md)
+
+
+[iso-codes]: https://salsa.debian.org/iso-codes-team/iso-codes
diff --git a/vendor/respect/validation/docs/rules/Cpf.md b/vendor/respect/validation/docs/rules/Cpf.md
index 0fc3a717af13febc2d111218e534d9f61271e037..14a0acbd5b29a95502941165115797b833956ea4 100644
--- a/vendor/respect/validation/docs/rules/Cpf.md
+++ b/vendor/respect/validation/docs/rules/Cpf.md
@@ -24,5 +24,8 @@ v::digit()->cpf()->validate('44455566820'); // true
 ***
 See also:
 
-  * [Cnpj](Cnpj.md)
+  * [Bsn](Bsn.md)
   * [Cnh](Cnh.md)
+  * [Cnpj](Cnpj.md)
+  * [Imei](Imei.md)
+  * [NfeAccessKey](NfeAccessKey.md)
diff --git a/vendor/respect/validation/docs/rules/Date.md b/vendor/respect/validation/docs/rules/Date.md
index 4afb9ecbd56a4b49614375508f38bc18cb1b5170..aa2dc9464d6da7f1fdc0358315193cf553c96d84 100644
--- a/vendor/respect/validation/docs/rules/Date.md
+++ b/vendor/respect/validation/docs/rules/Date.md
@@ -34,7 +34,8 @@ Message template for this validator includes `{{format}}`.
 ***
 See also:
 
+  * [Age](Age.md)
   * [Between](Between.md)
-  * [MinimumAge](MinimumAge.md)
   * [LeapDate](LeapDate.md)
   * [LeapYear](LeapYear.md)
+  * [MinimumAge](MinimumAge.md)
diff --git a/vendor/respect/validation/docs/rules/Digit.md b/vendor/respect/validation/docs/rules/Digit.md
index c4638483f4d6734817263c9891263a1ea2d41deb..70cc90b3f8501136e04265219e552e7b5c7d34f3 100644
--- a/vendor/respect/validation/docs/rules/Digit.md
+++ b/vendor/respect/validation/docs/rules/Digit.md
@@ -9,5 +9,13 @@ See also:
 
   * [Alnum](Alnum.md)
   * [Alpha](Alpha.md)
-  * [Vowel](Vowel.md)
   * [Consonant](Consonant.md)
+  * [Factor](Factor.md)
+  * [Finite](Finite.md)
+  * [Infinite](Infinite.md)
+  * [IntType](IntType.md)
+  * [IntVal](IntVal.md)
+  * [Numeric](Numeric.md)
+  * [Regex](Regex.md)
+  * [Vowel](Vowel.md)
+  * [Xdigit](Xdigit.md)
diff --git a/vendor/respect/validation/docs/rules/Directory.md b/vendor/respect/validation/docs/rules/Directory.md
index 7d49c63b726e0bec8c8d615092d3ed7ce275755c..9f577c6e5d04aa7d098f72265f188cdc05caa1a4 100644
--- a/vendor/respect/validation/docs/rules/Directory.md
+++ b/vendor/respect/validation/docs/rules/Directory.md
@@ -22,6 +22,7 @@ See also:
   * [Exists](Exists.md)
   * [Extension](Extension.md)
   * [File](File.md)
+  * [Image](Image.md)
   * [Mimetype](Mimetype.md)
   * [Readable](Readable.md)
   * [Size](Size.md)
diff --git a/vendor/respect/validation/docs/rules/Domain.md b/vendor/respect/validation/docs/rules/Domain.md
index ac5d76a7b77d89952de912a75c614fa3479f99aa..af444bf2cd53019f1566ffad0a668c4a46a0da94 100644
--- a/vendor/respect/validation/docs/rules/Domain.md
+++ b/vendor/respect/validation/docs/rules/Domain.md
@@ -33,8 +33,10 @@ Messages for this validator will reflect rules above.
 See also:
 
   * [Ip](Ip.md)
+  * [Json](Json.md)
   * [MacAddress](MacAddress.md)
   * [Tld](Tld.md)
+  * [Url](Url.md)
 
 [PunnyCode]: http://en.wikipedia.org/wiki/Punycode "Wikipedia: Punnycode"
 [IDNA]: http://en.wikipedia.org/wiki/Internationalized_domain_name#Internationalizing_Domain_Names_in_Applications "Wikipedia: Internationalized domain name"
diff --git a/vendor/respect/validation/docs/rules/Each.md b/vendor/respect/validation/docs/rules/Each.md
index ecc1c666359e921a9a33cdebe1a2c3ee5a6c4a92..a1d9a279276982a8c890e506d3d30073f88035f9 100644
--- a/vendor/respect/validation/docs/rules/Each.md
+++ b/vendor/respect/validation/docs/rules/Each.md
@@ -23,5 +23,5 @@ Using `arrayVal()` before `each()` is a best practice.
 ***
 See also:
 
-  * [Key](Key.md)
   * [ArrayVal](ArrayVal.md)
+  * [Key](Key.md)
diff --git a/vendor/respect/validation/docs/rules/Email.md b/vendor/respect/validation/docs/rules/Email.md
index 64a4d7cf3c4896dd1786e20c99b74bd89adbf184..2721ce169c487fa75ed46fa9cf0cb751675c3e00 100644
--- a/vendor/respect/validation/docs/rules/Email.md
+++ b/vendor/respect/validation/docs/rules/Email.md
@@ -11,6 +11,7 @@ v::email()->validate('alexandre@gaigalas.net'); // true
 ***
 See also:
 
+  * [Json](Json.md)
   * [Phone](Phone.md)
   * [Url](Url.md)
   * [VideoUrl](VideoUrl.md)
diff --git a/vendor/respect/validation/docs/rules/EndsWith.md b/vendor/respect/validation/docs/rules/EndsWith.md
index 99ec5b215a194760e80132ea1083bd791b903b0e..27ba193f31908ca9206ed530b449d955bc3631b9 100644
--- a/vendor/respect/validation/docs/rules/EndsWith.md
+++ b/vendor/respect/validation/docs/rules/EndsWith.md
@@ -26,6 +26,7 @@ Message template for this validator includes `{{endValue}}`.
 ***
 See also:
 
-  * [StartsWith](StartsWith.md)
   * [Contains](Contains.md)
   * [In](In.md)
+  * [Regex](Regex.md)
+  * [StartsWith](StartsWith.md)
diff --git a/vendor/respect/validation/docs/rules/Equals.md b/vendor/respect/validation/docs/rules/Equals.md
index e28f783dfcfd4128c7eecba94307e4ae53aeff1c..4a0c2cfbc206493f9b575af9a53cc151884e768f 100644
--- a/vendor/respect/validation/docs/rules/Equals.md
+++ b/vendor/respect/validation/docs/rules/Equals.md
@@ -15,3 +15,5 @@ See also:
 
   * [Contains](Contains.md)
   * [Identical](Identical.md)
+  * [KeyValue](KeyValue.md)
+  * [Version](Version.md)
diff --git a/vendor/respect/validation/docs/rules/Even.md b/vendor/respect/validation/docs/rules/Even.md
index da52597b85c0793e85862dd42611df0f4da6a7cd..73ed89afc00753d6ae36734c1174eacbce6a0354 100644
--- a/vendor/respect/validation/docs/rules/Even.md
+++ b/vendor/respect/validation/docs/rules/Even.md
@@ -13,5 +13,5 @@ Using `int()` before `even()` is a best practice.
 ***
 See also:
 
-  * [Odd](Odd.md)
   * [Multiple](Multiple.md)
+  * [Odd](Odd.md)
diff --git a/vendor/respect/validation/docs/rules/Executable.md b/vendor/respect/validation/docs/rules/Executable.md
index 7c1e1303dc350d4034dc1f8c6454e835943187e2..eda6f625efc2b43b20f4116f04c35cabe962a8ae 100644
--- a/vendor/respect/validation/docs/rules/Executable.md
+++ b/vendor/respect/validation/docs/rules/Executable.md
@@ -15,6 +15,7 @@ See also:
   * [Exists](Exists.md)
   * [Extension](Extension.md)
   * [File](File.md)
+  * [Image](Image.md)
   * [Mimetype](Mimetype.md)
   * [Readable](Readable.md)
   * [Size](Size.md)
diff --git a/vendor/respect/validation/docs/rules/Exists.md b/vendor/respect/validation/docs/rules/Exists.md
index 681c50743b70cd7b36548571ca47ae2d51cc4075..b69b1f3128bc7902912730ec985e7eab1fb725e5 100644
--- a/vendor/respect/validation/docs/rules/Exists.md
+++ b/vendor/respect/validation/docs/rules/Exists.md
@@ -22,6 +22,7 @@ See also:
   * [Executable](Executable.md)
   * [Extension](Extension.md)
   * [File](File.md)
+  * [Image](Image.md)
   * [Mimetype](Mimetype.md)
   * [Readable](Readable.md)
   * [Size](Size.md)
diff --git a/vendor/respect/validation/docs/rules/Extension.md b/vendor/respect/validation/docs/rules/Extension.md
index 4abc0d5ba51f701827dd166daac098ec79c65e3f..51b5a268ce7b6fa49095b921ca04f9e26dcdaa22 100644
--- a/vendor/respect/validation/docs/rules/Extension.md
+++ b/vendor/respect/validation/docs/rules/Extension.md
@@ -17,6 +17,7 @@ See also:
   * [Executable](Executable.md)
   * [Exists](Exists.md)
   * [File](File.md)
+  * [Image](Image.md)
   * [Mimetype](Mimetype.md)
   * [Readable](Readable.md)
   * [Size](Size.md)
diff --git a/vendor/respect/validation/docs/rules/Factor.md b/vendor/respect/validation/docs/rules/Factor.md
index 1e04276432d1bc8583fa89da6c004d43abdb2568..3d95fa4bbb38be9dd663a8e98d3ba2f931889065 100644
--- a/vendor/respect/validation/docs/rules/Factor.md
+++ b/vendor/respect/validation/docs/rules/Factor.md
@@ -17,3 +17,5 @@ See also:
   * [Finite](Finite.md)
   * [Infinite](Infinite.md)
   * [Numeric](Numeric.md)
+  * [PerfectSquare](PerfectSquare.md)
+  * [PrimeNumber](PrimeNumber.md)
diff --git a/vendor/respect/validation/docs/rules/Fibonacci.md b/vendor/respect/validation/docs/rules/Fibonacci.md
index fe8c5235b775e98fda3c81e43f1736e7e18dc30f..4d13154cb472a576bfa19a95f62da2b88629e168 100644
--- a/vendor/respect/validation/docs/rules/Fibonacci.md
+++ b/vendor/respect/validation/docs/rules/Fibonacci.md
@@ -13,5 +13,5 @@ v::fibonacci()->validate(6); // false
 ***
 See also:
 
+  * [PerfectSquare](PerfectSquare.md)
   * [PrimeNumber](PrimeNumber.md)
-  * [PerfectSquare](PerfectSquare.md)
\ No newline at end of file
diff --git a/vendor/respect/validation/docs/rules/File.md b/vendor/respect/validation/docs/rules/File.md
index 8454d0258d2d1922fc5105c71f1e6ea3a3ab28fb..05667f1c12a8991e231888cb0ddccb089111c1ee 100644
--- a/vendor/respect/validation/docs/rules/File.md
+++ b/vendor/respect/validation/docs/rules/File.md
@@ -22,6 +22,7 @@ See also:
   * [Executable](Executable.md)
   * [Exists](Exists.md)
   * [Extension](Extension.md)
+  * [Image](Image.md)
   * [Mimetype](Mimetype.md)
   * [Readable](Readable.md)
   * [Size](Size.md)
diff --git a/vendor/respect/validation/docs/rules/FilterVar.md b/vendor/respect/validation/docs/rules/FilterVar.md
index a13d4fa091ffab6afb9a9df90b13d9adba374d64..ba1d714a9e0b591c697c2adcf60fcb70dccbab34 100644
--- a/vendor/respect/validation/docs/rules/FilterVar.md
+++ b/vendor/respect/validation/docs/rules/FilterVar.md
@@ -16,3 +16,5 @@ v::filterVar(FILTER_VALIDATE_URL, FILTER_FLAG_PATH_REQUIRED)->validate('http://e
 See also:
 
   * [Callback](Callback.md)
+  * [Json](Json.md)
+  * [Url](Url.md)
diff --git a/vendor/respect/validation/docs/rules/Finite.md b/vendor/respect/validation/docs/rules/Finite.md
index 42ef9f30d6d833305e0140c368d87694dd9b887c..7f99e8bb2391bfad815436a6046af03ed2e022d2 100644
--- a/vendor/respect/validation/docs/rules/Finite.md
+++ b/vendor/respect/validation/docs/rules/Finite.md
@@ -13,6 +13,9 @@ v::finite()->validate(10); // true
 See also:
 
   * [Digit](Digit.md)
+  * [Factor](Factor.md)
   * [Infinite](Infinite.md)
+  * [IntType](IntType.md)
   * [IntVal](IntVal.md)
   * [Numeric](Numeric.md)
+  * [Type](Type.md)
diff --git a/vendor/respect/validation/docs/rules/FloatType.md b/vendor/respect/validation/docs/rules/FloatType.md
index 87efee83511a971477a7ec4ca2f84fc4ab81dbcc..a4dd195109f697db309534232cee2b793fc6c78d 100644
--- a/vendor/respect/validation/docs/rules/FloatType.md
+++ b/vendor/respect/validation/docs/rules/FloatType.md
@@ -13,7 +13,9 @@ v::floatType()->validate(0e5); // true
 ***
 See also:
 
+  * [ArrayType](ArrayType.md)
   * [BoolType](BoolType.md)
+  * [BoolVal](BoolVal.md)
   * [CallableType](CallableType.md)
   * [FloatVal](FloatVal.md)
   * [IntType](IntType.md)
diff --git a/vendor/respect/validation/docs/rules/FloatVal.md b/vendor/respect/validation/docs/rules/FloatVal.md
index f73c2fc073094600820a00cba34c34ec6c378bd3..70983323f408260400cdb7b6b4f9e4dfe23cc1ef 100644
--- a/vendor/respect/validation/docs/rules/FloatVal.md
+++ b/vendor/respect/validation/docs/rules/FloatVal.md
@@ -12,6 +12,9 @@ v::floatVal()->validate('1e5'); // true
 ***
 See also:
 
+  * [BoolType](BoolType.md)
+  * [BoolVal](BoolVal.md)
   * [FloatType](FloatType.md)
   * [IntType](IntType.md)
   * [IntVal](IntVal.md)
+  * [Type](Type.md)
diff --git a/vendor/respect/validation/docs/rules/Graph.md b/vendor/respect/validation/docs/rules/Graph.md
index 2c7503ad785414e4459968261f12b844a93db206..9a767be63533e40721d6bcd3bc1b136bcabf4aba 100644
--- a/vendor/respect/validation/docs/rules/Graph.md
+++ b/vendor/respect/validation/docs/rules/Graph.md
@@ -13,3 +13,4 @@ v::graph()->validate('LKM@#$%4;'); // true
 See also:
 
   * [Prnt](Prnt.md)
+  * [Punct](Punct.md)
diff --git a/vendor/respect/validation/docs/rules/HexRgbColor.md b/vendor/respect/validation/docs/rules/HexRgbColor.md
index 3e4a1e98d9e538d3f90f4aa2f25ab88e85bfaf8e..020a1b6c6df051ae96fba88315479279eb1c5408 100644
--- a/vendor/respect/validation/docs/rules/HexRgbColor.md
+++ b/vendor/respect/validation/docs/rules/HexRgbColor.md
@@ -9,8 +9,6 @@ v::hexRgbColor()->validate('#FFFAAA'); // true
 v::hexRgbColor()->validate('123123'); // true
 v::hexRgbColor()->validate('FCD'); // true
 ```
-
-***
 See also:
 
-  * [Vxdigit](Vxdigit.md)
+  * [Xdigit](Xdigit.md)
diff --git a/vendor/respect/validation/docs/rules/In.md b/vendor/respect/validation/docs/rules/In.md
index a8aa698141b844e55c90845c8acdefca31f05ba1..432968b380145ca5e6b69611536ade7b1d8df9ac 100644
--- a/vendor/respect/validation/docs/rules/In.md
+++ b/vendor/respect/validation/docs/rules/In.md
@@ -25,6 +25,7 @@ Message template for this validator includes `{{haystack}}`.
 ***
 See also:
 
-  * [StartsWith](StartsWith.md)
-  * [EndsWith](EndsWith.md)
   * [Contains](Contains.md)
+  * [EndsWith](EndsWith.md)
+  * [Roman](Roman.md)
+  * [StartsWith](StartsWith.md)
diff --git a/vendor/respect/validation/docs/rules/Infinite.md b/vendor/respect/validation/docs/rules/Infinite.md
index d29c666a4f11afd0ae697fca58c4c837705a72b1..dee5a290bee85e266d4560644714258ab9c42362 100644
--- a/vendor/respect/validation/docs/rules/Infinite.md
+++ b/vendor/respect/validation/docs/rules/Infinite.md
@@ -12,6 +12,9 @@ v::infinite()->validate(INF); // true
 See also:
 
   * [Digit](Digit.md)
+  * [Factor](Factor.md)
   * [Finite](Finite.md)
+  * [IntType](IntType.md)
   * [IntVal](IntVal.md)
   * [Numeric](Numeric.md)
+  * [Type](Type.md)
diff --git a/vendor/respect/validation/docs/rules/Instance.md b/vendor/respect/validation/docs/rules/Instance.md
index bbb45dd0c888a24183525f1d9e539c59bbd3c8cf..b1ba010d9b8d0a26f735e5c28ec971034643f433 100644
--- a/vendor/respect/validation/docs/rules/Instance.md
+++ b/vendor/respect/validation/docs/rules/Instance.md
@@ -14,4 +14,7 @@ Message template for this validator includes `{{instanceName}}`.
 ***
 See also:
 
+  * [Countable](Countable.md)
+  * [IterableType](IterableType.md)
   * [ObjectType](ObjectType.md)
+  * [Type](Type.md)
diff --git a/vendor/respect/validation/docs/rules/IntType.md b/vendor/respect/validation/docs/rules/IntType.md
index d4313657fccba3df7b4c9c9a4fd95744a6d10950..6db5f709fbf5d9bbdbc944732ef82e5507dc329c 100644
--- a/vendor/respect/validation/docs/rules/IntType.md
+++ b/vendor/respect/validation/docs/rules/IntType.md
@@ -12,11 +12,14 @@ v::intType()->validate('10'); // false
 ***
 See also:
 
+  * [ArrayType](ArrayType.md)
   * [BoolType](BoolType.md)
+  * [BoolVal](BoolVal.md)
   * [CallableType](CallableType.md)
   * [Digit](Digit.md)
   * [Finite](Finite.md)
   * [FloatType](FloatType.md)
+  * [FloatVal](FloatVal.md)
   * [Infinite](Infinite.md)
   * [IntVal](IntVal.md)
   * [NullType](NullType.md)
diff --git a/vendor/respect/validation/docs/rules/IntVal.md b/vendor/respect/validation/docs/rules/IntVal.md
index 18a04046192e8e3e6642d635d394946f16ec078f..c754eb68a374aded54fc9afbdd9a8719309ae0c4 100644
--- a/vendor/respect/validation/docs/rules/IntVal.md
+++ b/vendor/respect/validation/docs/rules/IntVal.md
@@ -14,5 +14,9 @@ See also:
 
   * [Digit](Digit.md)
   * [Finite](Finite.md)
+  * [FloatType](FloatType.md)
+  * [FloatVal](FloatVal.md)
   * [Infinite](Infinite.md)
+  * [IntType](IntType.md)
   * [Numeric](Numeric.md)
+  * [Type](Type.md)
diff --git a/vendor/respect/validation/docs/rules/Iterable.md b/vendor/respect/validation/docs/rules/Iterable.md
index b64abe28899857ddec73717780d5e5acc4a4560c..d23795824afd124a81eb79d15fda39ce06dcc39f 100644
--- a/vendor/respect/validation/docs/rules/Iterable.md
+++ b/vendor/respect/validation/docs/rules/Iterable.md
@@ -3,3 +3,6 @@
 - `v::iterable()`
 
 **Deprecated**: Use [IterableType](IterableType.md) instead.
+See also:
+
+  * [IterableType](IterableType.md)
diff --git a/vendor/respect/validation/docs/rules/IterableType.md b/vendor/respect/validation/docs/rules/IterableType.md
index a246af271f9cba26a1b0dd538f1eb637e6056e14..93b67c16b73491e0da04bf075ac0f6a59d2e201a 100644
--- a/vendor/respect/validation/docs/rules/IterableType.md
+++ b/vendor/respect/validation/docs/rules/IterableType.md
@@ -15,6 +15,8 @@ v::iterableType()->validate('string'); // false
 ***
 See also:
 
+  * [ArrayType](ArrayType.md)
   * [ArrayVal](ArrayVal.md)
   * [Countable](Countable.md)
   * [Instance](Instance.md)
+  * [Iterable](Iterable.md)
diff --git a/vendor/respect/validation/docs/rules/Key.md b/vendor/respect/validation/docs/rules/Key.md
index 70a74c07a5a2836c4879799cddfbae89d377a23a..f3081dd6974757f32a2503b9a3776b1230e9725b 100644
--- a/vendor/respect/validation/docs/rules/Key.md
+++ b/vendor/respect/validation/docs/rules/Key.md
@@ -31,4 +31,9 @@ The name of this validator is automatically set to the key name.
 ***
 See also:
 
+  * [ArrayVal](ArrayVal.md)
   * [Attribute](Attribute.md)
+  * [Each](Each.md)
+  * [KeyNested](KeyNested.md)
+  * [KeySet](KeySet.md)
+  * [KeyValue](KeyValue.md)
diff --git a/vendor/respect/validation/docs/rules/KeyNested.md b/vendor/respect/validation/docs/rules/KeyNested.md
index 3129dde31c723082fab3332c9c0fa6a3ef81bd2e..ed0134767a52969612f7a87a915ccb2158fa139c 100644
--- a/vendor/respect/validation/docs/rules/KeyNested.md
+++ b/vendor/respect/validation/docs/rules/KeyNested.md
@@ -35,6 +35,6 @@ See also:
 
   * [Attribute](Attribute.md)
   * [Key](Key.md)
-
+  * [KeyValue](KeyValue.md)
 
 [Yii2 ArrayHelper]: https://github.com/yiisoft/yii2/blob/68c30c1/framework/helpers/BaseArrayHelper.php "Yii2 ArrayHelper"
diff --git a/vendor/respect/validation/docs/rules/KeySet.md b/vendor/respect/validation/docs/rules/KeySet.md
index faf40818aafbd384335127681e039e5c744ce1dc..23d8bca5e6e7b0ac7966afb2a95892c6309f68ef 100644
--- a/vendor/respect/validation/docs/rules/KeySet.md
+++ b/vendor/respect/validation/docs/rules/KeySet.md
@@ -48,4 +48,6 @@ The keys' order is not considered in the validation.
 ***
 See also:
 
+  * [ArrayVal](ArrayVal.md)
   * [Key](Key.md)
+  * [KeyValue](KeyValue.md)
diff --git a/vendor/respect/validation/docs/rules/KeyValue.md b/vendor/respect/validation/docs/rules/KeyValue.md
index 98ee9db8731581b6fbda57e80f05742a5e4b4b0c..d512eb5c8af5db6cbb408f667f755d479ae1b63f 100644
--- a/vendor/respect/validation/docs/rules/KeyValue.md
+++ b/vendor/respect/validation/docs/rules/KeyValue.md
@@ -56,7 +56,9 @@ password_confirmation must be equals "password"
 ***
 See also:
 
+  * [ArrayVal](ArrayVal.md)
+  * [Equals](Equals.md)
   * [Key](Key.md)
   * [KeyNested](KeyNested.md)
   * [KeySet](KeySet.md)
-
+  * [SubdivisionCode](SubdivisionCode.md)
diff --git a/vendor/respect/validation/docs/rules/LanguageCode.md b/vendor/respect/validation/docs/rules/LanguageCode.md
index a990f315a9a6f8d8b5261bfeab954fa5890a1bed..df1a93e8e3de7192459cac9646908bfbeadaf959 100644
--- a/vendor/respect/validation/docs/rules/LanguageCode.md
+++ b/vendor/respect/validation/docs/rules/LanguageCode.md
@@ -17,4 +17,4 @@ You can choose between alpha-2 and alpha-3, alpha-2 is set by default.
 ***
 See also:
 
-  * [CountryCode](CountryCode.md)
\ No newline at end of file
+  * [CountryCode](CountryCode.md)
diff --git a/vendor/respect/validation/docs/rules/Max.md b/vendor/respect/validation/docs/rules/Max.md
index 1c199b9497ad9067e2241117fbc8893543443996..9e02a0682e7986541f9cc27a3e08fa0c9d31bd6e 100644
--- a/vendor/respect/validation/docs/rules/Max.md
+++ b/vendor/respect/validation/docs/rules/Max.md
@@ -32,5 +32,6 @@ Message template for this validator includes `{{maxValue}}`.
 ***
 See also:
 
-  * [Min](Min.md)
+  * [Age](Age.md)
   * [Between](Between.md)
+  * [Min](Min.md)
diff --git a/vendor/respect/validation/docs/rules/Mimetype.md b/vendor/respect/validation/docs/rules/Mimetype.md
index a2af05e8c74aec337944d3a1566a5a050ba822b4..523ae1493dd181f8f98d51230b7fb425f8b59a64 100644
--- a/vendor/respect/validation/docs/rules/Mimetype.md
+++ b/vendor/respect/validation/docs/rules/Mimetype.md
@@ -18,6 +18,7 @@ See also:
   * [Exists](Exists.md)
   * [Extension](Extension.md)
   * [File](File.md)
+  * [Image](Image.md)
   * [Readable](Readable.md)
   * [Size](Size.md)
   * [SymbolicLink](SymbolicLink.md)
diff --git a/vendor/respect/validation/docs/rules/Min.md b/vendor/respect/validation/docs/rules/Min.md
index 460154f25f8435fe489caff1681dd0c1ee49ce37..9e186865079e3658942b7659204e07ec05c3af29 100644
--- a/vendor/respect/validation/docs/rules/Min.md
+++ b/vendor/respect/validation/docs/rules/Min.md
@@ -25,5 +25,6 @@ Message template for this validator includes `{{minValue}}`.
 ***
 See also:
 
-  * [Max](Max.md)
+  * [Age](Age.md)
   * [Between](Between.md)
+  * [Max](Max.md)
diff --git a/vendor/respect/validation/docs/rules/Multiple.md b/vendor/respect/validation/docs/rules/Multiple.md
index b6d8c7ff02ce91038d3b57c4abff84308cacc737..8f59586468d036a25e42dc5db7c35d678379cd64 100644
--- a/vendor/respect/validation/docs/rules/Multiple.md
+++ b/vendor/respect/validation/docs/rules/Multiple.md
@@ -11,4 +11,6 @@ v::intVal()->multiple(3)->validate(9); // true
 ***
 See also:
 
+  * [Even](Even.md)
+  * [Odd](Odd.md)
   * [PrimeNumber](PrimeNumber.md)
diff --git a/vendor/respect/validation/docs/rules/No.md b/vendor/respect/validation/docs/rules/No.md
index e50b4c72becd343ad8682869488b9522d8fd456f..4e01e47383bfc1c368e97f83589700cd37a7f0f7 100644
--- a/vendor/respect/validation/docs/rules/No.md
+++ b/vendor/respect/validation/docs/rules/No.md
@@ -21,4 +21,6 @@ If `$locale` is TRUE, uses the value of [nl_langinfo()](http://php.net/nl_langin
 ***
 See also:
 
+  * [BoolType](BoolType.md)
+  * [BoolVal](BoolVal.md)
   * [Yes](Yes.md)
diff --git a/vendor/respect/validation/docs/rules/NoWhitespace.md b/vendor/respect/validation/docs/rules/NoWhitespace.md
index 052cfcdee028d66c24fe55bb1b6bce6ee64e7a27..521379e252bc4a9604456acdc14aeeaf60252c83 100644
--- a/vendor/respect/validation/docs/rules/NoWhitespace.md
+++ b/vendor/respect/validation/docs/rules/NoWhitespace.md
@@ -19,3 +19,4 @@ See also:
   * [NotBlank](NotBlank.md)
   * [NotEmpty](NotEmpty.md)
   * [NotOptional](NotOptional.md)
+  * [Optional](Optional.md)
diff --git a/vendor/respect/validation/docs/rules/NoneOf.md b/vendor/respect/validation/docs/rules/NoneOf.md
index 44e91537e8754135bf7f3a0400e0d5259d036188..3608bc5d7876a3365702dba2ffbf515ce5137f74 100644
--- a/vendor/respect/validation/docs/rules/NoneOf.md
+++ b/vendor/respect/validation/docs/rules/NoneOf.md
@@ -16,6 +16,7 @@ In the sample above, 'foo' isn't a integer nor a float, so noneOf returns true.
 ***
 See also:
 
-  * [Not](Not.md)
   * [AllOf](AllOf.md)
+  * [Not](Not.md)
   * [OneOf](OneOf.md)
+  * [When](When.md)
diff --git a/vendor/respect/validation/docs/rules/NotBlank.md b/vendor/respect/validation/docs/rules/NotBlank.md
index 35a5ef2de273e29918c98c4a743603b026ffd3ca..c90ab1397d4c63ba5c2d089eb7393c55277f7940 100644
--- a/vendor/respect/validation/docs/rules/NotBlank.md
+++ b/vendor/respect/validation/docs/rules/NotBlank.md
@@ -31,4 +31,6 @@ See also:
 
   * [NoWhitespace](NoWhitespace.md)
   * [NotEmpty](NotEmpty.md)
+  * [NotOptional](NotOptional.md)
   * [NullType](NullType.md)
+  * [Optional](Optional.md)
diff --git a/vendor/respect/validation/docs/rules/NotEmpty.md b/vendor/respect/validation/docs/rules/NotEmpty.md
index ab888f6a641664ad296b7de9cb616c4421500f08..aa26ff9f3ce0da4354e58e915f9efe09dcd0ea3e 100644
--- a/vendor/respect/validation/docs/rules/NotEmpty.md
+++ b/vendor/respect/validation/docs/rules/NotEmpty.md
@@ -39,4 +39,7 @@ v::stringType()->notEmpty()->validate("\t \n \r");  //false
 See also:
 
   * [NoWhitespace](NoWhitespace.md)
+  * [NotBlank](NotBlank.md)
+  * [NotOptional](NotOptional.md)
   * [NullType](NullType.md)
+  * [Optional](Optional.md)
diff --git a/vendor/respect/validation/docs/rules/NullType.md b/vendor/respect/validation/docs/rules/NullType.md
index 5b39feb6c2d0eb36a964fc982d2fcd58aa73cea8..ec2b45b65ff36a5ddaaa07ea04d7c1b4656993ee 100644
--- a/vendor/respect/validation/docs/rules/NullType.md
+++ b/vendor/respect/validation/docs/rules/NullType.md
@@ -11,15 +11,17 @@ v::nullType()->validate(null); // true
 ***
 See also:
 
+  * [ArrayType](ArrayType.md)
   * [BoolType](BoolType.md)
+  * [BoolVal](BoolVal.md)
   * [CallableType](CallableType.md)
   * [FloatType](FloatType.md)
   * [IntType](IntType.md)
   * [NotBlank](NotBlank.md)
   * [NotEmpty](NotEmpty.md)
   * [NotOptional](NotOptional.md)
-  * [NullType](NullType.md)
   * [ObjectType](ObjectType.md)
+  * [Optional](Optional.md)
   * [ResourceType](ResourceType.md)
   * [StringType](StringType.md)
   * [Type](Type.md)
diff --git a/vendor/respect/validation/docs/rules/Numeric.md b/vendor/respect/validation/docs/rules/Numeric.md
index d8121fb61c9ae621e4ebe74b45b80853e5c95721..952fa9273e74051b7678d3d1d026d8fc13917fdb 100644
--- a/vendor/respect/validation/docs/rules/Numeric.md
+++ b/vendor/respect/validation/docs/rules/Numeric.md
@@ -13,6 +13,8 @@ v::numeric()->validate('135.0'); // true
 See also:
 
   * [Digit](Digit.md)
+  * [Factor](Factor.md)
   * [Finite](Finite.md)
   * [Infinite](Infinite.md)
+  * [IntType](IntType.md)
   * [IntVal](IntVal.md)
diff --git a/vendor/respect/validation/docs/rules/ObjectType.md b/vendor/respect/validation/docs/rules/ObjectType.md
index 39212603155048570ca891161b495f1f8f41792c..1df033d2752f2d5439f6f1dae999c5522614b7c1 100644
--- a/vendor/respect/validation/docs/rules/ObjectType.md
+++ b/vendor/respect/validation/docs/rules/ObjectType.md
@@ -11,14 +11,15 @@ v::objectType()->validate(new stdClass); // true
 ***
 See also:
 
+  * [ArrayType](ArrayType.md)
   * [Attribute](Attribute.md)
   * [BoolType](BoolType.md)
+  * [BoolVal](BoolVal.md)
   * [CallableType](CallableType.md)
   * [FloatType](FloatType.md)
   * [Instance](Instance.md)
   * [IntType](IntType.md)
   * [NullType](NullType.md)
-  * [ObjectType](ObjectType.md)
   * [ResourceType](ResourceType.md)
   * [StringType](StringType.md)
   * [Type](Type.md)
diff --git a/vendor/respect/validation/docs/rules/PerfectSquare.md b/vendor/respect/validation/docs/rules/PerfectSquare.md
index 3a344b27c9125bd28f0ac6afc1fa8b3d485d372b..d31a6241a47a9382bbf8c2fae626d376344b0d18 100644
--- a/vendor/respect/validation/docs/rules/PerfectSquare.md
+++ b/vendor/respect/validation/docs/rules/PerfectSquare.md
@@ -13,4 +13,5 @@ v::perfectSquare()->validate(9); // true (3*3)
 See also:
 
   * [Factor](Factor.md)
+  * [Fibonacci](Fibonacci.md)
   * [PrimeNumber](PrimeNumber.md)
diff --git a/vendor/respect/validation/docs/rules/Pesel.md b/vendor/respect/validation/docs/rules/Pesel.md
index 275ff7f8d3117304f091e08f9b3424aff30cbf65..7b2d0e1273ddee44cbabf36896adf55568f09ba5 100644
--- a/vendor/respect/validation/docs/rules/Pesel.md
+++ b/vendor/respect/validation/docs/rules/Pesel.md
@@ -10,3 +10,6 @@ v::pesel()->validate('97072704800'); // true
 v::pesel()->validate('97072704801'); // false
 v::pesel()->validate('PESEL123456'); // false
 ```
+See also:
+
+  * [IdentityCard](IdentityCard.md)
diff --git a/vendor/respect/validation/docs/rules/Phone.md b/vendor/respect/validation/docs/rules/Phone.md
index ac3cba9b9582c7192467e65376d4c0e7dd8b0899..b1248c2e2d4fb1ebf4172b6d3ab116019a238861 100644
--- a/vendor/respect/validation/docs/rules/Phone.md
+++ b/vendor/respect/validation/docs/rules/Phone.md
@@ -18,5 +18,6 @@ space or dashed notations) such as:
 See also:
 
   * [Email](Email.md)
+  * [Json](Json.md)
   * [Url](Url.md)
   * [VideoUrl](VideoUrl.md)
diff --git a/vendor/respect/validation/docs/rules/PhpLabel.md b/vendor/respect/validation/docs/rules/PhpLabel.md
index 4295267d72fb63767b02985ce2fd2f4479226e43..aca23007362677bda5287bcc9ef4752dfb2ac7d6 100644
--- a/vendor/respect/validation/docs/rules/PhpLabel.md
+++ b/vendor/respect/validation/docs/rules/PhpLabel.md
@@ -17,8 +17,7 @@ v::phpLabel()->validate('4ccess'); //false
 ***
 See also:
 
+  * [Charset](Charset.md)
   * [Regex](Regex.md)
   * [ResourceType](ResourceType.md)
   * [Slug](Slug.md)
-  * [Charset](Charset.md)
-  
\ No newline at end of file
diff --git a/vendor/respect/validation/docs/rules/PrimeNumber.md b/vendor/respect/validation/docs/rules/PrimeNumber.md
index dee58eabd4c93b89b4e351fd856d9608beeddfa6..7ea4062e73e3d037a7e0d96125e9c303893237bc 100644
--- a/vendor/respect/validation/docs/rules/PrimeNumber.md
+++ b/vendor/respect/validation/docs/rules/PrimeNumber.md
@@ -12,5 +12,6 @@ v::primeNumber()->validate(7); // true
 See also:
 
   * [Factor](Factor.md)
+  * [Fibonacci](Fibonacci.md)
+  * [Multiple](Multiple.md)
   * [PerfectSquare](PerfectSquare.md)
-  * [PrimeNumber](PrimeNumber.md)
diff --git a/vendor/respect/validation/docs/rules/Prnt.md b/vendor/respect/validation/docs/rules/Prnt.md
index 29dc6d76397b0d52e1cb0b8a269d4f4395952913..7ee17a3e300a375955e6cd1b6c5661834a0ec82e 100644
--- a/vendor/respect/validation/docs/rules/Prnt.md
+++ b/vendor/respect/validation/docs/rules/Prnt.md
@@ -12,4 +12,6 @@ v::prnt()->validate('LMKA0$% _123'); // true
 ***
 See also:
 
+  * [Cntrl](Cntrl.md)
   * [Graph](Graph.md)
+  * [Punct](Punct.md)
diff --git a/vendor/respect/validation/docs/rules/Readable.md b/vendor/respect/validation/docs/rules/Readable.md
index 00a074eb9142aa4700965e2bf593d6b3cbd67e3d..9befd559c23c292277f4d388243409279a54c3bf 100644
--- a/vendor/respect/validation/docs/rules/Readable.md
+++ b/vendor/respect/validation/docs/rules/Readable.md
@@ -16,6 +16,7 @@ See also:
   * [Exists](Exists.md)
   * [Extension](Extension.md)
   * [File](File.md)
+  * [Image](Image.md)
   * [Mimetype](Mimetype.md)
   * [Size](Size.md)
   * [SymbolicLink](SymbolicLink.md)
diff --git a/vendor/respect/validation/docs/rules/Regex.md b/vendor/respect/validation/docs/rules/Regex.md
index ed0d2517345e6fcb37c9ad8e68a3d83d98b815ab..72fc33bc45703a2bc0e645468622b6cc19bafb5c 100644
--- a/vendor/respect/validation/docs/rules/Regex.md
+++ b/vendor/respect/validation/docs/rules/Regex.md
@@ -18,4 +18,7 @@ See also:
   * [Contains](Contains.md)
   * [Digit](Digit.md)
   * [EndsWith](EndsWith.md)
+  * [PhpLabel](PhpLabel.md)
+  * [Roman](Roman.md)
   * [StartsWith](StartsWith.md)
+  * [Version](Version.md)
diff --git a/vendor/respect/validation/docs/rules/ResourceType.md b/vendor/respect/validation/docs/rules/ResourceType.md
index c21a2f1d89b7a85c966d8eefdd07e3abe4d4e565..1e376c92ccae3f36aedc4e3fcdef409aba30b759 100644
--- a/vendor/respect/validation/docs/rules/ResourceType.md
+++ b/vendor/respect/validation/docs/rules/ResourceType.md
@@ -11,11 +11,14 @@ v::resourceType()->validate(fopen('/path/to/file.txt', 'w')); // true
 ***
 See also:
 
+  * [ArrayType](ArrayType.md)
   * [BoolType](BoolType.md)
+  * [BoolVal](BoolVal.md)
   * [CallableType](CallableType.md)
   * [FloatType](FloatType.md)
   * [IntType](IntType.md)
   * [NullType](NullType.md)
   * [ObjectType](ObjectType.md)
+  * [PhpLabel](PhpLabel.md)
   * [StringType](StringType.md)
   * [Type](Type.md)
diff --git a/vendor/respect/validation/docs/rules/Roman.md b/vendor/respect/validation/docs/rules/Roman.md
index b619930e1bf61ec67b70c246aa1aaa23bbfafb00..4a2452c20ed87802eac544b1009e6b00f374944a 100644
--- a/vendor/respect/validation/docs/rules/Roman.md
+++ b/vendor/respect/validation/docs/rules/Roman.md
@@ -14,3 +14,4 @@ See also:
   * [In](In.md)
   * [Regex](Regex.md)
   * [Uppercase](Uppercase.md)
+  * [Version](Version.md)
diff --git a/vendor/respect/validation/docs/rules/Size.md b/vendor/respect/validation/docs/rules/Size.md
index 13f5aee4e96aec1c383ef7bed1c78a471aa33f6f..539ac4f2a5592525df85bd82873ddde81eb7eb14 100644
--- a/vendor/respect/validation/docs/rules/Size.md
+++ b/vendor/respect/validation/docs/rules/Size.md
@@ -41,6 +41,7 @@ See also:
   * [Exists](Exists.md)
   * [Extension](Extension.md)
   * [File](File.md)
+  * [Image](Image.md)
   * [Mimetype](Mimetype.md)
   * [Readable](Readable.md)
   * [SymbolicLink](SymbolicLink.md)
diff --git a/vendor/respect/validation/docs/rules/Slug.md b/vendor/respect/validation/docs/rules/Slug.md
index 599bbbaac904fdef72ddcf7fc753511aa67fc8a7..d0dfd61fbb39ddba699e3d7aa237e0ac7dfe99f4 100644
--- a/vendor/respect/validation/docs/rules/Slug.md
+++ b/vendor/respect/validation/docs/rules/Slug.md
@@ -13,5 +13,6 @@ v::slug()->validate('my-wordpress-title-'); // false
 ***
 See also:
 
+  * [PhpLabel](PhpLabel.md)
   * [Url](Url.md)
   * [VideoUrl](VideoUrl.md)
diff --git a/vendor/respect/validation/docs/rules/StartsWith.md b/vendor/respect/validation/docs/rules/StartsWith.md
index 842655d94b25b1460254e12d1d4618032cf77d5c..072795f6b852d14cd4e02983b792aa3a86e3f161 100644
--- a/vendor/respect/validation/docs/rules/StartsWith.md
+++ b/vendor/respect/validation/docs/rules/StartsWith.md
@@ -26,6 +26,7 @@ Message template for this validator includes `{{startValue}}`.
 ***
 See also:
 
-  * [EndsWith](EndsWith.md)
   * [Contains](Contains.md)
+  * [EndsWith](EndsWith.md)
   * [In](In.md)
+  * [Regex](Regex.md)
diff --git a/vendor/respect/validation/docs/rules/StringType.md b/vendor/respect/validation/docs/rules/StringType.md
index 624c3df8cfbe16b0774d69203d9d5d32a5c12f03..a6444522dc73e19ab6b56e47f70d87acfd93e93f 100644
--- a/vendor/respect/validation/docs/rules/StringType.md
+++ b/vendor/respect/validation/docs/rules/StringType.md
@@ -12,7 +12,9 @@ v::stringType()->validate('hi'); // true
 See also:
 
   * [Alnum](Alnum.md)
+  * [ArrayType](ArrayType.md)
   * [BoolType](BoolType.md)
+  * [BoolVal](BoolVal.md)
   * [CallableType](CallableType.md)
   * [FloatType](FloatType.md)
   * [IntType](IntType.md)
diff --git a/vendor/respect/validation/docs/rules/SubdivisionCode.md b/vendor/respect/validation/docs/rules/SubdivisionCode.md
index 3cb031922eff171dcac07b05827f9420049fa83c..062c7d894d5de2cc94181915b93320de389aef1f 100644
--- a/vendor/respect/validation/docs/rules/SubdivisionCode.md
+++ b/vendor/respect/validation/docs/rules/SubdivisionCode.md
@@ -11,274 +11,17 @@ v::subdivisionCode('BR')->validate('SP'); // true
 v::subdivisionCode('US')->validate('CA'); // true
 ```
 
-This rule is case sensitive.
-
-## Available country codes
-
-- `AD`: Andorra
-- `AE`: United Arab Emirates
-- `AF`: Afghanistan
-- `AG`: Antigua and Barbuda
-- `AI`: Anguilla
-- `AL`: Albania
-- `AM`: Armenia
-- `AN`: AN.html
-- `AO`: Angola
-- `AQ`: Antarctica
-- `AR`: Argentina
-- `AS`: American Samoa
-- `AT`: Austria
-- `AU`: Australia
-- `AW`: Aruba
-- `AX`: Ã…land
-- `AZ`: Azerbaijan
-- `BA`: Bosnia and Herzegovina
-- `BB`: Barbados
-- `BD`: Bangladesh
-- `BE`: Belgium
-- `BF`: Burkina Faso
-- `BG`: Bulgaria
-- `BH`: Bahrain
-- `BI`: Burundi
-- `BJ`: Benin
-- `BL`: Saint Barthélemy
-- `BM`: Bermuda
-- `BN`: Brunei
-- `BO`: Bolivia
-- `BQ`: Bonaire
-- `BR`: Brazil
-- `BS`: Bahamas
-- `BT`: Bhutan
-- `BV`: Bouvet Island
-- `BW`: Botswana
-- `BY`: Belarus
-- `BZ`: Belize
-- `CA`: Canada
-- `CC`: Cocos [Keeling] Islands
-- `CD`: Democratic Republic of the Congo
-- `CF`: Central African Republic
-- `CG`: Republic of the Congo
-- `CH`: Switzerland
-- `CI`: Ivory Coast
-- `CK`: Cook Islands
-- `CL`: Chile
-- `CM`: Cameroon
-- `CN`: China
-- `CO`: Colombia
-- `CR`: Costa Rica
-- `CS`: CS.html
-- `CU`: Cuba
-- `CV`: Cape Verde
-- `CW`: Curacao
-- `CX`: Christmas Island
-- `CY`: Cyprus
-- `CZ`: Czech Republic
-- `DE`: Germany
-- `DJ`: Djibouti
-- `DK`: Denmark
-- `DM`: Dominica
-- `DO`: Dominican Republic
-- `DZ`: Algeria
-- `EC`: Ecuador
-- `EE`: Estonia
-- `EG`: Egypt
-- `EH`: Western Sahara
-- `ER`: Eritrea
-- `ES`: Spain
-- `ET`: Ethiopia
-- `FI`: Finland
-- `FJ`: Fiji
-- `FK`: Falkland Islands
-- `FM`: Micronesia
-- `FO`: Faroe Islands
-- `FR`: France
-- `GA`: Gabon
-- `GB`: United Kingdom
-- `GD`: Grenada
-- `GE`: Georgia
-- `GF`: French Guiana
-- `GG`: Guernsey
-- `GH`: Ghana
-- `GI`: Gibraltar
-- `GL`: Greenland
-- `GM`: Gambia
-- `GN`: Guinea
-- `GP`: Guadeloupe
-- `GQ`: Equatorial Guinea
-- `GR`: Greece
-- `GS`: South Georgia and the South Sandwich Islands
-- `GT`: Guatemala
-- `GU`: Guam
-- `GW`: Guinea-Bissau
-- `GY`: Guyana
-- `HK`: Hong Kong
-- `HM`: Heard Island and McDonald Islands
-- `HN`: Honduras
-- `HR`: Croatia
-- `HT`: Haiti
-- `HU`: Hungary
-- `ID`: Indonesia
-- `IE`: Ireland
-- `IL`: Israel
-- `IM`: Isle of Man
-- `IN`: India
-- `IO`: British Indian Ocean Territory
-- `IQ`: Iraq
-- `IR`: Iran
-- `IS`: Iceland
-- `IT`: Italy
-- `JE`: Jersey
-- `JM`: Jamaica
-- `JO`: Jordan
-- `JP`: Japan
-- `KE`: Kenya
-- `KG`: Kyrgyzstan
-- `KH`: Cambodia
-- `KI`: Kiribati
-- `KM`: Comoros
-- `KN`: Saint Kitts and Nevis
-- `KP`: North Korea
-- `KR`: South Korea
-- `KW`: Kuwait
-- `KY`: Cayman Islands
-- `KZ`: Kazakhstan
-- `LA`: Laos
-- `LB`: Lebanon
-- `LC`: Saint Lucia
-- `LI`: Liechtenstein
-- `LK`: Sri Lanka
-- `LR`: Liberia
-- `LS`: Lesotho
-- `LT`: Lithuania
-- `LU`: Luxembourg
-- `LV`: Latvia
-- `LY`: Libya
-- `MA`: Morocco
-- `MC`: Monaco
-- `MD`: Moldova
-- `ME`: Montenegro
-- `MF`: Saint Martin
-- `MG`: Madagascar
-- `MH`: Marshall Islands
-- `MK`: Macedonia
-- `ML`: Mali
-- `MM`: Myanmar [Burma]
-- `MN`: Mongolia
-- `MO`: Macao
-- `MP`: Northern Mariana Islands
-- `MQ`: Martinique
-- `MR`: Mauritania
-- `MS`: Montserrat
-- `MT`: Malta
-- `MU`: Mauritius
-- `MV`: Maldives
-- `MW`: Malawi
-- `MX`: Mexico
-- `MY`: Malaysia
-- `MZ`: Mozambique
-- `NA`: Namibia
-- `NC`: New Caledonia
-- `NE`: Niger
-- `NF`: Norfolk Island
-- `NG`: Nigeria
-- `NI`: Nicaragua
-- `NL`: Netherlands
-- `NO`: Norway
-- `NP`: Nepal
-- `NR`: Nauru
-- `NU`: Niue
-- `NZ`: New Zealand
-- `OM`: Oman
-- `PA`: Panama
-- `PE`: Peru
-- `PF`: French Polynesia
-- `PG`: Papua New Guinea
-- `PH`: Philippines
-- `PK`: Pakistan
-- `PL`: Poland
-- `PM`: Saint Pierre and Miquelon
-- `PN`: Pitcairn Islands
-- `PR`: Puerto Rico
-- `PS`: Palestine
-- `PT`: Portugal
-- `PW`: Palau
-- `PY`: Paraguay
-- `QA`: Qatar
-- `RE`: Réunion
-- `RO`: Romania
-- `RS`: Serbia
-- `RU`: Russia
-- `RW`: Rwanda
-- `SA`: Saudi Arabia
-- `SB`: Solomon Islands
-- `SC`: Seychelles
-- `SD`: Sudan
-- `SE`: Sweden
-- `SG`: Singapore
-- `SH`: Saint Helena
-- `SI`: Slovenia
-- `SJ`: Svalbard and Jan Mayen
-- `SK`: Slovakia
-- `SL`: Sierra Leone
-- `SM`: San Marino
-- `SN`: Senegal
-- `SO`: Somalia
-- `SR`: Suriname
-- `SS`: South Sudan
-- `ST`: São Tomé and Príncipe
-- `SV`: El Salvador
-- `SX`: Sint Maarten
-- `SY`: Syria
-- `SZ`: Swaziland
-- `TC`: Turks and Caicos Islands
-- `TD`: Chad
-- `TF`: French Southern Territories
-- `TG`: Togo
-- `TH`: Thailand
-- `TJ`: Tajikistan
-- `TK`: Tokelau
-- `TL`: East Timor
-- `TM`: Turkmenistan
-- `TN`: Tunisia
-- `TO`: Tonga
-- `TR`: Turkey
-- `TT`: Trinidad and Tobago
-- `TV`: Tuvalu
-- `TW`: Taiwan
-- `TZ`: Tanzania
-- `UA`: Ukraine
-- `UG`: Uganda
-- `UM`: U.S. Minor Outlying Islands
-- `US`: United States
-- `UY`: Uruguay
-- `UZ`: Uzbekistan
-- `VA`: Vatican City
-- `VC`: Saint Vincent and the Grenadines
-- `VE`: Venezuela
-- `VG`: British Virgin Islands
-- `VI`: U.S. Virgin Islands
-- `VN`: Vietnam
-- `VU`: Vanuatu
-- `WF`: Wallis and Futuna
-- `WS`: Samoa
-- `XK`: Kosovo
-- `YE`: Yemen
-- `YT`: Mayotte
-- `ZA`: South Africa
-- `ZM`: Zambia
-- `ZW`: Zimbabwe
-
-All data was extrated from [GeoNames][] which is licensed under a
-[Creative Commons Attribution 3.0 License][].
+This rules uses data from [iso-codes][].
 
 ***
 See also:
 
   * [CountryCode](CountryCode.md)
+  * [CurrencyCode](CurrencyCode.md)
+  * [IdentityCard](IdentityCard.md)
+  * [KeyValue](KeyValue.md)
   * [Tld](Tld.md)
 
-
-[Creative Commons Attribution 3.0 License]: http://creativecommons.org/licenses/by/3.0 "Creative Commons Attribution 3.0 License"
-[GeoNames]: http://www.geonames.org "GetNames"
+[iso-codes]: https://salsa.debian.org/iso-codes-team/iso-codes
 [ISO 3166-1 alpha-2]: http://en.wikipedia.org/wiki/ISO_3166-1_alpha-2 "ISO 3166-1 alpha-2"
 [ISO 3166-2]: http://en.wikipedia.org/wiki/ISO_3166-2 "ISO 3166-2"
diff --git a/vendor/respect/validation/docs/rules/SymbolicLink.md b/vendor/respect/validation/docs/rules/SymbolicLink.md
index bc9019657bc68072e439020da43c0169169eab43..c1284e5e1c2e49413554accc498dd170d0be4185 100644
--- a/vendor/respect/validation/docs/rules/SymbolicLink.md
+++ b/vendor/respect/validation/docs/rules/SymbolicLink.md
@@ -16,6 +16,7 @@ See also:
   * [Exists](Exists.md)
   * [Extension](Extension.md)
   * [File](File.md)
+  * [Image](Image.md)
   * [Mimetype](Mimetype.md)
   * [Readable](Readable.md)
   * [Size](Size.md)
diff --git a/vendor/respect/validation/docs/rules/Tld.md b/vendor/respect/validation/docs/rules/Tld.md
index db05452a196958e19b794707740c69487c99d5a2..05fdc910b63512b8b42fa6b58e9f4f73bd63ffbe 100644
--- a/vendor/respect/validation/docs/rules/Tld.md
+++ b/vendor/respect/validation/docs/rules/Tld.md
@@ -13,5 +13,8 @@ v::tld()->validate('org'); // true
 ***
 See also:
 
- * [Domain](Domain.md)
- * [CountryCode](CountryCode.md)
+  * [CountryCode](CountryCode.md)
+  * [Domain](Domain.md)
+  * [Ip](Ip.md)
+  * [MacAddress](MacAddress.md)
+  * [SubdivisionCode](SubdivisionCode.md)
diff --git a/vendor/respect/validation/docs/rules/TrueVal.md b/vendor/respect/validation/docs/rules/TrueVal.md
index 59869d200419e5db273de2f4fa7c6bb30847dbd7..1329873ac55ceebe0cbbc04cdce519d7d18fe85e 100644
--- a/vendor/respect/validation/docs/rules/TrueVal.md
+++ b/vendor/respect/validation/docs/rules/TrueVal.md
@@ -18,4 +18,6 @@ v::trueVal()->validate('2'); // false
 ***
 See also:
 
+  * [BoolType](BoolType.md)
+  * [BoolVal](BoolVal.md)
   * [FalseVal](FalseVal.md)
diff --git a/vendor/respect/validation/docs/rules/Type.md b/vendor/respect/validation/docs/rules/Type.md
index 50f2abb9f9a75a2e1fa087a69b38274ad45d8631..8d7635fa0f674db19bc08982a4f734e082290434 100644
--- a/vendor/respect/validation/docs/rules/Type.md
+++ b/vendor/respect/validation/docs/rules/Type.md
@@ -13,8 +13,10 @@ v::type('object')->validate(new stdClass()); // true
 ***
 See also:
 
+  * [ArrayType](ArrayType.md)
   * [ArrayVal](ArrayVal.md)
   * [BoolType](BoolType.md)
+  * [BoolVal](BoolVal.md)
   * [CallableType](CallableType.md)
   * [Finite](Finite.md)
   * [FloatType](FloatType.md)
@@ -28,4 +30,3 @@ See also:
   * [ResourceType](ResourceType.md)
   * [ScalarVal](ScalarVal.md)
   * [StringType](StringType.md)
-  * [Type](Type.md)
diff --git a/vendor/respect/validation/docs/rules/Uploaded.md b/vendor/respect/validation/docs/rules/Uploaded.md
index 774f9bb8216835034c4fa9c02263dfe2c9f898f5..9d4f9bf72e31ddb82fddc235d6d9f26ec3b9abef 100644
--- a/vendor/respect/validation/docs/rules/Uploaded.md
+++ b/vendor/respect/validation/docs/rules/Uploaded.md
@@ -16,6 +16,7 @@ See also:
   * [Exists](Exists.md)
   * [Extension](Extension.md)
   * [File](File.md)
+  * [Image](Image.md)
   * [Mimetype](Mimetype.md)
   * [Readable](Readable.md)
   * [Size](Size.md)
diff --git a/vendor/respect/validation/docs/rules/Uppercase.md b/vendor/respect/validation/docs/rules/Uppercase.md
index 1dff7acf584a5ee43724526f6ff729879521ef2e..4334e10ecc4a37f0ada73e7a8e2c084048d35e56 100644
--- a/vendor/respect/validation/docs/rules/Uppercase.md
+++ b/vendor/respect/validation/docs/rules/Uppercase.md
@@ -12,3 +12,4 @@ v::stringType()->uppercase()->validate('W3C'); // true
 See also:
 
   * [Lowercase](Lowercase.md)
+  * [Roman](Roman.md)
diff --git a/vendor/respect/validation/docs/rules/Url.md b/vendor/respect/validation/docs/rules/Url.md
index 5638cf55f4b364edceea324d80904c3f87ce3178..7a1850f878809a169e9f1fde0d65381475f49211 100644
--- a/vendor/respect/validation/docs/rules/Url.md
+++ b/vendor/respect/validation/docs/rules/Url.md
@@ -21,4 +21,5 @@ See also:
   * [Email](Email.md)
   * [FilterVar](FilterVar.md)
   * [Phone](Phone.md)
+  * [Slug](Slug.md)
   * [VideoUrl](VideoUrl.md)
diff --git a/vendor/respect/validation/docs/rules/VideoUrl.md b/vendor/respect/validation/docs/rules/VideoUrl.md
index 1ef962793bdc6082f57ad70d42f059a06095ca5a..544aceb861cbca476ccf77c918122f9d890ece1e 100644
--- a/vendor/respect/validation/docs/rules/VideoUrl.md
+++ b/vendor/respect/validation/docs/rules/VideoUrl.md
@@ -32,4 +32,8 @@ Message template for this validator includes `{{service}}`.
 ***
 See also:
 
+  * [Email](Email.md)
+  * [Json](Json.md)
+  * [Phone](Phone.md)
+  * [Slug](Slug.md)
   * [Url](Url.md)
diff --git a/vendor/respect/validation/docs/rules/Vowel.md b/vendor/respect/validation/docs/rules/Vowel.md
index 98d806f5d90b39658d61d9e69dec3d86b5330e2f..ddbff351d0b9edf1c61b46d770509e60a4e367cd 100644
--- a/vendor/respect/validation/docs/rules/Vowel.md
+++ b/vendor/respect/validation/docs/rules/Vowel.md
@@ -12,6 +12,6 @@ v::vowel()->validate('aei'); // true
 See also:
 
   * [Alnum](Alnum.md)
-  * [Digit](Digit.md)
   * [Alpha](Alpha.md)
   * [Consonant](Consonant.md)
+  * [Digit](Digit.md)
diff --git a/vendor/respect/validation/docs/rules/When.md b/vendor/respect/validation/docs/rules/When.md
index 6254cb34d991733bd29c9b2281bad838f362a24e..12e6a262d43eb004e9fe2d6b8f7968ef9576c67a 100644
--- a/vendor/respect/validation/docs/rules/When.md
+++ b/vendor/respect/validation/docs/rules/When.md
@@ -20,5 +20,6 @@ When `$else` is not defined use [AlwaysInvalid](AlwaysInvalid.md)
 See also:
 
   * [AllOf](AllOf.md)
-  * [OneOf](OneOf.md)
+  * [AlwaysInvalid](AlwaysInvalid.md)
   * [NoneOf](NoneOf.md)
+  * [OneOf](OneOf.md)
diff --git a/vendor/respect/validation/docs/rules/Writable.md b/vendor/respect/validation/docs/rules/Writable.md
index b7aa5e436534c6fee4bdf42b5fdafefc7494b08f..a3def6c05728d9ed0a4cad87d9d5f278f2ca37b9 100644
--- a/vendor/respect/validation/docs/rules/Writable.md
+++ b/vendor/respect/validation/docs/rules/Writable.md
@@ -16,6 +16,7 @@ See also:
   * [Exists](Exists.md)
   * [Extension](Extension.md)
   * [File](File.md)
+  * [Image](Image.md)
   * [Mimetype](Mimetype.md)
   * [Readable](Readable.md)
   * [Size](Size.md)
diff --git a/vendor/respect/validation/docs/rules/Xdigit.md b/vendor/respect/validation/docs/rules/Xdigit.md
index 9e79d0fdfc6b52ac263f8748ce5dc03c778c9c81..9fda7fe7d0bb8592ee3d399c258eec48114f7d92 100644
--- a/vendor/respect/validation/docs/rules/Xdigit.md
+++ b/vendor/respect/validation/docs/rules/Xdigit.md
@@ -17,6 +17,6 @@ v::xdigit()->validate('0x1f'); // false
 ***
 See also:
 
-  * [Digit](Digit.md)
   * [Alnum](Alnum.md)
+  * [Digit](Digit.md)
   * [HexRgbColor](HexRgbColor.md)
diff --git a/vendor/respect/validation/docs/rules/Yes.md b/vendor/respect/validation/docs/rules/Yes.md
index 9fef6d8f4d6b0e02e6b9dab619c39451b9f83db6..11bf814ac56e72bff7af3cec8049834349a23068 100644
--- a/vendor/respect/validation/docs/rules/Yes.md
+++ b/vendor/respect/validation/docs/rules/Yes.md
@@ -20,4 +20,6 @@ If `$locale` is TRUE, uses the value of [nl_langinfo()](http://php.net/nl_langin
 ***
 See also:
 
+  * [BoolType](BoolType.md)
+  * [BoolVal](BoolVal.md)
   * [No](No.md)
diff --git a/vendor/respect/validation/library/Rules/CountryCode.php b/vendor/respect/validation/library/Rules/CountryCode.php
index 91dbfd284cb4cc49bfe86f396b1122ba7fc6cc52..e8fa6fe1fd17c7e736ba589e4a3972100c842e41 100644
--- a/vendor/respect/validation/library/Rules/CountryCode.php
+++ b/vendor/respect/validation/library/Rules/CountryCode.php
@@ -23,7 +23,7 @@ class CountryCode extends AbstractRule
     const NUMERIC = 'numeric';
 
     /**
-     * @link http://download.geonames.org/export/dump/countryInfo.txt
+     * @link https://salsa.debian.org/iso-codes-team/iso-codes
      *
      * @var array
      */
@@ -32,6 +32,7 @@ class CountryCode extends AbstractRule
         ['AE', 'ARE', '784'], // United Arab Emirates
         ['AF', 'AFG', '004'], // Afghanistan
         ['AG', 'ATG', '028'], // Antigua and Barbuda
+        ['AI', 'AFI', '262'], // French Afars and Issas
         ['AI', 'AIA', '660'], // Anguilla
         ['AL', 'ALB', '008'], // Albania
         ['AM', 'ARM', '051'], // Armenia
@@ -43,7 +44,7 @@ class CountryCode extends AbstractRule
         ['AT', 'AUT', '040'], // Austria
         ['AU', 'AUS', '036'], // Australia
         ['AW', 'ABW', '533'], // Aruba
-        ['AX', 'ALA', '248'], // Aland Islands
+        ['AX', 'ALA', '248'], // Ã…land Islands
         ['AZ', 'AZE', '031'], // Azerbaijan
         ['BA', 'BIH', '070'], // Bosnia and Herzegovina
         ['BB', 'BRB', '052'], // Barbados
@@ -54,43 +55,50 @@ class CountryCode extends AbstractRule
         ['BH', 'BHR', '048'], // Bahrain
         ['BI', 'BDI', '108'], // Burundi
         ['BJ', 'BEN', '204'], // Benin
-        ['BL', 'BLM', '652'], // Saint Barthelemy
+        ['BL', 'BLM', '652'], // Saint Barthélemy
         ['BM', 'BMU', '060'], // Bermuda
-        ['BN', 'BRN', '096'], // Brunei
-        ['BO', 'BOL', '068'], // Bolivia
-        ['BQ', 'BES', '535'], // Bonaire, Saint Eustatius and Saba
+        ['BN', 'BRN', '096'], // Brunei Darussalam
+        ['BO', 'BOL', '068'], // Bolivia, Plurinational State of
+        ['BQ', 'ATB', null], // British Antarctic Territory
+        ['BQ', 'BES', '535'], // Bonaire, Sint Eustatius and Saba
         ['BR', 'BRA', '076'], // Brazil
         ['BS', 'BHS', '044'], // Bahamas
         ['BT', 'BTN', '064'], // Bhutan
+        ['BU', 'BUR', '104'], // Burma, Socialist Republic of the Union of
         ['BV', 'BVT', '074'], // Bouvet Island
         ['BW', 'BWA', '072'], // Botswana
         ['BY', 'BLR', '112'], // Belarus
+        ['BY', 'BYS', '112'], // Byelorussian SSR Soviet Socialist Republic
         ['BZ', 'BLZ', '084'], // Belize
         ['CA', 'CAN', '124'], // Canada
-        ['CC', 'CCK', '166'], // Cocos Islands
-        ['CD', 'COD', '180'], // Democratic Republic of the Congo
+        ['CC', 'CCK', '166'], // Cocos (Keeling) Islands
+        ['CD', 'COD', '180'], // Congo, The Democratic Republic of the
         ['CF', 'CAF', '140'], // Central African Republic
-        ['CG', 'COG', '178'], // Republic of the Congo
+        ['CG', 'COG', '178'], // Congo
         ['CH', 'CHE', '756'], // Switzerland
-        ['CI', 'CIV', '384'], // Ivory Coast
+        ['CI', 'CIV', '384'], // Côte d'Ivoire
         ['CK', 'COK', '184'], // Cook Islands
         ['CL', 'CHL', '152'], // Chile
         ['CM', 'CMR', '120'], // Cameroon
         ['CN', 'CHN', '156'], // China
         ['CO', 'COL', '170'], // Colombia
         ['CR', 'CRI', '188'], // Costa Rica
+        ['CS', 'CSK', '200'], // Czechoslovakia, Czechoslovak Socialist Republic
         ['CS', 'SCG', '891'], // Serbia and Montenegro
+        ['CT', 'CTE', '128'], // Canton and Enderbury Islands
         ['CU', 'CUB', '192'], // Cuba
-        ['CV', 'CPV', '132'], // Cape Verde
-        ['CW', 'CUW', '531'], // Curacao
+        ['CV', 'CPV', '132'], // Cabo Verde
+        ['CW', 'CUW', '531'], // Curaçao
         ['CX', 'CXR', '162'], // Christmas Island
         ['CY', 'CYP', '196'], // Cyprus
-        ['CZ', 'CZE', '203'], // Czech Republic
+        ['CZ', 'CZE', '203'], // Czechia
+        ['DD', 'DDR', '278'], // German Democratic Republic
         ['DE', 'DEU', '276'], // Germany
         ['DJ', 'DJI', '262'], // Djibouti
         ['DK', 'DNK', '208'], // Denmark
         ['DM', 'DMA', '212'], // Dominica
         ['DO', 'DOM', '214'], // Dominican Republic
+        ['DY', 'DHY', '204'], // Dahomey
         ['DZ', 'DZA', '012'], // Algeria
         ['EC', 'ECU', '218'], // Ecuador
         ['EE', 'EST', '233'], // Estonia
@@ -101,13 +109,16 @@ class CountryCode extends AbstractRule
         ['ET', 'ETH', '231'], // Ethiopia
         ['FI', 'FIN', '246'], // Finland
         ['FJ', 'FJI', '242'], // Fiji
-        ['FK', 'FLK', '238'], // Falkland Islands
-        ['FM', 'FSM', '583'], // Micronesia
+        ['FK', 'FLK', '238'], // Falkland Islands (Malvinas)
+        ['FM', 'FSM', '583'], // Micronesia, Federated States of
         ['FO', 'FRO', '234'], // Faroe Islands
+        ['FQ', 'ATF', null], // French Southern and Antarctic Territories
         ['FR', 'FRA', '250'], // France
+        ['FX', 'FXX', '249'], // France, Metropolitan
         ['GA', 'GAB', '266'], // Gabon
         ['GB', 'GBR', '826'], // United Kingdom
         ['GD', 'GRD', '308'], // Grenada
+        ['GE', 'GEL', '296'], // Gilbert and Ellice Islands
         ['GE', 'GEO', '268'], // Georgia
         ['GF', 'GUF', '254'], // French Guiana
         ['GG', 'GGY', '831'], // Guernsey
@@ -130,6 +141,7 @@ class CountryCode extends AbstractRule
         ['HR', 'HRV', '191'], // Croatia
         ['HT', 'HTI', '332'], // Haiti
         ['HU', 'HUN', '348'], // Hungary
+        ['HV', 'HVO', '854'], // Upper Volta, Republic of
         ['ID', 'IDN', '360'], // Indonesia
         ['IE', 'IRL', '372'], // Ireland
         ['IL', 'ISR', '376'], // Israel
@@ -137,25 +149,26 @@ class CountryCode extends AbstractRule
         ['IN', 'IND', '356'], // India
         ['IO', 'IOT', '086'], // British Indian Ocean Territory
         ['IQ', 'IRQ', '368'], // Iraq
-        ['IR', 'IRN', '364'], // Iran
+        ['IR', 'IRN', '364'], // Iran, Islamic Republic of
         ['IS', 'ISL', '352'], // Iceland
         ['IT', 'ITA', '380'], // Italy
         ['JE', 'JEY', '832'], // Jersey
         ['JM', 'JAM', '388'], // Jamaica
         ['JO', 'JOR', '400'], // Jordan
         ['JP', 'JPN', '392'], // Japan
+        ['JT', 'JTN', '396'], // Johnston Island
         ['KE', 'KEN', '404'], // Kenya
         ['KG', 'KGZ', '417'], // Kyrgyzstan
         ['KH', 'KHM', '116'], // Cambodia
         ['KI', 'KIR', '296'], // Kiribati
         ['KM', 'COM', '174'], // Comoros
         ['KN', 'KNA', '659'], // Saint Kitts and Nevis
-        ['KP', 'PRK', '408'], // North Korea
-        ['KR', 'KOR', '410'], // South Korea
+        ['KP', 'PRK', '408'], // Korea, Democratic People's Republic of
+        ['KR', 'KOR', '410'], // Korea, Republic of
         ['KW', 'KWT', '414'], // Kuwait
         ['KY', 'CYM', '136'], // Cayman Islands
         ['KZ', 'KAZ', '398'], // Kazakhstan
-        ['LA', 'LAO', '418'], // Laos
+        ['LA', 'LAO', '418'], // Lao People's Democratic Republic
         ['LB', 'LBN', '422'], // Lebanon
         ['LC', 'LCA', '662'], // Saint Lucia
         ['LI', 'LIE', '438'], // Liechtenstein
@@ -168,12 +181,13 @@ class CountryCode extends AbstractRule
         ['LY', 'LBY', '434'], // Libya
         ['MA', 'MAR', '504'], // Morocco
         ['MC', 'MCO', '492'], // Monaco
-        ['MD', 'MDA', '498'], // Moldova
+        ['MD', 'MDA', '498'], // Moldova, Republic of
         ['ME', 'MNE', '499'], // Montenegro
-        ['MF', 'MAF', '663'], // Saint Martin
+        ['MF', 'MAF', '663'], // Saint Martin (French part)
         ['MG', 'MDG', '450'], // Madagascar
         ['MH', 'MHL', '584'], // Marshall Islands
-        ['MK', 'MKD', '807'], // Macedonia
+        ['MI', 'MID', '488'], // Midway Islands
+        ['MK', 'MKD', '807'], // North Macedonia
         ['ML', 'MLI', '466'], // Mali
         ['MM', 'MMR', '104'], // Myanmar
         ['MN', 'MNG', '496'], // Mongolia
@@ -194,15 +208,19 @@ class CountryCode extends AbstractRule
         ['NE', 'NER', '562'], // Niger
         ['NF', 'NFK', '574'], // Norfolk Island
         ['NG', 'NGA', '566'], // Nigeria
+        ['NH', 'NHB', '548'], // New Hebrides
         ['NI', 'NIC', '558'], // Nicaragua
         ['NL', 'NLD', '528'], // Netherlands
         ['NO', 'NOR', '578'], // Norway
         ['NP', 'NPL', '524'], // Nepal
+        ['NQ', 'ATN', '216'], // Dronning Maud Land
         ['NR', 'NRU', '520'], // Nauru
+        ['NT', 'NTZ', '536'], // Neutral Zone
         ['NU', 'NIU', '570'], // Niue
         ['NZ', 'NZL', '554'], // New Zealand
         ['OM', 'OMN', '512'], // Oman
         ['PA', 'PAN', '591'], // Panama
+        ['PC', 'PCI', '582'], // Pacific Islands (trust territory)
         ['PE', 'PER', '604'], // Peru
         ['PF', 'PYF', '258'], // French Polynesia
         ['PG', 'PNG', '598'], // Papua New Guinea
@@ -212,15 +230,18 @@ class CountryCode extends AbstractRule
         ['PM', 'SPM', '666'], // Saint Pierre and Miquelon
         ['PN', 'PCN', '612'], // Pitcairn
         ['PR', 'PRI', '630'], // Puerto Rico
-        ['PS', 'PSE', '275'], // Palestinian Territory
+        ['PS', 'PSE', '275'], // Palestine, State of
         ['PT', 'PRT', '620'], // Portugal
+        ['PU', 'PUS', '849'], // US Miscellaneous Pacific Islands
         ['PW', 'PLW', '585'], // Palau
         ['PY', 'PRY', '600'], // Paraguay
+        ['PZ', 'PCZ', null], // Panama Canal Zone
         ['QA', 'QAT', '634'], // Qatar
-        ['RE', 'REU', '638'], // Reunion
+        ['RE', 'REU', '638'], // Réunion
+        ['RH', 'RHO', '716'], // Southern Rhodesia
         ['RO', 'ROU', '642'], // Romania
         ['RS', 'SRB', '688'], // Serbia
-        ['RU', 'RUS', '643'], // Russia
+        ['RU', 'RUS', '643'], // Russian Federation
         ['RW', 'RWA', '646'], // Rwanda
         ['SA', 'SAU', '682'], // Saudi Arabia
         ['SB', 'SLB', '090'], // Solomon Islands
@@ -228,9 +249,10 @@ class CountryCode extends AbstractRule
         ['SD', 'SDN', '729'], // Sudan
         ['SE', 'SWE', '752'], // Sweden
         ['SG', 'SGP', '702'], // Singapore
-        ['SH', 'SHN', '654'], // Saint Helena
+        ['SH', 'SHN', '654'], // Saint Helena, Ascension and Tristan da Cunha
         ['SI', 'SVN', '705'], // Slovenia
         ['SJ', 'SJM', '744'], // Svalbard and Jan Mayen
+        ['SK', 'SKM', null], // Sikkim
         ['SK', 'SVK', '703'], // Slovakia
         ['SL', 'SLE', '694'], // Sierra Leone
         ['SM', 'SMR', '674'], // San Marino
@@ -239,10 +261,11 @@ class CountryCode extends AbstractRule
         ['SR', 'SUR', '740'], // Suriname
         ['SS', 'SSD', '728'], // South Sudan
         ['ST', 'STP', '678'], // Sao Tome and Principe
+        ['SU', 'SUN', '810'], // USSR, Union of Soviet Socialist Republics
         ['SV', 'SLV', '222'], // El Salvador
-        ['SX', 'SXM', '534'], // Sint Maarten
-        ['SY', 'SYR', '760'], // Syria
-        ['SZ', 'SWZ', '748'], // Swaziland
+        ['SX', 'SXM', '534'], // Sint Maarten (Dutch part)
+        ['SY', 'SYR', '760'], // Syrian Arab Republic
+        ['SZ', 'SWZ', '748'], // Eswatini
         ['TC', 'TCA', '796'], // Turks and Caicos Islands
         ['TD', 'TCD', '148'], // Chad
         ['TF', 'ATF', '260'], // French Southern Territories
@@ -250,37 +273,41 @@ class CountryCode extends AbstractRule
         ['TH', 'THA', '764'], // Thailand
         ['TJ', 'TJK', '762'], // Tajikistan
         ['TK', 'TKL', '772'], // Tokelau
-        ['TL', 'TLS', '626'], // East Timor
+        ['TL', 'TLS', '626'], // Timor-Leste
         ['TM', 'TKM', '795'], // Turkmenistan
         ['TN', 'TUN', '788'], // Tunisia
         ['TO', 'TON', '776'], // Tonga
+        ['TP', 'TMP', '626'], // East Timor
         ['TR', 'TUR', '792'], // Turkey
         ['TT', 'TTO', '780'], // Trinidad and Tobago
         ['TV', 'TUV', '798'], // Tuvalu
-        ['TW', 'TWN', '158'], // Taiwan
-        ['TZ', 'TZA', '834'], // Tanzania
+        ['TW', 'TWN', '158'], // Taiwan, Province of China
+        ['TZ', 'TZA', '834'], // Tanzania, United Republic of
         ['UA', 'UKR', '804'], // Ukraine
         ['UG', 'UGA', '800'], // Uganda
         ['UM', 'UMI', '581'], // United States Minor Outlying Islands
         ['US', 'USA', '840'], // United States
         ['UY', 'URY', '858'], // Uruguay
         ['UZ', 'UZB', '860'], // Uzbekistan
-        ['VA', 'VAT', '336'], // Vatican
+        ['VA', 'VAT', '336'], // Holy See (Vatican City State)
         ['VC', 'VCT', '670'], // Saint Vincent and the Grenadines
-        ['VE', 'VEN', '862'], // Venezuela
-        ['VG', 'VGB', '092'], // British Virgin Islands
-        ['VI', 'VIR', '850'], // U.S. Virgin Islands
-        ['VN', 'VNM', '704'], // Vietnam
+        ['VD', 'VDR', null], // Viet-Nam, Democratic Republic of
+        ['VE', 'VEN', '862'], // Venezuela, Bolivarian Republic of
+        ['VG', 'VGB', '092'], // Virgin Islands, British
+        ['VI', 'VIR', '850'], // Virgin Islands, U.S.
+        ['VN', 'VNM', '704'], // Viet Nam
         ['VU', 'VUT', '548'], // Vanuatu
         ['WF', 'WLF', '876'], // Wallis and Futuna
+        ['WK', 'WAK', '872'], // Wake Island
         ['WS', 'WSM', '882'], // Samoa
-        ['XK', 'XKX', '0'], // Kosovo
+        ['YD', 'YMD', '720'], // Yemen, Democratic, People's Democratic Republic of
         ['YE', 'YEM', '887'], // Yemen
         ['YT', 'MYT', '175'], // Mayotte
+        ['YU', 'YUG', '891'], // Yugoslavia, Socialist Federal Republic of
         ['ZA', 'ZAF', '710'], // South Africa
         ['ZM', 'ZMB', '894'], // Zambia
+        ['ZR', 'ZAR', '180'], // Zaire, Republic of
         ['ZW', 'ZWE', '716'], // Zimbabwe
-
     ];
 
     public $set;
diff --git a/vendor/respect/validation/library/Rules/Cpf.php b/vendor/respect/validation/library/Rules/Cpf.php
index 8c2f1c4406504ef79f848c69bbb2ce0dc75bb7eb..5ae63780b0cd70d5a24dce8137b1c5adf68d171f 100644
--- a/vendor/respect/validation/library/Rules/Cpf.php
+++ b/vendor/respect/validation/library/Rules/Cpf.php
@@ -18,7 +18,7 @@ class Cpf extends AbstractRule
         // Code ported from jsfromhell.com
         $c = preg_replace('/\D/', '', $input);
 
-        if (strlen($c) != 11 || preg_match("/^{$c[0]}{11}$/", $c)) {
+        if (strlen($c) != 11 || preg_match("/^{$c[0]}{11}$/", $c) || $c === '01234567890') {
             return false;
         }
 
diff --git a/vendor/respect/validation/library/Rules/CurrencyCode.php b/vendor/respect/validation/library/Rules/CurrencyCode.php
index 024daef8825d66d4b0012a8e5cb4bf9dc2d65610..8fa73e5b07fd4868a9c9b452d0105bed84e9c2d0 100644
--- a/vendor/respect/validation/library/Rules/CurrencyCode.php
+++ b/vendor/respect/validation/library/Rules/CurrencyCode.php
@@ -22,184 +22,285 @@ class CurrencyCode extends AbstractRule
      * @var array
      */
     private $currencyCodes = [
-        'AED', // UAE Dirham
         'AFN', // Afghani
+        'EUR', // Euro
         'ALL', // Lek
-        'AMD', // Armenian Dram
-        'ANG', // Netherlands Antillean Guilder
+        'DZD', // Algerian Dinar
+        'USD', // US Dollar
+        'EUR', // Euro
         'AOA', // Kwanza
+        'XCD', // East Caribbean Dollar
+        '', // No universal currency
+        'XCD', // East Caribbean Dollar
         'ARS', // Argentine Peso
-        'AUD', // Australian Dollar
+        'AMD', // Armenian Dram
         'AWG', // Aruban Florin
-        'AZN', // Azerbaijanian Manat
-        'BAM', // Convertible Mark
-        'BBD', // Barbados Dollar
-        'BDT', // Taka
-        'BGN', // Bulgarian Lev
+        'AUD', // Australian Dollar
+        'EUR', // Euro
+        'AZN', // Azerbaijan Manat
+        'BSD', // Bahamian Dollar
         'BHD', // Bahraini Dinar
-        'BIF', // Burundi Franc
+        'BDT', // Taka
+        'BBD', // Barbados Dollar
+        'BYN', // Belarusian Ruble
+        'EUR', // Euro
+        'BZD', // Belize Dollar
+        'XOF', // CFA Franc BCEAO
         'BMD', // Bermudian Dollar
-        'BND', // Brunei Dollar
+        'INR', // Indian Rupee
+        'BTN', // Ngultrum
         'BOB', // Boliviano
         'BOV', // Mvdol
-        'BRL', // Brazilian Real
-        'BSD', // Bahamian Dollar
-        'BTN', // Ngultrum
+        'USD', // US Dollar
+        'BAM', // Convertible Mark
         'BWP', // Pula
-        'BYN', // Belarussian Ruble
-        'BZD', // Belize Dollar
+        'NOK', // Norwegian Krone
+        'BRL', // Brazilian Real
+        'USD', // US Dollar
+        'BND', // Brunei Dollar
+        'BGN', // Bulgarian Lev
+        'XOF', // CFA Franc BCEAO
+        'BIF', // Burundi Franc
+        'CVE', // Cabo Verde Escudo
+        'KHR', // Riel
+        'XAF', // CFA Franc BEAC
         'CAD', // Canadian Dollar
-        'CDF', // Congolese Franc
-        'CHE', // WIR Euro
-        'CHF', // Swiss Franc
-        'CHW', // WIR Franc
-        'CLF', // Unidad de Fomento
+        'KYD', // Cayman Islands Dollar
+        'XAF', // CFA Franc BEAC
+        'XAF', // CFA Franc BEAC
         'CLP', // Chilean Peso
+        'CLF', // Unidad de Fomento
         'CNY', // Yuan Renminbi
+        'AUD', // Australian Dollar
+        'AUD', // Australian Dollar
         'COP', // Colombian Peso
         'COU', // Unidad de Valor Real
+        'KMF', // Comorian Franc 
+        'CDF', // Congolese Franc
+        'XAF', // CFA Franc BEAC
+        'NZD', // New Zealand Dollar
         'CRC', // Costa Rican Colon
-        'CUC', // Peso Convertible
+        'XOF', // CFA Franc BCEAO
+        'HRK', // Kuna
         'CUP', // Cuban Peso
-        'CVE', // Cabo Verde Escudo
+        'CUC', // Peso Convertible
+        'ANG', // Netherlands Antillean Guilder
+        'EUR', // Euro
         'CZK', // Czech Koruna
-        'DJF', // Djibouti Franc
         'DKK', // Danish Krone
+        'DJF', // Djibouti Franc
+        'XCD', // East Caribbean Dollar
         'DOP', // Dominican Peso
-        'DZD', // Algerian Dinar
+        'USD', // US Dollar
         'EGP', // Egyptian Pound
+        'SVC', // El Salvador Colon
+        'USD', // US Dollar
+        'XAF', // CFA Franc BEAC
         'ERN', // Nakfa
+        'EUR', // Euro
         'ETB', // Ethiopian Birr
         'EUR', // Euro
-        'FJD', // Fiji Dollar
         'FKP', // Falkland Islands Pound
-        'GBP', // Pound Sterling
+        'DKK', // Danish Krone
+        'FJD', // Fiji Dollar
+        'EUR', // Euro
+        'EUR', // Euro
+        'EUR', // Euro
+        'XPF', // CFP Franc
+        'EUR', // Euro
+        'XAF', // CFA Franc BEAC
+        'GMD', // Dalasi
         'GEL', // Lari
+        'EUR', // Euro
         'GHS', // Ghana Cedi
         'GIP', // Gibraltar Pound
-        'GMD', // Dalasi
-        'GNF', // Guinea Franc
+        'EUR', // Euro
+        'DKK', // Danish Krone
+        'XCD', // East Caribbean Dollar
+        'EUR', // Euro
+        'USD', // US Dollar
         'GTQ', // Quetzal
+        'GBP', // Pound Sterling
+        'GNF', // Guinean Franc
+        'XOF', // CFA Franc BCEAO
         'GYD', // Guyana Dollar
-        'HKD', // Hong Kong Dollar
-        'HNL', // Lempira
-        'HRK', // Kuna
         'HTG', // Gourde
+        'USD', // US Dollar
+        'AUD', // Australian Dollar
+        'EUR', // Euro
+        'HNL', // Lempira
+        'HKD', // Hong Kong Dollar
         'HUF', // Forint
-        'IDR', // Rupiah
-        'ILS', // New Israeli Sheqel
+        'ISK', // Iceland Krona
         'INR', // Indian Rupee
-        'IQD', // Iraqi Dinar
+        'IDR', // Rupiah
+        'XDR', // SDR (Special Drawing Right)
         'IRR', // Iranian Rial
-        'ISK', // Iceland Krona
+        'IQD', // Iraqi Dinar
+        'EUR', // Euro
+        'GBP', // Pound Sterling
+        'ILS', // New Israeli Sheqel
+        'EUR', // Euro
         'JMD', // Jamaican Dollar
-        'JOD', // Jordanian Dinar
         'JPY', // Yen
+        'GBP', // Pound Sterling
+        'JOD', // Jordanian Dinar
+        'KZT', // Tenge
         'KES', // Kenyan Shilling
-        'KGS', // Som
-        'KHR', // Riel
-        'KMF', // Comoro Franc
+        'AUD', // Australian Dollar
         'KPW', // North Korean Won
         'KRW', // Won
         'KWD', // Kuwaiti Dinar
-        'KYD', // Cayman Islands Dollar
-        'KZT', // Tenge
-        'LAK', // Kip
+        'KGS', // Som
+        'LAK', // Lao Kip
+        'EUR', // Euro
         'LBP', // Lebanese Pound
-        'LKR', // Sri Lanka Rupee
-        'LRD', // Liberian Dollar
         'LSL', // Loti
+        'ZAR', // Rand
+        'LRD', // Liberian Dollar
         'LYD', // Libyan Dinar
-        'MAD', // Moroccan Dirham
-        'MDL', // Moldovan Leu
-        'MGA', // Malagasy Ariary
-        'MKD', // Denar
-        'MMK', // Kyat
-        'MNT', // Tugrik
+        'CHF', // Swiss Franc
+        'EUR', // Euro
+        'EUR', // Euro
         'MOP', // Pataca
-        'MRO', // Ouguiya
-        'MUR', // Mauritius Rupee
+        'MKD', // Denar
+        'MGA', // Malagasy Ariary
+        'MWK', // Malawi Kwacha
+        'MYR', // Malaysian Ringgit
         'MVR', // Rufiyaa
-        'MWK', // Kwacha
+        'XOF', // CFA Franc BCEAO
+        'EUR', // Euro
+        'USD', // US Dollar
+        'EUR', // Euro
+        'MRU', // Ouguiya
+        'MUR', // Mauritius Rupee
+        'EUR', // Euro
+        'XUA', // ADB Unit of Account
         'MXN', // Mexican Peso
         'MXV', // Mexican Unidad de Inversion (UDI)
-        'MYR', // Malaysian Ringgit
+        'USD', // US Dollar
+        'MDL', // Moldovan Leu
+        'EUR', // Euro
+        'MNT', // Tugrik
+        'EUR', // Euro
+        'XCD', // East Caribbean Dollar
+        'MAD', // Moroccan Dirham
         'MZN', // Mozambique Metical
+        'MMK', // Kyat
         'NAD', // Namibia Dollar
-        'NGN', // Naira
-        'NIO', // Cordoba Oro
-        'NOK', // Norwegian Krone
+        'ZAR', // Rand
+        'AUD', // Australian Dollar
         'NPR', // Nepalese Rupee
+        'EUR', // Euro
+        'XPF', // CFP Franc
+        'NZD', // New Zealand Dollar
+        'NIO', // Cordoba Oro
+        'XOF', // CFA Franc BCEAO
+        'NGN', // Naira
         'NZD', // New Zealand Dollar
+        'AUD', // Australian Dollar
+        'USD', // US Dollar
+        'NOK', // Norwegian Krone
         'OMR', // Rial Omani
+        'PKR', // Pakistan Rupee
+        'USD', // US Dollar
+        '', // No universal currency
         'PAB', // Balboa
-        'PEN', // Nuevo Sol
+        'USD', // US Dollar
         'PGK', // Kina
+        'PYG', // Guarani
+        'PEN', // Sol
         'PHP', // Philippine Peso
-        'PKR', // Pakistan Rupee
+        'NZD', // New Zealand Dollar
         'PLN', // Zloty
-        'PYG', // Guarani
+        'EUR', // Euro
+        'USD', // US Dollar
         'QAR', // Qatari Rial
+        'EUR', // Euro
         'RON', // Romanian Leu
-        'RSD', // Serbian Dinar
         'RUB', // Russian Ruble
         'RWF', // Rwanda Franc
+        'EUR', // Euro
+        'SHP', // Saint Helena Pound
+        'XCD', // East Caribbean Dollar
+        'XCD', // East Caribbean Dollar
+        'EUR', // Euro
+        'EUR', // Euro
+        'XCD', // East Caribbean Dollar
+        'WST', // Tala
+        'EUR', // Euro
+        'STN', // Dobra
         'SAR', // Saudi Riyal
-        'SBD', // Solomon Islands Dollar
+        'XOF', // CFA Franc BCEAO
+        'RSD', // Serbian Dinar
         'SCR', // Seychelles Rupee
-        'SDG', // Sudanese Pound
-        'SEK', // Swedish Krona
-        'SGD', // Singapore Dollar
-        'SHP', // Saint Helena Pound
         'SLL', // Leone
+        'SGD', // Singapore Dollar
+        'ANG', // Netherlands Antillean Guilder
+        'XSU', // Sucre
+        'EUR', // Euro
+        'EUR', // Euro
+        'SBD', // Solomon Islands Dollar
         'SOS', // Somali Shilling
-        'SRD', // Surinam Dollar
+        'ZAR', // Rand
+        '', // No universal currency
         'SSP', // South Sudanese Pound
-        'STD', // Dobra
-        'SVC', // El Salvador Colon
-        'SYP', // Syrian Pound
+        'EUR', // Euro
+        'LKR', // Sri Lanka Rupee
+        'SDG', // Sudanese Pound
+        'SRD', // Surinam Dollar
+        'NOK', // Norwegian Krone
         'SZL', // Lilangeni
-        'THB', // Baht
+        'SEK', // Swedish Krona
+        'CHF', // Swiss Franc
+        'CHE', // WIR Euro
+        'CHW', // WIR Franc
+        'SYP', // Syrian Pound
+        'TWD', // New Taiwan Dollar
         'TJS', // Somoni
-        'TMT', // Turkmenistan New Manat
-        'TND', // Tunisian Dinar
+        'TZS', // Tanzanian Shilling
+        'THB', // Baht
+        'USD', // US Dollar
+        'XOF', // CFA Franc BCEAO
+        'NZD', // New Zealand Dollar
         'TOP', // Pa’anga
-        'TRY', // Turkish Lira
         'TTD', // Trinidad and Tobago Dollar
-        'TWD', // New Taiwan Dollar
-        'TZS', // Tanzanian Shilling
-        'UAH', // Hryvnia
+        'TND', // Tunisian Dinar
+        'TRY', // Turkish Lira
+        'TMT', // Turkmenistan New Manat
+        'USD', // US Dollar
+        'AUD', // Australian Dollar
         'UGX', // Uganda Shilling
+        'UAH', // Hryvnia
+        'AED', // UAE Dirham
+        'GBP', // Pound Sterling
+        'USD', // US Dollar
         'USD', // US Dollar
         'USN', // US Dollar (Next day)
-        'UYI', // Uruguay Peso en Unidades Indexadas (URUIURUI)
         'UYU', // Peso Uruguayo
+        'UYI', // Uruguay Peso en Unidades Indexadas (UI)
+        'UYW', // Unidad Previsional
         'UZS', // Uzbekistan Sum
-        'VEF', // Bolivar
-        'VND', // Dong
         'VUV', // Vatu
-        'WST', // Tala
-        'XAF', // CFA Franc BEAC
-        'XAG', // Silver
-        'XAU', // Gold
+        'VES', // Bolívar Soberano
+        'VND', // Dong
+        'USD', // US Dollar
+        'USD', // US Dollar
+        'XPF', // CFP Franc
+        'MAD', // Moroccan Dirham
+        'YER', // Yemeni Rial
+        'ZMW', // Zambian Kwacha
+        'ZWL', // Zimbabwe Dollar
         'XBA', // Bond Markets Unit European Composite Unit (EURCO)
         'XBB', // Bond Markets Unit European Monetary Unit (E.M.U.-6)
         'XBC', // Bond Markets Unit European Unit of Account 9 (E.U.A.-9)
         'XBD', // Bond Markets Unit European Unit of Account 17 (E.U.A.-17)
-        'XCD', // East Caribbean Dollar
-        'XDR', // SDR (Special Drawing Right)
-        'XOF', // CFA Franc BCEAO
-        'XPD', // Palladium
-        'XPF', // CFP Franc
-        'XPT', // Platinum
-        'XSU', // Sucre
         'XTS', // Codes specifically reserved for testing purposes
-        'XUA', // ADB Unit of Account
         'XXX', // The codes assigned for transactions where no currency is involved
-        'YER', // Yemeni Rial
-        'ZAR', // Rand
-        'ZMW', // Zambian Kwacha
-        'ZWL', // Zimbabwe Dollar
+        'XAU', // Gold
+        'XPD', // Palladium
+        'XPT', // Platinum
+        'XAG', // Silver
     ];
 
     public function validate($input)
diff --git a/vendor/respect/validation/library/Rules/LanguageCode.php b/vendor/respect/validation/library/Rules/LanguageCode.php
index 19bdf22c1d87a54e3c47f91de0d4f4fbf8fcf2f8..370f7c93aec8877b94dbd4098871602586ad6542 100644
--- a/vendor/respect/validation/library/Rules/LanguageCode.php
+++ b/vendor/respect/validation/library/Rules/LanguageCode.php
@@ -27,492 +27,492 @@ class LanguageCode extends AbstractRule
      * @var array
      */
     protected $languageCodeList = [
-        ['AA', 'AAR'], // AFAR
-        ['AB', 'ABK'], // ABKHAZIAN
-        ['', 'ACE'], // ACHINESE
-        ['', 'ACH'], // ACOLI
-        ['', 'ADA'], // ADANGME
-        ['', 'ADY'], // ADYGHE; ADYGEI
-        ['', 'AFA'], // AFRO-ASIATIC LANGUAGES
-        ['', 'AFH'], // AFRIHILI
-        ['AF', 'AFR'], // AFRIKAANS
-        ['', 'AIN'], // AINU
-        ['AK', 'AKA'], // AKAN
-        ['', 'AKK'], // AKKADIAN
-        ['SQ', 'ALB'], // ALBANIAN
-        ['', 'ALE'], // ALEUT
-        ['', 'ALG'], // ALGONQUIAN LANGUAGES
-        ['', 'ALT'], // SOUTHERN ALTAI
-        ['AM', 'AMH'], // AMHARIC
-        ['', 'ANG'], // ENGLISH, OLD (CA.450-1100)
-        ['', 'ANP'], // ANGIKA
-        ['', 'APA'], // APACHE LANGUAGES
-        ['AR', 'ARA'], // ARABIC
-        ['', 'ARC'], // OFFICIAL ARAMAIC (700-300 BCE); IMPERIAL ARAMAIC (700-300 BCE)
-        ['AN', 'ARG'], // ARAGONESE
-        ['HY', 'ARM'], // ARMENIAN
-        ['', 'ARN'], // MAPUDUNGUN; MAPUCHE
-        ['', 'ARP'], // ARAPAHO
-        ['', 'ART'], // ARTIFICIAL LANGUAGES
-        ['', 'ARW'], // ARAWAK
-        ['AS', 'ASM'], // ASSAMESE
-        ['', 'AST'], // ASTURIAN; BABLE; LEONESE; ASTURLEONESE
-        ['', 'ATH'], // ATHAPASCAN LANGUAGES
-        ['', 'AUS'], // AUSTRALIAN LANGUAGES
-        ['AV', 'AVA'], // AVARIC
-        ['AE', 'AVE'], // AVESTAN
-        ['', 'AWA'], // AWADHI
-        ['AY', 'AYM'], // AYMARA
-        ['AZ', 'AZE'], // AZERBAIJANI
-        ['', 'BAD'], // BANDA LANGUAGES
-        ['', 'BAI'], // BAMILEKE LANGUAGES
-        ['BA', 'BAK'], // BASHKIR
-        ['', 'BAL'], // BALUCHI
-        ['BM', 'BAM'], // BAMBARA
-        ['', 'BAN'], // BALINESE
-        ['EU', 'BAQ'], // BASQUE
-        ['', 'BAS'], // BASA
-        ['', 'BAT'], // BALTIC LANGUAGES
-        ['', 'BEJ'], // BEJA; BEDAWIYET
-        ['BE', 'BEL'], // BELARUSIAN
-        ['', 'BEM'], // BEMBA
-        ['BN', 'BEN'], // BENGALI
-        ['', 'BER'], // BERBER LANGUAGES
-        ['', 'BHO'], // BHOJPURI
-        ['BH', 'BIH'], // BIHARI LANGUAGES
-        ['', 'BIK'], // BIKOL
-        ['', 'BIN'], // BINI; EDO
-        ['BI', 'BIS'], // BISLAMA
-        ['', 'BLA'], // SIKSIKA
-        ['', 'BNT'], // BANTU (OTHER)
-        ['BS', 'BOS'], // BOSNIAN
-        ['', 'BRA'], // BRAJ
-        ['BR', 'BRE'], // BRETON
-        ['', 'BTK'], // BATAK LANGUAGES
-        ['', 'BUA'], // BURIAT
-        ['', 'BUG'], // BUGINESE
-        ['BG', 'BUL'], // BULGARIAN
-        ['MY', 'BUR'], // BURMESE
-        ['', 'BYN'], // BLIN; BILIN
-        ['', 'CAD'], // CADDO
-        ['', 'CAI'], // CENTRAL AMERICAN INDIAN LANGUAGES
-        ['', 'CAR'], // GALIBI CARIB
-        ['CA', 'CAT'], // CATALAN; VALENCIAN
-        ['', 'CAU'], // CAUCASIAN LANGUAGES
-        ['', 'CEB'], // CEBUANO
-        ['', 'CEL'], // CELTIC LANGUAGES
-        ['CH', 'CHA'], // CHAMORRO
-        ['', 'CHB'], // CHIBCHA
-        ['CE', 'CHE'], // CHECHEN
-        ['', 'CHG'], // CHAGATAI
-        ['ZH', 'CHI'], // CHINESE
-        ['', 'CHK'], // CHUUKESE
-        ['', 'CHM'], // MARI
-        ['', 'CHN'], // CHINOOK JARGON
-        ['', 'CHO'], // CHOCTAW
-        ['', 'CHP'], // CHIPEWYAN; DENE SULINE
-        ['', 'CHR'], // CHEROKEE
-        ['CU', 'CHU'], // CHURCH SLAVIC; OLD SLAVONIC; CHURCH SLAVONIC; OLD BULGARIAN; OLD CHURCH SLAVONIC
-        ['CV', 'CHV'], // CHUVASH
-        ['', 'CHY'], // CHEYENNE
-        ['', 'CMC'], // CHAMIC LANGUAGES
-        ['', 'COP'], // COPTIC
-        ['KW', 'COR'], // CORNISH
-        ['CO', 'COS'], // CORSICAN
-        ['', 'CPE'], // CREOLES AND PIDGINS, ENGLISH BASED
-        ['', 'CPF'], // CREOLES AND PIDGINS, FRENCH-BASED
-        ['', 'CPP'], // CREOLES AND PIDGINS, PORTUGUESE-BASED
-        ['CR', 'CRE'], // CREE
-        ['', 'CRH'], // CRIMEAN TATAR; CRIMEAN TURKISH
-        ['', 'CRP'], // CREOLES AND PIDGINS
-        ['', 'CSB'], // KASHUBIAN
-        ['', 'CUS'], // CUSHITIC LANGUAGES
-        ['CS', 'CZE'], // CZECH
-        ['', 'DAK'], // DAKOTA
-        ['DA', 'DAN'], // DANISH
-        ['', 'DAR'], // DARGWA
-        ['', 'DAY'], // LAND DAYAK LANGUAGES
-        ['', 'DEL'], // DELAWARE
-        ['', 'DEN'], // SLAVE (ATHAPASCAN)
-        ['', 'DGR'], // DOGRIB
-        ['', 'DIN'], // DINKA
-        ['DV', 'DIV'], // DIVEHI; DHIVEHI; MALDIVIAN
-        ['', 'DOI'], // DOGRI
-        ['', 'DRA'], // DRAVIDIAN LANGUAGES
-        ['', 'DSB'], // LOWER SORBIAN
-        ['', 'DUA'], // DUALA
-        ['', 'DUM'], // DUTCH, MIDDLE (CA.1050-1350)
-        ['NL', 'DUT'], // DUTCH; FLEMISH
-        ['', 'DYU'], // DYULA
-        ['DZ', 'DZO'], // DZONGKHA
-        ['', 'EFI'], // EFIK
-        ['', 'EGY'], // EGYPTIAN (ANCIENT)
-        ['', 'EKA'], // EKAJUK
-        ['', 'ELX'], // ELAMITE
-        ['EN', 'ENG'], // ENGLISH
-        ['', 'ENM'], // ENGLISH, MIDDLE (1100-1500)
-        ['EO', 'EPO'], // ESPERANTO
-        ['ET', 'EST'], // ESTONIAN
-        ['EE', 'EWE'], // EWE
-        ['', 'EWO'], // EWONDO
-        ['', 'FAN'], // FANG
-        ['FO', 'FAO'], // FAROESE
-        ['', 'FAT'], // FANTI
-        ['FJ', 'FIJ'], // FIJIAN
-        ['', 'FIL'], // FILIPINO; PILIPINO
-        ['FI', 'FIN'], // FINNISH
-        ['', 'FIU'], // FINNO-UGRIAN LANGUAGES
-        ['', 'FON'], // FON
-        ['FR', 'FRE'], // FRENCH
-        ['', 'FRM'], // FRENCH, MIDDLE (CA.1400-1600)
-        ['', 'FRO'], // FRENCH, OLD (842-CA.1400)
-        ['', 'FRR'], // NORTHERN FRISIAN
-        ['', 'FRS'], // EASTERN FRISIAN
-        ['FY', 'FRY'], // WESTERN FRISIAN
-        ['FF', 'FUL'], // FULAH
-        ['', 'FUR'], // FRIULIAN
-        ['', 'GAA'], // GA
-        ['', 'GAY'], // GAYO
-        ['', 'GBA'], // GBAYA
-        ['', 'GEM'], // GERMANIC LANGUAGES
-        ['KA', 'GEO'], // GEORGIAN
-        ['DE', 'GER'], // GERMAN
-        ['', 'GEZ'], // GEEZ
-        ['', 'GIL'], // GILBERTESE
-        ['GD', 'GLA'], // GAELIC; SCOTTISH GAELIC
-        ['GA', 'GLE'], // IRISH
-        ['GL', 'GLG'], // GALICIAN
-        ['GV', 'GLV'], // MANX
-        ['', 'GMH'], // GERMAN, MIDDLE HIGH (CA.1050-1500)
-        ['', 'GOH'], // GERMAN, OLD HIGH (CA.750-1050)
-        ['', 'GON'], // GONDI
-        ['', 'GOR'], // GORONTALO
-        ['', 'GOT'], // GOTHIC
-        ['', 'GRB'], // GREBO
-        ['', 'GRC'], // GREEK, ANCIENT (TO 1453)
-        ['EL', 'GRE'], // GREEK, MODERN (1453-)
-        ['GN', 'GRN'], // GUARANI
-        ['', 'GSW'], // SWISS GERMAN; ALEMANNIC; ALSATIAN
-        ['GU', 'GUJ'], // GUJARATI
-        ['', 'GWI'], // GWICH'IN
-        ['', 'HAI'], // HAIDA
-        ['HT', 'HAT'], // HAITIAN; HAITIAN CREOLE
-        ['HA', 'HAU'], // HAUSA
-        ['', 'HAW'], // HAWAIIAN
-        ['HE', 'HEB'], // HEBREW
-        ['HZ', 'HER'], // HERERO
-        ['', 'HIL'], // HILIGAYNON
-        ['', 'HIM'], // HIMACHALI LANGUAGES; WESTERN PAHARI LANGUAGES
-        ['HI', 'HIN'], // HINDI
-        ['', 'HIT'], // HITTITE
-        ['', 'HMN'], // HMONG; MONG
-        ['HO', 'HMO'], // HIRI MOTU
-        ['HR', 'HRV'], // CROATIAN
-        ['', 'HSB'], // UPPER SORBIAN
-        ['HU', 'HUN'], // HUNGARIAN
-        ['', 'HUP'], // HUPA
-        ['', 'IBA'], // IBAN
-        ['IG', 'IBO'], // IGBO
-        ['IS', 'ICE'], // ICELANDIC
-        ['IO', 'IDO'], // IDO
-        ['II', 'III'], // SICHUAN YI; NUOSU
-        ['', 'IJO'], // IJO LANGUAGES
-        ['IU', 'IKU'], // INUKTITUT
-        ['IE', 'ILE'], // INTERLINGUE; OCCIDENTAL
-        ['', 'ILO'], // ILOKO
-        ['IA', 'INA'], // INTERLINGUA (INTERNATIONAL AUXILIARY LANGUAGE ASSOCIATION)
-        ['', 'INC'], // INDIC LANGUAGES
-        ['ID', 'IND'], // INDONESIAN
-        ['', 'INE'], // INDO-EUROPEAN LANGUAGES
-        ['', 'INH'], // INGUSH
-        ['IK', 'IPK'], // INUPIAQ
-        ['', 'IRA'], // IRANIAN LANGUAGES
-        ['', 'IRO'], // IROQUOIAN LANGUAGES
-        ['IT', 'ITA'], // ITALIAN
-        ['JV', 'JAV'], // JAVANESE
-        ['', 'JBO'], // LOJBAN
-        ['JA', 'JPN'], // JAPANESE
-        ['', 'JPR'], // JUDEO-PERSIAN
-        ['', 'JRB'], // JUDEO-ARABIC
-        ['', 'KAA'], // KARA-KALPAK
-        ['', 'KAB'], // KABYLE
-        ['', 'KAC'], // KACHIN; JINGPHO
-        ['KL', 'KAL'], // KALAALLISUT; GREENLANDIC
-        ['', 'KAM'], // KAMBA
-        ['KN', 'KAN'], // KANNADA
-        ['', 'KAR'], // KAREN LANGUAGES
-        ['KS', 'KAS'], // KASHMIRI
-        ['KR', 'KAU'], // KANURI
-        ['', 'KAW'], // KAWI
-        ['KK', 'KAZ'], // KAZAKH
-        ['', 'KBD'], // KABARDIAN
-        ['', 'KHA'], // KHASI
-        ['', 'KHI'], // KHOISAN LANGUAGES
-        ['KM', 'KHM'], // CENTRAL KHMER
-        ['', 'KHO'], // KHOTANESE; SAKAN
-        ['KI', 'KIK'], // KIKUYU; GIKUYU
-        ['RW', 'KIN'], // KINYARWANDA
-        ['KY', 'KIR'], // KIRGHIZ; KYRGYZ
-        ['', 'KMB'], // KIMBUNDU
-        ['', 'KOK'], // KONKANI
-        ['KV', 'KOM'], // KOMI
-        ['KG', 'KON'], // KONGO
-        ['KO', 'KOR'], // KOREAN
-        ['', 'KOS'], // KOSRAEAN
-        ['', 'KPE'], // KPELLE
-        ['', 'KRC'], // KARACHAY-BALKAR
-        ['', 'KRL'], // KARELIAN
-        ['', 'KRO'], // KRU LANGUAGES
-        ['', 'KRU'], // KURUKH
-        ['KJ', 'KUA'], // KUANYAMA; KWANYAMA
-        ['', 'KUM'], // KUMYK
-        ['KU', 'KUR'], // KURDISH
-        ['', 'KUT'], // KUTENAI
-        ['', 'LAD'], // LADINO
-        ['', 'LAH'], // LAHNDA
-        ['', 'LAM'], // LAMBA
-        ['LO', 'LAO'], // LAO
-        ['LA', 'LAT'], // LATIN
-        ['LV', 'LAV'], // LATVIAN
-        ['', 'LEZ'], // LEZGHIAN
-        ['LI', 'LIM'], // LIMBURGAN; LIMBURGER; LIMBURGISH
-        ['LN', 'LIN'], // LINGALA
-        ['LT', 'LIT'], // LITHUANIAN
-        ['', 'LOL'], // MONGO
-        ['', 'LOZ'], // LOZI
-        ['LB', 'LTZ'], // LUXEMBOURGISH; LETZEBURGESCH
-        ['', 'LUA'], // LUBA-LULUA
-        ['LU', 'LUB'], // LUBA-KATANGA
-        ['LG', 'LUG'], // GANDA
-        ['', 'LUI'], // LUISENO
-        ['', 'LUN'], // LUNDA
-        ['', 'LUO'], // LUO (KENYA AND TANZANIA)
-        ['', 'LUS'], // LUSHAI
-        ['MK', 'MAC'], // MACEDONIAN
-        ['', 'MAD'], // MADURESE
-        ['', 'MAG'], // MAGAHI
-        ['MH', 'MAH'], // MARSHALLESE
-        ['', 'MAI'], // MAITHILI
-        ['', 'MAK'], // MAKASAR
-        ['ML', 'MAL'], // MALAYALAM
-        ['', 'MAN'], // MANDINGO
-        ['MI', 'MAO'], // MAORI
-        ['', 'MAP'], // AUSTRONESIAN LANGUAGES
-        ['MR', 'MAR'], // MARATHI
-        ['', 'MAS'], // MASAI
-        ['MS', 'MAY'], // MALAY
-        ['', 'MDF'], // MOKSHA
-        ['', 'MDR'], // MANDAR
-        ['', 'MEN'], // MENDE
-        ['', 'MGA'], // IRISH, MIDDLE (900-1200)
-        ['', 'MIC'], // MI'KMAQ; MICMAC
-        ['', 'MIN'], // MINANGKABAU
-        ['', 'MIS'], // UNCODED LANGUAGES
-        ['', 'MKH'], // MON-KHMER LANGUAGES
-        ['MG', 'MLG'], // MALAGASY
-        ['MT', 'MLT'], // MALTESE
-        ['', 'MNC'], // MANCHU
-        ['', 'MNI'], // MANIPURI
-        ['', 'MNO'], // MANOBO LANGUAGES
-        ['', 'MOH'], // MOHAWK
-        ['MN', 'MON'], // MONGOLIAN
-        ['', 'MOS'], // MOSSI
-        ['', 'MUL'], // MULTIPLE LANGUAGES
-        ['', 'MUN'], // MUNDA LANGUAGES
-        ['', 'MUS'], // CREEK
-        ['', 'MWL'], // MIRANDESE
-        ['', 'MWR'], // MARWARI
-        ['', 'MYN'], // MAYAN LANGUAGES
-        ['', 'MYV'], // ERZYA
-        ['', 'NAH'], // NAHUATL LANGUAGES
-        ['', 'NAI'], // NORTH AMERICAN INDIAN LANGUAGES
-        ['', 'NAP'], // NEAPOLITAN
-        ['NA', 'NAU'], // NAURU
-        ['NV', 'NAV'], // NAVAJO; NAVAHO
-        ['NR', 'NBL'], // NDEBELE, SOUTH; SOUTH NDEBELE
-        ['ND', 'NDE'], // NDEBELE, NORTH; NORTH NDEBELE
-        ['NG', 'NDO'], // NDONGA
-        ['', 'NDS'], // LOW GERMAN; LOW SAXON; GERMAN, LOW; SAXON, LOW
-        ['NE', 'NEP'], // NEPALI
-        ['', 'NEW'], // NEPAL BHASA; NEWARI
-        ['', 'NIA'], // NIAS
-        ['', 'NIC'], // NIGER-KORDOFANIAN LANGUAGES
-        ['', 'NIU'], // NIUEAN
-        ['NN', 'NNO'], // NORWEGIAN NYNORSK; NYNORSK, NORWEGIAN
-        ['NB', 'NOB'], // BOKMÃ…L, NORWEGIAN; NORWEGIAN BOKMÃ…L
-        ['', 'NOG'], // NOGAI
-        ['', 'NON'], // NORSE, OLD
-        ['NO', 'NOR'], // NORWEGIAN
-        ['', 'NQO'], // N'KO
-        ['', 'NSO'], // PEDI; SEPEDI; NORTHERN SOTHO
-        ['', 'NUB'], // NUBIAN LANGUAGES
-        ['', 'NWC'], // CLASSICAL NEWARI; OLD NEWARI; CLASSICAL NEPAL BHASA
-        ['NY', 'NYA'], // CHICHEWA; CHEWA; NYANJA
-        ['', 'NYM'], // NYAMWEZI
-        ['', 'NYN'], // NYANKOLE
-        ['', 'NYO'], // NYORO
-        ['', 'NZI'], // NZIMA
-        ['OC', 'OCI'], // OCCITAN (POST 1500); PROVENÇAL
-        ['OJ', 'OJI'], // OJIBWA
-        ['OR', 'ORI'], // ORIYA
-        ['OM', 'ORM'], // OROMO
-        ['', 'OSA'], // OSAGE
-        ['OS', 'OSS'], // OSSETIAN; OSSETIC
-        ['', 'OTA'], // TURKISH, OTTOMAN (1500-1928)
-        ['', 'OTO'], // OTOMIAN LANGUAGES
-        ['', 'PAA'], // PAPUAN LANGUAGES
-        ['', 'PAG'], // PANGASINAN
-        ['', 'PAL'], // PAHLAVI
-        ['', 'PAM'], // PAMPANGA; KAPAMPANGAN
-        ['PA', 'PAN'], // PANJABI; PUNJABI
-        ['', 'PAP'], // PAPIAMENTO
-        ['', 'PAU'], // PALAUAN
-        ['', 'PEO'], // PERSIAN, OLD (CA.600-400 B.C.)
-        ['FA', 'PER'], // PERSIAN
-        ['', 'PHI'], // PHILIPPINE LANGUAGES
-        ['', 'PHN'], // PHOENICIAN
-        ['PI', 'PLI'], // PALI
-        ['PL', 'POL'], // POLISH
-        ['', 'PON'], // POHNPEIAN
-        ['PT', 'POR'], // PORTUGUESE
-        ['', 'PRA'], // PRAKRIT LANGUAGES
-        ['', 'PRO'], // PROVENÇAL, OLD (TO 1500)
-        ['PS', 'PUS'], // PUSHTO; PASHTO
-        ['', 'QAA-QTZ'], // RESERVED FOR LOCAL USE
-        ['QU', 'QUE'], // QUECHUA
-        ['', 'RAJ'], // RAJASTHANI
-        ['', 'RAP'], // RAPANUI
-        ['', 'RAR'], // RAROTONGAN; COOK ISLANDS MAORI
-        ['', 'ROA'], // ROMANCE LANGUAGES
-        ['RM', 'ROH'], // ROMANSH
-        ['', 'ROM'], // ROMANY
-        ['RO', 'RUM'], // ROMANIAN; MOLDAVIAN; MOLDOVAN
-        ['RN', 'RUN'], // RUNDI
-        ['', 'RUP'], // AROMANIAN; ARUMANIAN; MACEDO-ROMANIAN
-        ['RU', 'RUS'], // RUSSIAN
-        ['', 'SAD'], // SANDAWE
-        ['SG', 'SAG'], // SANGO
-        ['', 'SAH'], // YAKUT
-        ['', 'SAI'], // SOUTH AMERICAN INDIAN (OTHER)
-        ['', 'SAL'], // SALISHAN LANGUAGES
-        ['', 'SAM'], // SAMARITAN ARAMAIC
-        ['SA', 'SAN'], // SANSKRIT
-        ['', 'SAS'], // SASAK
-        ['', 'SAT'], // SANTALI
-        ['', 'SCN'], // SICILIAN
-        ['', 'SCO'], // SCOTS
-        ['', 'SEL'], // SELKUP
-        ['', 'SEM'], // SEMITIC LANGUAGES
-        ['', 'SGA'], // IRISH, OLD (TO 900)
-        ['', 'SGN'], // SIGN LANGUAGES
-        ['', 'SHN'], // SHAN
-        ['', 'SID'], // SIDAMO
-        ['SI', 'SIN'], // SINHALA; SINHALESE
-        ['', 'SIO'], // SIOUAN LANGUAGES
-        ['', 'SIT'], // SINO-TIBETAN LANGUAGES
-        ['', 'SLA'], // SLAVIC LANGUAGES
-        ['SK', 'SLO'], // SLOVAK
-        ['SL', 'SLV'], // SLOVENIAN
-        ['', 'SMA'], // SOUTHERN SAMI
-        ['SE', 'SME'], // NORTHERN SAMI
-        ['', 'SMI'], // SAMI LANGUAGES
-        ['', 'SMJ'], // LULE SAMI
-        ['', 'SMN'], // INARI SAMI
-        ['SM', 'SMO'], // SAMOAN
-        ['', 'SMS'], // SKOLT SAMI
-        ['SN', 'SNA'], // SHONA
-        ['SD', 'SND'], // SINDHI
-        ['', 'SNK'], // SONINKE
-        ['', 'SOG'], // SOGDIAN
-        ['SO', 'SOM'], // SOMALI
-        ['', 'SON'], // SONGHAI LANGUAGES
-        ['ST', 'SOT'], // SOTHO, SOUTHERN
-        ['ES', 'SPA'], // SPANISH; CASTILIAN
-        ['SC', 'SRD'], // SARDINIAN
-        ['', 'SRN'], // SRANAN TONGO
-        ['SR', 'SRP'], // SERBIAN
-        ['', 'SRR'], // SERER
-        ['', 'SSA'], // NILO-SAHARAN LANGUAGES
-        ['SS', 'SSW'], // SWATI
-        ['', 'SUK'], // SUKUMA
-        ['SU', 'SUN'], // SUNDANESE
-        ['', 'SUS'], // SUSU
-        ['', 'SUX'], // SUMERIAN
-        ['SW', 'SWA'], // SWAHILI
-        ['SV', 'SWE'], // SWEDISH
-        ['', 'SYC'], // CLASSICAL SYRIAC
-        ['', 'SYR'], // SYRIAC
-        ['TY', 'TAH'], // TAHITIAN
-        ['', 'TAI'], // TAI LANGUAGES
-        ['TA', 'TAM'], // TAMIL
-        ['TT', 'TAT'], // TATAR
-        ['TE', 'TEL'], // TELUGU
-        ['', 'TEM'], // TIMNE
-        ['', 'TER'], // TERENO
-        ['', 'TET'], // TETUM
-        ['TG', 'TGK'], // TAJIK
-        ['TL', 'TGL'], // TAGALOG
-        ['TH', 'THA'], // THAI
-        ['BO', 'TIB'], // TIBETAN
-        ['', 'TIG'], // TIGRE
-        ['TI', 'TIR'], // TIGRINYA
-        ['', 'TIV'], // TIV
-        ['', 'TKL'], // TOKELAU
-        ['', 'TLH'], // KLINGON; TLHINGAN-HOL
-        ['', 'TLI'], // TLINGIT
-        ['', 'TMH'], // TAMASHEK
-        ['', 'TOG'], // TONGA (NYASA)
-        ['TO', 'TON'], // TONGA (TONGA ISLANDS)
-        ['', 'TPI'], // TOK PISIN
-        ['', 'TSI'], // TSIMSHIAN
-        ['TN', 'TSN'], // TSWANA
-        ['TS', 'TSO'], // TSONGA
-        ['TK', 'TUK'], // TURKMEN
-        ['', 'TUM'], // TUMBUKA
-        ['', 'TUP'], // TUPI LANGUAGES
-        ['TR', 'TUR'], // TURKISH
-        ['', 'TUT'], // ALTAIC LANGUAGES
-        ['', 'TVL'], // TUVALU
-        ['TW', 'TWI'], // TWI
-        ['', 'TYV'], // TUVINIAN
-        ['', 'UDM'], // UDMURT
-        ['', 'UGA'], // UGARITIC
-        ['UG', 'UIG'], // UIGHUR; UYGHUR
-        ['UK', 'UKR'], // UKRAINIAN
-        ['', 'UMB'], // UMBUNDU
-        ['', 'UND'], // UNDETERMINED
-        ['UR', 'URD'], // URDU
-        ['UZ', 'UZB'], // UZBEK
-        ['', 'VAI'], // VAI
-        ['VE', 'VEN'], // VENDA
-        ['VI', 'VIE'], // VIETNAMESE
-        ['VO', 'VOL'], // VOLAPÃœK
-        ['', 'VOT'], // VOTIC
-        ['', 'WAK'], // WAKASHAN LANGUAGES
-        ['', 'WAL'], // WALAMO
-        ['', 'WAR'], // WARAY
-        ['', 'WAS'], // WASHO
-        ['CY', 'WEL'], // WELSH
-        ['', 'WEN'], // SORBIAN LANGUAGES
-        ['WA', 'WLN'], // WALLOON
-        ['WO', 'WOL'], // WOLOF
-        ['', 'XAL'], // KALMYK; OIRAT
-        ['XH', 'XHO'], // XHOSA
-        ['', 'YAO'], // YAO
-        ['', 'YAP'], // YAPESE
-        ['YI', 'YID'], // YIDDISH
-        ['YO', 'YOR'], // YORUBA
-        ['', 'YPK'], // YUPIK LANGUAGES
-        ['', 'ZAP'], // ZAPOTEC
-        ['', 'ZBL'], // BLISSYMBOLS; BLISSYMBOLICS; BLISS
-        ['', 'ZEN'], // ZENAGA
-        ['', 'ZGH'], // STANDARD MOROCCAN TAMAZIGHT
-        ['ZA', 'ZHA'], // ZHUANG; CHUANG
-        ['', 'ZND'], // ZANDE LANGUAGES
-        ['ZU', 'ZUL'], // ZULU
-        ['', 'ZUN'], // ZUNI
-        ['', 'ZXX'], // NO LINGUISTIC CONTENT; NOT APPLICABLE
-        ['', 'ZZA'], // ZAZA; DIMILI; DIMLI; KIRDKI; KIRMANJKI; ZAZAKI
+        ['AA', 'AAR'], // Afar
+        ['AB', 'ABK'], // Abkhazian
+        ['', 'ACE'], // Achinese
+        ['', 'ACH'], // Acoli
+        ['', 'ADA'], // Adangme
+        ['', 'ADY'], // Adyghe; Adygei
+        ['', 'AFA'], // Afro-Asiatic languages
+        ['', 'AFH'], // Afrihili
+        ['AF', 'AFR'], // Afrikaans
+        ['', 'AIN'], // Ainu
+        ['AK', 'AKA'], // Akan
+        ['', 'AKK'], // Akkadian
+        ['SQ', 'ALB'], // Albanian
+        ['', 'ALE'], // Aleut
+        ['', 'ALG'], // Algonquian languages
+        ['', 'ALT'], // Southern Altai
+        ['AM', 'AMH'], // Amharic
+        ['', 'ANG'], // English, Old (ca.450-1100)
+        ['', 'ANP'], // Angika
+        ['', 'APA'], // Apache languages
+        ['AR', 'ARA'], // Arabic
+        ['', 'ARC'], // Official Aramaic (700-300 BCE); Imperial Aramaic (700-300 BCE)
+        ['AN', 'ARG'], // Aragonese
+        ['HY', 'ARM'], // Armenian
+        ['', 'ARN'], // Mapudungun; Mapuche
+        ['', 'ARP'], // Arapaho
+        ['', 'ART'], // Artificial languages
+        ['', 'ARW'], // Arawak
+        ['AS', 'ASM'], // Assamese
+        ['', 'AST'], // Asturian; Bable; Leonese; Asturleonese
+        ['', 'ATH'], // Athapascan languages
+        ['', 'AUS'], // Australian languages
+        ['AV', 'AVA'], // Avaric
+        ['AE', 'AVE'], // Avestan
+        ['', 'AWA'], // Awadhi
+        ['AY', 'AYM'], // Aymara
+        ['AZ', 'AZE'], // Azerbaijani
+        ['', 'BAD'], // Banda languages
+        ['', 'BAI'], // Bamileke languages
+        ['BA', 'BAK'], // Bashkir
+        ['', 'BAL'], // Baluchi
+        ['BM', 'BAM'], // Bambara
+        ['', 'BAN'], // Balinese
+        ['EU', 'BAQ'], // Basque
+        ['', 'BAS'], // Basa
+        ['', 'BAT'], // Baltic languages
+        ['', 'BEJ'], // Beja; Bedawiyet
+        ['BE', 'BEL'], // Belarusian
+        ['', 'BEM'], // Bemba
+        ['BN', 'BEN'], // Bengali
+        ['', 'BER'], // Berber languages
+        ['', 'BHO'], // Bhojpuri
+        ['BH', 'BIH'], // Bihari languages
+        ['', 'BIK'], // Bikol
+        ['', 'BIN'], // Bini; Edo
+        ['BI', 'BIS'], // Bislama
+        ['', 'BLA'], // Siksika
+        ['', 'BNT'], // Bantu (Other)
+        ['BS', 'BOS'], // Bosnian
+        ['', 'BRA'], // Braj
+        ['BR', 'BRE'], // Breton
+        ['', 'BTK'], // Batak languages
+        ['', 'BUA'], // Buriat
+        ['', 'BUG'], // Buginese
+        ['BG', 'BUL'], // Bulgarian
+        ['MY', 'BUR'], // Burmese
+        ['', 'BYN'], // Blin; Bilin
+        ['', 'CAD'], // Caddo
+        ['', 'CAI'], // Central American Indian languages
+        ['', 'CAR'], // Galibi Carib
+        ['CA', 'CAT'], // Catalan; Valencian
+        ['', 'CAU'], // Caucasian languages
+        ['', 'CEB'], // Cebuano
+        ['', 'CEL'], // Celtic languages
+        ['CH', 'CHA'], // Chamorro
+        ['', 'CHB'], // Chibcha
+        ['CE', 'CHE'], // Chechen
+        ['', 'CHG'], // Chagatai
+        ['ZH', 'CHI'], // Chinese
+        ['', 'CHK'], // Chuukese
+        ['', 'CHM'], // Mari
+        ['', 'CHN'], // Chinook jargon
+        ['', 'CHO'], // Choctaw
+        ['', 'CHP'], // Chipewyan; Dene Suline
+        ['', 'CHR'], // Cherokee
+        ['CU', 'CHU'], // Church Slavic; Old Slavonic; Church Slavonic; Old Bulgarian; Old Church Slavonic
+        ['CV', 'CHV'], // Chuvash
+        ['', 'CHY'], // Cheyenne
+        ['', 'CMC'], // Chamic languages
+        ['', 'CNR'], // Montenegrin
+        ['', 'COP'], // Coptic
+        ['KW', 'COR'], // Cornish
+        ['CO', 'COS'], // Corsican
+        ['', 'CPE'], // Creoles and pidgins, English based
+        ['', 'CPF'], // Creoles and pidgins, French-based 
+        ['', 'CPP'], // Creoles and pidgins, Portuguese-based 
+        ['CR', 'CRE'], // Cree
+        ['', 'CRH'], // Crimean Tatar; Crimean Turkish
+        ['', 'CRP'], // Creoles and pidgins 
+        ['', 'CSB'], // Kashubian
+        ['', 'CUS'], // Cushitic languages
+        ['CS', 'CZE'], // Czech
+        ['', 'DAK'], // Dakota
+        ['DA', 'DAN'], // Danish
+        ['', 'DAR'], // Dargwa
+        ['', 'DAY'], // Land Dayak languages
+        ['', 'DEL'], // Delaware
+        ['', 'DEN'], // Slave (Athapascan)
+        ['', 'DGR'], // Dogrib
+        ['', 'DIN'], // Dinka
+        ['DV', 'DIV'], // Divehi; Dhivehi; Maldivian
+        ['', 'DOI'], // Dogri
+        ['', 'DRA'], // Dravidian languages
+        ['', 'DSB'], // Lower Sorbian
+        ['', 'DUA'], // Duala
+        ['', 'DUM'], // Dutch, Middle (ca.1050-1350)
+        ['NL', 'DUT'], // Dutch; Flemish
+        ['', 'DYU'], // Dyula
+        ['DZ', 'DZO'], // Dzongkha
+        ['', 'EFI'], // Efik
+        ['', 'EGY'], // Egyptian (Ancient)
+        ['', 'EKA'], // Ekajuk
+        ['', 'ELX'], // Elamite
+        ['EN', 'ENG'], // English
+        ['', 'ENM'], // English, Middle (1100-1500)
+        ['EO', 'EPO'], // Esperanto
+        ['ET', 'EST'], // Estonian
+        ['EE', 'EWE'], // Ewe
+        ['', 'EWO'], // Ewondo
+        ['', 'FAN'], // Fang
+        ['FO', 'FAO'], // Faroese
+        ['', 'FAT'], // Fanti
+        ['FJ', 'FIJ'], // Fijian
+        ['', 'FIL'], // Filipino; Pilipino
+        ['FI', 'FIN'], // Finnish
+        ['', 'FIU'], // Finno-Ugrian languages
+        ['', 'FON'], // Fon
+        ['FR', 'FRE'], // French
+        ['', 'FRM'], // French, Middle (ca.1400-1600)
+        ['', 'FRO'], // French, Old (842-ca.1400)
+        ['', 'FRR'], // Northern Frisian
+        ['', 'FRS'], // Eastern Frisian
+        ['FY', 'FRY'], // Western Frisian
+        ['FF', 'FUL'], // Fulah
+        ['', 'FUR'], // Friulian
+        ['', 'GAA'], // Ga
+        ['', 'GAY'], // Gayo
+        ['', 'GBA'], // Gbaya
+        ['', 'GEM'], // Germanic languages
+        ['KA', 'GEO'], // Georgian
+        ['DE', 'GER'], // German
+        ['', 'GEZ'], // Geez
+        ['', 'GIL'], // Gilbertese
+        ['GD', 'GLA'], // Gaelic; Scottish Gaelic
+        ['GA', 'GLE'], // Irish
+        ['GL', 'GLG'], // Galician
+        ['GV', 'GLV'], // Manx
+        ['', 'GMH'], // German, Middle High (ca.1050-1500)
+        ['', 'GOH'], // German, Old High (ca.750-1050)
+        ['', 'GON'], // Gondi
+        ['', 'GOR'], // Gorontalo
+        ['', 'GOT'], // Gothic
+        ['', 'GRB'], // Grebo
+        ['', 'GRC'], // Greek, Ancient (to 1453)
+        ['EL', 'GRE'], // Greek, Modern (1453-)
+        ['GN', 'GRN'], // Guarani
+        ['', 'GSW'], // Swiss German; Alemannic; Alsatian
+        ['GU', 'GUJ'], // Gujarati
+        ['', 'GWI'], // Gwich'in
+        ['', 'HAI'], // Haida
+        ['HT', 'HAT'], // Haitian; Haitian Creole
+        ['HA', 'HAU'], // Hausa
+        ['', 'HAW'], // Hawaiian
+        ['HE', 'HEB'], // Hebrew
+        ['HZ', 'HER'], // Herero
+        ['', 'HIL'], // Hiligaynon
+        ['', 'HIM'], // Himachali languages; Western Pahari languages
+        ['HI', 'HIN'], // Hindi
+        ['', 'HIT'], // Hittite
+        ['', 'HMN'], // Hmong; Mong
+        ['HO', 'HMO'], // Hiri Motu
+        ['HR', 'HRV'], // Croatian
+        ['', 'HSB'], // Upper Sorbian
+        ['HU', 'HUN'], // Hungarian
+        ['', 'HUP'], // Hupa
+        ['', 'IBA'], // Iban
+        ['IG', 'IBO'], // Igbo
+        ['IS', 'ICE'], // Icelandic
+        ['IO', 'IDO'], // Ido
+        ['II', 'III'], // Sichuan Yi; Nuosu
+        ['', 'IJO'], // Ijo languages
+        ['IU', 'IKU'], // Inuktitut
+        ['IE', 'ILE'], // Interlingue; Occidental
+        ['', 'ILO'], // Iloko
+        ['IA', 'INA'], // Interlingua (International Auxiliary Language Association)
+        ['', 'INC'], // Indic languages
+        ['ID', 'IND'], // Indonesian
+        ['', 'INE'], // Indo-European languages
+        ['', 'INH'], // Ingush
+        ['IK', 'IPK'], // Inupiaq
+        ['', 'IRA'], // Iranian languages
+        ['', 'IRO'], // Iroquoian languages
+        ['IT', 'ITA'], // Italian
+        ['JV', 'JAV'], // Javanese
+        ['', 'JBO'], // Lojban
+        ['JA', 'JPN'], // Japanese
+        ['', 'JPR'], // Judeo-Persian
+        ['', 'JRB'], // Judeo-Arabic
+        ['', 'KAA'], // Kara-Kalpak
+        ['', 'KAB'], // Kabyle
+        ['', 'KAC'], // Kachin; Jingpho
+        ['KL', 'KAL'], // Kalaallisut; Greenlandic
+        ['', 'KAM'], // Kamba
+        ['KN', 'KAN'], // Kannada
+        ['', 'KAR'], // Karen languages
+        ['KS', 'KAS'], // Kashmiri
+        ['KR', 'KAU'], // Kanuri
+        ['', 'KAW'], // Kawi
+        ['KK', 'KAZ'], // Kazakh
+        ['', 'KBD'], // Kabardian
+        ['', 'KHA'], // Khasi
+        ['', 'KHI'], // Khoisan languages
+        ['KM', 'KHM'], // Central Khmer
+        ['', 'KHO'], // Khotanese; Sakan
+        ['KI', 'KIK'], // Kikuyu; Gikuyu
+        ['RW', 'KIN'], // Kinyarwanda
+        ['KY', 'KIR'], // Kirghiz; Kyrgyz
+        ['', 'KMB'], // Kimbundu
+        ['', 'KOK'], // Konkani
+        ['KV', 'KOM'], // Komi
+        ['KG', 'KON'], // Kongo
+        ['KO', 'KOR'], // Korean
+        ['', 'KOS'], // Kosraean
+        ['', 'KPE'], // Kpelle
+        ['', 'KRC'], // Karachay-Balkar
+        ['', 'KRL'], // Karelian
+        ['', 'KRO'], // Kru languages
+        ['', 'KRU'], // Kurukh
+        ['KJ', 'KUA'], // Kuanyama; Kwanyama
+        ['', 'KUM'], // Kumyk
+        ['KU', 'KUR'], // Kurdish
+        ['', 'KUT'], // Kutenai
+        ['', 'LAD'], // Ladino
+        ['', 'LAH'], // Lahnda
+        ['', 'LAM'], // Lamba
+        ['LO', 'LAO'], // Lao
+        ['LA', 'LAT'], // Latin
+        ['LV', 'LAV'], // Latvian
+        ['', 'LEZ'], // Lezghian
+        ['LI', 'LIM'], // Limburgan; Limburger; Limburgish
+        ['LN', 'LIN'], // Lingala
+        ['LT', 'LIT'], // Lithuanian
+        ['', 'LOL'], // Mongo
+        ['', 'LOZ'], // Lozi
+        ['LB', 'LTZ'], // Luxembourgish; Letzeburgesch
+        ['', 'LUA'], // Luba-Lulua
+        ['LU', 'LUB'], // Luba-Katanga
+        ['LG', 'LUG'], // Ganda
+        ['', 'LUI'], // Luiseno
+        ['', 'LUN'], // Lunda
+        ['', 'LUO'], // Luo (Kenya and Tanzania)
+        ['', 'LUS'], // Lushai
+        ['MK', 'MAC'], // Macedonian
+        ['', 'MAD'], // Madurese
+        ['', 'MAG'], // Magahi
+        ['MH', 'MAH'], // Marshallese
+        ['', 'MAI'], // Maithili
+        ['', 'MAK'], // Makasar
+        ['ML', 'MAL'], // Malayalam
+        ['', 'MAN'], // Mandingo
+        ['MI', 'MAO'], // Maori
+        ['', 'MAP'], // Austronesian languages
+        ['MR', 'MAR'], // Marathi
+        ['', 'MAS'], // Masai
+        ['MS', 'MAY'], // Malay
+        ['', 'MDF'], // Moksha
+        ['', 'MDR'], // Mandar
+        ['', 'MEN'], // Mende
+        ['', 'MGA'], // Irish, Middle (900-1200)
+        ['', 'MIC'], // Mi'kmaq; Micmac
+        ['', 'MIN'], // Minangkabau
+        ['', 'MIS'], // Uncoded languages
+        ['', 'MKH'], // Mon-Khmer languages
+        ['MG', 'MLG'], // Malagasy
+        ['MT', 'MLT'], // Maltese
+        ['', 'MNC'], // Manchu
+        ['', 'MNI'], // Manipuri
+        ['', 'MNO'], // Manobo languages
+        ['', 'MOH'], // Mohawk
+        ['MN', 'MON'], // Mongolian
+        ['', 'MOS'], // Mossi
+        ['', 'MUL'], // Multiple languages
+        ['', 'MUN'], // Munda languages
+        ['', 'MUS'], // Creek
+        ['', 'MWL'], // Mirandese
+        ['', 'MWR'], // Marwari
+        ['', 'MYN'], // Mayan languages
+        ['', 'MYV'], // Erzya
+        ['', 'NAH'], // Nahuatl languages
+        ['', 'NAI'], // North American Indian languages
+        ['', 'NAP'], // Neapolitan
+        ['NA', 'NAU'], // Nauru
+        ['NV', 'NAV'], // Navajo; Navaho
+        ['NR', 'NBL'], // Ndebele, South; South Ndebele
+        ['ND', 'NDE'], // Ndebele, North; North Ndebele
+        ['NG', 'NDO'], // Ndonga
+        ['', 'NDS'], // Low German; Low Saxon; German, Low; Saxon, Low
+        ['NE', 'NEP'], // Nepali
+        ['', 'NEW'], // Nepal Bhasa; Newari
+        ['', 'NIA'], // Nias
+        ['', 'NIC'], // Niger-Kordofanian languages
+        ['', 'NIU'], // Niuean
+        ['NN', 'NNO'], // Norwegian Nynorsk; Nynorsk, Norwegian
+        ['NB', 'NOB'], // Bokmål, Norwegian; Norwegian Bokmål
+        ['', 'NOG'], // Nogai
+        ['', 'NON'], // Norse, Old
+        ['NO', 'NOR'], // Norwegian
+        ['', 'NQO'], // N'Ko
+        ['', 'NSO'], // Pedi; Sepedi; Northern Sotho
+        ['', 'NUB'], // Nubian languages
+        ['', 'NWC'], // Classical Newari; Old Newari; Classical Nepal Bhasa
+        ['NY', 'NYA'], // Chichewa; Chewa; Nyanja
+        ['', 'NYM'], // Nyamwezi
+        ['', 'NYN'], // Nyankole
+        ['', 'NYO'], // Nyoro
+        ['', 'NZI'], // Nzima
+        ['OC', 'OCI'], // Occitan (post 1500); Provençal
+        ['OJ', 'OJI'], // Ojibwa
+        ['OR', 'ORI'], // Oriya
+        ['OM', 'ORM'], // Oromo
+        ['', 'OSA'], // Osage
+        ['OS', 'OSS'], // Ossetian; Ossetic
+        ['', 'OTA'], // Turkish, Ottoman (1500-1928)
+        ['', 'OTO'], // Otomian languages
+        ['', 'PAA'], // Papuan languages
+        ['', 'PAG'], // Pangasinan
+        ['', 'PAL'], // Pahlavi
+        ['', 'PAM'], // Pampanga; Kapampangan
+        ['PA', 'PAN'], // Panjabi; Punjabi
+        ['', 'PAP'], // Papiamento
+        ['', 'PAU'], // Palauan
+        ['', 'PEO'], // Persian, Old (ca.600-400 B.C.)
+        ['FA', 'PER'], // Persian
+        ['', 'PHI'], // Philippine languages
+        ['', 'PHN'], // Phoenician
+        ['PI', 'PLI'], // Pali
+        ['PL', 'POL'], // Polish
+        ['', 'PON'], // Pohnpeian
+        ['PT', 'POR'], // Portuguese
+        ['', 'PRA'], // Prakrit languages
+        ['', 'PRO'], // Provençal, Old (to 1500)
+        ['PS', 'PUS'], // Pushto; Pashto
+        ['', 'QAAQTZ'], // Reserved for local use
+        ['QU', 'QUE'], // Quechua
+        ['', 'RAJ'], // Rajasthani
+        ['', 'RAP'], // Rapanui
+        ['', 'RAR'], // Rarotongan; Cook Islands Maori
+        ['', 'ROA'], // Romance languages
+        ['RM', 'ROH'], // Romansh
+        ['', 'ROM'], // Romany
+        ['RO', 'RUM'], // Romanian; Moldavian; Moldovan
+        ['RN', 'RUN'], // Rundi
+        ['', 'RUP'], // Aromanian; Arumanian; Macedo-Romanian
+        ['RU', 'RUS'], // Russian
+        ['', 'SAD'], // Sandawe
+        ['SG', 'SAG'], // Sango
+        ['', 'SAH'], // Yakut
+        ['', 'SAI'], // South American Indian (Other)
+        ['', 'SAL'], // Salishan languages
+        ['', 'SAM'], // Samaritan Aramaic
+        ['SA', 'SAN'], // Sanskrit
+        ['', 'SAS'], // Sasak
+        ['', 'SAT'], // Santali
+        ['', 'SCN'], // Sicilian
+        ['', 'SCO'], // Scots
+        ['', 'SEL'], // Selkup
+        ['', 'SEM'], // Semitic languages
+        ['', 'SGA'], // Irish, Old (to 900)
+        ['', 'SGN'], // Sign Languages
+        ['', 'SHN'], // Shan
+        ['', 'SID'], // Sidamo
+        ['SI', 'SIN'], // Sinhala; Sinhalese
+        ['', 'SIO'], // Siouan languages
+        ['', 'SIT'], // Sino-Tibetan languages
+        ['', 'SLA'], // Slavic languages
+        ['SK', 'SLO'], // Slovak
+        ['SL', 'SLV'], // Slovenian
+        ['', 'SMA'], // Southern Sami
+        ['SE', 'SME'], // Northern Sami
+        ['', 'SMI'], // Sami languages
+        ['', 'SMJ'], // Lule Sami
+        ['', 'SMN'], // Inari Sami
+        ['SM', 'SMO'], // Samoan
+        ['', 'SMS'], // Skolt Sami
+        ['SN', 'SNA'], // Shona
+        ['SD', 'SND'], // Sindhi
+        ['', 'SNK'], // Soninke
+        ['', 'SOG'], // Sogdian
+        ['SO', 'SOM'], // Somali
+        ['', 'SON'], // Songhai languages
+        ['ST', 'SOT'], // Sotho, Southern
+        ['ES', 'SPA'], // Spanish; Castilian
+        ['SC', 'SRD'], // Sardinian
+        ['', 'SRN'], // Sranan Tongo
+        ['SR', 'SRP'], // Serbian
+        ['', 'SRR'], // Serer
+        ['', 'SSA'], // Nilo-Saharan languages
+        ['SS', 'SSW'], // Swati
+        ['', 'SUK'], // Sukuma
+        ['SU', 'SUN'], // Sundanese
+        ['', 'SUS'], // Susu
+        ['', 'SUX'], // Sumerian
+        ['SW', 'SWA'], // Swahili
+        ['SV', 'SWE'], // Swedish
+        ['', 'SYC'], // Classical Syriac
+        ['', 'SYR'], // Syriac
+        ['TY', 'TAH'], // Tahitian
+        ['', 'TAI'], // Tai languages
+        ['TA', 'TAM'], // Tamil
+        ['TT', 'TAT'], // Tatar
+        ['TE', 'TEL'], // Telugu
+        ['', 'TEM'], // Timne
+        ['', 'TER'], // Tereno
+        ['', 'TET'], // Tetum
+        ['TG', 'TGK'], // Tajik
+        ['TL', 'TGL'], // Tagalog
+        ['TH', 'THA'], // Thai
+        ['BO', 'TIB'], // Tibetan
+        ['', 'TIG'], // Tigre
+        ['TI', 'TIR'], // Tigrinya
+        ['', 'TIV'], // Tiv
+        ['', 'TKL'], // Tokelau
+        ['', 'TLH'], // Klingon; tlhIngan-Hol
+        ['', 'TLI'], // Tlingit
+        ['', 'TMH'], // Tamashek
+        ['', 'TOG'], // Tonga (Nyasa)
+        ['TO', 'TON'], // Tonga (Tonga Islands)
+        ['', 'TPI'], // Tok Pisin
+        ['', 'TSI'], // Tsimshian
+        ['TN', 'TSN'], // Tswana
+        ['TS', 'TSO'], // Tsonga
+        ['TK', 'TUK'], // Turkmen
+        ['', 'TUM'], // Tumbuka
+        ['', 'TUP'], // Tupi languages
+        ['TR', 'TUR'], // Turkish
+        ['', 'TUT'], // Altaic languages
+        ['', 'TVL'], // Tuvalu
+        ['TW', 'TWI'], // Twi
+        ['', 'TYV'], // Tuvinian
+        ['', 'UDM'], // Udmurt
+        ['', 'UGA'], // Ugaritic
+        ['UG', 'UIG'], // Uighur; Uyghur
+        ['UK', 'UKR'], // Ukrainian
+        ['', 'UMB'], // Umbundu
+        ['', 'UND'], // Undetermined
+        ['UR', 'URD'], // Urdu
+        ['UZ', 'UZB'], // Uzbek
+        ['', 'VAI'], // Vai
+        ['VE', 'VEN'], // Venda
+        ['VI', 'VIE'], // Vietnamese
+        ['VO', 'VOL'], // Volapük
+        ['', 'VOT'], // Votic
+        ['', 'WAK'], // Wakashan languages
+        ['', 'WAL'], // Walamo
+        ['', 'WAR'], // Waray
+        ['', 'WAS'], // Washo
+        ['CY', 'WEL'], // Welsh
+        ['', 'WEN'], // Sorbian languages
+        ['WA', 'WLN'], // Walloon
+        ['WO', 'WOL'], // Wolof
+        ['', 'XAL'], // Kalmyk; Oirat
+        ['XH', 'XHO'], // Xhosa
+        ['', 'YAO'], // Yao
+        ['', 'YAP'], // Yapese
+        ['YI', 'YID'], // Yiddish
+        ['YO', 'YOR'], // Yoruba
+        ['', 'YPK'], // Yupik languages
+        ['', 'ZAP'], // Zapotec
+        ['', 'ZBL'], // Blissymbols; Blissymbolics; Bliss
+        ['', 'ZEN'], // Zenaga
+        ['', 'ZGH'], // Standard Moroccan Tamazight
+        ['ZA', 'ZHA'], // Zhuang; Chuang
+        ['', 'ZND'], // Zande languages
+        ['ZU', 'ZUL'], // Zulu
+        ['', 'ZUN'], // Zuni
+        ['', 'ZXX'], // No linguistic content; Not applicable
     ];
 
     public $set;
diff --git a/vendor/respect/validation/library/Rules/PostalCode.php b/vendor/respect/validation/library/Rules/PostalCode.php
index ebdba1670df89a07ff571adaa06fb5277a3b6fc0..41ab10499da51d5dfd59226e7c514b0c1d460fe0 100644
--- a/vendor/respect/validation/library/Rules/PostalCode.php
+++ b/vendor/respect/validation/library/Rules/PostalCode.php
@@ -81,7 +81,7 @@ class PostalCode extends Regex
         'HT' => '/^(?:HT)*(\d{4})$/',
         'HU' => '/^(\d{4})$/',
         'ID' => '/^(\d{5})$/',
-        'IE' => '/^[A-Z]\d{2}$|^[A-Z]{3}[A-Z]{4}$/',
+        'IE' => '/^([AC-FHKNPRTV-Y][0-9]{2}|D6W) ?[0-9AC-FHKNPRTV-Y]{4}$/',
         'IL' => '/^(\d{5})$/',
         'IM' => '/^((?:(?:[A-PR-UWYZ][A-HK-Y]\d[ABEHMNPRV-Y0-9]|[A-PR-UWYZ]\d[A-HJKPS-UW0-9])\s\d[ABD-HJLNP-UW-Z]{2})|GIR\s?0AA)$/',
         'IN' => '/^(\d{6})$/',
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/AdSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/AdSubdivisionCode.php
index 1b836dad6c9fb33618874e29ba19f6fcc3c57081..7bf8f672804bbcdc2fba6abe6d74c2e9452ea079 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/AdSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/AdSubdivisionCode.php
@@ -18,7 +18,7 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: AD
  *
- * @link http://www.geonames.org/AD/administrative-division-andorra.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class AdSubdivisionCode extends AbstractSearcher
 {
@@ -27,7 +27,7 @@ class AdSubdivisionCode extends AbstractSearcher
         '03', // Encamp
         '04', // La Massana
         '05', // Ordino
-        '06', // Sant Julia de Lòria
+        '06', // Sant Julià de Lòria
         '07', // Andorra la Vella
         '08', // Escaldes-Engordany
     ];
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/AeSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/AeSubdivisionCode.php
index 3a42ea17c074a4c5a91c028744040ec5e507dfed..bbedb700933ced2d16072277fcaf3636d79b889a 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/AeSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/AeSubdivisionCode.php
@@ -18,17 +18,17 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: AE
  *
- * @link http://www.geonames.org/AE/administrative-division-united-arab-emirates.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class AeSubdivisionCode extends AbstractSearcher
 {
     public $haystack = [
-        'AJ', // 'Ajman
-        'AZ', // Abu Zaby
+        'AJ', // 'Ajmān
+        'AZ', // Abū Ȥaby [Abu Dhabi]
         'DU', // Dubayy
         'FU', // Al Fujayrah
-        'RK', // R'as al Khaymah
-        'SH', // Ash Shariqah
+        'RK', // Ra’s al Khaymah
+        'SH', // Ash Shāriqah
         'UQ', // Umm al Qaywayn
     ];
 
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/AfSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/AfSubdivisionCode.php
index 1bec67bfdd55e18fe83142e6d25ca8ec15531809..a8c2c5abe791b7f09efe79d8047cf3eafdf2aae0 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/AfSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/AfSubdivisionCode.php
@@ -18,45 +18,45 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: AF
  *
- * @link http://www.geonames.org/AF/administrative-division-afghanistan.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class AfSubdivisionCode extends AbstractSearcher
 {
     public $haystack = [
-        'BAL', // Balkh province
-        'BAM', // Bamian province
-        'BDG', // Badghis province
-        'BDS', // Badakhshan province
-        'BGL', // Baghlan province
+        'BAL', // Balkh
+        'BAM', // Bāmyān
+        'BDG', // Bādghīs
+        'BDS', // Badakhshān
+        'BGL', // Baghlān
         'DAY', // Dāykundī
-        'FRA', // Farah province
-        'FYB', // Faryab province
-        'GHA', // Ghazni province
-        'GHO', // Ghowr province
-        'HEL', // Helmand province
-        'HER', // Herat province
-        'JOW', // Jowzjan province
-        'KAB', // Kabul province
-        'KAN', // Kandahar province
-        'KAP', // Kapisa province
-        'KDZ', // Kondoz province
-        'KHO', // Khost province
-        'KNR', // Konar province
-        'LAG', // Laghman province
-        'LOW', // Lowgar province
-        'NAN', // Nangrahar province
-        'NIM', // Nimruz province
-        'NUR', // Nurestan province
-        'ORU', // Oruzgan province
-        'PAN', // Panjshir
-        'PAR', // Parwan province
-        'PIA', // Paktia province
-        'PKA', // Paktika province
-        'SAM', // Samangan province
-        'SAR', // Sar-e Pol province
-        'TAK', // Takhar province
-        'WAR', // Wardak province
-        'ZAB', // Zabol province
+        'FRA', // Farāh
+        'FYB', // Fāryāb
+        'GHA', // Ghaznī
+        'GHO', // Ghōr
+        'HEL', // Helmand
+        'HER', // Herāt
+        'JOW', // Jowzjān
+        'KAB', // Kābul
+        'KAN', // Kandahār
+        'KAP', // Kāpīsā
+        'KDZ', // Kunduz
+        'KHO', // Khōst
+        'KNR', // Kunar
+        'LAG', // Laghmān
+        'LOG', // Lōgar
+        'NAN', // Nangarhār
+        'NIM', // Nīmrōz
+        'NUR', // Nūristān
+        'PAN', // Panjshayr
+        'PAR', // Parwān
+        'PIA', // Paktiyā
+        'PKA', // Paktīkā
+        'SAM', // Samangān
+        'SAR', // Sar-e Pul
+        'TAK', // Takhār
+        'URU', // Uruzgān
+        'WAR', // Wardak
+        'ZAB', // Zābul
     ];
 
     public $compareIdentical = true;
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/AgSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/AgSubdivisionCode.php
index 73d379d9d8b440a820e593cb98b38452a45b5bb4..b59e11ba137fcaff7e8c72b8b5f55bd4dd24ef7a 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/AgSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/AgSubdivisionCode.php
@@ -18,7 +18,7 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: AG
  *
- * @link http://www.geonames.org/AG/administrative-division-antigua-and-barbuda.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class AgSubdivisionCode extends AbstractSearcher
 {
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/AiSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/AiSubdivisionCode.php
index e2b23128140055df151275745efa1594c8b7af76..28cb0b120fe8db3b71f099af46b76df7db366fd2 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/AiSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/AiSubdivisionCode.php
@@ -18,7 +18,7 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: AI
  *
- * @link http://www.geonames.org/AI/administrative-division-anguilla.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class AiSubdivisionCode extends AbstractSearcher
 {
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/AlSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/AlSubdivisionCode.php
index 97ac19fe2b91a656c935904363631599a97d6c14..52e0edbd443e5ac03a45220f01652c46a09c6313 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/AlSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/AlSubdivisionCode.php
@@ -18,59 +18,59 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: AL
  *
- * @link http://www.geonames.org/AL/administrative-division-albania.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class AlSubdivisionCode extends AbstractSearcher
 {
     public $haystack = [
         '01', // Berat
-        '02', // Durres
+        '02', // Durrës
         '03', // Elbasan
         '04', // Fier
-        '05', // Gjirokaster
-        '06', // Korce
-        '07', // Kukes
-        '08', // Lezhe
-        '09', // Diber
-        '10', // Shkoder
-        '11', // Tirane
-        '12', // Vlore
+        '05', // Gjirokastër
+        '06', // Korçë
+        '07', // Kukës
+        '08', // Lezhë
+        '09', // Dibër
+        '10', // Shkodër
+        '11', // Tiranë
+        '12', // Vlorë
         'BR', // Berat
-        'BU', // Bulqize
-        'DI', // Diber
-        'DL', // Delvine
-        'DR', // Durres
+        'BU', // Bulqizë
+        'DI', // Dibër
+        'DL', // Delvinë
+        'DR', // Durrës
         'DV', // Devoll
         'EL', // Elbasan
-        'ER', // Kolonje
+        'ER', // Kolonjë
         'FR', // Fier
-        'GJ', // Gjirokaster
+        'GJ', // Gjirokastër
         'GR', // Gramsh
         'HA', // Has
-        'KA', // Kavaje
+        'KA', // Kavajë
         'KB', // Kurbin
-        'KC', // Kucove
-        'KO', // Korce
-        'KR', // Kruje
-        'KU', // Kukes
+        'KC', // Kuçovë
+        'KO', // Korçë
+        'KR', // Krujë
+        'KU', // Kukës
         'LB', // Librazhd
-        'LE', // Lezhe
-        'LU', // Lushnje
-        'MK', // Mallakaster
-        'MM', // Malesi e Madhe
-        'MR', // Mirdite
+        'LE', // Lezhë
+        'LU', // Lushnjë
+        'MK', // Mallakastër
+        'MM', // Malësi e Madhe
+        'MR', // Mirditë
         'MT', // Mat
         'PG', // Pogradec
         'PQ', // Peqin
-        'PR', // Permet
-        'PU', // Puke
-        'SH', // Shkoder
+        'PR', // Përmet
+        'PU', // Pukë
+        'SH', // Shkodër
         'SK', // Skrapar
-        'SR', // Sarande
-        'TE', // Tepelene
-        'TP', // Tropoje
-        'TR', // Tirane
-        'VL', // Vlore
+        'SR', // Sarandë
+        'TE', // Tepelenë
+        'TP', // Tropojë
+        'TR', // Tiranë
+        'VL', // Vlorë
     ];
 
     public $compareIdentical = true;
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/AmSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/AmSubdivisionCode.php
index c8132c358a09f2c51fda7efca97bbc5e0b21ec23..acbcd07cde52c30e5833f5fbd21f5c34558bebd0 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/AmSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/AmSubdivisionCode.php
@@ -18,22 +18,22 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: AM
  *
- * @link http://www.geonames.org/AM/administrative-division-armenia.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class AmSubdivisionCode extends AbstractSearcher
 {
     public $haystack = [
-        'AG', // Aragatsotn
+        'AG', // Aragacotn
         'AR', // Ararat
         'AV', // Armavir
-        'ER', // Yerevan
-        'GR', // Geghark'unik'
+        'ER', // Erevan
+        'GR', // Gegarkunik'
         'KT', // Kotayk'
-        'LO', // Lorri
-        'SH', // Shirak
+        'LO', // Lory
+        'SH', // Sirak
         'SU', // Syunik'
-        'TV', // Tavush
-        'VD', // Vayots' Dzor
+        'TV', // Tavus
+        'VD', // Vayoc Jor
     ];
 
     public $compareIdentical = true;
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/AnSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/AnSubdivisionCode.php
index cc755ec431c61a2e2b2f9466b443cb529d2c4cc4..5e7c4845da8f4bc6e94e1a132bc0b36512c3c07c 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/AnSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/AnSubdivisionCode.php
@@ -18,7 +18,7 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: AN
  *
- * @link http://www.geonames.org/AN/administrative-division-netherlands-antilles.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class AnSubdivisionCode extends AbstractSearcher
 {
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/AoSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/AoSubdivisionCode.php
index 5d589303a89ad3645178cc6d0e173a47eb6beeb4..db69a7294384bced6c6701a2e6f622652a5c4945 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/AoSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/AoSubdivisionCode.php
@@ -18,28 +18,28 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: AO
  *
- * @link http://www.geonames.org/AO/administrative-division-angola.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class AoSubdivisionCode extends AbstractSearcher
 {
     public $haystack = [
         'BGO', // Bengo
-        'BGU', // Benguela province
-        'BIE', // Bie
+        'BGU', // Benguela
+        'BIE', // Bié
         'CAB', // Cabinda
         'CCU', // Cuando-Cubango
         'CNN', // Cunene
         'CNO', // Cuanza Norte
         'CUS', // Cuanza Sul
-        'HUA', // Huambo province
-        'HUI', // Huila province
+        'HUA', // Huambo
+        'HUI', // Huíla
         'LNO', // Lunda Norte
         'LSU', // Lunda Sul
         'LUA', // Luanda
         'MAL', // Malange
         'MOX', // Moxico
         'NAM', // Namibe
-        'UIG', // Uige
+        'UIG', // Uíge
         'ZAI', // Zaire
     ];
 
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/AqSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/AqSubdivisionCode.php
index 2fe6a6db4adb018bbef7f16e5664a43463e96cd0..4370e667590eac737c90a49bb55d3f1f961317cd 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/AqSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/AqSubdivisionCode.php
@@ -18,7 +18,7 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: AQ
  *
- * @link http://www.geonames.org/AQ/administrative-division-antarctica.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class AqSubdivisionCode extends AbstractSearcher
 {
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/ArSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/ArSubdivisionCode.php
index 204ce8af76f173f66448bd0cb96e07a93ef87978..876d43ec09cc31b478caccc4072154644c9c426e 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/ArSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/ArSubdivisionCode.php
@@ -18,17 +18,16 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: AR
  *
- * @link http://www.geonames.org/AR/administrative-division-argentina.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class ArSubdivisionCode extends AbstractSearcher
 {
     public $haystack = [
         'A', // Salta
-        'B', // Buenos Aires Province
+        'B', // Buenos Aires
         'C', // Ciudad Autónoma de Buenos Aires
         'D', // San Luis
         'E', // Entre Rios
-        'F', // La Rioja
         'G', // Santiago del Estero
         'H', // Chaco
         'J', // San Juan
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/AsSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/AsSubdivisionCode.php
index a8dd9c85018be97f8b9063fa5b61fb10ca272883..39c1a840252b67f832bd0f6d8746dd6bed3afd14 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/AsSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/AsSubdivisionCode.php
@@ -18,7 +18,7 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: AS
  *
- * @link http://www.geonames.org/AS/administrative-division-american-samoa.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class AsSubdivisionCode extends AbstractSearcher
 {
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/AtSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/AtSubdivisionCode.php
index 77e64b2716de363052196ce0731c4561adea217c..bbc851edea038c02599b24e37a6a70063eeef0a7 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/AtSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/AtSubdivisionCode.php
@@ -18,15 +18,15 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: AT
  *
- * @link http://www.geonames.org/AT/administrative-division-austria.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class AtSubdivisionCode extends AbstractSearcher
 {
     public $haystack = [
         '1', // Burgenland
-        '2', // Karnten
-        '3', // Niederosterreich
-        '4', // Oberosterreich
+        '2', // Kärnten
+        '3', // Niederösterreich
+        '4', // Oberösterreich
         '5', // Salzburg
         '6', // Steiermark
         '7', // Tirol
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/AuSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/AuSubdivisionCode.php
index db52e3718ff5b69962cff6f68171668a3f3ced8c..15aa0d41f6cad3a0c428a12b130ce1937525ce72 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/AuSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/AuSubdivisionCode.php
@@ -18,7 +18,7 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: AU
  *
- * @link http://www.geonames.org/AU/administrative-division-australia.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class AuSubdivisionCode extends AbstractSearcher
 {
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/AwSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/AwSubdivisionCode.php
index 575424de58b5cb6b6d05de8c91a9fcbbeb2a0bb4..9abc18ed4ff639ad57e2d4d8e9c2550a0de1832a 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/AwSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/AwSubdivisionCode.php
@@ -18,7 +18,7 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: AW
  *
- * @link http://www.geonames.org/AW/administrative-division-aruba.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class AwSubdivisionCode extends AbstractSearcher
 {
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/AxSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/AxSubdivisionCode.php
index 0041a6c204b12e71d02bea4493cff9b227769356..e550add57b2172ad39f701631d78e305c796212e 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/AxSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/AxSubdivisionCode.php
@@ -18,7 +18,7 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: AX
  *
- * @link http://www.geonames.org/AX/administrative-division-aland.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class AxSubdivisionCode extends AbstractSearcher
 {
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/AzSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/AzSubdivisionCode.php
index 05d6239f211f325aaa4aa09ee85a344186cb8d3a..2e9e1bf3003216845565114e5fcf4acc9e409a41 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/AzSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/AzSubdivisionCode.php
@@ -18,90 +18,89 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: AZ
  *
- * @link http://www.geonames.org/AZ/administrative-division-azerbaijan.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class AzSubdivisionCode extends AbstractSearcher
 {
     public $haystack = [
-        'AB', // Åžirvan
-        'ABS', // Abseron
-        'AGA', // Agstafa
-        'AGC', // AgcabAdi
-        'AGM', // Agdam
-        'AGS', // Agdas
-        'AGU', // Agsu
+        'ABS', // AbÅŸeron
+        'AGA', // AÄŸstafa
+        'AGC', // Ağcabədi
+        'AGM', // AÄŸdam
+        'AGS', // AÄŸdaÅŸ
+        'AGU', // AÄŸsu
         'AST', // Astara
-        'BA', // Baki
-        'BAL', // BalakAn
-        'BAR', // Barda
-        'BEY', // Beylaqan
-        'BIL', // Bilasuvar
-        'CAB', // Cabrayil
-        'CAL', // Calilabab
-        'DAS', // Daskasan
-        'DAV', // Åžabran
-        'FUZ', // Fuzuli
-        'GA', // Ganca
-        'GAD', // Gadabay
+        'BA', // Bakı
+        'BAB', // Babək
+        'BAL', // Balakən
+        'BAR', // Bərdə
+        'BEY', // Beyləqan
+        'BIL', // Biləsuvar
+        'CAB', // Cəbrayıl
+        'CAL', // Cəlilabab
+        'CUL', // Culfa
+        'DAS', // Daşkəsən
+        'FUZ', // Füzuli
+        'GA', // Gəncə
+        'GAD', // Gədəbəy
         'GOR', // Goranboy
-        'GOY', // Goycay
-        'HAC', // Haciqabul
-        'IMI', // Imisli
-        'ISM', // Ismayilli
-        'KAL', // Kalbacar
-        'KAN', // Kəngərli
-        'KUR', // Kurdamir
-        'LA', // Lankaran
-        'LAC', // Lacin
-        'LAN', // Lankaran Sahari
+        'GOY', // Göyçay
+        'GYG', // Göygöl
+        'HAC', // Hacıqabul
+        'IMI', // Ä°miÅŸli
+        'ISM', // İsmayıllı
+        'KAL', // Kəlbəcər
+        'KAN', // Kǝngǝrli
+        'KUR', // Kürdəmir
+        'LA', // Lənkəran
+        'LAC', // Laçın
+        'LAN', // Lənkəran
         'LER', // Lerik
-        'MAS', // Masalli
+        'MAS', // Masallı
         'MI', // Mingəçevir
         'NA', // Naftalan
-        'NEF', // Neftcala
-        'NV', // Naxçivan
-        'NX', // Naxcivan
-        'OGU', // Oguz
-        'QAB', // Qabala
+        'NEF', // Neftçala
+        'NV', // Naxçıvan
+        'NX', // Naxçıvan
+        'OGU', // OÄŸuz
+        'ORD', // Ordubad
+        'QAB', // Qəbələ
         'QAX', // Qax
         'QAZ', // Qazax
         'QBA', // Quba
-        'QBI', // Qubadli
+        'QBI', // Qubadlı
         'QOB', // Qobustan
         'QUS', // Qusar
-        'SA', // Saki
+        'SA', // Şəki
         'SAB', // Sabirabad
-        'SAK', // Saki Sahari
+        'SAD', // Sədərək
+        'SAH', // Åžahbuz
+        'SAK', // Şəki
         'SAL', // Salyan
-        'SAT', // Saatli
-        'SIY', // Siyazan
-        'SKR', // Samkir
-        'SM', // Sumqayit
-        'SMI', // Samaxi
+        'SAR', // Şərur
+        'SAT', // Saatlı
+        'SBN', // Åžabran
+        'SIY', // Siyəzən
+        'SKR', // Şəmkir
+        'SM', // Sumqayıt
+        'SMI', // Şamaxı
         'SMX', // Samux
-        'SS', // Susa
-        'SUS', // Susa Sahari
-        'TAR', // Tartar
+        'SR', // Åžirvan
+        'SUS', // ÅžuÅŸa
+        'TAR', // Tərtər
         'TOV', // Tovuz
         'UCA', // Ucar
-        'XA', // Xankandi
-        'XAC', // Xacmaz
-        'XAN', // Göygöl
-        'XCI', // Xocali
-        'XIZ', // Xizi
-        'XVD', // Xocavand
-        'YAR', // Yardimli
-        'YE', // Yevlax Sahari
+        'XA', // Xankəndi
+        'XAC', // Xaçmaz
+        'XCI', // Xocalı
+        'XIZ', // Xızı
+        'XVD', // Xocavənd
+        'YAR', // Yardımlı
+        'YE', // Yevlax
         'YEV', // Yevlax
-        'ZAN', // Zangilan
+        'ZAN', // Zəngilan
         'ZAQ', // Zaqatala
-        'ZAR', // Zardab
-        'BAB', // Babek
-        'CUL', // Culfa
-        'ORD', // Ordubad
-        'SAD', // Sadarak
-        'SAH', // Sahbuz
-        'SAR', // Sarur
+        'ZAR', // Zərdab
     ];
 
     public $compareIdentical = true;
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/BaSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/BaSubdivisionCode.php
index 53e08a33a2bb5143798be346378aeed5693d82b1..43f6600c7708dbf4b3176e63dacc27ee54418116 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/BaSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/BaSubdivisionCode.php
@@ -18,24 +18,24 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: BA
  *
- * @link http://www.geonames.org/BA/administrative-division-bosnia-and-herzegovina.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class BaSubdivisionCode extends AbstractSearcher
 {
     public $haystack = [
-        'BIH', // Federacija Bosna i Hercegovina
-        'BRC', // Brcko District
-        'SRP', // Republika Srpska
         '01', // Unsko-sanski kanton
         '02', // Posavski kanton
         '03', // Tuzlanski kanton
         '04', // Zeničko-dobojski kanton
         '05', // Bosansko-podrinjski kanton
-        '06', // Srednjobosanski kantonn
+        '06', // Srednjobosanski kanton
         '07', // Hercegovačko-neretvanski kanton
         '08', // Zapadnohercegovački kanton
         '09', // Kanton Sarajevo
         '10', // Kanton br. 10 (Livanjski kanton)
+        'BIH', // Federacija Bosne i Hercegovine
+        'BRC', // Brčko distrikt
+        'SRP', // Republika Srpska
     ];
 
     public $compareIdentical = true;
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/BbSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/BbSubdivisionCode.php
index 2ab08369659cc5884f9553d03581422fe1d2aba7..a2215a1f7d1cf44212efeca3b1e2d1688ce086a9 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/BbSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/BbSubdivisionCode.php
@@ -18,7 +18,7 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: BB
  *
- * @link http://www.geonames.org/BB/administrative-division-barbados.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class BbSubdivisionCode extends AbstractSearcher
 {
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/BdSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/BdSubdivisionCode.php
index 270c9450e7e64c0ed6feec2320d882ee73e53d6f..0dfa1fc89cab0aeb30151c309492db772a81f778 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/BdSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/BdSubdivisionCode.php
@@ -18,11 +18,75 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: BD
  *
- * @link http://www.geonames.org/BD/administrative-division-bangladesh.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class BdSubdivisionCode extends AbstractSearcher
 {
     public $haystack = [
+        '01', // Bandarban
+        '02', // Barguna
+        '03', // Bogra
+        '04', // Brahmanbaria
+        '05', // Bagerhat
+        '06', // Barisal
+        '07', // Bhola
+        '08', // Comilla
+        '09', // Chandpur
+        '10', // Chittagong
+        '11', // Cox's Bazar
+        '12', // Chuadanga
+        '13', // Dhaka
+        '14', // Dinajpur
+        '15', // Faridpur
+        '16', // Feni
+        '17', // Gopalganj
+        '18', // Gazipur
+        '19', // Gaibandha
+        '20', // Habiganj
+        '21', // Jamalpur
+        '22', // Jessore
+        '23', // Jhenaidah
+        '24', // Jaipurhat
+        '25', // Jhalakati
+        '26', // Kishorganj
+        '27', // Khulna
+        '28', // Kurigram
+        '29', // Khagrachari
+        '30', // Kushtia
+        '31', // Lakshmipur
+        '32', // Lalmonirhat
+        '33', // Manikganj
+        '34', // Mymensingh
+        '35', // Munshiganj
+        '36', // Madaripur
+        '37', // Magura
+        '38', // Moulvibazar
+        '39', // Meherpur
+        '40', // Narayanganj
+        '41', // Netrakona
+        '42', // Narsingdi
+        '43', // Narail
+        '44', // Natore
+        '45', // Nawabganj
+        '46', // Nilphamari
+        '47', // Noakhali
+        '48', // Naogaon
+        '49', // Pabna
+        '50', // Pirojpur
+        '51', // Patuakhali
+        '52', // Panchagarh
+        '53', // Rajbari
+        '54', // Rajshahi
+        '55', // Rangpur
+        '56', // Rangamati
+        '57', // Sherpur
+        '58', // Satkhira
+        '59', // Sirajganj
+        '60', // Sylhet
+        '61', // Sunamganj
+        '62', // Shariatpur
+        '63', // Tangail
+        '64', // Thakurgaon
         'A', // Barisal
         'B', // Chittagong
         'C', // Dhaka
@@ -30,70 +94,6 @@ class BdSubdivisionCode extends AbstractSearcher
         'E', // Rajshahi
         'F', // Rangpur
         'G', // Sylhet
-        '01', // Bandarban zila
-        '02', // Barguna zila
-        '03', // Bogra zila
-        '04', // Brahmanbaria zila
-        '05', // Bagerhat zila
-        '06', // Barisal zila
-        '07', // Bhola zila
-        '08', // Comilla zila
-        '09', // Chandpur zila
-        '10', // Chittagong zila
-        '11', // Cox's Bazar zila
-        '12', // Chuadanga zila
-        '13', // Dhaka zila
-        '14', // Dinajpur zila
-        '15', // Faridpur zila
-        '16', // Feni zila
-        '17', // Gopalganj zila
-        '18', // Gazipur zila
-        '19', // Gaibandha zila
-        '20', // Habiganj zila
-        '21', // Jamalpur zila
-        '22', // Jessore zila
-        '23', // Jhenaidah zila
-        '24', // Jaipurhat zila
-        '25', // Jhalakati zila
-        '26', // Kishoreganj zila
-        '27', // Khulna zila
-        '28', // Kurigram zila
-        '29', // Khagrachari zila
-        '30', // Kushtia zila
-        '31', // Lakshmipur zila
-        '32', // Lalmonirhat zila
-        '33', // Manikganj zila
-        '34', // Mymensingh zila
-        '35', // Munshiganj zila
-        '36', // Madaripur zila
-        '37', // Magura zila
-        '38', // Moulvibazar zila
-        '39', // Meherpur zila
-        '40', // Narayanganj zila
-        '41', // Netrakona zila
-        '42', // Narsingdi zila
-        '43', // Narail zila
-        '44', // Natore zila
-        '45', // Nawabganj zila
-        '46', // Nilphamari zila
-        '47', // Noakhali zila
-        '48', // Naogaon zila
-        '49', // Pabna zila
-        '50', // Pirojpur zila
-        '51', // Patuakhali zila
-        '52', // Panchagarh zila
-        '53', // Rajbari zila
-        '54', // Rajshahi zila
-        '55', // Rangpur zila
-        '56', // Rangamati zila
-        '57', // Sherpur zila
-        '58', // Satkhira zila
-        '59', // Sirajganj zila
-        '60', // Sylhet zila
-        '61', // Sunamganj zila
-        '62', // Shariatpur zila
-        '63', // Tangail zila
-        '64', // Thakurgaon zila
     ];
 
     public $compareIdentical = true;
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/BeSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/BeSubdivisionCode.php
index f59582b236b91caf2c1e1f66acca40647bf77e79..ece7d3d88800fb12d7ae13ef369daa852688e86c 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/BeSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/BeSubdivisionCode.php
@@ -18,23 +18,22 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: BE
  *
- * @link http://www.geonames.org/BE/administrative-division-belgium.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class BeSubdivisionCode extends AbstractSearcher
 {
     public $haystack = [
-        'BRU', // Brussels
-        'VLG', // Flanders
-        'WAL', // Wallonia
-        'BRU', // Brussels
+        'BRU', // Bruxelles-Capitale, Région de;Brussels Hoofdstedelijk Gewest
         'VAN', // Antwerpen
-        'VBR', // Vlaams Brabant
+        'VBR', // Vlaams-Brabant
+        'VLG', // Vlaams Gewest
         'VLI', // Limburg
         'VOV', // Oost-Vlaanderen
         'VWV', // West-Vlaanderen
-        'WBR', // Brabant Wallon
+        'WAL', // wallonne, Région
+        'WBR', // Brabant wallon
         'WHT', // Hainaut
-        'WLG', // Liege
+        'WLG', // Liège
         'WLX', // Luxembourg
         'WNA', // Namur
     ];
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/BfSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/BfSubdivisionCode.php
index a0a99e8af8cae5853b41843bd20077da0c90b628..6c09f411ed37ac2bbc6217374fc8b5fdfe799ef1 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/BfSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/BfSubdivisionCode.php
@@ -18,7 +18,7 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: BF
  *
- * @link http://www.geonames.org/BF/administrative-division-burkina-faso.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class BfSubdivisionCode extends AbstractSearcher
 {
@@ -36,51 +36,51 @@ class BfSubdivisionCode extends AbstractSearcher
         '11', // Plateau-Central
         '12', // Sahel
         '13', // Sud-Ouest
-        'BAL', // Bale
+        'BAL', // Balé
         'BAM', // Bam
         'BAN', // Banwa
-        'BAZ', // Bazega
+        'BAZ', // Bazèga
         'BGR', // Bougouriba
         'BLG', // Boulgou
-        'BLK', // Boulkiemde
-        'COM', // Comoe
+        'BLK', // Boulkiemdé
+        'COM', // Comoé
         'GAN', // Ganzourgou
         'GNA', // Gnagna
         'GOU', // Gourma
         'HOU', // Houet
         'IOB', // Ioba
         'KAD', // Kadiogo
-        'KEN', // Kenedougou
+        'KEN', // Kénédougou
         'KMD', // Komondjari
         'KMP', // Kompienga
-        'KOP', // Koulpelogo
+        'KOP', // Koulpélogo
         'KOS', // Kossi
         'KOT', // Kouritenga
-        'KOW', // Kourweogo
-        'LER', // Leraba
+        'KOW', // Kourwéogo
+        'LER', // Léraba
         'LOR', // Loroum
         'MOU', // Mouhoun
         'NAM', // Namentenga
-        'NAO', // Nahouri
+        'NAO', // Naouri
         'NAY', // Nayala
         'NOU', // Noumbiel
         'OUB', // Oubritenga
         'OUD', // Oudalan
-        'PAS', // Passore
+        'PAS', // Passoré
         'PON', // Poni
-        'SEN', // Seno
+        'SEN', // Séno
         'SIS', // Sissili
         'SMT', // Sanmatenga
-        'SNG', // Sanguie
+        'SNG', // Sanguié
         'SOM', // Soum
         'SOR', // Sourou
         'TAP', // Tapoa
-        'TUI', // Tuy
+        'TUI', // Tui
         'YAG', // Yagha
         'YAT', // Yatenga
         'ZIR', // Ziro
         'ZON', // Zondoma
-        'ZOU', // Zoundweogo
+        'ZOU', // Zoundwéogo
     ];
 
     public $compareIdentical = true;
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/BgSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/BgSubdivisionCode.php
index c484a23d9472d66418a2f5cb020bb3b864f3c026..835defd03e1ef00bfc14e728ae87cda78ae0250c 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/BgSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/BgSubdivisionCode.php
@@ -18,7 +18,7 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: BG
  *
- * @link http://www.geonames.org/BG/administrative-division-bulgaria.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class BgSubdivisionCode extends AbstractSearcher
 {
@@ -26,12 +26,12 @@ class BgSubdivisionCode extends AbstractSearcher
         '01', // Blagoevgrad
         '02', // Burgas
         '03', // Varna
-        '04', // Veliko Turnovo
+        '04', // Veliko Tarnovo
         '05', // Vidin
         '06', // Vratsa
         '07', // Gabrovo
         '08', // Dobrich
-        '09', // Kurdzhali
+        '09', // Kardzhali
         '10', // Kyustendil
         '11', // Lovech
         '12', // Montana
@@ -44,11 +44,11 @@ class BgSubdivisionCode extends AbstractSearcher
         '19', // Silistra
         '20', // Sliven
         '21', // Smolyan
-        '22', // Sofia Region
+        '22', // Sofia-Grad
         '23', // Sofia
         '24', // Stara Zagora
-        '25', // Turgovishte
-        '26', // Khaskovo
+        '25', // Targovishte
+        '26', // Haskovo
         '27', // Shumen
         '28', // Yambol
     ];
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/BhSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/BhSubdivisionCode.php
index 0e6b32016d13eb28c4a5a2ea4708616407152a9c..d3b5f7c70c77193daf215fb9e3be73122dff6ae0 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/BhSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/BhSubdivisionCode.php
@@ -18,16 +18,16 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: BH
  *
- * @link http://www.geonames.org/BH/administrative-division-bahrain.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class BhSubdivisionCode extends AbstractSearcher
 {
     public $haystack = [
-        '13', // Capital
-        '14', // Southern
-        '15', // Muharraq
-        '16', // Central
-        '17', // Northern
+        '13', // Al Manāmah (Al ‘Āşimah)
+        '14', // Al Janūbīyah
+        '15', // Al Muḩarraq
+        '16', // Al Wusţá
+        '17', // Ash Shamālīyah
     ];
 
     public $compareIdentical = true;
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/BiSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/BiSubdivisionCode.php
index b7f7c51e7472825015352a9ead5243a9f04990de..0e88712fa87e554f184744fd015add890bae3723 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/BiSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/BiSubdivisionCode.php
@@ -18,7 +18,7 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: BI
  *
- * @link http://www.geonames.org/BI/administrative-division-burundi.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class BiSubdivisionCode extends AbstractSearcher
 {
@@ -36,7 +36,6 @@ class BiSubdivisionCode extends AbstractSearcher
         'MA', // Makamba
         'MU', // Muramvya
         'MW', // Mwaro
-        'MY', // Muyinga
         'NG', // Ngozi
         'RT', // Rutana
         'RY', // Ruyigi
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/BjSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/BjSubdivisionCode.php
index 8a7f44325514b47598d9fc430113818c9eb5f04d..08469ca4c09f134ebb5cd5b03028ebc7a435e0ac 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/BjSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/BjSubdivisionCode.php
@@ -18,7 +18,7 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: BJ
  *
- * @link http://www.geonames.org/BJ/administrative-division-benin.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class BjSubdivisionCode extends AbstractSearcher
 {
@@ -32,7 +32,7 @@ class BjSubdivisionCode extends AbstractSearcher
         'KO', // Kouffo
         'LI', // Littoral
         'MO', // Mono
-        'OU', // Oueme
+        'OU', // Ouémé
         'PL', // Plateau
         'ZO', // Zou
     ];
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/BlSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/BlSubdivisionCode.php
index 17e777d97f28406ab7fce4cc9dfcdce9bbcae00c..8a1b2487371a8f1f8e0ac665317dcfd6c075d2b3 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/BlSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/BlSubdivisionCode.php
@@ -18,7 +18,7 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: BL
  *
- * @link http://www.geonames.org/BL/administrative-division-saint-barthelemy.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class BlSubdivisionCode extends AbstractSearcher
 {
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/BmSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/BmSubdivisionCode.php
index 137ff33bf7e9671408b3e0a8d5f2ba7acce922bf..550f5cb861ac70452df40333b1b8307ce54e83fc 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/BmSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/BmSubdivisionCode.php
@@ -18,7 +18,7 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: BM
  *
- * @link http://www.geonames.org/BM/administrative-division-bermuda.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class BmSubdivisionCode extends AbstractSearcher
 {
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/BnSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/BnSubdivisionCode.php
index 776c92ba5c84c8f5a1274285b5df201c0c8285c9..681ee255f12a00140f00ed7d89ceb324074464a8 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/BnSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/BnSubdivisionCode.php
@@ -18,13 +18,13 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: BN
  *
- * @link http://www.geonames.org/BN/administrative-division-brunei.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class BnSubdivisionCode extends AbstractSearcher
 {
     public $haystack = [
         'BE', // Belait
-        'BM', // Brunei and Muara
+        'BM', // Brunei-Muara
         'TE', // Temburong
         'TU', // Tutong
     ];
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/BoSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/BoSubdivisionCode.php
index ec6764a6614a4b849d97d0d6ab2f279212d04bd7..306839d2d288bf1ff9e144a2f0448dbe43f26e63 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/BoSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/BoSubdivisionCode.php
@@ -18,20 +18,20 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: BO
  *
- * @link http://www.geonames.org/BO/administrative-division-bolivia.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class BoSubdivisionCode extends AbstractSearcher
 {
     public $haystack = [
-        'B', // Departmento Beni
-        'C', // Departmento Cochabamba
-        'H', // Departmento Chuquisaca
-        'L', // Departmento La Paz
-        'N', // Departmento Pando
-        'O', // Departmento Oruro
-        'P', // Departmento Potosi
-        'S', // Departmento Santa Cruz
-        'T', // Departmento Tarija
+        'B', // El Beni
+        'C', // Cochabamba
+        'H', // Chuquisaca
+        'L', // La Paz
+        'N', // Pando
+        'O', // Oruro
+        'P', // Potosí
+        'S', // Santa Cruz
+        'T', // Tarija
     ];
 
     public $compareIdentical = true;
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/BqSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/BqSubdivisionCode.php
index 96aa5295a3f24dd982308db01000d413d26924e8..2837de23d510bb87362ad964dbb80f5ab2487c1a 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/BqSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/BqSubdivisionCode.php
@@ -18,7 +18,7 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: BQ
  *
- * @link http://www.geonames.org/BQ/administrative-division-bonaire.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class BqSubdivisionCode extends AbstractSearcher
 {
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/BrSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/BrSubdivisionCode.php
index 6cab6a5c1aad90b70cf5e971894c67b1aab99fa8..7bb67378ab26017c0b1b067f371697f6023efe28 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/BrSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/BrSubdivisionCode.php
@@ -18,7 +18,7 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: BR
  *
- * @link http://www.geonames.org/BR/administrative-division-brazil.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class BrSubdivisionCode extends AbstractSearcher
 {
@@ -26,29 +26,30 @@ class BrSubdivisionCode extends AbstractSearcher
         'AC', // Acre
         'AL', // Alagoas
         'AM', // Amazonas
-        'AP', // Amapa
+        'AP', // Amapá
         'BA', // Bahia
-        'CE', // Ceara
+        'CE', // Ceará
         'DF', // Distrito Federal
-        'ES', // Espirito Santo
-        'GO', // Goias
-        'MA', // Maranhao
+        'ES', // Espírito Santo
+        'FN', // Fernando de Noronha
+        'GO', // Goiás
+        'MA', // Maranhão
         'MG', // Minas Gerais
         'MS', // Mato Grosso do Sul
         'MT', // Mato Grosso
-        'PA', // Para
-        'PB', // Paraiba
+        'PA', // Pará
+        'PB', // Paraíba
         'PE', // Pernambuco
-        'PI', // Piaui
-        'PR', // Parana
+        'PI', // Piauí
+        'PR', // Paraná
         'RJ', // Rio de Janeiro
         'RN', // Rio Grande do Norte
-        'RO', // Rondonia
+        'RO', // Rondônia
         'RR', // Roraima
         'RS', // Rio Grande do Sul
         'SC', // Santa Catarina
         'SE', // Sergipe
-        'SP', // Sao Paulo
+        'SP', // São Paulo
         'TO', // Tocantins
     ];
 
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/BsSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/BsSubdivisionCode.php
index 62505430e957f671556e0949fc8e2d902926e9c2..89c6f4cf92191b9019f42fc0a2c09db7df6fd6de 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/BsSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/BsSubdivisionCode.php
@@ -18,13 +18,13 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: BS
  *
- * @link http://www.geonames.org/BS/administrative-division-bahamas.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class BsSubdivisionCode extends AbstractSearcher
 {
     public $haystack = [
-        'AK', // Acklins Islands
-        'BI', // Bimini and Cat Cay
+        'AK', // Acklins
+        'BI', // Bimini
         'BP', // Black Point
         'BY', // Berry Islands
         'CE', // Central Eleuthera
@@ -45,7 +45,6 @@ class BsSubdivisionCode extends AbstractSearcher
         'MI', // Moore's Island
         'NE', // North Eleuthera
         'NO', // North Abaco
-        'NP', // New Providence
         'NS', // North Andros
         'RC', // Rum Cay
         'RI', // Ragged Island
@@ -55,14 +54,6 @@ class BsSubdivisionCode extends AbstractSearcher
         'SS', // San Salvador
         'SW', // Spanish Wells
         'WG', // West Grand Bahama
-        'CO', // Governor’s Harbour
-        'FC', // Fresh Creek
-        'GT', // Green Turtle Cay
-        'HR', // High Rock District
-        'KE', // Kemps Bay District
-        'MH', // Marsh Harbour District
-        'RS', // Rock Sound
-        'SP', // Sandy Point
     ];
 
     public $compareIdentical = true;
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/BtSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/BtSubdivisionCode.php
index b32a3f6d48a72a93422ec46688a350d18c08a969..b467b89e49a94358ff14579f2f43f2e4be261ccd 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/BtSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/BtSubdivisionCode.php
@@ -18,15 +18,15 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: BT
  *
- * @link http://www.geonames.org/BT/administrative-division-bhutan.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class BtSubdivisionCode extends AbstractSearcher
 {
     public $haystack = [
         '11', // Paro
-        '12', // Chukha
-        '13', // Haa
-        '14', // Samtse
+        '12', // Chhukha
+        '13', // Ha
+        '14', // Samtee
         '15', // Thimphu
         '21', // Tsirang
         '22', // Dagana
@@ -37,12 +37,12 @@ class BtSubdivisionCode extends AbstractSearcher
         '33', // Bumthang
         '34', // Zhemgang
         '41', // Trashigang
-        '42', // Mongar
+        '42', // Monggar
         '43', // Pemagatshel
-        '44', // Lhuntse
-        '45', // Samdrup Jongkhar
+        '44', // Lhuentse
+        '45', // Samdrup Jongkha
         'GA', // Gasa
-        'TY', // Trashi Yangste
+        'TY', // Trashi Yangtse
     ];
 
     public $compareIdentical = true;
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/BvSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/BvSubdivisionCode.php
index 9ef3f1cd10b34c352495904fd10b4b753a061aaf..609d62d0075cff845d98a5c76b40d65e0c2dc119 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/BvSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/BvSubdivisionCode.php
@@ -18,7 +18,7 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: BV
  *
- * @link http://www.geonames.org/BV/administrative-division-bouvet-island.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class BvSubdivisionCode extends AbstractSearcher
 {
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/BwSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/BwSubdivisionCode.php
index 7dffd7318e8a7db9e6dd9be87d257338cae3d59e..a117e44c9a8dfaf7a79a5809281bd618f663ac57 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/BwSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/BwSubdivisionCode.php
@@ -18,7 +18,7 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: BW
  *
- * @link http://www.geonames.org/BW/administrative-division-botswana.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class BwSubdivisionCode extends AbstractSearcher
 {
@@ -28,9 +28,9 @@ class BwSubdivisionCode extends AbstractSearcher
         'KG', // Kgalagadi
         'KL', // Kgatleng
         'KW', // Kweneng
-        'NE', // North East
-        'NW', // North West
-        'SE', // South East
+        'NE', // North-East
+        'NW', // North-West
+        'SE', // South-East
         'SO', // Southern
     ];
 
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/BySubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/BySubdivisionCode.php
index 042e5372f879ae7b33067aaff9fc518b4a4eadc1..e9d1dc77f56c91b4f5b66248a61bbd87fc9954a9 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/BySubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/BySubdivisionCode.php
@@ -18,18 +18,18 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: BY
  *
- * @link http://www.geonames.org/BY/administrative-division-belarus.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class BySubdivisionCode extends AbstractSearcher
 {
     public $haystack = [
-        'BR', // Brest voblast
+        'BR', // Brèsckaja voblasc'
         'HM', // Horad Minsk
-        'HO', // Homyel voblast
-        'HR', // Hrodna voblast
-        'MA', // Mahilyow voblast
-        'MI', // Minsk voblast
-        'VI', // Vitsebsk voblast
+        'HO', // Homel'skaja voblasc'
+        'HR', // Hrodzenskaja voblasc'
+        'MA', // Mahilëuskaja voblasc'
+        'MI', // Minskaja voblasc'
+        'VI', // Vicebskaja voblasc'
     ];
 
     public $compareIdentical = true;
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/BzSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/BzSubdivisionCode.php
index 0b982806d8c3c11bebad9dd0ce66bc59ad2f4225..7973417bf5d0c43f7dde134684e7d67b2ca9cb9e 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/BzSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/BzSubdivisionCode.php
@@ -18,17 +18,17 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: BZ
  *
- * @link http://www.geonames.org/BZ/administrative-division-belize.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class BzSubdivisionCode extends AbstractSearcher
 {
     public $haystack = [
-        'BZ', // Belize District
-        'CY', // Cayo District
-        'CZL', // Corozal District
-        'OW', // Orange Walk District
-        'SC', // Stann Creek District
-        'TOL', // Toledo District
+        'BZ', // Belize
+        'CY', // Cayo
+        'CZL', // Corozal
+        'OW', // Orange Walk
+        'SC', // Stann Creek
+        'TOL', // Toledo
     ];
 
     public $compareIdentical = true;
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/CaSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/CaSubdivisionCode.php
index c61293553837a6d4afb32ea75a74c0a7dc26eda6..632970ae1f35128aeceebee53eed8ceacfd07946 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/CaSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/CaSubdivisionCode.php
@@ -18,7 +18,7 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: CA
  *
- * @link http://www.geonames.org/CA/administrative-division-canada.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class CaSubdivisionCode extends AbstractSearcher
 {
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/CcSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/CcSubdivisionCode.php
index aa6bdcfa8647aeaa8c5ca3831120b6be008cecf5..ac191dcdbd5f3e246e12bdd6fdd38228d7f96357 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/CcSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/CcSubdivisionCode.php
@@ -18,7 +18,7 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: CC
  *
- * @link http://www.geonames.org/CC/administrative-division-cocos-islands.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class CcSubdivisionCode extends AbstractSearcher
 {
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/CdSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/CdSubdivisionCode.php
index 868ce764412d47604be61ab27afb8f66924d733e..847f73c6e4e54b4e32225800683e23e636e45086 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/CdSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/CdSubdivisionCode.php
@@ -18,14 +18,14 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: CD
  *
- * @link http://www.geonames.org/CD/administrative-division-democratic-republic-of-the-congo.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class CdSubdivisionCode extends AbstractSearcher
 {
     public $haystack = [
         'BC', // Bas-Congo
         'BN', // Bandundu
-        'EQ', // Equateur
+        'EQ', // Équateur
         'KA', // Katanga
         'KE', // Kasai-Oriental
         'KN', // Kinshasa
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/CfSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/CfSubdivisionCode.php
index caf54eab156dc48f3d9d8b8dbbec0f9e9b37cb0c..172fd2e8b9bccce87a099c5e427d6b047abf97bc 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/CfSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/CfSubdivisionCode.php
@@ -18,7 +18,7 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: CF
  *
- * @link http://www.geonames.org/CF/administrative-division-central-african-republic.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class CfSubdivisionCode extends AbstractSearcher
 {
@@ -29,15 +29,15 @@ class CfSubdivisionCode extends AbstractSearcher
         'BK', // Basse-Kotto
         'HK', // Haute-Kotto
         'HM', // Haut-Mbomou
-        'HS', // Mambere-Kadeï
-        'KB', // Nana-Grebizi
-        'KG', // Kemo
+        'HS', // Haute-Sangha / Mambéré-Kadéï
+        'KB', // Gribingui
+        'KG', // Kémo-Gribingui
         'LB', // Lobaye
         'MB', // Mbomou
-        'MP', // Ombella-M'Poko
-        'NM', // Nana-Mambere
-        'OP', // Ouham-Pende
-        'SE', // Sangha-Mbaere
+        'MP', // Ombella-M'poko
+        'NM', // Nana-Mambéré
+        'OP', // Ouham-Pendé
+        'SE', // Sangha
         'UK', // Ouaka
         'VK', // Vakaga
     ];
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/CgSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/CgSubdivisionCode.php
index f2793aa5f739fbed29c2192c63435c624caa2a41..361bd783da32d598283c968f65a0832bd2acf4fc 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/CgSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/CgSubdivisionCode.php
@@ -18,7 +18,7 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: CG
  *
- * @link http://www.geonames.org/CG/administrative-division-republic-of-the-congo.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class CgSubdivisionCode extends AbstractSearcher
 {
@@ -28,8 +28,7 @@ class CgSubdivisionCode extends AbstractSearcher
         '13', // Sangha
         '14', // Plateaux
         '15', // Cuvette-Ouest
-        '16', // Pointe-Noire
-        '2', // Lekoumou
+        '2', // Lékoumou
         '5', // Kouilou
         '7', // Likouala
         '8', // Cuvette
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/ChSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/ChSubdivisionCode.php
index dac06496904fc7d0a0bd30a900cdd81e8b70c955..d9d53d1a20b484628e350225d903a51e27131358 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/ChSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/ChSubdivisionCode.php
@@ -18,27 +18,27 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: CH
  *
- * @link http://www.geonames.org/CH/administrative-division-switzerland.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class ChSubdivisionCode extends AbstractSearcher
 {
     public $haystack = [
         'AG', // Aargau
-        'AI', // Appenzell Innerhoden
+        'AI', // Appenzell Innerrhoden
         'AR', // Appenzell Ausserrhoden
         'BE', // Bern
         'BL', // Basel-Landschaft
         'BS', // Basel-Stadt
         'FR', // Fribourg
-        'GE', // Geneva
+        'GE', // Genève
         'GL', // Glarus
-        'GR', // Graubunden
+        'GR', // Graubünden
         'JU', // Jura
-        'LU', // Lucerne
+        'LU', // Luzern
         'NE', // Neuchâtel
         'NW', // Nidwalden
         'OW', // Obwalden
-        'SG', // St. Gallen
+        'SG', // Sankt Gallen
         'SH', // Schaffhausen
         'SO', // Solothurn
         'SZ', // Schwyz
@@ -48,7 +48,7 @@ class ChSubdivisionCode extends AbstractSearcher
         'VD', // Vaud
         'VS', // Valais
         'ZG', // Zug
-        'ZH', // Zurich
+        'ZH', // Zürich
     ];
 
     public $compareIdentical = true;
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/CiSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/CiSubdivisionCode.php
index 592cdab7df7a05124a59fe0c888ef102340ddd19..7978ec56d6b7120b04ca8ae41eb4b7e7c2ee9de4 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/CiSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/CiSubdivisionCode.php
@@ -18,7 +18,7 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: CI
  *
- * @link http://www.geonames.org/CI/administrative-division-ivory-coast.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class CiSubdivisionCode extends AbstractSearcher
 {
@@ -36,7 +36,7 @@ class CiSubdivisionCode extends AbstractSearcher
         '11', // Nzi-Comoé (Région)
         '12', // Marahoué (Région de la)
         '13', // Sud-Comoé (Région du)
-        '14', // Worodougou (Région du)
+        '14', // Worodouqou (Région du)
         '15', // Sud-Bandama (Région du)
         '16', // Agnébi (Région de l')
         '17', // Bafing (Région du)
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/CkSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/CkSubdivisionCode.php
index aa0d1bfc5dd0f0565a6b9f2f12a2e84a4469da9f..c9b0b41fc455e9d76f0c4c475a597336e4b34272 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/CkSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/CkSubdivisionCode.php
@@ -18,7 +18,7 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: CK
  *
- * @link http://www.geonames.org/CK/administrative-division-cook-islands.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class CkSubdivisionCode extends AbstractSearcher
 {
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/ClSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/ClSubdivisionCode.php
index b8c85b108f029cb0779d861c57b6ef9f18f7dac2..3113c02bb5b664c8448a205c65e28eeb71af6d05 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/ClSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/ClSubdivisionCode.php
@@ -18,26 +18,26 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: CL
  *
- * @link http://www.geonames.org/CL/administrative-division-chile.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class ClSubdivisionCode extends AbstractSearcher
 {
     public $haystack = [
-        'AI', // Aisen del General Carlos Ibanez del Campo (XI)
-        'AN', // Antofagasta (II)
+        'AI', // Aisén del General Carlos Ibáñez del Campo
+        'AN', // Antofagasta
         'AP', // Arica y Parinacota
-        'AR', // Araucania (IX)
-        'AT', // Atacama (III)
-        'BI', // Bio-Bio (VIII)
-        'CO', // Coquimbo (IV)
-        'LI', // Libertador General Bernardo O'Higgins (VI)
-        'LL', // Los Lagos (X)
+        'AR', // Araucanía
+        'AT', // Atacama
+        'BI', // Bío-Bío
+        'CO', // Coquimbo
+        'LI', // Libertador General Bernardo O'Higgins
+        'LL', // Los Lagos
         'LR', // Los Ríos
-        'MA', // Magallanes (XII)
-        'ML', // Maule (VII)
-        'RM', // Region Metropolitana (RM)
-        'TA', // Tarapaca (I)
-        'VS', // Valparaiso (V)
+        'MA', // Magallanes y Antártica Chilena
+        'ML', // Maule
+        'RM', // Región Metropolitana de Santiago
+        'TA', // Tarapacá
+        'VS', // Valparaíso
     ];
 
     public $compareIdentical = true;
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/CmSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/CmSubdivisionCode.php
index b20169a27fa895f7e92f015354dddea8a213fd6c..88b60fbd59c5c47f85fc2a32cc12e722dd47d673 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/CmSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/CmSubdivisionCode.php
@@ -18,21 +18,21 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: CM
  *
- * @link http://www.geonames.org/CM/administrative-division-cameroon.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class CmSubdivisionCode extends AbstractSearcher
 {
     public $haystack = [
-        'AD', // Adamawa Province (Adamaoua)
-        'CE', // Centre Province
-        'EN', // Extreme North Province (Extrême-Nord)
-        'ES', // East Province (Est)
-        'LT', // Littoral Province
-        'NO', // North Province (Nord)
-        'NW', // Northwest Province (Nord-Ouest)
-        'OU', // West Province (Ouest)
-        'SU', // South Province (Sud)
-        'SW', // Southwest Province (Sud-Ouest).
+        'AD', // Adamaoua
+        'CE', // Centre
+        'EN', // Far North
+        'ES', // East
+        'LT', // Littoral
+        'NO', // North
+        'NW', // North-West (Cameroon)
+        'OU', // West
+        'SU', // South
+        'SW', // South-West
     ];
 
     public $compareIdentical = true;
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/CnSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/CnSubdivisionCode.php
index 723c4e8c07346f70724b1f7651724d525dad9360..4ba8a5b7bcaec94af16ce21d2b02335d3a0efba2 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/CnSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/CnSubdivisionCode.php
@@ -18,45 +18,45 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: CN
  *
- * @link http://www.geonames.org/CN/administrative-division-china.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class CnSubdivisionCode extends AbstractSearcher
 {
     public $haystack = [
-        '11', // Beijing
-        '12', // Tianjin
-        '13', // Hebei
-        '14', // Shanxi
-        '15', // Nei Mongol
-        '21', // Liaoning
-        '22', // Jilin
-        '23', // Heilongjiang
-        '31', // Shanghai
-        '32', // Jiangsu
-        '33', // Zhejiang
-        '34', // Anhui
-        '35', // Fujian
-        '36', // Jiangxi
-        '37', // Shandong
-        '41', // Henan
-        '42', // Hubei
-        '43', // Hunan
-        '44', // Guangdong
-        '45', // Guangxi
-        '46', // Hainan
-        '50', // Chongqìng
-        '51', // Sichuan
-        '52', // Guizhou
-        '53', // Yunnan
-        '54', // Xizang Zìzhìqu (Tibet)
-        '61', // Shaanxi
-        '62', // Gansu
-        '63', // Qinghai
-        '64', // Ningxia
-        '65', // Xinjiang
-        '71', // Taiwan
-        '91', // Xianggang
-        '92', // Aomen
+        'AH', // Anhui Sheng
+        'BJ', // Beijing Shi
+        'CQ', // Chongqing Shi
+        'FJ', // Fujian Sheng
+        'GD', // Guangdong Sheng
+        'GS', // Gansu Sheng
+        'GX', // Guangxi Zhuangzu Zizhiqu
+        'GZ', // Guizhou Sheng
+        'HA', // Henan Sheng
+        'HB', // Hubei Sheng
+        'HE', // Hebei Sheng
+        'HI', // Hainan Sheng
+        'HK', // Hong Kong SAR (see also separate country code entry under HK)
+        'HL', // Heilongjiang Sheng
+        'HN', // Hunan Sheng
+        'JL', // Jilin Sheng
+        'JS', // Jiangsu Sheng
+        'JX', // Jiangxi Sheng
+        'LN', // Liaoning Sheng
+        'MO', // Macao SAR (see also separate country code entry under MO)
+        'NM', // Nei Mongol Zizhiqu
+        'NX', // Ningxia Huizi Zizhiqu
+        'QH', // Qinghai Sheng
+        'SC', // Sichuan Sheng
+        'SD', // Shandong Sheng
+        'SH', // Shanghai Shi
+        'SN', // Shaanxi Sheng
+        'SX', // Shanxi Sheng
+        'TJ', // Tianjin Shi
+        'TW', // Taiwan Sheng (see also separate country code entry under TW)
+        'XJ', // Xinjiang Uygur Zizhiqu
+        'XZ', // Xizang Zizhiqu
+        'YN', // Yunnan Sheng
+        'ZJ', // Zhejiang Sheng
     ];
 
     public $compareIdentical = true;
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/CoSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/CoSubdivisionCode.php
index 3577ee4f338e05c98200b6e610a43829ecec0f94..75ad557d7f3e1967d8c2e1b6a4434fa0e48510f7 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/CoSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/CoSubdivisionCode.php
@@ -18,7 +18,7 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: CO
  *
- * @link http://www.geonames.org/CO/administrative-division-colombia.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class CoSubdivisionCode extends AbstractSearcher
 {
@@ -26,35 +26,35 @@ class CoSubdivisionCode extends AbstractSearcher
         'AMA', // Amazonas
         'ANT', // Antioquia
         'ARA', // Arauca
-        'ATL', // Atlantico
-        'BOL', // Bolivar
-        'BOY', // Boyaca
+        'ATL', // Atlántico
+        'BOL', // Bolívar
+        'BOY', // Boyacá
         'CAL', // Caldas
-        'CAQ', // Caqueta
+        'CAQ', // Caquetá
         'CAS', // Casanare
         'CAU', // Cauca
         'CES', // Cesar
-        'CHO', // Choco
-        'COR', // Cordoba
+        'CHO', // Chocó
+        'COR', // Córdoba
         'CUN', // Cundinamarca
-        'DC', // Bogota D.C.
-        'GUA', // Guainia
+        'DC', // Distrito Capital de Bogotá
+        'GUA', // Guainía
         'GUV', // Guaviare
         'HUI', // Huila
         'LAG', // La Guajira
         'MAG', // Magdalena
         'MET', // Meta
-        'NAR', // Narino
+        'NAR', // Nariño
         'NSA', // Norte de Santander
         'PUT', // Putumayo
-        'QUI', // Quindio
+        'QUI', // Quindío
         'RIS', // Risaralda
         'SAN', // Santander
-        'SAP', // San Andres y Providencia
+        'SAP', // San Andrés, Providencia y Santa Catalina
         'SUC', // Sucre
         'TOL', // Tolima
         'VAC', // Valle del Cauca
-        'VAU', // Vaupes
+        'VAU', // Vaupés
         'VID', // Vichada
     ];
 
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/CrSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/CrSubdivisionCode.php
index 0fad16d53e2e3420bfbbf23c710d8f46d52b01ad..c4b8ee9cb82e67f89e2656980d763eeb9a196357 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/CrSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/CrSubdivisionCode.php
@@ -18,7 +18,7 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: CR
  *
- * @link http://www.geonames.org/CR/administrative-division-costa-rica.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class CrSubdivisionCode extends AbstractSearcher
 {
@@ -27,9 +27,9 @@ class CrSubdivisionCode extends AbstractSearcher
         'C', // Cartago
         'G', // Guanacaste
         'H', // Heredia
-        'L', // Limon
+        'L', // Limón
         'P', // Puntarenas
-        'SJ', // San Jose
+        'SJ', // San José
     ];
 
     public $compareIdentical = true;
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/CsSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/CsSubdivisionCode.php
index 24d7eaa5b5e3e3be58f982849b7f87ac82ea9e4c..3a5bc0af86e83288494cb45e543a5086d27ef475 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/CsSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/CsSubdivisionCode.php
@@ -18,7 +18,7 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: CS
  *
- * @link http://www.geonames.org/CS/administrative-division-serbia-and-montenegro.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class CsSubdivisionCode extends AbstractSearcher
 {
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/CuSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/CuSubdivisionCode.php
index 84ac1a2796e3cc7a1ae847d20842dfecc2e355c6..ff915402dfe489ebb201cd2574c851006731120b 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/CuSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/CuSubdivisionCode.php
@@ -18,26 +18,25 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: CU
  *
- * @link http://www.geonames.org/CU/administrative-division-cuba.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class CuSubdivisionCode extends AbstractSearcher
 {
     public $haystack = [
         '01', // Pinar del Rio
-        '03', // La Habana
+        '02', // La Habana
+        '03', // Ciudad de La Habana
         '04', // Matanzas
         '05', // Villa Clara
         '06', // Cienfuegos
-        '07', // Sancti Spiritus
-        '08', // Ciego de Avila
-        '09', // Camaguey
+        '07', // Sancti Spíritus
+        '08', // Ciego de Ávila
+        '09', // Camagüey
         '10', // Las Tunas
-        '11', // Holguin
+        '11', // Holguín
         '12', // Granma
         '13', // Santiago de Cuba
-        '14', // Guantanamo
-        '15', // Artemisa
-        '16', // Mayabeque
+        '14', // Guantánamo
         '99', // Isla de la Juventud
     ];
 
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/CvSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/CvSubdivisionCode.php
index 83288ff06700f42edac53ca6b9bb841e7aac63b1..dd98f2adfaced7678bce68c12f29d856a63a3e53 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/CvSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/CvSubdivisionCode.php
@@ -18,17 +18,16 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: CV
  *
- * @link http://www.geonames.org/CV/administrative-division-cape-verde.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class CvSubdivisionCode extends AbstractSearcher
 {
     public $haystack = [
         'B', // Ilhas de Barlavento
-        'S', // Ilhas de Sotavento
         'BR', // Brava
         'BV', // Boa Vista
         'CA', // Santa Catarina
-        'CF', // Santa Catarina do Fogo
+        'CF', // Santa Catarina de Fogo
         'CR', // Santa Cruz
         'MA', // Maio
         'MO', // Mosteiros
@@ -38,13 +37,14 @@ class CvSubdivisionCode extends AbstractSearcher
         'RB', // Ribeira Brava
         'RG', // Ribeira Grande
         'RS', // Ribeira Grande de Santiago
-        'SD', // Sao Domingos
-        'SF', // Sao Filipe
+        'S', // Ilhas de Sotavento
+        'SD', // São Domingos
+        'SF', // São Filipe
         'SL', // Sal
-        'SL*', // São Lourenço dos Orgãos
         'SM', // São Miguel
+        'SO', // São Lourenço dos Órgãos
         'SS', // São Salvador do Mundo
-        'SV', // Sao Vicente
+        'SV', // São Vicente
         'TA', // Tarrafal
         'TS', // Tarrafal de São Nicolau
     ];
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/CwSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/CwSubdivisionCode.php
index 883a0832b271601868f0d3d095ae46351727b5fc..cf31841cf938c4d7fd8fd0aeada172f02759a3af 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/CwSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/CwSubdivisionCode.php
@@ -18,7 +18,7 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: CW
  *
- * @link http://www.geonames.org/CW/administrative-division-curacao.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class CwSubdivisionCode extends AbstractSearcher
 {
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/CxSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/CxSubdivisionCode.php
index d1536e29fc564e332e06fa6bb62b9829064137c4..770ad0bffa91f086f567b37574a1e859c5327ab4 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/CxSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/CxSubdivisionCode.php
@@ -18,7 +18,7 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: CX
  *
- * @link http://www.geonames.org/CX/administrative-division-christmas-island.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class CxSubdivisionCode extends AbstractSearcher
 {
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/CySubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/CySubdivisionCode.php
index 679a8fac13b11a22584bb70ffca3d81b4c4ef97e..6fc86fa76be8d3611be63ff0be72c19725359e54 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/CySubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/CySubdivisionCode.php
@@ -18,7 +18,7 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: CY
  *
- * @link http://www.geonames.org/CY/administrative-division-cyprus.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class CySubdivisionCode extends AbstractSearcher
 {
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/CzSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/CzSubdivisionCode.php
index da343832474549777470353df0a4e695f99d4428..e81899aa49043af64ba15f558f442dd5bc286ea6 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/CzSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/CzSubdivisionCode.php
@@ -18,25 +18,12 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: CZ
  *
- * @link http://www.geonames.org/CZ/administrative-division-czech-republic.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class CzSubdivisionCode extends AbstractSearcher
 {
     public $haystack = [
-        'JC', // South Bohemian Region (Jihocesky kraj)
-        'JM', // South Moravian Region (Jihomoravsky kraj)
-        'KA', // Carlsbad Region  (Karlovarsky kraj)
-        'KR', // Hradec Kralove Region (Kralovehradecky kraj)
-        'LI', // Liberec Region (Liberecky kraj)
-        'MO', // Moravian-Silesian Region (Moravskoslezsky kraj)
-        'OL', // Olomouc Region (Olomoucky kraj)
-        'PA', // Pardubice Region (Pardubicky kraj)
-        'PL', // Plzen( Region Plzensky kraj)
-        'PR', // Prague - the Capital (Praha - hlavni mesto)
-        'ST', // Central Bohemian Region (Stredocesky kraj)
-        'US', // Usti nad Labem Region (Ustecky kraj)
-        'VY', // Vysocina Region (kraj Vysocina)
-        'ZL', // Zlin Region (Zlinsky kraj)
+        '10', // Praha, Hlavní mešto
         '101', // Praha 1
         '102', // Praha 2
         '103', // Praha 3
@@ -46,12 +33,20 @@ class CzSubdivisionCode extends AbstractSearcher
         '107', // Praha 7
         '108', // Praha 8
         '109', // Praha 9
-        '10A', // Praha 10
-        '10B', // Praha 11
-        '10C', // Praha 12
-        '10D', // Praha 13
-        '10E', // Praha 14
-        '10F', // Praha 15
+        '110', // Praha 10
+        '111', // Praha 11
+        '112', // Praha 12
+        '113', // Praha 13
+        '114', // Praha 14
+        '115', // Praha 15
+        '116', // Praha 16
+        '117', // Praha 17
+        '118', // Praha 18
+        '119', // Praha 19
+        '120', // Praha 20
+        '121', // Praha 21
+        '122', // Praha 22
+        '20', // Středočeský kraj
         '201', // Benešov
         '202', // Beroun
         '203', // Kladno
@@ -64,6 +59,7 @@ class CzSubdivisionCode extends AbstractSearcher
         '20A', // Praha-západ
         '20B', // Příbram
         '20C', // Rakovník
+        '31', // Jihočeský kraj
         '311', // České Budějovice
         '312', // Český Krumlov
         '313', // Jindřichův Hradec
@@ -71,6 +67,7 @@ class CzSubdivisionCode extends AbstractSearcher
         '315', // Prachatice
         '316', // Strakonice
         '317', // Tábor
+        '32', // Plzeňský kraj
         '321', // Domažlice
         '322', // Klatovy
         '323', // Plzeň-město
@@ -78,9 +75,11 @@ class CzSubdivisionCode extends AbstractSearcher
         '325', // Plzeň-sever
         '326', // Rokycany
         '327', // Tachov
+        '41', // Karlovarský kraj
         '411', // Cheb
         '412', // Karlovy Vary
         '413', // Sokolov
+        '42', // Ústecký kraj
         '421', // Děčín
         '422', // Chomutov
         '423', // Litoměřice
@@ -88,46 +87,54 @@ class CzSubdivisionCode extends AbstractSearcher
         '425', // Most
         '426', // Teplice
         '427', // Ústí nad Labem
+        '51', // Liberecký kraj
         '511', // Česká Lípa
         '512', // Jablonec nad Nisou
         '513', // Liberec
         '514', // Semily
+        '52', // Královéhradecký kraj
         '521', // Hradec Králové
         '522', // Jičín
         '523', // Náchod
         '524', // Rychnov nad Kněžnou
         '525', // Trutnov
+        '53', // Pardubický kraj
         '531', // Chrudim
         '532', // Pardubice
         '533', // Svitavy
         '534', // Ústí nad Orlicí
-        '611', // Havlíčkův Brod
-        '612', // Jihlava
-        '613', // Pelhřimov
-        '614', // Třebíč
-        '615', // Žd’ár nad Sázavou
-        '621', // Blansko
-        '622', // Brno-město
-        '623', // Brno-venkov
-        '624', // Břeclav
-        '625', // Hodonín
-        '626', // Vyškov
-        '627', // Znojmo
+        '63', // Kraj Vysočina
+        '631', // Havlíčkův Brod
+        '632', // Jihlava
+        '633', // Pelhřimov
+        '634', // Třebíč
+        '635', // Žďár nad Sázavou
+        '64', // Jihomoravský kraj
+        '641', // Blansko
+        '642', // Brno-město
+        '643', // Brno-venkov
+        '644', // Břeclav
+        '645', // Hodonín
+        '646', // Vyškov
+        '647', // Znojmo
+        '71', // Olomoucký kraj
         '711', // Jeseník
         '712', // Olomouc
-        '713', // Prostĕjov
+        '713', // Prostějov
         '714', // Přerov
         '715', // Å umperk
-        '721', // Kromĕříž
-        '722', // Uherské Hradištĕ
+        '72', // Zlínský kraj
+        '721', // Kroměříž
+        '722', // Uherské Hradiště
         '723', // Vsetín
         '724', // Zlín
+        '80', // Moravskoslezský kraj
         '801', // Bruntál
-        '802', // Frýdek - Místek
+        '802', // Frýdek Místek
         '803', // Karviná
         '804', // Nový Jičín
         '805', // Opava
-        '806', // Ostrava - město
+        '806', // Ostrava-město
     ];
 
     public $compareIdentical = true;
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/DeSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/DeSubdivisionCode.php
index f800ad9ed52d383c4599f2e6b36bd1ae74fb03e6..e194686802a2b82c03f2da79a7e0ad4eba7b3eb8 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/DeSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/DeSubdivisionCode.php
@@ -18,7 +18,7 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: DE
  *
- * @link http://www.geonames.org/DE/administrative-division-germany.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class DeSubdivisionCode extends AbstractSearcher
 {
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/DjSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/DjSubdivisionCode.php
index 6d489fd71a994cea7801612f976cec6700ec3204..5e030784daf02cfab5a74948681d68a21e2bcd34 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/DjSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/DjSubdivisionCode.php
@@ -18,17 +18,17 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: DJ
  *
- * @link http://www.geonames.org/DJ/administrative-division-djibouti.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class DjSubdivisionCode extends AbstractSearcher
 {
     public $haystack = [
         'AR', // Arta
-        'AS', // 'Ali Sabih
+        'AS', // Ali Sabieh
         'DI', // Dikhil
         'DJ', // Djibouti
         'OB', // Obock
-        'TA', // Tadjoura
+        'TA', // Tadjourah
     ];
 
     public $compareIdentical = true;
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/DkSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/DkSubdivisionCode.php
index 0a1fd377720da063cb00dbe3b42b555443265c43..2008e74f78d10203159fe61ce63e853c20ca2ac6 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/DkSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/DkSubdivisionCode.php
@@ -18,16 +18,16 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: DK
  *
- * @link http://www.geonames.org/DK/administrative-division-denmark.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class DkSubdivisionCode extends AbstractSearcher
 {
     public $haystack = [
-        '81', // Region Nordjylland
-        '82', // Region Midtjylland
-        '83', // Region Syddanmark
-        '84', // Region Hovedstaden
-        '85', // Region Sjæland
+        '81', // Nordjylland
+        '82', // Midtjylland
+        '83', // Syddanmark
+        '84', // Hovedstaden
+        '85', // Sjælland
     ];
 
     public $compareIdentical = true;
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/DmSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/DmSubdivisionCode.php
index df4ca22be657c39179180e477dba520ed4e39098..b9e0b28632294238bc7cf52a42662c7daf540914 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/DmSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/DmSubdivisionCode.php
@@ -18,21 +18,21 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: DM
  *
- * @link http://www.geonames.org/DM/administrative-division-dominica.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class DmSubdivisionCode extends AbstractSearcher
 {
     public $haystack = [
-        '02', // Saint Andrew Parish
-        '03', // Saint David Parish
-        '04', // Saint George Parish
-        '05', // Saint John Parish
-        '06', // Saint Joseph Parish
-        '07', // Saint Luke Parish
-        '08', // Saint Mark Parish
-        '09', // Saint Patrick Parish
-        '10', // Saint Paul Parish
-        '11', // Saint Peter Parish
+        '01', // Saint Peter
+        '02', // Saint Andrew
+        '03', // Saint David
+        '04', // Saint George
+        '05', // Saint John
+        '06', // Saint Joseph
+        '07', // Saint Luke
+        '08', // Saint Mark
+        '09', // Saint Patrick
+        '10', // Saint Paul
     ];
 
     public $compareIdentical = true;
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/DoSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/DoSubdivisionCode.php
index 437f5decddd94fda6f132dff3c8ee96d5244defe..2f528859f0e9d9e915001203823d9a7bb4c51204 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/DoSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/DoSubdivisionCode.php
@@ -18,39 +18,39 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: DO
  *
- * @link http://www.geonames.org/DO/administrative-division-dominican-republic.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class DoSubdivisionCode extends AbstractSearcher
 {
     public $haystack = [
-        '01', // Distrito Nacional
+        '01', // Distrito Nacional (Santo Domingo)
         '02', // Azua
-        '03', // Baoruco
+        '03', // Bahoruco
         '04', // Barahona
-        '05', // Dajabon
+        '05', // Dajabón
         '06', // Duarte
-        '07', // Elias Pina
-        '08', // El Seybo
+        '07', // La Estrelleta [Elías Piña]
+        '08', // El Seybo [El Seibo]
         '09', // Espaillat
         '10', // Independencia
         '11', // La Altagracia
         '12', // La Romana
         '13', // La Vega
-        '14', // Maria Trinidad Sanchez
+        '14', // María Trinidad Sánchez
         '15', // Monte Cristi
         '16', // Pedernales
-        '17', // Peravia (Bani)
+        '17', // Peravia
         '18', // Puerto Plata
         '19', // Salcedo
-        '20', // Samana
-        '21', // San Cristobal
+        '20', // Samaná
+        '21', // San Cristóbal
         '22', // San Juan
-        '23', // San Pedro de Macoris
-        '24', // Sanchez Ramirez
+        '23', // San Pedro de Macorís
+        '24', // Sánchez Ramírez
         '25', // Santiago
-        '26', // Santiago Rodriguez
+        '26', // Santiago Rodríguez
         '27', // Valverde
-        '28', // Monsenor Nouel
+        '28', // Monseñor Nouel
         '29', // Monte Plata
         '30', // Hato Mayor
     ];
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/DzSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/DzSubdivisionCode.php
index 2d5d9f8889faff73ba8d4890e0f3ebf8d8268e0d..85d5abf480049c2055979c51c90108831ffcecf1 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/DzSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/DzSubdivisionCode.php
@@ -18,7 +18,7 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: DZ
  *
- * @link http://www.geonames.org/DZ/administrative-division-algeria.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class DzSubdivisionCode extends AbstractSearcher
 {
@@ -26,38 +26,38 @@ class DzSubdivisionCode extends AbstractSearcher
         '01', // Adrar
         '02', // Chlef
         '03', // Laghouat
-        '04', // Oum el-Bouaghi
+        '04', // Oum el Bouaghi
         '05', // Batna
-        '06', // Bejaia
+        '06', // Béjaïa
         '07', // Biskra
-        '08', // Bechar
+        '08', // Béchar
         '09', // Blida
         '10', // Bouira
         '11', // Tamanghasset
-        '12', // Tebessa
+        '12', // Tébessa
         '13', // Tlemcen
         '14', // Tiaret
         '15', // Tizi Ouzou
         '16', // Alger
         '17', // Djelfa
         '18', // Jijel
-        '19', // Setif
-        '20', // Saida
+        '19', // Sétif
+        '20', // Saïda
         '21', // Skikda
-        '22', // Sidi Bel Abbes
+        '22', // Sidi Bel Abbès
         '23', // Annaba
         '24', // Guelma
         '25', // Constantine
-        '26', // Medea
+        '26', // Médéa
         '27', // Mostaganem
-        '28', // M'Sila
-        '29', // Muaskar
+        '28', // Msila
+        '29', // Mascara
         '30', // Ouargla
         '31', // Oran
         '32', // El Bayadh
         '33', // Illizi
-        '34', // Bordj Bou Arreridj
-        '35', // Boumerdes
+        '34', // Bordj Bou Arréridj
+        '35', // Boumerdès
         '36', // El Tarf
         '37', // Tindouf
         '38', // Tissemsilt
@@ -66,10 +66,10 @@ class DzSubdivisionCode extends AbstractSearcher
         '41', // Souk Ahras
         '42', // Tipaza
         '43', // Mila
-        '44', // Ain Defla
+        '44', // Aïn Defla
         '45', // Naama
-        '46', // Ain Temouchent
-        '47', // Ghardaia
+        '46', // Aïn Témouchent
+        '47', // Ghardaïa
         '48', // Relizane
     ];
 
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/EcSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/EcSubdivisionCode.php
index b38a65cc81dd7f21c0ed87ca7778195332c720eb..1f61a38626e3c7bca6cd471874a38a058f99f796 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/EcSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/EcSubdivisionCode.php
@@ -18,32 +18,32 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: EC
  *
- * @link http://www.geonames.org/EC/administrative-division-ecuador.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class EcSubdivisionCode extends AbstractSearcher
 {
     public $haystack = [
         'A', // Azuay
-        'B', // Bolivar
+        'B', // Bolívar
         'C', // Carchi
         'D', // Orellana
         'E', // Esmeraldas
-        'F', // Canar
+        'F', // Cañar
         'G', // Guayas
         'H', // Chimborazo
         'I', // Imbabura
         'L', // Loja
-        'M', // Manabi
+        'M', // Manabí
         'N', // Napo
         'O', // El Oro
         'P', // Pichincha
-        'R', // Los Rios
+        'R', // Los Ríos
         'S', // Morona-Santiago
         'SD', // Santo Domingo de los Tsáchilas
         'SE', // Santa Elena
         'T', // Tungurahua
-        'U', // Sucumbios
-        'W', // Galapagos
+        'U', // Sucumbíos
+        'W', // Galápagos
         'X', // Cotopaxi
         'Y', // Pastaza
         'Z', // Zamora-Chinchipe
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/EeSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/EeSubdivisionCode.php
index 1e4177db71ea74e0b07b71d11d21a59ffdfe1dc8..6fe7f156c1bed615759ffbab31408f35d309a122 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/EeSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/EeSubdivisionCode.php
@@ -18,26 +18,26 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: EE
  *
- * @link http://www.geonames.org/EE/administrative-division-estonia.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class EeSubdivisionCode extends AbstractSearcher
 {
     public $haystack = [
-        '37', // Harju County
-        '39', // Hiiu County
-        '44', // Ida-Viru County
-        '49', // Jõgeva County
-        '51', // Järva County
-        '57', // Lääne County
-        '59', // Lääne-Viru County
-        '65', // Põlva County
-        '67', // Pärnu County
-        '70', // Rapla County
-        '74', // Saare County
-        '78', // Tartu County
-        '82', // Valga County
-        '84', // Viljandi County
-        '86', // Võru County
+        '37', // Harjumaa
+        '39', // Hiiumaa
+        '44', // Ida-Virumaa
+        '49', // Jõgevamaa
+        '51', // Järvamaa
+        '57', // Läänemaa
+        '59', // Lääne-Virumaa
+        '65', // Põlvamaa
+        '67', // Pärnumaa
+        '70', // Raplamaa
+        '74', // Saaremaa
+        '78', // Tartumaa
+        '82', // Valgamaa
+        '84', // Viljandimaa
+        '86', // Võrumaa
     ];
 
     public $compareIdentical = true;
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/EgSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/EgSubdivisionCode.php
index 452b1da95a1d822f63bf33b290db401ef6dd37e6..e750b112667b9d917675fd0550049a437d89f525 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/EgSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/EgSubdivisionCode.php
@@ -18,40 +18,39 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: EG
  *
- * @link http://www.geonames.org/EG/administrative-division-egypt.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class EgSubdivisionCode extends AbstractSearcher
 {
     public $haystack = [
-        'ALX', // Al Iskandariyah
-        'ASN', // Aswan
-        'AST', // Asyut
+        'ALX', // Al Iskandarīyah
+        'ASN', // Aswān
+        'AST', // Asyūt
         'BA', // Al Bahr al Ahmar
         'BH', // Al Buhayrah
-        'BNS', // Bani Suwayf
-        'C', // Al Qahirah
-        'DK', // Ad Daqahliyah
-        'DT', // Dumyat
-        'FYM', // Al Fayyum
-        'GH', // Al Gharbiyah
-        'GZ', // Al Jizah
-        'IS', // Al Isma'iliyah
-        'JS', // Janub Sina'
-        'KB', // Al Qalyubiyah
+        'BNS', // Banī Suwayf
+        'C', // Al Qāhirah
+        'DK', // Ad Daqahlīyah
+        'DT', // Dumyāt
+        'FYM', // Al Fayyūm
+        'GH', // Al Gharbīyah
+        'GZ', // Al JÄ«zah
+        'HU', // Ḩulwān
+        'IS', // Al Ismā`īlīyah
+        'JS', // Janūb Sīnā'
+        'KB', // Al Qalyūbīyah
         'KFS', // Kafr ash Shaykh
-        'KN', // Qina
-        'LX', // Al UqÅŸur
-        'MN', // Al Minya
-        'MNF', // Al Minufiyah
-        'MT', // Matruh
-        'PTS', // Bur Sa'id
-        'SHG', // Suhaj
-        'SHR', // Ash Sharqiyah
-        'SIN', // Shamal Sina'
-        'SUZ', // As Suways
-        'WAD', // Al Wadi al Jadid
-        'HU', // Helwan
+        'KN', // Qinā
+        'MN', // Al Minyā
+        'MNF', // Al Minūfīyah
+        'MT', // Matrūh
+        'PTS', // BÅ«r Sa`Ä«d
+        'SHG', // Sūhāj
+        'SHR', // Ash Sharqīyah
+        'SIN', // Shamal Sīnā'
         'SU', // As Sādis min Uktūbar
+        'SUZ', // As Suways
+        'WAD', // Al Wādī al Jadīd
     ];
 
     public $compareIdentical = true;
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/EhSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/EhSubdivisionCode.php
index fb0f7cd74c81a536c0bd2b289fe6cc0d4aa555d3..eb4cb31613a35db5cec38fa20690d9291e22ea93 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/EhSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/EhSubdivisionCode.php
@@ -18,7 +18,7 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: EH
  *
- * @link http://www.geonames.org/EH/administrative-division-western-sahara.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class EhSubdivisionCode extends AbstractSearcher
 {
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/ErSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/ErSubdivisionCode.php
index 20a5b952634ec0393badfe93146044c6045b85f6..649911cc107cec105368f03ea6a1f20d5c658bb1 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/ErSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/ErSubdivisionCode.php
@@ -18,17 +18,17 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: ER
  *
- * @link http://www.geonames.org/ER/administrative-division-eritrea.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class ErSubdivisionCode extends AbstractSearcher
 {
     public $haystack = [
-        'AN', // Anseba (Keren)
-        'DK', // Southern Red Sea (Debub-Keih-Bahri)
-        'DU', // Southern (Debub)
-        'GB', // Gash-Barka (Barentu)
-        'MA', // Central (Maekel)
-        'SK', // Northern Red Sea (Semien-Keih-Bahri)
+        'AN', // Ansabā
+        'DK', // Janūbī al Baḩrī al Aḩmar
+        'DU', // Al Janūbī
+        'GB', // Qāsh-Barkah
+        'MA', // Al Awsaţ
+        'SK', // Shimālī al Baḩrī al Aḩmar
     ];
 
     public $compareIdentical = true;
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/EsSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/EsSubdivisionCode.php
index 8f5f03ee1ffed1b23e42e9dcd15c98132c020589..eebf6a853ff5a3d4468349e6578096c18bb23e57 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/EsSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/EsSubdivisionCode.php
@@ -18,51 +18,44 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: ES
  *
- * @link http://www.geonames.org/ES/administrative-division-spain.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class EsSubdivisionCode extends AbstractSearcher
 {
     public $haystack = [
-        'AN', // Comunidad Autónoma de Andalucía
-        'AR', // Comunidad Autónoma de Aragón
-        'AS', // Comunidad Autónoma del Principado de Asturias
-        'CB', // Comunidad Autónoma de Cantabria
-        'CE', // Ceuta
-        'CL', // Comunidad Autónoma de Castilla y León
-        'CM', // Comunidad Autónoma de Castilla-La Mancha
-        'CN', // Comunidad Autónoma de Canarias
-        'CT', // Catalunya
-        'EX', // Comunidad Autónoma de Extremadura
-        'GA', // Comunidad Autónoma de Galicia
-        'IB', // Comunidad Autónoma de las Islas Baleares
-        'MC', // Comunidad Autónoma de la Región de Murcia
-        'MD', // Comunidad de Madrid
-        'ML', // Melilla
-        'NC', // Comunidad Foral de Navarra
-        'PV', // Euskal Autonomia Erkidegoa
-        'RI', // Comunidad Autónoma de La Rioja
-        'VC', // Comunidad Valenciana
         'A', // Alicante
         'AB', // Albacete
         'AL', // Almería
+        'AN', // Andalucía
+        'AR', // Aragón
+        'AS', // Asturias, Principado de
         'AV', // Ávila
         'B', // Barcelona
         'BA', // Badajoz
-        'BI', // Vizcaya
+        'BI', // Bizkaia
         'BU', // Burgos
         'C', // A Coruña
         'CA', // Cádiz
+        'CB', // Cantabria
         'CC', // Cáceres
+        'CE', // Ceuta
+        'CL', // Castilla y León
+        'CM', // Castilla-La Mancha
+        'CN', // Canarias
         'CO', // Córdoba
         'CR', // Ciudad Real
         'CS', // Castellón
+        'CT', // Catalunya
         'CU', // Cuenca
+        'EX', // Extremadura
+        'GA', // Galicia
         'GC', // Las Palmas
         'GI', // Girona
         'GR', // Granada
         'GU', // Guadalajara
         'H', // Huelva
         'HU', // Huesca
+        'IB', // Illes Balears
         'J', // Jaén
         'L', // Lleida
         'LE', // León
@@ -70,25 +63,32 @@ class EsSubdivisionCode extends AbstractSearcher
         'LU', // Lugo
         'M', // Madrid
         'MA', // Málaga
+        'MC', // Murcia, Región de
+        'MD', // Madrid, Comunidad de
+        'ML', // Melilla
         'MU', // Murcia
-        'NA', // Navarra
+        'NA', // Navarra / Nafarroa
+        'NC', // Navarra, Comunidad Foral de / Nafarroako Foru Komunitatea
         'O', // Asturias
         'OR', // Ourense
         'P', // Palencia
-        'PM', // Baleares
+        'PM', // Balears
         'PO', // Pontevedra
+        'PV', // País Vasco / Euskal Herria
+        'RI', // La Rioja
         'S', // Cantabria
         'SA', // Salamanca
         'SE', // Sevilla
         'SG', // Segovia
         'SO', // Soria
-        'SS', // Guipúzcoa
+        'SS', // Gipuzkoa
         'T', // Tarragona
         'TE', // Teruel
         'TF', // Santa Cruz de Tenerife
         'TO', // Toledo
-        'V', // Valencia
+        'V', // Valencia / València
         'VA', // Valladolid
+        'VC', // Valenciana, Comunidad / Valenciana, Comunitat
         'VI', // Álava
         'Z', // Zaragoza
         'ZA', // Zamora
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/EtSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/EtSubdivisionCode.php
index e867967727b63d0a4244f989a18b5456d1877cc9..d9ac62f3e63c7fca1fde0ad78f40a4f54b557a21 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/EtSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/EtSubdivisionCode.php
@@ -18,21 +18,21 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: ET
  *
- * @link http://www.geonames.org/ET/administrative-division-ethiopia.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class EtSubdivisionCode extends AbstractSearcher
 {
     public $haystack = [
-        'AA', // Addis Ababa
-        'AF', // Afar
-        'AM', // Amhara
-        'BE', // Benishangul-Gumaz
-        'DD', // Dire Dawa
-        'GA', // Gambela
-        'HA', // Hariai
-        'OR', // Oromia
-        'SN', // Southern Nations - Nationalities and Peoples Region
-        'SO', // Somali
+        'AA', // Ādīs Ābeba
+        'AF', // Āfar
+        'AM', // Āmara
+        'BE', // BÄ«nshangul Gumuz
+        'DD', // Dirē Dawa
+        'GA', // Gambēla Hizboch
+        'HA', // Hārerī Hizb
+        'OR', // Oromīya
+        'SN', // YeDebub Bihēroch Bihēreseboch na Hizboch
+        'SO', // Sumalē
         'TI', // Tigray
     ];
 
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/FiSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/FiSubdivisionCode.php
index 87655533d9e21c19d6331363617cd2c62c9182e0..08da2a0002c4b38fe09145ab0ac015411e0c6bfb 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/FiSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/FiSubdivisionCode.php
@@ -18,36 +18,30 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: FI
  *
- * @link http://www.geonames.org/FI/administrative-division-finland.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class FiSubdivisionCode extends AbstractSearcher
 {
     public $haystack = [
-        '01', // Ahvenanmaa [Finnish] / Ã…land [Swedish]
-        '02', // Etelä-Karjala [Finnish] / Södra Karelen [Swedish]
-        '03', // Etelä-Pohjanmaa [Finnish] / Södra Österbotten [Swedish]
-        '04', // Etelä-Savo [Finnish] / Södra Savolax [Swedish]
-        '05', // Kainuu [Finnish] / Kajanaland [Swedish]
-        '06', // Kanta-Häme [Finnish] / Egentliga Tavastland [Swedish]
-        '07', // Keski-Pohjanmaa [Finnish] / Mellersta Österbotten [Swedish]
-        '08', // Keski-Suomi [Finnish] / Mellersta Finland [Swedish]
-        '09', // Kymenlaakso [Finnish] / Kymmenedalen [Swedish]
-        '10', // Lappi [Finnish] / Lappland [Swedish]
-        '11', // Pirkanmaa [Finnish] / Birkaland [Swedish]
-        '12', // Pohjanmaa [Finnish] / Österbotten [Swedish]
-        '13', // Pohjois-Karjala [Finnish] / Norra Karelen [Swedish]
-        '14', // Pohjois-Pohjanmaa [Finnish] / Norra Österbotten [Swedish]
-        '15', // Pohjois-Savo [Finnish] / Norra Savolax [Swedish]
-        '16', // Päijät-Häme [Finnish] / Päijänne-Tavastland [Swedish]
-        '17', // Satakunta [Finnish and Swedish]
-        '18', // Uusimaa [Finnish] / Nyland [Swedish]
-        '19', // Varsinais-Suomi [Finnish] / Egentliga Finland [Swedish]
-        'AL', // Ahvenanmaan laani
-        'ES', // Etela-Suomen laani
-        'IS', // Ita-Suomen laani
-        'LL', // Lapin laani
-        'LS', // Lansi-Suomen laani
-        'OL', // Oulun laani
+        '01', // Ahvenanmaan maakunta
+        '02', // Etelä-Karjala
+        '03', // Etelä-Pohjanmaa
+        '04', // Etelä-Savo
+        '05', // Kainuu
+        '06', // Kanta-Häme
+        '07', // Keski-Pohjanmaa
+        '08', // Keski-Suomi
+        '09', // Kymenlaakso
+        '10', // Lappi
+        '11', // Pirkanmaa
+        '12', // Pohjanmaa
+        '13', // Pohjois-Karjala
+        '14', // Pohjois-Pohjanmaa
+        '15', // Pohjois-Savo
+        '16', // Päijät-Häme
+        '17', // Satakunta
+        '18', // Uusimaa
+        '19', // Varsinais-Suomi
     ];
 
     public $compareIdentical = true;
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/FjSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/FjSubdivisionCode.php
index 4fd9a6bf48a1c3088b13bf7e4e8aa1763c199cd2..ca534c28eba8cafb848a26e3b448368379a92f62 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/FjSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/FjSubdivisionCode.php
@@ -18,16 +18,16 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: FJ
  *
- * @link http://www.geonames.org/FJ/administrative-division-fiji.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class FjSubdivisionCode extends AbstractSearcher
 {
     public $haystack = [
-        'C', // Central Division
-        'E', // Eastern Division
-        'N', // Northern Division
+        'C', // Central
+        'E', // Eastern
+        'N', // Northern
         'R', // Rotuma
-        'W', // Western Division
+        'W', // Western
     ];
 
     public $compareIdentical = true;
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/FkSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/FkSubdivisionCode.php
index 4cd525d47d13b21d906fb4f9df0ddfd7addb7bd7..45a9f5faf0e1a20ef33200a708652650c8ede8a4 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/FkSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/FkSubdivisionCode.php
@@ -18,7 +18,7 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: FK
  *
- * @link http://www.geonames.org/FK/administrative-division-falkland-islands.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class FkSubdivisionCode extends AbstractSearcher
 {
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/FmSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/FmSubdivisionCode.php
index 6bb26367201b70f59fbf952f69be8722412ab9a5..e150aee63116ccce77f477c1c815ce7462ff3443 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/FmSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/FmSubdivisionCode.php
@@ -18,7 +18,7 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: FM
  *
- * @link http://www.geonames.org/FM/administrative-division-micronesia.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class FmSubdivisionCode extends AbstractSearcher
 {
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/FoSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/FoSubdivisionCode.php
index 8fe6df18f1dbf2afbdff392d433c7a374f031caf..b45a1962a2a92467cf8584e21778960bca425980 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/FoSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/FoSubdivisionCode.php
@@ -18,7 +18,7 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: FO
  *
- * @link http://www.geonames.org/FO/administrative-division-faroe-islands.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class FoSubdivisionCode extends AbstractSearcher
 {
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/FrSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/FrSubdivisionCode.php
index 0f64a2e8715067498b8415d439c4a491b6e03ce6..912d955f2917908d0c653581f8590bd55f27fca8 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/FrSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/FrSubdivisionCode.php
@@ -18,28 +18,12 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: FR
  *
- * @link http://www.geonames.org/FR/administrative-division-france.html
- * @link https://www.iso.org/obp/ui/en/#iso:code:3166:FR
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class FrSubdivisionCode extends AbstractSearcher
 {
     public $haystack = [
-        'ARA', // Auvergne-Rhône-Alpes
-        'BFC', // Bourgogne-Franche-Comté
-        'BRE', // Bretagne
-        'CVL', // Centre-Val de Loire
-        'COR', // Corse
-        'GES', // Grand Est
-        'GUA', // Guadeloupe
-        'HDF', // Hauts-de-France
-        'IDF', // ÃŽle-de-France
-        'MAY', // Mayotte
-        'NOR', // Normandie
-        'NAQ', // Nouvelle-Aquitaine
-        'OCC', // Occitanie
-        'PDL', // Pays de la Loire
-        'PAC', // Provence-Alpes-Côte d'Azur
-        'LRE', // La Réunion
         '01', // Ain
         '02', // Aisne
         '03', // Allier
@@ -136,19 +120,35 @@ class FrSubdivisionCode extends AbstractSearcher
         '93', // Seine-Saint-Denis
         '94', // Val-de-Marne
         '95', // Val-d'Oise
-        'BL', // Saint Barthélemy (see also separate ISO 3166-1 entry under BL)
+        'ARA', // Auvergne-Rhône-Alpes
+        'BFC', // Bourgogne-Franche-Comté
+        'BL', // Saint-Barthélemy
+        'BRE', // Bretagne
+        'COR', // Corse
         'CP', // Clipperton
-        'GF', // Guyane (française) (see also separate country code entry under GF)
-        'GP', // Guadeloupe (see also separate country code entry under GP)
-        'MF', // Saint Martin (see also separate ISO 3166-1 entry under MF)
-        'MQ', // Martinique (see also separate country code entry under MQ)
-        'NC', // Nouvelle-Calédonie (see also separate ISO 3166-1 entry under NC)
-        'PF', // Polynésie française (see also separate ISO 3166-1 entry under PF)
-        'PM', // Saint-Pierre-et-Miquelon (see also separate ISO 3166-1 entry under PM)
-        'RE', // La Réunion (see also separate country code entry under RE)
-        'TF', // Terres Australes Françaises (see also separate ISO 3166-1 entry under TF)
-        'WF', // Wallis et Futuna (see also separate ISO 3166-1 entry under WF)
-        'YT', // Mayotte (see also separate ISO 3166-1 entry under YT)
+        'CVL', // Centre-Val de Loire
+        'GES', // Grand-Est
+        'GF', // Guyane (française)
+        'GP', // Guadeloupe
+        'GUA', // Guadeloupe
+        'HDF', // Hauts-de-France
+        'IDF', // ÃŽle-de-France
+        'LRE', // La Réunion
+        'MAY', // Mayotte
+        'MF', // Saint-Martin
+        'MQ', // Martinique
+        'NAQ', // Nouvelle-Aquitaine
+        'NC', // Nouvelle-Calédonie
+        'NOR', // Normandie
+        'OCC', // Occitanie
+        'PAC', // Provence-Alpes-Côte-d’Azur
+        'PDL', // Pays-de-la-Loire
+        'PF', // Polynésie française
+        'PM', // Saint-Pierre-et-Miquelon
+        'RE', // La Réunion
+        'TF', // Terres australes françaises
+        'WF', // Wallis-et-Futuna
+        'YT', // Mayotte
     ];
 
     public $compareIdentical = true;
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/GaSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/GaSubdivisionCode.php
index 9eddfc473b58a78f057279c8da3473291f7cf5c4..e6e1c0774364ea3a6c5f66f443beeb0972c6ab8c 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/GaSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/GaSubdivisionCode.php
@@ -18,19 +18,19 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: GA
  *
- * @link http://www.geonames.org/GA/administrative-division-gabon.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class GaSubdivisionCode extends AbstractSearcher
 {
     public $haystack = [
         '1', // Estuaire
-        '2', // Haut-Ogooue
-        '3', // Moyen-Ogooue
-        '4', // Ngounie
+        '2', // Haut-Ogooué
+        '3', // Moyen-Ogooué
+        '4', // Ngounié
         '5', // Nyanga
-        '6', // Ogooue-Ivindo
-        '7', // Ogooue-Lolo
-        '8', // Ogooue-Maritime
+        '6', // Ogooué-Ivindo
+        '7', // Ogooué-Lolo
+        '8', // Ogooué-Maritime
         '9', // Woleu-Ntem
     ];
 
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/GbSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/GbSubdivisionCode.php
index 1ef0bad6cc63f32ec3e98ba8c6e4e332d1f14ab5..091dcdb312ea13ffc6b4cd1964f43201a776f489 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/GbSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/GbSubdivisionCode.php
@@ -18,23 +18,19 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: GB
  *
- * @link http://www.geonames.org/GB/administrative-division-united-kingdom.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class GbSubdivisionCode extends AbstractSearcher
 {
     public $haystack = [
-        'ENG', // England
-        'NIR', // Northern Ireland
-        'SCT', // Scotland
-        'WLS', // Wales
+        'ABC', // Armagh, Banbridge and Craigavon
         'ABD', // Aberdeenshire
-        'ABE', // Aberdeen
+        'ABE', // Aberdeen City
         'AGB', // Argyll and Bute
-        'AGY', // Isle of Anglesey
+        'AGY', // Isle of Anglesey; Sir Ynys Môn
+        'AND', // Ards and North Down
+        'ANN', // Antrim and Newtownabbey
         'ANS', // Angus
-        'ANT', // Antrim
-        'ARD', // Ards
-        'ARM', // Armagh
         'BAS', // Bath and North East Somerset
         'BBD', // Blackburn with Darwen
         'BDF', // Bedford
@@ -42,14 +38,11 @@ class GbSubdivisionCode extends AbstractSearcher
         'BEN', // Brent
         'BEX', // Bexley
         'BFS', // Belfast
-        'BGE', // Bridgend
+        'BGE', // Bridgend; Pen-y-bont ar Ogwr
         'BGW', // Blaenau Gwent
         'BIR', // Birmingham
         'BKM', // Buckinghamshire
-        'BLA', // Ballymena
-        'BLY', // Ballymoney
         'BMH', // Bournemouth
-        'BNB', // Banbridge
         'BNE', // Barnet
         'BNH', // Brighton and Hove
         'BNS', // Barnsley
@@ -58,60 +51,57 @@ class GbSubdivisionCode extends AbstractSearcher
         'BRC', // Bracknell Forest
         'BRD', // Bradford
         'BRY', // Bromley
-        'BST', // Bristol City of
+        'BST', // Bristol, City of
         'BUR', // Bury
         'CAM', // Cambridgeshire
-        'CAY', // Caerphilly
+        'CAY', // Caerphilly; Caerffili
         'CBF', // Central Bedfordshire
-        'CGN', // Ceredigion
-        'CGV', // Craigavon
+        'CCG', // Causeway Coast and Glens
+        'CGN', // Ceredigion; Sir Ceredigion
         'CHE', // Cheshire East
         'CHW', // Cheshire West and Chester
-        'CKF', // Carrickfergus
-        'CKT', // Cookstown
         'CLD', // Calderdale
         'CLK', // Clackmannanshire
-        'CLR', // Coleraine
         'CMA', // Cumbria
         'CMD', // Camden
-        'CMN', // Carmarthenshire
+        'CMN', // Carmarthenshire; Sir Gaerfyrddin
         'CON', // Cornwall
-        'COV', // Coventry (West Midlands district)
-        'CRF', // Cardiff
+        'COV', // Coventry
+        'CRF', // Cardiff; Caerdydd
         'CRY', // Croydon
-        'CSR', // Castlereagh
         'CWY', // Conwy
         'DAL', // Darlington
         'DBY', // Derbyshire
-        'DEN', // Denbighshire
+        'DEN', // Denbighshire; Sir Ddinbych
         'DER', // Derby
         'DEV', // Devon
-        'DGN', // Dungannon and South Tyrone
         'DGY', // Dumfries and Galloway
         'DNC', // Doncaster
-        'DND', // Dundee
+        'DND', // Dundee City
         'DOR', // Dorset
-        'DOW', // Down
-        'DRY', // Derry
-        'DUD', // Dudley (West Midlands district)
-        'DUR', // Durham
+        'DRS', // Derry and Strabane
+        'DUD', // Dudley
+        'DUR', // Durham County
         'EAL', // Ealing
+        'EAW', // England and Wales
         'EAY', // East Ayrshire
-        'EDH', // Edinburgh
+        'EDH', // Edinburgh, City of
         'EDU', // East Dunbartonshire
         'ELN', // East Lothian
         'ELS', // Eilean Siar
         'ENF', // Enfield
+        'ENG', // England
         'ERW', // East Renfrewshire
         'ERY', // East Riding of Yorkshire
         'ESS', // Essex
         'ESX', // East Sussex
         'FAL', // Falkirk
-        'FER', // Fermanagh
         'FIF', // Fife
-        'FLN', // Flintshire
-        'GAT', // Gateshead (Tyne
-        'GLG', // Glasgow
+        'FLN', // Flintshire; Sir y Fflint
+        'FMO', // Fermanagh and Omagh
+        'GAT', // Gateshead
+        'GBN', // Great Britain
+        'GLG', // Glasgow City
         'GLS', // Gloucestershire
         'GRE', // Greenwich
         'GWN', // Gwynedd
@@ -119,7 +109,7 @@ class GbSubdivisionCode extends AbstractSearcher
         'HAM', // Hampshire
         'HAV', // Havering
         'HCK', // Hackney
-        'HEF', // Herefordshire County of
+        'HEF', // Herefordshire
         'HIL', // Hillingdon
         'HLD', // Highland
         'HMF', // Hammersmith and Fulham
@@ -128,16 +118,18 @@ class GbSubdivisionCode extends AbstractSearcher
         'HRT', // Hertfordshire
         'HRW', // Harrow
         'HRY', // Haringey
+        'IOS', // Isles of Scilly
         'IOW', // Isle of Wight
         'ISL', // Islington
         'IVC', // Inverclyde
         'KEC', // Kensington and Chelsea
         'KEN', // Kent
-        'KHL', // Kingston upon Hull City of
+        'KHL', // Kingston upon Hull
         'KIR', // Kirklees
         'KTT', // Kingston upon Thames
         'KWL', // Knowsley
         'LAN', // Lancashire
+        'LBC', // Lisburn and Castlereagh
         'LBH', // Lambeth
         'LCE', // Leicester
         'LDS', // Leeds
@@ -145,46 +137,41 @@ class GbSubdivisionCode extends AbstractSearcher
         'LEW', // Lewisham
         'LIN', // Lincolnshire
         'LIV', // Liverpool
-        'LMV', // Limavady
-        'LND', // London City of
-        'LRN', // Larne
-        'LSB', // Lisburn
+        'LND', // London, City of
         'LUT', // Luton
         'MAN', // Manchester
         'MDB', // Middlesbrough
         'MDW', // Medway
-        'MFT', // Magherafelt
+        'MEA', // Mid and East Antrim
         'MIK', // Milton Keynes
         'MLN', // Midlothian
-        'MON', // Monmouthshire
+        'MON', // Monmouthshire; Sir Fynwy
         'MRT', // Merton
         'MRY', // Moray
-        'MTY', // Merthyr Tydfil
-        'MYL', // Moyle
+        'MTY', // Merthyr Tydfil; Merthyr Tudful
+        'MUL', // Mid Ulster
         'NAY', // North Ayrshire
         'NBL', // Northumberland
-        'NDN', // North Down
         'NEL', // North East Lincolnshire
         'NET', // Newcastle upon Tyne
         'NFK', // Norfolk
         'NGM', // Nottingham
+        'NIR', // Northern Ireland
         'NLK', // North Lanarkshire
         'NLN', // North Lincolnshire
+        'NMD', // Newry, Mourne and Down
         'NSM', // North Somerset
-        'NTA', // Newtownabbey
         'NTH', // Northamptonshire
-        'NTL', // Neath Port Talbot
+        'NTL', // Neath Port Talbot; Castell-nedd Port Talbot
         'NTT', // Nottinghamshire
         'NTY', // North Tyneside
         'NWM', // Newham
-        'NWP', // Newport
+        'NWP', // Newport; Casnewydd
         'NYK', // North Yorkshire
-        'NYM', // Newry and Mourne
         'OLD', // Oldham
-        'OMH', // Omagh
         'ORK', // Orkney Islands
         'OXF', // Oxfordshire
-        'PEM', // Pembrokeshire
+        'PEM', // Pembrokeshire; Sir Benfro
         'PKN', // Perth and Kinross
         'PLY', // Plymouth
         'POL', // Poole
@@ -193,7 +180,7 @@ class GbSubdivisionCode extends AbstractSearcher
         'PTE', // Peterborough
         'RCC', // Redcar and Cleveland
         'RCH', // Rochdale
-        'RCT', // Rhondda Cynon Taf
+        'RCT', // Rhondda, Cynon, Taff; Rhondda, Cynon, Taf
         'RDB', // Redbridge
         'RDG', // Reading
         'RFW', // Renfrewshire
@@ -202,12 +189,13 @@ class GbSubdivisionCode extends AbstractSearcher
         'RUT', // Rutland
         'SAW', // Sandwell
         'SAY', // South Ayrshire
-        'SCB', // Scottish Borders The
+        'SCB', // Scottish Borders, The
+        'SCT', // Scotland
         'SFK', // Suffolk
         'SFT', // Sefton
         'SGC', // South Gloucestershire
         'SHF', // Sheffield
-        'SHN', // St Helens
+        'SHN', // St. Helens
         'SHR', // Shropshire
         'SKP', // Stockport
         'SLF', // Salford
@@ -218,7 +206,6 @@ class GbSubdivisionCode extends AbstractSearcher
         'SOM', // Somerset
         'SOS', // Southend-on-Sea
         'SRY', // Surrey
-        'STB', // Strabane
         'STE', // Stoke-on-Trent
         'STG', // Stirling
         'STH', // Southampton
@@ -226,17 +213,18 @@ class GbSubdivisionCode extends AbstractSearcher
         'STS', // Staffordshire
         'STT', // Stockton-on-Tees
         'STY', // South Tyneside
-        'SWA', // Swansea
+        'SWA', // Swansea; Abertawe
         'SWD', // Swindon
         'SWK', // Southwark
         'TAM', // Tameside
         'TFW', // Telford and Wrekin
         'THR', // Thurrock
         'TOB', // Torbay
-        'TOF', // Torfaen
+        'TOF', // Torfaen; Tor-faen
         'TRF', // Trafford
         'TWH', // Tower Hamlets
-        'VGL', // Vale of Glamorgan
+        'UKM', // United Kingdom
+        'VGL', // Vale of Glamorgan, The; Bro Morgannwg
         'WAR', // Warwickshire
         'WBK', // West Berkshire
         'WDU', // West Dunbartonshire
@@ -246,6 +234,7 @@ class GbSubdivisionCode extends AbstractSearcher
         'WKF', // Wakefield
         'WLL', // Walsall
         'WLN', // West Lothian
+        'WLS', // Wales; Cymru
         'WLV', // Wolverhampton
         'WND', // Wandsworth
         'WNM', // Windsor and Maidenhead
@@ -253,13 +242,11 @@ class GbSubdivisionCode extends AbstractSearcher
         'WOR', // Worcestershire
         'WRL', // Wirral
         'WRT', // Warrington
-        'WRX', // Wrexham
+        'WRX', // Wrexham; Wrecsam
         'WSM', // Westminster
         'WSX', // West Sussex
         'YOR', // York
         'ZET', // Shetland Islands
-        'BDF', // Bedfordshire
-        'CHS', // Cheshire
     ];
 
     public $compareIdentical = true;
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/GdSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/GdSubdivisionCode.php
index e8272a81a9fbf547d832cfbcf7eb64a920da3349..c6f732dc7a178f2dff21dde964141c0e0700629f 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/GdSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/GdSubdivisionCode.php
@@ -18,7 +18,7 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: GD
  *
- * @link http://www.geonames.org/GD/administrative-division-grenada.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class GdSubdivisionCode extends AbstractSearcher
 {
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/GeSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/GeSubdivisionCode.php
index 6ab737fc0abae180d5178789950059ad68a56ea8..af8d018687f74d2bf3d4ddb7ec9b4ed9a18f2e2d 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/GeSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/GeSubdivisionCode.php
@@ -18,7 +18,7 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: GE
  *
- * @link http://www.geonames.org/GE/administrative-division-georgia.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class GeSubdivisionCode extends AbstractSearcher
 {
@@ -26,15 +26,15 @@ class GeSubdivisionCode extends AbstractSearcher
         'AB', // Abkhazia
         'AJ', // Ajaria
         'GU', // Guria
-        'IM', // Imereti
-        'KA', // Kakheti
-        'KK', // Kvemo Kartli
-        'MM', // Mtskheta-Mtianeti
-        'RL', // Racha Lechkhumi and Kvemo Svaneti
-        'SJ', // Samtskhe-Javakheti
-        'SK', // Shida Kartli
-        'SZ', // Samegrelo-Zemo Svaneti
-        'TB', // Tbilisi
+        'IM', // Imeret’i
+        'KA', // Kakhet’i
+        'KK', // K’vemo K’art’li
+        'MM', // Mts’khet’a-Mt’ianet’i
+        'RL', // Racha-Lech’khumi-K’vemo Svanet’i
+        'SJ', // Samts’khe-Javakhet’i
+        'SK', // Shida K’art’li
+        'SZ', // Samegrelo-Zemo Svanet’i
+        'TB', // T’bilisi
     ];
 
     public $compareIdentical = true;
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/GfSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/GfSubdivisionCode.php
index 4e0ea66633aecbd28efcbb8a8cb8380a085ff33d..723bae6b21c52ae57cbd1a90f0529849ccd7ff3f 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/GfSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/GfSubdivisionCode.php
@@ -18,7 +18,7 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: GF
  *
- * @link http://www.geonames.org/GF/administrative-division-french-guiana.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class GfSubdivisionCode extends AbstractSearcher
 {
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/GgSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/GgSubdivisionCode.php
index 5d9e8d5c8a06c1ed61f3fe1282dc1be97de55dde..7447043f395e04da233da4541856e0b5b91b6033 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/GgSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/GgSubdivisionCode.php
@@ -18,7 +18,7 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: GG
  *
- * @link http://www.geonames.org/GG/administrative-division-guernsey.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class GgSubdivisionCode extends AbstractSearcher
 {
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/GhSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/GhSubdivisionCode.php
index d6a06d88459ea74c3735c9355b876e0d3f9650a6..7bdfb98ae5132c9d374c3e03dd2e87d0a1d6c7fd 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/GhSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/GhSubdivisionCode.php
@@ -18,21 +18,21 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: GH
  *
- * @link http://www.geonames.org/GH/administrative-division-ghana.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class GhSubdivisionCode extends AbstractSearcher
 {
     public $haystack = [
-        'AA', // Greater Accra Region
-        'AH', // Ashanti Region
-        'BA', // Brong-Ahafo Region
-        'CP', // Central Region
-        'EP', // Eastern Region
-        'NP', // Northern Region
-        'TV', // Volta Region
-        'UE', // Upper East Region
-        'UW', // Upper West Region
-        'WP', // Western Region
+        'AA', // Greater Accra
+        'AH', // Ashanti
+        'BA', // Brong-Ahafo
+        'CP', // Central
+        'EP', // Eastern
+        'NP', // Northern
+        'TV', // Volta
+        'UE', // Upper East
+        'UW', // Upper West
+        'WP', // Western
     ];
 
     public $compareIdentical = true;
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/GiSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/GiSubdivisionCode.php
index 5d7d877c7523b05c76835862e3eac4fb3db8da3e..9ff9831f351d3e8ed7e0387a077133ba7605f39b 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/GiSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/GiSubdivisionCode.php
@@ -18,7 +18,7 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: GI
  *
- * @link http://www.geonames.org/GI/administrative-division-gibraltar.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class GiSubdivisionCode extends AbstractSearcher
 {
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/GlSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/GlSubdivisionCode.php
index 71f96585b2dddcb6413b253e70916250e1a0b630..3eeaab2ab17b1ebc9049489356116c29a7e7f23c 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/GlSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/GlSubdivisionCode.php
@@ -18,15 +18,15 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: GL
  *
- * @link http://www.geonames.org/GL/administrative-division-greenland.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class GlSubdivisionCode extends AbstractSearcher
 {
     public $haystack = [
-        'KU', // Kujalleq
-        'QA', // Qaasuitsup
-        'QE', // Qeqqata
-        'SM', // Sermersooq
+        'KU', // Kommune Kujalleq
+        'QA', // Qaasuitsup Kommunia
+        'QE', // Qeqqata Kommunia
+        'SM', // Kommuneqarfik Sermersooq
     ];
 
     public $compareIdentical = true;
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/GmSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/GmSubdivisionCode.php
index 318959e99bd48c99d68493a479053459d80301e4..6d97d8e74b3e5db896176587e4c73ea8d35428c7 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/GmSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/GmSubdivisionCode.php
@@ -18,7 +18,7 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: GM
  *
- * @link http://www.geonames.org/GM/administrative-division-gambia.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class GmSubdivisionCode extends AbstractSearcher
 {
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/GnSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/GnSubdivisionCode.php
index 42a197c78683e656263b4bc16acd6892fd831011..8ee5b9dfa4aac44fa0db77bb6a02a9779e4bc017 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/GnSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/GnSubdivisionCode.php
@@ -18,51 +18,51 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: GN
  *
- * @link http://www.geonames.org/GN/administrative-division-guinea.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class GnSubdivisionCode extends AbstractSearcher
 {
     public $haystack = [
         'B', // Boké
-        'C', // Conakry
-        'D', // Kindia
-        'F', // Faranah
-        'K', // Kankan
-        'L', // Labé
-        'M', // Mamou
-        'N', // Nzérékoré
         'BE', // Beyla
         'BF', // Boffa
-        'BK', // Boke
+        'BK', // Boké
+        'C', // Conakry
         'CO', // Coyah
+        'D', // Kindia
         'DB', // Dabola
         'DI', // Dinguiraye
         'DL', // Dalaba
-        'DU', // Dubreka
+        'DU', // Dubréka
+        'F', // Faranah
         'FA', // Faranah
-        'FO', // Forecariah
+        'FO', // Forécariah
         'FR', // Fria
         'GA', // Gaoual
-        'GU', // Gueckedou
+        'GU', // Guékédou
+        'K', // Kankan
         'KA', // Kankan
         'KB', // Koubia
         'KD', // Kindia
-        'KE', // Kerouane
+        'KE', // Kérouané
         'KN', // Koundara
         'KO', // Kouroussa
         'KS', // Kissidougou
-        'LA', // Labe
-        'LE', // Lelouma
+        'L', // Labé
+        'LA', // Labé
+        'LE', // Lélouma
         'LO', // Lola
+        'M', // Mamou
         'MC', // Macenta
         'MD', // Mandiana
         'ML', // Mali
         'MM', // Mamou
-        'NZ', // Nzerekore
+        'N', // Nzérékoré
+        'NZ', // Nzérékoré
         'PI', // Pita
         'SI', // Siguiri
-        'TE', // Telimele
-        'TO', // Tougue
+        'TE', // Télimélé
+        'TO', // Tougué
         'YO', // Yomou
     ];
 
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/GpSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/GpSubdivisionCode.php
index 16c15e005239e02b6982f4a813bfa9a96a27365d..198d51f3eaca57ed6512ebff7bfb26ed757e3ea6 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/GpSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/GpSubdivisionCode.php
@@ -18,7 +18,7 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: GP
  *
- * @link http://www.geonames.org/GP/administrative-division-guadeloupe.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class GpSubdivisionCode extends AbstractSearcher
 {
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/GqSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/GqSubdivisionCode.php
index 452bb732469c36cbc2a22d47e6cfb05d7dbf838b..1f8d667129c3fa2c7728b7a86d2bfe7e1d79fabf 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/GqSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/GqSubdivisionCode.php
@@ -18,20 +18,20 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: GQ
  *
- * @link http://www.geonames.org/GQ/administrative-division-equatorial-guinea.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class GqSubdivisionCode extends AbstractSearcher
 {
     public $haystack = [
+        'AN', // Annobón
+        'BN', // Bioko Norte
+        'BS', // Bioko Sur
         'C', // Región Continental
+        'CS', // Centro Sur
         'I', // Región Insular
-        'AN', // Provincia Annobon
-        'BN', // Provincia Bioko Norte
-        'BS', // Provincia Bioko Sur
-        'CS', // Provincia Centro Sur
-        'KN', // Provincia Kie-Ntem
-        'LI', // Provincia Litoral
-        'WN', // Provincia Wele-Nzas
+        'KN', // Kié-Ntem
+        'LI', // Litoral
+        'WN', // Wele-Nzas
     ];
 
     public $compareIdentical = true;
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/GrSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/GrSubdivisionCode.php
index cf4ac022cf0d94fc19ddacce0b4c597a950daf42..d4d0840f06c2e87b5ab9c7116e93465181f66efc 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/GrSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/GrSubdivisionCode.php
@@ -18,13 +18,64 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: GR
  *
- * @link http://www.geonames.org/GR/administrative-division-greece.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class GrSubdivisionCode extends AbstractSearcher
 {
     public $haystack = [
+        '01', // Aitolia kai Akarnania
+        '03', // Voiotia
+        '04', // Evvoias
+        '05', // Evrytania
+        '06', // Fthiotida
+        '07', // Fokida
+        '11', // Argolida
+        '12', // Arkadia
+        '13', // Achaïa
+        '14', // Ileia
+        '15', // Korinthia
+        '16', // Lakonia
+        '17', // Messinia
+        '21', // Zakynthos
+        '22', // Kerkyra
+        '23', // Kefallonia
+        '24', // Lefkada
+        '31', // Arta
+        '32', // Thesprotia
+        '33', // Ioannina
+        '34', // Preveza
+        '41', // Karditsa
+        '42', // Larisa
+        '43', // Magnisia
+        '44', // Trikala
+        '51', // Grevena
+        '52', // Drama
+        '53', // Imathia
+        '54', // Thessaloniki
+        '55', // Kavala
+        '56', // Kastoria
+        '57', // Kilkis
+        '58', // Kozani
+        '59', // Pella
+        '61', // Pieria
+        '62', // Serres
+        '63', // Florina
+        '64', // Chalkidiki
         '69', // Agio Oros
+        '71', // Evros
+        '72', // Xanthi
+        '73', // Rodopi
+        '81', // Dodekanisos
+        '82', // Kyklades
+        '83', // Lesvos
+        '84', // Samos
+        '85', // Chios
+        '91', // Irakleio
+        '92', // Lasithi
+        '93', // Rethymno
+        '94', // Chania
         'A', // Anatoliki Makedonia kai Thraki
+        'A1', // Attiki
         'B', // Kentriki Makedonia
         'C', // Dytiki Makedonia
         'D', // Ipeiros
@@ -37,57 +88,6 @@ class GrSubdivisionCode extends AbstractSearcher
         'K', // Voreio Aigaio
         'L', // Notio Aigaio
         'M', // Kriti
-        '01', // Nomós Aitolías kai Akarnanías
-        '03', // Nomós Voiotías
-        '04', // Nomós Evvoías
-        '05', // Nomós Evrytanías
-        '06', // Nomós Fthiótidos
-        '07', // Nomós Fokídos
-        '11', // Nomós Argolídos
-        '12', // Nomós Arkadías
-        '13', // Nomós Achaḯas
-        '14', // Nomós Ileías
-        '15', // Nomós Korinthías
-        '16', // Nomós Lakonías
-        '17', // Nomós Messinías
-        '21', // Nomós Zakýnthou
-        '22', // Nomós Kerkýras
-        '23', // Nomós Kefallinías
-        '24', // Nomós Lefkádas
-        '31', // Nomós Ártis
-        '32', // Nomós Thesprotías
-        '33', // Nomós Ioannínon
-        '34', // Nomós Prevézis
-        '41', // Nomós Kardhítsas
-        '42', // Nomós Larísis
-        '43', // Nomós Magnisías
-        '44', // Nomós Trikálon
-        '51', // Nomós Grevenón
-        '52', // Nomós Drámas
-        '53', // Nomós Imathías
-        '54', // Nomós Thessaloníkis
-        '55', // Nomós Kaválas
-        '56', // Nomós Kastoriás
-        '57', // Nomós Kilkís
-        '58', // Nomós Kozánis
-        '59', // Nomós Péllis
-        '61', // Nomós Pierías
-        '62', // Nomós Serrón
-        '63', // Nomós Florínis
-        '64', // Nomós Chalkidikís
-        '71', // Nomós Évrou
-        '72', // Nomós Xánthis
-        '73', // Nomós Rodópis
-        '81', // Nomós Dodekanísou
-        '82', // Nomós Kykládon
-        '83', // Nomós Lésvou
-        '84', // Nomós Sámou
-        '85', // Nomós Chíou
-        '91', // Nomós Irakleíou
-        '92', // Nomós Lasithíou
-        '93', // Nomós Rethýmnis
-        '94', // Nomós Chaniás
-        'A1', // Nomós Attikís
     ];
 
     public $compareIdentical = true;
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/GsSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/GsSubdivisionCode.php
index d2f4c68fffca1087970c9ee5e8137206e3b7e8c3..b6f04974d05556b205b224a10844fbb206dc331c 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/GsSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/GsSubdivisionCode.php
@@ -18,7 +18,7 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: GS
  *
- * @link http://www.geonames.org/GS/administrative-division-south-georgia-and-the-south-sandwich-islands.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class GsSubdivisionCode extends AbstractSearcher
 {
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/GtSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/GtSubdivisionCode.php
index 1507027a0b383dc60f9a2f88dc0df42e4ad2d19d..49b90e2b8b6b2bf6e42f4765cbb37a2fbf4ceb10 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/GtSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/GtSubdivisionCode.php
@@ -18,7 +18,7 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: GT
  *
- * @link http://www.geonames.org/GT/administrative-division-guatemala.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class GtSubdivisionCode extends AbstractSearcher
 {
@@ -33,17 +33,17 @@ class GtSubdivisionCode extends AbstractSearcher
         'IZ', // Izabal
         'JA', // Jalapa
         'JU', // Jutiapa
-        'PE', // El Peten
+        'PE', // Petén
         'PR', // El Progreso
-        'QC', // El Quiche
+        'QC', // Quiché
         'QZ', // Quetzaltenango
         'RE', // Retalhuleu
-        'SA', // Sacatepequez
+        'SA', // Sacatepéquez
         'SM', // San Marcos
-        'SO', // Solola
+        'SO', // Sololá
         'SR', // Santa Rosa
-        'SU', // Suchitepequez
-        'TO', // Totonicapan
+        'SU', // Suchitepéquez
+        'TO', // Totonicapán
         'ZA', // Zacapa
     ];
 
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/GuSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/GuSubdivisionCode.php
index ecf777e15230684d8e5fe142e44840f221c12c23..40e4ad2c891bbeffad894ade24ba828e0d6fb34c 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/GuSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/GuSubdivisionCode.php
@@ -18,7 +18,7 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: GU
  *
- * @link http://www.geonames.org/GU/administrative-division-guam.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class GuSubdivisionCode extends AbstractSearcher
 {
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/GwSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/GwSubdivisionCode.php
index 146900d99692cfbe447c79b19e0f1c8b9be66fe1..5db0d23a9b9922f44a7222ca209d125e29d8dd87 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/GwSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/GwSubdivisionCode.php
@@ -18,23 +18,23 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: GW
  *
- * @link http://www.geonames.org/GW/administrative-division-guinea-bissau.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class GwSubdivisionCode extends AbstractSearcher
 {
     public $haystack = [
+        'BA', // Bafatá
+        'BL', // Bolama
+        'BM', // Biombo
+        'BS', // Bissau
+        'CA', // Cacheu
+        'GA', // Gabú
         'L', // Leste
         'N', // Norte
+        'OI', // Oio
+        'QU', // Quinara
         'S', // Sul
-        'BA', // Bafata Region
-        'BL', // Bolama Region
-        'BM', // Biombo Region
-        'BS', // Bissau Region
-        'CA', // Cacheu Region
-        'GA', // Gabu Region
-        'OI', // Oio Region
-        'QU', // Quinara Region
-        'TO', // Tombali Region
+        'TO', // Tombali
     ];
 
     public $compareIdentical = true;
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/GySubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/GySubdivisionCode.php
index 2ce6929f1ef96362ad51a153381e7208e1f7eb6e..f350f602191bebd89252b3e69ee40d98d13fa2ad 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/GySubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/GySubdivisionCode.php
@@ -18,7 +18,7 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: GY
  *
- * @link http://www.geonames.org/GY/administrative-division-guyana.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class GySubdivisionCode extends AbstractSearcher
 {
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/HkSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/HkSubdivisionCode.php
index 41830d4cd39cd599d1608a865524dab6d6ea798c..d51be6c6b5b71d38ae5d537b1e2bbec6dd5814a3 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/HkSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/HkSubdivisionCode.php
@@ -18,7 +18,7 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: HK
  *
- * @link http://www.geonames.org/HK/administrative-division-hong-kong.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class HkSubdivisionCode extends AbstractSearcher
 {
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/HmSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/HmSubdivisionCode.php
index d29c7e16e7c4c843fb146c2f1b60734e19d3d12c..53834340ca1262cb728a9e4488b154da07e712a3 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/HmSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/HmSubdivisionCode.php
@@ -18,7 +18,7 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: HM
  *
- * @link http://www.geonames.org/HM/administrative-division-heard-island-and-mcdonald-islands.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class HmSubdivisionCode extends AbstractSearcher
 {
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/HnSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/HnSubdivisionCode.php
index d714a493fa5d9b0f4fb720ef337b03637ae65338..4e2292df8a1a969f6cf37f26f098c14245f19c3c 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/HnSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/HnSubdivisionCode.php
@@ -18,27 +18,27 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: HN
  *
- * @link http://www.geonames.org/HN/administrative-division-honduras.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class HnSubdivisionCode extends AbstractSearcher
 {
     public $haystack = [
-        'AT', // Atlantida
+        'AT', // Atlántida
         'CH', // Choluteca
-        'CL', // Colon
+        'CL', // Colón
         'CM', // Comayagua
-        'CP', // Copan
-        'CR', // Cortes
-        'EP', // El Paraiso
-        'FM', // Francisco Morazan
+        'CP', // Copán
+        'CR', // Cortés
+        'EP', // El Paraíso
+        'FM', // Francisco Morazán
         'GD', // Gracias a Dios
-        'IB', // Islas de la Bahia (Bay Islands)
-        'IN', // Intibuca
+        'IB', // Islas de la Bahía
+        'IN', // Intibucá
         'LE', // Lempira
         'LP', // La Paz
         'OC', // Ocotepeque
         'OL', // Olancho
-        'SB', // Santa Barbara
+        'SB', // Santa Bárbara
         'VA', // Valle
         'YO', // Yoro
     ];
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/HrSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/HrSubdivisionCode.php
index 884768ac4fd2c4280e0494d07ce701722b479c64..d1e5dc50ae679c0f5ee930775147eb101600defd 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/HrSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/HrSubdivisionCode.php
@@ -18,32 +18,32 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: HR
  *
- * @link http://www.geonames.org/HR/administrative-division-croatia.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class HrSubdivisionCode extends AbstractSearcher
 {
     public $haystack = [
-        '01', // Zagreb county
-        '02', // Krapina-Zagorje county
-        '03', // Sisak-Moslavina county
-        '04', // Karlovac county
-        '05', // Varazdin county
-        '06', // Koprivnica-Krizevci county
-        '07', // Bjelovar-Bilogora county
-        '08', // Primorje-Gorski Kotar county
-        '09', // Lika-Senj county
-        '10', // Virovitica-Podravina county
-        '11', // Pozega-Slavonia county
-        '12', // Brod-Posavina county
-        '13', // Zadar county
-        '14', // Osijek-Baranja county
-        '15', // Sibenik-Knin county
-        '16', // Vukovar-Srijem county
-        '17', // Split-Dalmatia county
-        '18', // Istria county
-        '19', // Dubrovnik-Neretva county
-        '20', // Medjimurje county
-        '21', // Zagreb (city)
+        '01', // Zagrebačka županija
+        '02', // Krapinsko-zagorska županija
+        '03', // Sisačko-moslavačka županija
+        '04', // Karlovačka županija
+        '05', // Varaždinska županija
+        '06', // Koprivničko-križevačka županija
+        '07', // Bjelovarsko-bilogorska županija
+        '08', // Primorsko-goranska županija
+        '09', // Ličko-senjska županija
+        '10', // Virovitičko-podravska županija
+        '11', // Požeško-slavonska županija
+        '12', // Brodsko-posavska županija
+        '13', // Zadarska županija
+        '14', // Osječko-baranjska županija
+        '15', // Šibensko-kninska županija
+        '16', // Vukovarsko-srijemska županija
+        '17', // Splitsko-dalmatinska županija
+        '18', // Istarska županija
+        '19', // Dubrovačko-neretvanska županija
+        '20', // Međimurska županija
+        '21', // Grad Zagreb
     ];
 
     public $compareIdentical = true;
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/HtSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/HtSubdivisionCode.php
index b4ceed793302966af95d8f74704233d64f524d7c..657817035948c7c1381db75db5bb63462c94c4d2 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/HtSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/HtSubdivisionCode.php
@@ -18,14 +18,14 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: HT
  *
- * @link http://www.geonames.org/HT/administrative-division-haiti.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class HtSubdivisionCode extends AbstractSearcher
 {
     public $haystack = [
         'AR', // Artibonite
         'CE', // Centre
-        'GA', // Grand'Anse
+        'GA', // Grande-Anse
         'ND', // Nord
         'NE', // Nord-Est
         'NO', // Nord-Ouest
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/HuSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/HuSubdivisionCode.php
index f3909546a2cc1e5f39c42d42fc827d494958c6ea..f1038c16b36200fb6bea9f1b30cac09454b163a5 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/HuSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/HuSubdivisionCode.php
@@ -18,53 +18,53 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: HU
  *
- * @link http://www.geonames.org/HU/administrative-division-hungary.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class HuSubdivisionCode extends AbstractSearcher
 {
     public $haystack = [
-        'BA', // Baranya megye
+        'BA', // Baranya
         'BC', // Békéscsaba
-        'BE', // Békés megye
-        'BK', // Bács-Kiskun megye
-        'BU', // Budapest főváros
-        'BZ', // Borsod-Abaúj-Zemplén megye
-        'CS', // Csongrád megye
+        'BE', // Békés
+        'BK', // Bács-Kiskun
+        'BU', // Budapest
+        'BZ', // Borsod-Abaúj-Zemplén
+        'CS', // Csongrád
         'DE', // Debrecen
         'DU', // Dunaújváros
-        'EG', // Erd
-        'ER', // Eger
-        'FE', // Fejér megye
-        'GS', // Győr-Moson-Sopron megye
+        'EG', // Eger
+        'ER', // Érd
+        'FE', // Fejér
+        'GS', // Győr-Moson-Sopron
         'GY', // Győr
-        'HB', // Hajdú-Bihar megye
-        'HE', // Heves megye
+        'HB', // Hajdú-Bihar
+        'HE', // Heves
         'HV', // Hódmezővásárhely
-        'JN', // Jász-Nagykun-Szolnok megye
-        'KE', // Komárom-Esztergom megye
+        'JN', // Jász-Nagykun-Szolnok
+        'KE', // Komárom-Esztergom
         'KM', // Kecskemét
         'KV', // Kaposvár
         'MI', // Miskolc
         'NK', // Nagykanizsa
-        'NO', // Nógrád megye
+        'NO', // Nógrád
         'NY', // Nyíregyháza
-        'PE', // Pest megye
+        'PE', // Pest
         'PS', // Pécs
         'SD', // Szeged
         'SF', // Székesfehérvár
         'SH', // Szombathely
         'SK', // Szolnok
         'SN', // Sopron
-        'SO', // Somogy megye
+        'SO', // Somogy
         'SS', // Szekszárd
         'ST', // Salgótarján
-        'SZ', // Szabolcs-Szatmár-Bereg megye
+        'SZ', // Szabolcs-Szatmár-Bereg
         'TB', // Tatabánya
-        'TO', // Tolna megye
-        'VA', // Vas megye
-        'VE', // Veszprém megye
+        'TO', // Tolna
+        'VA', // Vas
+        'VE', // Veszprém (county)
         'VM', // Veszprém
-        'ZA', // Zala megye
+        'ZA', // Zala
         'ZE', // Zalaegerszeg
     ];
 
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/IdSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/IdSubdivisionCode.php
index a3e29c9e8a4c17a341304dc67fc5095d2ca026ca..47369db06a46daebffa0c079ac7584dfdc2231f6 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/IdSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/IdSubdivisionCode.php
@@ -18,49 +18,48 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: ID
  *
- * @link http://www.geonames.org/ID/administrative-division-indonesia.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class IdSubdivisionCode extends AbstractSearcher
 {
     public $haystack = [
-        'IJ', // Papua
-        'JW', // Java
-        'KA', // Kalimantan
-        'MA', // Maluku
-        'NU', // Nusa Tenggara
-        'SL', // Sulawesi
-        'SM', // Sumatera
         'AC', // Aceh
         'BA', // Bali
-        'BB', // Bangka-Belitung
+        'BB', // Bangka Belitung
         'BE', // Bengkulu
         'BT', // Banten
         'GO', // Gorontalo
+        'IJ', // Papua
         'JA', // Jambi
         'JB', // Jawa Barat
         'JI', // Jawa Timur
         'JK', // Jakarta Raya
         'JT', // Jawa Tengah
+        'JW', // Jawa
+        'KA', // Kalimantan
         'KB', // Kalimantan Barat
         'KI', // Kalimantan Timur
-        'KI', // Kalimantan Utara
         'KR', // Kepulauan Riau
         'KS', // Kalimantan Selatan
         'KT', // Kalimantan Tengah
         'LA', // Lampung
         'MA', // Maluku
+        'ML', // Maluku
         'MU', // Maluku Utara
         'NB', // Nusa Tenggara Barat
         'NT', // Nusa Tenggara Timur
+        'NU', // Nusa Tenggara
         'PA', // Papua
         'PB', // Papua Barat
         'RI', // Riau
         'SA', // Sulawesi Utara
-        'SB', // Sumatera Barat
+        'SB', // Sumatra Barat
         'SG', // Sulawesi Tenggara
+        'SL', // Sulawesi
+        'SM', // Sumatera
         'SN', // Sulawesi Selatan
         'SR', // Sulawesi Barat
-        'SS', // Sumatera Selatan
+        'SS', // Sumatra Selatan
         'ST', // Sulawesi Tengah
         'SU', // Sumatera Utara
         'YO', // Yogyakarta
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/IeSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/IeSubdivisionCode.php
index 7043dabe785a802f66879ff1176208a8ba38fe58..083b8d9ed13436f800209359a10b8b27131618f9 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/IeSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/IeSubdivisionCode.php
@@ -18,18 +18,15 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: IE
  *
- * @link http://www.geonames.org/IE/administrative-division-ireland.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class IeSubdivisionCode extends AbstractSearcher
 {
     public $haystack = [
-        'C', // Connaught
-        'L', // Leinster
-        'M', // Munster
-        'U', // Ulster
-        'C', // Cork
+        'C', // Connacht
         'CE', // Clare
         'CN', // Cavan
+        'CO', // Cork
         'CW', // Carlow
         'D', // Dublin
         'DL', // Donegal
@@ -37,11 +34,13 @@ class IeSubdivisionCode extends AbstractSearcher
         'KE', // Kildare
         'KK', // Kilkenny
         'KY', // Kerry
+        'L', // Leinster
         'LD', // Longford
         'LH', // Louth
         'LK', // Limerick
         'LM', // Leitrim
         'LS', // Laois
+        'M', // Munster
         'MH', // Meath
         'MN', // Monaghan
         'MO', // Mayo
@@ -49,6 +48,7 @@ class IeSubdivisionCode extends AbstractSearcher
         'RN', // Roscommon
         'SO', // Sligo
         'TA', // Tipperary
+        'U', // Ulster
         'WD', // Waterford
         'WH', // Westmeath
         'WW', // Wicklow
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/IlSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/IlSubdivisionCode.php
index 4728f94854147a470f149a5197e46948b4ca1d3f..6a9781b6f68b1e99987f13d55bf7f50dd56a680b 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/IlSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/IlSubdivisionCode.php
@@ -18,17 +18,17 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: IL
  *
- * @link http://www.geonames.org/IL/administrative-division-israel.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class IlSubdivisionCode extends AbstractSearcher
 {
     public $haystack = [
-        'D', // Southern
-        'HA', // Haifa
-        'JM', // Jerusalem
-        'M', // Central
-        'TA', // Tel Aviv
-        'Z', // Northern
+        'D', // HaDarom
+        'HA', // Hefa
+        'JM', // Yerushalayim Al Quds
+        'M', // HaMerkaz
+        'TA', // Tel-Aviv
+        'Z', // HaZafon
     ];
 
     public $compareIdentical = true;
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/ImSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/ImSubdivisionCode.php
index 1530f887755deb57df51a35017d5812a097a84c9..2b2c5ec74037af2b580835456b746c6dc860c326 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/ImSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/ImSubdivisionCode.php
@@ -18,7 +18,7 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: IM
  *
- * @link http://www.geonames.org/IM/administrative-division-isle-of-man.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class ImSubdivisionCode extends AbstractSearcher
 {
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/InSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/InSubdivisionCode.php
index 60ae34009ba0c52715f0a7fc5a128631cfdc6bf1..cf332374039635babc1f8f485bebc26c209a767e 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/InSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/InSubdivisionCode.php
@@ -18,7 +18,7 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: IN
  *
- * @link http://www.geonames.org/IN/administrative-division-india.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class InSubdivisionCode extends AbstractSearcher
 {
@@ -48,15 +48,16 @@ class InSubdivisionCode extends AbstractSearcher
         'MP', // Madhya Pradesh
         'MZ', // Mizoram
         'NL', // Nagaland
-        'OR', // Orissa
+        'OR', // Odisha
         'PB', // Punjab
-        'PY', // Pondicherry
+        'PY', // Puducherry
         'RJ', // Rajasthan
         'SK', // Sikkim
+        'TG', // Telangana
         'TN', // Tamil Nadu
         'TR', // Tripura
-        'UL', // Uttaranchal
         'UP', // Uttar Pradesh
+        'UT', // Uttarakhand
         'WB', // West Bengal
     ];
 
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/IoSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/IoSubdivisionCode.php
index 2530c4dd1b144d7fb12a04f7dc5b0cb86348f31d..3ebade7f4f5983ba9ec90cc3878befaf5cb03d18 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/IoSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/IoSubdivisionCode.php
@@ -18,7 +18,7 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: IO
  *
- * @link http://www.geonames.org/IO/administrative-division-british-indian-ocean-territory.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class IoSubdivisionCode extends AbstractSearcher
 {
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/IqSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/IqSubdivisionCode.php
index ef2cc1938ee21119aca2c07fb5273e9a8648ea8d..95ab9c5f784f0833fff4bbb08f92d00de17cf57c 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/IqSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/IqSubdivisionCode.php
@@ -18,28 +18,28 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: IQ
  *
- * @link http://www.geonames.org/IQ/administrative-division-iraq.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class IqSubdivisionCode extends AbstractSearcher
 {
     public $haystack = [
         'AN', // Al Anbar
-        'AR', // Arbīl
+        'AR', // Arbil
         'BA', // Al Basrah
         'BB', // Babil
         'BG', // Baghdad
-        'DA', // Dahūk
+        'DA', // Dahuk
         'DI', // Diyala
         'DQ', // Dhi Qar
-        'KA', // Al Karbala
+        'KA', // Karbala'
         'MA', // Maysan
         'MU', // Al Muthanna
-        'NA', // An Najaf
+        'NA', // An Najef
         'NI', // Ninawa
-        'QA', // Al Qadisyah
+        'QA', // Al Qadisiyah
         'SD', // Salah ad Din
-        'SU', // As Sulaymānīyah
-        'TS', // Kirkūk
+        'SW', // As Sulaymaniyah
+        'TS', // At Ta'mim
         'WA', // Wasit
     ];
 
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/IrSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/IrSubdivisionCode.php
index bee26affa495ff94b7fafef1add284169b2ee3c1..bd6c726a9f63a57eca9951384a794e38c7b01185 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/IrSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/IrSubdivisionCode.php
@@ -18,42 +18,41 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: IR
  *
- * @link http://www.geonames.org/IR/administrative-division-iran.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class IrSubdivisionCode extends AbstractSearcher
 {
     public $haystack = [
-        '01', // East Azarbaijan
-        '02', // West Azarbaijan
-        '03', // Ardabil
-        '04', // Esfahan
-        '05', // Ilam
-        '06', // Bushehr
-        '07', // Tehran
-        '08', // Chahar Mahaal and Bakhtiari
-        '10', // Khuzestan
-        '11', // Zanjan
-        '12', // Semnan
-        '13', // Sistan and Baluchistan
-        '14', // Fars
-        '15', // Kerman
-        '16', // Kurdistan
-        '17', // Kermanshah
-        '18', // Kohkiluyeh and Buyer Ahmad
-        '19', // Gilan
-        '20', // Lorestan
-        '21', // Mazandaran
-        '22', // Markazi
-        '23', // Hormozgan
-        '24', // Hamadan
+        '01', // Āzarbāyjān-e Sharqī
+        '02', // Āzarbāyjān-e Gharbī
+        '03', // Ardabīl
+        '04', // Eşfahān
+        '05', // Īlām
+        '06', // BÅ«shehr
+        '07', // Tehrān
+        '08', // Chahār Mahāll va Bakhtīārī
+        '10', // Khūzestān
+        '11', // Zanjān
+        '12', // Semnān
+        '13', // Sīstān va Balūchestān
+        '14', // Fārs
+        '15', // Kermān
+        '16', // Kordestān
+        '17', // Kermānshāh
+        '18', // Kohgīlūyeh va Būyer Ahmad
+        '19', // Gīlān
+        '20', // Lorestān
+        '21', // Māzandarān
+        '22', // Markazī
+        '23', // Hormozgān
+        '24', // Hamadān
         '25', // Yazd
         '26', // Qom
-        '27', // Golestan
-        '28', // Qazvin
-        '29', // South Khorasan
-        '30', // Razavi Khorasan
-        '31', // North Khorasan
-        '09', // Khorāsān
+        '27', // Golestān
+        '28', // Qazvīn
+        '29', // Khorāsān-e Janūbī
+        '30', // Khorāsān-e Razavī
+        '31', // Khorāsān-e Shemālī
     ];
 
     public $compareIdentical = true;
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/IsSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/IsSubdivisionCode.php
index 7c736c0b54c27324ba68628032680b97d2219434..421ca9d519690381e3527714db6542b8a18900fd 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/IsSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/IsSubdivisionCode.php
@@ -18,17 +18,18 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: IS
  *
- * @link http://www.geonames.org/IS/administrative-division-iceland.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class IsSubdivisionCode extends AbstractSearcher
 {
     public $haystack = [
-        '1', // Höfuðborgarsvæði
+        '0', // Reykjavík
+        '1', // Höfuðborgarsvæðið
         '2', // Suðurnes
         '3', // Vesturland
         '4', // Vestfirðir
-        '5', // Norðurland Vestra
-        '6', // Norðurland Eystra
+        '5', // Norðurland vestra
+        '6', // Norðurland eystra
         '7', // Austurland
         '8', // Suðurland
     ];
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/ItSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/ItSubdivisionCode.php
index fa624a5f6f3bbd6d9e7057d50b49c3bf5b0391fd..d1a0095ad84cece154bf049c1af5405d7bb1f90e 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/ItSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/ItSubdivisionCode.php
@@ -18,31 +18,31 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: IT
  *
- * @link http://www.geonames.org/IT/administrative-division-italy.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class ItSubdivisionCode extends AbstractSearcher
 {
     public $haystack = [
-        '21', // Piedmont
-        '23', // Regione Autonoma Valle d'Aosta
-        '25', // Lombardy
-        '32', // Regione Autonoma Trentino-Alto Adige
-        '34', // Regione del Veneto
-        '36', // Regione Autonoma Friuli-Venezia Giulia
-        '42', // Regione Liguria
-        '45', // Regione Emilia-Romagna
-        '52', // Tuscany
-        '55', // Regione Umbria
-        '57', // Regione Marche
-        '62', // Regione Lazio
-        '65', // Regione Abruzzo
-        '67', // Regione Molise
-        '72', // Regione Campania
-        '75', // Regione Puglia
-        '77', // Regione Basilicata
-        '78', // Regione Calabria
-        '82', // Regione Autonoma Siciliana
-        '88', // Regione Autonoma della Sardegna
+        '21', // Piemonte
+        '23', // Valle d'Aosta
+        '25', // Lombardia
+        '32', // Trentino-Alto Adige
+        '34', // Veneto
+        '36', // Friuli-Venezia Giulia
+        '42', // Liguria
+        '45', // Emilia-Romagna
+        '52', // Toscana
+        '55', // Umbria
+        '57', // Marche
+        '62', // Lazio
+        '65', // Abruzzo
+        '67', // Molise
+        '72', // Campania
+        '75', // Puglia
+        '77', // Basilicata
+        '78', // Calabria
+        '82', // Sicilia
+        '88', // Sardegna
         'AG', // Agrigento
         'AL', // Alessandria
         'AN', // Ancona
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/JeSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/JeSubdivisionCode.php
index a18d79cf62f73418e4651e545d6a52313e099b74..2eed540301653742abc4506d921bfc815bd05d53 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/JeSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/JeSubdivisionCode.php
@@ -18,7 +18,7 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: JE
  *
- * @link http://www.geonames.org/JE/administrative-division-jersey.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class JeSubdivisionCode extends AbstractSearcher
 {
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/JmSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/JmSubdivisionCode.php
index 806e54ab12be9c0b3a214feabb0aca39182639e5..32231fd50cf8c94e64d42dc7a8fd8dcb8232074d 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/JmSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/JmSubdivisionCode.php
@@ -18,25 +18,25 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: JM
  *
- * @link http://www.geonames.org/JM/administrative-division-jamaica.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class JmSubdivisionCode extends AbstractSearcher
 {
     public $haystack = [
-        '01', // Kingston Parish
-        '02', // Saint Andrew Parish
-        '03', // Saint Thomas Parish
-        '04', // Portland Parish
-        '05', // Saint Mary Parish
-        '06', // Saint Ann Parish
-        '07', // Trelawny Parish
-        '08', // Saint James Parish
-        '09', // Hanover Parish
-        '10', // Westmoreland Parish
-        '11', // Saint Elizabeth Parish
-        '12', // Manchester Parish
-        '13', // Clarendon Parish
-        '14', // Saint Catherine Parish
+        '01', // Kingston
+        '02', // Saint Andrew
+        '03', // Saint Thomas
+        '04', // Portland
+        '05', // Saint Mary
+        '06', // Saint Ann
+        '07', // Trelawny
+        '08', // Saint James
+        '09', // Hanover
+        '10', // Westmoreland
+        '11', // Saint Elizabeth
+        '12', // Manchester
+        '13', // Clarendon
+        '14', // Saint Catherine
     ];
 
     public $compareIdentical = true;
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/JoSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/JoSubdivisionCode.php
index 76147cfb0c9380d49da134269965858b7e8a62d1..31acbc0d65d932e28913f3a3407f4d5d4110ad19 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/JoSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/JoSubdivisionCode.php
@@ -18,23 +18,23 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: JO
  *
- * @link http://www.geonames.org/JO/administrative-division-jordan.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class JoSubdivisionCode extends AbstractSearcher
 {
     public $haystack = [
-        'AJ', // Ajlun
-        'AM', // 'Amman
-        'AQ', // Al 'Aqabah
-        'AT', // At Tafilah
-        'AZ', // Az Zarqa'
-        'BA', // Al Balqa'
+        'AJ', // ‘Ajlūn
+        'AM', // ‘Ammān (Al ‘Aşimah)
+        'AQ', // Al ‘Aqabah
+        'AT', // Aţ Ţafīlah
+        'AZ', // Az Zarqā'
+        'BA', // Al Balqā'
         'IR', // Irbid
         'JA', // Jarash
         'KA', // Al Karak
         'MA', // Al Mafraq
-        'MD', // Madaba
-        'MN', // Ma'an
+        'MD', // Mādabā
+        'MN', // Ma‘ān
     ];
 
     public $compareIdentical = true;
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/JpSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/JpSubdivisionCode.php
index 75c65629e93d33cd2b64a9cdd511995743e1aeaa..fc819e0f45319e60a23e8a5744d3a3b4638eb89a 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/JpSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/JpSubdivisionCode.php
@@ -18,57 +18,57 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: JP
  *
- * @link http://www.geonames.org/JP/administrative-division-japan.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class JpSubdivisionCode extends AbstractSearcher
 {
     public $haystack = [
-        '01', // Hokkaidō
+        '01', // Hokkaido
         '02', // Aomori
         '03', // Iwate
         '04', // Miyagi
         '05', // Akita
         '06', // Yamagata
-        '07', // Hukusima (Fukushima)
+        '07', // Fukushima
         '08', // Ibaraki
-        '09', // Totigi (Tochigi)
+        '09', // Tochigi
         '10', // Gunma
         '11', // Saitama
-        '12', // Tiba (Chiba)
+        '12', // Chiba
         '13', // Tokyo
         '14', // Kanagawa
         '15', // Niigata
         '16', // Toyama
-        '17', // Isikawa (Ishikawa)
-        '18', // Hukui (Fukui)
-        '19', // Yamanasi (Yamanashi)
+        '17', // Ishikawa
+        '18', // Fukui
+        '19', // Yamanashi
         '20', // Nagano
-        '21', // Gihu  (Gifu)
-        '22', // Sizuoka (Shizuoka)
-        '23', // Aiti (Aichi)
+        '21', // Gifu
+        '22', // Shizuoka
+        '23', // Aichi
         '24', // Mie
-        '25', // Siga (Shiga)
+        '25', // Shiga
         '26', // Kyoto
         '27', // Osaka
         '28', // Hyogo
         '29', // Nara
         '30', // Wakayama
         '31', // Tottori
-        '32', // Simane (Shimane)
+        '32', // Shimane
         '33', // Okayama
-        '34', // Hirosima (Hiroshima)
-        '35', // Yamaguti (Yamaguchi)
-        '36', // Tokusima (Tokushima)
+        '34', // Hiroshima
+        '35', // Yamaguchi
+        '36', // Tokushima
         '37', // Kagawa
         '38', // Ehime
-        '39', // Koti (Kochi)
-        '40', // Hukuoka (Fukuoka)
+        '39', // Kochi
+        '40', // Fukuoka
         '41', // Saga
         '42', // Nagasaki
         '43', // Kumamoto
         '44', // Oita
         '45', // Miyazaki
-        '46', // Kagosima (Kagoshima)
+        '46', // Kagoshima
         '47', // Okinawa
     ];
 
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/KeSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/KeSubdivisionCode.php
index 418f8c1eee23021a6eaf8f60a454a7269b1f6180..073700775bec5d9ed44cf72490fd12b676faa4c1 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/KeSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/KeSubdivisionCode.php
@@ -18,19 +18,18 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: KE
  *
- * @link http://www.geonames.org/KE/administrative-division-kenya.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class KeSubdivisionCode extends AbstractSearcher
 {
     public $haystack = [
-        '110', // Nairobi Area
+        '110', // Nairobi Municipality
         '200', // Central
         '300', // Coast
         '400', // Eastern
-        '500', // North Eastern
-        '600', // Nyanza
+        '500', // North-Eastern Kaskazini Mashariki
         '700', // Rift Valley
-        '800', // Western
+        '800', // Western Magharibi
     ];
 
     public $compareIdentical = true;
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/KgSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/KgSubdivisionCode.php
index aaf7870420283a4538450d6e6c51d79315554aca..7f4f4e77954a197d29477c1d6a35ebf10f798f78 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/KgSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/KgSubdivisionCode.php
@@ -18,20 +18,19 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: KG
  *
- * @link http://www.geonames.org/KG/administrative-division-kyrgyzstan.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class KgSubdivisionCode extends AbstractSearcher
 {
     public $haystack = [
         'B', // Batken
-        'C', // Chu
+        'C', // Chü
         'GB', // Bishkek
-        'GO', // Osh City
         'J', // Jalal-Abad
         'N', // Naryn
         'O', // Osh
         'T', // Talas
-        'Y', // Ysyk-Kol
+        'Y', // Ysyk-Köl
     ];
 
     public $compareIdentical = true;
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/KhSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/KhSubdivisionCode.php
index 22b2049630523523ee5e68e2e8aae672cc389012..00908ea564033291b4a7068507b128f0b1b66635 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/KhSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/KhSubdivisionCode.php
@@ -18,35 +18,35 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: KH
  *
- * @link http://www.geonames.org/KH/administrative-division-cambodia.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class KhSubdivisionCode extends AbstractSearcher
 {
     public $haystack = [
-        '1', // Banteay Mean Choay
-        '10', // Kratie
-        '11', // Mondul Kiri
+        '1', // Banteay Mean Chey
+        '10', // Krachoh
+        '11', // Mondol Kiri
         '12', // Phnom Penh
         '13', // Preah Vihear
-        '14', // Prey Veng
-        '15', // Pursat
-        '16', // Rôtânôkiri
-        '17', // Siemreap
-        '18', // Preah Seihanu (Kompong Som or Sihanoukville)
-        '19', // Stung Treng
+        '14', // Prey Veaeng
+        '15', // Pousaat
+        '16', // Rotanak Kiri
+        '17', // Siem Reab
+        '18', // Krong Preah Sihanouk
+        '19', // Stueng Traeng
         '2', // Battambang
-        '20', // Svay Rieng
-        '21', // Takeo
-        '22', // Otdar Mean Choay
-        '23', // Keb
-        '24', // Pailin
+        '20', // Svaay Rieng
+        '21', // Taakaev
+        '22', // Otdar Mean Chey
+        '23', // Krong Kaeb
+        '24', // Krong Pailin
         '3', // Kampong Cham
         '4', // Kampong Chhnang
         '5', // Kampong Speu
         '6', // Kampong Thom
         '7', // Kampot
         '8', // Kandal
-        '9', // Kaoh Kong
+        '9', // Kach Kong
     ];
 
     public $compareIdentical = true;
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/KiSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/KiSubdivisionCode.php
index 85fe0dd58a853fbe44d6a46d87a74db2819f9406..8a19b20973fd164ef5bc6fa848e4a8765f7d320b 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/KiSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/KiSubdivisionCode.php
@@ -18,7 +18,7 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: KI
  *
- * @link http://www.geonames.org/KI/administrative-division-kiribati.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class KiSubdivisionCode extends AbstractSearcher
 {
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/KmSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/KmSubdivisionCode.php
index f3303affadca64b9c5e025e594a8ef56c75a61e2..547dea7a37c2af6346d47034ae0613401372028a 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/KmSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/KmSubdivisionCode.php
@@ -18,14 +18,14 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: KM
  *
- * @link http://www.geonames.org/KM/administrative-division-comoros.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class KmSubdivisionCode extends AbstractSearcher
 {
     public $haystack = [
-        'A', // Anjouan
-        'G', // Grande Comore
-        'M', // Moheli
+        'A', // Andjouân (Anjwān)
+        'G', // Andjazîdja (Anjazījah)
+        'M', // Moûhîlî (Mūhīlī)
     ];
 
     public $compareIdentical = true;
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/KnSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/KnSubdivisionCode.php
index de4be2daee57fd153b7ee2bc7cd3c96eff5c3077..fd0dbedc14349c4312427cb2af159754d0c3f665 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/KnSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/KnSubdivisionCode.php
@@ -18,27 +18,27 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: KN
  *
- * @link http://www.geonames.org/KN/administrative-division-saint-kitts-and-nevis.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class KnSubdivisionCode extends AbstractSearcher
 {
     public $haystack = [
-        'K', // Saint Kitts
-        'N', // Nevis
         '01', // Christ Church Nichola Town
         '02', // Saint Anne Sandy Point
         '03', // Saint George Basseterre
         '04', // Saint George Gingerland
         '05', // Saint James Windward
-        '06', // Saint John Capesterre
+        '06', // Saint John Capisterre
         '07', // Saint John Figtree
         '08', // Saint Mary Cayon
-        '09', // Saint Paul Capesterre
+        '09', // Saint Paul Capisterre
         '10', // Saint Paul Charlestown
         '11', // Saint Peter Basseterre
         '12', // Saint Thomas Lowland
         '13', // Saint Thomas Middle Island
         '15', // Trinity Palmetto Point
+        'K', // Saint Kitts
+        'N', // Nevis
     ];
 
     public $compareIdentical = true;
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/KpSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/KpSubdivisionCode.php
index 0338b902d54ac46cbfc28b1cbb4d071f1c4058cd..aa5dab19be623d664c6b659e0539ef95aeba63df 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/KpSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/KpSubdivisionCode.php
@@ -18,21 +18,21 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: KP
  *
- * @link http://www.geonames.org/KP/administrative-division-north-korea.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class KpSubdivisionCode extends AbstractSearcher
 {
     public $haystack = [
-        '01', // P'yongyang Special City
-        '02', // P'yongan-namdo
-        '03', // P'yongan-bukto
+        '01', // P’yŏngyang
+        '02', // P’yŏngan-namdo
+        '03', // P’yŏngan-bukto
         '04', // Chagang-do
         '05', // Hwanghae-namdo
         '06', // Hwanghae-bukto
-        '07', // Kangwon-do
-        '08', // Hamgyong-namdo
-        '09', // Hamgyong-bukto
-        '10', // Ryanggang-do (Yanggang-do)
+        '07', // Kangwŏn-do
+        '08', // Hamgyŏng-namdo
+        '09', // Hamgyŏng-bukto
+        '10', // Yanggang-do
         '13', // Nasŏn (Najin-Sŏnbong)
     ];
 
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/KrSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/KrSubdivisionCode.php
index d76cf6237add718852ff1f3a7f3b429ec2f95794..4e819a63f20bf718b2ab847db29d3335c56af6ee 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/KrSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/KrSubdivisionCode.php
@@ -18,27 +18,27 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: KR
  *
- * @link http://www.geonames.org/KR/administrative-division-south-korea.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class KrSubdivisionCode extends AbstractSearcher
 {
     public $haystack = [
-        '11', // Seoul Special City
-        '26', // Busan Metropolitan City
-        '27', // Daegu Metropolitan City
-        '28', // Incheon Metropolitan City
-        '29', // Gwangju Metropolitan City
-        '30', // Daejeon Metropolitan City
-        '31', // Ulsan Metropolitan City
-        '41', // Gyeonggi-do
-        '42', // Gangwon-do
-        '43', // Chungcheongbuk-do
-        '44', // Chungcheongnam-do
-        '45', // Jeollabuk-do
-        '46', // Jeollanam-do
-        '47', // Gyeongsangbuk-do
-        '48', // Gyeongsangnam-do
-        '49', // Jeju-do
+        '11', // Seoul Teugbyeolsi
+        '26', // Busan Gwang'yeogsi
+        '27', // Daegu Gwang'yeogsi
+        '28', // Incheon Gwang'yeogsi
+        '29', // Gwangju Gwang'yeogsi
+        '30', // Daejeon Gwang'yeogsi
+        '31', // Ulsan Gwang'yeogsi
+        '41', // Gyeonggido
+        '42', // Gang'weondo
+        '43', // Chungcheongbukdo
+        '44', // Chungcheongnamdo
+        '45', // Jeonrabukdo
+        '46', // Jeonranamdo
+        '47', // Gyeongsangbukdo
+        '48', // Gyeongsangnamdo
+        '49', // Jejudo
     ];
 
     public $compareIdentical = true;
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/KwSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/KwSubdivisionCode.php
index cd68bb91bfd6a2ee0e9f3afb9f377e7fa8e66404..16381cfda238a93346fee9cbbb4c7b9f5f4d568f 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/KwSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/KwSubdivisionCode.php
@@ -18,16 +18,16 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: KW
  *
- * @link http://www.geonames.org/KW/administrative-division-kuwait.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class KwSubdivisionCode extends AbstractSearcher
 {
     public $haystack = [
         'AH', // Al Ahmadi
-        'FA', // Al Farwaniyah
-        'HA', // Hawalli
-        'JA', // Al Jahra
-        'KU', // Al Asimah
+        'FA', // Al Farwānīyah
+        'HA', // Hawallī
+        'JA', // Al Jahrrā’
+        'KU', // Al Kuwayt (Al ‘Āşimah)
         'MU', // Mubārak al Kabīr
     ];
 
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/KySubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/KySubdivisionCode.php
index 998d3b2f3cf5e33b1084d64429e483950079bfb5..2d7cf7aa8e10bc1b8af6620cba681793557409c0 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/KySubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/KySubdivisionCode.php
@@ -18,7 +18,7 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: KY
  *
- * @link http://www.geonames.org/KY/administrative-division-cayman-islands.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class KySubdivisionCode extends AbstractSearcher
 {
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/KzSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/KzSubdivisionCode.php
index 6f1daacc04da9d84aa9ea057fcc6f0fd460074bb..14c10c08df9941ab7c6ff2d86b91d649a3284ce0 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/KzSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/KzSubdivisionCode.php
@@ -18,28 +18,27 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: KZ
  *
- * @link http://www.geonames.org/KZ/administrative-division-kazakhstan.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class KzSubdivisionCode extends AbstractSearcher
 {
     public $haystack = [
-        'AKM', // Aqmola
-        'AKT', // Aqtobe
+        'AKM', // Aqmola oblysy
+        'AKT', // Aqtöbe oblysy
         'ALA', // Almaty
-        'ALM', // Almaty
+        'ALM', // Almaty oblysy
         'AST', // Astana
-        'ATY', // Atyrau
-        'BAY', // Baykonyr
-        'KAR', // Qaraghandy
-        'KUS', // Qustanay
-        'KZY', // Qyzylorda
-        'MAN', // Mangghystau
-        'PAV', // Paylodar
-        'SEV', // Soltustik Qazaqstan
-        'VOS', // Shyghys Qazaqstan
-        'YUZ', // Ongtustik Qazaqstan
-        'ZAP', // Baty Qazaqstan
-        'ZHA', // Zhambyl
+        'ATY', // Atyraū oblysy
+        'KAR', // Qaraghandy oblysy
+        'KUS', // Qostanay oblysy
+        'KZY', // Qyzylorda oblysy
+        'MAN', // Mangghystaū oblysy
+        'PAV', // Pavlodar oblysy
+        'SEV', // Soltüstik Quzaqstan oblysy
+        'VOS', // Shyghys Qazaqstan oblysy
+        'YUZ', // Ongtüstik Qazaqstan oblysy
+        'ZAP', // Batys Quzaqstan oblysy
+        'ZHA', // Zhambyl oblysy
     ];
 
     public $compareIdentical = true;
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/LaSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/LaSubdivisionCode.php
index 7f875bae12fe035aa7a4d29a686d1b6ecd6b3802..7535d589d13ea319223a61f3bc2f766515dda89b 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/LaSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/LaSubdivisionCode.php
@@ -18,29 +18,29 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: LA
  *
- * @link http://www.geonames.org/LA/administrative-division-laos.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class LaSubdivisionCode extends AbstractSearcher
 {
     public $haystack = [
         'AT', // Attapu
-        'BK', // Bokeo
+        'BK', // Bokèo
         'BL', // Bolikhamxai
         'CH', // Champasak
         'HO', // Houaphan
         'KH', // Khammouan
         'LM', // Louang Namtha
         'LP', // Louangphabang
-        'OU', // Oudomxai
-        'PH', // Phongsali
+        'OU', // Oudômxai
+        'PH', // Phôngsali
         'SL', // Salavan
-        'SV', // Savannakhet
+        'SV', // Savannakhét
         'VI', // Vientiane
         'VT', // Vientiane
         'XA', // Xaignabouli
-        'XE', // Xekong
-        'XI', // Xiangkhoang
-        'XN', // Xaisomboun
+        'XE', // Xékong
+        'XI', // Xiangkhouang
+        'XS', // Xaisômboun
     ];
 
     public $compareIdentical = true;
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/LbSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/LbSubdivisionCode.php
index 59cc3c4ba25796e753789d0e299ef6045855a1f5..7e949305de0ce6c78a74523665e6ded85e1cae17 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/LbSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/LbSubdivisionCode.php
@@ -18,7 +18,7 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: LB
  *
- * @link http://www.geonames.org/LB/administrative-division-lebanon.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class LbSubdivisionCode extends AbstractSearcher
 {
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/LcSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/LcSubdivisionCode.php
index 9204c5251c895f9785df73930ad696852e1cb77a..0b60a9008e052fab58cff956e4cc0873f4924ba6 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/LcSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/LcSubdivisionCode.php
@@ -18,7 +18,7 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: LC
  *
- * @link http://www.geonames.org/LC/administrative-division-saint-lucia.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class LcSubdivisionCode extends AbstractSearcher
 {
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/LiSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/LiSubdivisionCode.php
index b8109914c0c4388d06e39d4d683859438c71b95f..ff3c7c4c853eb4b4f4c52a69a417d2b664f74aaa 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/LiSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/LiSubdivisionCode.php
@@ -18,7 +18,7 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: LI
  *
- * @link http://www.geonames.org/LI/administrative-division-liechtenstein.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class LiSubdivisionCode extends AbstractSearcher
 {
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/LkSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/LkSubdivisionCode.php
index dfedf89013560e1b052d5425d2d4a9ddc0f746f6..f4cd34129e6e8ca8b30f04a42647a9a9f7aa44fb 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/LkSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/LkSubdivisionCode.php
@@ -18,43 +18,43 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: LK
  *
- * @link http://www.geonames.org/LK/administrative-division-sri-lanka.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class LkSubdivisionCode extends AbstractSearcher
 {
     public $haystack = [
-        '1', // Western
-        '2', // Central
-        '3', // Southern
-        '4', // Northern
-        '5', // Eastern
-        '6', // North Western
-        '7', // North Central
-        '8', // Uva
-        '9', // Sabaragamuwa
+        '1', // Basnāhira paḷāta
         '11', // Kŏḷamba
         '12', // Gampaha
         '13', // Kaḷutara
+        '2', // Madhyama paḷāta
         '21', // Mahanuvara
         '22', // Mātale
         '23', // Nuvara Ĕliya
+        '3', // Dakuṇu paḷāta
         '31', // Gālla
         '32', // Mātara
         '33', // Hambantŏṭa
+        '4', // Uturu paḷāta
         '41', // Yāpanaya
         '42', // Kilinŏchchi
         '43', // Mannārama
         '44', // Vavuniyāva
         '45', // Mulativ
+        '5', // Næ̆gĕnahira paḷāta
         '51', // Maḍakalapuva
-        '52', // Ampāra
+        '52', // Ampāara
         '53', // Trikuṇāmalaya
+        '6', // Vayamba paḷāta
         '61', // Kuruṇægala
         '62', // Puttalama
+        '7', // Uturumæ̆da paḷāta
         '71', // Anurādhapura
         '72', // Pŏḷŏnnaruva
+        '8', // Ūva paḷāta
         '81', // Badulla
         '82', // Mŏṇarāgala
+        '9', // Sabaragamuva paḷāta
         '91', // Ratnapura
         '92', // Kægalla
     ];
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/LrSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/LrSubdivisionCode.php
index 530cd09660164d609c5b453efc419cb68d91ef36..268a7f39427ea9d5a9a98ac50ea2fa66c078de63 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/LrSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/LrSubdivisionCode.php
@@ -18,7 +18,7 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: LR
  *
- * @link http://www.geonames.org/LR/administrative-division-liberia.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class LrSubdivisionCode extends AbstractSearcher
 {
@@ -34,7 +34,7 @@ class LrSubdivisionCode extends AbstractSearcher
         'MO', // Montserrado
         'MY', // Maryland
         'NI', // Nimba
-        'RI', // River Cess
+        'RI', // Rivercess
         'SI', // Sinoe
     ];
 
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/LsSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/LsSubdivisionCode.php
index 23f5a2af4f7337686fde4f12277d45529c83d5ca..472639e8293cee996f3b86f4e0f9b343e7733a3e 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/LsSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/LsSubdivisionCode.php
@@ -18,7 +18,7 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: LS
  *
- * @link http://www.geonames.org/LS/administrative-division-lesotho.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class LsSubdivisionCode extends AbstractSearcher
 {
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/LtSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/LtSubdivisionCode.php
index 21a2e2b5745e9feea6753e370fa77872da6d49f1..4e6b03eb8279a650b88987610b8160ff386fb928 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/LtSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/LtSubdivisionCode.php
@@ -18,21 +18,21 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: LT
  *
- * @link http://www.geonames.org/LT/administrative-division-lithuania.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class LtSubdivisionCode extends AbstractSearcher
 {
     public $haystack = [
-        'AL', // Alytus
-        'KL', // Klaipeda
-        'KU', // Kaunas
-        'MR', // Marijampole
-        'PN', // Panevezys
-        'SA', // Siauliai
-        'TA', // Taurage
-        'TE', // Telsiai
-        'UT', // Utena
-        'VL', // Vilnius
+        'AL', // Alytaus Apskritis
+        'KL', // KlaipÄ—dos Apskritis
+        'KU', // Kauno Apskritis
+        'MR', // MarijampolÄ—s Apskritis
+        'PN', // Panevėžio Apskritis
+        'SA', // Šiaulių Apskritis
+        'TA', // Tauragés Apskritis
+        'TE', // Telšių Apskritis
+        'UT', // Utenos Apskritis
+        'VL', // Vilniaus Apskritis
     ];
 
     public $compareIdentical = true;
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/LuSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/LuSubdivisionCode.php
index 86b18b78f2cac525aee22014c7b884b3b0dcc721..30846041ec3c96c4d467323c4561181b94ac848e 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/LuSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/LuSubdivisionCode.php
@@ -18,7 +18,7 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: LU
  *
- * @link http://www.geonames.org/LU/administrative-division-luxembourg.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class LuSubdivisionCode extends AbstractSearcher
 {
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/LvSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/LvSubdivisionCode.php
index 16b413c0f8bb139847d89d282dec84834787ea36..b97c7cbcda4836a320744e20dd19a49f40320b0b 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/LvSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/LvSubdivisionCode.php
@@ -18,128 +18,128 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: LV
  *
- * @link http://www.geonames.org/LV/administrative-division-latvia.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class LvSubdivisionCode extends AbstractSearcher
 {
     public $haystack = [
-        '001', // Aglonas Novads
-        '002', // Aizkraukles Novads
-        '003', // Aizputes Novads
-        '004', // Aknīstes Novads
-        '005', // Alojas Novads
-        '006', // Alsungas Novads
-        '007', // Alūksnes Novads
-        '008', // Amatas Novads
-        '009', // Apes Novads
-        '010', // Auces Novads
-        '011', // Ādažu Novads
-        '012', // Babītes Novads
-        '013', // Baldones Novads
-        '014', // Baltinavas Novads
-        '015', // Balvu Novads
-        '016', // Bauskas Novads
-        '017', // Beverīnas Novads
-        '018', // Brocēnu Novads
-        '019', // Burtnieku Novads
-        '020', // Carnikavas Novads
-        '021', // Cesvaines Novads
-        '022', // CÄ“su Novads
-        '023', // Ciblas Novads
-        '024', // Dagdas Novads
-        '025', // Daugavpils Novads
-        '026', // Dobeles Novads
-        '027', // Dundagas Novads
-        '028', // Durbes Novads
-        '029', // Engures Novads
-        '030', // Ērgļu Novads
-        '031', // Garkalnes Novads
-        '032', // Grobiņas Novads
-        '033', // Gulbenes Novads
-        '034', // Iecavas Novads
-        '035', // Ikšķiles Novads
-        '036', // Ilūkstes Novads
-        '037', // Inčukalna Novads
-        '038', // Jaunjelgavas Novads
-        '039', // Jaunpiebalgas Novads
-        '040', // Jaunpils Novads
-        '041', // Jelgavas Novads
-        '042', // JÄ“kabpils Novads
-        '043', // Kandavas Novads
-        '044', // Kārsavas Novads
-        '045', // Kocēnu Novads
-        '046', // Kokneses Novads
-        '047', // Krāslavas Novads
-        '048', // Krimuldas Novads
-        '049', // Krustpils Novads
-        '050', // Kuldīgas Novads
-        '051', // Ķeguma Novads
-        '052', // Ķekavas Novads
-        '053', // Lielvārdes Novads
-        '054', // Limbažu Novads
-        '055', // LÄ«gatnes Novads
-        '056', // Līvānu Novads
-        '057', // Lubānas Novads
-        '058', // Ludzas Novads
-        '059', // Madonas Novads
-        '060', // Mazsalacas Novads
-        '061', // Mālpils Novads
-        '062', // Mārupes Novads
+        '001', // Aglonas novads
+        '002', // Aizkraukles novads
+        '003', // Aizputes novads
+        '004', // Aknīstes novads
+        '005', // Alojas novads
+        '006', // Alsungas novads
+        '007', // Alūksnes novads
+        '008', // Amatas novads
+        '009', // Apes novads
+        '010', // Auces novads
+        '011', // Ādažu novads
+        '012', // Babītes novads
+        '013', // Baldones novads
+        '014', // Baltinavas novads
+        '015', // Balvu novads
+        '016', // Bauskas novads
+        '017', // Beverīnas novads
+        '018', // Brocēnu novads
+        '019', // Burtnieku novads
+        '020', // Carnikavas novads
+        '021', // Cesvaines novads
+        '022', // CÄ“su novads
+        '023', // Ciblas novads
+        '024', // Dagdas novads
+        '025', // Daugavpils novads
+        '026', // Dobeles novads
+        '027', // Dundagas novads
+        '028', // Durbes novads
+        '029', // Engures novads
+        '030', // Ērgļu novads
+        '031', // Garkalnes novads
+        '032', // Grobiņas novads
+        '033', // Gulbenes novads
+        '034', // Iecavas novads
+        '035', // Ikšķiles novads
+        '036', // Ilūkstes novads
+        '037', // Inčukalna novads
+        '038', // Jaunjelgavas novads
+        '039', // Jaunpiebalgas novads
+        '040', // Jaunpils novads
+        '041', // Jelgavas novads
+        '042', // JÄ“kabpils novads
+        '043', // Kandavas novads
+        '044', // Kārsavas novads
+        '045', // Kocēnu novads
+        '046', // Kokneses novads
+        '047', // Krāslavas novads
+        '048', // Krimuldas novads
+        '049', // Krustpils novads
+        '050', // Kuldīgas novads
+        '051', // Ķeguma novads
+        '052', // Ķekavas novads
+        '053', // Lielvārdes novads
+        '054', // Limbažu novads
+        '055', // LÄ«gatnes novads
+        '056', // Līvānu novads
+        '057', // Lubānas novads
+        '058', // Ludzas novads
+        '059', // Madonas novads
+        '060', // Mazsalacas novads
+        '061', // Mālpils novads
+        '062', // Mārupes novads
         '063', // MÄ“rsraga novads
-        '064', // Naukšēnu Novads
-        '065', // Neretas Novads
-        '066', // NÄ«cas Novads
-        '067', // Ogres Novads
-        '068', // Olaines Novads
-        '069', // Ozolnieku Novads
-        '070', // Pārgaujas Novads
-        '071', // Pāvilostas Novads
-        '072', // Pļaviņu Novads
-        '073', // Preiļu Novads
-        '074', // Priekules Novads
-        '075', // Priekuļu Novads
-        '076', // Raunas Novads
-        '077', // RÄ“zeknes Novads
-        '078', // Riebiņu Novads
-        '079', // Rojas Novads
-        '080', // Ropažu Novads
-        '081', // Rucavas Novads
-        '082', // Rugāju Novads
-        '083', // Rundāles Novads
-        '084', // RÅ«jienas Novads
-        '085', // Salas Novads
-        '086', // Salacgrīvas Novads
-        '087', // Salaspils Novads
-        '088', // Saldus Novads
-        '089', // Saulkrastu Novads
-        '090', // SÄ“jas Novads
-        '091', // Siguldas Novads
-        '092', // Skrīveru Novads
-        '093', // Skrundas Novads
-        '094', // Smiltenes Novads
-        '095', // Stopiņu Novads
-        '096', // Strenču Novads
-        '097', // Talsu Novads
-        '098', // TÄ“rvetes Novads
-        '099', // Tukuma Novads
-        '100', // Vaiņodes Novads
-        '101', // Valkas Novads
-        '102', // Varakļānu Novads
-        '103', // Vārkavas Novads
-        '104', // Vecpiebalgas Novads
-        '105', // Vecumnieku Novads
-        '106', // Ventspils Novads
-        '107', // Viesītes Novads
-        '108', // Viļakas Novads
-        '109', // Viļānu Novads
-        '110', // Zilupes Novads
+        '064', // Naukšēnu novads
+        '065', // Neretas novads
+        '066', // NÄ«cas novads
+        '067', // Ogres novads
+        '068', // Olaines novads
+        '069', // Ozolnieku novads
+        '070', // Pārgaujas novads
+        '071', // Pāvilostas novads
+        '072', // Pļaviņu novads
+        '073', // Preiļu novads
+        '074', // Priekules novads
+        '075', // Priekuļu novads
+        '076', // Raunas novads
+        '077', // RÄ“zeknes novads
+        '078', // Riebiņu novads
+        '079', // Rojas novads
+        '080', // Ropažu novads
+        '081', // Rucavas novads
+        '082', // Rugāju novads
+        '083', // Rundāles novads
+        '084', // RÅ«jienas novads
+        '085', // Salas novads
+        '086', // Salacgrīvas novads
+        '087', // Salaspils novads
+        '088', // Saldus novads
+        '089', // Saulkrastu novads
+        '090', // SÄ“jas novads
+        '091', // Siguldas novads
+        '092', // Skrīveru novads
+        '093', // Skrundas novads
+        '094', // Smiltenes novads
+        '095', // Stopiņu novads
+        '096', // Strenču novads
+        '097', // Talsu novads
+        '098', // TÄ“rvetes novads
+        '099', // Tukuma novads
+        '100', // Vaiņodes novads
+        '101', // Valkas novads
+        '102', // Varakļānu novads
+        '103', // Vārkavas novads
+        '104', // Vecpiebalgas novads
+        '105', // Vecumnieku novads
+        '106', // Ventspils novads
+        '107', // Viesītes novads
+        '108', // Viļakas novads
+        '109', // Viļānu novads
+        '110', // Zilupes novads
         'DGV', // Daugavpils
         'JEL', // Jelgava
         'JKB', // JÄ“kabpils
-        'JUR', // Jurmala
-        'LPX', // Liepaja
-        'REZ', // Rezekne
-        'RIX', // Riga
+        'JUR', // JÅ«rmala
+        'LPX', // Liepāja
+        'REZ', // RÄ“zekne
+        'RIX', // RÄ«ga
         'VEN', // Ventspils
         'VMR', // Valmiera
     ];
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/LySubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/LySubdivisionCode.php
index ab5951dd1a63663f34fa154fd53a8f66faba5734..48009c6c0d399fff2f2da2bb7effafe8b3408474 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/LySubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/LySubdivisionCode.php
@@ -18,33 +18,34 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: LY
  *
- * @link http://www.geonames.org/LY/administrative-division-libya.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class LySubdivisionCode extends AbstractSearcher
 {
     public $haystack = [
-        'BA', // Banghazi
+        'BA', // Banghāzī
         'BU', // Al Buţnān
         'DR', // Darnah
         'GT', // Ghāt
-        'JA', // Al Jabal al Akhdar
+        'JA', // Al Jabal al Akhḑar
+        'JB', // Jaghbūb
         'JG', // Al Jabal al Gharbī
         'JI', // Al Jifārah
         'JU', // Al Jufrah
         'KF', // Al Kufrah
         'MB', // Al Marqab
-        'MI', // Misratah
-        'MJ', // Al Maraj
+        'MI', // Mişrātah
+        'MJ', // Al Marj
         'MQ', // Murzuq
         'NL', // Nālūt
-        'NQ', // An Nuqat al Khams
-        'SB', // Sabha
+        'NQ', // An Nuqaţ al Khams
+        'SB', // Sabhā
         'SR', // Surt
         'TB', // Ţarābulus
         'WA', // Al Wāḩāt
         'WD', // Wādī al Ḩayāt
-        'WS', // Wādī ash Shāţi´
-        'ZA', // Az Zawiyah
+        'WS', // Wādī ash Shāţiʾ
+        'ZA', // Az Zāwiyah
     ];
 
     public $compareIdentical = true;
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/MaSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/MaSubdivisionCode.php
index 28155d07c2420b412bfe854888b3113fe56ab767..4669c9a3e5b90cda9956186c1ba272c173821c0e 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/MaSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/MaSubdivisionCode.php
@@ -18,7 +18,7 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: MA
  *
- * @link http://www.geonames.org/MA/administrative-division-morocco.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class MaSubdivisionCode extends AbstractSearcher
 {
@@ -26,21 +26,21 @@ class MaSubdivisionCode extends AbstractSearcher
         '01', // Tanger-Tétouan
         '02', // Gharb-Chrarda-Beni Hssen
         '03', // Taza-Al Hoceima-Taounate
-        '04', // Oriental
+        '04', // L'Oriental
         '05', // Fès-Boulemane
         '06', // Meknès-Tafilalet
-        '07', // Rabat-Salé-Zemmour-Zaër
+        '07', // Rabat-Salé-Zemmour-Zaer
         '08', // Grand Casablanca
         '09', // Chaouia-Ouardigha
-        '10', // Doukkala-Abda
+        '10', // Doukhala-Abda
         '11', // Marrakech-Tensift-Al Haouz
         '12', // Tadla-Azilal
-        '13', // Souss-Massa-Drâa
+        '13', // Sous-Massa-Draa
         '14', // Guelmim-Es Smara
-        '15', // Laâyoune-Boujdour-Sakia El Hamra
+        '15', // Laâyoune-Boujdour-Sakia el Hamra
         '16', // Oued ed Dahab-Lagouira
         'AGD', // Agadir-Ida-Outanane
-        'AOU', // Aousserd (EH)
+        'AOU', // Aousserd
         'ASZ', // Assa-Zag
         'AZI', // Azilal
         'BEM', // Beni Mellal
@@ -68,10 +68,10 @@ class MaSubdivisionCode extends AbstractSearcher
         'JRA', // Jrada
         'KEN', // Kénitra
         'KES', // Kelaat es Sraghna
-        'KHE', // Khémisset
-        'KHN', // Khénifra
+        'KHE', // Khemisaet
+        'KHN', // Khenifra
         'KHO', // Khouribga
-        'LAA', // Laâyoune
+        'LAA', // Laâyoune (EH)
         'LAR', // Larache
         'MED', // Médiouna
         'MEK', // Meknès
@@ -89,7 +89,7 @@ class MaSubdivisionCode extends AbstractSearcher
         'SAL', // Salé
         'SEF', // Sefrou
         'SET', // Settat
-        'SIK', // Sidi Kacem
+        'SIK', // Sidl Kacem
         'SKH', // Skhirate-Témara
         'SYB', // Sidi Youssef Ben Ali
         'TAI', // Taourirt
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/McSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/McSubdivisionCode.php
index 98ae794a4c195e50ad94b733d5fcaf4a1221053c..d7473c767b6d87b8fad507e743f100a0aacf836e 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/McSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/McSubdivisionCode.php
@@ -18,7 +18,7 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: MC
  *
- * @link http://www.geonames.org/MC/administrative-division-monaco.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class McSubdivisionCode extends AbstractSearcher
 {
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/MdSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/MdSubdivisionCode.php
index 8bb28f1bfbec1aa384f0d6f8049b9624e131bea2..1e1d8a0e13e345f027cbf353b4c04a682b883e68 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/MdSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/MdSubdivisionCode.php
@@ -18,48 +18,48 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: MD
  *
- * @link http://www.geonames.org/MD/administrative-division-moldova.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class MdSubdivisionCode extends AbstractSearcher
 {
     public $haystack = [
-        'AN', // Raionul Anenii Noi
-        'BA', // Municipiul Bălţi
+        'AN', // Anenii Noi
+        'BA', // Bălți
         'BD', // Tighina
-        'BR', // Raionul Briceni
-        'BS', // Raionul Basarabeasca
+        'BR', // Briceni
+        'BS', // Basarabeasca
         'CA', // Cahul
-        'CL', // Raionul Călăraşi
-        'CM', // Raionul CimiÅŸlia
-        'CR', // Raionul Criuleni
-        'CS', // Raionul Căuşeni
-        'CT', // Raionul Cantemir
-        'CU', // Municipiul Chişinău
-        'DO', // DonduÅŸeni
-        'DR', // Raionul Drochia
+        'CL', // Călărași
+        'CM', // Cimișlia
+        'CR', // Criuleni
+        'CS', // Căușeni
+        'CT', // Cantemir
+        'CU', // Chișinău
+        'DO', // Dondușeni
+        'DR', // Drochia
         'DU', // Dubăsari
-        'ED', // Raionul Edineţ
-        'FA', // Făleşti
-        'FL', // FloreÅŸti
-        'GA', // U.T.A. Găgăuzia
-        'GL', // Raionul Glodeni
-        'HI', // Hînceşti
+        'ED', // EdineÈ›
+        'FA', // Fălești
+        'FL', // Florești
+        'GA', // Găgăuzia, Unitatea teritorială autonomă
+        'GL', // Glodeni
+        'HI', // Hîncești
         'IA', // Ialoveni
         'LE', // Leova
         'NI', // Nisporeni
-        'OC', // Raionul Ocniţa
-        'OR', // Raionul Orhei
+        'OC', // Ocnița
+        'OR', // Orhei
         'RE', // Rezina
-        'RI', // Rîşcani
-        'SD', // Raionul Şoldăneşti
+        'RI', // Rîșcani
+        'SD', // Șoldănești
         'SI', // Sîngerei
-        'SN', // Stînga Nistrului
+        'SN', // Stînga Nistrului, unitatea teritorială din
         'SO', // Soroca
-        'ST', // Raionul Străşeni
-        'SV', // Raionul Ştefan Vodă
-        'TA', // Raionul Taraclia
-        'TE', // TeleneÅŸti
-        'UN', // Raionul Ungheni
+        'ST', // Strășeni
+        'SV', // Ștefan Vodă
+        'TA', // Taraclia
+        'TE', // Telenești
+        'UN', // Ungheni
     ];
 
     public $compareIdentical = true;
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/MeSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/MeSubdivisionCode.php
index e08a495a13d355d58282ee7acb7e95ffe7d7fa61..b76a0629d9b66aea9932f46a9585fde3395cffcd 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/MeSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/MeSubdivisionCode.php
@@ -18,32 +18,32 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: ME
  *
- * @link http://www.geonames.org/ME/administrative-division-montenegro.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class MeSubdivisionCode extends AbstractSearcher
 {
     public $haystack = [
-        '01', // Opština Andrijevica
-        '02', // Opština Bar
-        '03', // Opština Berane
-        '04', // Opština Bijelo Polje
-        '05', // Opština Budva
-        '06', // Opština Cetinje
-        '07', // Opština Danilovgrad
-        '08', // Opština Herceg-Novi
-        '09', // Opština Kolašin
-        '10', // Opština Kotor
-        '11', // Opština Mojkovac
-        '12', // Opština Nikšić
-        '13', // Opština Plav
-        '14', // Opština Pljevlja
-        '15', // Opština Plužine
-        '16', // Opština Podgorica
-        '17', // Opština Rožaje
-        '18', // Opština Šavnik
-        '19', // Opština Tivat
-        '20', // Opština Ulcinj
-        '21', // Opština Žabljak
+        '01', // Andrijevica
+        '02', // Bar
+        '03', // Berane
+        '04', // Bijelo Polje
+        '05', // Budva
+        '06', // Cetinje
+        '07', // Danilovgrad
+        '08', // Herceg-Novi
+        '09', // Kolašin
+        '10', // Kotor
+        '11', // Mojkovac
+        '12', // Nikšić
+        '13', // Plav
+        '14', // Pljevlja
+        '15', // Plužine
+        '16', // Podgorica
+        '17', // Rožaje
+        '18', // Å avnik
+        '19', // Tivat
+        '20', // Ulcinj
+        '21', // Žabljak
     ];
 
     public $compareIdentical = true;
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/MfSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/MfSubdivisionCode.php
index af014edfe9025b9700ad5ff75975d70ba7752059..0d67d286ba2d5808e032429372cf0a7bfedbc82e 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/MfSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/MfSubdivisionCode.php
@@ -18,7 +18,7 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: MF
  *
- * @link http://www.geonames.org/MF/administrative-division-saint-martin.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class MfSubdivisionCode extends AbstractSearcher
 {
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/MgSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/MgSubdivisionCode.php
index 7c51c0731971ff6cb608f7dbcbefde2951fc8e34..4d21f731ca3c27fc34e1188144acaa3df193a397 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/MgSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/MgSubdivisionCode.php
@@ -18,17 +18,17 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: MG
  *
- * @link http://www.geonames.org/MG/administrative-division-madagascar.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class MgSubdivisionCode extends AbstractSearcher
 {
     public $haystack = [
-        'A', // Toamasina province
-        'D', // Antsiranana province
-        'F', // Fianarantsoa province
-        'M', // Mahajanga province
-        'T', // Antananarivo province
-        'U', // Toliara province
+        'A', // Toamasina
+        'D', // Antsiranana
+        'F', // Fianarantsoa
+        'M', // Mahajanga
+        'T', // Antananarivo
+        'U', // Toliara
     ];
 
     public $compareIdentical = true;
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/MhSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/MhSubdivisionCode.php
index 07c55061f47f38899750ac400648857f5a4d01d9..38e3c5fd8628cfc78d3162ca9b4bf2de564ebe1b 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/MhSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/MhSubdivisionCode.php
@@ -18,13 +18,11 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: MH
  *
- * @link http://www.geonames.org/MH/administrative-division-marshall-islands.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class MhSubdivisionCode extends AbstractSearcher
 {
     public $haystack = [
-        'L', // Ralik chain
-        'T', // Ratak chain
         'ALK', // Ailuk
         'ALL', // Ailinglaplap
         'ARN', // Arno
@@ -35,6 +33,7 @@ class MhSubdivisionCode extends AbstractSearcher
         'JAL', // Jaluit
         'KIL', // Kili
         'KWA', // Kwajalein
+        'L', // Ralik chain
         'LAE', // Lae
         'LIB', // Lib
         'LIK', // Likiep
@@ -42,13 +41,14 @@ class MhSubdivisionCode extends AbstractSearcher
         'MAL', // Maloelap
         'MEJ', // Mejit
         'MIL', // Mili
-        'NMK', // Namorik
+        'NMK', // Namdrik
         'NMU', // Namu
         'RON', // Rongelap
+        'T', // Ratak chain
         'UJA', // Ujae
         'UTI', // Utirik
-        'WTH', // Wotho
         'WTJ', // Wotje
+        'WTN', // Wotho
     ];
 
     public $compareIdentical = true;
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/MkSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/MkSubdivisionCode.php
index d365d60be3a2f2181fe4bae937a9f2aca8950195..38d4cce6efd0c8d4331ab7cf3a4dc3b32ab6516c 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/MkSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/MkSubdivisionCode.php
@@ -18,21 +18,20 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: MK
  *
- * @link http://www.geonames.org/MK/administrative-division-macedonia.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class MkSubdivisionCode extends AbstractSearcher
 {
     public $haystack = [
-        '01', // Aerodrom †
+        '01', // Aerodrom
         '02', // Aračinovo
         '03', // Berovo
         '04', // Bitola
         '05', // Bogdanci
         '06', // Bogovinje
         '07', // Bosilovo
-        '077', // Centar †
         '08', // Brvenica
-        '09', // Butel †
+        '09', // Butel
         '10', // Valandovo
         '11', // Vasilevo
         '12', // Vevčani
@@ -40,7 +39,7 @@ class MkSubdivisionCode extends AbstractSearcher
         '14', // Vinica
         '15', // Vraneštica
         '16', // Vrapčište
-        '17', // Gazi Baba †
+        '17', // Gazi Baba
         '18', // Gevgelija
         '19', // Gostivar
         '20', // Gradsko
@@ -52,7 +51,7 @@ class MkSubdivisionCode extends AbstractSearcher
         '26', // Dojran
         '27', // Dolneni
         '28', // Drugovo
-        '29', // Gjorče Petrov †
+        '29', // Gjorče Petrov
         '30', // Želino
         '31', // Zajas
         '32', // Zelenikovo
@@ -61,8 +60,8 @@ class MkSubdivisionCode extends AbstractSearcher
         '35', // Jegunovce
         '36', // Kavadarci
         '37', // Karbinci
-        '38', // Karpoš †
-        '39', // Kisela Voda †
+        '38', // Karpoš
+        '39', // Kisela Voda
         '40', // Kičevo
         '41', // Konče
         '42', // Kočani
@@ -91,22 +90,23 @@ class MkSubdivisionCode extends AbstractSearcher
         '65', // Rankovce
         '66', // Resen
         '67', // Rosoman
-        '68', // Saraj †
+        '68', // Saraj
         '69', // Sveti Nikole
-        '70', // Å tip
-        '71', // Struga
-        '72', // Strumica
-        '73', // Studeničani
-        '74', // Šuto Orizari †
+        '70', // Sopište
+        '71', // Staro Nagoričane
+        '72', // Struga
+        '73', // Strumica
+        '74', // Studeničani
         '75', // Tearce
         '76', // Tetovo
+        '77', // Centar
         '78', // Centar Župa
-        '79', // Čair †
+        '79', // ÄŒair
         '80', // Čaška
         '81', // Češinovo-Obleševo
         '82', // Čučer Sandevo
-        '83', // Sopište
-        '84', // Staro Nagoričane
+        '83', // Å tip
+        '84', // Å uto Orizari
     ];
 
     public $compareIdentical = true;
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/MlSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/MlSubdivisionCode.php
index 598ec4f5e4ef20be8de5a880a3a873940c1c8fae..b425209fdf3a37ea079c2eff294f44ceee395f69 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/MlSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/MlSubdivisionCode.php
@@ -18,7 +18,7 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: ML
  *
- * @link http://www.geonames.org/ML/administrative-division-mali.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class MlSubdivisionCode extends AbstractSearcher
 {
@@ -26,12 +26,12 @@ class MlSubdivisionCode extends AbstractSearcher
         '1', // Kayes
         '2', // Koulikoro
         '3', // Sikasso
-        '4', // Segou
+        '4', // Ségou
         '5', // Mopti
         '6', // Tombouctou
         '7', // Gao
         '8', // Kidal
-        'BKO', // Bamako Capital District
+        'BK0', // Bamako
     ];
 
     public $compareIdentical = true;
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/MmSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/MmSubdivisionCode.php
index 276daa3758d57c7b2f254764f4d436e6f140a2a7..bd25a21de76793a07daa0d710e800221ad25a917 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/MmSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/MmSubdivisionCode.php
@@ -18,7 +18,7 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: MM
  *
- * @link http://www.geonames.org/MM/administrative-division-myanmar.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class MmSubdivisionCode extends AbstractSearcher
 {
@@ -30,13 +30,13 @@ class MmSubdivisionCode extends AbstractSearcher
         '05', // Tanintharyi
         '06', // Yangon
         '07', // Ayeyarwady
-        '11', // Kachin State
-        '12', // Kayah State
-        '13', // Kayin State
-        '14', // Chin State
-        '15', // Mon State
-        '16', // Rakhine State
-        '17', // Shan State
+        '11', // Kachin
+        '12', // Kayah
+        '13', // Kayin
+        '14', // Chin
+        '15', // Mon
+        '16', // Rakhine
+        '17', // Shan
     ];
 
     public $compareIdentical = true;
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/MnSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/MnSubdivisionCode.php
index c0cf304b6326336c466541353b62ee2d2b1a8f4d..732f6b3353f64fa2b81587aacb665f2e23170b05 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/MnSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/MnSubdivisionCode.php
@@ -18,7 +18,7 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: MN
  *
- * @link http://www.geonames.org/MN/administrative-division-mongolia.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class MnSubdivisionCode extends AbstractSearcher
 {
@@ -26,23 +26,23 @@ class MnSubdivisionCode extends AbstractSearcher
         '035', // Orhon
         '037', // Darhan uul
         '039', // Hentiy
-        '041', // Hovsgol
+        '041', // Hövsgöl
         '043', // Hovd
         '046', // Uvs
-        '047', // Tov
+        '047', // Töv
         '049', // Selenge
-        '051', // Suhbaatar
-        '053', // Omnogovi
-        '055', // Ovorhangay
+        '051', // Sühbaatar
+        '053', // Ömnögovi
+        '055', // Övörhangay
         '057', // Dzavhan
-        '059', // DundgovL
+        '059', // Dundgovi
         '061', // Dornod
-        '063', // Dornogov
+        '063', // Dornogovi
         '064', // Govi-Sumber
         '065', // Govi-Altay
         '067', // Bulgan
         '069', // Bayanhongor
-        '071', // Bayan-Olgiy
+        '071', // Bayan-Ölgiy
         '073', // Arhangay
         '1', // Ulanbaatar
     ];
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/MoSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/MoSubdivisionCode.php
index 898be4e9c08550c9b08a621089532d82ea975d9f..4d9022cb8dd6fbafc54119e30324dcb71ab41032 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/MoSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/MoSubdivisionCode.php
@@ -18,7 +18,7 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: MO
  *
- * @link http://www.geonames.org/MO/administrative-division-macao.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class MoSubdivisionCode extends AbstractSearcher
 {
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/MpSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/MpSubdivisionCode.php
index a25ea1487e37cf2bd38cc2c3ae634544858481ff..1a5d87786fccf87e7e105a9936f7129ed3e20d16 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/MpSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/MpSubdivisionCode.php
@@ -18,7 +18,7 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: MP
  *
- * @link http://www.geonames.org/MP/administrative-division-northern-mariana-islands.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class MpSubdivisionCode extends AbstractSearcher
 {
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/MqSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/MqSubdivisionCode.php
index 6ae5f098da0adcb782e7841524f61477ae36c0e0..ca6a50d8ef89939cee6ddca0a65ab003d1bf4da8 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/MqSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/MqSubdivisionCode.php
@@ -18,7 +18,7 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: MQ
  *
- * @link http://www.geonames.org/MQ/administrative-division-martinique.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class MqSubdivisionCode extends AbstractSearcher
 {
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/MrSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/MrSubdivisionCode.php
index d93e559444a4a0b0697fe703e823076ca8a76273..482336618ad463c16c85705ffa5a160d6af17f75 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/MrSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/MrSubdivisionCode.php
@@ -18,13 +18,13 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: MR
  *
- * @link http://www.geonames.org/MR/administrative-division-mauritania.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class MrSubdivisionCode extends AbstractSearcher
 {
     public $haystack = [
-        '01', // Hodh Ech Chargui
-        '02', // Hodh El Gharbi
+        '01', // Hodh ech Chargui
+        '02', // Hodh el Charbi
         '03', // Assaba
         '04', // Gorgol
         '05', // Brakna
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/MsSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/MsSubdivisionCode.php
index ec34111be33df370f77bddc52a6ec96069c45799..d397ba118e9ae2511000631844e12982f4761032 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/MsSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/MsSubdivisionCode.php
@@ -18,7 +18,7 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: MS
  *
- * @link http://www.geonames.org/MS/administrative-division-montserrat.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class MsSubdivisionCode extends AbstractSearcher
 {
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/MtSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/MtSubdivisionCode.php
index 75037b843f39d433573e06adcf29928c5f608c79..9bf7ad379ae40f08fc263cb51a21fab59d3bb8fd 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/MtSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/MtSubdivisionCode.php
@@ -18,7 +18,7 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: MT
  *
- * @link http://www.geonames.org/MT/administrative-division-malta.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class MtSubdivisionCode extends AbstractSearcher
 {
@@ -27,24 +27,24 @@ class MtSubdivisionCode extends AbstractSearcher
         '02', // Balzan
         '03', // Birgu
         '04', // Birkirkara
-        '05', // Birzebbuga
+        '05', // Birżebbuġa
         '06', // Bormla
         '07', // Dingli
         '08', // Fgura
         '09', // Floriana
         '10', // Fontana
         '11', // Gudja
-        '12', // Gzira
-        '13', // Ghajnsielem
-        '14', // Gharb
-        '15', // Gargur
-        '16', // Ghasri
-        '17', // Gaxaq
-        '18', // Hamrun
+        '12', // Gżira
+        '13', // Għajnsielem
+        '14', // Għarb
+        '15', // Għargħur
+        '16', // Għasri
+        '17', // Għaxaq
+        '18', // Ħamrun
         '19', // Iklin
         '20', // Isla
         '21', // Kalkara
-        '22', // Kercem
+        '22', // Kerċem
         '23', // Kirkop
         '24', // Lija
         '25', // Luqa
@@ -52,8 +52,8 @@ class MtSubdivisionCode extends AbstractSearcher
         '27', // Marsaskala
         '28', // Marsaxlokk
         '29', // Mdina
-        '30', // Melliea
-        '31', // Mgarr
+        '30', // Mellieħa
+        '31', // MÄ¡arr
         '32', // Mosta
         '33', // Mqabba
         '34', // Msida
@@ -63,34 +63,34 @@ class MtSubdivisionCode extends AbstractSearcher
         '38', // Naxxar
         '39', // Paola
         '40', // Pembroke
-        '41', // Pieta
+        '41', // Pietà
         '42', // Qala
         '43', // Qormi
         '44', // Qrendi
         '45', // Rabat Għawdex
         '46', // Rabat Malta
         '47', // Safi
-        '48', // San Giljan
-        '49', // San Gwann
+        '48', // San Ä iljan
+        '49', // San Ä wann
         '50', // San Lawrenz
-        '51', // San Pawl il-Bahar
+        '51', // San Pawl il-Baħar
         '52', // Sannat
-        '53', // Santa Lucija
+        '53', // Santa Luċija
         '54', // Santa Venera
-        '55', // Siggiewi
+        '55', // Siġġiewi
         '56', // Sliema
         '57', // Swieqi
-        '58', // Tarxien
-        '59', // Ta Xbiex
+        '58', // Ta’ Xbiex
+        '59', // Tarxien
         '60', // Valletta
-        '61', // Xagra
+        '61', // Xagħra
         '62', // Xewkija
-        '63', // Xgajra
-        '64', // Zabbar
+        '63', // Xgħajra
+        '64', // Żabbar
         '65', // Żebbuġ Għawdex
         '66', // Żebbuġ Malta
-        '67', // Zejtun
-        '68', // Zurrieq
+        '67', // Żejtun
+        '68', // Żurrieq
     ];
 
     public $compareIdentical = true;
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/MuSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/MuSubdivisionCode.php
index 1aec7191f2ec0d4e51eacf758de7fb989cffb4cd..8e2db5a1a9f84b7cb1c7ab7bcb9cfaba1504a4ce 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/MuSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/MuSubdivisionCode.php
@@ -18,7 +18,7 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: MU
  *
- * @link http://www.geonames.org/MU/administrative-division-mauritius.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class MuSubdivisionCode extends AbstractSearcher
 {
@@ -26,7 +26,7 @@ class MuSubdivisionCode extends AbstractSearcher
         'AG', // Agalega Islands
         'BL', // Black River
         'BR', // Beau Bassin-Rose Hill
-        'CC', // Cargados Carajos Shoals (Saint Brandon Islands)
+        'CC', // Cargados Carajos Shoals
         'CU', // Curepipe
         'FL', // Flacq
         'GP', // Grand Port
@@ -36,8 +36,8 @@ class MuSubdivisionCode extends AbstractSearcher
         'PU', // Port Louis
         'PW', // Plaines Wilhems
         'QB', // Quatre Bornes
-        'RO', // Rodrigues
-        'RR', // Riviere du Rempart
+        'RO', // Rodrigues Island
+        'RP', // Rivière du Rempart
         'SA', // Savanne
         'VP', // Vacoas-Phoenix
     ];
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/MvSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/MvSubdivisionCode.php
index 4a9b6b2b58241e2e321ed75a7d6d80d0c679b1b8..79476281a545a3e7b32c3870cd86dced86526faa 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/MvSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/MvSubdivisionCode.php
@@ -18,39 +18,39 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: MV
  *
- * @link http://www.geonames.org/MV/administrative-division-maldives.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class MvSubdivisionCode extends AbstractSearcher
 {
     public $haystack = [
-        'CE', // Medhu
+        '00', // Alifu Dhaalu
+        '01', // Seenu
+        '02', // Alifu Alifu
+        '03', // Lhaviyani
+        '04', // Vaavu
+        '05', // Laamu
+        '07', // Haa Alifu
+        '08', // Thaa
+        '12', // Meemu
+        '13', // Raa
+        '14', // Faafu
+        '17', // Dhaalu
+        '20', // Baa
+        '23', // Haa Dhaalu
+        '24', // Shaviyani
+        '25', // Noonu
+        '26', // Kaafu
+        '27', // Gaafu Alifu
+        '28', // Gaafu Dhaalu
+        '29', // Gnaviyani
+        'CE', // Central
         'MLE', // Male
-        'NC', // Medhu Uthuru
-        'NO', // Uthuru
-        'SC', // Medhu Dhekunu
-        'SU', // Dhekunu
-        'UN', // Mathi Uthuru
-        'US', // Mathi Dhekunu
-        '00', // Alifu Dhaalu / Ari Atholhu Dhekunuburi
-        '01', // Seenu / Addu Atholhu
-        '02', // Alifu Alifu / Ari Atholhu Uthuruburi
-        '03', // Lhaviyani / Faadhippolhu
-        '04', // Vaavu / Felidhu Atholhu
-        '05', // Laamu / Haddhdhunmathi
-        '07', // Haa Alifu / Thiladhunmathee Uthuruburi
-        '08', // Thaa / Kolhumadulu
-        '12', // Meemu / Mulakatholhu
-        '13', // Raa / Maalhosmadulu Uthuruburi
-        '14', // Faafu / Nilandhe Atholhu Uthuruburi
-        '17', // Dhaalu / Nilandhe Atholhu Dhekunuburi
-        '20', // Baa / Maalhosmadulu Dhekunuburi
-        '23', // Haa Dhaalu / Thiladhunmathee Dhekunuburi
-        '24', // Shaviyani / Miladhunmadulu Uthuruburi
-        '25', // Noonu / Miladhunmadulu Dhekunuburi
-        '26', // Kaafu / Maale Atholhu
-        '27', // Gaafu Alifu / Huvadhu Atholhu Uthuruburi
-        '28', // Gaafu Dhaalu / Huvadhu Atholhu Dhekunuburi
-        '29', // Gnaviyani / Fuvammulah
+        'NC', // North Central
+        'NO', // North
+        'SC', // South Central
+        'SU', // South
+        'UN', // Upper North
+        'US', // Upper South
     ];
 
     public $compareIdentical = true;
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/MwSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/MwSubdivisionCode.php
index bcb1d211f0de376a8d687df9c900559d8fca1f73..1bde2b69b27c847cc6167bfc20c8d6b556a60bd0 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/MwSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/MwSubdivisionCode.php
@@ -18,16 +18,14 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: MW
  *
- * @link http://www.geonames.org/MW/administrative-division-malawi.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class MwSubdivisionCode extends AbstractSearcher
 {
     public $haystack = [
-        'C', // Central
-        'N', // Northern
-        'S', // Southern
         'BA', // Balaka
         'BL', // Blantyre
+        'C', // Central Region
         'CK', // Chikwawa
         'CR', // Chiradzulu
         'CT', // Chitipa
@@ -43,6 +41,7 @@ class MwSubdivisionCode extends AbstractSearcher
         'MU', // Mulanje
         'MW', // Mwanza
         'MZ', // Mzimba
+        'N', // Northern Region
         'NB', // Nkhata Bay
         'NE', // Neno
         'NI', // Ntchisi
@@ -51,6 +50,7 @@ class MwSubdivisionCode extends AbstractSearcher
         'NU', // Ntcheu
         'PH', // Phalombe
         'RU', // Rumphi
+        'S', // Southern Region
         'SA', // Salima
         'TH', // Thyolo
         'ZO', // Zomba
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/MxSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/MxSubdivisionCode.php
index a2bfc47ca143bccc277ed6bfbc5779d790bf681f..f991f50c601a90da3673b763a182c71cf5f3312f 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/MxSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/MxSubdivisionCode.php
@@ -18,7 +18,7 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: MX
  *
- * @link http://www.geonames.org/MX/administrative-division-mexico.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class MxSubdivisionCode extends AbstractSearcher
 {
@@ -29,31 +29,31 @@ class MxSubdivisionCode extends AbstractSearcher
         'CAM', // Campeche
         'CHH', // Chihuahua
         'CHP', // Chiapas
-        'COA', // Coahuila
+        'CMX', // Ciudad de México
+        'COA', // Coahuila de Zaragoza
         'COL', // Colima
-        'DIF', // Distrito Federal
         'DUR', // Durango
         'GRO', // Guerrero
         'GUA', // Guanajuato
         'HID', // Hidalgo
         'JAL', // Jalisco
-        'MEX', // Mexico
-        'MIC', // Michoacan
+        'MEX', // México
+        'MIC', // Michoacán de Ocampo
         'MOR', // Morelos
         'NAY', // Nayarit
-        'NLE', // Nuevo Leon
+        'NLE', // Nuevo León
         'OAX', // Oaxaca
         'PUE', // Puebla
-        'QUE', // Queretaro
+        'QUE', // Querétaro
         'ROO', // Quintana Roo
         'SIN', // Sinaloa
-        'SLP', // San Luis Potosi
+        'SLP', // San Luis Potosí
         'SON', // Sonora
         'TAB', // Tabasco
         'TAM', // Tamaulipas
         'TLA', // Tlaxcala
-        'VER', // Veracruz
-        'YUC', // Yucatan
+        'VER', // Veracruz de Ignacio de la Llave
+        'YUC', // Yucatán
         'ZAC', // Zacatecas
     ];
 
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/MySubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/MySubdivisionCode.php
index e37d1d7415352e40ee5eddfdf77d10a5162cea63..0ae037ef6bd2f31bfbd79c9e985fea25d8e8aade 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/MySubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/MySubdivisionCode.php
@@ -18,7 +18,7 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: MY
  *
- * @link http://www.geonames.org/MY/administrative-division-malaysia.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class MySubdivisionCode extends AbstractSearcher
 {
@@ -29,16 +29,16 @@ class MySubdivisionCode extends AbstractSearcher
         '04', // Melaka
         '05', // Negeri Sembilan
         '06', // Pahang
-        '07', // Pinang
+        '07', // Pulau Pinang
         '08', // Perak
         '09', // Perlis
         '10', // Selangor
         '11', // Terengganu
         '12', // Sabah
         '13', // Sarawak
-        '14', // Kuala Lumpur
-        '15', // Labuan
-        '16', // Putrajaya
+        '14', // Wilayah Persekutuan Kuala Lumpur
+        '15', // Wilayah Persekutuan Labuan
+        '16', // Wilayah Persekutuan Putrajaya
     ];
 
     public $compareIdentical = true;
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/MzSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/MzSubdivisionCode.php
index dfbbcefbfe4ff7f3d3515df0c52463edb67ed273..e2a09f048a75de8ff5adb1429e39a6d56a9275ae 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/MzSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/MzSubdivisionCode.php
@@ -18,7 +18,7 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: MZ
  *
- * @link http://www.geonames.org/MZ/administrative-division-mozambique.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class MzSubdivisionCode extends AbstractSearcher
 {
@@ -29,7 +29,7 @@ class MzSubdivisionCode extends AbstractSearcher
         'I', // Inhambane
         'L', // Maputo
         'MPM', // Maputo (city)
-        'N', // Nampula
+        'N', // Numpula
         'P', // Cabo Delgado
         'Q', // Zambezia
         'S', // Sofala
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/NaSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/NaSubdivisionCode.php
index fcbf4d84080992ca3c91298dc3e2b83d468f75b6..ab018d8115fa75a74a61bdeaa0c4739a6150185c 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/NaSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/NaSubdivisionCode.php
@@ -18,7 +18,7 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: NA
  *
- * @link http://www.geonames.org/NA/administrative-division-namibia.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class NaSubdivisionCode extends AbstractSearcher
 {
@@ -31,11 +31,11 @@ class NaSubdivisionCode extends AbstractSearcher
         'KU', // Kunene
         'OD', // Otjozondjupa
         'OH', // Omaheke
+        'OK', // Okavango
         'ON', // Oshana
         'OS', // Omusati
         'OT', // Oshikoto
         'OW', // Ohangwena
-        'OK', // Kavango
     ];
 
     public $compareIdentical = true;
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/NcSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/NcSubdivisionCode.php
index c52b9b7e68533e71bb776d63a6410770280a20c6..3539059fc33d7925910ac6a2de38518e258c32d6 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/NcSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/NcSubdivisionCode.php
@@ -18,7 +18,7 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: NC
  *
- * @link http://www.geonames.org/NC/administrative-division-new-caledonia.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class NcSubdivisionCode extends AbstractSearcher
 {
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/NeSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/NeSubdivisionCode.php
index 2186b02dc620e80a9a73a92028979d3e9763b5a4..3bf70266ac179b28d977ea305cd5c7bef606f289 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/NeSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/NeSubdivisionCode.php
@@ -18,7 +18,7 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: NE
  *
- * @link http://www.geonames.org/NE/administrative-division-niger.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class NeSubdivisionCode extends AbstractSearcher
 {
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/NfSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/NfSubdivisionCode.php
index 67275e506a9bf7b47e163cea2623b6072d9a9308..f275abca4dd1febc72d1a1170d9790953c71ba2d 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/NfSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/NfSubdivisionCode.php
@@ -18,7 +18,7 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: NF
  *
- * @link http://www.geonames.org/NF/administrative-division-norfolk-island.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class NfSubdivisionCode extends AbstractSearcher
 {
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/NgSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/NgSubdivisionCode.php
index dac3b9f7422bad3ef9a612001584f7a9b573492d..7fb015a3917fbf4c53ec7edab00aa7996ae176c6 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/NgSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/NgSubdivisionCode.php
@@ -18,7 +18,7 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: NG
  *
- * @link http://www.geonames.org/NG/administrative-division-nigeria.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class NgSubdivisionCode extends AbstractSearcher
 {
@@ -37,7 +37,7 @@ class NgSubdivisionCode extends AbstractSearcher
         'ED', // Edo
         'EK', // Ekiti
         'EN', // Enugu
-        'FC', // Federal Capital Territory
+        'FC', // Abuja Capital Territory
         'GO', // Gombe
         'IM', // Imo
         'JI', // Jigawa
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/NiSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/NiSubdivisionCode.php
index 040c9b6bef828549881914882e88a950f58a10cc..99fe61de8b5510fc00ae86bed71e758ca58bed97 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/NiSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/NiSubdivisionCode.php
@@ -18,28 +18,28 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: NI
  *
- * @link http://www.geonames.org/NI/administrative-division-nicaragua.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class NiSubdivisionCode extends AbstractSearcher
 {
     public $haystack = [
-        'AN', // Region Autonoma del Atlantico Norte
-        'AS', // Region Autonoma del Atlantico Sur
+        'AN', // Atlántico Norte
+        'AS', // Atlántico Sur
         'BO', // Boaco
         'CA', // Carazo
         'CI', // Chinandega
         'CO', // Chontales
-        'ES', // Esteli
+        'ES', // Estelí
         'GR', // Granada
         'JI', // Jinotega
-        'LE', // Leon
+        'LE', // León
         'MD', // Madriz
         'MN', // Managua
         'MS', // Masaya
         'MT', // Matagalpa
         'NS', // Nueva Segovia
         'RI', // Rivas
-        'SJ', // Rio San Juan
+        'SJ', // Río San Juan
     ];
 
     public $compareIdentical = true;
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/NlSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/NlSubdivisionCode.php
index 0979bab7fefb5cac805261e7f2fe395ae4f53231..d5deb957a362f0f714e79b13e1e5e26d66a1f75b 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/NlSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/NlSubdivisionCode.php
@@ -18,23 +18,29 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: NL
  *
- * @link http://www.geonames.org/NL/administrative-division-netherlands.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class NlSubdivisionCode extends AbstractSearcher
 {
     public $haystack = [
+        'AW', // Aruba
+        'BQ1', // Bonaire
+        'BQ2', // Saba
+        'BQ3', // Sint Eustatius
+        'CW', // Curaçao
         'DR', // Drenthe
         'FL', // Flevoland
         'FR', // Friesland
         'GE', // Gelderland
         'GR', // Groningen
         'LI', // Limburg
-        'NB', // Noord Brabant
-        'NH', // Noord Holland
+        'NB', // Noord-Brabant
+        'NH', // Noord-Holland
         'OV', // Overijssel
+        'SX', // Sint Maarten
         'UT', // Utrecht
         'ZE', // Zeeland
-        'ZH', // Zuid Holland
+        'ZH', // Zuid-Holland
     ];
 
     public $compareIdentical = true;
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/NoSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/NoSubdivisionCode.php
index 1fb6bcc14a914c2637c2a24ce9e93e133fe17acc..d013a14742cff9416716a628edf60b16f8b6b95f 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/NoSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/NoSubdivisionCode.php
@@ -18,12 +18,12 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: NO
  *
- * @link http://www.geonames.org/NO/administrative-division-norway.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class NoSubdivisionCode extends AbstractSearcher
 {
     public $haystack = [
-        '01', // Ostfold
+        '01', // Østfold
         '02', // Akershus
         '03', // Oslo
         '04', // Hedmark
@@ -36,14 +36,14 @@ class NoSubdivisionCode extends AbstractSearcher
         '11', // Rogaland
         '12', // Hordaland
         '14', // Sogn og Fjordane
-        '15', // More og Romdal
-        '16', // Sor-Trondelag
-        '17', // Nord-Trondelag
+        '15', // Møre og Romsdal
+        '16', // Sør-Trøndelag
+        '17', // Nord-Trøndelag
         '18', // Nordland
         '19', // Troms
         '20', // Finnmark
-        '21', // Svalbard
-        '22', // Jan Mayen
+        '21', // Svalbard (Arctic Region)
+        '22', // Jan Mayen (Arctic Region)
     ];
 
     public $compareIdentical = true;
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/NpSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/NpSubdivisionCode.php
index a0519e7510580b63f63c47e0a6c24897a6fa9ba5..9578d42bc59223c0ce45a1725ed9774b4bbe437a 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/NpSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/NpSubdivisionCode.php
@@ -18,7 +18,7 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: NP
  *
- * @link http://www.geonames.org/NP/administrative-division-nepal.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class NpSubdivisionCode extends AbstractSearcher
 {
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/NrSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/NrSubdivisionCode.php
index 652058a0cd5f82c3b516b63c5d41abeaf9d54f27..6d75adf54cb7a1b8cfd91f7b602d776b4c1c52b3 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/NrSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/NrSubdivisionCode.php
@@ -18,7 +18,7 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: NR
  *
- * @link http://www.geonames.org/NR/administrative-division-nauru.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class NrSubdivisionCode extends AbstractSearcher
 {
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/NuSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/NuSubdivisionCode.php
index e95721507b96948680f52397bed0d07cb88c1561..2c3c4b8b4ea3cb0bd68fdc2ae6dfd69ea9464047 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/NuSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/NuSubdivisionCode.php
@@ -18,7 +18,7 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: NU
  *
- * @link http://www.geonames.org/NU/administrative-division-niue.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class NuSubdivisionCode extends AbstractSearcher
 {
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/NzSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/NzSubdivisionCode.php
index fe4912c1f12abcac4868568538daee9a9d891e3a..08c39a9e27430638509c396828fa7e9b771751d2 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/NzSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/NzSubdivisionCode.php
@@ -18,26 +18,26 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: NZ
  *
- * @link http://www.geonames.org/NZ/administrative-division-new-zealand.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class NzSubdivisionCode extends AbstractSearcher
 {
     public $haystack = [
-        'N', // North Island
-        'S', // South Island
         'AUK', // Auckland
         'BOP', // Bay of Plenty
         'CAN', // Canterbury
-        'CIT', // Chatham Islands
-        'GIS', // Gisborne
+        'CIT', // Chatham Islands Territory
+        'GIS', // Gisborne District
         'HKB', // Hawke's Bay
-        'MBH', // Marlborough
+        'MBH', // Marlborough District
         'MWT', // Manawatu-Wanganui
-        'NSN', // Nelson
+        'N', // North Island
+        'NSN', // Nelson City
         'NTL', // Northland
         'OTA', // Otago
+        'S', // South Island
         'STL', // Southland
-        'TAS', // Tasman
+        'TAS', // Tasman District
         'TKI', // Taranaki
         'WGN', // Wellington
         'WKO', // Waikato
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/OmSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/OmSubdivisionCode.php
index e859e2e0096dafd261a593a340c502cc18d9364d..caa0ee11e08ac2cdd26fb35740aad213fd6f1689 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/OmSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/OmSubdivisionCode.php
@@ -18,20 +18,20 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: OM
  *
- * @link http://www.geonames.org/OM/administrative-division-oman.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class OmSubdivisionCode extends AbstractSearcher
 {
     public $haystack = [
-        'BA', // Al Batinah South
+        'BA', // Al Bāţinah
         'BU', // Al Buraymī
-        'DA', // Ad Dakhiliyah
-        'MA', // Masqat
+        'DA', // Ad Dākhilīya
+        'MA', // Masqaţ
         'MU', // Musandam
-        'SH', // Ash Sharqiyah South
-        'WU', // Al Wusta
-        'ZA', // Az Zahirah
-        'ZU', // Zufar
+        'SH', // Ash Sharqīyah
+        'WU', // Al Wusţá
+        'ZA', // Az̧ Z̧āhirah
+        'ZU', // Z̧ufār
     ];
 
     public $compareIdentical = true;
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/PaSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/PaSubdivisionCode.php
index d6763112d707e44c9cf8a46fd2e809d4c998879a..4ad4c4d374372f99bc76f654047d4f79750eb8a3 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/PaSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/PaSubdivisionCode.php
@@ -18,22 +18,22 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: PA
  *
- * @link http://www.geonames.org/PA/administrative-division-panama.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class PaSubdivisionCode extends AbstractSearcher
 {
     public $haystack = [
         '1', // Bocas del Toro
-        '2', // Cocle
-        '3', // Colon
-        '4', // Chiriqui
-        '5', // Darien
+        '2', // Coclé
+        '3', // Colón
+        '4', // Chiriquí
+        '5', // Darién
         '6', // Herrera
         '7', // Los Santos
-        '8', // Panama
+        '8', // Panamá
         '9', // Veraguas
-        'EM', // Comarca Emberá-Wounaan
-        'KY', // Comarca de Kuna Yala
+        'EM', // Emberá
+        'KY', // Kuna Yala
         'NB', // Ngöbe-Buglé
     ];
 
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/PeSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/PeSubdivisionCode.php
index 6618584a1db8d2bcc9535cb4504f89e92f3d8a4b..077d884e9d7b706a87b304e8282a2d89512aed11 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/PeSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/PeSubdivisionCode.php
@@ -18,23 +18,23 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: PE
  *
- * @link http://www.geonames.org/PE/administrative-division-peru.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class PeSubdivisionCode extends AbstractSearcher
 {
     public $haystack = [
         'AMA', // Amazonas
         'ANC', // Ancash
-        'APU', // Apurimac
+        'APU', // Apurímac
         'ARE', // Arequipa
         'AYA', // Ayacucho
         'CAJ', // Cajamarca
-        'CAL', // Callao
-        'CUS', // Cusco
-        'HUC', // Huanuco
+        'CAL', // El Callao
+        'CUS', // Cusco [Cuzco]
+        'HUC', // Huánuco
         'HUV', // Huancavelica
         'ICA', // Ica
-        'JUN', // Junin
+        'JUN', // Junín
         'LAL', // La Libertad
         'LAM', // Lambayeque
         'LIM', // Lima
@@ -45,7 +45,7 @@ class PeSubdivisionCode extends AbstractSearcher
         'PAS', // Pasco
         'PIU', // Piura
         'PUN', // Puno
-        'SAM', // San Martin
+        'SAM', // San Martín
         'TAC', // Tacna
         'TUM', // Tumbes
         'UCA', // Ucayali
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/PfSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/PfSubdivisionCode.php
index 6f8ed8f9210d96b0631431b7397deb8adcf76411..e319f7344ba80f1e76efdde76941ecb35a6d6d02 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/PfSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/PfSubdivisionCode.php
@@ -18,7 +18,7 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: PF
  *
- * @link http://www.geonames.org/PF/administrative-division-french-polynesia.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class PfSubdivisionCode extends AbstractSearcher
 {
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/PgSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/PgSubdivisionCode.php
index efdd1165a5e60ad4ab454f1c9c83197bceee8e76..14e36edfc32e6388acee5f432a6bc09ac30669ae 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/PgSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/PgSubdivisionCode.php
@@ -18,7 +18,7 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: PG
  *
- * @link http://www.geonames.org/PG/administrative-division-papua-new-guinea.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class PgSubdivisionCode extends AbstractSearcher
 {
@@ -34,10 +34,10 @@ class PgSubdivisionCode extends AbstractSearcher
         'MPL', // Morobe
         'MPM', // Madang
         'MRL', // Manus
-        'NCD', // National Capital
+        'NCD', // National Capital District (Port Moresby)
         'NIK', // New Ireland
         'NPP', // Northern
-        'NSA', // Bougainville
+        'NSB', // Bougainville
         'SAN', // Sandaun
         'SHM', // Southern Highlands
         'WBK', // West New Britain
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/PhSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/PhSubdivisionCode.php
index c8554afbd161889e69189a69d98a77e81a68782e..7a252c3aa2a0068b1cdf125bba4c1e157678f024 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/PhSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/PhSubdivisionCode.php
@@ -18,28 +18,28 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: PH
  *
- * @link http://www.geonames.org/PH/administrative-division-philippines.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class PhSubdivisionCode extends AbstractSearcher
 {
     public $haystack = [
         '00', // National Capital Region
-        '01', // Ilocos
-        '02', // Cagayan Valley
-        '03', // Central Luzon
-        '05', // Bicol
-        '06', // Western Visayas
-        '07', // Central Visayas
-        '08', // Eastern Visayas
-        '09', // Zamboanga Peninsula
-        '10', // Northern Mindanao
-        '11', // Davao
-        '12', // Soccsksargen
-        '13', // Caraga
-        '14', // Autonomous Region in Muslim Mindanao
-        '15', // Cordillera Administrative Region
-        '40', // Calabarzon
-        '41', // Mimaropa
+        '01', // Ilocos (Region I)
+        '02', // Cagayan Valley (Region II)
+        '03', // Central Luzon (Region III)
+        '05', // Bicol (Region V)
+        '06', // Western Visayas (Region VI)
+        '07', // Central Visayas (Region VII)
+        '08', // Eastern Visayas (Region VIII)
+        '09', // Zamboanga Peninsula (Region IX)
+        '10', // Northern Mindanao (Region X)
+        '11', // Davao (Region XI)
+        '12', // Soccsksargen (Region XII)
+        '13', // Caraga (Region XIII)
+        '14', // Autonomous Region in Muslim Mindanao (ARMM)
+        '15', // Cordillera Administrative Region (CAR)
+        '40', // CALABARZON (Region IV-A)
+        '41', // MIMAROPA (Region IV-B)
         'ABR', // Abra
         'AGN', // Agusan del Norte
         'AGS', // Agusan del Sur
@@ -48,7 +48,7 @@ class PhSubdivisionCode extends AbstractSearcher
         'ANT', // Antique
         'APA', // Apayao
         'AUR', // Aurora
-        'BAN', // Bataan
+        'BAN', // Batasn
         'BAS', // Basilan
         'BEN', // Benguet
         'BIL', // Biliran
@@ -77,7 +77,7 @@ class PhSubdivisionCode extends AbstractSearcher
         'ILN', // Ilocos Norte
         'ILS', // Ilocos Sur
         'ISA', // Isabela
-        'KAL', // Kalinga
+        'KAL', // Kalinga-Apayso
         'LAG', // Laguna
         'LAN', // Lanao del Norte
         'LAS', // Lanao del Sur
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/PkSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/PkSubdivisionCode.php
index c6812e4ddc490e33631c731aa90a3667c829e5f7..fb4a341abd935d2c7a755d5bdd750d7f4be2b61e 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/PkSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/PkSubdivisionCode.php
@@ -18,16 +18,16 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: PK
  *
- * @link http://www.geonames.org/PK/administrative-division-pakistan.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class PkSubdivisionCode extends AbstractSearcher
 {
     public $haystack = [
         'BA', // Balochistan
-        'IS', // Islamabad Capital Territory
+        'GB', // Gilgit-Baltistan
+        'IS', // Islamabad
         'JK', // Azad Kashmir
-        'NA', // Gilgit-Baltistan
-        'NW', // Khyber Pakhtunkhwa
+        'KP', // Khyber Pakhtunkhwa
         'PB', // Punjab
         'SD', // Sindh
         'TA', // Federally Administered Tribal Areas
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/PlSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/PlSubdivisionCode.php
index b2b0b1b6a7d253c4a7cbd1fd17071330f71da291..1a604f5308edfd0b373dc78103906177013493d8 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/PlSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/PlSubdivisionCode.php
@@ -18,25 +18,25 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: PL
  *
- * @link http://www.geonames.org/PL/administrative-division-poland.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class PlSubdivisionCode extends AbstractSearcher
 {
     public $haystack = [
-        'DS', // Dolnoslaskie
-        'KP', // Kujawsko-Pomorskie
+        'DS', // Dolnośląskie
+        'KP', // Kujawsko-pomorskie
         'LB', // Lubuskie
-        'LD', // Lodzkie
+        'LD', // Łódzkie
         'LU', // Lubelskie
-        'MA', // Malopolskie
+        'MA', // Małopolskie
         'MZ', // Mazowieckie
         'OP', // Opolskie
         'PD', // Podlaskie
         'PK', // Podkarpackie
         'PM', // Pomorskie
-        'SK', // Swietokrzyskie
-        'SL', // Slaskie
-        'WN', // Warminsko-Mazurskie
+        'SK', // Świętokrzyskie
+        'SL', // ÅšlÄ…skie
+        'WN', // Warmińsko-mazurskie
         'WP', // Wielkopolskie
         'ZP', // Zachodniopomorskie
     ];
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/PmSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/PmSubdivisionCode.php
index d5f3d4278f570e71205f059104d75cb7b177d4ae..8799715d34f19b6032bcd9e8c8c70a3428baf434 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/PmSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/PmSubdivisionCode.php
@@ -18,7 +18,7 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: PM
  *
- * @link http://www.geonames.org/PM/administrative-division-saint-pierre-and-miquelon.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class PmSubdivisionCode extends AbstractSearcher
 {
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/PnSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/PnSubdivisionCode.php
index 08365351369bacf688ec74b5499accf2b09b46e0..21080e8592b79c185a16b2256b02961cfc919309 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/PnSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/PnSubdivisionCode.php
@@ -18,7 +18,7 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: PN
  *
- * @link http://www.geonames.org/PN/administrative-division-pitcairn-islands.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class PnSubdivisionCode extends AbstractSearcher
 {
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/PrSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/PrSubdivisionCode.php
index c618056943fa48f74405fc4bbefacf8d704f0339..8869a55c91f48e19df095ee42baaf2a30cd8eef3 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/PrSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/PrSubdivisionCode.php
@@ -18,7 +18,7 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: PR
  *
- * @link http://www.geonames.org/PR/administrative-division-puerto-rico.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class PrSubdivisionCode extends AbstractSearcher
 {
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/PsSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/PsSubdivisionCode.php
index 3690303fc1c779802b5260af1873c0d6883c84a0..671403d21c3126a16a835a3ddafea431a6527653 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/PsSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/PsSubdivisionCode.php
@@ -18,27 +18,27 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: PS
  *
- * @link http://www.geonames.org/PS/administrative-division-palestine.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class PsSubdivisionCode extends AbstractSearcher
 {
     public $haystack = [
-        'DEB', // Bethlehem [conventional] / Bayt Laḩm [Arabic]
-        'DEB', // Deir El Balah [conventional] /Dayr al Balaḩ[Arabic]
-        'GZA', // Gaza [conventional] / Ghazzah[Arabic]
-        'HBN', // Hebron [conventional] / Al Khalīl [Arabic]
-        'JEM', // Jerusalem [conventional] / Al Quds [Arabic]
-        'JEN', // Jenin [conventional] / Janīn [Arabic]
-        'JRH', // Jericho [conventional] / Arīḩā wal Aghwār [Arabic]
-        'KYS', // Khan Yunis [conventional] / Khān Yūnis[Arabic]
-        'NBS', // Nablus [conventional] / Nāblus [Arabic]
-        'NGZ', // North Gaza [conventional] / Shamāl Ghazzah[Arabic]
-        'QQA', // Qalqiyah [conventional] / Qalqīlyah [Arabic]
-        'RBH', // Ramallah and Al Birah [conventional] / Rām Allāh wal Bīrah [Arabic]
-        'RFH', // Rafah [conventional] / Rafaḩ[Arabic]
-        'SLT', // Salfit [conventional] / Salfīt [Arabic]
-        'TBS', // Tubas [conventional] / Ţūbās [Arabic]
-        'TKM', // Tulkarm [conventional] /Ţūlkarm [Arabic]
+        'BTH', // Bethlehem
+        'DEB', // Deir El Balah
+        'GZA', // Gaza
+        'HBN', // Hebron
+        'JEM', // Jerusalem
+        'JEN', // Jenin
+        'JRH', // Jericho - Al Aghwar
+        'KYS', // Khan Yunis
+        'NBS', // Nablus
+        'NGZ', // North Gaza
+        'QQA', // Qalqilya
+        'RBH', // Ramallah
+        'RFH', // Rafah
+        'SLT', // Salfit
+        'TBS', // Tubas
+        'TKM', // Tulkarm
     ];
 
     public $compareIdentical = true;
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/PtSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/PtSubdivisionCode.php
index e16e822b4984991f47a8d356ad6ef90a45dae7b8..e03beaa53761b76247b718751b1abfc55ff8c84c 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/PtSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/PtSubdivisionCode.php
@@ -18,7 +18,7 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: PT
  *
- * @link http://www.geonames.org/PT/administrative-division-portugal.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class PtSubdivisionCode extends AbstractSearcher
 {
@@ -26,23 +26,23 @@ class PtSubdivisionCode extends AbstractSearcher
         '01', // Aveiro
         '02', // Beja
         '03', // Braga
-        '04', // Braganca
+        '04', // Bragança
         '05', // Castelo Branco
         '06', // Coimbra
-        '07', // Evora
+        '07', // Évora
         '08', // Faro
         '09', // Guarda
         '10', // Leiria
         '11', // Lisboa
         '12', // Portalegre
         '13', // Porto
-        '14', // Santarem
-        '15', // Setubal
+        '14', // Santarém
+        '15', // Setúbal
         '16', // Viana do Castelo
         '17', // Vila Real
         '18', // Viseu
-        '20', // Acores (Azores)
-        '30', // Madeira
+        '20', // Região Autónoma dos Açores
+        '30', // Região Autónoma da Madeira
     ];
 
     public $compareIdentical = true;
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/PwSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/PwSubdivisionCode.php
index fd127700a9c8f68c72fab4cfdce90346ef28f3fe..47eb7ba761497967fce75498fbca46726832dbd6 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/PwSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/PwSubdivisionCode.php
@@ -18,7 +18,7 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: PW
  *
- * @link http://www.geonames.org/PW/administrative-division-palau.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class PwSubdivisionCode extends AbstractSearcher
 {
@@ -26,7 +26,7 @@ class PwSubdivisionCode extends AbstractSearcher
         '002', // Aimeliik
         '004', // Airai
         '010', // Angaur
-        '050', // Hatohobei
+        '050', // Hatobohei
         '100', // Kayangel
         '150', // Koror
         '212', // Melekeok
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/PySubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/PySubdivisionCode.php
index f96d92aa743085759ff5412fa80f6833b2375c65..3bbb57b74c31b8f4aa49e2476a5ed9353af3577a 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/PySubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/PySubdivisionCode.php
@@ -18,29 +18,29 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: PY
  *
- * @link http://www.geonames.org/PY/administrative-division-paraguay.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class PySubdivisionCode extends AbstractSearcher
 {
     public $haystack = [
-        '1', // Concepcion
-        '10', // Alto Parana
+        '1', // Concepción
+        '10', // Alto Paraná
         '11', // Central
-        '12', // Neembucu
+        '12', // Ñeembucú
         '13', // Amambay
-        '14', // Canindeyu
+        '14', // Canindeyú
         '15', // Presidente Hayes
         '16', // Alto Paraguay
-        '19', // Boqueron
+        '19', // Boquerón
         '2', // San Pedro
         '3', // Cordillera
-        '4', // Guaira
-        '5', // Caaguazu
-        '6', // Caazapa
-        '7', // Itapua
+        '4', // Guairá
+        '5', // Caaguazú
+        '6', // Caazapá
+        '7', // Itapúa
         '8', // Misiones
-        '9', // Paraguari
-        'ASU', // Asuncion
+        '9', // Paraguarí
+        'ASU', // Asunción
     ];
 
     public $compareIdentical = true;
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/QaSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/QaSubdivisionCode.php
index 22357d48e25bada90502cb26d47a8fe6d4920d3d..b49608a199f701ae99edd74cb52d0ec26343ea63 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/QaSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/QaSubdivisionCode.php
@@ -18,18 +18,18 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: QA
  *
- * @link http://www.geonames.org/QA/administrative-division-qatar.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class QaSubdivisionCode extends AbstractSearcher
 {
     public $haystack = [
         'DA', // Ad Dawhah
         'KH', // Al Khawr wa adh Dhakhīrah
-        'MS', // Ash Shamāl
+        'MS', // Ash Shamal
         'RA', // Ar Rayyan
         'US', // Umm Salal
         'WA', // Al Wakrah
-        'ZA', // Az Z a‘āyin
+        'ZA', // Az̧ Z̧a‘āyin
     ];
 
     public $compareIdentical = true;
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/ReSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/ReSubdivisionCode.php
index df1f9a10e3ced749d85ccdf3719e50f732737095..209da6eab5bebedca4de1fa8dbec78c6f94c9f6d 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/ReSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/ReSubdivisionCode.php
@@ -18,7 +18,7 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: RE
  *
- * @link http://www.geonames.org/RE/administrative-division-reunion.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class ReSubdivisionCode extends AbstractSearcher
 {
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/RoSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/RoSubdivisionCode.php
index cc6865e12ee9990c53026036d218b5813a01cdca..f6dbbaea394fc5d61175319faa74764ae0a09d95 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/RoSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/RoSubdivisionCode.php
@@ -18,51 +18,51 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: RO
  *
- * @link http://www.geonames.org/RO/administrative-division-romania.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class RoSubdivisionCode extends AbstractSearcher
 {
     public $haystack = [
         'AB', // Alba
-        'AG', // Arges
+        'AG', // ArgeÈ™
         'AR', // Arad
-        'B', // Bucuresti
-        'BC', // Bacau
+        'B', // București
+        'BC', // Bacău
         'BH', // Bihor
-        'BN', // Bistrita-Nasaud
-        'BR', // Braila
-        'BT', // Botosani
-        'BV', // Brasov
-        'BZ', // Buzau
+        'BN', // Bistrița-Năsăud
+        'BR', // Brăila
+        'BT', // Botoșani
+        'BV', // Brașov
+        'BZ', // Buzău
         'CJ', // Cluj
-        'CL', // Calarasi
-        'CS', // Caras-Severin
-        'CT', // Constanta
+        'CL', // Călărași
+        'CS', // CaraÈ™-Severin
+        'CT', // Constanța
         'CV', // Covasna
-        'DB', // Dimbovita
+        'DB', // Dâmbovița
         'DJ', // Dolj
         'GJ', // Gorj
-        'GL', // Galati
+        'GL', // Galați
         'GR', // Giurgiu
         'HD', // Hunedoara
         'HR', // Harghita
         'IF', // Ilfov
-        'IL', // Ialomita
-        'IS', // Iasi
-        'MH', // Mehedinti
-        'MM', // Maramures
-        'MS', // Mures
-        'NT', // Neamt
+        'IL', // Ialomița
+        'IS', // Iași
+        'MH', // Mehedinți
+        'MM', // MaramureÈ™
+        'MS', // MureÈ™
+        'NT', // NeamÈ›
         'OT', // Olt
         'PH', // Prahova
         'SB', // Sibiu
-        'SJ', // Salaj
+        'SJ', // Sălaj
         'SM', // Satu Mare
         'SV', // Suceava
         'TL', // Tulcea
-        'TM', // Timis
+        'TM', // TimiÈ™
         'TR', // Teleorman
-        'VL', // Vilcea
+        'VL', // Vâlcea
         'VN', // Vrancea
         'VS', // Vaslui
     ];
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/RsSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/RsSubdivisionCode.php
index 27b0c96a508a0e5d083bb53bdb32083158ef7277..f7f8c9ac548a623a5c1fb6a32cc985e7dd5ae066 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/RsSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/RsSubdivisionCode.php
@@ -18,35 +18,33 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: RS
  *
- * @link http://www.geonames.org/RS/administrative-division-serbia.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class RsSubdivisionCode extends AbstractSearcher
 {
     public $haystack = [
-        'KM', // Kosovo
-        'VO', // Vojvodina
         '00', // Beograd
         '01', // Severnobački okrug
         '02', // Srednjebanatski okrug
         '03', // Severnobanatski okrug
         '04', // Južnobanatski okrug
-        '05', // Zapadno-Bački Okrug
+        '05', // Zapadnobački okrug
         '06', // Južnobački okrug
-        '07', // Srem
+        '07', // Sremski okrug
         '08', // Mačvanski okrug
         '09', // Kolubarski okrug
         '10', // Podunavski okrug
         '11', // Braničevski okrug
-        '12', // Å umadija
+        '12', // Å umadijski okrug
         '13', // Pomoravski okrug
         '14', // Borski okrug
-        '15', // Zaječar
-        '16', // Zlatibor
+        '15', // Zaječarski okrug
+        '16', // Zlatiborski okrug
         '17', // Moravički okrug
         '18', // Raški okrug
         '19', // Rasinski okrug
         '20', // Nišavski okrug
-        '21', // Toplica
+        '21', // Toplički okrug
         '22', // Pirotski okrug
         '23', // Jablanički okrug
         '24', // Pčinjski okrug
@@ -55,6 +53,8 @@ class RsSubdivisionCode extends AbstractSearcher
         '27', // Prizrenski okrug
         '28', // Kosovsko-Mitrovački okrug
         '29', // Kosovsko-Pomoravski okrug
+        'KM', // Kosovo-Metohija
+        'VO', // Vojvodina
     ];
 
     public $compareIdentical = true;
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/RuSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/RuSubdivisionCode.php
index c13bbe121c3b653ad311d2c5629b9d0ac2079a1b..c8a5ebcefe3d1a6d0066e1862ac80258e608fb8e 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/RuSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/RuSubdivisionCode.php
@@ -18,94 +18,94 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: RU
  *
- * @link http://www.geonames.org/RU/administrative-division-russia.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class RuSubdivisionCode extends AbstractSearcher
 {
     public $haystack = [
-        'AD', // Adygeya
-        'AL', // Altai Republic
-        'ALT', // Altai Krai
-        'AMU', // Amur
-        'ARK', // Arkhangelsk
-        'AST', // Astrakhan
-        'BA', // Bashkortostan
-        'BEL', // Belgorod
-        'BRY', // Bryansk
-        'BU', // Buryatia
-        'CE', // Chechnya
-        'CHE', // Chelyabinsk
-        'CHU', // Chukotka
-        'CU', // Chuvashia
-        'DA', // Dagestan
-        'IN', // Ingushetia
-        'IRK', // Irkutsk
-        'IVA', // Ivanovo
-        'KAM', // Kamchatka
-        'KB', // Kabardino-Balkaria
-        'KC', // Karachay-Cherkessia
-        'KDA', // Krasnodar
-        'KEM', // Kemerovo
-        'KGD', // Kaliningrad
-        'KGN', // Kurgan
-        'KHA', // Khabarovsk
-        'KHM', // Khantia-Mansia
-        'KIR', // Kirov
-        'KK', // Khakassia
-        'KL', // Kalmykia
-        'KLU', // Kaluga
-        'KO', // Komi
-        'KOS', // Kostroma
-        'KR', // Karelia
-        'KRS', // Kursk
-        'KYA', // Krasnoyarsk
-        'LEN', // Leningrad
-        'LIP', // Lipetsk
-        'MAG', // Magadan
-        'ME', // Mari El
-        'MO', // Mordovia
-        'MOS', // Moscow (Province)
-        'MOW', // Moscow (City)
-        'MUR', // Murmansk
-        'NEN', // Nenetsia
-        'NGR', // Novgorod
-        'NIZ', // Nizhny Novgorod
-        'NVS', // Novosibirsk
-        'OMS', // Omsk
-        'ORE', // Orenburg
-        'ORL', // Oryol
-        'PER', // Perm
-        'PNZ', // Penza
-        'PRI', // Primorsky
-        'PSK', // Pskov
-        'ROS', // Rostov
-        'RYA', // Ryazan
-        'SA', // Sakha
-        'SAK', // Sakhalin
-        'SAM', // Samara
-        'SAR', // Saratov
-        'SE', // North Ossetia
-        'SMO', // Smolensk
-        'SPE', // St. Petersburg
-        'STA', // Stavropol
-        'SVE', // Sverdlovsk
-        'TA', // Tatarstan
-        'TAM', // Tambov
-        'TOM', // Tomsk
-        'TUL', // Tula
-        'TVE', // Tver
-        'TY', // Tuva
-        'TYU', // Tyumen
-        'UD', // Udmurtia
-        'ULY', // Ulynovsk
-        'VGG', // Volgograd
-        'VLA', // Vladimir
-        'VLG', // Vologda
-        'VOR', // Voronezh
-        'YAN', // Yamalia
-        'YAR', // Yaroslavl
-        'YEV', // Jewish Oblast
-        'ZAB', // Zabaykal'skiy kray
+        'AD', // Adygeya, Respublika
+        'AL', // Altay, Respublika
+        'ALT', // Altayskiy kray
+        'AMU', // Amurskaya oblast'
+        'ARK', // Arkhangel'skaya oblast'
+        'AST', // Astrakhanskaya oblast'
+        'BA', // Bashkortostan, Respublika
+        'BEL', // Belgorodskaya oblast'
+        'BRY', // Bryanskaya oblast'
+        'BU', // Buryatiya, Respublika
+        'CE', // Chechenskaya Respublika
+        'CHE', // Chelyabinskaya oblast'
+        'CHU', // Chukotskiy avtonomnyy okrug
+        'CU', // Chuvashskaya Respublika
+        'DA', // Dagestan, Respublika
+        'IN', // Respublika Ingushetiya
+        'IRK', // Irkutiskaya oblast'
+        'IVA', // Ivanovskaya oblast'
+        'KAM', // Kamchatskiy kray
+        'KB', // Kabardino-Balkarskaya Respublika
+        'KC', // Karachayevo-Cherkesskaya Respublika
+        'KDA', // Krasnodarskiy kray
+        'KEM', // Kemerovskaya oblast'
+        'KGD', // Kaliningradskaya oblast'
+        'KGN', // Kurganskaya oblast'
+        'KHA', // Khabarovskiy kray
+        'KHM', // Khanty-Mansiysky avtonomnyy okrug-Yugra
+        'KIR', // Kirovskaya oblast'
+        'KK', // Khakasiya, Respublika
+        'KL', // Kalmykiya, Respublika
+        'KLU', // Kaluzhskaya oblast'
+        'KO', // Komi, Respublika
+        'KOS', // Kostromskaya oblast'
+        'KR', // Kareliya, Respublika
+        'KRS', // Kurskaya oblast'
+        'KYA', // Krasnoyarskiy kray
+        'LEN', // Leningradskaya oblast'
+        'LIP', // Lipetskaya oblast'
+        'MAG', // Magadanskaya oblast'
+        'ME', // Mariy El, Respublika
+        'MO', // Mordoviya, Respublika
+        'MOS', // Moskovskaya oblast'
+        'MOW', // Moskva
+        'MUR', // Murmanskaya oblast'
+        'NEN', // Nenetskiy avtonomnyy okrug
+        'NGR', // Novgorodskaya oblast'
+        'NIZ', // Nizhegorodskaya oblast'
+        'NVS', // Novosibirskaya oblast'
+        'OMS', // Omskaya oblast'
+        'ORE', // Orenburgskaya oblast'
+        'ORL', // Orlovskaya oblast'
+        'PER', // Permskiy kray
+        'PNZ', // Penzenskaya oblast'
+        'PRI', // Primorskiy kray
+        'PSK', // Pskovskaya oblast'
+        'ROS', // Rostovskaya oblast'
+        'RYA', // Ryazanskaya oblast'
+        'SA', // Sakha, Respublika [Yakutiya]
+        'SAK', // Sakhalinskaya oblast'
+        'SAM', // Samaraskaya oblast'
+        'SAR', // Saratovskaya oblast'
+        'SE', // Severnaya Osetiya-Alaniya, Respublika
+        'SMO', // Smolenskaya oblast'
+        'SPE', // Sankt-Peterburg
+        'STA', // Stavropol'skiy kray
+        'SVE', // Sverdlovskaya oblast'
+        'TA', // Tatarstan, Respublika
+        'TAM', // Tambovskaya oblast'
+        'TOM', // Tomskaya oblast'
+        'TUL', // Tul'skaya oblast'
+        'TVE', // Tverskaya oblast'
+        'TY', // Tyva, Respublika [Tuva]
+        'TYU', // Tyumenskaya oblast'
+        'UD', // Udmurtskaya Respublika
+        'ULY', // Ul'yanovskaya oblast'
+        'VGG', // Volgogradskaya oblast'
+        'VLA', // Vladimirskaya oblast'
+        'VLG', // Vologodskaya oblast'
+        'VOR', // Voronezhskaya oblast'
+        'YAN', // Yamalo-Nenetskiy avtonomnyy okrug
+        'YAR', // Yaroslavskaya oblast'
+        'YEV', // Yevreyskaya avtonomnaya oblast'
+        'ZAB', // Zabajkal'skij kraj
     ];
 
     public $compareIdentical = true;
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/RwSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/RwSubdivisionCode.php
index 020fce732ebf2039f09466abbba59f239209eca5..51ebb5ad80fed9b8b80637d12ec07817b41e0646 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/RwSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/RwSubdivisionCode.php
@@ -18,12 +18,12 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: RW
  *
- * @link http://www.geonames.org/RW/administrative-division-rwanda.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class RwSubdivisionCode extends AbstractSearcher
 {
     public $haystack = [
-        '01', // Kigali
+        '01', // Ville de Kigali
         '02', // Est
         '03', // Nord
         '04', // Ouest
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/SaSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/SaSubdivisionCode.php
index 6b05f359dfb43413e2d7448923a81fef622e4057..901f0c14491c62bd892cc2e63566395afcacd822 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/SaSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/SaSubdivisionCode.php
@@ -18,24 +18,24 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: SA
  *
- * @link http://www.geonames.org/SA/administrative-division-saudi-arabia.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class SaSubdivisionCode extends AbstractSearcher
 {
     public $haystack = [
-        '01', // Ar Riyad
+        '01', // Ar Riyāḍ
         '02', // Makkah
-        '03', // Al Madinah
-        '04', // Ash Sharqiyah (Eastern Province)
-        '05', // Al Qasim
-        '06', // Ha'il
-        '07', // Tabuk
-        '08', // Al Hudud ash Shamaliyah
-        '09', // Jizan
-        '10', // Najran
-        '11', // Al Bahah
+        '03', // Al Madīnah
+        '04', // Ash Sharqīyah
+        '05', // Al QaÅŸÄ«m
+        '06', // Ḥā'il
+        '07', // Tabūk
+        '08', // Al Ḥudūd ash Shamāliyah
+        '09', // JÄ«zan
+        '10', // Najrān
+        '11', // Al Bāhah
         '12', // Al Jawf
-        '14', // 'Asir
+        '14', // `Asīr
     ];
 
     public $compareIdentical = true;
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/SbSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/SbSubdivisionCode.php
index daeaedc4c9c7b6c22b5fb5a0b3eca98903f82398..af6413977a59b501ae6208975fdf9745275e94b0 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/SbSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/SbSubdivisionCode.php
@@ -18,14 +18,14 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: SB
  *
- * @link http://www.geonames.org/SB/administrative-division-solomon-islands.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class SbSubdivisionCode extends AbstractSearcher
 {
     public $haystack = [
         'CE', // Central
         'CH', // Choiseul
-        'CT', // Capital Territory
+        'CT', // Capital Territory (Honiara)
         'GU', // Guadalcanal
         'IS', // Isabel
         'MK', // Makira
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/ScSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/ScSubdivisionCode.php
index 9f0dfe210761ce49fe6e711baa0b7ab244c39bec..4f7372540ebcfb214ad52c5c47bc3b06544349a9 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/ScSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/ScSubdivisionCode.php
@@ -18,7 +18,7 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: SC
  *
- * @link http://www.geonames.org/SC/administrative-division-seychelles.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class ScSubdivisionCode extends AbstractSearcher
 {
@@ -35,19 +35,19 @@ class ScSubdivisionCode extends AbstractSearcher
         '10', // Bel Ombre
         '11', // Cascade
         '12', // Glacis
-        '13', // Grand' Anse (on Mahe)
-        '14', // Grand' Anse (on Praslin)
+        '13', // Grand Anse Mahe
+        '14', // Grand Anse Praslin
         '15', // La Digue
-        '16', // La Riviere Anglaise
+        '16', // English River
         '17', // Mont Buxton
         '18', // Mont Fleuri
         '19', // Plaisance
-        '20', // Pointe La Rue
+        '20', // Pointe Larue
         '21', // Port Glaud
         '22', // Saint Louis
         '23', // Takamaka
         '24', // Les Mamelles
-        '25', // Roche Caïman
+        '25', // Roche Caiman
     ];
 
     public $compareIdentical = true;
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/SdSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/SdSubdivisionCode.php
index 89c9574cc382bc3b8d1c812318d068557b906160..f438dbddd802bbe473ffa324e1748b4615cf5d13 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/SdSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/SdSubdivisionCode.php
@@ -18,12 +18,12 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: SD
  *
- * @link http://www.geonames.org/SD/administrative-division-sudan.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class SdSubdivisionCode extends AbstractSearcher
 {
     public $haystack = [
-        'DC', // Wasaţ Dārfūr
+        'DC', // Zalingei
         'DE', // Sharq Dārfūr
         'DN', // Shamāl Dārfūr
         'DS', // Janūb Dārfūr
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/SeSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/SeSubdivisionCode.php
index 273cf470253859fa08ebf58e5ee0b0d55b4336ba..8737ec4492bdfa188a28f022ffbb2b130c676f89 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/SeSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/SeSubdivisionCode.php
@@ -18,32 +18,32 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: SE
  *
- * @link http://www.geonames.org/SE/administrative-division-sweden.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class SeSubdivisionCode extends AbstractSearcher
 {
     public $haystack = [
-        'AB', // Stockholms
-        'AC', // Vasterbottens
-        'BD', // Norrbottens
-        'C', // Uppsala
-        'D', // Sodermanlands
-        'E', // Ostergotlands
-        'F', // Jonkopings
-        'G', // Kronobergs
-        'H', // Kalmar
-        'I', // Gotlands
-        'K', // Blekinge
-        'M', // Skåne
-        'N', // Hallands
-        'O', // Västra Götaland
-        'S', // Varmlands
-        'T', // Orebro
-        'U', // Vastmanlands
-        'W', // Dalarna
-        'X', // Gavleborgs
-        'Y', // Vasternorrlands
-        'Z', // Jamtlands
+        'AB', // Stockholms län
+        'AC', // Västerbottens län
+        'BD', // Norrbottens län
+        'C', // Uppsala län
+        'D', // Södermanlands län
+        'E', // Östergötlands län
+        'F', // Jönköpings län
+        'G', // Kronobergs län
+        'H', // Kalmar län
+        'I', // Gotlands län
+        'K', // Blekinge län
+        'M', // Skåne län
+        'N', // Hallands län
+        'O', // Västra Götalands län
+        'S', // Värmlands län
+        'T', // Örebro län
+        'U', // Västmanlands län
+        'W', // Dalarnas län
+        'X', // Gävleborgs län
+        'Y', // Västernorrlands län
+        'Z', // Jämtlands län
     ];
 
     public $compareIdentical = true;
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/SgSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/SgSubdivisionCode.php
index 7cad35e542fffd744dfae8220c729c99a3d221a1..ef951ed4390b6ee56d41fed094045ab366a77efd 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/SgSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/SgSubdivisionCode.php
@@ -18,7 +18,7 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: SG
  *
- * @link http://www.geonames.org/SG/administrative-division-singapore.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class SgSubdivisionCode extends AbstractSearcher
 {
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/ShSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/ShSubdivisionCode.php
index c2189a64ba1dd50142205df1a974a588580d9feb..90e27d3a27b512c5e9b08eb456c3342150db4864 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/ShSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/ShSubdivisionCode.php
@@ -18,7 +18,7 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: SH
  *
- * @link http://www.geonames.org/SH/administrative-division-saint-helena.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class ShSubdivisionCode extends AbstractSearcher
 {
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/SiSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/SiSubdivisionCode.php
index b5584631ae24dc3c485fe5546508639345c4e3a8..7e5fbb1111d50ed6751642629078913fbe716047 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/SiSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/SiSubdivisionCode.php
@@ -18,7 +18,7 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: SI
  *
- * @link http://www.geonames.org/SI/administrative-division-slovenia.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class SiSubdivisionCode extends AbstractSearcher
 {
@@ -49,7 +49,7 @@ class SiSubdivisionCode extends AbstractSearcher
         '024', // Dornava
         '025', // Dravograd
         '026', // Duplek
-        '027', // Gorenja Vas-Poljane
+        '027', // Gorenja vas-Poljane
         '028', // Gorišnica
         '029', // Gornja Radgona
         '030', // Gornji Grad
@@ -87,7 +87,7 @@ class SiSubdivisionCode extends AbstractSearcher
         '062', // Ljubno
         '063', // Ljutomer
         '064', // Logatec
-        '065', // Loška Dolina
+        '065', // Loška dolina
         '066', // Loški Potok
         '067', // Luče
         '068', // Lukovica
@@ -107,7 +107,7 @@ class SiSubdivisionCode extends AbstractSearcher
         '082', // Naklo
         '083', // Nazarje
         '084', // Nova Gorica
-        '085', // Novo Mesto
+        '085', // Novo mesto
         '086', // Odranci
         '087', // Ormož
         '088', // Osilnica
@@ -137,6 +137,7 @@ class SiSubdivisionCode extends AbstractSearcher
         '112', // Slovenj Gradec
         '113', // Slovenska Bistrica
         '114', // Slovenske Konjice
+        '115', // Starče
         '116', // Sveti Jurij
         '117', // Šenčur
         '118', // Å entilj
@@ -176,7 +177,7 @@ class SiSubdivisionCode extends AbstractSearcher
         '153', // Cerkvenjak
         '154', // Dobje
         '155', // Dobrna
-        '156', // Dobrovnik-Dobronak
+        '156', // Dobrovnik/Dobronak
         '157', // Dolenjske Toplice
         '158', // Grad
         '159', // Hajdina
@@ -202,7 +203,7 @@ class SiSubdivisionCode extends AbstractSearcher
         '179', // Sodražica
         '180', // Solčava
         '181', // Sveta Ana
-        '182', // Sveti Andraž v Slovenskih goricah
+        '182', // Sveta Andraž v Slovenskih Goricah
         '183', // Å empeter-Vrtojba
         '184', // Tabor
         '185', // Trnovska vas
@@ -226,13 +227,12 @@ class SiSubdivisionCode extends AbstractSearcher
         '203', // Straža
         '204', // Sveta Trojica v Slovenskih Goricah
         '205', // Sveti Tomaž
-        '206', // Šmarješke Toplice
+        '206', // Šmarjeske Topliče
         '207', // Gorje
         '208', // Log-Dragomer
         '209', // Rečica ob Savinji
         '210', // Sveti Jurij v Slovenskih Goricah
         '211', // Å entrupert
-        '215', // Starše
     ];
 
     public $compareIdentical = true;
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/SjSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/SjSubdivisionCode.php
index d66c2e808e73bc26703dfe53ccea54f4f956c6f1..26230e871d708111b90ad1993af192744b1a6554 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/SjSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/SjSubdivisionCode.php
@@ -18,7 +18,7 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: SJ
  *
- * @link http://www.geonames.org/SJ/administrative-division-svalbard-and-jan-mayen.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class SjSubdivisionCode extends AbstractSearcher
 {
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/SkSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/SkSubdivisionCode.php
index 620d5d10dab27a6be3302180fba87efccf73d8a4..0a91d401c22603cf1d5ff20b9227496616f6c688 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/SkSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/SkSubdivisionCode.php
@@ -18,19 +18,19 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: SK
  *
- * @link http://www.geonames.org/SK/administrative-division-slovakia.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class SkSubdivisionCode extends AbstractSearcher
 {
     public $haystack = [
-        'BC', // Banskobystricky
-        'BL', // Bratislavsky
-        'KI', // Kosicky
-        'NI', // Nitriansky
-        'PV', // Presovsky
-        'TA', // Trnavsky
-        'TC', // Trenciansky
-        'ZI', // Zilinsky
+        'BC', // Banskobystrický kraj
+        'BL', // Bratislavský kraj
+        'KI', // Košický kraj
+        'NI', // Nitriansky kraj
+        'PV', // Prešovský kraj
+        'TA', // Trnavský kraj
+        'TC', // Trenčiansky kraj
+        'ZI', // Žilinský kraj
     ];
 
     public $compareIdentical = true;
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/SlSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/SlSubdivisionCode.php
index ac6fb83c7be7973e6e85c8b9a9d6969731be29af..d71273546364abb1c9e5766114c48bd9b0e8fd98 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/SlSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/SlSubdivisionCode.php
@@ -18,15 +18,15 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: SL
  *
- * @link http://www.geonames.org/SL/administrative-division-sierra-leone.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class SlSubdivisionCode extends AbstractSearcher
 {
     public $haystack = [
         'E', // Eastern
         'N', // Northern
-        'S', // Southern
-        'W', // Western
+        'S', // Southern (Sierra Leone)
+        'W', // Western Area (Freetown)
     ];
 
     public $compareIdentical = true;
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/SmSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/SmSubdivisionCode.php
index d81be92bf6919fd147d15cd8a81a389c5fb91ba5..75314be9132dcbb557798caafcf2d520d61cda9b 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/SmSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/SmSubdivisionCode.php
@@ -18,7 +18,7 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: SM
  *
- * @link http://www.geonames.org/SM/administrative-division-san-marino.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class SmSubdivisionCode extends AbstractSearcher
 {
@@ -29,7 +29,7 @@ class SmSubdivisionCode extends AbstractSearcher
         '04', // Faetano
         '05', // Fiorentino
         '06', // Borgo Maggiore
-        '07', // Citta di San Marino
+        '07', // San Marino
         '08', // Montegiardino
         '09', // Serravalle
     ];
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/SnSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/SnSubdivisionCode.php
index 09edb61196b9ec0366e704bcd5624f7df6c64209..c9902d5e65bce58576b5d9a4ca06c0044ce27ab1 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/SnSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/SnSubdivisionCode.php
@@ -18,7 +18,7 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: SN
  *
- * @link http://www.geonames.org/SN/administrative-division-senegal.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class SnSubdivisionCode extends AbstractSearcher
 {
@@ -35,7 +35,7 @@ class SnSubdivisionCode extends AbstractSearcher
         'SE', // Sédhiou
         'SL', // Saint-Louis
         'TC', // Tambacounda
-        'TH', // Thies
+        'TH', // Thiès
         'ZG', // Ziguinchor
     ];
 
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/SoSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/SoSubdivisionCode.php
index d0fe1b57a3f207b8074c328e683347b5e9636675..8f72ffa4d6aca09a5f9ce2bb522d512aa5764065 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/SoSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/SoSubdivisionCode.php
@@ -18,7 +18,7 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: SO
  *
- * @link http://www.geonames.org/SO/administrative-division-somalia.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class SoSubdivisionCode extends AbstractSearcher
 {
@@ -30,12 +30,12 @@ class SoSubdivisionCode extends AbstractSearcher
         'BY', // Bay
         'GA', // Galguduud
         'GE', // Gedo
-        'HI', // Hiiraan
+        'HI', // Hiirsan
         'JD', // Jubbada Dhexe
         'JH', // Jubbada Hoose
         'MU', // Mudug
         'NU', // Nugaal
-        'SA', // Sanaag
+        'SA', // Saneag
         'SD', // Shabeellaha Dhexe
         'SH', // Shabeellaha Hoose
         'SO', // Sool
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/SrSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/SrSubdivisionCode.php
index d560c2d1661a7d2ba543beeb82c62bc04a73a42e..633bf6ad02044033be2702a98de27f63174babbb 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/SrSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/SrSubdivisionCode.php
@@ -18,7 +18,7 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: SR
  *
- * @link http://www.geonames.org/SR/administrative-division-suriname.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class SrSubdivisionCode extends AbstractSearcher
 {
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/SsSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/SsSubdivisionCode.php
index b2ed28331aa29944bc3aa3953857296d37dd0c1c..e38480015705e2fbbd298848c4643903893ece4c 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/SsSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/SsSubdivisionCode.php
@@ -18,15 +18,15 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: SS
  *
- * @link http://www.geonames.org/SS/administrative-division-south-sudan.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class SsSubdivisionCode extends AbstractSearcher
 {
     public $haystack = [
-        'BN', // Northern Bahr el Ghazal
-        'BW', // Western Bahr el Ghazal
+        'BN', // Northern Bahr el-Ghazal
+        'BW', // Western Bahr el-Ghazal
         'EC', // Central Equatoria
-        'EE', // Eastern Equatoria
+        'EE8', // Eastern Equatoria
         'EW', // Western Equatoria
         'JG', // Jonglei
         'LK', // Lakes
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/StSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/StSubdivisionCode.php
index 5f08b04e73154fa177b3790b0bf000e65230df4e..99dab470869efda37f2bf5f0d05a9de05c528fce 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/StSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/StSubdivisionCode.php
@@ -18,13 +18,13 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: ST
  *
- * @link http://www.geonames.org/ST/administrative-division-sao-tome-and-principe.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class StSubdivisionCode extends AbstractSearcher
 {
     public $haystack = [
-        'P', // Principe
-        'S', // Sao Tome
+        'P', // Príncipe
+        'S', // São Tomé
     ];
 
     public $compareIdentical = true;
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/SvSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/SvSubdivisionCode.php
index f30e7c3fdf2cd5e9992aa14937a289a0aef30e3c..7b30d04811db9514130edc4ced5688a4782edf43 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/SvSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/SvSubdivisionCode.php
@@ -18,25 +18,25 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: SV
  *
- * @link http://www.geonames.org/SV/administrative-division-el-salvador.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class SvSubdivisionCode extends AbstractSearcher
 {
     public $haystack = [
-        'AH', // Ahuachapan
-        'CA', // Cabanas
+        'AH', // Ahuachapán
+        'CA', // Cabañas
         'CH', // Chalatenango
-        'CU', // Cuscatlan
+        'CU', // Cuscatlán
         'LI', // La Libertad
-        'MO', // Morazan
+        'MO', // Morazán
         'PA', // La Paz
         'SA', // Santa Ana
         'SM', // San Miguel
         'SO', // Sonsonate
         'SS', // San Salvador
         'SV', // San Vicente
-        'UN', // La Union
-        'US', // Usulutan
+        'UN', // La Unión
+        'US', // Usulután
     ];
 
     public $compareIdentical = true;
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/SxSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/SxSubdivisionCode.php
index f89823a4e43bcf8d02034922214e17041fa4df51..12a52c0a9cd9fbe4a320a80bcd0c0342ae2b80fa 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/SxSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/SxSubdivisionCode.php
@@ -18,7 +18,7 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: SX
  *
- * @link http://www.geonames.org/SX/administrative-division-sint-maarten.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class SxSubdivisionCode extends AbstractSearcher
 {
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/SySubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/SySubdivisionCode.php
index 8bc624284046f1d0027fb60aa0c5693e333b91b6..0c334dcef74099a3a8fdcffb681ab8f83df2ba15 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/SySubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/SySubdivisionCode.php
@@ -18,16 +18,16 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: SY
  *
- * @link http://www.geonames.org/SY/administrative-division-syria.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class SySubdivisionCode extends AbstractSearcher
 {
     public $haystack = [
         'DI', // Dimashq
-        'DR', // Dara
+        'DR', // Dar'a
         'DY', // Dayr az Zawr
         'HA', // Al Hasakah
-        'HI', // Hims
+        'HI', // Homs
         'HL', // Halab
         'HM', // Hamah
         'ID', // Idlib
@@ -35,7 +35,7 @@ class SySubdivisionCode extends AbstractSearcher
         'QU', // Al Qunaytirah
         'RA', // Ar Raqqah
         'RD', // Rif Dimashq
-        'SU', // As Suwayda
+        'SU', // As Suwayda'
         'TA', // Tartus
     ];
 
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/SzSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/SzSubdivisionCode.php
index 94f64e7e4c8e77bd4700f451fbf52aad8be9cb8b..2f35c4b0dbd9cfbd2c67e4f241295b343786e999 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/SzSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/SzSubdivisionCode.php
@@ -18,7 +18,7 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: SZ
  *
- * @link http://www.geonames.org/SZ/administrative-division-swaziland.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class SzSubdivisionCode extends AbstractSearcher
 {
@@ -26,7 +26,7 @@ class SzSubdivisionCode extends AbstractSearcher
         'HH', // Hhohho
         'LU', // Lubombo
         'MA', // Manzini
-        'SH', // Shishelweni
+        'SH', // Shiselweni
     ];
 
     public $compareIdentical = true;
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/TcSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/TcSubdivisionCode.php
index dfea0c095d20a658206123ac9406d46ff4cbc170..e0c4e52a011fb5707bdfb347f5641ad2074bfeed 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/TcSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/TcSubdivisionCode.php
@@ -18,7 +18,7 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: TC
  *
- * @link http://www.geonames.org/TC/administrative-division-turks-and-caicos-islands.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class TcSubdivisionCode extends AbstractSearcher
 {
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/TdSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/TdSubdivisionCode.php
index aac3c0287c4116169a41b052ee4fe8f4baa16efd..cc09e174fd82d96b3a3454c77024b72a2e7d3061 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/TdSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/TdSubdivisionCode.php
@@ -18,35 +18,33 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: TD
  *
- * @link http://www.geonames.org/TD/administrative-division-chad.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class TdSubdivisionCode extends AbstractSearcher
 {
     public $haystack = [
-        'BA', // Batha
-        'BG', // Barh el Ghazel
-        'BO', // Borkou
-        'CB', // Chari-Baguirmi
-        'EN', // Ennedi Est
-        'EN', // Ennedi Quest
-        'GR', // Guéra
-        'HL', // Hadjer-Lamis
-        'KA', // Kanem
-        'LC', // Lac
-        'LO', // Logone Occidental
-        'LR', // Logone Oriental
-        'MA', // Mandoul
-        'MC', // Moyen-Chari
-        'ME', // Mayo-Kebbi Est
-        'MO', // Mayo-Kebbi Ouest
-        'ND', // Ville de N'Djamena
-        'OD', // Ouaddaï
-        'SA', // Salamat
-        'SI', // Sila
-        'TA', // Tandjile
-        'TI', // Tibesti
-        'WF', // Wadi Fira
-        'EN', // Ennedi
+        'BA', // Al Baṭḩah
+        'BG', // Baḩr al Ghazāl
+        'BO', // Būrkū
+        'CB', // Shārī Bāqirmī
+        'EN', // Innīdī
+        'GR', // Qīrā
+        'HL', // Ḥajjar Lamīs
+        'KA', // Kānim
+        'LC', // Al Buḩayrah
+        'LO', // Lūqūn al Gharbī
+        'LR', // Lūqūn ash Sharqī
+        'MA', // Māndūl
+        'MC', // Shārī al Awsaṭ
+        'ME', // Māyū Kībbī ash Sharqī
+        'MO', // Māyū Kībbī al Gharbī
+        'ND', // Madīnat Injamīnā
+        'OD', // Waddāy
+        'SA', // Salāmāt
+        'SI', // Sīlā
+        'TA', // Tānjilī
+        'TI', // Tibastī
+        'WF', // Wādī Fīrā
     ];
 
     public $compareIdentical = true;
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/TfSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/TfSubdivisionCode.php
index 2cee3515e20f9dea4338382e04ea5b5550d96073..59b8d6773dae3fe1dacf5c342be2cfa8efd24efe 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/TfSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/TfSubdivisionCode.php
@@ -18,7 +18,7 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: TF
  *
- * @link http://www.geonames.org/TF/administrative-division-french-southern-territories.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class TfSubdivisionCode extends AbstractSearcher
 {
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/TgSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/TgSubdivisionCode.php
index dd87ff02fae215c54c9f0a290a6f36d31cd25db0..d2583cef246f32cd0771d5e12a8dad832c408d5f 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/TgSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/TgSubdivisionCode.php
@@ -18,16 +18,16 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: TG
  *
- * @link http://www.geonames.org/TG/administrative-division-togo.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class TgSubdivisionCode extends AbstractSearcher
 {
     public $haystack = [
-        'C', // Centrale
-        'K', // Kara
-        'M', // Maritime
-        'P', // Plateaux
-        'S', // Savanes
+        'C', // Région du Centre
+        'K', // Région de la Kara
+        'M', // Région Maritime
+        'P', // Région des Plateaux
+        'S', // Région des Savannes
     ];
 
     public $compareIdentical = true;
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/ThSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/ThSubdivisionCode.php
index 1e5fbe557ca01def86a5f284bfc930cb32eb0817..50157cc022564983ce5510527e986ce742ef26dc 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/ThSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/ThSubdivisionCode.php
@@ -18,12 +18,12 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: TH
  *
- * @link http://www.geonames.org/TH/administrative-division-thailand.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class ThSubdivisionCode extends AbstractSearcher
 {
     public $haystack = [
-        '10', // Bangkok
+        '10', // Krung Thep Maha Nakhon Bangkok
         '11', // Samut Prakan
         '12', // Nonthaburi
         '13', // Pathum Thani
@@ -49,7 +49,6 @@ class ThSubdivisionCode extends AbstractSearcher
         '35', // Yasothon
         '36', // Chaiyaphum
         '37', // Amnat Charoen
-        '38', // Bueng Kan
         '39', // Nong Bua Lam Phu
         '40', // Khon Kaen
         '41', // Udon Thani
@@ -80,7 +79,7 @@ class ThSubdivisionCode extends AbstractSearcher
         '67', // Phetchabun
         '70', // Ratchaburi
         '71', // Kanchanaburi
-        '72', // Suphanburi
+        '72', // Suphan Buri
         '73', // Nakhon Pathom
         '74', // Samut Sakhon
         '75', // Samut Songkhram
@@ -88,18 +87,19 @@ class ThSubdivisionCode extends AbstractSearcher
         '77', // Prachuap Khiri Khan
         '80', // Nakhon Si Thammarat
         '81', // Krabi
-        '82', // Phang Nga
+        '82', // Phangnga
         '83', // Phuket
         '84', // Surat Thani
         '85', // Ranong
-        '86', // Chumpon
+        '86', // Chumphon
         '90', // Songkhla
         '91', // Satun
         '92', // Trang
-        '93', // Phattalung
+        '93', // Phatthalung
         '94', // Pattani
         '95', // Yala
         '96', // Narathiwat
+        'S', // Phatthaya
     ];
 
     public $compareIdentical = true;
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/TjSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/TjSubdivisionCode.php
index f07d46b09a1f9333128ba83c45619eec72dce65a..9e4f98d67e3414bfebffc88865ec6e072af4c731 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/TjSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/TjSubdivisionCode.php
@@ -18,12 +18,12 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: TJ
  *
- * @link http://www.geonames.org/TJ/administrative-division-tajikistan.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class TjSubdivisionCode extends AbstractSearcher
 {
     public $haystack = [
-        'GB', // Gorno-Badakhstan
+        'GB', // Gorno-Badakhshan
         'KT', // Khatlon
         'SU', // Sughd
     ];
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/TkSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/TkSubdivisionCode.php
index 13ce7c8bc27b23fd3ae61558360214c5336708f1..9f8296c350ebe5bee3bce7f8a863aff26d54d68b 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/TkSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/TkSubdivisionCode.php
@@ -18,7 +18,7 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: TK
  *
- * @link http://www.geonames.org/TK/administrative-division-tokelau.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class TkSubdivisionCode extends AbstractSearcher
 {
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/TlSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/TlSubdivisionCode.php
index b803a9a62e562c1988fd4e260b5705f264392d2e..41de30410dc5fef4c7d6361a73457270d796f02b 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/TlSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/TlSubdivisionCode.php
@@ -18,7 +18,7 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: TL
  *
- * @link http://www.geonames.org/TL/administrative-division-east-timor.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class TlSubdivisionCode extends AbstractSearcher
 {
@@ -28,10 +28,10 @@ class TlSubdivisionCode extends AbstractSearcher
         'BA', // Baucau
         'BO', // Bobonaro
         'CO', // Cova Lima
-        'DI', // Dili
+        'DI', // Díli
         'ER', // Ermera
         'LA', // Lautem
-        'LI', // Liquica
+        'LI', // Liquiça
         'MF', // Manufahi
         'MT', // Manatuto
         'OE', // Oecussi
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/TmSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/TmSubdivisionCode.php
index b9a4540b32caa545a8ec4cd03365db250d96496a..5ecef8e664673b706e4ff150f0e2b2db174dfe68 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/TmSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/TmSubdivisionCode.php
@@ -18,16 +18,16 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: TM
  *
- * @link http://www.geonames.org/TM/administrative-division-turkmenistan.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class TmSubdivisionCode extends AbstractSearcher
 {
     public $haystack = [
-        'A', // Ahal Welayaty
-        'B', // Balkan Welayaty
-        'D', // Dashhowuz Welayaty
-        'L', // Lebap Welayaty
-        'M', // Mary Welayaty
+        'A', // Ahal
+        'B', // Balkan
+        'D', // DaÅŸoguz
+        'L', // Lebap
+        'M', // Mary
         'S', // AÅŸgabat
     ];
 
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/TnSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/TnSubdivisionCode.php
index 90c621cfc758010fff2b2e3894715c73eb9c356e..850ce23f7ce1bf9a2b1c88a39ccf23916873ca27 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/TnSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/TnSubdivisionCode.php
@@ -18,13 +18,13 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: TN
  *
- * @link http://www.geonames.org/TN/administrative-division-tunisia.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class TnSubdivisionCode extends AbstractSearcher
 {
     public $haystack = [
         '11', // Tunis
-        '12', // L'Ariana
+        '12', // Ariana
         '13', // Ben Arous
         '14', // La Manouba
         '21', // Nabeul
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/ToSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/ToSubdivisionCode.php
index 2d895e6dd2ca3543703fd08a55ea928f2f6f92bc..8e130f91a8d2dcfc4b298bc99d0a85dec59c7b35 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/ToSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/ToSubdivisionCode.php
@@ -18,12 +18,12 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: TO
  *
- * @link http://www.geonames.org/TO/administrative-division-tonga.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class ToSubdivisionCode extends AbstractSearcher
 {
     public $haystack = [
-        '01', // Eua
+        '01', // 'Eua
         '02', // Ha'apai
         '03', // Niuas
         '04', // Tongatapu
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/TrSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/TrSubdivisionCode.php
index 88605bae3eeffbdeac4f87dd6fabd5ff09adc845..34181f2acb981db4d9134501c04514abd37a948f 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/TrSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/TrSubdivisionCode.php
@@ -18,62 +18,62 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: TR
  *
- * @link http://www.geonames.org/TR/administrative-division-turkey.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class TrSubdivisionCode extends AbstractSearcher
 {
     public $haystack = [
         '01', // Adana
-        '02', // Adiyaman
+        '02', // Adıyaman
         '03', // Afyonkarahisar
-        '04', // Agri
+        '04', // Ağrı
         '05', // Amasya
         '06', // Ankara
         '07', // Antalya
         '08', // Artvin
-        '09', // Aydin
-        '10', // Balikesir
+        '09', // Aydın
+        '10', // Balıkesir
         '11', // Bilecik
-        '12', // Bingol
+        '12', // Bingöl
         '13', // Bitlis
         '14', // Bolu
         '15', // Burdur
         '16', // Bursa
-        '17', // Canakkale
-        '18', // Cankiri
-        '19', // Corum
+        '17', // Çanakkale
+        '18', // Çankırı
+        '19', // Çorum
         '20', // Denizli
-        '21', // Diyarbakir
+        '21', // Diyarbakır
         '22', // Edirne
-        '23', // Elazig
+        '23', // Elazığ
         '24', // Erzincan
         '25', // Erzurum
-        '26', // Eskisehir
+        '26', // EskiÅŸehir
         '27', // Gaziantep
         '28', // Giresun
-        '29', // Gumushane
-        '30', // Hakkari
+        '29', // Gümüşhane
+        '30', // Hakkâri
         '31', // Hatay
         '32', // Isparta
         '33', // Mersin
-        '34', // Istanbul
-        '35', // Izmir
+        '34', // Ä°stanbul
+        '35', // Ä°zmir
         '36', // Kars
         '37', // Kastamonu
         '38', // Kayseri
-        '39', // Kirklareli
-        '40', // Kirsehir
+        '39', // Kırklareli
+        '40', // Kırşehir
         '41', // Kocaeli
         '42', // Konya
-        '43', // Kutahya
+        '43', // Kütahya
         '44', // Malatya
         '45', // Manisa
-        '46', // Kahramanmaras
+        '46', // KahramanmaraÅŸ
         '47', // Mardin
-        '48', // Mugla
-        '49', // Mus
-        '50', // Nevsehir
-        '51', // Nigde
+        '48', // MuÄŸla
+        '49', // MuÅŸ
+        '50', // NevÅŸehir
+        '51', // NiÄŸde
         '52', // Ordu
         '53', // Rize
         '54', // Sakarya
@@ -81,29 +81,29 @@ class TrSubdivisionCode extends AbstractSearcher
         '56', // Siirt
         '57', // Sinop
         '58', // Sivas
-        '59', // Tekirdag
+        '59', // TekirdaÄŸ
         '60', // Tokat
         '61', // Trabzon
         '62', // Tunceli
-        '63', // Sanliurfa
-        '64', // Usak
+        '63', // Şanlıurfa
+        '64', // UÅŸak
         '65', // Van
         '66', // Yozgat
         '67', // Zonguldak
         '68', // Aksaray
         '69', // Bayburt
         '70', // Karaman
-        '71', // Kirikkale
+        '71', // Kırıkkale
         '72', // Batman
-        '73', // Sirnak
-        '74', // Bartin
+        '73', // Şırnak
+        '74', // Bartın
         '75', // Ardahan
-        '76', // Igdir
+        '76', // Iğdır
         '77', // Yalova
-        '78', // Karabuk
+        '78', // Karabük
         '79', // Kilis
         '80', // Osmaniye
-        '81', // Duzce
+        '81', // Düzce
     ];
 
     public $compareIdentical = true;
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/TtSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/TtSubdivisionCode.php
index c93c9603e2775188f41d7d9671327e226fe026ed..2c1279af7af3ec663ed9513f5b12cb63312820a3 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/TtSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/TtSubdivisionCode.php
@@ -18,27 +18,27 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: TT
  *
- * @link http://www.geonames.org/TT/administrative-division-trinidad-and-tobago.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class TtSubdivisionCode extends AbstractSearcher
 {
     public $haystack = [
         'ARI', // Arima
         'CHA', // Chaguanas
-        'CTT', // Couva/Tabaquite/Talparo
+        'CTT', // Couva-Tabaquite-Talparo
         'DMN', // Diego Martin
         'ETO', // Eastern Tobago
-        'PED', // Penal/Debe
+        'PED', // Penal-Debe
         'POS', // Port of Spain
         'PRT', // Princes Town
         'PTF', // Point Fortin
-        'RCM', // Mayaro/Rio Claro
+        'RCM', // Rio Claro-Mayaro
         'SFO', // San Fernando
         'SGE', // Sangre Grande
         'SIP', // Siparia
-        'SJL', // San Juan/Laventille
-        'TUP', // Tunapuna/Piarco
-        'WTO', // Tobago
+        'SJL', // San Juan-Laventille
+        'TUP', // Tunapuna-Piarco
+        'WTO', // Western Tobago
     ];
 
     public $compareIdentical = true;
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/TvSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/TvSubdivisionCode.php
index 5757e7eb45f9982d69fcd92b6c8f941da351220d..3265e30fe12d3d7443782264f3cd3cc75cb25e33 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/TvSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/TvSubdivisionCode.php
@@ -18,7 +18,7 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: TV
  *
- * @link http://www.geonames.org/TV/administrative-division-tuvalu.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class TvSubdivisionCode extends AbstractSearcher
 {
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/TwSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/TwSubdivisionCode.php
index 8cddb494279bf6c070e4ada621c26f46590b94db..cb1c4a03a7a02b989943416cf37462bf444799aa 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/TwSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/TwSubdivisionCode.php
@@ -18,32 +18,34 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: TW
  *
- * @link http://www.geonames.org/TW/administrative-division-taiwan.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class TwSubdivisionCode extends AbstractSearcher
 {
     public $haystack = [
         'CHA', // Changhua
-        'CYI', // Chiayi
+        'CYI', // Chiay City
         'CYQ', // Chiayi
         'HSQ', // Hsinchu
-        'HSZ', // Hsinchu
+        'HSZ', // Hsinchui City
         'HUA', // Hualien
         'ILA', // Ilan
-        'KEE', // Keelung
-        'KHH', // Kaohsiung
+        'KEE', // Keelung City
+        'KHH', // Kaohsiung City
+        'KHQ', // Kaohsiung
         'MIA', // Miaoli
         'NAN', // Nantou
         'PEN', // Penghu
         'PIF', // Pingtung
         'TAO', // Taoyuan
-        'TNN', // Tainan
-        'TPE', // Taipei
-        'TPQ', // New Taipei
+        'TNN', // Tainan City
+        'TNQ', // Tainan
+        'TPE', // Taipei City
+        'TPQ', // Taipei
         'TTT', // Taitung
-        'TXG', // Taichung
+        'TXG', // Taichung City
+        'TXQ', // Taichung
         'YUN', // Yunlin
-        'TXQ', // Taichung County
     ];
 
     public $compareIdentical = true;
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/TzSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/TzSubdivisionCode.php
index 04678b175b5da5af7500455bb0ae3b51e807e7e1..5b720c2823d96175567a9a88398e464cc44e3e19 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/TzSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/TzSubdivisionCode.php
@@ -18,26 +18,26 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: TZ
  *
- * @link http://www.geonames.org/TZ/administrative-division-tanzania.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class TzSubdivisionCode extends AbstractSearcher
 {
     public $haystack = [
         '01', // Arusha
-        '02', // Dar es Salaam
+        '02', // Dar-es-Salaam
         '03', // Dodoma
         '04', // Iringa
         '05', // Kagera
-        '06', // Pemba North
-        '07', // Zanzibar North
+        '06', // Kaskazini Pemba
+        '07', // Kaskazini Unguja
         '08', // Kigoma
         '09', // Kilimanjaro
-        '10', // Pemba South
-        '11', // Zanzibar Central/South
+        '10', // Kusini Pemba
+        '11', // Kusini Unguja
         '12', // Lindi
         '13', // Mara
         '14', // Mbeya
-        '15', // Zanzibar Urban/West
+        '15', // Mjini Magharibi
         '16', // Morogoro
         '17', // Mtwara
         '18', // Mwanza
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/UaSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/UaSubdivisionCode.php
index 8b4c9337c69e2c5831347a2b4c2cd64ab6882e0d..533ad72355b5824e8da48c543e1fa6248989bd57 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/UaSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/UaSubdivisionCode.php
@@ -18,38 +18,38 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: UA
  *
- * @link http://www.geonames.org/UA/administrative-division-ukraine.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class UaSubdivisionCode extends AbstractSearcher
 {
     public $haystack = [
-        '05', // Vinnytsya
-        '07', // Volyn'
-        '09', // Luhans'k
-        '12', // Dnipropetrovs'k
-        '14', // Donets'k
-        '18', // Zhytomyr
-        '21', // Zakarpattya
-        '23', // Zaporizhzhya
-        '26', // Ivano-Frankivs'k
-        '30', // Kyyiv
-        '32', // Kiev
-        '35', // Kirovohrad
+        '05', // Vinnyts'ka Oblast'
+        '07', // Volyns'ka Oblast'
+        '09', // Luhans'ka Oblast'
+        '12', // Dnipropetrovs'ka Oblast'
+        '14', // Donets'ka Oblast'
+        '18', // Zhytomyrs'ka Oblast'
+        '21', // Zakarpats'ka Oblast'
+        '23', // Zaporiz'ka Oblast'
+        '26', // Ivano-Frankivs'ka Oblast'
+        '30', // Kyïvs'ka mis'ka rada
+        '32', // Kyïvs'ka Oblast'
+        '35', // Kirovohrads'ka Oblast'
         '40', // Sevastopol
-        '43', // Crimea
-        '46', // L'viv
-        '48', // Mykolayiv
-        '51', // Odesa
-        '53', // Poltava
-        '56', // Rivne
-        '59', // Sumy
-        '61', // Ternopil'
-        '63', // Kharkiv
-        '65', // Kherson
-        '68', // Khmel'nyts'kyy
-        '71', // Cherkasy
-        '74', // Chernihiv
-        '77', // Chernivtsi
+        '43', // Respublika Krym
+        '46', // L'vivs'ka Oblast'
+        '48', // Mykolaïvs'ka Oblast'
+        '51', // Odes'ka Oblast'
+        '53', // Poltavs'ka Oblast'
+        '56', // Rivnens'ka Oblast'
+        '59', // Sums 'ka Oblast'
+        '61', // Ternopil's'ka Oblast'
+        '63', // Kharkivs'ka Oblast'
+        '65', // Khersons'ka Oblast'
+        '68', // Khmel'nyts'ka Oblast'
+        '71', // Cherkas'ka Oblast'
+        '74', // Chernihivs'ka Oblast'
+        '77', // Chernivets'ka Oblast'
     ];
 
     public $compareIdentical = true;
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/UgSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/UgSubdivisionCode.php
index 63b4596c93a4fd64ffd1baeca7255d71454f7a21..c8384252f3306a712862e01f03348bd73d225160 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/UgSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/UgSubdivisionCode.php
@@ -18,15 +18,11 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: UG
  *
- * @link http://www.geonames.org/UG/administrative-division-uganda.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class UgSubdivisionCode extends AbstractSearcher
 {
     public $haystack = [
-        'C', // Central
-        'E', // Eastern
-        'N', // Northern
-        'W', // Western
         '101', // Kalangala
         '102', // Kampala
         '103', // Kiboga
@@ -107,6 +103,10 @@ class UgSubdivisionCode extends AbstractSearcher
         '417', // Isingiro
         '418', // Kiruhura
         '419', // Buliisa
+        'C', // Central
+        'E', // Eastern
+        'N', // Northern
+        'W', // Western
     ];
 
     public $compareIdentical = true;
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/UmSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/UmSubdivisionCode.php
index 64a5fa2f43f534380cec49701d6231f17dda18e3..c7e1e8ca494db5b76991083327da8c7998a691d2 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/UmSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/UmSubdivisionCode.php
@@ -18,13 +18,13 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: UM
  *
- * @link http://www.geonames.org/UM/administrative-division-united-states-minor-outlying-islands.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class UmSubdivisionCode extends AbstractSearcher
 {
     public $haystack = [
         '67', // Johnston Atoll
-        '71', // Midway Atoll
+        '71', // Midway Islands
         '76', // Navassa Island
         '79', // Wake Island
         '81', // Baker Island
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/UsSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/UsSubdivisionCode.php
index b9c86b350996e534dcb125454eddd5c990ee86f3..7d000a37c4968d1d651a63511a63f53ad4e7c202 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/UsSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/UsSubdivisionCode.php
@@ -18,7 +18,7 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: US
  *
- * @link http://www.geonames.org/US/administrative-division-united-states.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class UsSubdivisionCode extends AbstractSearcher
 {
@@ -71,10 +71,10 @@ class UsSubdivisionCode extends AbstractSearcher
         'SD', // South Dakota
         'TN', // Tennessee
         'TX', // Texas
-        'UM', // U.S. Minor Outlying Islands
+        'UM', // United States Minor Outlying Islands
         'UT', // Utah
         'VA', // Virginia
-        'VI', // Virgin Islands of the U.S.
+        'VI', // Virgin Islands
         'VT', // Vermont
         'WA', // Washington
         'WI', // Wisconsin
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/UySubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/UySubdivisionCode.php
index 8692cb5810463aed849ff1269cd87014498b7dff..399a3968fdebf06fdac01cba74cb27d869cf7bb5 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/UySubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/UySubdivisionCode.php
@@ -18,7 +18,7 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: UY
  *
- * @link http://www.geonames.org/UY/administrative-division-uruguay.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class UySubdivisionCode extends AbstractSearcher
 {
@@ -33,12 +33,12 @@ class UySubdivisionCode extends AbstractSearcher
         'LA', // Lavalleja
         'MA', // Maldonado
         'MO', // Montevideo
-        'PA', // Paysandu
-        'RN', // Rio Negro
+        'PA', // Paysandú
+        'RN', // Río Negro
         'RO', // Rocha
         'RV', // Rivera
         'SA', // Salto
-        'SJ', // San Jose
+        'SJ', // San José
         'SO', // Soriano
         'TA', // Tacuarembó
         'TT', // Treinta y Tres
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/UzSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/UzSubdivisionCode.php
index fc7e9c9fa6e6b8c5053665c2a75720e76bb91aed..496744db89407a09d643410b965ecbff727e2ff7 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/UzSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/UzSubdivisionCode.php
@@ -18,7 +18,7 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: UZ
  *
- * @link http://www.geonames.org/UZ/administrative-division-uzbekistan.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class UzSubdivisionCode extends AbstractSearcher
 {
@@ -30,12 +30,12 @@ class UzSubdivisionCode extends AbstractSearcher
         'NG', // Namangan
         'NW', // Navoiy
         'QA', // Qashqadaryo
-        'QR', // Qoraqalpog'iston Republikasi
+        'QR', // Qoraqalpog'iston Respublikasi
         'SA', // Samarqand
         'SI', // Sirdaryo
         'SU', // Surxondaryo
-        'TK', // Toshkent city
-        'TO', // Toshkent region
+        'TK', // Toshkent
+        'TO', // Toshkent
         'XO', // Xorazm
     ];
 
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/VaSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/VaSubdivisionCode.php
index 2e128b542dbed15a64a6daa960c5a43ede6a7901..7c91df2d9ce14d27ae1a4632a6300b201d4980f4 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/VaSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/VaSubdivisionCode.php
@@ -18,7 +18,7 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: VA
  *
- * @link http://www.geonames.org/VA/administrative-division-vatican-city.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class VaSubdivisionCode extends AbstractSearcher
 {
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/VcSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/VcSubdivisionCode.php
index 339126165ab675eabd24478f8fad38c4a826b184..481e5756e4c6666bfd58b9bba840b8a347954071 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/VcSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/VcSubdivisionCode.php
@@ -18,7 +18,7 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: VC
  *
- * @link http://www.geonames.org/VC/administrative-division-saint-vincent-and-the-grenadines.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class VcSubdivisionCode extends AbstractSearcher
 {
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/VeSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/VeSubdivisionCode.php
index 7ec212fc06918248b161addd113046ccfbb51429..c2a37dbbeebf73c15eab315d6bd5e40634d2d758 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/VeSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/VeSubdivisionCode.php
@@ -18,33 +18,33 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: VE
  *
- * @link http://www.geonames.org/VE/administrative-division-venezuela.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class VeSubdivisionCode extends AbstractSearcher
 {
     public $haystack = [
-        'A', // Federal Capital
-        'B', // Anzoategui
+        'A', // Distrito Federal
+        'B', // Anzoátegui
         'C', // Apure
         'D', // Aragua
         'E', // Barinas
-        'F', // Bolivar
+        'F', // Bolívar
         'G', // Carabobo
         'H', // Cojedes
-        'I', // Falcon
-        'J', // Guarico
+        'I', // Falcón
+        'J', // Guárico
         'K', // Lara
-        'L', // Merida
+        'L', // Mérida
         'M', // Miranda
         'N', // Monagas
         'O', // Nueva Esparta
         'P', // Portuguesa
         'R', // Sucre
-        'S', // Tachira
+        'S', // Táchira
         'T', // Trujillo
         'U', // Yaracuy
         'V', // Zulia
-        'W', // Federal Dependency
+        'W', // Dependencias Federales
         'X', // Vargas
         'Y', // Delta Amacuro
         'Z', // Amazonas
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/VgSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/VgSubdivisionCode.php
index 29240aca19abe5fa52affb89bc264f0f2a4fb25d..36a3c2e2dd09829ed0313abae43b6337800976cc 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/VgSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/VgSubdivisionCode.php
@@ -18,7 +18,7 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: VG
  *
- * @link http://www.geonames.org/VG/administrative-division-british-virgin-islands.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class VgSubdivisionCode extends AbstractSearcher
 {
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/ViSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/ViSubdivisionCode.php
index 684f8e6de5f83272a45c78353fd7fb3672c1ff97..8bf0b3ad65c819f142a84b5df6189181e61db635 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/ViSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/ViSubdivisionCode.php
@@ -18,7 +18,7 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: VI
  *
- * @link http://www.geonames.org/VI/administrative-division-u-s-virgin-islands.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class ViSubdivisionCode extends AbstractSearcher
 {
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/VnSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/VnSubdivisionCode.php
index d219db88f8ee037d89ad46f903ee3f56ee98f5ed..81c3ef1b93926e3679d4187bac3b544b3dc6d8e3 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/VnSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/VnSubdivisionCode.php
@@ -18,75 +18,75 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: VN
  *
- * @link http://www.geonames.org/VN/administrative-division-vietnam.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class VnSubdivisionCode extends AbstractSearcher
 {
     public $haystack = [
-        '01', // Lai Chau
-        '02', // Lao Cai
-        '03', // Ha Giang
-        '04', // Cao Bang
-        '05', // Son La
-        '06', // Yen Bai
-        '07', // Tuyen Quang
-        '09', // Lang Son
-        '13', // Quang Ninh
-        '14', // Hoa Binh
-        '18', // Ninh Binh
-        '20', // Thai Binh
-        '21', // Thanh Hoa
-        '22', // Nghe An
-        '23', // Ha Tinh
-        '24', // Quang Binh
-        '25', // Quang Tri
-        '26', // Thua Thien-Hue
-        '27', // Quang Nam
+        '01', // Lai Châu
+        '02', // Lào Cai
+        '03', // Hà Giang
+        '04', // Cao Bằng
+        '05', // SÆ¡n La
+        '06', // Yên Bái
+        '07', // Tuyên Quang
+        '09', // Lạng Sơn
+        '13', // Quảng Ninh
+        '14', // Hoà Bình
+        '15', // Hà Tây
+        '18', // Ninh Bình
+        '20', // Thái Bình
+        '21', // Thanh Hóa
+        '22', // Nghệ An
+        '23', // Hà Tỉnh
+        '24', // Quảng Bình
+        '25', // Quảng Trị
+        '26', // Thừa Thiên-Huế
+        '27', // Quảng Nam
         '28', // Kon Tum
-        '29', // Quang Ngai
+        '29', // Quảng Ngãi
         '30', // Gia Lai
-        '31', // Binh Dinh
-        '32', // Phu Yen
-        '33', // Dak Lak
-        '34', // Khanh Hoa
-        '35', // Lam Dong
-        '36', // Ninh Thuan
-        '37', // Tay Ninh
-        '39', // Dong Nai
-        '40', // Binh Thuan
+        '31', // Bình Định
+        '32', // Phú Yên
+        '33', // Đắc Lắk
+        '34', // Khánh Hòa
+        '35', // Lâm Đồng
+        '36', // Ninh Thuận
+        '37', // Tây Ninh
+        '39', // Đồng Nai
+        '40', // Bình Thuận
         '41', // Long An
-        '43', // Ba Ria-Vung Tau
+        '43', // Bà Rịa-Vũng Tàu
         '44', // An Giang
-        '45', // Dong Thap
-        '46', // Tien Giang
-        '47', // Kien Giang
-        '48', // Can Tho
-        '49', // Vinh Long
-        '50', // Ben Tre
-        '51', // Tra Vinh
-        '52', // Soc Trang
-        '53', // Bac Can
-        '54', // Bac Giang
-        '55', // Bac Lieu
-        '56', // Bac Ninh
-        '57', // Binh Duong
-        '58', // Binh Phuoc
-        '59', // Ca Mau
-        '60', // Da Nang
-        '61', // Hai Duong
-        '62', // Hai Phong
-        '63', // Ha Nam
-        '64', // Ha Noi
-        '65', // Ho Chi Minh
-        '66', // Hung Yen
-        '67', // Nam Dinh
-        '68', // Phu Tho
-        '69', // Thai Nguyen
-        '70', // Vinh Phuc
-        '71', // Dien Bien
-        '72', // Dak Nong
-        '73', // Hau Giang
-        '15', // Ha Tay
+        '45', // Đồng Tháp
+        '46', // Tiền Giang
+        '47', // Kiên Giang
+        '49', // VÄ©nh Long
+        '50', // Bến Tre
+        '51', // Trà Vinh
+        '52', // Sóc Trăng
+        '53', // Bắc Kạn
+        '54', // Bắc Giang
+        '55', // Bạc Liêu
+        '56', // Bắc Ninh
+        '57', // Bình Dương
+        '58', // Bình Phước
+        '59', // Cà Mau
+        '61', // Hải Duong
+        '63', // Hà Nam
+        '66', // Hưng Yên
+        '67', // Nam Định
+        '68', // Phú Thọ
+        '69', // Thái Nguyên
+        '70', // Vĩnh Phúc
+        '71', // Điện Biên
+        '72', // Đắk Nông
+        '73', // Hậu Giang
+        'CT', // Cần Thơ
+        'DN', // Đà Nẵng
+        'HN', // Hà Nội
+        'HP', // Hải Phòng
+        'SG', // Hồ Chí Minh [Sài Gòn]
     ];
 
     public $compareIdentical = true;
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/VuSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/VuSubdivisionCode.php
index 8657749b861558474f6cb9577ad612de132fc06f..58761ffeeb6e3cdaf3ab8dbc72f763d0c9c1606b 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/VuSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/VuSubdivisionCode.php
@@ -18,16 +18,16 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: VU
  *
- * @link http://www.geonames.org/VU/administrative-division-vanuatu.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class VuSubdivisionCode extends AbstractSearcher
 {
     public $haystack = [
         'MAP', // Malampa
-        'PAM', // Penama
+        'PAM', // Pénama
         'SAM', // Sanma
-        'SEE', // Shefa
-        'TAE', // Tafea
+        'SEE', // Shéfa
+        'TAE', // Taféa
         'TOB', // Torba
     ];
 
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/WfSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/WfSubdivisionCode.php
index 1497d3dc045f5bd7c7cecceeb4bdc0f0f4e0056c..0099253c08e9ed1e3419abe9f1a1768f75e01523 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/WfSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/WfSubdivisionCode.php
@@ -18,7 +18,7 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: WF
  *
- * @link http://www.geonames.org/WF/administrative-division-wallis-and-futuna.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class WfSubdivisionCode extends AbstractSearcher
 {
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/WsSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/WsSubdivisionCode.php
index 9d1ab9ef1eb000d692af529fb55425160c60642d..869b9258b06b4f57ea3d53f219f012c9c0afb3ed 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/WsSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/WsSubdivisionCode.php
@@ -18,7 +18,7 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: WS
  *
- * @link http://www.geonames.org/WS/administrative-division-samoa.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class WsSubdivisionCode extends AbstractSearcher
 {
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/XkSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/XkSubdivisionCode.php
index 98c039ebdd8ae0223081dc227efb2955f0958256..1015a714a47316ad337fc54de830d83885e8a633 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/XkSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/XkSubdivisionCode.php
@@ -18,7 +18,7 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: XK
  *
- * @link http://www.geonames.org/XK/administrative-division-kosovo.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class XkSubdivisionCode extends AbstractSearcher
 {
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/YeSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/YeSubdivisionCode.php
index 0c5049f672f70b53dd55b934cfb4af5ec82ce243..116bb29031a4223196a18ca4ddac1005280beafa 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/YeSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/YeSubdivisionCode.php
@@ -18,32 +18,31 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: YE
  *
- * @link http://www.geonames.org/YE/administrative-division-yemen.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class YeSubdivisionCode extends AbstractSearcher
 {
     public $haystack = [
-        'AB', // Abyan
-        'AD', // Adan
-        'AM', // Amran
-        'BA', // Al Bayda
-        'DA', // Ad Dali
-        'DH', // Dhamar
-        'HD', // Hadramawt
-        'HJ', // Hajjah
-        'HU', // Al Hudaydah
+        'AB', // Abyān
+        'AD', // 'Adan
+        'AM', // 'Amrān
+        'BA', // Al Bayḑā'
+        'DA', // Aḑ Ḑāli‘
+        'DH', // Dhamār
+        'HD', // Ḩaḑramawt
+        'HJ', // Ḩajjah
         'IB', // Ibb
         'JA', // Al Jawf
-        'LA', // Lahij
+        'LA', // Laḩij
         'MA', // Ma'rib
         'MR', // Al Mahrah
-        'MW', // Al Mahwit
+        'MU', // Al Ḩudaydah
+        'MW', // Al Maḩwīt
         'RA', // Raymah
-        'SA', // Amanat Al Asimah
-        'SD', // Sa'dah
+        'SD', // Åža'dah
         'SH', // Shabwah
-        'SN', // San'a
-        'TA', // Ta'izz
+        'SN', // Şan'ā'
+        'TA', // Tā'izz
     ];
 
     public $compareIdentical = true;
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/YtSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/YtSubdivisionCode.php
index a3ae34f0c2a8d17cde0a03458969534d808aaf50..0685091cbc7f22f034e42a39d1b428edd700b030 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/YtSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/YtSubdivisionCode.php
@@ -18,7 +18,7 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: YT
  *
- * @link http://www.geonames.org/YT/administrative-division-mayotte.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class YtSubdivisionCode extends AbstractSearcher
 {
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/ZaSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/ZaSubdivisionCode.php
index cb1244114bbeb79dca01156087ac84c24168b656..a7ed6b1798a4d71d02eea8acb5c4a5e6b50e6618 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/ZaSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/ZaSubdivisionCode.php
@@ -18,20 +18,20 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: ZA
  *
- * @link http://www.geonames.org/ZA/administrative-division-south-africa.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class ZaSubdivisionCode extends AbstractSearcher
 {
     public $haystack = [
         'EC', // Eastern Cape
         'FS', // Free State
-        'GP', // Gauteng
+        'GT', // Gauteng
         'LP', // Limpopo
         'MP', // Mpumalanga
         'NC', // Northern Cape
-        'NW', // North West
+        'NL', // Kwazulu-Natal
+        'NW', // North-West (South Africa)
         'WC', // Western Cape
-        'ZN', // KwaZulu-Natal
     ];
 
     public $compareIdentical = true;
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/ZmSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/ZmSubdivisionCode.php
index 6ae8525636f62cd56adedd02a819684e0aa6ceb6..24707e01bc3dbaaf7fb413a5177de7df8bf86c44 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/ZmSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/ZmSubdivisionCode.php
@@ -18,20 +18,20 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: ZM
  *
- * @link http://www.geonames.org/ZM/administrative-division-zambia.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class ZmSubdivisionCode extends AbstractSearcher
 {
     public $haystack = [
-        '01', // Western Province
-        '02', // Central Province
-        '03', // Eastern Province
-        '04', // Luapula Province
-        '05', // Northern Province
-        '06', // North-Western Province
-        '07', // Southern Province
-        '08', // Copperbelt Province
-        '09', // Lusaka Province
+        '01', // Western
+        '02', // Central
+        '03', // Eastern
+        '04', // Luapula
+        '05', // Northern
+        '06', // North-Western
+        '07', // Southern (Zambia)
+        '08', // Copperbelt
+        '09', // Lusaka
     ];
 
     public $compareIdentical = true;
diff --git a/vendor/respect/validation/library/Rules/SubdivisionCode/ZwSubdivisionCode.php b/vendor/respect/validation/library/Rules/SubdivisionCode/ZwSubdivisionCode.php
index 9b873b5b68a389f88f0d0c5b8b26fed497da1ebe..78ffeed8f4dd81a2b53655de1483141029d88edf 100644
--- a/vendor/respect/validation/library/Rules/SubdivisionCode/ZwSubdivisionCode.php
+++ b/vendor/respect/validation/library/Rules/SubdivisionCode/ZwSubdivisionCode.php
@@ -18,13 +18,13 @@ use Respect\Validation\Rules\AbstractSearcher;
  *
  * ISO 3166-1 alpha-2: ZW
  *
- * @link http://www.geonames.org/ZW/administrative-division-zimbabwe.html
+ * @link https://salsa.debian.org/iso-codes-team/iso-codes
  */
 class ZwSubdivisionCode extends AbstractSearcher
 {
     public $haystack = [
-        'BU', // Bulawayo (city)
-        'HA', // Harare (city)
+        'BU', // Bulawayo
+        'HA', // Harare
         'MA', // Manicaland
         'MC', // Mashonaland Central
         'ME', // Mashonaland East
diff --git a/vendor/respect/validation/library/Rules/Tld.php b/vendor/respect/validation/library/Rules/Tld.php
index fe53ad898ef3dd6413a367011b549a539cd1e397..038ffc7d06774a5ecadea7d6cb1f8af2b274d2db 100644
--- a/vendor/respect/validation/library/Rules/Tld.php
+++ b/vendor/respect/validation/library/Rules/Tld.php
@@ -13,14 +13,14 @@ namespace Respect\Validation\Rules;
 
 class Tld extends AbstractRule
 {
+    // List extracted from https://data.iana.org/TLD/tlds-alpha-by-domain.txt
+    // Version 2019052600, Last Updated Sun May 26 07:07:02 2019 UTC
     protected $tldList = [
-        // https://data.iana.org/TLD/tlds-alpha-by-domain.txt
-        // Version 2018100800, Last Updated Mon Oct  8 07:07:01 2018 UTC
         'aaa', 'aarp', 'abarth', 'abb', 'abbott', 'abbvie', 'abc', 'able',
         'abogado', 'abudhabi', 'ac', 'academy', 'accenture', 'accountant',
-        'accountants', 'aco', 'active', 'actor', 'ad', 'adac', 'ads', 'adult',
-        'ae', 'aeg', 'aero', 'aetna', 'af', 'afamilycompany', 'afl', 'africa',
-        'ag', 'agakhan', 'agency', 'ai', 'aig', 'aigo', 'airbus', 'airforce',
+        'accountants', 'aco', 'actor', 'ad', 'adac', 'ads', 'adult', 'ae',
+        'aeg', 'aero', 'aetna', 'af', 'afamilycompany', 'afl', 'africa', 'ag',
+        'agakhan', 'agency', 'ai', 'aig', 'aigo', 'airbus', 'airforce',
         'airtel', 'akdn', 'al', 'alfaromeo', 'alibaba', 'alipay', 'allfinanz',
         'allstate', 'ally', 'alsace', 'alstom', 'am', 'americanexpress',
         'americanfamily', 'amex', 'amfam', 'amica', 'amsterdam', 'analytics',
@@ -35,101 +35,101 @@ class Tld extends AbstractRule
         'bbt', 'bbva', 'bcg', 'bcn', 'bd', 'be', 'beats', 'beauty', 'beer',
         'bentley', 'berlin', 'best', 'bestbuy', 'bet', 'bf', 'bg', 'bh',
         'bharti', 'bi', 'bible', 'bid', 'bike', 'bing', 'bingo', 'bio', 'biz',
-        'bj', 'black', 'blackfriday', 'blanco', 'blockbuster', 'blog',
-        'bloomberg', 'blue', 'bm', 'bms', 'bmw', 'bn', 'bnl', 'bnpparibas',
-        'bo', 'boats', 'boehringer', 'bofa', 'bom', 'bond', 'boo', 'book',
-        'booking', 'bosch', 'bostik', 'boston', 'bot', 'boutique', 'box', 'br',
-        'bradesco', 'bridgestone', 'broadway', 'broker', 'brother', 'brussels',
-        'bs', 'bt', 'budapest', 'bugatti', 'build', 'builders', 'business',
-        'buy', 'buzz', 'bv', 'bw', 'by', 'bz', 'bzh', 'ca', 'cab', 'cafe',
-        'cal', 'call', 'calvinklein', 'cam', 'camera', 'camp',
-        'cancerresearch', 'canon', 'capetown', 'capital', 'capitalone', 'car',
-        'caravan', 'cards', 'care', 'career', 'careers', 'cars', 'cartier',
-        'casa', 'case', 'caseih', 'cash', 'casino', 'cat', 'catering',
-        'catholic', 'cba', 'cbn', 'cbre', 'cbs', 'cc', 'cd', 'ceb', 'center',
-        'ceo', 'cern', 'cf', 'cfa', 'cfd', 'cg', 'ch', 'chanel', 'channel',
-        'charity', 'chase', 'chat', 'cheap', 'chintai', 'christmas', 'chrome',
-        'chrysler', 'church', 'ci', 'cipriani', 'circle', 'cisco', 'citadel',
-        'citi', 'citic', 'city', 'cityeats', 'ck', 'cl', 'claims', 'cleaning',
-        'click', 'clinic', 'clinique', 'clothing', 'cloud', 'club', 'clubmed',
-        'cm', 'cn', 'co', 'coach', 'codes', 'coffee', 'college', 'cologne',
-        'com', 'comcast', 'commbank', 'community', 'company', 'compare',
-        'computer', 'comsec', 'condos', 'construction', 'consulting',
-        'contact', 'contractors', 'cooking', 'cookingchannel', 'cool', 'coop',
-        'corsica', 'country', 'coupon', 'coupons', 'courses', 'cr', 'credit',
-        'creditcard', 'creditunion', 'cricket', 'crown', 'crs', 'cruise',
-        'cruises', 'csc', 'cu', 'cuisinella', 'cv', 'cw', 'cx', 'cy', 'cymru',
-        'cyou', 'cz', 'dabur', 'dad', 'dance', 'data', 'date', 'dating',
-        'datsun', 'day', 'dclk', 'dds', 'de', 'deal', 'dealer', 'deals',
-        'degree', 'delivery', 'dell', 'deloitte', 'delta', 'democrat',
-        'dental', 'dentist', 'desi', 'design', 'dev', 'dhl', 'diamonds',
-        'diet', 'digital', 'direct', 'directory', 'discount', 'discover',
-        'dish', 'diy', 'dj', 'dk', 'dm', 'dnp', 'do', 'docs', 'doctor',
-        'dodge', 'dog', 'doha', 'domains', 'dot', 'download', 'drive', 'dtv',
-        'dubai', 'duck', 'dunlop', 'duns', 'dupont', 'durban', 'dvag', 'dvr',
-        'dz', 'earth', 'eat', 'ec', 'eco', 'edeka', 'edu', 'education', 'ee',
-        'eg', 'email', 'emerck', 'energy', 'engineer', 'engineering',
-        'enterprises', 'epost', 'epson', 'equipment', 'er', 'ericsson', 'erni',
-        'es', 'esq', 'estate', 'esurance', 'et', 'etisalat', 'eu',
-        'eurovision', 'eus', 'events', 'everbank', 'exchange', 'expert',
-        'exposed', 'express', 'extraspace', 'fage', 'fail', 'fairwinds',
-        'faith', 'family', 'fan', 'fans', 'farm', 'farmers', 'fashion', 'fast',
-        'fedex', 'feedback', 'ferrari', 'ferrero', 'fi', 'fiat', 'fidelity',
-        'fido', 'film', 'final', 'finance', 'financial', 'fire', 'firestone',
-        'firmdale', 'fish', 'fishing', 'fit', 'fitness', 'fj', 'fk', 'flickr',
-        'flights', 'flir', 'florist', 'flowers', 'fly', 'fm', 'fo', 'foo',
-        'food', 'foodnetwork', 'football', 'ford', 'forex', 'forsale', 'forum',
-        'foundation', 'fox', 'fr', 'free', 'fresenius', 'frl', 'frogans',
-        'frontdoor', 'frontier', 'ftr', 'fujitsu', 'fujixerox', 'fun', 'fund',
-        'furniture', 'futbol', 'fyi', 'ga', 'gal', 'gallery', 'gallo',
-        'gallup', 'game', 'games', 'gap', 'garden', 'gb', 'gbiz', 'gd', 'gdn',
-        'ge', 'gea', 'gent', 'genting', 'george', 'gf', 'gg', 'ggee', 'gh',
-        'gi', 'gift', 'gifts', 'gives', 'giving', 'gl', 'glade', 'glass',
-        'gle', 'global', 'globo', 'gm', 'gmail', 'gmbh', 'gmo', 'gmx', 'gn',
-        'godaddy', 'gold', 'goldpoint', 'golf', 'goo', 'goodyear', 'goog',
-        'google', 'gop', 'got', 'gov', 'gp', 'gq', 'gr', 'grainger',
-        'graphics', 'gratis', 'green', 'gripe', 'grocery', 'group', 'gs', 'gt',
-        'gu', 'guardian', 'gucci', 'guge', 'guide', 'guitars', 'guru', 'gw',
-        'gy', 'hair', 'hamburg', 'hangout', 'haus', 'hbo', 'hdfc', 'hdfcbank',
-        'health', 'healthcare', 'help', 'helsinki', 'here', 'hermes', 'hgtv',
-        'hiphop', 'hisamitsu', 'hitachi', 'hiv', 'hk', 'hkt', 'hm', 'hn',
-        'hockey', 'holdings', 'holiday', 'homedepot', 'homegoods', 'homes',
-        'homesense', 'honda', 'honeywell', 'horse', 'hospital', 'host',
-        'hosting', 'hot', 'hoteles', 'hotels', 'hotmail', 'house', 'how', 'hr',
-        'hsbc', 'ht', 'hu', 'hughes', 'hyatt', 'hyundai', 'ibm', 'icbc', 'ice',
-        'icu', 'id', 'ie', 'ieee', 'ifm', 'ikano', 'il', 'im', 'imamat',
-        'imdb', 'immo', 'immobilien', 'in', 'inc', 'industries', 'infiniti',
-        'info', 'ing', 'ink', 'institute', 'insurance', 'insure', 'int',
-        'intel', 'international', 'intuit', 'investments', 'io', 'ipiranga',
-        'iq', 'ir', 'irish', 'is', 'iselect', 'ismaili', 'ist', 'istanbul',
-        'it', 'itau', 'itv', 'iveco', 'jaguar', 'java', 'jcb', 'jcp', 'je',
-        'jeep', 'jetzt', 'jewelry', 'jio', 'jll', 'jm', 'jmp', 'jnj', 'jo',
-        'jobs', 'joburg', 'jot', 'joy', 'jp', 'jpmorgan', 'jprs', 'juegos',
-        'juniper', 'kaufen', 'kddi', 'ke', 'kerryhotels', 'kerrylogistics',
-        'kerryproperties', 'kfh', 'kg', 'kh', 'ki', 'kia', 'kim', 'kinder',
-        'kindle', 'kitchen', 'kiwi', 'km', 'kn', 'koeln', 'komatsu', 'kosher',
-        'kp', 'kpmg', 'kpn', 'kr', 'krd', 'kred', 'kuokgroup', 'kw', 'ky',
-        'kyoto', 'kz', 'la', 'lacaixa', 'ladbrokes', 'lamborghini', 'lamer',
-        'lancaster', 'lancia', 'lancome', 'land', 'landrover', 'lanxess',
-        'lasalle', 'lat', 'latino', 'latrobe', 'law', 'lawyer', 'lb', 'lc',
-        'lds', 'lease', 'leclerc', 'lefrak', 'legal', 'lego', 'lexus', 'lgbt',
-        'li', 'liaison', 'lidl', 'life', 'lifeinsurance', 'lifestyle',
-        'lighting', 'like', 'lilly', 'limited', 'limo', 'lincoln', 'linde',
-        'link', 'lipsy', 'live', 'living', 'lixil', 'lk', 'llc', 'loan',
-        'loans', 'locker', 'locus', 'loft', 'lol', 'london', 'lotte', 'lotto',
-        'love', 'lpl', 'lplfinancial', 'lr', 'ls', 'lt', 'ltd', 'ltda', 'lu',
-        'lundbeck', 'lupin', 'luxe', 'luxury', 'lv', 'ly', 'ma', 'macys',
-        'madrid', 'maif', 'maison', 'makeup', 'man', 'management', 'mango',
-        'map', 'market', 'marketing', 'markets', 'marriott', 'marshalls',
-        'maserati', 'mattel', 'mba', 'mc', 'mckinsey', 'md', 'me', 'med',
-        'media', 'meet', 'melbourne', 'meme', 'memorial', 'men', 'menu',
-        'merckmsd', 'metlife', 'mg', 'mh', 'miami', 'microsoft', 'mil', 'mini',
-        'mint', 'mit', 'mitsubishi', 'mk', 'ml', 'mlb', 'mls', 'mm', 'mma',
-        'mn', 'mo', 'mobi', 'mobile', 'mobily', 'moda', 'moe', 'moi', 'mom',
-        'monash', 'money', 'monster', 'mopar', 'mormon', 'mortgage', 'moscow',
-        'moto', 'motorcycles', 'mov', 'movie', 'movistar', 'mp', 'mq', 'mr',
-        'ms', 'msd', 'mt', 'mtn', 'mtr', 'mu', 'museum', 'mutual', 'mv', 'mw',
-        'mx', 'my', 'mz', 'na', 'nab', 'nadex', 'nagoya', 'name', 'nationwide',
+        'bj', 'black', 'blackfriday', 'blockbuster', 'blog', 'bloomberg',
+        'blue', 'bm', 'bms', 'bmw', 'bn', 'bnl', 'bnpparibas', 'bo', 'boats',
+        'boehringer', 'bofa', 'bom', 'bond', 'boo', 'book', 'booking', 'bosch',
+        'bostik', 'boston', 'bot', 'boutique', 'box', 'br', 'bradesco',
+        'bridgestone', 'broadway', 'broker', 'brother', 'brussels', 'bs', 'bt',
+        'budapest', 'bugatti', 'build', 'builders', 'business', 'buy', 'buzz',
+        'bv', 'bw', 'by', 'bz', 'bzh', 'ca', 'cab', 'cafe', 'cal', 'call',
+        'calvinklein', 'cam', 'camera', 'camp', 'cancerresearch', 'canon',
+        'capetown', 'capital', 'capitalone', 'car', 'caravan', 'cards', 'care',
+        'career', 'careers', 'cars', 'cartier', 'casa', 'case', 'caseih',
+        'cash', 'casino', 'cat', 'catering', 'catholic', 'cba', 'cbn', 'cbre',
+        'cbs', 'cc', 'cd', 'ceb', 'center', 'ceo', 'cern', 'cf', 'cfa', 'cfd',
+        'cg', 'ch', 'chanel', 'channel', 'charity', 'chase', 'chat', 'cheap',
+        'chintai', 'christmas', 'chrome', 'chrysler', 'church', 'ci',
+        'cipriani', 'circle', 'cisco', 'citadel', 'citi', 'citic', 'city',
+        'cityeats', 'ck', 'cl', 'claims', 'cleaning', 'click', 'clinic',
+        'clinique', 'clothing', 'cloud', 'club', 'clubmed', 'cm', 'cn', 'co',
+        'coach', 'codes', 'coffee', 'college', 'cologne', 'com', 'comcast',
+        'commbank', 'community', 'company', 'compare', 'computer', 'comsec',
+        'condos', 'construction', 'consulting', 'contact', 'contractors',
+        'cooking', 'cookingchannel', 'cool', 'coop', 'corsica', 'country',
+        'coupon', 'coupons', 'courses', 'cr', 'credit', 'creditcard',
+        'creditunion', 'cricket', 'crown', 'crs', 'cruise', 'cruises', 'csc',
+        'cu', 'cuisinella', 'cv', 'cw', 'cx', 'cy', 'cymru', 'cyou', 'cz',
+        'dabur', 'dad', 'dance', 'data', 'date', 'dating', 'datsun', 'day',
+        'dclk', 'dds', 'de', 'deal', 'dealer', 'deals', 'degree', 'delivery',
+        'dell', 'deloitte', 'delta', 'democrat', 'dental', 'dentist', 'desi',
+        'design', 'dev', 'dhl', 'diamonds', 'diet', 'digital', 'direct',
+        'directory', 'discount', 'discover', 'dish', 'diy', 'dj', 'dk', 'dm',
+        'dnp', 'do', 'docs', 'doctor', 'dodge', 'dog', 'domains', 'dot',
+        'download', 'drive', 'dtv', 'dubai', 'duck', 'dunlop', 'duns',
+        'dupont', 'durban', 'dvag', 'dvr', 'dz', 'earth', 'eat', 'ec', 'eco',
+        'edeka', 'edu', 'education', 'ee', 'eg', 'email', 'emerck', 'energy',
+        'engineer', 'engineering', 'enterprises', 'epson', 'equipment', 'er',
+        'ericsson', 'erni', 'es', 'esq', 'estate', 'esurance', 'et',
+        'etisalat', 'eu', 'eurovision', 'eus', 'events', 'everbank',
+        'exchange', 'expert', 'exposed', 'express', 'extraspace', 'fage',
+        'fail', 'fairwinds', 'faith', 'family', 'fan', 'fans', 'farm',
+        'farmers', 'fashion', 'fast', 'fedex', 'feedback', 'ferrari',
+        'ferrero', 'fi', 'fiat', 'fidelity', 'fido', 'film', 'final',
+        'finance', 'financial', 'fire', 'firestone', 'firmdale', 'fish',
+        'fishing', 'fit', 'fitness', 'fj', 'fk', 'flickr', 'flights', 'flir',
+        'florist', 'flowers', 'fly', 'fm', 'fo', 'foo', 'food', 'foodnetwork',
+        'football', 'ford', 'forex', 'forsale', 'forum', 'foundation', 'fox',
+        'fr', 'free', 'fresenius', 'frl', 'frogans', 'frontdoor', 'frontier',
+        'ftr', 'fujitsu', 'fujixerox', 'fun', 'fund', 'furniture', 'futbol',
+        'fyi', 'ga', 'gal', 'gallery', 'gallo', 'gallup', 'game', 'games',
+        'gap', 'garden', 'gb', 'gbiz', 'gd', 'gdn', 'ge', 'gea', 'gent',
+        'genting', 'george', 'gf', 'gg', 'ggee', 'gh', 'gi', 'gift', 'gifts',
+        'gives', 'giving', 'gl', 'glade', 'glass', 'gle', 'global', 'globo',
+        'gm', 'gmail', 'gmbh', 'gmo', 'gmx', 'gn', 'godaddy', 'gold',
+        'goldpoint', 'golf', 'goo', 'goodyear', 'goog', 'google', 'gop', 'got',
+        'gov', 'gp', 'gq', 'gr', 'grainger', 'graphics', 'gratis', 'green',
+        'gripe', 'grocery', 'group', 'gs', 'gt', 'gu', 'guardian', 'gucci',
+        'guge', 'guide', 'guitars', 'guru', 'gw', 'gy', 'hair', 'hamburg',
+        'hangout', 'haus', 'hbo', 'hdfc', 'hdfcbank', 'health', 'healthcare',
+        'help', 'helsinki', 'here', 'hermes', 'hgtv', 'hiphop', 'hisamitsu',
+        'hitachi', 'hiv', 'hk', 'hkt', 'hm', 'hn', 'hockey', 'holdings',
+        'holiday', 'homedepot', 'homegoods', 'homes', 'homesense', 'honda',
+        'honeywell', 'horse', 'hospital', 'host', 'hosting', 'hot', 'hoteles',
+        'hotels', 'hotmail', 'house', 'how', 'hr', 'hsbc', 'ht', 'hu',
+        'hughes', 'hyatt', 'hyundai', 'ibm', 'icbc', 'ice', 'icu', 'id', 'ie',
+        'ieee', 'ifm', 'ikano', 'il', 'im', 'imamat', 'imdb', 'immo',
+        'immobilien', 'in', 'inc', 'industries', 'infiniti', 'info', 'ing',
+        'ink', 'institute', 'insurance', 'insure', 'int', 'intel',
+        'international', 'intuit', 'investments', 'io', 'ipiranga', 'iq', 'ir',
+        'irish', 'is', 'iselect', 'ismaili', 'ist', 'istanbul', 'it', 'itau',
+        'itv', 'iveco', 'jaguar', 'java', 'jcb', 'jcp', 'je', 'jeep', 'jetzt',
+        'jewelry', 'jio', 'jll', 'jm', 'jmp', 'jnj', 'jo', 'jobs', 'joburg',
+        'jot', 'joy', 'jp', 'jpmorgan', 'jprs', 'juegos', 'juniper', 'kaufen',
+        'kddi', 'ke', 'kerryhotels', 'kerrylogistics', 'kerryproperties',
+        'kfh', 'kg', 'kh', 'ki', 'kia', 'kim', 'kinder', 'kindle', 'kitchen',
+        'kiwi', 'km', 'kn', 'koeln', 'komatsu', 'kosher', 'kp', 'kpmg', 'kpn',
+        'kr', 'krd', 'kred', 'kuokgroup', 'kw', 'ky', 'kyoto', 'kz', 'la',
+        'lacaixa', 'ladbrokes', 'lamborghini', 'lamer', 'lancaster', 'lancia',
+        'lancome', 'land', 'landrover', 'lanxess', 'lasalle', 'lat', 'latino',
+        'latrobe', 'law', 'lawyer', 'lb', 'lc', 'lds', 'lease', 'leclerc',
+        'lefrak', 'legal', 'lego', 'lexus', 'lgbt', 'li', 'liaison', 'lidl',
+        'life', 'lifeinsurance', 'lifestyle', 'lighting', 'like', 'lilly',
+        'limited', 'limo', 'lincoln', 'linde', 'link', 'lipsy', 'live',
+        'living', 'lixil', 'lk', 'llc', 'loan', 'loans', 'locker', 'locus',
+        'loft', 'lol', 'london', 'lotte', 'lotto', 'love', 'lpl',
+        'lplfinancial', 'lr', 'ls', 'lt', 'ltd', 'ltda', 'lu', 'lundbeck',
+        'lupin', 'luxe', 'luxury', 'lv', 'ly', 'ma', 'macys', 'madrid', 'maif',
+        'maison', 'makeup', 'man', 'management', 'mango', 'map', 'market',
+        'marketing', 'markets', 'marriott', 'marshalls', 'maserati', 'mattel',
+        'mba', 'mc', 'mckinsey', 'md', 'me', 'med', 'media', 'meet',
+        'melbourne', 'meme', 'memorial', 'men', 'menu', 'merckmsd', 'metlife',
+        'mg', 'mh', 'miami', 'microsoft', 'mil', 'mini', 'mint', 'mit',
+        'mitsubishi', 'mk', 'ml', 'mlb', 'mls', 'mm', 'mma', 'mn', 'mo',
+        'mobi', 'mobile', 'mobily', 'moda', 'moe', 'moi', 'mom', 'monash',
+        'money', 'monster', 'mopar', 'mormon', 'mortgage', 'moscow', 'moto',
+        'motorcycles', 'mov', 'movie', 'movistar', 'mp', 'mq', 'mr', 'ms',
+        'msd', 'mt', 'mtn', 'mtr', 'mu', 'museum', 'mutual', 'mv', 'mw', 'mx',
+        'my', 'mz', 'na', 'nab', 'nadex', 'nagoya', 'name', 'nationwide',
         'natura', 'navy', 'nba', 'nc', 'ne', 'nec', 'net', 'netbank',
         'netflix', 'network', 'neustar', 'new', 'newholland', 'news', 'next',
         'nextdirect', 'nexus', 'nf', 'nfl', 'ng', 'ngo', 'nhk', 'ni', 'nico',
@@ -169,46 +169,46 @@ class Tld extends AbstractRule
         'sk', 'ski', 'skin', 'sky', 'skype', 'sl', 'sling', 'sm', 'smart',
         'smile', 'sn', 'sncf', 'so', 'soccer', 'social', 'softbank',
         'software', 'sohu', 'solar', 'solutions', 'song', 'sony', 'soy',
-        'space', 'spiegel', 'sport', 'spot', 'spreadbetting', 'sr', 'srl',
-        'srt', 'st', 'stada', 'staples', 'star', 'starhub', 'statebank',
-        'statefarm', 'stc', 'stcgroup', 'stockholm', 'storage', 'store',
-        'stream', 'studio', 'study', 'style', 'su', 'sucks', 'supplies',
-        'supply', 'support', 'surf', 'surgery', 'suzuki', 'sv', 'swatch',
-        'swiftcover', 'swiss', 'sx', 'sy', 'sydney', 'symantec', 'systems',
-        'sz', 'tab', 'taipei', 'talk', 'taobao', 'target', 'tatamotors',
-        'tatar', 'tattoo', 'tax', 'taxi', 'tc', 'tci', 'td', 'tdk', 'team',
-        'tech', 'technology', 'tel', 'telefonica', 'temasek', 'tennis', 'teva',
-        'tf', 'tg', 'th', 'thd', 'theater', 'theatre', 'tiaa', 'tickets',
-        'tienda', 'tiffany', 'tips', 'tires', 'tirol', 'tj', 'tjmaxx', 'tjx',
-        'tk', 'tkmaxx', 'tl', 'tm', 'tmall', 'tn', 'to', 'today', 'tokyo',
-        'tools', 'top', 'toray', 'toshiba', 'total', 'tours', 'town', 'toyota',
-        'toys', 'tr', 'trade', 'trading', 'training', 'travel',
-        'travelchannel', 'travelers', 'travelersinsurance', 'trust', 'trv',
-        'tt', 'tube', 'tui', 'tunes', 'tushu', 'tv', 'tvs', 'tw', 'tz', 'ua',
-        'ubank', 'ubs', 'uconnect', 'ug', 'uk', 'unicom', 'university', 'uno',
-        'uol', 'ups', 'us', 'uy', 'uz', 'va', 'vacations', 'vana', 'vanguard',
-        'vc', 've', 'vegas', 'ventures', 'verisign', 'versicherung', 'vet',
-        'vg', 'vi', 'viajes', 'video', 'vig', 'viking', 'villas', 'vin', 'vip',
-        'virgin', 'visa', 'vision', 'vistaprint', 'viva', 'vivo', 'vlaanderen',
-        'vn', 'vodka', 'volkswagen', 'volvo', 'vote', 'voting', 'voto',
-        'voyage', 'vu', 'vuelos', 'wales', 'walmart', 'walter', 'wang',
-        'wanggou', 'warman', 'watch', 'watches', 'weather', 'weatherchannel',
-        'webcam', 'weber', 'website', 'wed', 'wedding', 'weibo', 'weir', 'wf',
-        'whoswho', 'wien', 'wiki', 'williamhill', 'win', 'windows', 'wine',
-        'winners', 'wme', 'wolterskluwer', 'woodside', 'work', 'works',
-        'world', 'wow', 'ws', 'wtc', 'wtf', 'xbox', 'xerox', 'xfinity',
-        'xihuan', 'xin', 'xn--11b4c3d', 'xn--1ck2e1b', 'xn--1qqw23a',
-        'xn--2scrj9c', 'xn--30rr7y', 'xn--3bst00m', 'xn--3ds443g',
-        'xn--3e0b707e', 'xn--3hcrj9c', 'xn--3oq18vl8pn36a', 'xn--3pxu8k',
-        'xn--42c2d9a', 'xn--45br5cyl', 'xn--45brj9c', 'xn--45q11c',
-        'xn--4gbrim', 'xn--54b7fta0cc', 'xn--55qw42g', 'xn--55qx5d',
-        'xn--5su34j936bgsg', 'xn--5tzm5g', 'xn--6frz82g', 'xn--6qq986b3xl',
-        'xn--80adxhks', 'xn--80ao21a', 'xn--80aqecdr1a', 'xn--80asehdb',
-        'xn--80aswg', 'xn--8y0a063a', 'xn--90a3ac', 'xn--90ae', 'xn--90ais',
-        'xn--9dbq2a', 'xn--9et52u', 'xn--9krt00a', 'xn--b4w605ferd',
-        'xn--bck1b9a5dre4c', 'xn--c1avg', 'xn--c2br7g', 'xn--cck2b3b',
-        'xn--cg4bki', 'xn--clchc0ea0b2g2a9gcd', 'xn--czr694b', 'xn--czrs0t',
-        'xn--czru2d', 'xn--d1acj3b', 'xn--d1alf', 'xn--e1a4c', 'xn--eckvdtc9d',
+        'space', 'sport', 'spot', 'spreadbetting', 'sr', 'srl', 'srt', 'ss',
+        'st', 'stada', 'staples', 'star', 'starhub', 'statebank', 'statefarm',
+        'stc', 'stcgroup', 'stockholm', 'storage', 'store', 'stream', 'studio',
+        'study', 'style', 'su', 'sucks', 'supplies', 'supply', 'support',
+        'surf', 'surgery', 'suzuki', 'sv', 'swatch', 'swiftcover', 'swiss',
+        'sx', 'sy', 'sydney', 'symantec', 'systems', 'sz', 'tab', 'taipei',
+        'talk', 'taobao', 'target', 'tatamotors', 'tatar', 'tattoo', 'tax',
+        'taxi', 'tc', 'tci', 'td', 'tdk', 'team', 'tech', 'technology', 'tel',
+        'telefonica', 'temasek', 'tennis', 'teva', 'tf', 'tg', 'th', 'thd',
+        'theater', 'theatre', 'tiaa', 'tickets', 'tienda', 'tiffany', 'tips',
+        'tires', 'tirol', 'tj', 'tjmaxx', 'tjx', 'tk', 'tkmaxx', 'tl', 'tm',
+        'tmall', 'tn', 'to', 'today', 'tokyo', 'tools', 'top', 'toray',
+        'toshiba', 'total', 'tours', 'town', 'toyota', 'toys', 'tr', 'trade',
+        'trading', 'training', 'travel', 'travelchannel', 'travelers',
+        'travelersinsurance', 'trust', 'trv', 'tt', 'tube', 'tui', 'tunes',
+        'tushu', 'tv', 'tvs', 'tw', 'tz', 'ua', 'ubank', 'ubs', 'uconnect',
+        'ug', 'uk', 'unicom', 'university', 'uno', 'uol', 'ups', 'us', 'uy',
+        'uz', 'va', 'vacations', 'vana', 'vanguard', 'vc', 've', 'vegas',
+        'ventures', 'verisign', 'versicherung', 'vet', 'vg', 'vi', 'viajes',
+        'video', 'vig', 'viking', 'villas', 'vin', 'vip', 'virgin', 'visa',
+        'vision', 'vistaprint', 'viva', 'vivo', 'vlaanderen', 'vn', 'vodka',
+        'volkswagen', 'volvo', 'vote', 'voting', 'voto', 'voyage', 'vu',
+        'vuelos', 'wales', 'walmart', 'walter', 'wang', 'wanggou', 'warman',
+        'watch', 'watches', 'weather', 'weatherchannel', 'webcam', 'weber',
+        'website', 'wed', 'wedding', 'weibo', 'weir', 'wf', 'whoswho', 'wien',
+        'wiki', 'williamhill', 'win', 'windows', 'wine', 'winners', 'wme',
+        'wolterskluwer', 'woodside', 'work', 'works', 'world', 'wow', 'ws',
+        'wtc', 'wtf', 'xbox', 'xerox', 'xfinity', 'xihuan', 'xin',
+        'xn--11b4c3d', 'xn--1ck2e1b', 'xn--1qqw23a', 'xn--2scrj9c',
+        'xn--30rr7y', 'xn--3bst00m', 'xn--3ds443g', 'xn--3e0b707e',
+        'xn--3hcrj9c', 'xn--3oq18vl8pn36a', 'xn--3pxu8k', 'xn--42c2d9a',
+        'xn--45br5cyl', 'xn--45brj9c', 'xn--45q11c', 'xn--4gbrim',
+        'xn--54b7fta0cc', 'xn--55qw42g', 'xn--55qx5d', 'xn--5su34j936bgsg',
+        'xn--5tzm5g', 'xn--6frz82g', 'xn--6qq986b3xl', 'xn--80adxhks',
+        'xn--80ao21a', 'xn--80aqecdr1a', 'xn--80asehdb', 'xn--80aswg',
+        'xn--8y0a063a', 'xn--90a3ac', 'xn--90ae', 'xn--90ais', 'xn--9dbq2a',
+        'xn--9et52u', 'xn--9krt00a', 'xn--b4w605ferd', 'xn--bck1b9a5dre4c',
+        'xn--c1avg', 'xn--c2br7g', 'xn--cck2b3b', 'xn--cg4bki',
+        'xn--clchc0ea0b2g2a9gcd', 'xn--czr694b', 'xn--czrs0t', 'xn--czru2d',
+        'xn--d1acj3b', 'xn--d1alf', 'xn--e1a4c', 'xn--eckvdtc9d',
         'xn--efvy88h', 'xn--estv75g', 'xn--fct429k', 'xn--fhbei',
         'xn--fiq228c5hs', 'xn--fiq64b', 'xn--fiqs8s', 'xn--fiqz9s',
         'xn--fjq720a', 'xn--flw351e', 'xn--fpcrj9c3d', 'xn--fzc2c9e2c',
@@ -220,24 +220,24 @@ class Tld extends AbstractRule
         'xn--kpu716f', 'xn--kput3i', 'xn--l1acc', 'xn--lgbbat1ad8j',
         'xn--mgb9awbf', 'xn--mgba3a3ejt', 'xn--mgba3a4f16a',
         'xn--mgba7c0bbn0a', 'xn--mgbaakc7dvf', 'xn--mgbaam7a8h',
-        'xn--mgbab2bd', 'xn--mgbai9azgqp6j', 'xn--mgbayh7gpa',
-        'xn--mgbb9fbpob', 'xn--mgbbh1a', 'xn--mgbbh1a71e', 'xn--mgbc0a9azcg',
-        'xn--mgbca7dzdo', 'xn--mgberp4a5d4ar', 'xn--mgbgu82a',
-        'xn--mgbi4ecexp', 'xn--mgbpl2fh', 'xn--mgbt3dhd', 'xn--mgbtx2b',
-        'xn--mgbx4cd0ab', 'xn--mix891f', 'xn--mk1bu44c', 'xn--mxtq1m',
-        'xn--ngbc5azd', 'xn--ngbe9e0a', 'xn--ngbrx', 'xn--node', 'xn--nqv7f',
-        'xn--nqv7fs00ema', 'xn--nyqy26a', 'xn--o3cw4h', 'xn--ogbpf8fl',
-        'xn--otu796d', 'xn--p1acf', 'xn--p1ai', 'xn--pbt977c', 'xn--pgbs0dh',
-        'xn--pssy2u', 'xn--q9jyb4c', 'xn--qcka1pmc', 'xn--qxam', 'xn--rhqv96g',
-        'xn--rovu88b', 'xn--rvc1e0am3e', 'xn--s9brj9c', 'xn--ses554g',
-        'xn--t60b56a', 'xn--tckwe', 'xn--tiq49xqyj', 'xn--unup4y',
-        'xn--vermgensberater-ctb', 'xn--vermgensberatung-pwb', 'xn--vhquv',
-        'xn--vuq861b', 'xn--w4r85el8fhu5dnra', 'xn--w4rs40l', 'xn--wgbh1c',
-        'xn--wgbl6a', 'xn--xhq521b', 'xn--xkc2al3hye2a', 'xn--xkc2dl3a5ee0h',
-        'xn--y9a3aq', 'xn--yfro4i67o', 'xn--ygbi2ammx', 'xn--zfr164b', 'xxx',
-        'xyz', 'yachts', 'yahoo', 'yamaxun', 'yandex', 'ye', 'yodobashi',
-        'yoga', 'yokohama', 'you', 'youtube', 'yt', 'yun', 'za', 'zappos',
-        'zara', 'zero', 'zip', 'zippo', 'zm', 'zone', 'zuerich', 'zw',
+        'xn--mgbab2bd', 'xn--mgbah1a3hjkrd', 'xn--mgbai9azgqp6j',
+        'xn--mgbayh7gpa', 'xn--mgbb9fbpob', 'xn--mgbbh1a', 'xn--mgbbh1a71e',
+        'xn--mgbc0a9azcg', 'xn--mgbca7dzdo', 'xn--mgberp4a5d4ar',
+        'xn--mgbgu82a', 'xn--mgbi4ecexp', 'xn--mgbpl2fh', 'xn--mgbt3dhd',
+        'xn--mgbtx2b', 'xn--mgbx4cd0ab', 'xn--mix891f', 'xn--mk1bu44c',
+        'xn--mxtq1m', 'xn--ngbc5azd', 'xn--ngbe9e0a', 'xn--ngbrx', 'xn--node',
+        'xn--nqv7f', 'xn--nqv7fs00ema', 'xn--nyqy26a', 'xn--o3cw4h',
+        'xn--ogbpf8fl', 'xn--otu796d', 'xn--p1acf', 'xn--p1ai', 'xn--pbt977c',
+        'xn--pgbs0dh', 'xn--pssy2u', 'xn--q9jyb4c', 'xn--qcka1pmc', 'xn--qxam',
+        'xn--rhqv96g', 'xn--rovu88b', 'xn--rvc1e0am3e', 'xn--s9brj9c',
+        'xn--ses554g', 'xn--t60b56a', 'xn--tckwe', 'xn--tiq49xqyj',
+        'xn--unup4y', 'xn--vermgensberater-ctb', 'xn--vermgensberatung-pwb',
+        'xn--vhquv', 'xn--vuq861b', 'xn--w4r85el8fhu5dnra', 'xn--w4rs40l',
+        'xn--wgbh1c', 'xn--wgbl6a', 'xn--xhq521b', 'xn--xkc2al3hye2a',
+        'xn--xkc2dl3a5ee0h', 'xn--y9a3aq', 'xn--yfro4i67o', 'xn--ygbi2ammx',
+        'xn--zfr164b', 'xxx', 'xyz', 'yachts', 'yahoo', 'yamaxun', 'yandex',
+        'ye', 'yodobashi', 'yoga', 'yokohama', 'you', 'youtube', 'yt', 'yun',
+        'za', 'zappos', 'zara', 'zero', 'zip', 'zm', 'zone', 'zuerich', 'zw',
     ];
 
     public function validate($input)
diff --git a/vendor/respect/validation/mkdocs.yml b/vendor/respect/validation/mkdocs.yml
new file mode 100644
index 0000000000000000000000000000000000000000..91814441c69facfb32402ae8d3e90f22cfab8d4f
--- /dev/null
+++ b/vendor/respect/validation/mkdocs.yml
@@ -0,0 +1,2 @@
+site_name: Respect\Validation
+theme: readthedocs
diff --git a/vendor/respect/validation/tests/fixtures/executable b/vendor/respect/validation/tests/fixtures/executable
new file mode 100755
index 0000000000000000000000000000000000000000..f2f2453406694809df1f1ea27a661cc682aa5880
--- /dev/null
+++ b/vendor/respect/validation/tests/fixtures/executable
@@ -0,0 +1,3 @@
+#!/usr/bin/env php
+<?php
+echo 'Hello world!', PHP_EOL;
diff --git a/vendor/respect/validation/tests/fixtures/non-writable b/vendor/respect/validation/tests/fixtures/non-writable
new file mode 100755
index 0000000000000000000000000000000000000000..8b909a63d3de4554b016c2d918ad1e8014218659
--- /dev/null
+++ b/vendor/respect/validation/tests/fixtures/non-writable
@@ -0,0 +1 @@
+The content of this file is not important
diff --git a/vendor/respect/validation/tests/fixtures/symbolic-link b/vendor/respect/validation/tests/fixtures/symbolic-link
new file mode 120000
index 0000000000000000000000000000000000000000..42892180f69eb3d112476d55d11f2569b652b678
--- /dev/null
+++ b/vendor/respect/validation/tests/fixtures/symbolic-link
@@ -0,0 +1 @@
+./valid-image.jpg
\ No newline at end of file
diff --git a/vendor/respect/validation/tests/integration/rules/callableType_4.phpt b/vendor/respect/validation/tests/integration/rules/callableType_4.phpt
index 954ff66827e6ca1f789ebee437eb71809b2cc159..01a92a567d791cb8921d3b6798ac40f55823b6cd 100644
--- a/vendor/respect/validation/tests/integration/rules/callableType_4.phpt
+++ b/vendor/respect/validation/tests/integration/rules/callableType_4.phpt
@@ -1,9 +1,3 @@
---SKIPIF--
-<?php
-  if (defined('HHVM_VERSION')) {
-      die('skip: Not working on hhvm because of dynamic callable id');
-  }
-?>
 --FILE--
 <?php
 require 'vendor/autoload.php';
@@ -34,4 +28,4 @@ try {
 --EXPECTF--
 `[object] (Closure: { })` must not be a callable
 "trim" must not be a callable
-`[object] (Respect\Validation\Validator: { })` must not be a callable
\ No newline at end of file
+`[object] (Respect\Validation\Validator: { })` must not be a callable
diff --git a/vendor/respect/validation/tests/library/Rules/RuleTestCase.php b/vendor/respect/validation/tests/library/Rules/RuleTestCase.php
index ddb8b8693bc517abcb576b57d42e24f9cba8fa6b..4eb40187028f9a1733ec19e9cdc2a8d6b8d7c8dc 100644
--- a/vendor/respect/validation/tests/library/Rules/RuleTestCase.php
+++ b/vendor/respect/validation/tests/library/Rules/RuleTestCase.php
@@ -12,9 +12,10 @@
 namespace Respect\Validation\Rules;
 
 use Respect\Validation\Exceptions\ValidationException;
+use Respect\Validation\TestCase;
 use Respect\Validation\Validatable;
 
-abstract class RuleTestCase extends \PHPUnit_Framework_TestCase
+abstract class RuleTestCase extends TestCase
 {
     /**
      * It is to provide constructor arguments and.
diff --git a/vendor/respect/validation/tests/library/TestCase.php b/vendor/respect/validation/tests/library/TestCase.php
new file mode 100644
index 0000000000000000000000000000000000000000..cb49a15e9122a38dbe527922d02b764a7848627d
--- /dev/null
+++ b/vendor/respect/validation/tests/library/TestCase.php
@@ -0,0 +1,38 @@
+<?php
+
+/*
+ * This file is part of Respect/Validation.
+ *
+ * (c) Alexandre Gomes Gaigalas <alexandre@gaigalas.net>
+ *
+ * For the full copyright and license information, please view the "LICENSE.md"
+ * file that was distributed with this source code.
+ */
+
+namespace Respect\Validation;
+
+use PHPUnit_Framework_MockObject_MockObject;
+use PHPUnit_Framework_TestCase;
+
+abstract class TestCase extends PHPUnit_Framework_TestCase
+{
+    /**
+     * Returns a test double for the specified class.
+     *
+     * This method is created to keep compatibility with PHPUnit ~4.0.
+     *
+     * @param string $originalClassName
+     *
+     * @return PHPUnit_Framework_MockObject_MockObject
+     */
+    protected function createMock($originalClassName)
+    {
+        if (!class_exists('PHPUnit_Framework_Constraint_IsFinite')) {
+            return $this->getMockBuilder($originalClassName)
+                ->disableOriginalConstructor()
+                ->getMock();
+        }
+
+        return parent::createMock($originalClassName);
+    }
+}
diff --git a/vendor/respect/validation/tests/unit/Exceptions/CheckExceptionsTest.php b/vendor/respect/validation/tests/unit/Exceptions/CheckExceptionsTest.php
index 1169c34384ebeee26fa24ad58a605165b7bf81df..b6e69ef0dc0e06c248250344fd9e62cf358189d0 100644
--- a/vendor/respect/validation/tests/unit/Exceptions/CheckExceptionsTest.php
+++ b/vendor/respect/validation/tests/unit/Exceptions/CheckExceptionsTest.php
@@ -13,8 +13,9 @@ namespace Respect\Validation\Exceptions;
 
 use DirectoryIterator;
 use ReflectionClass;
+use Respect\Validation\TestCase;
 
-class CheckExceptionsTest extends \PHPUnit_Framework_TestCase
+class CheckExceptionsTest extends TestCase
 {
     protected $deprecateds = ['Iterable'];
 
diff --git a/vendor/respect/validation/tests/unit/Exceptions/NestedValidationExceptionTest.php b/vendor/respect/validation/tests/unit/Exceptions/NestedValidationExceptionTest.php
index 0109d1ec87484424629dc175d323184934df20b0..4e88fd9cdc04858513b1f85fa7b0773164bf7f7a 100644
--- a/vendor/respect/validation/tests/unit/Exceptions/NestedValidationExceptionTest.php
+++ b/vendor/respect/validation/tests/unit/Exceptions/NestedValidationExceptionTest.php
@@ -11,15 +11,9 @@
 
 namespace Respect\Validation\Exceptions;
 
-/**
- * phpunit has an issue with mocking exceptions when in HHVM:
- * https://github.com/sebastianbergmann/phpunit-mock-objects/issues/207.
- */
-class PrivateNestedValidationException extends NestedValidationException
-{
-}
+use Respect\Validation\TestCase;
 
-class NestedValidationExceptionTest extends \PHPUnit_Framework_TestCase
+class NestedValidationExceptionTest extends TestCase
 {
     public function testGetRelatedShouldReturnExceptionAddedByAddRelated()
     {
diff --git a/vendor/respect/validation/tests/unit/Exceptions/ValidationExceptionTest.php b/vendor/respect/validation/tests/unit/Exceptions/ValidationExceptionTest.php
index 7854e22814a27adbc44a9cb7e9439514ba74769f..6f23090393daa1465769321865ce945f8d65d0bf 100644
--- a/vendor/respect/validation/tests/unit/Exceptions/ValidationExceptionTest.php
+++ b/vendor/respect/validation/tests/unit/Exceptions/ValidationExceptionTest.php
@@ -14,10 +14,11 @@ namespace Respect\Validation\Exceptions;
 use ArrayIterator;
 use DateTime;
 use Exception;
+use Respect\Validation\TestCase;
 use SplFileInfo;
 use stdClass;
 
-class ValidationExceptionTest extends \PHPUnit_Framework_TestCase
+class ValidationExceptionTest extends TestCase
 {
     public function testItImplementsExceptionInterface()
     {
diff --git a/vendor/respect/validation/tests/unit/FactoryTest.php b/vendor/respect/validation/tests/unit/FactoryTest.php
index c29a873b05be7008b39e3b225d7e4cf64e263d84..117e9627bef4ff77df8e03f88491bcd4af36810e 100644
--- a/vendor/respect/validation/tests/unit/FactoryTest.php
+++ b/vendor/respect/validation/tests/unit/FactoryTest.php
@@ -14,7 +14,7 @@ namespace Respect\Validation;
 /**
  * @covers Respect\Validation\Factory
  */
-class FactoryTest extends \PHPUnit_Framework_TestCase
+class FactoryTest extends TestCase
 {
     public function testShouldHaveRulePrefixesByDefault()
     {
diff --git a/vendor/respect/validation/tests/unit/Rules/AbstractCompositeTest.php b/vendor/respect/validation/tests/unit/Rules/AbstractCompositeTest.php
index 2943a6f82262fe703a7320d4a0e5724d510860c5..7d1c7a6261dca07e43d5cb09f99c27aabae21c34 100644
--- a/vendor/respect/validation/tests/unit/Rules/AbstractCompositeTest.php
+++ b/vendor/respect/validation/tests/unit/Rules/AbstractCompositeTest.php
@@ -11,13 +11,15 @@
 
 namespace Respect\Validation\Rules;
 
-class AbstractCompositeTest extends \PHPUnit_Framework_TestCase
+use Respect\Validation\TestCase;
+
+class AbstractCompositeTest extends TestCase
 {
     public function testShouldDefineNameForInternalWhenAppendRuleToCompositeRule()
     {
         $ruleName = 'something';
 
-        $simpleRuleMock = $this->getMock('Respect\\Validation\\Validatable');
+        $simpleRuleMock = $this->createMock('Respect\\Validation\\Validatable');
         $simpleRuleMock
             ->expects($this->once())
             ->method('getName')
@@ -40,7 +42,7 @@ class AbstractCompositeTest extends \PHPUnit_Framework_TestCase
         $ruleName1 = 'something';
         $ruleName2 = 'something else';
 
-        $simpleRuleMock = $this->getMock('Respect\\Validation\\Validatable');
+        $simpleRuleMock = $this->createMock('Respect\\Validation\\Validatable');
         $simpleRuleMock
             ->expects($this->at(0))
             ->method('getName')
@@ -69,7 +71,7 @@ class AbstractCompositeTest extends \PHPUnit_Framework_TestCase
 
     public function testShouldNotUpdateInternalRuleAlreadyHasAName()
     {
-        $simpleRuleMock = $this->getMock('Respect\\Validation\\Validatable');
+        $simpleRuleMock = $this->createMock('Respect\\Validation\\Validatable');
         $simpleRuleMock
             ->expects($this->any())
             ->method('getName')
@@ -90,7 +92,7 @@ class AbstractCompositeTest extends \PHPUnit_Framework_TestCase
     {
         $ruleName = 'something';
 
-        $simpleRuleMock = $this->getMock('Respect\\Validation\\Validatable');
+        $simpleRuleMock = $this->createMock('Respect\\Validation\\Validatable');
         $simpleRuleMock
             ->expects($this->any())
             ->method('getName')
@@ -112,7 +114,7 @@ class AbstractCompositeTest extends \PHPUnit_Framework_TestCase
     {
         $ruleName = 'something';
 
-        $simpleRuleMock = $this->getMock('Respect\\Validation\\Validatable');
+        $simpleRuleMock = $this->createMock('Respect\\Validation\\Validatable');
         $simpleRuleMock
             ->expects($this->any())
             ->method('getName')
@@ -134,7 +136,7 @@ class AbstractCompositeTest extends \PHPUnit_Framework_TestCase
     {
         $ruleName = 'something';
 
-        $simpleRuleMock = $this->getMock('Respect\\Validation\\Validatable');
+        $simpleRuleMock = $this->createMock('Respect\\Validation\\Validatable');
         $simpleRuleMock
             ->expects($this->any())
             ->method('getName')
@@ -153,7 +155,7 @@ class AbstractCompositeTest extends \PHPUnit_Framework_TestCase
 
     public function testRemoveRulesShouldRemoveAllTheAddedRules()
     {
-        $simpleRuleMock = $this->getMock('Respect\\Validation\\Validatable');
+        $simpleRuleMock = $this->createMock('Respect\\Validation\\Validatable');
 
         $compositeRuleMock = $this->getMockForAbstractClass('Respect\\Validation\\Rules\\AbstractComposite');
         $compositeRuleMock->addRule($simpleRuleMock);
@@ -165,9 +167,9 @@ class AbstractCompositeTest extends \PHPUnit_Framework_TestCase
     public function testShouldReturnTheAmountOfAddedRules()
     {
         $compositeRuleMock = $this->getMockForAbstractClass('Respect\\Validation\\Rules\\AbstractComposite');
-        $compositeRuleMock->addRule($this->getMock('Respect\\Validation\\Validatable'));
-        $compositeRuleMock->addRule($this->getMock('Respect\\Validation\\Validatable'));
-        $compositeRuleMock->addRule($this->getMock('Respect\\Validation\\Validatable'));
+        $compositeRuleMock->addRule($this->createMock('Respect\\Validation\\Validatable'));
+        $compositeRuleMock->addRule($this->createMock('Respect\\Validation\\Validatable'));
+        $compositeRuleMock->addRule($this->createMock('Respect\\Validation\\Validatable'));
 
         $this->assertCount(3, $compositeRuleMock->getRules());
     }
@@ -181,19 +183,19 @@ class AbstractCompositeTest extends \PHPUnit_Framework_TestCase
 
     public function testHasRuleShouldReturnFalseWhenRuleIsNotFound()
     {
-        $oneSimpleRuleMock = $this->getMock('Respect\\Validation\\Validatable');
+        $oneSimpleRuleMock = $this->createMock('Respect\\Validation\\Validatable');
 
         $compositeRuleMock = $this->getMockForAbstractClass('Respect\\Validation\\Rules\\AbstractComposite');
         $compositeRuleMock->addRule($oneSimpleRuleMock);
 
-        $anotherSimpleRuleMock = $this->getMock('Respect\\Validation\\Validatable');
+        $anotherSimpleRuleMock = $this->createMock('Respect\\Validation\\Validatable');
 
         $this->assertFalse($compositeRuleMock->hasRule($anotherSimpleRuleMock));
     }
 
     public function testHasRuleShouldReturnFalseWhenRulePassedAsStringIsNotFound()
     {
-        $simpleRuleMock = $this->getMock('Respect\\Validation\\Validatable');
+        $simpleRuleMock = $this->createMock('Respect\\Validation\\Validatable');
 
         $compositeRuleMock = $this->getMockForAbstractClass('Respect\\Validation\\Rules\\AbstractComposite');
         $compositeRuleMock->addRule($simpleRuleMock);
@@ -203,7 +205,7 @@ class AbstractCompositeTest extends \PHPUnit_Framework_TestCase
 
     public function testHasRuleShouldReturnTrueWhenRuleIsFound()
     {
-        $simpleRuleMock = $this->getMock('Respect\\Validation\\Validatable');
+        $simpleRuleMock = $this->createMock('Respect\\Validation\\Validatable');
 
         $compositeRuleMock = $this->getMockForAbstractClass('Respect\\Validation\\Rules\\AbstractComposite');
         $compositeRuleMock->addRule($simpleRuleMock);
@@ -213,8 +215,8 @@ class AbstractCompositeTest extends \PHPUnit_Framework_TestCase
 
     public function testShouldAddRulesByPassingThroughConstructor()
     {
-        $simpleRuleMock = $this->getMock('Respect\\Validation\\Validatable');
-        $anotherSimpleRuleMock = $this->getMock('Respect\\Validation\\Validatable');
+        $simpleRuleMock = $this->createMock('Respect\\Validation\\Validatable');
+        $anotherSimpleRuleMock = $this->createMock('Respect\\Validation\\Validatable');
 
         $compositeRuleMock = $this->getMockForAbstractClass('Respect\\Validation\\Rules\\AbstractComposite', [
             $simpleRuleMock,
diff --git a/vendor/respect/validation/tests/unit/Rules/AbstractCtypeRuleTest.php b/vendor/respect/validation/tests/unit/Rules/AbstractCtypeRuleTest.php
index 47ff31fd3a0481a5a6f0a7dcc0821c0e615fd95c..2658095a9455f49bcd46b0e1cc60ec976aded409 100644
--- a/vendor/respect/validation/tests/unit/Rules/AbstractCtypeRuleTest.php
+++ b/vendor/respect/validation/tests/unit/Rules/AbstractCtypeRuleTest.php
@@ -11,7 +11,9 @@
 
 namespace Respect\Validation\Rules;
 
-class AbstractCtypeRuleTest extends \PHPUnit_Framework_TestCase
+use Respect\Validation\TestCase;
+
+class AbstractCtypeRuleTest extends TestCase
 {
     public function testValidateCleanShouldReturnTrueWhenCtypeFunctionReturnsTrue()
     {
diff --git a/vendor/respect/validation/tests/unit/Rules/AbstractFilterRuleTest.php b/vendor/respect/validation/tests/unit/Rules/AbstractFilterRuleTest.php
index bb90bfbd559f5d5c7ee2084c73bd4d1b87bd3efa..1bc2f71caeef52decee4b802779d0b4f8c2ae882 100644
--- a/vendor/respect/validation/tests/unit/Rules/AbstractFilterRuleTest.php
+++ b/vendor/respect/validation/tests/unit/Rules/AbstractFilterRuleTest.php
@@ -11,7 +11,9 @@
 
 namespace Respect\Validation\Rules;
 
-class AbstractFilterRuleTest extends \PHPUnit_Framework_TestCase
+use Respect\Validation\TestCase;
+
+class AbstractFilterRuleTest extends TestCase
 {
     /**
      * @expectedException Respect\Validation\Exceptions\ComponentException
diff --git a/vendor/respect/validation/tests/unit/Rules/AbstractRegexRuleTest.php b/vendor/respect/validation/tests/unit/Rules/AbstractRegexRuleTest.php
index 90a2fe86d79acbe17045863b14ceee1426cede99..aa20793e1c4e9c5e3f9a5c93a0de5044bfa5bbfc 100644
--- a/vendor/respect/validation/tests/unit/Rules/AbstractRegexRuleTest.php
+++ b/vendor/respect/validation/tests/unit/Rules/AbstractRegexRuleTest.php
@@ -11,7 +11,9 @@
 
 namespace Respect\Validation\Rules;
 
-class AbstractRegexRuleTest extends \PHPUnit_Framework_TestCase
+use Respect\Validation\TestCase;
+
+class AbstractRegexRuleTest extends TestCase
 {
     public function testValidateCleanShouldReturnOneIfPatternIsFound()
     {
diff --git a/vendor/respect/validation/tests/unit/Rules/AbstractRelatedTest.php b/vendor/respect/validation/tests/unit/Rules/AbstractRelatedTest.php
index 43012f0b790cd03f000431964b538ab2d7769991..1c4b06713d6c428e0e34137104b1ce9b9ccf1de5 100644
--- a/vendor/respect/validation/tests/unit/Rules/AbstractRelatedTest.php
+++ b/vendor/respect/validation/tests/unit/Rules/AbstractRelatedTest.php
@@ -11,7 +11,9 @@
 
 namespace Respect\Validation\Rules;
 
-final class AbstractRelatedTest extends \PHPUnit_Framework_TestCase
+use Respect\Validation\TestCase;
+
+final class AbstractRelatedTest extends TestCase
 {
     const NAME = 'Respect\\Validation\\Rules\\AbstractRelated';
 
@@ -26,7 +28,7 @@ final class AbstractRelatedTest extends \PHPUnit_Framework_TestCase
 
     public function testConstructionOfAbstractRelatedClass()
     {
-        $validatableMock = $this->getMock('Respect\\Validation\\Validatable');
+        $validatableMock = $this->createMock('Respect\\Validation\\Validatable');
         $relatedRuleMock = $this->getMockForAbstractClass('Respect\\Validation\\Rules\\AbstractRelated', ['foo', $validatableMock]);
 
         $this->assertEquals('foo', $relatedRuleMock->getName());
@@ -40,7 +42,7 @@ final class AbstractRelatedTest extends \PHPUnit_Framework_TestCase
      */
     public function testOperationsShouldReturnTrueWhenReferenceValidatesItsValue($method)
     {
-        $validatableMock = $this->getMock('Respect\\Validation\\Validatable');
+        $validatableMock = $this->createMock('Respect\\Validation\\Validatable');
         $validatableMock->expects($this->any())
             ->method($method)
             ->will($this->returnValue(true));
@@ -87,7 +89,7 @@ final class AbstractRelatedTest extends \PHPUnit_Framework_TestCase
 
     public function testShouldAcceptReferenceAndRuleOnConstructor()
     {
-        $ruleMock = $this->getMock('Respect\\Validation\\Validatable');
+        $ruleMock = $this->createMock('Respect\\Validation\\Validatable');
 
         $abstractMock = $this
             ->getMockBuilder(self::NAME)
@@ -101,7 +103,7 @@ final class AbstractRelatedTest extends \PHPUnit_Framework_TestCase
     {
         $reference = 'something';
 
-        $ruleMock = $this->getMock('Respect\\Validation\\Validatable');
+        $ruleMock = $this->createMock('Respect\\Validation\\Validatable');
         $ruleMock
             ->expects($this->at(0))
             ->method('getName')
@@ -123,7 +125,7 @@ final class AbstractRelatedTest extends \PHPUnit_Framework_TestCase
     {
         $reference = 'something';
 
-        $ruleMock = $this->getMock('Respect\\Validation\\Validatable');
+        $ruleMock = $this->createMock('Respect\\Validation\\Validatable');
         $ruleMock
             ->expects($this->at(0))
             ->method('getName')
@@ -146,7 +148,7 @@ final class AbstractRelatedTest extends \PHPUnit_Framework_TestCase
 
         $abstractMock = $this
             ->getMockBuilder(self::NAME)
-            ->setConstructorArgs(['something', $this->getMock('Respect\\Validation\\Validatable'), $mandatory])
+            ->setConstructorArgs(['something', $this->createMock('Respect\\Validation\\Validatable'), $mandatory])
             ->getMock();
 
         $this->assertSame($mandatory, $abstractMock->mandatory);
@@ -157,7 +159,7 @@ final class AbstractRelatedTest extends \PHPUnit_Framework_TestCase
         $name = 'My new name';
         $reference = 'something';
 
-        $ruleMock = $this->getMock('Respect\\Validation\\Validatable');
+        $ruleMock = $this->createMock('Respect\\Validation\\Validatable');
         $ruleMock
             ->expects($this->at(0))
             ->method('getName')
diff --git a/vendor/respect/validation/tests/unit/Rules/AbstractRuleTest.php b/vendor/respect/validation/tests/unit/Rules/AbstractRuleTest.php
index f10c7b95bce41022b0c7cfcf1782c155c968823e..3b56e322a1847f161fc497d4d3715ed9fb0f9acc 100644
--- a/vendor/respect/validation/tests/unit/Rules/AbstractRuleTest.php
+++ b/vendor/respect/validation/tests/unit/Rules/AbstractRuleTest.php
@@ -12,8 +12,9 @@
 namespace Respect\Validation\Rules;
 
 use Respect\Validation\Exceptions\ValidationException;
+use Respect\Validation\TestCase;
 
-class AbstractRuleTest extends \PHPUnit_Framework_TestCase
+class AbstractRuleTest extends TestCase
 {
     public function providerForTrueAndFalse()
     {
@@ -68,10 +69,6 @@ class AbstractRuleTest extends \PHPUnit_Framework_TestCase
             ->with($input)
             ->will($this->returnValue(true));
 
-        $abstractRuleMock
-            ->expects($this->never())
-            ->method('reportError');
-
         $abstractRuleMock->assert($input);
     }
 
@@ -129,10 +126,6 @@ class AbstractRuleTest extends \PHPUnit_Framework_TestCase
      */
     public function testShouldCreateExceptionBasedOnTheCurrentClassName()
     {
-        if (defined('HHVM_VERSION')) {
-            return $this->markTestSkipped('If you are a HHVM user, and you are in the mood, please fix it');
-        }
-
         $exceptionMock = $this
             ->getMockBuilder('Respect\Validation\Exceptions\ValidationException')
             ->setMockClassName('MockRule1Exception')
diff --git a/vendor/respect/validation/tests/unit/Rules/AbstractSearcherTest.php b/vendor/respect/validation/tests/unit/Rules/AbstractSearcherTest.php
index cc2149d5fec79331fa37c1d1a7f662a765606fda..7ee90bb02eefd0c6d9e182ecb81bf1d812df116a 100644
--- a/vendor/respect/validation/tests/unit/Rules/AbstractSearcherTest.php
+++ b/vendor/respect/validation/tests/unit/Rules/AbstractSearcherTest.php
@@ -11,7 +11,9 @@
 
 namespace Respect\Validation\Rules;
 
-class AbstractSearcherTest extends \PHPUnit_Framework_TestCase
+use Respect\Validation\TestCase;
+
+class AbstractSearcherTest extends TestCase
 {
     protected $searcherRuleMock;
 
diff --git a/vendor/respect/validation/tests/unit/Rules/AbstractWrapperTest.php b/vendor/respect/validation/tests/unit/Rules/AbstractWrapperTest.php
index 2565824911cca319a1087c65e76899306a384fc1..ccc18acf3293866253281e903e091dfca1590664 100644
--- a/vendor/respect/validation/tests/unit/Rules/AbstractWrapperTest.php
+++ b/vendor/respect/validation/tests/unit/Rules/AbstractWrapperTest.php
@@ -12,8 +12,9 @@
 namespace Respect\Validation\Rules;
 
 use ReflectionObject;
+use Respect\Validation\TestCase;
 
-class AbstractWrapperTest extends \PHPUnit_Framework_TestCase
+class AbstractWrapperTest extends TestCase
 {
     /**
      * @expectedException Respect\Validation\Exceptions\ComponentException
@@ -35,7 +36,7 @@ class AbstractWrapperTest extends \PHPUnit_Framework_TestCase
 
     public function testShouldReturnDefinedValidatable()
     {
-        $validatable = $this->getMock('Respect\Validation\Validatable');
+        $validatable = $this->createMock('Respect\Validation\Validatable');
 
         $wrapper = $this->getMockForAbstractClass('Respect\Validation\Rules\AbstractWrapper');
         $this->bindValidatable($wrapper, $validatable);
@@ -47,7 +48,7 @@ class AbstractWrapperTest extends \PHPUnit_Framework_TestCase
     {
         $input = 'Whatever';
 
-        $validatable = $this->getMock('Respect\Validation\Validatable');
+        $validatable = $this->createMock('Respect\Validation\Validatable');
         $validatable
             ->expects($this->once())
             ->method('validate')
@@ -64,7 +65,7 @@ class AbstractWrapperTest extends \PHPUnit_Framework_TestCase
     {
         $input = 'Whatever';
 
-        $validatable = $this->getMock('Respect\Validation\Validatable');
+        $validatable = $this->createMock('Respect\Validation\Validatable');
         $validatable
             ->expects($this->once())
             ->method('assert')
@@ -81,7 +82,7 @@ class AbstractWrapperTest extends \PHPUnit_Framework_TestCase
     {
         $input = 'Whatever';
 
-        $validatable = $this->getMock('Respect\Validation\Validatable');
+        $validatable = $this->createMock('Respect\Validation\Validatable');
         $validatable
             ->expects($this->once())
             ->method('check')
@@ -98,7 +99,7 @@ class AbstractWrapperTest extends \PHPUnit_Framework_TestCase
     {
         $name = 'Whatever';
 
-        $validatable = $this->getMock('Respect\Validation\Validatable');
+        $validatable = $this->createMock('Respect\Validation\Validatable');
         $validatable
             ->expects($this->once())
             ->method('setName')
diff --git a/vendor/respect/validation/tests/unit/Rules/AgeTest.php b/vendor/respect/validation/tests/unit/Rules/AgeTest.php
index 0c22d503511398af9f629baf05a8801d7819d483..32d5f824c67c5c8a3b308ee7e3c1b95716861c7e 100644
--- a/vendor/respect/validation/tests/unit/Rules/AgeTest.php
+++ b/vendor/respect/validation/tests/unit/Rules/AgeTest.php
@@ -12,13 +12,14 @@
 namespace Respect\Validation\Rules;
 
 use DateTime;
+use Respect\Validation\TestCase;
 
 /**
  * @group  rule
  * @covers Respect\Validation\Rules\Age
  * @covers Respect\Validation\Exceptions\AgeException
  */
-class AgeTest extends \PHPUnit_Framework_TestCase
+class AgeTest extends TestCase
 {
     /**
      * @expectedException Respect\Validation\Exceptions\ComponentException
diff --git a/vendor/respect/validation/tests/unit/Rules/AllOfTest.php b/vendor/respect/validation/tests/unit/Rules/AllOfTest.php
index 977d93470aae2e3caf3a2908d2c7ea6dc2d10e89..a1e1d84bebe295d70f049b36891c3f61ef06c71a 100644
--- a/vendor/respect/validation/tests/unit/Rules/AllOfTest.php
+++ b/vendor/respect/validation/tests/unit/Rules/AllOfTest.php
@@ -11,12 +11,14 @@
 
 namespace Respect\Validation\Rules;
 
+use Respect\Validation\TestCase;
+
 /**
  * @group  rule
  * @covers Respect\Validation\Rules\AllOf
  * @covers Respect\Validation\Exceptions\AllOfException
  */
-class AllOfTest extends \PHPUnit_Framework_TestCase
+class AllOfTest extends TestCase
 {
     public function testRemoveRulesShouldRemoveAllRules()
     {
@@ -47,14 +49,14 @@ class AllOfTest extends \PHPUnit_Framework_TestCase
     public function testValidationShouldWorkIfAllRulesReturnTrue()
     {
         $valid1 = new Callback(function () {
-                    return true;
-                });
+            return true;
+        });
         $valid2 = new Callback(function () {
-                    return true;
-                });
+            return true;
+        });
         $valid3 = new Callback(function () {
-                    return true;
-                });
+            return true;
+        });
         $o = new AllOf($valid1, $valid2, $valid3);
         $this->assertTrue($o->__invoke('any'));
         $this->assertTrue($o->check('any'));
@@ -108,14 +110,14 @@ class AllOfTest extends \PHPUnit_Framework_TestCase
     public function providerStaticDummyRules()
     {
         $theInvalidOne = new Callback(function () {
-                    return false;
-                });
+            return false;
+        });
         $valid1 = new Callback(function () {
-                    return true;
-                });
+            return true;
+        });
         $valid2 = new Callback(function () {
-                    return true;
-                });
+            return true;
+        });
 
         return [
             [$theInvalidOne, $valid1, $valid2],
diff --git a/vendor/respect/validation/tests/unit/Rules/AlnumTest.php b/vendor/respect/validation/tests/unit/Rules/AlnumTest.php
index f9983209a9901cb5e92f589508093bcb4bd52cb0..bcce1615ec5c721144e3532b482d5aa033a91374 100644
--- a/vendor/respect/validation/tests/unit/Rules/AlnumTest.php
+++ b/vendor/respect/validation/tests/unit/Rules/AlnumTest.php
@@ -11,12 +11,14 @@
 
 namespace Respect\Validation\Rules;
 
+use Respect\Validation\TestCase;
+
 /**
  * @group  rule
  * @covers Respect\Validation\Rules\Alnum
  * @covers Respect\Validation\Exceptions\AlnumException
  */
-class AlnumTest extends \PHPUnit_Framework_TestCase
+class AlnumTest extends TestCase
 {
     /**
      * @dataProvider providerForValidAlnum
diff --git a/vendor/respect/validation/tests/unit/Rules/AlphaTest.php b/vendor/respect/validation/tests/unit/Rules/AlphaTest.php
index 73033764457aea9ef56e711cd2adbc4589f4f77c..6713eb69f20212c463368dc7fa4190321c3280ce 100644
--- a/vendor/respect/validation/tests/unit/Rules/AlphaTest.php
+++ b/vendor/respect/validation/tests/unit/Rules/AlphaTest.php
@@ -11,12 +11,14 @@
 
 namespace Respect\Validation\Rules;
 
+use Respect\Validation\TestCase;
+
 /**
  * @group  rule
  * @covers Respect\Validation\Rules\Alpha
  * @covers Respect\Validation\Exceptions\AlphaException
  */
-class AlphaTest extends \PHPUnit_Framework_TestCase
+class AlphaTest extends TestCase
 {
     /**
      * @dataProvider providerForValidAlpha
diff --git a/vendor/respect/validation/tests/unit/Rules/AlwaysInvalidTest.php b/vendor/respect/validation/tests/unit/Rules/AlwaysInvalidTest.php
index 49c3fc82dcc54b9a4b00af75dafb46e6f9ae406e..032e18994e7afa1f59fbda7dd372075615971860 100644
--- a/vendor/respect/validation/tests/unit/Rules/AlwaysInvalidTest.php
+++ b/vendor/respect/validation/tests/unit/Rules/AlwaysInvalidTest.php
@@ -11,11 +11,13 @@
 
 namespace Respect\Validation\Rules;
 
+use Respect\Validation\TestCase;
+
 /**
  * @group  rule
  * @covers Respect\Validation\Rules\AlwaysInvalid
  */
-class AlwaysInvalidTest extends \PHPUnit_Framework_TestCase
+class AlwaysInvalidTest extends TestCase
 {
     public function providerForValidAlwaysInvalid()
     {
diff --git a/vendor/respect/validation/tests/unit/Rules/AlwaysValidTest.php b/vendor/respect/validation/tests/unit/Rules/AlwaysValidTest.php
index 7274de58002f49bd70fb5aa6f8dea755a335e7d6..03b78c34b6d654cd8048ce33b4eb388eab2450ac 100644
--- a/vendor/respect/validation/tests/unit/Rules/AlwaysValidTest.php
+++ b/vendor/respect/validation/tests/unit/Rules/AlwaysValidTest.php
@@ -11,11 +11,13 @@
 
 namespace Respect\Validation\Rules;
 
+use Respect\Validation\TestCase;
+
 /**
  * @group  rule
  * @covers Respect\Validation\Rules\AlwaysValid
  */
-class AlwaysValidTest extends \PHPUnit_Framework_TestCase
+class AlwaysValidTest extends TestCase
 {
     public function providerForValidAlwaysValid()
     {
diff --git a/vendor/respect/validation/tests/unit/Rules/AttributeTest.php b/vendor/respect/validation/tests/unit/Rules/AttributeTest.php
index 65cb25d30bc90539b63ffc80601ad1c7f1619aba..8c226e5b6aee0e7d8b3334bafde3acdf42496cb9 100644
--- a/vendor/respect/validation/tests/unit/Rules/AttributeTest.php
+++ b/vendor/respect/validation/tests/unit/Rules/AttributeTest.php
@@ -11,6 +11,8 @@
 
 namespace Respect\Validation\Rules;
 
+use Respect\Validation\TestCase;
+
 class PrivClass
 {
     private $bar = 'foo';
@@ -21,7 +23,7 @@ class PrivClass
  * @covers Respect\Validation\Rules\Attribute
  * @covers Respect\Validation\Exceptions\AttributeException
  */
-class AttributeTest extends \PHPUnit_Framework_TestCase
+class AttributeTest extends TestCase
 {
     public function testAttributeWithNoExtraValidationShouldCheckItsPresence()
     {
diff --git a/vendor/respect/validation/tests/unit/Rules/BaseTest.php b/vendor/respect/validation/tests/unit/Rules/BaseTest.php
index 7e372380e110c57e0a08eefc127339485587c084..bb835a00be6cb23f8151d68893c0e97d23ed29eb 100644
--- a/vendor/respect/validation/tests/unit/Rules/BaseTest.php
+++ b/vendor/respect/validation/tests/unit/Rules/BaseTest.php
@@ -11,12 +11,14 @@
 
 namespace Respect\Validation\Rules;
 
+use Respect\Validation\TestCase;
+
 /**
  * @group  rule
  * @covers Respect\Validation\Rules\Base
  * @covers Respect\Validation\Exceptions\BaseException
  */
-class BaseTest extends \PHPUnit_Framework_TestCase
+class BaseTest extends TestCase
 {
     protected $object;
 
diff --git a/vendor/respect/validation/tests/unit/Rules/BetweenTest.php b/vendor/respect/validation/tests/unit/Rules/BetweenTest.php
index 97c05f699f24d5db1c10fec4fa92d9f7930bd4d6..37927842d7fc1b9b43de1f26ddcb46c2b23b6a30 100644
--- a/vendor/respect/validation/tests/unit/Rules/BetweenTest.php
+++ b/vendor/respect/validation/tests/unit/Rules/BetweenTest.php
@@ -11,6 +11,7 @@
 
 namespace Respect\Validation\Rules;
 
+use Respect\Validation\TestCase;
 use DateTime;
 
 /**
@@ -18,7 +19,7 @@ use DateTime;
  * @covers Respect\Validation\Rules\Between
  * @covers Respect\Validation\Exceptions\BetweenException
  */
-class BetweenTest extends \PHPUnit_Framework_TestCase
+class BetweenTest extends TestCase
 {
     public function providerValid()
     {
diff --git a/vendor/respect/validation/tests/unit/Rules/BoolTypeTest.php b/vendor/respect/validation/tests/unit/Rules/BoolTypeTest.php
index d626ff2aa836b4759a0fa9de77efa7c2aae14074..5a645b334d1e134f589178734d59fd2d269d998b 100644
--- a/vendor/respect/validation/tests/unit/Rules/BoolTypeTest.php
+++ b/vendor/respect/validation/tests/unit/Rules/BoolTypeTest.php
@@ -11,12 +11,14 @@
 
 namespace Respect\Validation\Rules;
 
+use Respect\Validation\TestCase;
+
 /**
  * @group  rule
  * @covers Respect\Validation\Rules\BoolType
  * @covers Respect\Validation\Exceptions\BoolTypeException
  */
-class BoolTypeTest extends \PHPUnit_Framework_TestCase
+class BoolTypeTest extends TestCase
 {
     public function testBooleanValuesONLYShouldReturnTrue()
     {
diff --git a/vendor/respect/validation/tests/unit/Rules/BsnTest.php b/vendor/respect/validation/tests/unit/Rules/BsnTest.php
index 673c4a91e02346253254a280127024e559b9bc4e..4c0a8ca1248b177f0964d46f3a781280f705ed2c 100644
--- a/vendor/respect/validation/tests/unit/Rules/BsnTest.php
+++ b/vendor/respect/validation/tests/unit/Rules/BsnTest.php
@@ -11,14 +11,14 @@
 
 namespace Respect\Validation\Rules;
 
-use PHPUnit_Framework_TestCase;
+use Respect\Validation\TestCase;
 
 /**
  * @group  rule
  * @covers Respect\Validation\Rules\Bsn
  * @covers Respect\Validation\Exceptions\BsnException
  */
-class BsnTest extends PHPUnit_Framework_TestCase
+class BsnTest extends TestCase
 {
     /**
      * @var Bsn
diff --git a/vendor/respect/validation/tests/unit/Rules/CallTest.php b/vendor/respect/validation/tests/unit/Rules/CallTest.php
index a3603181046760588766a59549ded3582dd28d64..720e60d91729e8e8c9ab59b5d2499bb9e383c1d0 100644
--- a/vendor/respect/validation/tests/unit/Rules/CallTest.php
+++ b/vendor/respect/validation/tests/unit/Rules/CallTest.php
@@ -11,12 +11,14 @@
 
 namespace Respect\Validation\Rules;
 
+use Respect\Validation\TestCase;
+
 /**
  * @group  rule
  * @covers Respect\Validation\Rules\Call
  * @covers Respect\Validation\Exceptions\CallException
  */
-class CallTest extends \PHPUnit_Framework_TestCase
+class CallTest extends TestCase
 {
     public function thisIsASampleCallbackUsedInsideThisTest()
     {
@@ -44,8 +46,8 @@ class CallTest extends \PHPUnit_Framework_TestCase
     public function testCallbackValidatorShouldAcceptClosures()
     {
         $v = new Call(function () {
-                    return [];
-                }, new ArrayVal());
+            return [];
+        }, new ArrayVal());
         $this->assertTrue($v->assert('test'));
     }
 
diff --git a/vendor/respect/validation/tests/unit/Rules/CallableTypeTest.php b/vendor/respect/validation/tests/unit/Rules/CallableTypeTest.php
index e41ffbe9ad7d05a250745d37334131fedfa23a5e..5599a255e7bf7f03a3411e259811524378eebf27 100644
--- a/vendor/respect/validation/tests/unit/Rules/CallableTypeTest.php
+++ b/vendor/respect/validation/tests/unit/Rules/CallableTypeTest.php
@@ -11,12 +11,14 @@
 
 namespace Respect\Validation\Rules;
 
+use Respect\Validation\TestCase;
+
 /**
  * @group  rule
  * @covers Respect\Validation\Rules\CallableType
  * @covers Respect\Validation\Exceptions\CallableTypeException
  */
-class CallableTypeTest extends \PHPUnit_Framework_TestCase
+class CallableTypeTest extends TestCase
 {
     protected $rule;
 
@@ -53,7 +55,8 @@ class CallableTypeTest extends \PHPUnit_Framework_TestCase
     public function providerForCallable()
     {
         return [
-            [function () {}],
+            [function () {
+            }],
             ['trim'],
             [__METHOD__],
             [[$this, __FUNCTION__]],
diff --git a/vendor/respect/validation/tests/unit/Rules/CallbackTest.php b/vendor/respect/validation/tests/unit/Rules/CallbackTest.php
index 2d61be76f6eafc23e3234adeaa69efbc5f039ce0..3975558973ed278247f92a10e8448d33eb5330e0 100644
--- a/vendor/respect/validation/tests/unit/Rules/CallbackTest.php
+++ b/vendor/respect/validation/tests/unit/Rules/CallbackTest.php
@@ -11,14 +11,17 @@
 
 namespace Respect\Validation\Rules;
 
+use Respect\Validation\TestCase;
+
 /**
  * @group  rule
  * @covers Respect\Validation\Rules\Callback
  * @covers Respect\Validation\Exceptions\CallbackException
  */
-class CallbackTest extends \PHPUnit_Framework_TestCase
+class CallbackTest extends TestCase
 {
-    private $truthy, $falsy;
+    private $truthy;
+    private $falsy;
 
     public function setUp()
     {
diff --git a/vendor/respect/validation/tests/unit/Rules/CharsetTest.php b/vendor/respect/validation/tests/unit/Rules/CharsetTest.php
index ddd94913f66b59454c9f6fa6ff2d6e815e530e0d..e73fe3c8da885807bde6563bc123b3d4067de523 100644
--- a/vendor/respect/validation/tests/unit/Rules/CharsetTest.php
+++ b/vendor/respect/validation/tests/unit/Rules/CharsetTest.php
@@ -11,12 +11,14 @@
 
 namespace Respect\Validation\Rules;
 
+use Respect\Validation\TestCase;
+
 /**
  * @group  rule
  * @covers Respect\Validation\Rules\Charset
  * @covers Respect\Validation\Exceptions\CharsetException
  */
-class CharsetTest extends \PHPUnit_Framework_TestCase
+class CharsetTest extends TestCase
 {
     /**
      * @dataProvider providerForValidCharset
diff --git a/vendor/respect/validation/tests/unit/Rules/CnhTest.php b/vendor/respect/validation/tests/unit/Rules/CnhTest.php
index 0dda57f4917f3e037640266431e6817cb7e6cd39..e66a9a9e7f1dc5cd34769b2bb145468446bfec8a 100644
--- a/vendor/respect/validation/tests/unit/Rules/CnhTest.php
+++ b/vendor/respect/validation/tests/unit/Rules/CnhTest.php
@@ -11,12 +11,14 @@
 
 namespace Respect\Validation\Rules;
 
+use Respect\Validation\TestCase;
+
 /**
  * @group  rule
  * @covers Respect\Validation\Rules\Cnh
  * @covers Respect\Validation\Exceptions\CnhException
  */
-class CnhTest extends \PHPUnit_Framework_TestCase
+class CnhTest extends TestCase
 {
     protected $cnhValidator;
 
diff --git a/vendor/respect/validation/tests/unit/Rules/CnpjTest.php b/vendor/respect/validation/tests/unit/Rules/CnpjTest.php
index b0de5b7e5c07048ebb6793234cec9d1ee9e7a315..1906faccbe6461b6676e4ffa9f1f9e51164f505c 100644
--- a/vendor/respect/validation/tests/unit/Rules/CnpjTest.php
+++ b/vendor/respect/validation/tests/unit/Rules/CnpjTest.php
@@ -11,12 +11,14 @@
 
 namespace Respect\Validation\Rules;
 
+use Respect\Validation\TestCase;
+
 /**
  * @group  rule
  * @covers Respect\Validation\Rules\Cnpj
  * @covers Respect\Validation\Exceptions\CnpjException
  */
-class CnpjTest extends \PHPUnit_Framework_TestCase
+class CnpjTest extends TestCase
 {
     protected $cnpjValidator;
 
diff --git a/vendor/respect/validation/tests/unit/Rules/CntrlTest.php b/vendor/respect/validation/tests/unit/Rules/CntrlTest.php
index 1a8fdd46b94a2d3f2bdd61fecf5c03358203b248..4f66567059fb4311ff48c60544b65398ab68599a 100644
--- a/vendor/respect/validation/tests/unit/Rules/CntrlTest.php
+++ b/vendor/respect/validation/tests/unit/Rules/CntrlTest.php
@@ -11,12 +11,14 @@
 
 namespace Respect\Validation\Rules;
 
+use Respect\Validation\TestCase;
+
 /**
  * @group  rule
  * @covers Respect\Validation\Rules\Cntrl
  * @covers Respect\Validation\Exceptions\CntrlException
  */
-class CntrlTest extends \PHPUnit_Framework_TestCase
+class CntrlTest extends TestCase
 {
     /**
      * @dataProvider providerForValidCntrl
diff --git a/vendor/respect/validation/tests/unit/Rules/ConsonantTest.php b/vendor/respect/validation/tests/unit/Rules/ConsonantTest.php
index a9e7a4822e65ae07864dd0784d7db22379f87a17..b0167507cc9d7ce06d01db191f2c917ab62a7e80 100644
--- a/vendor/respect/validation/tests/unit/Rules/ConsonantTest.php
+++ b/vendor/respect/validation/tests/unit/Rules/ConsonantTest.php
@@ -11,12 +11,14 @@
 
 namespace Respect\Validation\Rules;
 
+use Respect\Validation\TestCase;
+
 /**
  * @group  rule
  * @covers Respect\Validation\Rules\Consonant
  * @covers Respect\Validation\Exceptions\ConsonantException
  */
-class ConsonantTest extends \PHPUnit_Framework_TestCase
+class ConsonantTest extends TestCase
 {
     /**
      * @dataProvider providerForValidConsonants
diff --git a/vendor/respect/validation/tests/unit/Rules/ContainsTest.php b/vendor/respect/validation/tests/unit/Rules/ContainsTest.php
index 3cefaea19e608f0fd5a5ef138ed24dfc1ebdf5e9..355e9e54376fce50b0219331aa47f0a06ee1b446 100644
--- a/vendor/respect/validation/tests/unit/Rules/ContainsTest.php
+++ b/vendor/respect/validation/tests/unit/Rules/ContainsTest.php
@@ -11,12 +11,14 @@
 
 namespace Respect\Validation\Rules;
 
+use Respect\Validation\TestCase;
+
 /**
  * @group  rule
  * @covers Respect\Validation\Rules\Contains
  * @covers Respect\Validation\Exceptions\ContainsException
  */
-class ContainsTest extends \PHPUnit_Framework_TestCase
+class ContainsTest extends TestCase
 {
     /**
      * @dataProvider providerForContainsIdentical
diff --git a/vendor/respect/validation/tests/unit/Rules/CountryCodeTest.php b/vendor/respect/validation/tests/unit/Rules/CountryCodeTest.php
index d6754521e5fa67c51094f7a34ecda04493ee9a74..227ef2088c9c19cf2b2fdfd6cf9cae3f57014c39 100644
--- a/vendor/respect/validation/tests/unit/Rules/CountryCodeTest.php
+++ b/vendor/respect/validation/tests/unit/Rules/CountryCodeTest.php
@@ -11,11 +11,13 @@
 
 namespace Respect\Validation\Rules;
 
+use Respect\Validation\TestCase;
+
 /**
  * @group  rule
  * @covers Respect\Validation\Rules\CountryCode
  */
-class CountryCodeTest extends \PHPUnit_Framework_TestCase
+class CountryCodeTest extends TestCase
 {
     /**
      * @expectedException        Respect\Validation\Exceptions\ComponentException
diff --git a/vendor/respect/validation/tests/unit/Rules/CpfTest.php b/vendor/respect/validation/tests/unit/Rules/CpfTest.php
index 6764bb66651d56cd6571220fd5454ac279f8ba50..0a831c69f1ee9897ec781300d97eb18a9dbab4ef 100644
--- a/vendor/respect/validation/tests/unit/Rules/CpfTest.php
+++ b/vendor/respect/validation/tests/unit/Rules/CpfTest.php
@@ -11,12 +11,14 @@
 
 namespace Respect\Validation\Rules;
 
+use Respect\Validation\TestCase;
+
 /**
  * @group  rule
  * @covers Respect\Validation\Rules\Cpf
  * @covers Respect\Validation\Exceptions\CpfException
  */
-class CpfTest extends \PHPUnit_Framework_TestCase
+class CpfTest extends TestCase
 {
     protected $cpfValidator;
 
@@ -106,6 +108,7 @@ class CpfTest extends \PHPUnit_Framework_TestCase
     public function providerInvalidUnformattedCpf()
     {
         return [
+            ['01234567890'],
             ['11111111111'],
             ['22222222222'],
             ['12345678900'],
diff --git a/vendor/respect/validation/tests/unit/Rules/DigitTest.php b/vendor/respect/validation/tests/unit/Rules/DigitTest.php
index 9b6ed714fce4e54356f196cf677a06952ab00c86..3e5362941a3c44182b2cfc55a3a2ff601bc39fe2 100644
--- a/vendor/respect/validation/tests/unit/Rules/DigitTest.php
+++ b/vendor/respect/validation/tests/unit/Rules/DigitTest.php
@@ -11,12 +11,14 @@
 
 namespace Respect\Validation\Rules;
 
+use Respect\Validation\TestCase;
+
 /**
  * @group  rule
  * @covers Respect\Validation\Rules\Digit
  * @covers Respect\Validation\Exceptions\DigitException
  */
-class DigitTest extends \PHPUnit_Framework_TestCase
+class DigitTest extends TestCase
 {
     /**
      * @dataProvider providerForValidDigits
diff --git a/vendor/respect/validation/tests/unit/Rules/DirectoryTest.php b/vendor/respect/validation/tests/unit/Rules/DirectoryTest.php
index a555e7caa7f5ea82bfe841947167ebcec2acbc0f..1bdd9f671a49e5f922a779ff1335476c9077db58 100644
--- a/vendor/respect/validation/tests/unit/Rules/DirectoryTest.php
+++ b/vendor/respect/validation/tests/unit/Rules/DirectoryTest.php
@@ -11,12 +11,14 @@
 
 namespace Respect\Validation\Rules;
 
+use Respect\Validation\TestCase;
+
 /**
  * @group  rule
  * @covers Respect\Validation\Rules\Directory
  * @covers Respect\Validation\Exceptions\DirectoryException
  */
-class DirectoryTest extends \PHPUnit_Framework_TestCase
+class DirectoryTest extends TestCase
 {
     /**
      * @dataProvider providerForValidDirectory
diff --git a/vendor/respect/validation/tests/unit/Rules/DomainTest.php b/vendor/respect/validation/tests/unit/Rules/DomainTest.php
index 8324edf6fad53663fdb75bea7386486b6da7fbfc..68a51fff7e194b21da0aacb00b560a266bb6338e 100644
--- a/vendor/respect/validation/tests/unit/Rules/DomainTest.php
+++ b/vendor/respect/validation/tests/unit/Rules/DomainTest.php
@@ -11,6 +11,7 @@
 
 namespace Respect\Validation\Rules;
 
+use Respect\Validation\TestCase;
 use Respect\Validation\Validator as v;
 
 /**
@@ -18,7 +19,7 @@ use Respect\Validation\Validator as v;
  * @covers Respect\Validation\Rules\Domain
  * @covers Respect\Validation\Exceptions\DomainException
  */
-class DomainTest extends \PHPUnit_Framework_TestCase
+class DomainTest extends TestCase
 {
     protected $object;
 
diff --git a/vendor/respect/validation/tests/unit/Rules/EmailTest.php b/vendor/respect/validation/tests/unit/Rules/EmailTest.php
index 3c32e47392d91f18da14ec8d6c7b0b12c7986e12..e66ac540655caaf26f1240b25288da6725e2dea8 100644
--- a/vendor/respect/validation/tests/unit/Rules/EmailTest.php
+++ b/vendor/respect/validation/tests/unit/Rules/EmailTest.php
@@ -11,6 +11,7 @@
 
 namespace Respect\Validation\Rules;
 
+use Respect\Validation\TestCase;
 use stdClass;
 
 function class_exists($className)
@@ -27,7 +28,7 @@ function class_exists($className)
  * @covers Respect\Validation\Rules\Email
  * @covers Respect\Validation\Exceptions\EmailException
  */
-class EmailTest extends \PHPUnit_Framework_TestCase
+class EmailTest extends TestCase
 {
     private function setEmailValidatorExists($value)
     {
diff --git a/vendor/respect/validation/tests/unit/Rules/EndsWithTest.php b/vendor/respect/validation/tests/unit/Rules/EndsWithTest.php
index 1fb5074642397c5f8b4af1cb0fb61cd2869e9533..9d25aae3a0630e0482ee0ee8dda5611c1b89d846 100644
--- a/vendor/respect/validation/tests/unit/Rules/EndsWithTest.php
+++ b/vendor/respect/validation/tests/unit/Rules/EndsWithTest.php
@@ -11,12 +11,14 @@
 
 namespace Respect\Validation\Rules;
 
+use Respect\Validation\TestCase;
+
 /**
  * @group  rule
  * @covers Respect\Validation\Rules\EndsWith
  * @covers Respect\Validation\Exceptions\EndsWithException
  */
-class EndsWithTest extends \PHPUnit_Framework_TestCase
+class EndsWithTest extends TestCase
 {
     /**
      * @dataProvider providerForEndsWith
diff --git a/vendor/respect/validation/tests/unit/Rules/EqualsTest.php b/vendor/respect/validation/tests/unit/Rules/EqualsTest.php
index b90a2b6a08febde23b6dbfb84557f8e744e1e1ea..756e9fd8d1ef84fd6f5eec9eb46d03ab005107e5 100644
--- a/vendor/respect/validation/tests/unit/Rules/EqualsTest.php
+++ b/vendor/respect/validation/tests/unit/Rules/EqualsTest.php
@@ -11,6 +11,7 @@
 
 namespace Respect\Validation\Rules;
 
+use Respect\Validation\TestCase;
 use stdClass;
 
 /**
@@ -18,7 +19,7 @@ use stdClass;
  * @covers Respect\Validation\Rules\Equals
  * @covers Respect\Validation\Exceptions\EqualsException
  */
-class EqualsTest extends \PHPUnit_Framework_TestCase
+class EqualsTest extends TestCase
 {
     /**
      * @dataProvider providerForEquals
diff --git a/vendor/respect/validation/tests/unit/Rules/EvenTest.php b/vendor/respect/validation/tests/unit/Rules/EvenTest.php
index fe72d460ede2ad1e0e7aadf45020947119bf25ae..1c30f486c76b5853cd049a62048820dd6c3e8e48 100644
--- a/vendor/respect/validation/tests/unit/Rules/EvenTest.php
+++ b/vendor/respect/validation/tests/unit/Rules/EvenTest.php
@@ -11,12 +11,14 @@
 
 namespace Respect\Validation\Rules;
 
+use Respect\Validation\TestCase;
+
 /**
  * @group  rule
  * @covers Respect\Validation\Rules\Even
  * @covers Respect\Validation\Exceptions\EvenException
  */
-class EvenTest extends \PHPUnit_Framework_TestCase
+class EvenTest extends TestCase
 {
     protected $evenValidator;
 
diff --git a/vendor/respect/validation/tests/unit/Rules/ExecutableTest.php b/vendor/respect/validation/tests/unit/Rules/ExecutableTest.php
index 9a04cb63d4de12910972b79999e1e4c555f2b7de..799697893421c447fff6cb2c922298bb07f6ec3f 100644
--- a/vendor/respect/validation/tests/unit/Rules/ExecutableTest.php
+++ b/vendor/respect/validation/tests/unit/Rules/ExecutableTest.php
@@ -11,6 +11,9 @@
 
 namespace Respect\Validation\Rules;
 
+use Respect\Validation\TestCase;
+use SplFileInfo;
+
 $GLOBALS['is_executable'] = null;
 
 function is_executable($executable)
@@ -29,7 +32,7 @@ function is_executable($executable)
  * @covers Respect\Validation\Rules\Executable
  * @covers Respect\Validation\Exceptions\ExecutableException
  */
-class ExecutableTest extends \PHPUnit_Framework_TestCase
+class ExecutableTest extends TestCase
 {
     public function testValidExecutableFileShouldReturnTrue()
     {
@@ -52,10 +55,7 @@ class ExecutableTest extends \PHPUnit_Framework_TestCase
     public function testShouldValidateObjects()
     {
         $rule = new Executable();
-        $object = $this->getMock('SplFileInfo', ['isExecutable'], ['somefile.txt']);
-        $object->expects($this->once())
-                ->method('isExecutable')
-                ->will($this->returnValue(true));
+        $object = new SplFileInfo('tests/fixtures/executable');
 
         $this->assertTrue($rule->validate($object));
     }
diff --git a/vendor/respect/validation/tests/unit/Rules/ExistsTest.php b/vendor/respect/validation/tests/unit/Rules/ExistsTest.php
index 94be30727e789ea6c9a70aeec71e33e500b17774..253f798abadea69c65182ed62b4ba8a10b5e62ca 100644
--- a/vendor/respect/validation/tests/unit/Rules/ExistsTest.php
+++ b/vendor/respect/validation/tests/unit/Rules/ExistsTest.php
@@ -13,7 +13,7 @@ namespace Respect\Validation\Rules;
 
 use org\bovigo\vfs\content\LargeFileContent;
 use org\bovigo\vfs\vfsStream;
-use PHPUnit_Framework_TestCase;
+use Respect\Validation\TestCase;
 use SplFileInfo;
 
 /**
@@ -21,7 +21,7 @@ use SplFileInfo;
  * @covers Respect\Validation\Rules\Exists
  * @covers Respect\Validation\Exceptions\ExistsException
  */
-class ExistsTest extends PHPUnit_Framework_TestCase
+class ExistsTest extends TestCase
 {
     /**
      * @dataProvider fileProvider
diff --git a/vendor/respect/validation/tests/unit/Rules/ExtensionTest.php b/vendor/respect/validation/tests/unit/Rules/ExtensionTest.php
index 3f282ba9b1f86dbb45b1ce053acc0ba7863f30ff..18d84bf33cd8ae7301e96ebeaff5b48c1d619479 100644
--- a/vendor/respect/validation/tests/unit/Rules/ExtensionTest.php
+++ b/vendor/respect/validation/tests/unit/Rules/ExtensionTest.php
@@ -11,7 +11,7 @@
 
 namespace Respect\Validation\Rules;
 
-use PHPUnit_Framework_TestCase;
+use Respect\Validation\TestCase;
 use SplFileInfo;
 
 /**
@@ -20,7 +20,7 @@ use SplFileInfo;
  * @covers Respect\Validation\Rules\Extension
  * @covers Respect\Validation\Exceptions\ExtensionException
  */
-class ExtensionTest extends PHPUnit_Framework_TestCase
+class ExtensionTest extends TestCase
 {
     public function providerValidExtension()
     {
diff --git a/vendor/respect/validation/tests/unit/Rules/FactorTest.php b/vendor/respect/validation/tests/unit/Rules/FactorTest.php
index d4016e8ac0853a6dd8a5f3a24e200fcd54343a46..a1a03c24d1a4f002a7bf62868730e88d2d9faf2a 100644
--- a/vendor/respect/validation/tests/unit/Rules/FactorTest.php
+++ b/vendor/respect/validation/tests/unit/Rules/FactorTest.php
@@ -11,6 +11,7 @@
 
 namespace Respect\Validation\Rules;
 
+use Respect\Validation\TestCase;
 use Respect\Validation\Exceptions\ValidationException;
 
 /**
@@ -20,7 +21,7 @@ use Respect\Validation\Exceptions\ValidationException;
  *
  * @author David Meister <thedavidmeister@gmail.com>
  */
-class FactorTest extends \PHPUnit_Framework_TestCase
+class FactorTest extends TestCase
 {
     /**
      * @dataProvider providerForValidFactor
diff --git a/vendor/respect/validation/tests/unit/Rules/FalseValTest.php b/vendor/respect/validation/tests/unit/Rules/FalseValTest.php
index 1c9b38590246951cb177c36b78c8404b636a046a..6a328174a7bfdc3ce4ee2aae37eac86515c8b53d 100644
--- a/vendor/respect/validation/tests/unit/Rules/FalseValTest.php
+++ b/vendor/respect/validation/tests/unit/Rules/FalseValTest.php
@@ -11,12 +11,14 @@
 
 namespace Respect\Validation\Rules;
 
+use Respect\Validation\TestCase;
+
 /**
  * @group  rule
  * @covers Respect\Validation\Rules\FalseVal
  * @covers Respect\Validation\Exceptions\FalseValException
  */
-class FalseValTest extends \PHPUnit_Framework_TestCase
+class FalseValTest extends TestCase
 {
     /**
      * @dataProvider validFalseProvider
diff --git a/vendor/respect/validation/tests/unit/Rules/FileTest.php b/vendor/respect/validation/tests/unit/Rules/FileTest.php
index 74505aa35e87c7c71f0a39dcfd33ff2cdeccbb66..f843ee65581294ed1b63de4df69281e737230e74 100644
--- a/vendor/respect/validation/tests/unit/Rules/FileTest.php
+++ b/vendor/respect/validation/tests/unit/Rules/FileTest.php
@@ -11,6 +11,9 @@
 
 namespace Respect\Validation\Rules;
 
+use Respect\Validation\TestCase;
+use SplFileInfo;
+
 $GLOBALS['is_file'] = null;
 
 function is_file($file)
@@ -29,7 +32,7 @@ function is_file($file)
  * @covers Respect\Validation\Rules\File
  * @covers Respect\Validation\Exceptions\FileException
  */
-class FileTest extends \PHPUnit_Framework_TestCase
+class FileTest extends TestCase
 {
     /**
      * @covers Respect\Validation\Rules\File::validate
@@ -61,10 +64,7 @@ class FileTest extends \PHPUnit_Framework_TestCase
     public function testShouldValidateObjects()
     {
         $rule = new File();
-        $object = $this->getMock('SplFileInfo', ['isFile'], ['somefile.txt']);
-        $object->expects($this->once())
-                ->method('isFile')
-                ->will($this->returnValue(true));
+        $object = new SplFileInfo('tests/fixtures/valid-image.png');
 
         $this->assertTrue($rule->validate($object));
     }
diff --git a/vendor/respect/validation/tests/unit/Rules/FilterVarTest.php b/vendor/respect/validation/tests/unit/Rules/FilterVarTest.php
index 5b0b7f935e0a1c38a7b5150d840b249b2e05bc4f..8de0f4eea40981facc034c78df253c05815dc5a8 100644
--- a/vendor/respect/validation/tests/unit/Rules/FilterVarTest.php
+++ b/vendor/respect/validation/tests/unit/Rules/FilterVarTest.php
@@ -11,12 +11,14 @@
 
 namespace Respect\Validation\Rules;
 
+use Respect\Validation\TestCase;
+
 /**
  * @group  rule
  * @covers Respect\Validation\Rules\FilterVar
  * @covers Respect\Validation\Exceptions\FilterVarException
  */
-class FilterVarTest extends \PHPUnit_Framework_TestCase
+class FilterVarTest extends TestCase
 {
     /**
      * @expectedException Respect\Validation\Exceptions\ComponentException
diff --git a/vendor/respect/validation/tests/unit/Rules/FiniteTest.php b/vendor/respect/validation/tests/unit/Rules/FiniteTest.php
index 51272f371f0239fe321708b033a622b4c5fbc62c..a910e2117c8922fa7f5d9df996b61f7f6ba3f7b4 100644
--- a/vendor/respect/validation/tests/unit/Rules/FiniteTest.php
+++ b/vendor/respect/validation/tests/unit/Rules/FiniteTest.php
@@ -11,12 +11,14 @@
 
 namespace Respect\Validation\Rules;
 
+use Respect\Validation\TestCase;
+
 /**
  * @group  rule
  * @covers Respect\Validation\Rules\Finite
  * @covers Respect\Validation\Exceptions\FiniteException
  */
-class FiniteTest extends \PHPUnit_Framework_TestCase
+class FiniteTest extends TestCase
 {
     protected $rule;
 
diff --git a/vendor/respect/validation/tests/unit/Rules/FloatValTest.php b/vendor/respect/validation/tests/unit/Rules/FloatValTest.php
index a7208331bcc052ae49900d0b2adf801d6ca4be8f..026d18c64644e14bc6cf44d0c0ca68fe7f0c1a4a 100644
--- a/vendor/respect/validation/tests/unit/Rules/FloatValTest.php
+++ b/vendor/respect/validation/tests/unit/Rules/FloatValTest.php
@@ -11,12 +11,14 @@
 
 namespace Respect\Validation\Rules;
 
+use Respect\Validation\TestCase;
+
 /**
  * @group  rule
  * @covers Respect\Validation\Rules\FloatVal
  * @covers Respect\Validation\Exceptions\FloatValException
  */
-class FloatValTest extends \PHPUnit_Framework_TestCase
+class FloatValTest extends TestCase
 {
     protected $floatValidator;
 
diff --git a/vendor/respect/validation/tests/unit/Rules/GraphTest.php b/vendor/respect/validation/tests/unit/Rules/GraphTest.php
index 341440d5e28f23ba8b29a3a11c3ff31394a8476b..1a7281114a22e867a1087c388b47eace8fa50bf1 100644
--- a/vendor/respect/validation/tests/unit/Rules/GraphTest.php
+++ b/vendor/respect/validation/tests/unit/Rules/GraphTest.php
@@ -11,12 +11,14 @@
 
 namespace Respect\Validation\Rules;
 
+use Respect\Validation\TestCase;
+
 /**
  * @group  rule
  * @covers Respect\Validation\Rules\Graph
  * @covers Respect\Validation\Exceptions\GraphException
  */
-class GraphTest extends \PHPUnit_Framework_TestCase
+class GraphTest extends TestCase
 {
     /**
      * @dataProvider providerForValidGraph
diff --git a/vendor/respect/validation/tests/unit/Rules/HexRgbColorTest.php b/vendor/respect/validation/tests/unit/Rules/HexRgbColorTest.php
index f29c8505d743068367ca900777eb62463068b666..7f534acad3ac7b80734a50aa737b93f9c74f62e5 100644
--- a/vendor/respect/validation/tests/unit/Rules/HexRgbColorTest.php
+++ b/vendor/respect/validation/tests/unit/Rules/HexRgbColorTest.php
@@ -11,12 +11,14 @@
 
 namespace Respect\Validation\Rules;
 
+use Respect\Validation\TestCase;
+
 /**
  * @group  rule
  * @covers Respect\Validation\Rules\HexRgbColor
  * @covers Respect\Validation\Exceptions\HexRgbColorException
  */
-class HexRgbColorTest extends \PHPUnit_Framework_TestCase
+class HexRgbColorTest extends TestCase
 {
     /**
      * @dataProvider providerForValidHexRgbColor
diff --git a/vendor/respect/validation/tests/unit/Rules/IdenticalTest.php b/vendor/respect/validation/tests/unit/Rules/IdenticalTest.php
index 705ca66ea86e9ca2b6e502c10c351b0e79a86a27..ea74e25b2cd49c4cc99b592a5b2bb3be8852d827 100644
--- a/vendor/respect/validation/tests/unit/Rules/IdenticalTest.php
+++ b/vendor/respect/validation/tests/unit/Rules/IdenticalTest.php
@@ -11,6 +11,7 @@
 
 namespace Respect\Validation\Rules;
 
+use Respect\Validation\TestCase;
 use stdClass;
 
 /**
@@ -18,7 +19,7 @@ use stdClass;
  * @covers Respect\Validation\Rules\Identical
  * @covers Respect\Validation\Exceptions\IdenticalException
  */
-class IdenticalTest extends \PHPUnit_Framework_TestCase
+class IdenticalTest extends TestCase
 {
     /**
      * @dataProvider providerForIdentical
diff --git a/vendor/respect/validation/tests/unit/Rules/InTest.php b/vendor/respect/validation/tests/unit/Rules/InTest.php
index 7f69a7f542cbcd78a45f030d270abe90736d8253..6ca74d99f9b9348187ee795005f6ca08766b1088 100644
--- a/vendor/respect/validation/tests/unit/Rules/InTest.php
+++ b/vendor/respect/validation/tests/unit/Rules/InTest.php
@@ -11,12 +11,14 @@
 
 namespace Respect\Validation\Rules;
 
+use Respect\Validation\TestCase;
+
 /**
  * @group  rule
  * @covers Respect\Validation\Rules\In
  * @covers Respect\Validation\Exceptions\InException
  */
-class InTest extends \PHPUnit_Framework_TestCase
+class InTest extends TestCase
 {
     /**
      * @dataProvider providerForIn
diff --git a/vendor/respect/validation/tests/unit/Rules/InfiniteTest.php b/vendor/respect/validation/tests/unit/Rules/InfiniteTest.php
index 6158d103d73181e6f91557a6a236fc3cd86b74b4..d0f08ae7688709ed0a020a915e42705a2ebc57b1 100644
--- a/vendor/respect/validation/tests/unit/Rules/InfiniteTest.php
+++ b/vendor/respect/validation/tests/unit/Rules/InfiniteTest.php
@@ -11,12 +11,14 @@
 
 namespace Respect\Validation\Rules;
 
+use Respect\Validation\TestCase;
+
 /**
  * @group  rule
  * @covers Respect\Validation\Rules\Infinite
  * @covers Respect\Validation\Exceptions\InfiniteException
  */
-class InfiniteTest extends \PHPUnit_Framework_TestCase
+class InfiniteTest extends TestCase
 {
     protected $rule;
 
diff --git a/vendor/respect/validation/tests/unit/Rules/InstanceTest.php b/vendor/respect/validation/tests/unit/Rules/InstanceTest.php
index 448f92738bd1ad3bb2e66ce96cfcb9d8323c97b2..8cf8b66e675e2a4e6e1db88ead2bd181b3fffea0 100644
--- a/vendor/respect/validation/tests/unit/Rules/InstanceTest.php
+++ b/vendor/respect/validation/tests/unit/Rules/InstanceTest.php
@@ -11,12 +11,14 @@
 
 namespace Respect\Validation\Rules;
 
+use Respect\Validation\TestCase;
+
 /**
  * @group  rule
  * @covers Respect\Validation\Rules\Instance
  * @covers Respect\Validation\Exceptions\InstanceException
  */
-class InstanceTest extends \PHPUnit_Framework_TestCase
+class InstanceTest extends TestCase
 {
     protected $instanceValidator;
 
diff --git a/vendor/respect/validation/tests/unit/Rules/IntTypeTest.php b/vendor/respect/validation/tests/unit/Rules/IntTypeTest.php
index 2575e0e0bcfe400b0412e30fff36d8a3aa5f112d..05e7f099a55093f103a96661c12acfc30caeb94e 100644
--- a/vendor/respect/validation/tests/unit/Rules/IntTypeTest.php
+++ b/vendor/respect/validation/tests/unit/Rules/IntTypeTest.php
@@ -11,11 +11,13 @@
 
 namespace Respect\Validation\Rules;
 
+use Respect\Validation\TestCase;
+
 /**
  * @group  rule
  * @covers Respect\Validation\Rules\IntType
  */
-class IntTypeTest extends \PHPUnit_Framework_TestCase
+class IntTypeTest extends TestCase
 {
     public function providerForValidIntType()
     {
diff --git a/vendor/respect/validation/tests/unit/Rules/IntValTest.php b/vendor/respect/validation/tests/unit/Rules/IntValTest.php
index 302c19da32b373a63103e2803152e4f397b6d1a8..062fd3886b0f4ae5e9504b924e4980edeb944e5e 100644
--- a/vendor/respect/validation/tests/unit/Rules/IntValTest.php
+++ b/vendor/respect/validation/tests/unit/Rules/IntValTest.php
@@ -11,12 +11,14 @@
 
 namespace Respect\Validation\Rules;
 
+use Respect\Validation\TestCase;
+
 /**
  * @group  rule
  * @covers Respect\Validation\Rules\IntVal
  * @covers Respect\Validation\Exceptions\IntValException
  */
-class IntValTest extends \PHPUnit_Framework_TestCase
+class IntValTest extends TestCase
 {
     protected $intValidator;
 
diff --git a/vendor/respect/validation/tests/unit/Rules/IpTest.php b/vendor/respect/validation/tests/unit/Rules/IpTest.php
index 3991c57bd38da1490c970573c9fbf53b1911408c..191aa440625161160a9c4e78783498032d1afefb 100644
--- a/vendor/respect/validation/tests/unit/Rules/IpTest.php
+++ b/vendor/respect/validation/tests/unit/Rules/IpTest.php
@@ -11,12 +11,14 @@
 
 namespace Respect\Validation\Rules;
 
+use Respect\Validation\TestCase;
+
 /**
  * @group  rule
  * @covers Respect\Validation\Rules\Ip
  * @covers Respect\Validation\Exceptions\IpException
  */
-class IpTest extends \PHPUnit_Framework_TestCase
+class IpTest extends TestCase
 {
     /**
      * @dataProvider providerForIp
diff --git a/vendor/respect/validation/tests/unit/Rules/KeyNestedTest.php b/vendor/respect/validation/tests/unit/Rules/KeyNestedTest.php
index 4500f6122a4bc27afa2cdbdb7dcc1318fc7d1423..84e182480f116660874ea2b7cb2ca2ddcc79b314 100644
--- a/vendor/respect/validation/tests/unit/Rules/KeyNestedTest.php
+++ b/vendor/respect/validation/tests/unit/Rules/KeyNestedTest.php
@@ -11,6 +11,7 @@
 
 namespace Respect\Validation\Rules;
 
+use Respect\Validation\TestCase;
 use ArrayObject;
 
 /**
@@ -18,7 +19,7 @@ use ArrayObject;
  * @covers Respect\Validation\Rules\KeyNested
  * @covers Respect\Validation\Exceptions\KeyNestedException
  */
-class KeyNestedTest extends \PHPUnit_Framework_TestCase
+class KeyNestedTest extends TestCase
 {
     public function testArrayWithPresentKeysWillReturnTrueForFullPathValidator()
     {
diff --git a/vendor/respect/validation/tests/unit/Rules/KeySetTest.php b/vendor/respect/validation/tests/unit/Rules/KeySetTest.php
index 3422132b58bd19f6e91de83fe42302bb24cf7df7..d4a757ca503482e85b75189e4e1f80fd754d6299 100644
--- a/vendor/respect/validation/tests/unit/Rules/KeySetTest.php
+++ b/vendor/respect/validation/tests/unit/Rules/KeySetTest.php
@@ -11,14 +11,14 @@
 
 namespace Respect\Validation\Rules;
 
-use PHPUnit_Framework_TestCase;
+use Respect\Validation\TestCase;
 
 /**
  * @group  rule
  * @covers Respect\Validation\Rules\KeySet
  * @covers Respect\Validation\Exceptions\KeySetException
  */
-class KeySetTest extends PHPUnit_Framework_TestCase
+class KeySetTest extends TestCase
 {
     public function testShouldAcceptKeyRule()
     {
diff --git a/vendor/respect/validation/tests/unit/Rules/KeyTest.php b/vendor/respect/validation/tests/unit/Rules/KeyTest.php
index ac986c093b0184788985668933437f68157e229d..29c547b52a500e6419c0be7fb668cdbb9ee85a5c 100644
--- a/vendor/respect/validation/tests/unit/Rules/KeyTest.php
+++ b/vendor/respect/validation/tests/unit/Rules/KeyTest.php
@@ -11,12 +11,14 @@
 
 namespace Respect\Validation\Rules;
 
+use Respect\Validation\TestCase;
+
 /**
  * @group  rule
  * @covers Respect\Validation\Rules\Key
  * @covers Respect\Validation\Exceptions\KeyException
  */
-class KeyTest extends \PHPUnit_Framework_TestCase
+class KeyTest extends TestCase
 {
     public function testArrayWithPresentKeyShouldReturnTrue()
     {
diff --git a/vendor/respect/validation/tests/unit/Rules/KeyValueTest.php b/vendor/respect/validation/tests/unit/Rules/KeyValueTest.php
index a4406abf1772a5d174699bab8b5e46f5f539804d..f54bd7973e09e42e8eb5f83550b0e3d5fda97f1a 100644
--- a/vendor/respect/validation/tests/unit/Rules/KeyValueTest.php
+++ b/vendor/respect/validation/tests/unit/Rules/KeyValueTest.php
@@ -11,14 +11,14 @@
 
 namespace Respect\Validation\Rules;
 
-use PHPUnit_Framework_TestCase;
+use Respect\Validation\TestCase;
 
 /**
  * @group  rule
  * @covers Respect\Validation\Rules\KeyValue
  * @covers Respect\Validation\Exceptions\KeyValueException
  */
-class KeyValueTest extends PHPUnit_Framework_TestCase
+class KeyValueTest extends TestCase
 {
     public function testShouldDefineValuesOnConstructor()
     {
diff --git a/vendor/respect/validation/tests/unit/Rules/LeapDateTest.php b/vendor/respect/validation/tests/unit/Rules/LeapDateTest.php
index 60ab1f3638b60a9272cf60b26e543795eeb40230..83f8b4e227d314671caef71b6092adc2442bc361 100644
--- a/vendor/respect/validation/tests/unit/Rules/LeapDateTest.php
+++ b/vendor/respect/validation/tests/unit/Rules/LeapDateTest.php
@@ -11,6 +11,7 @@
 
 namespace Respect\Validation\Rules;
 
+use Respect\Validation\TestCase;
 use DateTime;
 
 /**
@@ -18,7 +19,7 @@ use DateTime;
  * @covers Respect\Validation\Rules\LeapDate
  * @covers Respect\Validation\Exceptions\LeapDateException
  */
-class LeapDateTest extends \PHPUnit_Framework_TestCase
+class LeapDateTest extends TestCase
 {
     protected $leapDateValidator;
 
@@ -35,7 +36,8 @@ class LeapDateTest extends \PHPUnit_Framework_TestCase
     public function testValidLeapDate_with_date_time()
     {
         $this->assertTrue($this->leapDateValidator->validate(
-            new DateTime('1988-02-29')));
+            new DateTime('1988-02-29')
+        ));
     }
 
     public function testInvalidLeapDate_with_string()
@@ -46,7 +48,8 @@ class LeapDateTest extends \PHPUnit_Framework_TestCase
     public function testInvalidLeapDate_with_date_time()
     {
         $this->assertFalse($this->leapDateValidator->validate(
-            new DateTime('1989-02-29')));
+            new DateTime('1989-02-29')
+        ));
     }
     public function testInvalidLeapDate_input()
     {
diff --git a/vendor/respect/validation/tests/unit/Rules/LeapYearTest.php b/vendor/respect/validation/tests/unit/Rules/LeapYearTest.php
index 7c375156d871be4be75e374697c35462dbabdeef..95beb513edacd1c5107df960a554649fa8384c45 100644
--- a/vendor/respect/validation/tests/unit/Rules/LeapYearTest.php
+++ b/vendor/respect/validation/tests/unit/Rules/LeapYearTest.php
@@ -11,6 +11,7 @@
 
 namespace Respect\Validation\Rules;
 
+use Respect\Validation\TestCase;
 use DateTime;
 
 /**
@@ -18,7 +19,7 @@ use DateTime;
  * @covers Respect\Validation\Rules\LeapYear
  * @covers Respect\Validation\Exceptions\LeapYearException
  */
-class LeapYearTest extends \PHPUnit_Framework_TestCase
+class LeapYearTest extends TestCase
 {
     protected $leapYearValidator;
 
@@ -33,7 +34,8 @@ class LeapYearTest extends \PHPUnit_Framework_TestCase
         $this->assertTrue($this->leapYearValidator->__invoke('2008-02-29'));
         $this->assertTrue($this->leapYearValidator->__invoke(2008));
         $this->assertTrue($this->leapYearValidator->__invoke(
-            new DateTime('2008-02-29')));
+            new DateTime('2008-02-29')
+        ));
     }
 
     public function testInvalidLeapDate()
@@ -43,7 +45,8 @@ class LeapYearTest extends \PHPUnit_Framework_TestCase
         $this->assertFalse($this->leapYearValidator->__invoke('2009-02-29'));
         $this->assertFalse($this->leapYearValidator->__invoke(2009));
         $this->assertFalse($this->leapYearValidator->__invoke(
-            new DateTime('2009-02-29')));
+            new DateTime('2009-02-29')
+        ));
         $this->assertFalse($this->leapYearValidator->__invoke([]));
     }
 }
diff --git a/vendor/respect/validation/tests/unit/Rules/LengthTest.php b/vendor/respect/validation/tests/unit/Rules/LengthTest.php
index 51de3a2fec87e79c9c3d013a3205bfb153c21c4f..c9263aea2da12ef3ed17d468cab5440b749a29ea 100644
--- a/vendor/respect/validation/tests/unit/Rules/LengthTest.php
+++ b/vendor/respect/validation/tests/unit/Rules/LengthTest.php
@@ -11,12 +11,14 @@
 
 namespace Respect\Validation\Rules;
 
+use Respect\Validation\TestCase;
+
 /**
  * @group  rule
  * @covers Respect\Validation\Rules\Length
  * @covers Respect\Validation\Exceptions\LengthException
  */
-class LengthTest extends \PHPUnit_Framework_TestCase
+class LengthTest extends TestCase
 {
     /**
      * @dataProvider providerForValidLengthInclusive
diff --git a/vendor/respect/validation/tests/unit/Rules/LowercaseTest.php b/vendor/respect/validation/tests/unit/Rules/LowercaseTest.php
index 58ed2ada3b4c67b71c11e7521983b3914ef86fbf..53b979130b5842de2d31134d8d1a2e9d112e4096 100644
--- a/vendor/respect/validation/tests/unit/Rules/LowercaseTest.php
+++ b/vendor/respect/validation/tests/unit/Rules/LowercaseTest.php
@@ -11,12 +11,14 @@
 
 namespace Respect\Validation\Rules;
 
+use Respect\Validation\TestCase;
+
 /**
  * @group  rule
  * @covers Respect\Validation\Rules\Lowercase
  * @covers Respect\Validation\Exceptions\LowercaseException
  */
-class LowercaseTest extends \PHPUnit_Framework_TestCase
+class LowercaseTest extends TestCase
 {
     /**
      * @dataProvider providerForValidLowercase
diff --git a/vendor/respect/validation/tests/unit/Rules/MacAddressTest.php b/vendor/respect/validation/tests/unit/Rules/MacAddressTest.php
index 67cfea1295326cbe0c912c0ab8d162840ad430be..cdb92db596e91065dd6a3597368cb9e4cf53eb81 100644
--- a/vendor/respect/validation/tests/unit/Rules/MacAddressTest.php
+++ b/vendor/respect/validation/tests/unit/Rules/MacAddressTest.php
@@ -11,12 +11,14 @@
 
 namespace Respect\Validation\Rules;
 
+use Respect\Validation\TestCase;
+
 /**
  * @group  rule
  * @covers Respect\Validation\Rules\MacAddress
  * @covers Respect\Validation\Exceptions\MacAddressException
  */
-class MacAddressTest extends \PHPUnit_Framework_TestCase
+class MacAddressTest extends TestCase
 {
     protected $macaddressValidator;
 
diff --git a/vendor/respect/validation/tests/unit/Rules/MaxTest.php b/vendor/respect/validation/tests/unit/Rules/MaxTest.php
index 72771e52cc442dcd8793e9157f5487cb3f70224a..fa21e26f79c0e2758e4b0eeb0c00795a022f8683 100644
--- a/vendor/respect/validation/tests/unit/Rules/MaxTest.php
+++ b/vendor/respect/validation/tests/unit/Rules/MaxTest.php
@@ -11,12 +11,14 @@
 
 namespace Respect\Validation\Rules;
 
+use Respect\Validation\TestCase;
+
 /**
  * @group  rule
  * @covers Respect\Validation\Rules\Max
  * @covers Respect\Validation\Exceptions\MaxException
  */
-class MaxTest extends \PHPUnit_Framework_TestCase
+class MaxTest extends TestCase
 {
     /**
      * @dataProvider providerForValidMax
diff --git a/vendor/respect/validation/tests/unit/Rules/MimetypeTest.php b/vendor/respect/validation/tests/unit/Rules/MimetypeTest.php
index 1e603c269c5f518d2f36b6ed89512ef9b97ed111..be53368ab2e51f704d518c5a11cf45f9ab97aaeb 100644
--- a/vendor/respect/validation/tests/unit/Rules/MimetypeTest.php
+++ b/vendor/respect/validation/tests/unit/Rules/MimetypeTest.php
@@ -11,7 +11,7 @@
 
 namespace Respect\Validation\Rules;
 
-use PHPUnit_Framework_TestCase;
+use Respect\Validation\TestCase;
 use SplFileInfo;
 
 /**
@@ -20,16 +20,12 @@ use SplFileInfo;
  * @covers Respect\Validation\Rules\Mimetype
  * @covers Respect\Validation\Exceptions\MimetypeException
  */
-class MimetypeTest extends PHPUnit_Framework_TestCase
+class MimetypeTest extends TestCase
 {
     private $filename;
 
     protected function setUp()
     {
-        if (defined('HHVM_VERSION')) {
-            return $this->markTestSkipped('If you are a HHVM user, and you are in the mood, please fix it');
-        }
-
         $this->filename = sprintf('%s/validation.txt', sys_get_temp_dir());
 
         file_put_contents($this->filename, 'File content');
diff --git a/vendor/respect/validation/tests/unit/Rules/MinTest.php b/vendor/respect/validation/tests/unit/Rules/MinTest.php
index fa01e132792e6d2345117ef923dbe713397880f6..17cd6a9bb0a63192e7e86394f8d3bb3dae5c4e88 100644
--- a/vendor/respect/validation/tests/unit/Rules/MinTest.php
+++ b/vendor/respect/validation/tests/unit/Rules/MinTest.php
@@ -11,6 +11,7 @@
 
 namespace Respect\Validation\Rules;
 
+use Respect\Validation\TestCase;
 use DateTime;
 
 /**
@@ -18,7 +19,7 @@ use DateTime;
  * @covers Respect\Validation\Rules\Min
  * @covers Respect\Validation\Exceptions\MinException
  */
-class MinTest extends \PHPUnit_Framework_TestCase
+class MinTest extends TestCase
 {
     /**
      * @dataProvider providerForValidMin
diff --git a/vendor/respect/validation/tests/unit/Rules/MininumAgeTest.php b/vendor/respect/validation/tests/unit/Rules/MininumAgeTest.php
index 61d5e005b86e7d960010be509b47de75e76bfd85..f7f189b5d0ccb542af135867db549e7fc100f469 100644
--- a/vendor/respect/validation/tests/unit/Rules/MininumAgeTest.php
+++ b/vendor/respect/validation/tests/unit/Rules/MininumAgeTest.php
@@ -11,12 +11,14 @@
 
 namespace Respect\Validation\Rules;
 
+use Respect\Validation\TestCase;
+
 /**
  * @group  rule
  * @covers Respect\Validation\Rules\MinimumAge
  * @covers Respect\Validation\Exceptions\MinimumAgeException
  */
-class MininumAgeTest extends \PHPUnit_Framework_TestCase
+class MininumAgeTest extends TestCase
 {
     /**
      * @dataProvider providerForValidDateValidMinimumAge
diff --git a/vendor/respect/validation/tests/unit/Rules/MultipleTest.php b/vendor/respect/validation/tests/unit/Rules/MultipleTest.php
index ce29862ee4529d7890f9b029072564c864826480..edd9ceb1ee456a505655dace778ea2e88d570cce 100644
--- a/vendor/respect/validation/tests/unit/Rules/MultipleTest.php
+++ b/vendor/respect/validation/tests/unit/Rules/MultipleTest.php
@@ -11,12 +11,14 @@
 
 namespace Respect\Validation\Rules;
 
+use Respect\Validation\TestCase;
+
 /**
  * @group  rule
  * @covers Respect\Validation\Rules\Multiple
  * @covers Respect\Validation\Exceptions\MultipleException
  */
-class MultipleTest extends \PHPUnit_Framework_TestCase
+class MultipleTest extends TestCase
 {
     /**
      * @dataProvider providerForMultiple
diff --git a/vendor/respect/validation/tests/unit/Rules/NegativeTest.php b/vendor/respect/validation/tests/unit/Rules/NegativeTest.php
index 608a17e1faf8970f94bfc999bd677689265fd527..9a2771d5701ff9e89ddd1fbccf3df097d5903461 100644
--- a/vendor/respect/validation/tests/unit/Rules/NegativeTest.php
+++ b/vendor/respect/validation/tests/unit/Rules/NegativeTest.php
@@ -11,12 +11,14 @@
 
 namespace Respect\Validation\Rules;
 
+use Respect\Validation\TestCase;
+
 /**
  * @group  rule
  * @covers Respect\Validation\Rules\Negative
  * @covers Respect\Validation\Exceptions\NegativeException
  */
-class NegativeTest extends \PHPUnit_Framework_TestCase
+class NegativeTest extends TestCase
 {
     protected $negativeValidator;
 
diff --git a/vendor/respect/validation/tests/unit/Rules/NfeAccessKeyTest.php b/vendor/respect/validation/tests/unit/Rules/NfeAccessKeyTest.php
index a47a53f1d9753a6f26739a0a3a78e2f06ee75f5b..71131102c887455f3c493e52fddcdbb6ded55d19 100644
--- a/vendor/respect/validation/tests/unit/Rules/NfeAccessKeyTest.php
+++ b/vendor/respect/validation/tests/unit/Rules/NfeAccessKeyTest.php
@@ -11,12 +11,14 @@
 
 namespace Respect\Validation\Rules;
 
+use Respect\Validation\TestCase;
+
 /**
  * @group  rule
  * @covers Respect\Validation\Rules\NfeAccessKey
  * @covers Respect\Validation\Exceptions\NfeAccessKeyException
  */
-class NfeAccessKeyTest extends \PHPUnit_Framework_TestCase
+class NfeAccessKeyTest extends TestCase
 {
     protected $nfeValidator;
 
diff --git a/vendor/respect/validation/tests/unit/Rules/NoTest.php b/vendor/respect/validation/tests/unit/Rules/NoTest.php
index 0ef2ee1934f0fc46cd4a8a7203ff9763ca628d02..5ea214d2f312c18904d22b450d7e2cd0ac442609 100644
--- a/vendor/respect/validation/tests/unit/Rules/NoTest.php
+++ b/vendor/respect/validation/tests/unit/Rules/NoTest.php
@@ -11,12 +11,14 @@
 
 namespace Respect\Validation\Rules;
 
+use Respect\Validation\TestCase;
+
 /**
  * @group  rule
  * @covers Respect\Validation\Rules\No
  * @covers Respect\Validation\Exceptions\NoException
  */
-class NoTest extends \PHPUnit_Framework_TestCase
+class NoTest extends TestCase
 {
     public function testShouldUseDefaultPattern()
     {
diff --git a/vendor/respect/validation/tests/unit/Rules/NoWhitespaceTest.php b/vendor/respect/validation/tests/unit/Rules/NoWhitespaceTest.php
index 9a6bad89406f2711446b79998fcc795ee2d7e818..c7bc494e15d2c12b1c231ef77e90b61ef325cb0c 100644
--- a/vendor/respect/validation/tests/unit/Rules/NoWhitespaceTest.php
+++ b/vendor/respect/validation/tests/unit/Rules/NoWhitespaceTest.php
@@ -11,12 +11,14 @@
 
 namespace Respect\Validation\Rules;
 
+use Respect\Validation\TestCase;
+
 /**
  * @group  rule
  * @covers Respect\Validation\Rules\NoWhitespace
  * @covers Respect\Validation\Exceptions\NoWhitespaceException
  */
-class NoWhitespaceTest extends \PHPUnit_Framework_TestCase
+class NoWhitespaceTest extends TestCase
 {
     protected $noWhitespaceValidator;
 
diff --git a/vendor/respect/validation/tests/unit/Rules/NoneOfTest.php b/vendor/respect/validation/tests/unit/Rules/NoneOfTest.php
index 62c6c87bf0e3b9c09d6168b31962feb93cb21ec4..3ee4e0a6ca2852019e04c071622519d08778d057 100644
--- a/vendor/respect/validation/tests/unit/Rules/NoneOfTest.php
+++ b/vendor/respect/validation/tests/unit/Rules/NoneOfTest.php
@@ -11,24 +11,26 @@
 
 namespace Respect\Validation\Rules;
 
+use Respect\Validation\TestCase;
+
 /**
  * @group  rule
  * @covers Respect\Validation\Rules\NoneOf
  * @covers Respect\Validation\Exceptions\NoneOfException
  */
-class NoneOfTest extends \PHPUnit_Framework_TestCase
+class NoneOfTest extends TestCase
 {
     public function testValid()
     {
         $valid1 = new Callback(function () {
-                    return false;
-                });
+            return false;
+        });
         $valid2 = new Callback(function () {
-                    return false;
-                });
+            return false;
+        });
         $valid3 = new Callback(function () {
-                    return false;
-                });
+            return false;
+        });
         $o = new NoneOf($valid1, $valid2, $valid3);
         $this->assertTrue($o->validate('any'));
         $this->assertTrue($o->assert('any'));
@@ -41,14 +43,14 @@ class NoneOfTest extends \PHPUnit_Framework_TestCase
     public function testInvalid()
     {
         $valid1 = new Callback(function () {
-                    return false;
-                });
+            return false;
+        });
         $valid2 = new Callback(function () {
-                    return false;
-                });
+            return false;
+        });
         $valid3 = new Callback(function () {
-                    return true;
-                });
+            return true;
+        });
         $o = new NoneOf($valid1, $valid2, $valid3);
         $this->assertFalse($o->validate('any'));
         $this->assertFalse($o->assert('any'));
diff --git a/vendor/respect/validation/tests/unit/Rules/NotBlankTest.php b/vendor/respect/validation/tests/unit/Rules/NotBlankTest.php
index 30550152b04fc4092269a13171ac962413bc07ac..7615435a74e7710029329f6970255334428f9251 100644
--- a/vendor/respect/validation/tests/unit/Rules/NotBlankTest.php
+++ b/vendor/respect/validation/tests/unit/Rules/NotBlankTest.php
@@ -11,6 +11,7 @@
 
 namespace Respect\Validation\Rules;
 
+use Respect\Validation\TestCase;
 use stdClass;
 
 /**
@@ -18,7 +19,7 @@ use stdClass;
  * @covers Respect\Validation\Rules\NotBlank
  * @covers Respect\Validation\Exceptions\NotBlankException
  */
-class NotBlankTest extends \PHPUnit_Framework_TestCase
+class NotBlankTest extends TestCase
 {
     /**
      * @dataProvider providerForNotBlank
diff --git a/vendor/respect/validation/tests/unit/Rules/NotEmptyTest.php b/vendor/respect/validation/tests/unit/Rules/NotEmptyTest.php
index 4496f090b14e3a16bfe3741bf5c5c3fc07a93452..02b879d56471d5e7bd071e3b869e5627f63872ef 100644
--- a/vendor/respect/validation/tests/unit/Rules/NotEmptyTest.php
+++ b/vendor/respect/validation/tests/unit/Rules/NotEmptyTest.php
@@ -11,12 +11,14 @@
 
 namespace Respect\Validation\Rules;
 
+use Respect\Validation\TestCase;
+
 /**
  * @group  rule
  * @covers Respect\Validation\Rules\NotEmpty
  * @covers Respect\Validation\Exceptions\NotEmptyException
  */
-class NotEmptyTest extends \PHPUnit_Framework_TestCase
+class NotEmptyTest extends TestCase
 {
     protected $object;
 
diff --git a/vendor/respect/validation/tests/unit/Rules/NotOptionalTest.php b/vendor/respect/validation/tests/unit/Rules/NotOptionalTest.php
index 5724a8836b4b187efec6a8a279fcf4629d8d3e2d..f11ed5bc26198d5421d241674f68fe99ea4e5d1b 100644
--- a/vendor/respect/validation/tests/unit/Rules/NotOptionalTest.php
+++ b/vendor/respect/validation/tests/unit/Rules/NotOptionalTest.php
@@ -11,13 +11,14 @@
 
 namespace Respect\Validation\Rules;
 
+use Respect\Validation\TestCase;
 use stdClass;
 
 /**
  * @group  rule
  * @covers Respect\Validation\Rules\NotOptional
  */
-class NotOptionalTest extends \PHPUnit_Framework_TestCase
+class NotOptionalTest extends TestCase
 {
     /**
      * @dataProvider providerForNotOptional
diff --git a/vendor/respect/validation/tests/unit/Rules/NotTest.php b/vendor/respect/validation/tests/unit/Rules/NotTest.php
index 03b69a067d47b7036704f16b8dc104075d63e4d7..235339a816791ea63afed1eb748811276dbd0eab 100644
--- a/vendor/respect/validation/tests/unit/Rules/NotTest.php
+++ b/vendor/respect/validation/tests/unit/Rules/NotTest.php
@@ -11,6 +11,7 @@
 
 namespace Respect\Validation\Rules;
 
+use Respect\Validation\TestCase;
 use Respect\Validation\Validator;
 
 /**
@@ -18,7 +19,7 @@ use Respect\Validation\Validator;
  * @covers Respect\Validation\Rules\Not
  * @covers Respect\Validation\Exceptions\NotException
  */
-class NotTest extends \PHPUnit_Framework_TestCase
+class NotTest extends TestCase
 {
     /**
      * @dataProvider providerForValidNot
diff --git a/vendor/respect/validation/tests/unit/Rules/NullTypeTest.php b/vendor/respect/validation/tests/unit/Rules/NullTypeTest.php
index d10a9c6dabd6db40382747c7f4e8c72e3c773f9f..be40b0e09c86f237dd0d23f8184cb00dae55deca 100644
--- a/vendor/respect/validation/tests/unit/Rules/NullTypeTest.php
+++ b/vendor/respect/validation/tests/unit/Rules/NullTypeTest.php
@@ -11,12 +11,14 @@
 
 namespace Respect\Validation\Rules;
 
+use Respect\Validation\TestCase;
+
 /**
  * @group  rule
  * @covers Respect\Validation\Rules\NullType
  * @covers Respect\Validation\Exceptions\NullTypeException
  */
-class NullTypeTest extends \PHPUnit_Framework_TestCase
+class NullTypeTest extends TestCase
 {
     protected $object;
 
diff --git a/vendor/respect/validation/tests/unit/Rules/NumericTest.php b/vendor/respect/validation/tests/unit/Rules/NumericTest.php
index ff05d7bae0e27cd7113d0a7b96fa38248bbd594c..6c32728d4239ef882b59c26a63576db8afbdeeef 100644
--- a/vendor/respect/validation/tests/unit/Rules/NumericTest.php
+++ b/vendor/respect/validation/tests/unit/Rules/NumericTest.php
@@ -11,12 +11,14 @@
 
 namespace Respect\Validation\Rules;
 
+use Respect\Validation\TestCase;
+
 /**
  * @group  rule
  * @covers Respect\Validation\Rules\Numeric
  * @covers Respect\Validation\Exceptions\NumericException
  */
-class NumericTest extends \PHPUnit_Framework_TestCase
+class NumericTest extends TestCase
 {
     protected $object;
 
diff --git a/vendor/respect/validation/tests/unit/Rules/ObjectTypeTest.php b/vendor/respect/validation/tests/unit/Rules/ObjectTypeTest.php
index 940f2ad0e962afbaf40b812aece5ffe1b6f9a513..e818a1c99aedd233bd5d38aa6dae067fe066fd1b 100644
--- a/vendor/respect/validation/tests/unit/Rules/ObjectTypeTest.php
+++ b/vendor/respect/validation/tests/unit/Rules/ObjectTypeTest.php
@@ -11,12 +11,14 @@
 
 namespace Respect\Validation\Rules;
 
+use Respect\Validation\TestCase;
+
 /**
  * @group  rule
  * @covers Respect\Validation\Rules\ObjectType
  * @covers Respect\Validation\Exceptions\ObjectTypeException
  */
-class ObjectTypeTest extends \PHPUnit_Framework_TestCase
+class ObjectTypeTest extends TestCase
 {
     protected $object;
 
diff --git a/vendor/respect/validation/tests/unit/Rules/OddTest.php b/vendor/respect/validation/tests/unit/Rules/OddTest.php
index 3d387ba31d658927f6c5146d122418e4a6490849..a9a93a8e5df9c11d3a2bf91eb364e85819fba131 100644
--- a/vendor/respect/validation/tests/unit/Rules/OddTest.php
+++ b/vendor/respect/validation/tests/unit/Rules/OddTest.php
@@ -11,12 +11,14 @@
 
 namespace Respect\Validation\Rules;
 
+use Respect\Validation\TestCase;
+
 /**
  * @group  rule
  * @covers Respect\Validation\Rules\Odd
  * @covers Respect\Validation\Exceptions\OddException
  */
-class OddTest extends \PHPUnit_Framework_TestCase
+class OddTest extends TestCase
 {
     protected $object;
 
diff --git a/vendor/respect/validation/tests/unit/Rules/OneOfTest.php b/vendor/respect/validation/tests/unit/Rules/OneOfTest.php
index 15e0a77947ea166889d4a8b548eefd62d8c5fbab..d76a2a415551149d67ec9f7fedf5c216565d4fb6 100644
--- a/vendor/respect/validation/tests/unit/Rules/OneOfTest.php
+++ b/vendor/respect/validation/tests/unit/Rules/OneOfTest.php
@@ -11,24 +11,26 @@
 
 namespace Respect\Validation\Rules;
 
+use Respect\Validation\TestCase;
+
 /**
  * @group  rule
  * @covers Respect\Validation\Rules\OneOf
  * @covers Respect\Validation\Exceptions\OneOfException
  */
-class OneOfTest extends \PHPUnit_Framework_TestCase
+class OneOfTest extends TestCase
 {
     public function testValid()
     {
         $valid1 = new Callback(function () {
-                    return false;
-                });
+            return false;
+        });
         $valid2 = new Callback(function () {
-                    return true;
-                });
+            return true;
+        });
         $valid3 = new Callback(function () {
-                    return false;
-                });
+            return false;
+        });
         $o = new OneOf($valid1, $valid2, $valid3);
         $this->assertTrue($o->validate('any'));
         $this->assertTrue($o->assert('any'));
@@ -41,14 +43,14 @@ class OneOfTest extends \PHPUnit_Framework_TestCase
     public function testInvalid()
     {
         $valid1 = new Callback(function () {
-                    return false;
-                });
+            return false;
+        });
         $valid2 = new Callback(function () {
-                    return false;
-                });
+            return false;
+        });
         $valid3 = new Callback(function () {
-                    return false;
-                });
+            return false;
+        });
         $o = new OneOf($valid1, $valid2, $valid3);
         $this->assertFalse($o->validate('any'));
         $this->assertFalse($o->assert('any'));
diff --git a/vendor/respect/validation/tests/unit/Rules/OptionalTest.php b/vendor/respect/validation/tests/unit/Rules/OptionalTest.php
index 256798174c27258cbaba911ec9522cb77a11dd65..51616edeebc58c3a4a54637fee8b79a01b8ed20e 100644
--- a/vendor/respect/validation/tests/unit/Rules/OptionalTest.php
+++ b/vendor/respect/validation/tests/unit/Rules/OptionalTest.php
@@ -11,13 +11,14 @@
 
 namespace Respect\Validation\Rules;
 
+use Respect\Validation\TestCase;
 use stdClass;
 
 /**
  * @group  rule
  * @covers Respect\Validation\Rules\Optional
  */
-class OptionalTest extends \PHPUnit_Framework_TestCase
+class OptionalTest extends TestCase
 {
     public function providerForOptional()
     {
@@ -50,7 +51,7 @@ class OptionalTest extends \PHPUnit_Framework_TestCase
 
     public function testShouldAcceptInstanceOfValidatobleOnConstructor()
     {
-        $validatable = $this->getMock('Respect\\Validation\\Validatable');
+        $validatable = $this->createMock('Respect\\Validation\\Validatable');
         $rule = new Optional($validatable);
 
         $this->assertSame($validatable, $rule->getValidatable());
@@ -61,7 +62,7 @@ class OptionalTest extends \PHPUnit_Framework_TestCase
      */
     public function testShouldNotValidateRuleWhenInputIsOptional($input)
     {
-        $validatable = $this->getMock('Respect\\Validation\\Validatable');
+        $validatable = $this->createMock('Respect\\Validation\\Validatable');
         $validatable
             ->expects($this->never())
             ->method('validate');
@@ -76,7 +77,7 @@ class OptionalTest extends \PHPUnit_Framework_TestCase
      */
     public function testShouldValidateRuleWhenInputIsNotOptional($input)
     {
-        $validatable = $this->getMock('Respect\\Validation\\Validatable');
+        $validatable = $this->createMock('Respect\\Validation\\Validatable');
         $validatable
             ->expects($this->once())
             ->method('validate')
@@ -90,7 +91,7 @@ class OptionalTest extends \PHPUnit_Framework_TestCase
 
     public function testShouldNotAssertRuleWhenInputIsOptional()
     {
-        $validatable = $this->getMock('Respect\\Validation\\Validatable');
+        $validatable = $this->createMock('Respect\\Validation\\Validatable');
         $validatable
             ->expects($this->never())
             ->method('assert');
@@ -104,7 +105,7 @@ class OptionalTest extends \PHPUnit_Framework_TestCase
     {
         $input = 'foo';
 
-        $validatable = $this->getMock('Respect\\Validation\\Validatable');
+        $validatable = $this->createMock('Respect\\Validation\\Validatable');
         $validatable
             ->expects($this->once())
             ->method('assert')
@@ -118,7 +119,7 @@ class OptionalTest extends \PHPUnit_Framework_TestCase
 
     public function testShouldNotCheckRuleWhenInputIsOptional()
     {
-        $validatable = $this->getMock('Respect\\Validation\\Validatable');
+        $validatable = $this->createMock('Respect\\Validation\\Validatable');
         $validatable
             ->expects($this->never())
             ->method('check');
@@ -132,7 +133,7 @@ class OptionalTest extends \PHPUnit_Framework_TestCase
     {
         $input = 'foo';
 
-        $validatable = $this->getMock('Respect\\Validation\\Validatable');
+        $validatable = $this->createMock('Respect\\Validation\\Validatable');
         $validatable
             ->expects($this->once())
             ->method('check')
diff --git a/vendor/respect/validation/tests/unit/Rules/PerfectSquareTest.php b/vendor/respect/validation/tests/unit/Rules/PerfectSquareTest.php
index 15512a2a4aa4b85fee4d8536f6ced6d2fe546da6..a5c64c758f81329f8118f3be3169e30926f5ea2d 100644
--- a/vendor/respect/validation/tests/unit/Rules/PerfectSquareTest.php
+++ b/vendor/respect/validation/tests/unit/Rules/PerfectSquareTest.php
@@ -11,12 +11,14 @@
 
 namespace Respect\Validation\Rules;
 
+use Respect\Validation\TestCase;
+
 /**
  * @group  rule
  * @covers Respect\Validation\Rules\PerfectSquare
  * @covers Respect\Validation\Exceptions\PerfectSquareException
  */
-class PerfectSquareTest extends \PHPUnit_Framework_TestCase
+class PerfectSquareTest extends TestCase
 {
     protected $object;
 
diff --git a/vendor/respect/validation/tests/unit/Rules/PhoneTest.php b/vendor/respect/validation/tests/unit/Rules/PhoneTest.php
index 21569a0aedb102b923c51e1b95764db6a9abdace..354027e8539a9bdb186230f03165548a5c54fb9a 100644
--- a/vendor/respect/validation/tests/unit/Rules/PhoneTest.php
+++ b/vendor/respect/validation/tests/unit/Rules/PhoneTest.php
@@ -11,12 +11,14 @@
 
 namespace Respect\Validation\Rules;
 
+use Respect\Validation\TestCase;
+
 /**
  * @group  rule
  * @covers Respect\Validation\Rules\Phone
  * @covers Respect\Validation\Exceptions\PhoneException
  */
-class PhoneTest extends \PHPUnit_Framework_TestCase
+class PhoneTest extends TestCase
 {
     protected $phoneValidator;
 
diff --git a/vendor/respect/validation/tests/unit/Rules/PositiveTest.php b/vendor/respect/validation/tests/unit/Rules/PositiveTest.php
index edc62153704e04ab5f73185737134e96a760c2ee..168ab572d2882aa7481f73d906d9719996e8397f 100644
--- a/vendor/respect/validation/tests/unit/Rules/PositiveTest.php
+++ b/vendor/respect/validation/tests/unit/Rules/PositiveTest.php
@@ -11,12 +11,14 @@
 
 namespace Respect\Validation\Rules;
 
+use Respect\Validation\TestCase;
+
 /**
  * @group  rule
  * @covers Respect\Validation\Rules\Positive
  * @covers Respect\Validation\Exceptions\PositiveException
  */
-class PositiveTest extends \PHPUnit_Framework_TestCase
+class PositiveTest extends TestCase
 {
     protected $object;
 
diff --git a/vendor/respect/validation/tests/unit/Rules/PostalCodeTest.php b/vendor/respect/validation/tests/unit/Rules/PostalCodeTest.php
index 32dc7a1412ac0f36c5f1b278a9c69b5eefb5ad33..60b70507fa2a81d8dd8305023151faf7c5bc40f8 100644
--- a/vendor/respect/validation/tests/unit/Rules/PostalCodeTest.php
+++ b/vendor/respect/validation/tests/unit/Rules/PostalCodeTest.php
@@ -11,12 +11,14 @@
 
 namespace Respect\Validation\Rules;
 
+use Respect\Validation\TestCase;
+
 /**
  * @group  rule
  * @covers Respect\Validation\Rules\PostalCode
  * @covers Respect\Validation\Exceptions\PostalCodeException
  */
-class PostalCodeTest extends \PHPUnit_Framework_TestCase
+class PostalCodeTest extends TestCase
 {
     public function testShouldUsePatternAccordingToCountryCode()
     {
@@ -98,6 +100,8 @@ class PostalCodeTest extends \PHPUnit_Framework_TestCase
             ['PT', '3660606'],
             ['CO', '110231'],
             ['KR', '03187'],
+            ['IE', 'D14 YD91'],
+            ['IE', 'D6W 3333'],
         ];
     }
 
diff --git a/vendor/respect/validation/tests/unit/Rules/PrimeNumberTest.php b/vendor/respect/validation/tests/unit/Rules/PrimeNumberTest.php
index 7d02a92db2da3b295045fc9c446caba6cd206d0c..7b9bd68092d3aa8aa834e2773560653225d8115e 100644
--- a/vendor/respect/validation/tests/unit/Rules/PrimeNumberTest.php
+++ b/vendor/respect/validation/tests/unit/Rules/PrimeNumberTest.php
@@ -11,12 +11,14 @@
 
 namespace Respect\Validation\Rules;
 
+use Respect\Validation\TestCase;
+
 /**
  * @group  rule
  * @covers Respect\Validation\Rules\PrimeNumber
  * @covers Respect\Validation\Exceptions\PrimeNumberException
  */
-class PrimeNumberTest extends \PHPUnit_Framework_TestCase
+class PrimeNumberTest extends TestCase
 {
     protected $object;
 
diff --git a/vendor/respect/validation/tests/unit/Rules/PrntTest.php b/vendor/respect/validation/tests/unit/Rules/PrntTest.php
index c125f505a796ada58e58236e654333c841f7ea77..c11ec7ebec5049870bab879c7156981378e2c31f 100644
--- a/vendor/respect/validation/tests/unit/Rules/PrntTest.php
+++ b/vendor/respect/validation/tests/unit/Rules/PrntTest.php
@@ -11,12 +11,14 @@
 
 namespace Respect\Validation\Rules;
 
+use Respect\Validation\TestCase;
+
 /**
  * @group  rule
  * @covers Respect\Validation\Rules\Prnt
  * @covers Respect\Validation\Exceptions\PrntException
  */
-class PrntTest extends \PHPUnit_Framework_TestCase
+class PrntTest extends TestCase
 {
     /**
      * @dataProvider providerForValidPrint
diff --git a/vendor/respect/validation/tests/unit/Rules/PunctTest.php b/vendor/respect/validation/tests/unit/Rules/PunctTest.php
index 1875bc0f48f0ad0fa62c37c67e07e65b0d22df9c..a5d19c2fdacde391b6bd337df237cb1a5cb2268b 100644
--- a/vendor/respect/validation/tests/unit/Rules/PunctTest.php
+++ b/vendor/respect/validation/tests/unit/Rules/PunctTest.php
@@ -11,12 +11,14 @@
 
 namespace Respect\Validation\Rules;
 
+use Respect\Validation\TestCase;
+
 /**
  * @group  rule
  * @covers Respect\Validation\Rules\Punct
  * @covers Respect\Validation\Exceptions\PunctException
  */
-class PunctTest extends \PHPUnit_Framework_TestCase
+class PunctTest extends TestCase
 {
     /**
      * @dataProvider providerForValidPunct
diff --git a/vendor/respect/validation/tests/unit/Rules/ReadableTest.php b/vendor/respect/validation/tests/unit/Rules/ReadableTest.php
index 577c3af9522fe72fc5def618f06e3ae55b097c52..8acff9a80ab64aa9235ad70950a85472bbd35db2 100644
--- a/vendor/respect/validation/tests/unit/Rules/ReadableTest.php
+++ b/vendor/respect/validation/tests/unit/Rules/ReadableTest.php
@@ -11,6 +11,9 @@
 
 namespace Respect\Validation\Rules;
 
+use Respect\Validation\TestCase;
+use SplFileInfo;
+
 $GLOBALS['is_readable'] = null;
 
 function is_readable($readable)
@@ -29,7 +32,7 @@ function is_readable($readable)
  * @covers Respect\Validation\Rules\Readable
  * @covers Respect\Validation\Exceptions\ReadableException
  */
-class ReadableTest extends \PHPUnit_Framework_TestCase
+class ReadableTest extends TestCase
 {
     /**
      * @covers Respect\Validation\Rules\Readable::validate
@@ -61,10 +64,7 @@ class ReadableTest extends \PHPUnit_Framework_TestCase
     public function testShouldValidateObjects()
     {
         $rule = new Readable();
-        $object = $this->getMock('SplFileInfo', ['isReadable'], ['somefile.txt']);
-        $object->expects($this->once())
-                ->method('isReadable')
-                ->will($this->returnValue(true));
+        $object = new SplFileInfo('tests/fixtures/valid-image.gif');
 
         $this->assertTrue($rule->validate($object));
     }
diff --git a/vendor/respect/validation/tests/unit/Rules/ResourceTypeTest.php b/vendor/respect/validation/tests/unit/Rules/ResourceTypeTest.php
index 4380109cf42675032af0966d87ad9eede7be8416..8092c814263e48fee62a16b62ccf92c04fe4594d 100644
--- a/vendor/respect/validation/tests/unit/Rules/ResourceTypeTest.php
+++ b/vendor/respect/validation/tests/unit/Rules/ResourceTypeTest.php
@@ -11,12 +11,14 @@
 
 namespace Respect\Validation\Rules;
 
+use Respect\Validation\TestCase;
+
 /**
  * @group  rule
  * @covers Respect\Validation\Rules\ResourceType
  * @covers Respect\Validation\Exceptions\ResourceTypeException
  */
-class ResourceTypeTest extends \PHPUnit_Framework_TestCase
+class ResourceTypeTest extends TestCase
 {
     protected $rule;
 
@@ -65,7 +67,8 @@ class ResourceTypeTest extends \PHPUnit_Framework_TestCase
             ['String'],
             [123],
             [[]],
-            [function () {}],
+            [function () {
+            }],
             [new \stdClass()],
             [null],
         ];
diff --git a/vendor/respect/validation/tests/unit/Rules/RomanTest.php b/vendor/respect/validation/tests/unit/Rules/RomanTest.php
index ed068de4178ae8ec66a927e2752624859859d490..2b17d304bfe1bfe162a25386461d1d921a713b28 100644
--- a/vendor/respect/validation/tests/unit/Rules/RomanTest.php
+++ b/vendor/respect/validation/tests/unit/Rules/RomanTest.php
@@ -11,12 +11,14 @@
 
 namespace Respect\Validation\Rules;
 
+use Respect\Validation\TestCase;
+
 /**
  * @group  rule
  * @covers Respect\Validation\Rules\Roman
  * @covers Respect\Validation\Exceptions\RomanException
  */
-class RomanTest extends \PHPUnit_Framework_TestCase
+class RomanTest extends TestCase
 {
     protected $romanValidator;
 
diff --git a/vendor/respect/validation/tests/unit/Rules/ScalarValTest.php b/vendor/respect/validation/tests/unit/Rules/ScalarValTest.php
index 4c242712d8d90d0f44002890b31a45610d3f6c16..7062d68b7963a2b8886779f8e44dc2201d1d723d 100644
--- a/vendor/respect/validation/tests/unit/Rules/ScalarValTest.php
+++ b/vendor/respect/validation/tests/unit/Rules/ScalarValTest.php
@@ -11,12 +11,14 @@
 
 namespace Respect\Validation\Rules;
 
+use Respect\Validation\TestCase;
+
 /**
  * @group  rule
  * @covers Respect\Validation\Rules\ScalarVal
  * @covers Respect\Validation\Exceptions\ScalarValException
  */
-class ScalarValTest extends \PHPUnit_Framework_TestCase
+class ScalarValTest extends TestCase
 {
     protected $rule;
 
@@ -66,7 +68,8 @@ class ScalarValTest extends \PHPUnit_Framework_TestCase
     {
         return [
             [[]],
-            [function () {}],
+            [function () {
+            }],
             [new \stdClass()],
             [null],
             [tmpfile()],
diff --git a/vendor/respect/validation/tests/unit/Rules/SfTest.php b/vendor/respect/validation/tests/unit/Rules/SfTest.php
index 22e65980fbf2f488af7c1c73edc6c41065764eb2..451527ac99fcbcdad67de5da1312b3447b629242 100644
--- a/vendor/respect/validation/tests/unit/Rules/SfTest.php
+++ b/vendor/respect/validation/tests/unit/Rules/SfTest.php
@@ -11,6 +11,7 @@
 
 namespace Respect\Validation\Rules;
 
+use Respect\Validation\TestCase;
 use Respect\Validation\Validator as v;
 
 /**
@@ -18,7 +19,7 @@ use Respect\Validation\Validator as v;
  * @covers Respect\Validation\Rules\Sf
  * @covers Respect\Validation\Exceptions\SfException
  */
-class SfTest extends \PHPUnit_Framework_TestCase
+class SfTest extends TestCase
 {
     public function testValidationWithAnExistingValidationConstraint()
     {
diff --git a/vendor/respect/validation/tests/unit/Rules/SizeTest.php b/vendor/respect/validation/tests/unit/Rules/SizeTest.php
index 9818db41852b1a8c62659647247df1c85aab4033..21631a5c5781b5548314427dac157f624a1602cf 100644
--- a/vendor/respect/validation/tests/unit/Rules/SizeTest.php
+++ b/vendor/respect/validation/tests/unit/Rules/SizeTest.php
@@ -13,7 +13,7 @@ namespace Respect\Validation\Rules;
 
 use org\bovigo\vfs\content\LargeFileContent;
 use org\bovigo\vfs\vfsStream;
-use PHPUnit_Framework_TestCase;
+use Respect\Validation\TestCase;
 use SplFileInfo;
 
 /**
@@ -22,7 +22,7 @@ use SplFileInfo;
  * @covers Respect\Validation\Rules\Size
  * @covers Respect\Validation\Exceptions\SizeException
  */
-class SizeTest extends PHPUnit_Framework_TestCase
+class SizeTest extends TestCase
 {
     public function validSizeProvider()
     {
diff --git a/vendor/respect/validation/tests/unit/Rules/SlugTest.php b/vendor/respect/validation/tests/unit/Rules/SlugTest.php
index b0988835dc10b0cc422e5f0add9140dc6e2b8f0d..2d033bce8441f77fd72afa23d84a6a7c11217a88 100644
--- a/vendor/respect/validation/tests/unit/Rules/SlugTest.php
+++ b/vendor/respect/validation/tests/unit/Rules/SlugTest.php
@@ -11,11 +11,13 @@
 
 namespace Respect\Validation\Rules;
 
+use Respect\Validation\TestCase;
+
 /**
  * @group  rule
  * @covers Respect\Validation\Rules\Slug
  */
-class SlugTest extends \PHPUnit_Framework_TestCase
+class SlugTest extends TestCase
 {
     /**
      * @dataProvider providerValidSlug
diff --git a/vendor/respect/validation/tests/unit/Rules/SpaceTest.php b/vendor/respect/validation/tests/unit/Rules/SpaceTest.php
index 4a065936abd2e61acc38352037b4fb93c4d25b67..bd0d8729fc5ef0fa09bb8cc59a24f463ca154d0c 100644
--- a/vendor/respect/validation/tests/unit/Rules/SpaceTest.php
+++ b/vendor/respect/validation/tests/unit/Rules/SpaceTest.php
@@ -11,12 +11,14 @@
 
 namespace Respect\Validation\Rules;
 
+use Respect\Validation\TestCase;
+
 /**
  * @group  rule
  * @covers Respect\Validation\Rules\Space
  * @covers Respect\Validation\Exceptions\SpaceException
  */
-class SpaceTest extends \PHPUnit_Framework_TestCase
+class SpaceTest extends TestCase
 {
     /**
      * @dataProvider providerForValidSpace
diff --git a/vendor/respect/validation/tests/unit/Rules/StartsWithTest.php b/vendor/respect/validation/tests/unit/Rules/StartsWithTest.php
index f2f907efddd2b5ecc2f09384a68615f5aacab4bc..01aaf721b50cb9e66be9208c932900aa458d34b6 100644
--- a/vendor/respect/validation/tests/unit/Rules/StartsWithTest.php
+++ b/vendor/respect/validation/tests/unit/Rules/StartsWithTest.php
@@ -11,12 +11,14 @@
 
 namespace Respect\Validation\Rules;
 
+use Respect\Validation\TestCase;
+
 /**
  * @group  rule
  * @covers Respect\Validation\Rules\StartsWith
  * @covers Respect\Validation\Exceptions\StartsWithException
  */
-class StartsWithTest extends \PHPUnit_Framework_TestCase
+class StartsWithTest extends TestCase
 {
     /**
      * @dataProvider providerForStartsWith
diff --git a/vendor/respect/validation/tests/unit/Rules/StringTypeTest.php b/vendor/respect/validation/tests/unit/Rules/StringTypeTest.php
index b15e9f6b411609c2b5f27c51d7bbee3ca866fe95..021e8bd5ebb0f2878f09d7d5759a0fd866b6df84 100644
--- a/vendor/respect/validation/tests/unit/Rules/StringTypeTest.php
+++ b/vendor/respect/validation/tests/unit/Rules/StringTypeTest.php
@@ -11,12 +11,14 @@
 
 namespace Respect\Validation\Rules;
 
+use Respect\Validation\TestCase;
+
 /**
  * @group  rule
  * @covers Respect\Validation\Rules\StringType
  * @covers Respect\Validation\Exceptions\StringTypeException
  */
-class StringTypeTest extends \PHPUnit_Framework_TestCase
+class StringTypeTest extends TestCase
 {
     /**
      * @dataProvider providerForString
diff --git a/vendor/respect/validation/tests/unit/Rules/SubdivisionCodeTest.php b/vendor/respect/validation/tests/unit/Rules/SubdivisionCodeTest.php
index 76bdf67d7459cd4e76319ca76d2d75ada6731a49..ed372b75ff6f01c62384f104fe6774505825a4bc 100644
--- a/vendor/respect/validation/tests/unit/Rules/SubdivisionCodeTest.php
+++ b/vendor/respect/validation/tests/unit/Rules/SubdivisionCodeTest.php
@@ -11,13 +11,13 @@
 
 namespace Respect\Validation\Rules;
 
-use PHPUnit_Framework_TestCase;
+use Respect\Validation\TestCase;
 
 /**
  * @covers Respect\Validation\Rules\SubdivisionCode
  * @covers Respect\Validation\Exceptions\SubdivisionCodeException
  */
-class SubdivisionCodeTest extends PHPUnit_Framework_TestCase
+class SubdivisionCodeTest extends TestCase
 {
     /**
      * @expectedException Respect\Validation\Exceptions\ComponentException
diff --git a/vendor/respect/validation/tests/unit/Rules/SymbolicLinkTest.php b/vendor/respect/validation/tests/unit/Rules/SymbolicLinkTest.php
index 8ba867a1c7f0f0a3871234aa2f003e47bcbd03ce..21cd75bc019566fc64b0e201cabc723bca9189b4 100644
--- a/vendor/respect/validation/tests/unit/Rules/SymbolicLinkTest.php
+++ b/vendor/respect/validation/tests/unit/Rules/SymbolicLinkTest.php
@@ -11,6 +11,9 @@
 
 namespace Respect\Validation\Rules;
 
+use Respect\Validation\TestCase;
+use SplFileInfo;
+
 $GLOBALS['is_link'] = null;
 
 function is_link($link)
@@ -29,7 +32,7 @@ function is_link($link)
  * @covers Respect\Validation\Rules\SymbolicLink
  * @covers Respect\Validation\Exceptions\SymbolicLinkException
  */
-class SymbolicLinkTest extends \PHPUnit_Framework_TestCase
+class SymbolicLinkTest extends TestCase
 {
     /**
      * @covers Respect\Validation\Rules\SymbolicLink::validate
@@ -61,10 +64,7 @@ class SymbolicLinkTest extends \PHPUnit_Framework_TestCase
     public function testShouldValidateObjects()
     {
         $rule = new SymbolicLink();
-        $object = $this->getMock('SplFileInfo', ['isLink'], ['somelink.lnk']);
-        $object->expects($this->once())
-                ->method('isLink')
-                ->will($this->returnValue(true));
+        $object = new SplFileInfo('tests/fixtures/symbolic-link');
 
         $this->assertTrue($rule->validate($object));
     }
diff --git a/vendor/respect/validation/tests/unit/Rules/TldTest.php b/vendor/respect/validation/tests/unit/Rules/TldTest.php
index c60c48fbbdb71257e3fc19cb502ebe54795979c2..3408822cd570a60e5f423c2c5513afe78b4fa355 100644
--- a/vendor/respect/validation/tests/unit/Rules/TldTest.php
+++ b/vendor/respect/validation/tests/unit/Rules/TldTest.php
@@ -11,11 +11,13 @@
 
 namespace Respect\Validation\Rules;
 
+use Respect\Validation\TestCase;
+
 /**
  * @group  rule
  * @covers Respect\Validation\Rules\Tld
  */
-class TldTest extends \PHPUnit_Framework_TestCase
+class TldTest extends TestCase
 {
     public function providerForValidTld()
     {
diff --git a/vendor/respect/validation/tests/unit/Rules/TrueValTest.php b/vendor/respect/validation/tests/unit/Rules/TrueValTest.php
index 67b3386ce23218dc9622e94c1132806d3b905a2c..1a6ba82a682aea3b67f61836fa62ef1361c9a6b7 100644
--- a/vendor/respect/validation/tests/unit/Rules/TrueValTest.php
+++ b/vendor/respect/validation/tests/unit/Rules/TrueValTest.php
@@ -11,12 +11,14 @@
 
 namespace Respect\Validation\Rules;
 
+use Respect\Validation\TestCase;
+
 /**
  * @group  rule
  * @covers Respect\Validation\Rules\TrueVal
  * @covers Respect\Validation\Exceptions\TrueValException
  */
-class TrueValTest extends \PHPUnit_Framework_TestCase
+class TrueValTest extends TestCase
 {
     /**
      * @dataProvider validTrueProvider
diff --git a/vendor/respect/validation/tests/unit/Rules/TypeTest.php b/vendor/respect/validation/tests/unit/Rules/TypeTest.php
index 40b3c77916b015ee0b420d5f98cddb0c4d355f2c..8c547d362d9f8f5942db3df2b314890b7cb82f9b 100644
--- a/vendor/respect/validation/tests/unit/Rules/TypeTest.php
+++ b/vendor/respect/validation/tests/unit/Rules/TypeTest.php
@@ -11,6 +11,7 @@
 
 namespace Respect\Validation\Rules;
 
+use Respect\Validation\TestCase;
 use stdClass;
 
 /**
@@ -18,7 +19,7 @@ use stdClass;
  * @covers Respect\Validation\Rules\Type
  * @covers Respect\Validation\Exceptions\TypeException
  */
-class TypeTest extends \PHPUnit_Framework_TestCase
+class TypeTest extends TestCase
 {
     public function testShouldDefineTypeOnConstructor()
     {
@@ -80,7 +81,8 @@ class TypeTest extends \PHPUnit_Framework_TestCase
             ['array', []],
             ['bool', true],
             ['boolean', false],
-            ['callable', function () {}],
+            ['callable', function () {
+            }],
             ['double', 0.8],
             ['float', 1.0],
             ['int', 42],
diff --git a/vendor/respect/validation/tests/unit/Rules/UploadedTest.php b/vendor/respect/validation/tests/unit/Rules/UploadedTest.php
index 2a34f3a8cbddc07425e37e6c12ca6c1ca2dcc8bc..8c916ab80ab383229b4950f1c870ed41ec477d22 100644
--- a/vendor/respect/validation/tests/unit/Rules/UploadedTest.php
+++ b/vendor/respect/validation/tests/unit/Rules/UploadedTest.php
@@ -11,6 +11,8 @@
 
 namespace Respect\Validation\Rules;
 
+use Respect\Validation\TestCase;
+
 $GLOBALS['is_uploaded_file'] = null;
 
 function is_uploaded_file($uploaded)
@@ -29,7 +31,7 @@ function is_uploaded_file($uploaded)
  * @covers Respect\Validation\Rules\Uploaded
  * @covers Respect\Validation\Exceptions\UploadedException
  */
-class UploadedTest extends \PHPUnit_Framework_TestCase
+class UploadedTest extends TestCase
 {
     /**
      * @covers Respect\Validation\Rules\Uploaded::validate
diff --git a/vendor/respect/validation/tests/unit/Rules/UppercaseTest.php b/vendor/respect/validation/tests/unit/Rules/UppercaseTest.php
index afc8c5a988164158532ae9fcdb8c12ea33a5e13a..f3123957daac9d880cff8df14a66a7ad1d97e3fc 100644
--- a/vendor/respect/validation/tests/unit/Rules/UppercaseTest.php
+++ b/vendor/respect/validation/tests/unit/Rules/UppercaseTest.php
@@ -11,12 +11,14 @@
 
 namespace Respect\Validation\Rules;
 
+use Respect\Validation\TestCase;
+
 /**
  * @group  rule
  * @covers Respect\Validation\Rules\Uppercase
  * @covers Respect\Validation\Exceptions\UppercaseException
  */
-class UppercaseTest extends \PHPUnit_Framework_TestCase
+class UppercaseTest extends TestCase
 {
     /**
      * @dataProvider providerForValidUppercase
diff --git a/vendor/respect/validation/tests/unit/Rules/UrlTest.php b/vendor/respect/validation/tests/unit/Rules/UrlTest.php
index b0a8cb3b22f2543b48b4e91b3f38228667073ed4..d5067a1469945968d5c14ecada32a619b07084b6 100644
--- a/vendor/respect/validation/tests/unit/Rules/UrlTest.php
+++ b/vendor/respect/validation/tests/unit/Rules/UrlTest.php
@@ -11,12 +11,14 @@
 
 namespace Respect\Validation\Rules;
 
+use Respect\Validation\TestCase;
+
 /**
  * @group  rule
  * @covers Respect\Validation\Rules\Url
  * @covers Respect\Validation\Exceptions\UrlException
  */
-class UrlTest extends \PHPUnit_Framework_TestCase
+class UrlTest extends TestCase
 {
     /**
      * @dataProvider providerForValidUrl
diff --git a/vendor/respect/validation/tests/unit/Rules/VersionTest.php b/vendor/respect/validation/tests/unit/Rules/VersionTest.php
index 72d6989ccf6275e15cd97a8f3c2be372d50d8e5e..859e0401e76017224da3576badad7c65dade74e7 100644
--- a/vendor/respect/validation/tests/unit/Rules/VersionTest.php
+++ b/vendor/respect/validation/tests/unit/Rules/VersionTest.php
@@ -11,12 +11,14 @@
 
 namespace Respect\Validation\Rules;
 
+use Respect\Validation\TestCase;
+
 /**
  * @group  rule
  * @covers Respect\Validation\Rules\Version
  * @covers Respect\Validation\Exceptions\VersionException
  */
-class VersionTest extends \PHPUnit_Framework_TestCase
+class VersionTest extends TestCase
 {
     /**
      * @dataProvider providerForValidVersion
diff --git a/vendor/respect/validation/tests/unit/Rules/VideoUrlTest.php b/vendor/respect/validation/tests/unit/Rules/VideoUrlTest.php
index 3d627bf570c388553c31a139ce76b91e1a134d54..fe195afdc5856665249db834eb54fb85be505516 100644
--- a/vendor/respect/validation/tests/unit/Rules/VideoUrlTest.php
+++ b/vendor/respect/validation/tests/unit/Rules/VideoUrlTest.php
@@ -11,12 +11,14 @@
 
 namespace Respect\Validation\Rules;
 
+use Respect\Validation\TestCase;
+
 /**
  * @group  rule
  * @covers Respect\Validation\Rules\VideoUrl
  * @covers Respect\Validation\Exceptions\VideoUrlException
  */
-class VideoUrlTest extends \PHPUnit_Framework_TestCase
+class VideoUrlTest extends TestCase
 {
     /**
      * @expectedException Respect\Validation\Exceptions\ComponentException
diff --git a/vendor/respect/validation/tests/unit/Rules/VowelTest.php b/vendor/respect/validation/tests/unit/Rules/VowelTest.php
index 3dea2190a7ede40ebcd347dbab135238aa3f9e63..ffe1eb5ad8c04e236bf49a725199332ea02d296b 100644
--- a/vendor/respect/validation/tests/unit/Rules/VowelTest.php
+++ b/vendor/respect/validation/tests/unit/Rules/VowelTest.php
@@ -11,12 +11,14 @@
 
 namespace Respect\Validation\Rules;
 
+use Respect\Validation\TestCase;
+
 /**
  * @group  rule
  * @covers Respect\Validation\Rules\Vowel
  * @covers Respect\Validation\Exceptions\VowelException
  */
-class VowelTest extends \PHPUnit_Framework_TestCase
+class VowelTest extends TestCase
 {
     /**
      * @dataProvider providerForValidVowels
diff --git a/vendor/respect/validation/tests/unit/Rules/WritableTest.php b/vendor/respect/validation/tests/unit/Rules/WritableTest.php
index f87fe80ff64b3f4ebe679648050e79db6fd1fe1f..c001a173d22217cbab02823b070a00c465b30aa4 100644
--- a/vendor/respect/validation/tests/unit/Rules/WritableTest.php
+++ b/vendor/respect/validation/tests/unit/Rules/WritableTest.php
@@ -11,6 +11,9 @@
 
 namespace Respect\Validation\Rules;
 
+use Respect\Validation\TestCase;
+use SplFileInfo;
+
 $GLOBALS['is_writable'] = null;
 
 function is_writable($writable)
@@ -29,7 +32,7 @@ function is_writable($writable)
  * @covers Respect\Validation\Rules\Writable
  * @covers Respect\Validation\Exceptions\WritableException
  */
-class WritableTest extends \PHPUnit_Framework_TestCase
+class WritableTest extends TestCase
 {
     /**
      * @covers Respect\Validation\Rules\Writable::validate
@@ -61,10 +64,7 @@ class WritableTest extends \PHPUnit_Framework_TestCase
     public function testShouldValidateObjects()
     {
         $rule = new Writable();
-        $object = $this->getMock('SplFileInfo', ['isWritable'], ['somefile.txt']);
-        $object->expects($this->once())
-                ->method('isWritable')
-                ->will($this->returnValue(true));
+        $object = new SplFileInfo('tests/fixtures/valid-image.jpg');
 
         $this->assertTrue($rule->validate($object));
     }
diff --git a/vendor/respect/validation/tests/unit/Rules/XdigitTest.php b/vendor/respect/validation/tests/unit/Rules/XdigitTest.php
index 1d4d8165bee0324094665a874bc07800e60d7ff2..a77fe33112e2e85a13689f5a273c9aa38ed4591f 100644
--- a/vendor/respect/validation/tests/unit/Rules/XdigitTest.php
+++ b/vendor/respect/validation/tests/unit/Rules/XdigitTest.php
@@ -11,12 +11,14 @@
 
 namespace Respect\Validation\Rules;
 
+use Respect\Validation\TestCase;
+
 /**
  * @group  rule
  * @covers Respect\Validation\Rules\Xdigit
  * @covers Respect\Validation\Exceptions\XdigitException
  */
-class XdigitTest extends \PHPUnit_Framework_TestCase
+class XdigitTest extends TestCase
 {
     protected $xdigitsValidator;
 
diff --git a/vendor/respect/validation/tests/unit/Rules/YesTest.php b/vendor/respect/validation/tests/unit/Rules/YesTest.php
index f0b631c458db7922dddb24538c4a8b27c6b6b342..12c9817c6ec4e3e9867c59173482aea69b843934 100644
--- a/vendor/respect/validation/tests/unit/Rules/YesTest.php
+++ b/vendor/respect/validation/tests/unit/Rules/YesTest.php
@@ -11,12 +11,14 @@
 
 namespace Respect\Validation\Rules;
 
+use Respect\Validation\TestCase;
+
 /**
  * @group  rule
  * @covers Respect\Validation\Rules\Yes
  * @covers Respect\Validation\Exceptions\YesException
  */
-class YesTest extends \PHPUnit_Framework_TestCase
+class YesTest extends TestCase
 {
     public function testShouldUseDefaultPattern()
     {
diff --git a/vendor/respect/validation/tests/unit/Rules/ZendTest.php b/vendor/respect/validation/tests/unit/Rules/ZendTest.php
index 1a876c23efcf9aa9ee2cbf52a077e0c7357c5cad..5bc7224daf52187294c71bceecfed14bfb1dc747 100644
--- a/vendor/respect/validation/tests/unit/Rules/ZendTest.php
+++ b/vendor/respect/validation/tests/unit/Rules/ZendTest.php
@@ -11,6 +11,7 @@
 
 namespace Respect\Validation\Rules;
 
+use Respect\Validation\TestCase;
 use DateTime;
 
 /**
@@ -18,7 +19,7 @@ use DateTime;
  * @covers Respect\Validation\Rules\Zend
  * @covers Respect\Validation\Exceptions\ZendException
  */
-class ZendTest extends \PHPUnit_Framework_TestCase
+class ZendTest extends TestCase
 {
     public function testConstructorWithValidatorName()
     {
diff --git a/vendor/respect/validation/tests/unit/ValidatorTest.php b/vendor/respect/validation/tests/unit/ValidatorTest.php
index 1f5e0847b6c2cc3a4e35630503a9a471936c3506..cd263c40a6fe21dc081b74e2f9ef28c10c3de3f0 100644
--- a/vendor/respect/validation/tests/unit/ValidatorTest.php
+++ b/vendor/respect/validation/tests/unit/ValidatorTest.php
@@ -11,7 +11,7 @@
 
 namespace Respect\Validation;
 
-class ValidatorTest extends \PHPUnit_Framework_TestCase
+class ValidatorTest extends TestCase
 {
     public function testStaticCreateShouldReturnNewValidator()
     {
diff --git a/vendor/sebastian/cli-parser/ChangeLog.md b/vendor/sebastian/cli-parser/ChangeLog.md
new file mode 100644
index 0000000000000000000000000000000000000000..9431ec5943c969a4c2a79a6869850f79a7d29c82
--- /dev/null
+++ b/vendor/sebastian/cli-parser/ChangeLog.md
@@ -0,0 +1,15 @@
+# ChangeLog
+
+All notable changes are documented in this file using the [Keep a CHANGELOG](https://keepachangelog.com/) principles.
+
+## [1.0.1] - 2020-09-28
+
+### Changed
+
+* Changed PHP version constraint in `composer.json` from `^7.3 || ^8.0` to `>=7.3`
+
+## [1.0.0] - 2020-08-12
+
+* Initial release
+
+[1.0.0]: https://github.com/sebastianbergmann/cli-parser/compare/bb7bb3297957927962b0a3335befe7b66f7462e9...1.0.0
diff --git a/vendor/sebastian/cli-parser/LICENSE b/vendor/sebastian/cli-parser/LICENSE
new file mode 100644
index 0000000000000000000000000000000000000000..0e33c05910657159c8ec29da83065aa00745695d
--- /dev/null
+++ b/vendor/sebastian/cli-parser/LICENSE
@@ -0,0 +1,33 @@
+sebastian/cli-parser
+
+Copyright (c) 2020, Sebastian Bergmann <sebastian@phpunit.de>.
+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 Sebastian Bergmann nor the names of his
+   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/sebastian/cli-parser/README.md b/vendor/sebastian/cli-parser/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..39c17a72c52a3c517768ede3a5db4e4cecb6590b
--- /dev/null
+++ b/vendor/sebastian/cli-parser/README.md
@@ -0,0 +1,17 @@
+# sebastian/cli-parser
+
+Library for parsing `$_SERVER['argv']`, extracted from `phpunit/phpunit`.
+
+## Installation
+
+You can add this library as a local, per-project dependency to your project using [Composer](https://getcomposer.org/):
+
+```
+composer require sebastian/cli-parser
+```
+
+If you only need this library during development, for instance to run your project's test suite, then you should add it as a development-time dependency:
+
+```
+composer require --dev sebastian/cli-parser
+```
diff --git a/vendor/sebastian/cli-parser/composer.json b/vendor/sebastian/cli-parser/composer.json
new file mode 100644
index 0000000000000000000000000000000000000000..34c376f91b5f0540cfa9ecc1de4136ebd8b204ee
--- /dev/null
+++ b/vendor/sebastian/cli-parser/composer.json
@@ -0,0 +1,41 @@
+{
+    "name": "sebastian/cli-parser",
+    "description": "Library for parsing CLI options",
+    "type": "library",
+    "homepage": "https://github.com/sebastianbergmann/cli-parser",
+    "license": "BSD-3-Clause",
+    "authors": [
+        {
+            "name": "Sebastian Bergmann",
+            "email": "sebastian@phpunit.de",
+            "role": "lead"
+        }
+    ],
+    "support": {
+        "issues": "https://github.com/sebastianbergmann/cli-parser/issues"
+    },
+    "prefer-stable": true,
+    "require": {
+        "php": ">=7.3"
+    },
+    "require-dev": {
+        "phpunit/phpunit": "^9.3"
+    },
+    "config": {
+        "platform": {
+            "php": "7.3.0"
+        },
+        "optimize-autoloader": true,
+        "sort-packages": true
+    },
+    "autoload": {
+        "classmap": [
+            "src/"
+        ]
+    },
+    "extra": {
+        "branch-alias": {
+            "dev-master": "1.0-dev"
+        }
+    }
+}
diff --git a/vendor/sebastian/cli-parser/infection.json b/vendor/sebastian/cli-parser/infection.json
new file mode 100644
index 0000000000000000000000000000000000000000..09546514f216097304c01ff8d509c7bb4dcadf13
--- /dev/null
+++ b/vendor/sebastian/cli-parser/infection.json
@@ -0,0 +1,12 @@
+{
+    "source": {
+        "directories": [
+            "src"
+        ]
+    },
+    "mutators": {
+        "@default": true
+    },
+    "minMsi": 100,
+    "minCoveredMsi": 100
+}
diff --git a/vendor/sebastian/cli-parser/src/Parser.php b/vendor/sebastian/cli-parser/src/Parser.php
new file mode 100644
index 0000000000000000000000000000000000000000..a4f728bc6786ce4f48323c87d533dd107c4b5624
--- /dev/null
+++ b/vendor/sebastian/cli-parser/src/Parser.php
@@ -0,0 +1,204 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of sebastian/cli-parser.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\CliParser;
+
+use function array_map;
+use function array_merge;
+use function array_shift;
+use function array_slice;
+use function assert;
+use function count;
+use function current;
+use function explode;
+use function is_array;
+use function is_int;
+use function is_string;
+use function key;
+use function next;
+use function preg_replace;
+use function reset;
+use function sort;
+use function strlen;
+use function strpos;
+use function strstr;
+use function substr;
+
+final class Parser
+{
+    /**
+     * @psalm-param list<string> $argv
+     * @psalm-param list<string> $longOptions
+     *
+     * @throws AmbiguousOptionException
+     * @throws RequiredOptionArgumentMissingException
+     * @throws OptionDoesNotAllowArgumentException
+     * @throws UnknownOptionException
+     */
+    public function parse(array $argv, string $shortOptions, array $longOptions = null): array
+    {
+        if (empty($argv)) {
+            return [[], []];
+        }
+
+        $options     = [];
+        $nonOptions  = [];
+
+        if ($longOptions) {
+            sort($longOptions);
+        }
+
+        if (isset($argv[0][0]) && $argv[0][0] !== '-') {
+            array_shift($argv);
+        }
+
+        reset($argv);
+
+        $argv = array_map('trim', $argv);
+
+        while (false !== $arg = current($argv)) {
+            $i = key($argv);
+
+            assert(is_int($i));
+
+            next($argv);
+
+            if ($arg === '') {
+                continue;
+            }
+
+            if ($arg === '--') {
+                $nonOptions = array_merge($nonOptions, array_slice($argv, $i + 1));
+
+                break;
+            }
+
+            if ($arg[0] !== '-' || (strlen($arg) > 1 && $arg[1] === '-' && !$longOptions)) {
+                $nonOptions[] = $arg;
+
+                continue;
+            }
+
+            if (strlen($arg) > 1 && $arg[1] === '-' && is_array($longOptions)) {
+                $this->parseLongOption(
+                    substr($arg, 2),
+                    $longOptions,
+                    $options,
+                    $argv
+                );
+            } else {
+                $this->parseShortOption(
+                    substr($arg, 1),
+                    $shortOptions,
+                    $options,
+                    $argv
+                );
+            }
+        }
+
+        return [$options, $nonOptions];
+    }
+
+    /**
+     * @throws RequiredOptionArgumentMissingException
+     */
+    private function parseShortOption(string $arg, string $shortOptions, array &$opts, array &$args): void
+    {
+        $argLength = strlen($arg);
+
+        for ($i = 0; $i < $argLength; $i++) {
+            $option         = $arg[$i];
+            $optionArgument = null;
+
+            if ($arg[$i] === ':' || ($spec = strstr($shortOptions, $option)) === false) {
+                throw new UnknownOptionException('-' . $option);
+            }
+
+            assert(is_string($spec));
+
+            if (strlen($spec) > 1 && $spec[1] === ':') {
+                if ($i + 1 < $argLength) {
+                    $opts[] = [$option, substr($arg, $i + 1)];
+
+                    break;
+                }
+
+                if (!(strlen($spec) > 2 && $spec[2] === ':')) {
+                    $optionArgument = current($args);
+
+                    if (!$optionArgument) {
+                        throw new RequiredOptionArgumentMissingException('-' . $option);
+                    }
+
+                    assert(is_string($optionArgument));
+
+                    next($args);
+                }
+            }
+
+            $opts[] = [$option, $optionArgument];
+        }
+    }
+
+    /**
+     * @psalm-param list<string> $longOptions
+     *
+     * @throws AmbiguousOptionException
+     * @throws RequiredOptionArgumentMissingException
+     * @throws OptionDoesNotAllowArgumentException
+     * @throws UnknownOptionException
+     */
+    private function parseLongOption(string $arg, array $longOptions, array &$opts, array &$args): void
+    {
+        $count          = count($longOptions);
+        $list           = explode('=', $arg);
+        $option         = $list[0];
+        $optionArgument = null;
+
+        if (count($list) > 1) {
+            $optionArgument = $list[1];
+        }
+
+        $optionLength = strlen($option);
+
+        foreach ($longOptions as $i => $longOption) {
+            $opt_start = substr($longOption, 0, $optionLength);
+
+            if ($opt_start !== $option) {
+                continue;
+            }
+
+            $opt_rest = substr($longOption, $optionLength);
+
+            if ($opt_rest !== '' && $i + 1 < $count && $option[0] !== '=' && strpos($longOptions[$i + 1], $option) === 0) {
+                throw new AmbiguousOptionException('--' . $option);
+            }
+
+            if (substr($longOption, -1) === '=') {
+                /* @noinspection StrlenInEmptyStringCheckContextInspection */
+                if (substr($longOption, -2) !== '==' && !strlen((string) $optionArgument)) {
+                    if (false === $optionArgument = current($args)) {
+                        throw new RequiredOptionArgumentMissingException('--' . $option);
+                    }
+
+                    next($args);
+                }
+            } elseif ($optionArgument) {
+                throw new OptionDoesNotAllowArgumentException('--' . $option);
+            }
+
+            $fullOption = '--' . preg_replace('/={1,2}$/', '', $longOption);
+            $opts[]     = [$fullOption, $optionArgument];
+
+            return;
+        }
+
+        throw new UnknownOptionException('--' . $option);
+    }
+}
diff --git a/vendor/sebastian/cli-parser/src/exceptions/AmbiguousOptionException.php b/vendor/sebastian/cli-parser/src/exceptions/AmbiguousOptionException.php
new file mode 100644
index 0000000000000000000000000000000000000000..a99f63697cc81ad6c2f6bbd73c02ce1da2a97c14
--- /dev/null
+++ b/vendor/sebastian/cli-parser/src/exceptions/AmbiguousOptionException.php
@@ -0,0 +1,26 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of sebastian/cli-parser.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\CliParser;
+
+use function sprintf;
+use RuntimeException;
+
+final class AmbiguousOptionException extends RuntimeException implements Exception
+{
+    public function __construct(string $option)
+    {
+        parent::__construct(
+            sprintf(
+                'Option "%s" is ambiguous',
+                $option
+            )
+        );
+    }
+}
diff --git a/vendor/sebastian/cli-parser/src/exceptions/Exception.php b/vendor/sebastian/cli-parser/src/exceptions/Exception.php
new file mode 100644
index 0000000000000000000000000000000000000000..f35ad2457e3a80811bce99290a6cc663ffd5f352
--- /dev/null
+++ b/vendor/sebastian/cli-parser/src/exceptions/Exception.php
@@ -0,0 +1,16 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of sebastian/cli-parser.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\CliParser;
+
+use Throwable;
+
+interface Exception extends Throwable
+{
+}
diff --git a/vendor/sebastian/cli-parser/src/exceptions/OptionDoesNotAllowArgumentException.php b/vendor/sebastian/cli-parser/src/exceptions/OptionDoesNotAllowArgumentException.php
new file mode 100644
index 0000000000000000000000000000000000000000..0aad29ac036d01886345771aa6735d49c7a25fa8
--- /dev/null
+++ b/vendor/sebastian/cli-parser/src/exceptions/OptionDoesNotAllowArgumentException.php
@@ -0,0 +1,26 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of sebastian/cli-parser.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\CliParser;
+
+use function sprintf;
+use RuntimeException;
+
+final class OptionDoesNotAllowArgumentException extends RuntimeException implements Exception
+{
+    public function __construct(string $option)
+    {
+        parent::__construct(
+            sprintf(
+                'Option "%s" does not allow an argument',
+                $option
+            )
+        );
+    }
+}
diff --git a/vendor/sebastian/cli-parser/src/exceptions/RequiredOptionArgumentMissingException.php b/vendor/sebastian/cli-parser/src/exceptions/RequiredOptionArgumentMissingException.php
new file mode 100644
index 0000000000000000000000000000000000000000..d2a930b620263dee2b22723b66364b4f99e0a520
--- /dev/null
+++ b/vendor/sebastian/cli-parser/src/exceptions/RequiredOptionArgumentMissingException.php
@@ -0,0 +1,26 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of sebastian/cli-parser.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\CliParser;
+
+use function sprintf;
+use RuntimeException;
+
+final class RequiredOptionArgumentMissingException extends RuntimeException implements Exception
+{
+    public function __construct(string $option)
+    {
+        parent::__construct(
+            sprintf(
+                'Required argument for option "%s" is missing',
+                $option
+            )
+        );
+    }
+}
diff --git a/vendor/sebastian/cli-parser/src/exceptions/UnknownOptionException.php b/vendor/sebastian/cli-parser/src/exceptions/UnknownOptionException.php
new file mode 100644
index 0000000000000000000000000000000000000000..e98d9fd0209dc44a8be26a9dfd24e9275abaad21
--- /dev/null
+++ b/vendor/sebastian/cli-parser/src/exceptions/UnknownOptionException.php
@@ -0,0 +1,26 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of sebastian/cli-parser.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\CliParser;
+
+use function sprintf;
+use RuntimeException;
+
+final class UnknownOptionException extends RuntimeException implements Exception
+{
+    public function __construct(string $option)
+    {
+        parent::__construct(
+            sprintf(
+                'Unknown option "%s"',
+                $option
+            )
+        );
+    }
+}
diff --git a/vendor/sebastian/code-unit-reverse-lookup/ChangeLog.md b/vendor/sebastian/code-unit-reverse-lookup/ChangeLog.md
new file mode 100644
index 0000000000000000000000000000000000000000..43a5db90d8ff7ad3e5f81d6028985c4dad758ea5
--- /dev/null
+++ b/vendor/sebastian/code-unit-reverse-lookup/ChangeLog.md
@@ -0,0 +1,38 @@
+# Change Log
+
+All notable changes to `sebastianbergmann/code-unit-reverse-lookup` are documented in this file using the [Keep a CHANGELOG](http://keepachangelog.com/) principles.
+
+## [2.0.3] - 2020-09-28
+
+### Changed
+
+* Changed PHP version constraint in `composer.json` from `^7.3 || ^8.0` to `>=7.3`
+
+## [2.0.2] - 2020-06-26
+
+### Added
+
+* This component is now supported on PHP 8
+
+## [2.0.1] - 2020-06-15
+
+### Changed
+
+* Tests etc. are now ignored for archive exports
+
+## 2.0.0 - 2020-02-07
+
+### Removed
+
+* This component is no longer supported on PHP 5.6, PHP 7.0, PHP 7.1, and PHP 7.2
+
+## 1.0.0 - 2016-02-13
+
+### Added
+
+* Initial release
+
+[2.0.3]: https://github.com/sebastianbergmann/code-unit-reverse-lookup/compare/2.0.2...2.0.3
+[2.0.2]: https://github.com/sebastianbergmann/code-unit-reverse-lookup/compare/2.0.1...2.0.2
+[2.0.1]: https://github.com/sebastianbergmann/code-unit-reverse-lookup/compare/2.0.0...2.0.1
+[2.0.0]: https://github.com/sebastianbergmann/code-unit-reverse-lookup/compare/1.0.0...2.0.0
diff --git a/vendor/sebastian/code-unit-reverse-lookup/LICENSE b/vendor/sebastian/code-unit-reverse-lookup/LICENSE
new file mode 100644
index 0000000000000000000000000000000000000000..dc4bf70199449b5ab1ca0fa39b1af3927c791e9c
--- /dev/null
+++ b/vendor/sebastian/code-unit-reverse-lookup/LICENSE
@@ -0,0 +1,33 @@
+code-unit-reverse-lookup
+
+Copyright (c) 2016-2020, Sebastian Bergmann <sebastian@phpunit.de>.
+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 Sebastian Bergmann nor the names of his
+   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/sebastian/code-unit-reverse-lookup/README.md b/vendor/sebastian/code-unit-reverse-lookup/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..1c0ca235ef454d8f47cb3fa730fbad716231b98a
--- /dev/null
+++ b/vendor/sebastian/code-unit-reverse-lookup/README.md
@@ -0,0 +1,20 @@
+# sebastian/code-unit-reverse-lookup
+
+[![CI Status](https://github.com/sebastianbergmann/code-unit-reverse-lookup/workflows/CI/badge.svg)](https://github.com/sebastianbergmann/code-unit-reverse-lookup/actions)
+[![Type Coverage](https://shepherd.dev/github/sebastianbergmann/code-unit-reverse-lookup/coverage.svg)](https://shepherd.dev/github/sebastianbergmann/code-unit-reverse-lookup)
+
+Looks up which function or method a line of code belongs to.
+
+## Installation
+
+You can add this library as a local, per-project dependency to your project using [Composer](https://getcomposer.org/):
+
+```
+composer require sebastian/code-unit-reverse-lookup
+```
+
+If you only need this library during development, for instance to run your project's test suite, then you should add it as a development-time dependency:
+
+```
+composer require --dev sebastian/code-unit-reverse-lookup
+```
diff --git a/vendor/sebastian/code-unit-reverse-lookup/composer.json b/vendor/sebastian/code-unit-reverse-lookup/composer.json
new file mode 100644
index 0000000000000000000000000000000000000000..cff96167adeb88c49af1a164ee6c569cd16da7af
--- /dev/null
+++ b/vendor/sebastian/code-unit-reverse-lookup/composer.json
@@ -0,0 +1,36 @@
+{
+    "name": "sebastian/code-unit-reverse-lookup",
+    "description": "Looks up which function or method a line of code belongs to",
+    "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/",
+    "license": "BSD-3-Clause",
+    "authors": [
+        {
+            "name": "Sebastian Bergmann",
+            "email": "sebastian@phpunit.de"
+        }
+    ],
+    "prefer-stable": true,
+    "config": {
+        "platform": {
+            "php": "7.3.0"
+        },
+        "optimize-autoloader": true,
+        "sort-packages": true
+    },
+    "require": {
+        "php": ">=7.3"
+    },
+    "require-dev": {
+        "phpunit/phpunit": "^9.3"
+    },
+    "autoload": {
+        "classmap": [
+            "src/"
+        ]
+    },
+    "extra": {
+        "branch-alias": {
+            "dev-master": "2.0-dev"
+        }
+    }
+}
diff --git a/vendor/sebastian/code-unit-reverse-lookup/src/Wizard.php b/vendor/sebastian/code-unit-reverse-lookup/src/Wizard.php
new file mode 100644
index 0000000000000000000000000000000000000000..35de53981d86f53595f22fbcdda3b1dbd0afea55
--- /dev/null
+++ b/vendor/sebastian/code-unit-reverse-lookup/src/Wizard.php
@@ -0,0 +1,125 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of sebastian/code-unit-reverse-lookup.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\CodeUnitReverseLookup;
+
+use function array_merge;
+use function assert;
+use function get_declared_classes;
+use function get_declared_traits;
+use function get_defined_functions;
+use function is_array;
+use function range;
+use ReflectionClass;
+use ReflectionFunction;
+use ReflectionFunctionAbstract;
+use ReflectionMethod;
+
+/**
+ * @since Class available since Release 1.0.0
+ */
+class Wizard
+{
+    /**
+     * @var array
+     */
+    private $lookupTable = [];
+
+    /**
+     * @var array
+     */
+    private $processedClasses = [];
+
+    /**
+     * @var array
+     */
+    private $processedFunctions = [];
+
+    /**
+     * @param string $filename
+     * @param int    $lineNumber
+     *
+     * @return string
+     */
+    public function lookup($filename, $lineNumber)
+    {
+        if (!isset($this->lookupTable[$filename][$lineNumber])) {
+            $this->updateLookupTable();
+        }
+
+        if (isset($this->lookupTable[$filename][$lineNumber])) {
+            return $this->lookupTable[$filename][$lineNumber];
+        }
+
+        return $filename . ':' . $lineNumber;
+    }
+
+    private function updateLookupTable(): void
+    {
+        $this->processClassesAndTraits();
+        $this->processFunctions();
+    }
+
+    private function processClassesAndTraits(): void
+    {
+        $classes = get_declared_classes();
+        $traits  = get_declared_traits();
+
+        assert(is_array($classes));
+        assert(is_array($traits));
+
+        foreach (array_merge($classes, $traits) as $classOrTrait) {
+            if (isset($this->processedClasses[$classOrTrait])) {
+                continue;
+            }
+
+            $reflector = new ReflectionClass($classOrTrait);
+
+            foreach ($reflector->getMethods() as $method) {
+                $this->processFunctionOrMethod($method);
+            }
+
+            $this->processedClasses[$classOrTrait] = true;
+        }
+    }
+
+    private function processFunctions(): void
+    {
+        foreach (get_defined_functions()['user'] as $function) {
+            if (isset($this->processedFunctions[$function])) {
+                continue;
+            }
+
+            $this->processFunctionOrMethod(new ReflectionFunction($function));
+
+            $this->processedFunctions[$function] = true;
+        }
+    }
+
+    private function processFunctionOrMethod(ReflectionFunctionAbstract $functionOrMethod): void
+    {
+        if ($functionOrMethod->isInternal()) {
+            return;
+        }
+
+        $name = $functionOrMethod->getName();
+
+        if ($functionOrMethod instanceof ReflectionMethod) {
+            $name = $functionOrMethod->getDeclaringClass()->getName() . '::' . $name;
+        }
+
+        if (!isset($this->lookupTable[$functionOrMethod->getFileName()])) {
+            $this->lookupTable[$functionOrMethod->getFileName()] = [];
+        }
+
+        foreach (range($functionOrMethod->getStartLine(), $functionOrMethod->getEndLine()) as $line) {
+            $this->lookupTable[$functionOrMethod->getFileName()][$line] = $name;
+        }
+    }
+}
diff --git a/vendor/sebastian/code-unit/.psalm/baseline.xml b/vendor/sebastian/code-unit/.psalm/baseline.xml
new file mode 100644
index 0000000000000000000000000000000000000000..e448891902f220cc7a23c591209685cdde7da84e
--- /dev/null
+++ b/vendor/sebastian/code-unit/.psalm/baseline.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<files psalm-version="4.0.1@b1e2e30026936ef8d5bf6a354d1c3959b6231f44">
+  <file src="src/Mapper.php">
+    <ArgumentTypeCoercion occurrences="16">
+      <code>$firstPart</code>
+      <code>$firstPart</code>
+      <code>$firstPart</code>
+      <code>$firstPart</code>
+      <code>$firstPart</code>
+      <code>$firstPart</code>
+      <code>$firstPart</code>
+      <code>$firstPart</code>
+      <code>$firstPart</code>
+      <code>$secondPart</code>
+      <code>$unit</code>
+      <code>$unit</code>
+      <code>$unit</code>
+      <code>$unit</code>
+      <code>$unit</code>
+      <code>$unit</code>
+    </ArgumentTypeCoercion>
+  </file>
+</files>
diff --git a/vendor/sebastian/code-unit/.psalm/config.xml b/vendor/sebastian/code-unit/.psalm/config.xml
new file mode 100644
index 0000000000000000000000000000000000000000..a39e9a4c38fd3a507c34c962e09a9bc2a8251ccd
--- /dev/null
+++ b/vendor/sebastian/code-unit/.psalm/config.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0"?>
+<psalm
+    totallyTyped="true"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xmlns="https://getpsalm.org/schema/config"
+    xsi:schemaLocation="https://getpsalm.org/schema/config vendor/vimeo/psalm/config.xsd"
+    resolveFromConfigFile="false"
+    errorBaseline=".psalm/baseline.xml"
+>
+    <projectFiles>
+        <directory name="src" />
+        <ignoreFiles>
+            <directory name="vendor" />
+        </ignoreFiles>
+    </projectFiles>
+</psalm>
diff --git a/vendor/sebastian/code-unit/ChangeLog.md b/vendor/sebastian/code-unit/ChangeLog.md
new file mode 100644
index 0000000000000000000000000000000000000000..0978e651e3e3bdd7b848a2f6aa2d9d9576880d28
--- /dev/null
+++ b/vendor/sebastian/code-unit/ChangeLog.md
@@ -0,0 +1,65 @@
+# ChangeLog
+
+All notable changes are documented in this file using the [Keep a CHANGELOG](http://keepachangelog.com/) principles.
+
+## [1.0.8] - 2020-10-26
+
+### Fixed
+
+* `SebastianBergmann\CodeUnit\Exception` now correctly extends `\Throwable`
+
+## [1.0.7] - 2020-10-02
+
+### Fixed
+
+* `SebastianBergmann\CodeUnit\Mapper::stringToCodeUnits()` no longer attempts to create `CodeUnit` objects for code units that are not declared in userland
+
+## [1.0.6] - 2020-09-28
+
+### Changed
+
+* Changed PHP version constraint in `composer.json` from `^7.3 || ^8.0` to `>=7.3`
+
+## [1.0.5] - 2020-06-26
+
+### Fixed
+
+* [#3](https://github.com/sebastianbergmann/code-unit/issues/3): Regression in 1.0.4
+
+## [1.0.4] - 2020-06-26
+
+### Added
+
+* This component is now supported on PHP 8
+
+## [1.0.3] - 2020-06-15
+
+### Changed
+
+* Tests etc. are now ignored for archive exports
+
+## [1.0.2] - 2020-04-30
+
+### Fixed
+
+* `Mapper::stringToCodeUnits()` raised the wrong exception for `Class::method` when a class named `Class` exists but does not have a method named `method`
+
+## [1.0.1] - 2020-04-27
+
+### Fixed
+
+* [#2](https://github.com/sebastianbergmann/code-unit/issues/2): `Mapper::stringToCodeUnits()` breaks when `ClassName<extended>` is used for class that extends built-in class
+
+## [1.0.0] - 2020-03-30
+
+* Initial release
+
+[1.0.8]: https://github.com/sebastianbergmann/code-unit/compare/1.0.7...1.0.8
+[1.0.7]: https://github.com/sebastianbergmann/code-unit/compare/1.0.6...1.0.7
+[1.0.6]: https://github.com/sebastianbergmann/code-unit/compare/1.0.5...1.0.6
+[1.0.5]: https://github.com/sebastianbergmann/code-unit/compare/1.0.4...1.0.5
+[1.0.4]: https://github.com/sebastianbergmann/code-unit/compare/1.0.3...1.0.4
+[1.0.3]: https://github.com/sebastianbergmann/code-unit/compare/1.0.2...1.0.3
+[1.0.2]: https://github.com/sebastianbergmann/code-unit/compare/1.0.1...1.0.2
+[1.0.1]: https://github.com/sebastianbergmann/code-unit/compare/1.0.0...1.0.1
+[1.0.0]: https://github.com/sebastianbergmann/code-unit/compare/530c3900e5db9bcb8516da545bef0d62536cedaa...1.0.0
diff --git a/vendor/sebastian/code-unit/LICENSE b/vendor/sebastian/code-unit/LICENSE
new file mode 100644
index 0000000000000000000000000000000000000000..b99bc8ac446545b91999ecf9c9af17c9b5a92993
--- /dev/null
+++ b/vendor/sebastian/code-unit/LICENSE
@@ -0,0 +1,33 @@
+sebastian/code-unit
+
+Copyright (c) 2020, Sebastian Bergmann <sebastian@phpunit.de>.
+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 Sebastian Bergmann nor the names of his
+   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/sebastian/code-unit/README.md b/vendor/sebastian/code-unit/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..d20227a9bb4471bdcc13d11218e17de440894bc7
--- /dev/null
+++ b/vendor/sebastian/code-unit/README.md
@@ -0,0 +1,17 @@
+# sebastian/code-unit
+
+Collection of value objects that represent the PHP code units.
+
+## Installation
+
+You can add this library as a local, per-project dependency to your project using [Composer](https://getcomposer.org/):
+
+```
+composer require sebastian/code-unit
+```
+
+If you only need this library during development, for instance to run your project's test suite, then you should add it as a development-time dependency:
+
+```
+composer require --dev sebastian/code-unit
+```
diff --git a/vendor/sebastian/code-unit/composer.json b/vendor/sebastian/code-unit/composer.json
new file mode 100644
index 0000000000000000000000000000000000000000..5b86ec5895a5b19263ef8a9e4b5e8a44c9ddab74
--- /dev/null
+++ b/vendor/sebastian/code-unit/composer.json
@@ -0,0 +1,50 @@
+{
+    "name": "sebastian/code-unit",
+    "description": "Collection of value objects that represent the PHP code units",
+    "type": "library",
+    "homepage": "https://github.com/sebastianbergmann/code-unit",
+    "license": "BSD-3-Clause",
+    "authors": [
+        {
+            "name": "Sebastian Bergmann",
+            "email": "sebastian@phpunit.de",
+            "role": "lead"
+        }
+    ],
+    "support": {
+        "issues": "https://github.com/sebastianbergmann/code-unit/issues"
+    },
+    "prefer-stable": true,
+    "require": {
+        "php": ">=7.3"
+    },
+    "require-dev": {
+        "phpunit/phpunit": "^9.3"
+    },
+    "config": {
+        "platform": {
+            "php": "7.3.0"
+        },
+        "optimize-autoloader": true,
+        "sort-packages": true
+    },
+    "autoload": {
+        "classmap": [
+            "src/"
+        ]
+    },
+    "autoload-dev": {
+        "classmap": [
+            "tests/_fixture"
+        ],
+        "files": [
+            "tests/_fixture/file_with_multiple_code_units.php",
+            "tests/_fixture/function.php"
+        ]
+    },
+    "extra": {
+        "branch-alias": {
+            "dev-master": "1.0-dev"
+        }
+    }
+}
diff --git a/vendor/sebastian/code-unit/src/ClassMethodUnit.php b/vendor/sebastian/code-unit/src/ClassMethodUnit.php
new file mode 100644
index 0000000000000000000000000000000000000000..f9ddac29e1bd0d8e6971a0f46302b6896bbb522f
--- /dev/null
+++ b/vendor/sebastian/code-unit/src/ClassMethodUnit.php
@@ -0,0 +1,24 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of sebastian/code-unit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\CodeUnit;
+
+/**
+ * @psalm-immutable
+ */
+final class ClassMethodUnit extends CodeUnit
+{
+    /**
+     * @psalm-assert-if-true ClassMethodUnit $this
+     */
+    public function isClassMethod(): bool
+    {
+        return true;
+    }
+}
diff --git a/vendor/sebastian/code-unit/src/ClassUnit.php b/vendor/sebastian/code-unit/src/ClassUnit.php
new file mode 100644
index 0000000000000000000000000000000000000000..3ba0ee66173a08f356d3d56a344a53a7ea7a6d6f
--- /dev/null
+++ b/vendor/sebastian/code-unit/src/ClassUnit.php
@@ -0,0 +1,24 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of sebastian/code-unit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\CodeUnit;
+
+/**
+ * @psalm-immutable
+ */
+final class ClassUnit extends CodeUnit
+{
+    /**
+     * @psalm-assert-if-true ClassUnit $this
+     */
+    public function isClass(): bool
+    {
+        return true;
+    }
+}
diff --git a/vendor/sebastian/code-unit/src/CodeUnit.php b/vendor/sebastian/code-unit/src/CodeUnit.php
new file mode 100644
index 0000000000000000000000000000000000000000..9e5cceb35ac4e22a7a9213090ad0de15866529f1
--- /dev/null
+++ b/vendor/sebastian/code-unit/src/CodeUnit.php
@@ -0,0 +1,445 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of sebastian/code-unit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\CodeUnit;
+
+use function range;
+use function sprintf;
+use ReflectionClass;
+use ReflectionFunction;
+use ReflectionMethod;
+
+/**
+ * @psalm-immutable
+ */
+abstract class CodeUnit
+{
+    /**
+     * @var string
+     */
+    private $name;
+
+    /**
+     * @var string
+     */
+    private $sourceFileName;
+
+    /**
+     * @var array
+     * @psalm-var list<int>
+     */
+    private $sourceLines;
+
+    /**
+     * @psalm-param class-string $className
+     *
+     * @throws InvalidCodeUnitException
+     * @throws ReflectionException
+     */
+    public static function forClass(string $className): ClassUnit
+    {
+        self::ensureUserDefinedClass($className);
+
+        $reflector = self::reflectorForClass($className);
+
+        return new ClassUnit(
+            $className,
+            $reflector->getFileName(),
+            range(
+                $reflector->getStartLine(),
+                $reflector->getEndLine()
+            )
+        );
+    }
+
+    /**
+     * @psalm-param class-string $className
+     *
+     * @throws InvalidCodeUnitException
+     * @throws ReflectionException
+     */
+    public static function forClassMethod(string $className, string $methodName): ClassMethodUnit
+    {
+        self::ensureUserDefinedClass($className);
+
+        $reflector = self::reflectorForClassMethod($className, $methodName);
+
+        return new ClassMethodUnit(
+            $className . '::' . $methodName,
+            $reflector->getFileName(),
+            range(
+                $reflector->getStartLine(),
+                $reflector->getEndLine()
+            )
+        );
+    }
+
+    /**
+     * @psalm-param class-string $interfaceName
+     *
+     * @throws InvalidCodeUnitException
+     * @throws ReflectionException
+     */
+    public static function forInterface(string $interfaceName): InterfaceUnit
+    {
+        self::ensureUserDefinedInterface($interfaceName);
+
+        $reflector = self::reflectorForClass($interfaceName);
+
+        return new InterfaceUnit(
+            $interfaceName,
+            $reflector->getFileName(),
+            range(
+                $reflector->getStartLine(),
+                $reflector->getEndLine()
+            )
+        );
+    }
+
+    /**
+     * @psalm-param class-string $interfaceName
+     *
+     * @throws InvalidCodeUnitException
+     * @throws ReflectionException
+     */
+    public static function forInterfaceMethod(string $interfaceName, string $methodName): InterfaceMethodUnit
+    {
+        self::ensureUserDefinedInterface($interfaceName);
+
+        $reflector = self::reflectorForClassMethod($interfaceName, $methodName);
+
+        return new InterfaceMethodUnit(
+            $interfaceName . '::' . $methodName,
+            $reflector->getFileName(),
+            range(
+                $reflector->getStartLine(),
+                $reflector->getEndLine()
+            )
+        );
+    }
+
+    /**
+     * @psalm-param class-string $traitName
+     *
+     * @throws InvalidCodeUnitException
+     * @throws ReflectionException
+     */
+    public static function forTrait(string $traitName): TraitUnit
+    {
+        self::ensureUserDefinedTrait($traitName);
+
+        $reflector = self::reflectorForClass($traitName);
+
+        return new TraitUnit(
+            $traitName,
+            $reflector->getFileName(),
+            range(
+                $reflector->getStartLine(),
+                $reflector->getEndLine()
+            )
+        );
+    }
+
+    /**
+     * @psalm-param class-string $traitName
+     *
+     * @throws InvalidCodeUnitException
+     * @throws ReflectionException
+     */
+    public static function forTraitMethod(string $traitName, string $methodName): TraitMethodUnit
+    {
+        self::ensureUserDefinedTrait($traitName);
+
+        $reflector = self::reflectorForClassMethod($traitName, $methodName);
+
+        return new TraitMethodUnit(
+            $traitName . '::' . $methodName,
+            $reflector->getFileName(),
+            range(
+                $reflector->getStartLine(),
+                $reflector->getEndLine()
+            )
+        );
+    }
+
+    /**
+     * @psalm-param callable-string $functionName
+     *
+     * @throws InvalidCodeUnitException
+     * @throws ReflectionException
+     */
+    public static function forFunction(string $functionName): FunctionUnit
+    {
+        $reflector = self::reflectorForFunction($functionName);
+
+        if (!$reflector->isUserDefined()) {
+            throw new InvalidCodeUnitException(
+                sprintf(
+                    '"%s" is not a user-defined function',
+                    $functionName
+                )
+            );
+        }
+
+        return new FunctionUnit(
+            $functionName,
+            $reflector->getFileName(),
+            range(
+                $reflector->getStartLine(),
+                $reflector->getEndLine()
+            )
+        );
+    }
+
+    /**
+     * @psalm-param list<int> $sourceLines
+     */
+    private function __construct(string $name, string $sourceFileName, array $sourceLines)
+    {
+        $this->name           = $name;
+        $this->sourceFileName = $sourceFileName;
+        $this->sourceLines    = $sourceLines;
+    }
+
+    public function name(): string
+    {
+        return $this->name;
+    }
+
+    public function sourceFileName(): string
+    {
+        return $this->sourceFileName;
+    }
+
+    /**
+     * @psalm-return list<int>
+     */
+    public function sourceLines(): array
+    {
+        return $this->sourceLines;
+    }
+
+    public function isClass(): bool
+    {
+        return false;
+    }
+
+    public function isClassMethod(): bool
+    {
+        return false;
+    }
+
+    public function isInterface(): bool
+    {
+        return false;
+    }
+
+    public function isInterfaceMethod(): bool
+    {
+        return false;
+    }
+
+    public function isTrait(): bool
+    {
+        return false;
+    }
+
+    public function isTraitMethod(): bool
+    {
+        return false;
+    }
+
+    public function isFunction(): bool
+    {
+        return false;
+    }
+
+    /**
+     * @psalm-param class-string $className
+     *
+     * @throws InvalidCodeUnitException
+     */
+    private static function ensureUserDefinedClass(string $className): void
+    {
+        try {
+            $reflector = new ReflectionClass($className);
+
+            if ($reflector->isInterface()) {
+                throw new InvalidCodeUnitException(
+                    sprintf(
+                        '"%s" is an interface and not a class',
+                        $className
+                    )
+                );
+            }
+
+            if ($reflector->isTrait()) {
+                throw new InvalidCodeUnitException(
+                    sprintf(
+                        '"%s" is a trait and not a class',
+                        $className
+                    )
+                );
+            }
+
+            if (!$reflector->isUserDefined()) {
+                throw new InvalidCodeUnitException(
+                    sprintf(
+                        '"%s" is not a user-defined class',
+                        $className
+                    )
+                );
+            }
+            // @codeCoverageIgnoreStart
+        } catch (\ReflectionException $e) {
+            throw new ReflectionException(
+                $e->getMessage(),
+                (int) $e->getCode(),
+                $e
+            );
+        }
+        // @codeCoverageIgnoreEnd
+    }
+
+    /**
+     * @psalm-param class-string $interfaceName
+     *
+     * @throws InvalidCodeUnitException
+     */
+    private static function ensureUserDefinedInterface(string $interfaceName): void
+    {
+        try {
+            $reflector = new ReflectionClass($interfaceName);
+
+            if (!$reflector->isInterface()) {
+                throw new InvalidCodeUnitException(
+                    sprintf(
+                        '"%s" is not an interface',
+                        $interfaceName
+                    )
+                );
+            }
+
+            if (!$reflector->isUserDefined()) {
+                throw new InvalidCodeUnitException(
+                    sprintf(
+                        '"%s" is not a user-defined interface',
+                        $interfaceName
+                    )
+                );
+            }
+            // @codeCoverageIgnoreStart
+        } catch (\ReflectionException $e) {
+            throw new ReflectionException(
+                $e->getMessage(),
+                (int) $e->getCode(),
+                $e
+            );
+        }
+        // @codeCoverageIgnoreEnd
+    }
+
+    /**
+     * @psalm-param class-string $traitName
+     *
+     * @throws InvalidCodeUnitException
+     */
+    private static function ensureUserDefinedTrait(string $traitName): void
+    {
+        try {
+            $reflector = new ReflectionClass($traitName);
+
+            if (!$reflector->isTrait()) {
+                throw new InvalidCodeUnitException(
+                    sprintf(
+                        '"%s" is not a trait',
+                        $traitName
+                    )
+                );
+            }
+
+            // @codeCoverageIgnoreStart
+            if (!$reflector->isUserDefined()) {
+                throw new InvalidCodeUnitException(
+                    sprintf(
+                        '"%s" is not a user-defined trait',
+                        $traitName
+                    )
+                );
+            }
+        } catch (\ReflectionException $e) {
+            throw new ReflectionException(
+                $e->getMessage(),
+                (int) $e->getCode(),
+                $e
+            );
+        }
+        // @codeCoverageIgnoreEnd
+    }
+
+    /**
+     * @psalm-param class-string $className
+     *
+     * @throws ReflectionException
+     */
+    private static function reflectorForClass(string $className): ReflectionClass
+    {
+        try {
+            return new ReflectionClass($className);
+            // @codeCoverageIgnoreStart
+        } catch (\ReflectionException $e) {
+            throw new ReflectionException(
+                $e->getMessage(),
+                (int) $e->getCode(),
+                $e
+            );
+        }
+        // @codeCoverageIgnoreEnd
+    }
+
+    /**
+     * @psalm-param class-string $className
+     *
+     * @throws ReflectionException
+     */
+    private static function reflectorForClassMethod(string $className, string $methodName): ReflectionMethod
+    {
+        try {
+            return new ReflectionMethod($className, $methodName);
+            // @codeCoverageIgnoreStart
+        } catch (\ReflectionException $e) {
+            throw new ReflectionException(
+                $e->getMessage(),
+                (int) $e->getCode(),
+                $e
+            );
+        }
+        // @codeCoverageIgnoreEnd
+    }
+
+    /**
+     * @psalm-param callable-string $functionName
+     *
+     * @throws ReflectionException
+     */
+    private static function reflectorForFunction(string $functionName): ReflectionFunction
+    {
+        try {
+            return new ReflectionFunction($functionName);
+            // @codeCoverageIgnoreStart
+        } catch (\ReflectionException $e) {
+            throw new ReflectionException(
+                $e->getMessage(),
+                (int) $e->getCode(),
+                $e
+            );
+        }
+        // @codeCoverageIgnoreEnd
+    }
+}
diff --git a/vendor/sebastian/code-unit/src/CodeUnitCollection.php b/vendor/sebastian/code-unit/src/CodeUnitCollection.php
new file mode 100644
index 0000000000000000000000000000000000000000..f53db8a1280b6c7a8fefd1cd3837d418506aa071
--- /dev/null
+++ b/vendor/sebastian/code-unit/src/CodeUnitCollection.php
@@ -0,0 +1,84 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of sebastian/code-unit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\CodeUnit;
+
+use function array_merge;
+use function count;
+use Countable;
+use IteratorAggregate;
+
+final class CodeUnitCollection implements Countable, IteratorAggregate
+{
+    /**
+     * @psalm-var list<CodeUnit>
+     */
+    private $codeUnits = [];
+
+    /**
+     * @psalm-param list<CodeUnit> $items
+     */
+    public static function fromArray(array $items): self
+    {
+        $collection = new self;
+
+        foreach ($items as $item) {
+            $collection->add($item);
+        }
+
+        return $collection;
+    }
+
+    public static function fromList(CodeUnit ...$items): self
+    {
+        return self::fromArray($items);
+    }
+
+    private function __construct()
+    {
+    }
+
+    /**
+     * @psalm-return list<CodeUnit>
+     */
+    public function asArray(): array
+    {
+        return $this->codeUnits;
+    }
+
+    public function getIterator(): CodeUnitCollectionIterator
+    {
+        return new CodeUnitCollectionIterator($this);
+    }
+
+    public function count(): int
+    {
+        return count($this->codeUnits);
+    }
+
+    public function isEmpty(): bool
+    {
+        return empty($this->codeUnits);
+    }
+
+    public function mergeWith(self $other): self
+    {
+        return self::fromArray(
+            array_merge(
+                $this->asArray(),
+                $other->asArray()
+            )
+        );
+    }
+
+    private function add(CodeUnit $item): void
+    {
+        $this->codeUnits[] = $item;
+    }
+}
diff --git a/vendor/sebastian/code-unit/src/CodeUnitCollectionIterator.php b/vendor/sebastian/code-unit/src/CodeUnitCollectionIterator.php
new file mode 100644
index 0000000000000000000000000000000000000000..bdc86d8883b3b497d5ffcd4f2972a5983857dd2c
--- /dev/null
+++ b/vendor/sebastian/code-unit/src/CodeUnitCollectionIterator.php
@@ -0,0 +1,55 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of sebastian/code-unit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\CodeUnit;
+
+use Iterator;
+
+final class CodeUnitCollectionIterator implements Iterator
+{
+    /**
+     * @psalm-var list<CodeUnit>
+     */
+    private $codeUnits;
+
+    /**
+     * @var int
+     */
+    private $position = 0;
+
+    public function __construct(CodeUnitCollection $collection)
+    {
+        $this->codeUnits = $collection->asArray();
+    }
+
+    public function rewind(): void
+    {
+        $this->position = 0;
+    }
+
+    public function valid(): bool
+    {
+        return isset($this->codeUnits[$this->position]);
+    }
+
+    public function key(): int
+    {
+        return $this->position;
+    }
+
+    public function current(): CodeUnit
+    {
+        return $this->codeUnits[$this->position];
+    }
+
+    public function next(): void
+    {
+        $this->position++;
+    }
+}
diff --git a/vendor/sebastian/code-unit/src/FunctionUnit.php b/vendor/sebastian/code-unit/src/FunctionUnit.php
new file mode 100644
index 0000000000000000000000000000000000000000..df76cf1950025bac11a60f401ea76446ed3de7f3
--- /dev/null
+++ b/vendor/sebastian/code-unit/src/FunctionUnit.php
@@ -0,0 +1,24 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of sebastian/code-unit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\CodeUnit;
+
+/**
+ * @psalm-immutable
+ */
+final class FunctionUnit extends CodeUnit
+{
+    /**
+     * @psalm-assert-if-true FunctionUnit $this
+     */
+    public function isFunction(): bool
+    {
+        return true;
+    }
+}
diff --git a/vendor/sebastian/code-unit/src/InterfaceMethodUnit.php b/vendor/sebastian/code-unit/src/InterfaceMethodUnit.php
new file mode 100644
index 0000000000000000000000000000000000000000..fcd44f41a8421aad555a706e8f03a1886835b1f3
--- /dev/null
+++ b/vendor/sebastian/code-unit/src/InterfaceMethodUnit.php
@@ -0,0 +1,24 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of sebastian/code-unit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\CodeUnit;
+
+/**
+ * @psalm-immutable
+ */
+final class InterfaceMethodUnit extends CodeUnit
+{
+    /**
+     * @psalm-assert-if-true InterfaceMethod $this
+     */
+    public function isInterfaceMethod(): bool
+    {
+        return true;
+    }
+}
diff --git a/vendor/sebastian/code-unit/src/InterfaceUnit.php b/vendor/sebastian/code-unit/src/InterfaceUnit.php
new file mode 100644
index 0000000000000000000000000000000000000000..5cf585bfd6233576c532dec75d09cd2aacbf19e8
--- /dev/null
+++ b/vendor/sebastian/code-unit/src/InterfaceUnit.php
@@ -0,0 +1,24 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of sebastian/code-unit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\CodeUnit;
+
+/**
+ * @psalm-immutable
+ */
+final class InterfaceUnit extends CodeUnit
+{
+    /**
+     * @psalm-assert-if-true InterfaceUnit $this
+     */
+    public function isInterface(): bool
+    {
+        return true;
+    }
+}
diff --git a/vendor/sebastian/code-unit/src/Mapper.php b/vendor/sebastian/code-unit/src/Mapper.php
new file mode 100644
index 0000000000000000000000000000000000000000..a72b3b0ddbae537836de5bb60cefff46f10977a2
--- /dev/null
+++ b/vendor/sebastian/code-unit/src/Mapper.php
@@ -0,0 +1,414 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of sebastian/code-unit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\CodeUnit;
+
+use function array_keys;
+use function array_merge;
+use function array_unique;
+use function array_values;
+use function class_exists;
+use function explode;
+use function function_exists;
+use function interface_exists;
+use function ksort;
+use function method_exists;
+use function sort;
+use function sprintf;
+use function str_replace;
+use function strpos;
+use function trait_exists;
+use ReflectionClass;
+use ReflectionFunction;
+use ReflectionMethod;
+
+final class Mapper
+{
+    /**
+     * @psalm-return array<string,list<int>>
+     */
+    public function codeUnitsToSourceLines(CodeUnitCollection $codeUnits): array
+    {
+        $result = [];
+
+        foreach ($codeUnits as $codeUnit) {
+            $sourceFileName = $codeUnit->sourceFileName();
+
+            if (!isset($result[$sourceFileName])) {
+                $result[$sourceFileName] = [];
+            }
+
+            $result[$sourceFileName] = array_merge($result[$sourceFileName], $codeUnit->sourceLines());
+        }
+
+        foreach (array_keys($result) as $sourceFileName) {
+            $result[$sourceFileName] = array_values(array_unique($result[$sourceFileName]));
+
+            sort($result[$sourceFileName]);
+        }
+
+        ksort($result);
+
+        return $result;
+    }
+
+    /**
+     * @throws InvalidCodeUnitException
+     * @throws ReflectionException
+     */
+    public function stringToCodeUnits(string $unit): CodeUnitCollection
+    {
+        if (strpos($unit, '::') !== false) {
+            [$firstPart, $secondPart] = explode('::', $unit);
+
+            if (empty($firstPart) && $this->isUserDefinedFunction($secondPart)) {
+                return CodeUnitCollection::fromList(CodeUnit::forFunction($secondPart));
+            }
+
+            if ($this->isUserDefinedClass($firstPart)) {
+                if ($secondPart === '<public>') {
+                    return $this->publicMethodsOfClass($firstPart);
+                }
+
+                if ($secondPart === '<!public>') {
+                    return $this->protectedAndPrivateMethodsOfClass($firstPart);
+                }
+
+                if ($secondPart === '<protected>') {
+                    return $this->protectedMethodsOfClass($firstPart);
+                }
+
+                if ($secondPart === '<!protected>') {
+                    return $this->publicAndPrivateMethodsOfClass($firstPart);
+                }
+
+                if ($secondPart === '<private>') {
+                    return $this->privateMethodsOfClass($firstPart);
+                }
+
+                if ($secondPart === '<!private>') {
+                    return $this->publicAndProtectedMethodsOfClass($firstPart);
+                }
+
+                if ($this->isUserDefinedMethod($firstPart, $secondPart)) {
+                    return CodeUnitCollection::fromList(CodeUnit::forClassMethod($firstPart, $secondPart));
+                }
+            }
+
+            if ($this->isUserDefinedInterface($firstPart)) {
+                return CodeUnitCollection::fromList(CodeUnit::forInterfaceMethod($firstPart, $secondPart));
+            }
+
+            if ($this->isUserDefinedTrait($firstPart)) {
+                return CodeUnitCollection::fromList(CodeUnit::forTraitMethod($firstPart, $secondPart));
+            }
+        } else {
+            if ($this->isUserDefinedClass($unit)) {
+                $units = [CodeUnit::forClass($unit)];
+
+                foreach ($this->reflectorForClass($unit)->getTraits() as $trait) {
+                    if (!$trait->isUserDefined()) {
+                        // @codeCoverageIgnoreStart
+                        continue;
+                        // @codeCoverageIgnoreEnd
+                    }
+
+                    $units[] = CodeUnit::forTrait($trait->getName());
+                }
+
+                return CodeUnitCollection::fromArray($units);
+            }
+
+            if ($this->isUserDefinedInterface($unit)) {
+                return CodeUnitCollection::fromList(CodeUnit::forInterface($unit));
+            }
+
+            if ($this->isUserDefinedTrait($unit)) {
+                return CodeUnitCollection::fromList(CodeUnit::forTrait($unit));
+            }
+
+            if ($this->isUserDefinedFunction($unit)) {
+                return CodeUnitCollection::fromList(CodeUnit::forFunction($unit));
+            }
+
+            $unit = str_replace('<extended>', '', $unit);
+
+            if ($this->isUserDefinedClass($unit)) {
+                return $this->classAndParentClassesAndTraits($unit);
+            }
+        }
+
+        throw new InvalidCodeUnitException(
+            sprintf(
+                '"%s" is not a valid code unit',
+                $unit
+            )
+        );
+    }
+
+    /**
+     * @psalm-param class-string $className
+     *
+     * @throws ReflectionException
+     */
+    private function publicMethodsOfClass(string $className): CodeUnitCollection
+    {
+        return $this->methodsOfClass($className, ReflectionMethod::IS_PUBLIC);
+    }
+
+    /**
+     * @psalm-param class-string $className
+     *
+     * @throws ReflectionException
+     */
+    private function publicAndProtectedMethodsOfClass(string $className): CodeUnitCollection
+    {
+        return $this->methodsOfClass($className, ReflectionMethod::IS_PUBLIC | ReflectionMethod::IS_PROTECTED);
+    }
+
+    /**
+     * @psalm-param class-string $className
+     *
+     * @throws ReflectionException
+     */
+    private function publicAndPrivateMethodsOfClass(string $className): CodeUnitCollection
+    {
+        return $this->methodsOfClass($className, ReflectionMethod::IS_PUBLIC | ReflectionMethod::IS_PRIVATE);
+    }
+
+    /**
+     * @psalm-param class-string $className
+     *
+     * @throws ReflectionException
+     */
+    private function protectedMethodsOfClass(string $className): CodeUnitCollection
+    {
+        return $this->methodsOfClass($className, ReflectionMethod::IS_PROTECTED);
+    }
+
+    /**
+     * @psalm-param class-string $className
+     *
+     * @throws ReflectionException
+     */
+    private function protectedAndPrivateMethodsOfClass(string $className): CodeUnitCollection
+    {
+        return $this->methodsOfClass($className, ReflectionMethod::IS_PROTECTED | ReflectionMethod::IS_PRIVATE);
+    }
+
+    /**
+     * @psalm-param class-string $className
+     *
+     * @throws ReflectionException
+     */
+    private function privateMethodsOfClass(string $className): CodeUnitCollection
+    {
+        return $this->methodsOfClass($className, ReflectionMethod::IS_PRIVATE);
+    }
+
+    /**
+     * @psalm-param class-string $className
+     *
+     * @throws ReflectionException
+     */
+    private function methodsOfClass(string $className, int $filter): CodeUnitCollection
+    {
+        $units = [];
+
+        foreach ($this->reflectorForClass($className)->getMethods($filter) as $method) {
+            if (!$method->isUserDefined()) {
+                continue;
+            }
+
+            $units[] = CodeUnit::forClassMethod($className, $method->getName());
+        }
+
+        return CodeUnitCollection::fromArray($units);
+    }
+
+    /**
+     * @psalm-param class-string $className
+     *
+     * @throws ReflectionException
+     */
+    private function classAndParentClassesAndTraits(string $className): CodeUnitCollection
+    {
+        $units = [CodeUnit::forClass($className)];
+
+        $reflector = $this->reflectorForClass($className);
+
+        foreach ($this->reflectorForClass($className)->getTraits() as $trait) {
+            if (!$trait->isUserDefined()) {
+                // @codeCoverageIgnoreStart
+                continue;
+                // @codeCoverageIgnoreEnd
+            }
+
+            $units[] = CodeUnit::forTrait($trait->getName());
+        }
+
+        while ($reflector = $reflector->getParentClass()) {
+            if (!$reflector->isUserDefined()) {
+                break;
+            }
+
+            $units[] = CodeUnit::forClass($reflector->getName());
+
+            foreach ($reflector->getTraits() as $trait) {
+                if (!$trait->isUserDefined()) {
+                    // @codeCoverageIgnoreStart
+                    continue;
+                    // @codeCoverageIgnoreEnd
+                }
+
+                $units[] = CodeUnit::forTrait($trait->getName());
+            }
+        }
+
+        return CodeUnitCollection::fromArray($units);
+    }
+
+    /**
+     * @psalm-param class-string $className
+     *
+     * @throws ReflectionException
+     */
+    private function reflectorForClass(string $className): ReflectionClass
+    {
+        try {
+            return new ReflectionClass($className);
+            // @codeCoverageIgnoreStart
+        } catch (\ReflectionException $e) {
+            throw new ReflectionException(
+                $e->getMessage(),
+                (int) $e->getCode(),
+                $e
+            );
+        }
+        // @codeCoverageIgnoreEnd
+    }
+
+    /**
+     * @throws ReflectionException
+     */
+    private function isUserDefinedFunction(string $functionName): bool
+    {
+        if (!function_exists($functionName)) {
+            return false;
+        }
+
+        try {
+            return (new ReflectionFunction($functionName))->isUserDefined();
+            // @codeCoverageIgnoreStart
+        } catch (\ReflectionException $e) {
+            throw new ReflectionException(
+                $e->getMessage(),
+                (int) $e->getCode(),
+                $e
+            );
+        }
+        // @codeCoverageIgnoreEnd
+    }
+
+    /**
+     * @throws ReflectionException
+     */
+    private function isUserDefinedClass(string $className): bool
+    {
+        if (!class_exists($className)) {
+            return false;
+        }
+
+        try {
+            return (new ReflectionClass($className))->isUserDefined();
+            // @codeCoverageIgnoreStart
+        } catch (\ReflectionException $e) {
+            throw new ReflectionException(
+                $e->getMessage(),
+                (int) $e->getCode(),
+                $e
+            );
+        }
+        // @codeCoverageIgnoreEnd
+    }
+
+    /**
+     * @throws ReflectionException
+     */
+    private function isUserDefinedInterface(string $interfaceName): bool
+    {
+        if (!interface_exists($interfaceName)) {
+            return false;
+        }
+
+        try {
+            return (new ReflectionClass($interfaceName))->isUserDefined();
+            // @codeCoverageIgnoreStart
+        } catch (\ReflectionException $e) {
+            throw new ReflectionException(
+                $e->getMessage(),
+                (int) $e->getCode(),
+                $e
+            );
+        }
+        // @codeCoverageIgnoreEnd
+    }
+
+    /**
+     * @throws ReflectionException
+     */
+    private function isUserDefinedTrait(string $traitName): bool
+    {
+        if (!trait_exists($traitName)) {
+            return false;
+        }
+
+        try {
+            return (new ReflectionClass($traitName))->isUserDefined();
+            // @codeCoverageIgnoreStart
+        } catch (\ReflectionException $e) {
+            throw new ReflectionException(
+                $e->getMessage(),
+                (int) $e->getCode(),
+                $e
+            );
+        }
+        // @codeCoverageIgnoreEnd
+    }
+
+    /**
+     * @throws ReflectionException
+     */
+    private function isUserDefinedMethod(string $className, string $methodName): bool
+    {
+        if (!class_exists($className)) {
+            // @codeCoverageIgnoreStart
+            return false;
+            // @codeCoverageIgnoreEnd
+        }
+
+        if (!method_exists($className, $methodName)) {
+            // @codeCoverageIgnoreStart
+            return false;
+            // @codeCoverageIgnoreEnd
+        }
+
+        try {
+            return (new ReflectionMethod($className, $methodName))->isUserDefined();
+            // @codeCoverageIgnoreStart
+        } catch (\ReflectionException $e) {
+            throw new ReflectionException(
+                $e->getMessage(),
+                (int) $e->getCode(),
+                $e
+            );
+        }
+        // @codeCoverageIgnoreEnd
+    }
+}
diff --git a/vendor/sebastian/code-unit/src/TraitMethodUnit.php b/vendor/sebastian/code-unit/src/TraitMethodUnit.php
new file mode 100644
index 0000000000000000000000000000000000000000..a58f7249f4bf6232545b4b7a28cd8f320aca64d0
--- /dev/null
+++ b/vendor/sebastian/code-unit/src/TraitMethodUnit.php
@@ -0,0 +1,24 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of sebastian/code-unit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\CodeUnit;
+
+/**
+ * @psalm-immutable
+ */
+final class TraitMethodUnit extends CodeUnit
+{
+    /**
+     * @psalm-assert-if-true TraitMethodUnit $this
+     */
+    public function isTraitMethod(): bool
+    {
+        return true;
+    }
+}
diff --git a/vendor/sebastian/code-unit/src/TraitUnit.php b/vendor/sebastian/code-unit/src/TraitUnit.php
new file mode 100644
index 0000000000000000000000000000000000000000..abddfc1120c3462f37319ecb76c2745b297ce8a5
--- /dev/null
+++ b/vendor/sebastian/code-unit/src/TraitUnit.php
@@ -0,0 +1,24 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of sebastian/code-unit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\CodeUnit;
+
+/**
+ * @psalm-immutable
+ */
+final class TraitUnit extends CodeUnit
+{
+    /**
+     * @psalm-assert-if-true TraitUnit $this
+     */
+    public function isTrait(): bool
+    {
+        return true;
+    }
+}
diff --git a/vendor/sebastian/code-unit/src/exceptions/Exception.php b/vendor/sebastian/code-unit/src/exceptions/Exception.php
new file mode 100644
index 0000000000000000000000000000000000000000..74d0eeef844db96887923f628d494fbfe61deb59
--- /dev/null
+++ b/vendor/sebastian/code-unit/src/exceptions/Exception.php
@@ -0,0 +1,16 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of sebastian/code-unit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\CodeUnit;
+
+use Throwable;
+
+interface Exception extends Throwable
+{
+}
diff --git a/vendor/sebastian/code-unit/src/exceptions/InvalidCodeUnitException.php b/vendor/sebastian/code-unit/src/exceptions/InvalidCodeUnitException.php
new file mode 100644
index 0000000000000000000000000000000000000000..60a3da82b990a6d6e058470f4285bf823fc5cf40
--- /dev/null
+++ b/vendor/sebastian/code-unit/src/exceptions/InvalidCodeUnitException.php
@@ -0,0 +1,16 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of sebastian/code-unit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\CodeUnit;
+
+use RuntimeException;
+
+final class InvalidCodeUnitException extends RuntimeException implements Exception
+{
+}
diff --git a/vendor/sebastian/code-unit/src/exceptions/NoTraitException.php b/vendor/sebastian/code-unit/src/exceptions/NoTraitException.php
new file mode 100644
index 0000000000000000000000000000000000000000..e9b9b9c7aa783f6443565ff7c2defa5f93355547
--- /dev/null
+++ b/vendor/sebastian/code-unit/src/exceptions/NoTraitException.php
@@ -0,0 +1,16 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of sebastian/code-unit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\CodeUnit;
+
+use RuntimeException;
+
+final class NoTraitException extends RuntimeException implements Exception
+{
+}
diff --git a/vendor/sebastian/code-unit/src/exceptions/ReflectionException.php b/vendor/sebastian/code-unit/src/exceptions/ReflectionException.php
new file mode 100644
index 0000000000000000000000000000000000000000..232012783682cc1f3bfa8c0e75296421ce24518c
--- /dev/null
+++ b/vendor/sebastian/code-unit/src/exceptions/ReflectionException.php
@@ -0,0 +1,16 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of sebastian/code-unit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\CodeUnit;
+
+use RuntimeException;
+
+final class ReflectionException extends RuntimeException implements Exception
+{
+}
diff --git a/vendor/sebastian/comparator/ChangeLog.md b/vendor/sebastian/comparator/ChangeLog.md
new file mode 100644
index 0000000000000000000000000000000000000000..64c0251c19976221d4adb08a5d8f2911e80ff62f
--- /dev/null
+++ b/vendor/sebastian/comparator/ChangeLog.md
@@ -0,0 +1,108 @@
+# ChangeLog
+
+All notable changes are documented in this file using the [Keep a CHANGELOG](http://keepachangelog.com/) principles.
+
+## [4.0.6] - 2020-10-26
+
+### Fixed
+
+* `SebastianBergmann\Comparator\Exception` now correctly extends `\Throwable`
+
+## [4.0.5] - 2020-09-30
+
+### Fixed
+
+* [#89](https://github.com/sebastianbergmann/comparator/pull/89): Handle PHP 8 `ValueError`
+
+## [4.0.4] - 2020-09-28
+
+### Changed
+
+* Changed PHP version constraint in `composer.json` from `^7.3 || ^8.0` to `>=7.3`
+
+## [4.0.3] - 2020-06-26
+
+### Added
+
+* This component is now supported on PHP 8
+
+## [4.0.2] - 2020-06-15
+
+### Fixed
+
+* [#85](https://github.com/sebastianbergmann/comparator/issues/85): Version 4.0.1 breaks backward compatibility
+
+## [4.0.1] - 2020-06-15
+
+### Changed
+
+* Tests etc. are now ignored for archive exports
+
+## [4.0.0] - 2020-02-07
+
+### Removed
+
+* Removed support for PHP 7.1 and PHP 7.2
+
+## [3.0.2] - 2018-07-12
+
+### Changed
+
+* By default, `MockObjectComparator` is now tried before all other (default) comparators
+
+## [3.0.1] - 2018-06-14
+
+### Fixed
+
+* [#53](https://github.com/sebastianbergmann/comparator/pull/53): `DOMNodeComparator` ignores `$ignoreCase` parameter
+* [#58](https://github.com/sebastianbergmann/comparator/pull/58): `ScalarComparator` does not handle extremely ugly string comparison edge cases
+
+## [3.0.0] - 2018-04-18
+
+### Fixed
+
+* Fixed [#48](https://github.com/sebastianbergmann/comparator/issues/48): `DateTimeComparator` does not support fractional second deltas
+
+### Removed
+
+* Removed support for PHP 7.0
+
+## [2.1.3] - 2018-02-01
+
+### Changed
+
+* This component is now compatible with version 3 of `sebastian/diff`
+
+## [2.1.2] - 2018-01-12
+
+### Fixed
+
+* Fix comparison of `DateTimeImmutable` objects
+
+## [2.1.1] - 2017-12-22
+
+### Fixed
+
+* Fixed [phpunit/#2923](https://github.com/sebastianbergmann/phpunit/issues/2923): Unexpected failed date matching
+
+## [2.1.0] - 2017-11-03
+
+### Added
+
+* Added `SebastianBergmann\Comparator\Factory::reset()` to unregister all non-default comparators
+* Added support for `phpunit/phpunit-mock-objects` version `^5.0`
+
+[4.0.6]: https://github.com/sebastianbergmann/comparator/compare/4.0.5...4.0.6
+[4.0.5]: https://github.com/sebastianbergmann/comparator/compare/4.0.4...4.0.5
+[4.0.4]: https://github.com/sebastianbergmann/comparator/compare/4.0.3...4.0.4
+[4.0.3]: https://github.com/sebastianbergmann/comparator/compare/4.0.2...4.0.3
+[4.0.2]: https://github.com/sebastianbergmann/comparator/compare/4.0.1...4.0.2
+[4.0.1]: https://github.com/sebastianbergmann/comparator/compare/4.0.0...4.0.1
+[4.0.0]: https://github.com/sebastianbergmann/comparator/compare/3.0.2...4.0.0
+[3.0.2]: https://github.com/sebastianbergmann/comparator/compare/3.0.1...3.0.2
+[3.0.1]: https://github.com/sebastianbergmann/comparator/compare/3.0.0...3.0.1
+[3.0.0]: https://github.com/sebastianbergmann/comparator/compare/2.1.3...3.0.0
+[2.1.3]: https://github.com/sebastianbergmann/comparator/compare/2.1.2...2.1.3
+[2.1.2]: https://github.com/sebastianbergmann/comparator/compare/2.1.1...2.1.2
+[2.1.1]: https://github.com/sebastianbergmann/comparator/compare/2.1.0...2.1.1
+[2.1.0]: https://github.com/sebastianbergmann/comparator/compare/2.0.2...2.1.0
diff --git a/vendor/sebastian/comparator/LICENSE b/vendor/sebastian/comparator/LICENSE
new file mode 100644
index 0000000000000000000000000000000000000000..6ad70cbafce24870b569edfadc154e7d9b365b7d
--- /dev/null
+++ b/vendor/sebastian/comparator/LICENSE
@@ -0,0 +1,33 @@
+Comparator
+
+Copyright (c) 2002-2020, Sebastian Bergmann <sebastian@phpunit.de>.
+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 Sebastian Bergmann nor the names of his
+   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/sebastian/comparator/README.md b/vendor/sebastian/comparator/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..f6002db65f088cd3e52b1af02870b4f8985fd61a
--- /dev/null
+++ b/vendor/sebastian/comparator/README.md
@@ -0,0 +1,41 @@
+# sebastian/comparator
+
+[![CI Status](https://github.com/sebastianbergmann/comparator/workflows/CI/badge.svg)](https://github.com/sebastianbergmann/comparator/actions)
+[![Type Coverage](https://shepherd.dev/github/sebastianbergmann/comparator/coverage.svg)](https://shepherd.dev/github/sebastianbergmann/comparator)
+
+This component provides the functionality to compare PHP values for equality.
+
+## Installation
+
+You can add this library as a local, per-project dependency to your project using [Composer](https://getcomposer.org/):
+
+```
+composer require sebastian/comparator
+```
+
+If you only need this library during development, for instance to run your project's test suite, then you should add it as a development-time dependency:
+
+```
+composer require --dev sebastian/comparator
+```
+
+## Usage
+
+```php
+<?php
+use SebastianBergmann\Comparator\Factory;
+use SebastianBergmann\Comparator\ComparisonFailure;
+
+$date1 = new DateTime('2013-03-29 04:13:35', new DateTimeZone('America/New_York'));
+$date2 = new DateTime('2013-03-29 03:13:35', new DateTimeZone('America/Chicago'));
+
+$factory = new Factory;
+$comparator = $factory->getComparatorFor($date1, $date2);
+
+try {
+    $comparator->assertEquals($date1, $date2);
+    print "Dates match";
+} catch (ComparisonFailure $failure) {
+    print "Dates don't match";
+}
+```
diff --git a/vendor/sebastian/comparator/composer.json b/vendor/sebastian/comparator/composer.json
new file mode 100644
index 0000000000000000000000000000000000000000..b758e03c94cafc1b36584ee9e39850c3012b02cd
--- /dev/null
+++ b/vendor/sebastian/comparator/composer.json
@@ -0,0 +1,57 @@
+{
+    "name": "sebastian/comparator",
+    "description": "Provides the functionality to compare PHP values for equality",
+    "keywords": ["comparator","compare","equality"],
+    "homepage": "https://github.com/sebastianbergmann/comparator",
+    "license": "BSD-3-Clause",
+    "authors": [
+        {
+            "name": "Sebastian Bergmann",
+            "email": "sebastian@phpunit.de"
+        },
+        {
+            "name": "Jeff Welch",
+            "email": "whatthejeff@gmail.com"
+        },
+        {
+            "name": "Volker Dusch",
+            "email": "github@wallbash.com"
+        },
+        {
+            "name": "Bernhard Schussek",
+            "email": "bschussek@2bepublished.at"
+        }
+    ],
+    "prefer-stable": true,
+    "require": {
+        "php": ">=7.3",
+        "sebastian/diff": "^4.0",
+        "sebastian/exporter": "^4.0"
+    },
+    "require-dev": {
+        "phpunit/phpunit": "^9.3"
+    },
+    "config": {
+        "platform": {
+            "php": "7.3.0"
+        },
+        "optimize-autoloader": true,
+        "sort-packages": true
+    },
+    "autoload": {
+        "classmap": [
+            "src/"
+        ]
+    },
+    "autoload-dev": {
+        "classmap": [
+            "tests/_fixture"
+        ]
+    },
+    "extra": {
+        "branch-alias": {
+            "dev-master": "4.0-dev"
+        }
+    }
+}
+
diff --git a/vendor/sebastian/comparator/src/ArrayComparator.php b/vendor/sebastian/comparator/src/ArrayComparator.php
new file mode 100644
index 0000000000000000000000000000000000000000..5d9fbce6e1de1a5059d27bc15aa78d8e1faabdab
--- /dev/null
+++ b/vendor/sebastian/comparator/src/ArrayComparator.php
@@ -0,0 +1,141 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of sebastian/comparator.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\Comparator;
+
+use function array_key_exists;
+use function is_array;
+use function sort;
+use function sprintf;
+use function str_replace;
+use function trim;
+
+/**
+ * Compares arrays for equality.
+ *
+ * Arrays are equal if they contain the same key-value pairs.
+ * The order of the keys does not matter.
+ * The types of key-value pairs do not matter.
+ */
+class ArrayComparator extends Comparator
+{
+    /**
+     * Returns whether the comparator can compare two values.
+     *
+     * @param mixed $expected The first value to compare
+     * @param mixed $actual   The second value to compare
+     *
+     * @return bool
+     */
+    public function accepts($expected, $actual)
+    {
+        return is_array($expected) && is_array($actual);
+    }
+
+    /**
+     * Asserts that two arrays are equal.
+     *
+     * @param mixed $expected     First value to compare
+     * @param mixed $actual       Second value to compare
+     * @param float $delta        Allowed numerical distance between two values to consider them equal
+     * @param bool  $canonicalize Arrays are sorted before comparison when set to true
+     * @param bool  $ignoreCase   Case is ignored when set to true
+     * @param array $processed    List of already processed elements (used to prevent infinite recursion)
+     *
+     * @throws ComparisonFailure
+     */
+    public function assertEquals($expected, $actual, $delta = 0.0, $canonicalize = false, $ignoreCase = false, array &$processed = [])/*: void*/
+    {
+        if ($canonicalize) {
+            sort($expected);
+            sort($actual);
+        }
+
+        $remaining        = $actual;
+        $actualAsString   = "Array (\n";
+        $expectedAsString = "Array (\n";
+        $equal            = true;
+
+        foreach ($expected as $key => $value) {
+            unset($remaining[$key]);
+
+            if (!array_key_exists($key, $actual)) {
+                $expectedAsString .= sprintf(
+                    "    %s => %s\n",
+                    $this->exporter->export($key),
+                    $this->exporter->shortenedExport($value)
+                );
+
+                $equal = false;
+
+                continue;
+            }
+
+            try {
+                $comparator = $this->factory->getComparatorFor($value, $actual[$key]);
+                $comparator->assertEquals($value, $actual[$key], $delta, $canonicalize, $ignoreCase, $processed);
+
+                $expectedAsString .= sprintf(
+                    "    %s => %s\n",
+                    $this->exporter->export($key),
+                    $this->exporter->shortenedExport($value)
+                );
+
+                $actualAsString .= sprintf(
+                    "    %s => %s\n",
+                    $this->exporter->export($key),
+                    $this->exporter->shortenedExport($actual[$key])
+                );
+            } catch (ComparisonFailure $e) {
+                $expectedAsString .= sprintf(
+                    "    %s => %s\n",
+                    $this->exporter->export($key),
+                    $e->getExpectedAsString() ? $this->indent($e->getExpectedAsString()) : $this->exporter->shortenedExport($e->getExpected())
+                );
+
+                $actualAsString .= sprintf(
+                    "    %s => %s\n",
+                    $this->exporter->export($key),
+                    $e->getActualAsString() ? $this->indent($e->getActualAsString()) : $this->exporter->shortenedExport($e->getActual())
+                );
+
+                $equal = false;
+            }
+        }
+
+        foreach ($remaining as $key => $value) {
+            $actualAsString .= sprintf(
+                "    %s => %s\n",
+                $this->exporter->export($key),
+                $this->exporter->shortenedExport($value)
+            );
+
+            $equal = false;
+        }
+
+        $expectedAsString .= ')';
+        $actualAsString .= ')';
+
+        if (!$equal) {
+            throw new ComparisonFailure(
+                $expected,
+                $actual,
+                $expectedAsString,
+                $actualAsString,
+                false,
+                'Failed asserting that two arrays are equal.'
+            );
+        }
+    }
+
+    protected function indent($lines)
+    {
+        return trim(str_replace("\n", "\n    ", $lines));
+    }
+}
diff --git a/vendor/sebastian/comparator/src/Comparator.php b/vendor/sebastian/comparator/src/Comparator.php
new file mode 100644
index 0000000000000000000000000000000000000000..e1906c1679efe135d299e888d59a6fd2c31c661d
--- /dev/null
+++ b/vendor/sebastian/comparator/src/Comparator.php
@@ -0,0 +1,61 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of sebastian/comparator.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\Comparator;
+
+use SebastianBergmann\Exporter\Exporter;
+
+/**
+ * Abstract base class for comparators which compare values for equality.
+ */
+abstract class Comparator
+{
+    /**
+     * @var Factory
+     */
+    protected $factory;
+
+    /**
+     * @var Exporter
+     */
+    protected $exporter;
+
+    public function __construct()
+    {
+        $this->exporter = new Exporter;
+    }
+
+    public function setFactory(Factory $factory)/*: void*/
+    {
+        $this->factory = $factory;
+    }
+
+    /**
+     * Returns whether the comparator can compare two values.
+     *
+     * @param mixed $expected The first value to compare
+     * @param mixed $actual   The second value to compare
+     *
+     * @return bool
+     */
+    abstract public function accepts($expected, $actual);
+
+    /**
+     * Asserts that two values are equal.
+     *
+     * @param mixed $expected     First value to compare
+     * @param mixed $actual       Second value to compare
+     * @param float $delta        Allowed numerical distance between two values to consider them equal
+     * @param bool  $canonicalize Arrays are sorted before comparison when set to true
+     * @param bool  $ignoreCase   Case is ignored when set to true
+     *
+     * @throws ComparisonFailure
+     */
+    abstract public function assertEquals($expected, $actual, $delta = 0.0, $canonicalize = false, $ignoreCase = false);
+}
diff --git a/vendor/sebastian/comparator/src/ComparisonFailure.php b/vendor/sebastian/comparator/src/ComparisonFailure.php
new file mode 100644
index 0000000000000000000000000000000000000000..857314daa0334d72b2f545aa6c0b237739866c6f
--- /dev/null
+++ b/vendor/sebastian/comparator/src/ComparisonFailure.php
@@ -0,0 +1,129 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of sebastian/comparator.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\Comparator;
+
+use RuntimeException;
+use SebastianBergmann\Diff\Differ;
+use SebastianBergmann\Diff\Output\UnifiedDiffOutputBuilder;
+
+/**
+ * Thrown when an assertion for string equality failed.
+ */
+class ComparisonFailure extends RuntimeException
+{
+    /**
+     * Expected value of the retrieval which does not match $actual.
+     *
+     * @var mixed
+     */
+    protected $expected;
+
+    /**
+     * Actually retrieved value which does not match $expected.
+     *
+     * @var mixed
+     */
+    protected $actual;
+
+    /**
+     * The string representation of the expected value.
+     *
+     * @var string
+     */
+    protected $expectedAsString;
+
+    /**
+     * The string representation of the actual value.
+     *
+     * @var string
+     */
+    protected $actualAsString;
+
+    /**
+     * @var bool
+     */
+    protected $identical;
+
+    /**
+     * Optional message which is placed in front of the first line
+     * returned by toString().
+     *
+     * @var string
+     */
+    protected $message;
+
+    /**
+     * Initialises with the expected value and the actual value.
+     *
+     * @param mixed  $expected         expected value retrieved
+     * @param mixed  $actual           actual value retrieved
+     * @param string $expectedAsString
+     * @param string $actualAsString
+     * @param bool   $identical
+     * @param string $message          a string which is prefixed on all returned lines
+     *                                 in the difference output
+     */
+    public function __construct($expected, $actual, $expectedAsString, $actualAsString, $identical = false, $message = '')
+    {
+        $this->expected         = $expected;
+        $this->actual           = $actual;
+        $this->expectedAsString = $expectedAsString;
+        $this->actualAsString   = $actualAsString;
+        $this->message          = $message;
+    }
+
+    public function getActual()
+    {
+        return $this->actual;
+    }
+
+    public function getExpected()
+    {
+        return $this->expected;
+    }
+
+    /**
+     * @return string
+     */
+    public function getActualAsString()
+    {
+        return $this->actualAsString;
+    }
+
+    /**
+     * @return string
+     */
+    public function getExpectedAsString()
+    {
+        return $this->expectedAsString;
+    }
+
+    /**
+     * @return string
+     */
+    public function getDiff()
+    {
+        if (!$this->actualAsString && !$this->expectedAsString) {
+            return '';
+        }
+
+        $differ = new Differ(new UnifiedDiffOutputBuilder("\n--- Expected\n+++ Actual\n"));
+
+        return $differ->diff($this->expectedAsString, $this->actualAsString);
+    }
+
+    /**
+     * @return string
+     */
+    public function toString()
+    {
+        return $this->message . $this->getDiff();
+    }
+}
diff --git a/vendor/sebastian/comparator/src/DOMNodeComparator.php b/vendor/sebastian/comparator/src/DOMNodeComparator.php
new file mode 100644
index 0000000000000000000000000000000000000000..5bf854eaeab859c36fd7e6c995da14b328b7bf53
--- /dev/null
+++ b/vendor/sebastian/comparator/src/DOMNodeComparator.php
@@ -0,0 +1,93 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of sebastian/comparator.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\Comparator;
+
+use function sprintf;
+use function strtolower;
+use DOMDocument;
+use DOMNode;
+use ValueError;
+
+/**
+ * Compares DOMNode instances for equality.
+ */
+class DOMNodeComparator extends ObjectComparator
+{
+    /**
+     * Returns whether the comparator can compare two values.
+     *
+     * @param mixed $expected The first value to compare
+     * @param mixed $actual   The second value to compare
+     *
+     * @return bool
+     */
+    public function accepts($expected, $actual)
+    {
+        return $expected instanceof DOMNode && $actual instanceof DOMNode;
+    }
+
+    /**
+     * Asserts that two values are equal.
+     *
+     * @param mixed $expected     First value to compare
+     * @param mixed $actual       Second value to compare
+     * @param float $delta        Allowed numerical distance between two values to consider them equal
+     * @param bool  $canonicalize Arrays are sorted before comparison when set to true
+     * @param bool  $ignoreCase   Case is ignored when set to true
+     * @param array $processed    List of already processed elements (used to prevent infinite recursion)
+     *
+     * @throws ComparisonFailure
+     */
+    public function assertEquals($expected, $actual, $delta = 0.0, $canonicalize = false, $ignoreCase = false, array &$processed = [])/*: void*/
+    {
+        $expectedAsString = $this->nodeToText($expected, true, $ignoreCase);
+        $actualAsString   = $this->nodeToText($actual, true, $ignoreCase);
+
+        if ($expectedAsString !== $actualAsString) {
+            $type = $expected instanceof DOMDocument ? 'documents' : 'nodes';
+
+            throw new ComparisonFailure(
+                $expected,
+                $actual,
+                $expectedAsString,
+                $actualAsString,
+                false,
+                sprintf("Failed asserting that two DOM %s are equal.\n", $type)
+            );
+        }
+    }
+
+    /**
+     * Returns the normalized, whitespace-cleaned, and indented textual
+     * representation of a DOMNode.
+     */
+    private function nodeToText(DOMNode $node, bool $canonicalize, bool $ignoreCase): string
+    {
+        if ($canonicalize) {
+            $document = new DOMDocument;
+
+            try {
+                @$document->loadXML($node->C14N());
+            } catch (ValueError $e) {
+            }
+
+            $node = $document;
+        }
+
+        $document = $node instanceof DOMDocument ? $node : $node->ownerDocument;
+
+        $document->formatOutput = true;
+        $document->normalizeDocument();
+
+        $text = $node instanceof DOMDocument ? $node->saveXML() : $document->saveXML($node);
+
+        return $ignoreCase ? strtolower($text) : $text;
+    }
+}
diff --git a/vendor/sebastian/comparator/src/DateTimeComparator.php b/vendor/sebastian/comparator/src/DateTimeComparator.php
new file mode 100644
index 0000000000000000000000000000000000000000..0a303b623d9d1bd828ebcb0d0f5bb8ad3f0c7ab3
--- /dev/null
+++ b/vendor/sebastian/comparator/src/DateTimeComparator.php
@@ -0,0 +1,95 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of sebastian/comparator.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\Comparator;
+
+use function abs;
+use function floor;
+use function sprintf;
+use DateInterval;
+use DateTime;
+use DateTimeInterface;
+use DateTimeZone;
+use Exception;
+
+/**
+ * Compares DateTimeInterface instances for equality.
+ */
+class DateTimeComparator extends ObjectComparator
+{
+    /**
+     * Returns whether the comparator can compare two values.
+     *
+     * @param mixed $expected The first value to compare
+     * @param mixed $actual   The second value to compare
+     *
+     * @return bool
+     */
+    public function accepts($expected, $actual)
+    {
+        return ($expected instanceof DateTime || $expected instanceof DateTimeInterface) &&
+               ($actual instanceof DateTime || $actual instanceof DateTimeInterface);
+    }
+
+    /**
+     * Asserts that two values are equal.
+     *
+     * @param mixed $expected     First value to compare
+     * @param mixed $actual       Second value to compare
+     * @param float $delta        Allowed numerical distance between two values to consider them equal
+     * @param bool  $canonicalize Arrays are sorted before comparison when set to true
+     * @param bool  $ignoreCase   Case is ignored when set to true
+     * @param array $processed    List of already processed elements (used to prevent infinite recursion)
+     *
+     * @throws Exception
+     * @throws ComparisonFailure
+     */
+    public function assertEquals($expected, $actual, $delta = 0.0, $canonicalize = false, $ignoreCase = false, array &$processed = [])/*: void*/
+    {
+        /** @var DateTimeInterface $expected */
+        /** @var DateTimeInterface $actual */
+        $absDelta = abs($delta);
+        $delta    = new DateInterval(sprintf('PT%dS', $absDelta));
+        $delta->f = $absDelta - floor($absDelta);
+
+        $actualClone = (clone $actual)
+            ->setTimezone(new DateTimeZone('UTC'));
+
+        $expectedLower = (clone $expected)
+            ->setTimezone(new DateTimeZone('UTC'))
+            ->sub($delta);
+
+        $expectedUpper = (clone $expected)
+            ->setTimezone(new DateTimeZone('UTC'))
+            ->add($delta);
+
+        if ($actualClone < $expectedLower || $actualClone > $expectedUpper) {
+            throw new ComparisonFailure(
+                $expected,
+                $actual,
+                $this->dateTimeToString($expected),
+                $this->dateTimeToString($actual),
+                false,
+                'Failed asserting that two DateTime objects are equal.'
+            );
+        }
+    }
+
+    /**
+     * Returns an ISO 8601 formatted string representation of a datetime or
+     * 'Invalid DateTimeInterface object' if the provided DateTimeInterface was not properly
+     * initialized.
+     */
+    private function dateTimeToString(DateTimeInterface $datetime): string
+    {
+        $string = $datetime->format('Y-m-d\TH:i:s.uO');
+
+        return $string ?: 'Invalid DateTimeInterface object';
+    }
+}
diff --git a/vendor/sebastian/comparator/src/DoubleComparator.php b/vendor/sebastian/comparator/src/DoubleComparator.php
new file mode 100644
index 0000000000000000000000000000000000000000..d90b9e06bfd4e5f569a9ee7f7bc9f6bc97477268
--- /dev/null
+++ b/vendor/sebastian/comparator/src/DoubleComparator.php
@@ -0,0 +1,59 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of sebastian/comparator.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\Comparator;
+
+use function is_float;
+use function is_numeric;
+
+/**
+ * Compares doubles for equality.
+ */
+class DoubleComparator extends NumericComparator
+{
+    /**
+     * Smallest value available in PHP.
+     *
+     * @var float
+     */
+    public const EPSILON = 0.0000000001;
+
+    /**
+     * Returns whether the comparator can compare two values.
+     *
+     * @param mixed $expected The first value to compare
+     * @param mixed $actual   The second value to compare
+     *
+     * @return bool
+     */
+    public function accepts($expected, $actual)
+    {
+        return (is_float($expected) || is_float($actual)) && is_numeric($expected) && is_numeric($actual);
+    }
+
+    /**
+     * Asserts that two values are equal.
+     *
+     * @param mixed $expected     First value to compare
+     * @param mixed $actual       Second value to compare
+     * @param float $delta        Allowed numerical distance between two values to consider them equal
+     * @param bool  $canonicalize Arrays are sorted before comparison when set to true
+     * @param bool  $ignoreCase   Case is ignored when set to true
+     *
+     * @throws ComparisonFailure
+     */
+    public function assertEquals($expected, $actual, $delta = 0.0, $canonicalize = false, $ignoreCase = false)/*: void*/
+    {
+        if ($delta == 0) {
+            $delta = self::EPSILON;
+        }
+
+        parent::assertEquals($expected, $actual, $delta, $canonicalize, $ignoreCase);
+    }
+}
diff --git a/vendor/sebastian/comparator/src/ExceptionComparator.php b/vendor/sebastian/comparator/src/ExceptionComparator.php
new file mode 100644
index 0000000000000000000000000000000000000000..1fc0174efbf1c82a70c700beddc143c3a6a23db2
--- /dev/null
+++ b/vendor/sebastian/comparator/src/ExceptionComparator.php
@@ -0,0 +1,54 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of sebastian/comparator.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\Comparator;
+
+use Exception;
+
+/**
+ * Compares Exception instances for equality.
+ */
+class ExceptionComparator extends ObjectComparator
+{
+    /**
+     * Returns whether the comparator can compare two values.
+     *
+     * @param mixed $expected The first value to compare
+     * @param mixed $actual   The second value to compare
+     *
+     * @return bool
+     */
+    public function accepts($expected, $actual)
+    {
+        return $expected instanceof Exception && $actual instanceof Exception;
+    }
+
+    /**
+     * Converts an object to an array containing all of its private, protected
+     * and public properties.
+     *
+     * @param object $object
+     *
+     * @return array
+     */
+    protected function toArray($object)
+    {
+        $array = parent::toArray($object);
+
+        unset(
+            $array['file'],
+            $array['line'],
+            $array['trace'],
+            $array['string'],
+            $array['xdebug_message']
+        );
+
+        return $array;
+    }
+}
diff --git a/vendor/sebastian/comparator/src/Factory.php b/vendor/sebastian/comparator/src/Factory.php
new file mode 100644
index 0000000000000000000000000000000000000000..5b16366f043bfc5b9630c6a76fd25dac988927ac
--- /dev/null
+++ b/vendor/sebastian/comparator/src/Factory.php
@@ -0,0 +1,142 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of sebastian/comparator.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\Comparator;
+
+use function array_unshift;
+
+/**
+ * Factory for comparators which compare values for equality.
+ */
+class Factory
+{
+    /**
+     * @var Factory
+     */
+    private static $instance;
+
+    /**
+     * @var Comparator[]
+     */
+    private $customComparators = [];
+
+    /**
+     * @var Comparator[]
+     */
+    private $defaultComparators = [];
+
+    /**
+     * @return Factory
+     */
+    public static function getInstance()
+    {
+        if (self::$instance === null) {
+            self::$instance = new self; // @codeCoverageIgnore
+        }
+
+        return self::$instance;
+    }
+
+    /**
+     * Constructs a new factory.
+     */
+    public function __construct()
+    {
+        $this->registerDefaultComparators();
+    }
+
+    /**
+     * Returns the correct comparator for comparing two values.
+     *
+     * @param mixed $expected The first value to compare
+     * @param mixed $actual   The second value to compare
+     *
+     * @return Comparator
+     */
+    public function getComparatorFor($expected, $actual)
+    {
+        foreach ($this->customComparators as $comparator) {
+            if ($comparator->accepts($expected, $actual)) {
+                return $comparator;
+            }
+        }
+
+        foreach ($this->defaultComparators as $comparator) {
+            if ($comparator->accepts($expected, $actual)) {
+                return $comparator;
+            }
+        }
+
+        throw new RuntimeException('No suitable Comparator implementation found');
+    }
+
+    /**
+     * Registers a new comparator.
+     *
+     * This comparator will be returned by getComparatorFor() if its accept() method
+     * returns TRUE for the compared values. It has higher priority than the
+     * existing comparators, meaning that its accept() method will be invoked
+     * before those of the other comparators.
+     *
+     * @param Comparator $comparator The comparator to be registered
+     */
+    public function register(Comparator $comparator)/*: void*/
+    {
+        array_unshift($this->customComparators, $comparator);
+
+        $comparator->setFactory($this);
+    }
+
+    /**
+     * Unregisters a comparator.
+     *
+     * This comparator will no longer be considered by getComparatorFor().
+     *
+     * @param Comparator $comparator The comparator to be unregistered
+     */
+    public function unregister(Comparator $comparator)/*: void*/
+    {
+        foreach ($this->customComparators as $key => $_comparator) {
+            if ($comparator === $_comparator) {
+                unset($this->customComparators[$key]);
+            }
+        }
+    }
+
+    /**
+     * Unregisters all non-default comparators.
+     */
+    public function reset()/*: void*/
+    {
+        $this->customComparators = [];
+    }
+
+    private function registerDefaultComparators(): void
+    {
+        $this->registerDefaultComparator(new MockObjectComparator);
+        $this->registerDefaultComparator(new DateTimeComparator);
+        $this->registerDefaultComparator(new DOMNodeComparator);
+        $this->registerDefaultComparator(new SplObjectStorageComparator);
+        $this->registerDefaultComparator(new ExceptionComparator);
+        $this->registerDefaultComparator(new ObjectComparator);
+        $this->registerDefaultComparator(new ResourceComparator);
+        $this->registerDefaultComparator(new ArrayComparator);
+        $this->registerDefaultComparator(new DoubleComparator);
+        $this->registerDefaultComparator(new NumericComparator);
+        $this->registerDefaultComparator(new ScalarComparator);
+        $this->registerDefaultComparator(new TypeComparator);
+    }
+
+    private function registerDefaultComparator(Comparator $comparator): void
+    {
+        $this->defaultComparators[] = $comparator;
+
+        $comparator->setFactory($this);
+    }
+}
diff --git a/vendor/sebastian/comparator/src/MockObjectComparator.php b/vendor/sebastian/comparator/src/MockObjectComparator.php
new file mode 100644
index 0000000000000000000000000000000000000000..cb6703161323068bb94d82a9a500a6f78894794c
--- /dev/null
+++ b/vendor/sebastian/comparator/src/MockObjectComparator.php
@@ -0,0 +1,48 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of sebastian/comparator.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\Comparator;
+
+use PHPUnit\Framework\MockObject\MockObject;
+
+/**
+ * Compares PHPUnit\Framework\MockObject\MockObject instances for equality.
+ */
+class MockObjectComparator extends ObjectComparator
+{
+    /**
+     * Returns whether the comparator can compare two values.
+     *
+     * @param mixed $expected The first value to compare
+     * @param mixed $actual   The second value to compare
+     *
+     * @return bool
+     */
+    public function accepts($expected, $actual)
+    {
+        return $expected instanceof MockObject && $actual instanceof MockObject;
+    }
+
+    /**
+     * Converts an object to an array containing all of its private, protected
+     * and public properties.
+     *
+     * @param object $object
+     *
+     * @return array
+     */
+    protected function toArray($object)
+    {
+        $array = parent::toArray($object);
+
+        unset($array['__phpunit_invocationMocker']);
+
+        return $array;
+    }
+}
diff --git a/vendor/sebastian/comparator/src/NumericComparator.php b/vendor/sebastian/comparator/src/NumericComparator.php
new file mode 100644
index 0000000000000000000000000000000000000000..12e6721d66551507f437a82c68b00dd173c9042a
--- /dev/null
+++ b/vendor/sebastian/comparator/src/NumericComparator.php
@@ -0,0 +1,86 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of sebastian/comparator.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\Comparator;
+
+use function abs;
+use function is_float;
+use function is_infinite;
+use function is_nan;
+use function is_numeric;
+use function is_string;
+use function sprintf;
+
+/**
+ * Compares numerical values for equality.
+ */
+class NumericComparator extends ScalarComparator
+{
+    /**
+     * Returns whether the comparator can compare two values.
+     *
+     * @param mixed $expected The first value to compare
+     * @param mixed $actual   The second value to compare
+     *
+     * @return bool
+     */
+    public function accepts($expected, $actual)
+    {
+        // all numerical values, but not if one of them is a double
+        // or both of them are strings
+        return is_numeric($expected) && is_numeric($actual) &&
+               !(is_float($expected) || is_float($actual)) &&
+               !(is_string($expected) && is_string($actual));
+    }
+
+    /**
+     * Asserts that two values are equal.
+     *
+     * @param mixed $expected     First value to compare
+     * @param mixed $actual       Second value to compare
+     * @param float $delta        Allowed numerical distance between two values to consider them equal
+     * @param bool  $canonicalize Arrays are sorted before comparison when set to true
+     * @param bool  $ignoreCase   Case is ignored when set to true
+     *
+     * @throws ComparisonFailure
+     */
+    public function assertEquals($expected, $actual, $delta = 0.0, $canonicalize = false, $ignoreCase = false)/*: void*/
+    {
+        if ($this->isInfinite($actual) && $this->isInfinite($expected)) {
+            return;
+        }
+
+        if (($this->isInfinite($actual) xor $this->isInfinite($expected)) ||
+            ($this->isNan($actual) || $this->isNan($expected)) ||
+            abs($actual - $expected) > $delta) {
+            throw new ComparisonFailure(
+                $expected,
+                $actual,
+                '',
+                '',
+                false,
+                sprintf(
+                    'Failed asserting that %s matches expected %s.',
+                    $this->exporter->export($actual),
+                    $this->exporter->export($expected)
+                )
+            );
+        }
+    }
+
+    private function isInfinite($value): bool
+    {
+        return is_float($value) && is_infinite($value);
+    }
+
+    private function isNan($value): bool
+    {
+        return is_float($value) && is_nan($value);
+    }
+}
diff --git a/vendor/sebastian/comparator/src/ObjectComparator.php b/vendor/sebastian/comparator/src/ObjectComparator.php
new file mode 100644
index 0000000000000000000000000000000000000000..9380ba1508c64295688c105b609eeedc5a4779a4
--- /dev/null
+++ b/vendor/sebastian/comparator/src/ObjectComparator.php
@@ -0,0 +1,112 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of sebastian/comparator.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\Comparator;
+
+use function get_class;
+use function in_array;
+use function is_object;
+use function sprintf;
+use function substr_replace;
+
+/**
+ * Compares objects for equality.
+ */
+class ObjectComparator extends ArrayComparator
+{
+    /**
+     * Returns whether the comparator can compare two values.
+     *
+     * @param mixed $expected The first value to compare
+     * @param mixed $actual   The second value to compare
+     *
+     * @return bool
+     */
+    public function accepts($expected, $actual)
+    {
+        return is_object($expected) && is_object($actual);
+    }
+
+    /**
+     * Asserts that two values are equal.
+     *
+     * @param mixed $expected     First value to compare
+     * @param mixed $actual       Second value to compare
+     * @param float $delta        Allowed numerical distance between two values to consider them equal
+     * @param bool  $canonicalize Arrays are sorted before comparison when set to true
+     * @param bool  $ignoreCase   Case is ignored when set to true
+     * @param array $processed    List of already processed elements (used to prevent infinite recursion)
+     *
+     * @throws ComparisonFailure
+     */
+    public function assertEquals($expected, $actual, $delta = 0.0, $canonicalize = false, $ignoreCase = false, array &$processed = [])/*: void*/
+    {
+        if (get_class($actual) !== get_class($expected)) {
+            throw new ComparisonFailure(
+                $expected,
+                $actual,
+                $this->exporter->export($expected),
+                $this->exporter->export($actual),
+                false,
+                sprintf(
+                    '%s is not instance of expected class "%s".',
+                    $this->exporter->export($actual),
+                    get_class($expected)
+                )
+            );
+        }
+
+        // don't compare twice to allow for cyclic dependencies
+        if (in_array([$actual, $expected], $processed, true) ||
+            in_array([$expected, $actual], $processed, true)) {
+            return;
+        }
+
+        $processed[] = [$actual, $expected];
+
+        // don't compare objects if they are identical
+        // this helps to avoid the error "maximum function nesting level reached"
+        // CAUTION: this conditional clause is not tested
+        if ($actual !== $expected) {
+            try {
+                parent::assertEquals(
+                    $this->toArray($expected),
+                    $this->toArray($actual),
+                    $delta,
+                    $canonicalize,
+                    $ignoreCase,
+                    $processed
+                );
+            } catch (ComparisonFailure $e) {
+                throw new ComparisonFailure(
+                    $expected,
+                    $actual,
+                    // replace "Array" with "MyClass object"
+                    substr_replace($e->getExpectedAsString(), get_class($expected) . ' Object', 0, 5),
+                    substr_replace($e->getActualAsString(), get_class($actual) . ' Object', 0, 5),
+                    false,
+                    'Failed asserting that two objects are equal.'
+                );
+            }
+        }
+    }
+
+    /**
+     * Converts an object to an array containing all of its private, protected
+     * and public properties.
+     *
+     * @param object $object
+     *
+     * @return array
+     */
+    protected function toArray($object)
+    {
+        return $this->exporter->toArray($object);
+    }
+}
diff --git a/vendor/sebastian/comparator/src/ResourceComparator.php b/vendor/sebastian/comparator/src/ResourceComparator.php
new file mode 100644
index 0000000000000000000000000000000000000000..7822598b1c31c406a81b5ed72b5f03194e6125cb
--- /dev/null
+++ b/vendor/sebastian/comparator/src/ResourceComparator.php
@@ -0,0 +1,54 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of sebastian/comparator.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\Comparator;
+
+use function is_resource;
+
+/**
+ * Compares resources for equality.
+ */
+class ResourceComparator extends Comparator
+{
+    /**
+     * Returns whether the comparator can compare two values.
+     *
+     * @param mixed $expected The first value to compare
+     * @param mixed $actual   The second value to compare
+     *
+     * @return bool
+     */
+    public function accepts($expected, $actual)
+    {
+        return is_resource($expected) && is_resource($actual);
+    }
+
+    /**
+     * Asserts that two values are equal.
+     *
+     * @param mixed $expected     First value to compare
+     * @param mixed $actual       Second value to compare
+     * @param float $delta        Allowed numerical distance between two values to consider them equal
+     * @param bool  $canonicalize Arrays are sorted before comparison when set to true
+     * @param bool  $ignoreCase   Case is ignored when set to true
+     *
+     * @throws ComparisonFailure
+     */
+    public function assertEquals($expected, $actual, $delta = 0.0, $canonicalize = false, $ignoreCase = false)/*: void*/
+    {
+        if ($actual != $expected) {
+            throw new ComparisonFailure(
+                $expected,
+                $actual,
+                $this->exporter->export($expected),
+                $this->exporter->export($actual)
+            );
+        }
+    }
+}
diff --git a/vendor/sebastian/comparator/src/ScalarComparator.php b/vendor/sebastian/comparator/src/ScalarComparator.php
new file mode 100644
index 0000000000000000000000000000000000000000..08ded922b653de6da9859d04ba07effdecb157ef
--- /dev/null
+++ b/vendor/sebastian/comparator/src/ScalarComparator.php
@@ -0,0 +1,98 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of sebastian/comparator.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\Comparator;
+
+use function is_object;
+use function is_scalar;
+use function is_string;
+use function method_exists;
+use function sprintf;
+use function strtolower;
+
+/**
+ * Compares scalar or NULL values for equality.
+ */
+class ScalarComparator extends Comparator
+{
+    /**
+     * Returns whether the comparator can compare two values.
+     *
+     * @param mixed $expected The first value to compare
+     * @param mixed $actual   The second value to compare
+     *
+     * @return bool
+     *
+     * @since  Method available since Release 3.6.0
+     */
+    public function accepts($expected, $actual)
+    {
+        return ((is_scalar($expected) xor null === $expected) &&
+               (is_scalar($actual) xor null === $actual))
+               // allow comparison between strings and objects featuring __toString()
+               || (is_string($expected) && is_object($actual) && method_exists($actual, '__toString'))
+               || (is_object($expected) && method_exists($expected, '__toString') && is_string($actual));
+    }
+
+    /**
+     * Asserts that two values are equal.
+     *
+     * @param mixed $expected     First value to compare
+     * @param mixed $actual       Second value to compare
+     * @param float $delta        Allowed numerical distance between two values to consider them equal
+     * @param bool  $canonicalize Arrays are sorted before comparison when set to true
+     * @param bool  $ignoreCase   Case is ignored when set to true
+     *
+     * @throws ComparisonFailure
+     */
+    public function assertEquals($expected, $actual, $delta = 0.0, $canonicalize = false, $ignoreCase = false)/*: void*/
+    {
+        $expectedToCompare = $expected;
+        $actualToCompare   = $actual;
+
+        // always compare as strings to avoid strange behaviour
+        // otherwise 0 == 'Foobar'
+        if (is_string($expected) || is_string($actual)) {
+            $expectedToCompare = (string) $expectedToCompare;
+            $actualToCompare   = (string) $actualToCompare;
+
+            if ($ignoreCase) {
+                $expectedToCompare = strtolower($expectedToCompare);
+                $actualToCompare   = strtolower($actualToCompare);
+            }
+        }
+
+        if ($expectedToCompare !== $actualToCompare && is_string($expected) && is_string($actual)) {
+            throw new ComparisonFailure(
+                $expected,
+                $actual,
+                $this->exporter->export($expected),
+                $this->exporter->export($actual),
+                false,
+                'Failed asserting that two strings are equal.'
+            );
+        }
+
+        if ($expectedToCompare != $actualToCompare) {
+            throw new ComparisonFailure(
+                $expected,
+                $actual,
+                // no diff is required
+                '',
+                '',
+                false,
+                sprintf(
+                    'Failed asserting that %s matches expected %s.',
+                    $this->exporter->export($actual),
+                    $this->exporter->export($expected)
+                )
+            );
+        }
+    }
+}
diff --git a/vendor/sebastian/comparator/src/SplObjectStorageComparator.php b/vendor/sebastian/comparator/src/SplObjectStorageComparator.php
new file mode 100644
index 0000000000000000000000000000000000000000..d9b6f541a6dc1b148895cce8b65d5de5c4ab8ed8
--- /dev/null
+++ b/vendor/sebastian/comparator/src/SplObjectStorageComparator.php
@@ -0,0 +1,71 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of sebastian/comparator.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\Comparator;
+
+use SplObjectStorage;
+
+/**
+ * Compares \SplObjectStorage instances for equality.
+ */
+class SplObjectStorageComparator extends Comparator
+{
+    /**
+     * Returns whether the comparator can compare two values.
+     *
+     * @param mixed $expected The first value to compare
+     * @param mixed $actual   The second value to compare
+     *
+     * @return bool
+     */
+    public function accepts($expected, $actual)
+    {
+        return $expected instanceof SplObjectStorage && $actual instanceof SplObjectStorage;
+    }
+
+    /**
+     * Asserts that two values are equal.
+     *
+     * @param mixed $expected     First value to compare
+     * @param mixed $actual       Second value to compare
+     * @param float $delta        Allowed numerical distance between two values to consider them equal
+     * @param bool  $canonicalize Arrays are sorted before comparison when set to true
+     * @param bool  $ignoreCase   Case is ignored when set to true
+     *
+     * @throws ComparisonFailure
+     */
+    public function assertEquals($expected, $actual, $delta = 0.0, $canonicalize = false, $ignoreCase = false)/*: void*/
+    {
+        foreach ($actual as $object) {
+            if (!$expected->contains($object)) {
+                throw new ComparisonFailure(
+                    $expected,
+                    $actual,
+                    $this->exporter->export($expected),
+                    $this->exporter->export($actual),
+                    false,
+                    'Failed asserting that two objects are equal.'
+                );
+            }
+        }
+
+        foreach ($expected as $object) {
+            if (!$actual->contains($object)) {
+                throw new ComparisonFailure(
+                    $expected,
+                    $actual,
+                    $this->exporter->export($expected),
+                    $this->exporter->export($actual),
+                    false,
+                    'Failed asserting that two objects are equal.'
+                );
+            }
+        }
+    }
+}
diff --git a/vendor/sebastian/comparator/src/TypeComparator.php b/vendor/sebastian/comparator/src/TypeComparator.php
new file mode 100644
index 0000000000000000000000000000000000000000..b0d38d72edb5c1b36d2047b819248047267823b4
--- /dev/null
+++ b/vendor/sebastian/comparator/src/TypeComparator.php
@@ -0,0 +1,62 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of sebastian/comparator.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\Comparator;
+
+use function gettype;
+use function sprintf;
+
+/**
+ * Compares values for type equality.
+ */
+class TypeComparator extends Comparator
+{
+    /**
+     * Returns whether the comparator can compare two values.
+     *
+     * @param mixed $expected The first value to compare
+     * @param mixed $actual   The second value to compare
+     *
+     * @return bool
+     */
+    public function accepts($expected, $actual)
+    {
+        return true;
+    }
+
+    /**
+     * Asserts that two values are equal.
+     *
+     * @param mixed $expected     First value to compare
+     * @param mixed $actual       Second value to compare
+     * @param float $delta        Allowed numerical distance between two values to consider them equal
+     * @param bool  $canonicalize Arrays are sorted before comparison when set to true
+     * @param bool  $ignoreCase   Case is ignored when set to true
+     *
+     * @throws ComparisonFailure
+     */
+    public function assertEquals($expected, $actual, $delta = 0.0, $canonicalize = false, $ignoreCase = false)/*: void*/
+    {
+        if (gettype($expected) != gettype($actual)) {
+            throw new ComparisonFailure(
+                $expected,
+                $actual,
+                // we don't need a diff
+                '',
+                '',
+                false,
+                sprintf(
+                    '%s does not match expected type "%s".',
+                    $this->exporter->shortenedExport($actual),
+                    gettype($expected)
+                )
+            );
+        }
+    }
+}
diff --git a/vendor/sebastian/comparator/src/exceptions/Exception.php b/vendor/sebastian/comparator/src/exceptions/Exception.php
new file mode 100644
index 0000000000000000000000000000000000000000..8975aaf1b968fcba422bb0a6ad0e1840a6e2a6b9
--- /dev/null
+++ b/vendor/sebastian/comparator/src/exceptions/Exception.php
@@ -0,0 +1,16 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of sebastian/comparator.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\Comparator;
+
+use Throwable;
+
+interface Exception extends Throwable
+{
+}
diff --git a/vendor/sebastian/comparator/src/exceptions/RuntimeException.php b/vendor/sebastian/comparator/src/exceptions/RuntimeException.php
new file mode 100644
index 0000000000000000000000000000000000000000..ca726084a779c3dbb6342ad7e4cf59d2e66ea143
--- /dev/null
+++ b/vendor/sebastian/comparator/src/exceptions/RuntimeException.php
@@ -0,0 +1,14 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of sebastian/comparator.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\Comparator;
+
+final class RuntimeException extends \RuntimeException implements Exception
+{
+}
diff --git a/vendor/sebastian/complexity/.psalm/baseline.xml b/vendor/sebastian/complexity/.psalm/baseline.xml
new file mode 100644
index 0000000000000000000000000000000000000000..77e688e07efe46415e5eaee84fbc946c36b82bcb
--- /dev/null
+++ b/vendor/sebastian/complexity/.psalm/baseline.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<files psalm-version="4.0.1@b1e2e30026936ef8d5bf6a354d1c3959b6231f44"/>
diff --git a/vendor/sebastian/complexity/.psalm/config.xml b/vendor/sebastian/complexity/.psalm/config.xml
new file mode 100644
index 0000000000000000000000000000000000000000..8172fe15a6e7c509a6f17421da4944f4801623f0
--- /dev/null
+++ b/vendor/sebastian/complexity/.psalm/config.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0"?>
+<psalm
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xmlns="https://getpsalm.org/schema/config"
+    xsi:schemaLocation="https://getpsalm.org/schema/config vendor/vimeo/psalm/config.xsd"
+    resolveFromConfigFile="false"
+    errorBaseline=".psalm/baseline.xml"
+    totallyTyped="true"
+>
+    <projectFiles>
+        <directory name="src" />
+        <ignoreFiles>
+            <directory name="vendor" />
+        </ignoreFiles>
+    </projectFiles>
+</psalm>
diff --git a/vendor/sebastian/complexity/ChangeLog.md b/vendor/sebastian/complexity/ChangeLog.md
new file mode 100644
index 0000000000000000000000000000000000000000..cb93ff62010101f48be7d3ff7257bd604fd53add
--- /dev/null
+++ b/vendor/sebastian/complexity/ChangeLog.md
@@ -0,0 +1,30 @@
+# ChangeLog
+
+All notable changes are documented in this file using the [Keep a CHANGELOG](https://keepachangelog.com/) principles.
+
+## [2.0.2] - 2020-10-26
+
+### Fixed
+
+* `SebastianBergmann\Complexity\Exception` now correctly extends `\Throwable`
+
+## [2.0.1] - 2020-09-28
+
+### Changed
+
+* Changed PHP version constraint in `composer.json` from `^7.3 || ^8.0` to `>=7.3`
+
+## [2.0.0] - 2020-07-25
+
+### Removed
+
+* The `ParentConnectingVisitor` has been removed (it should have been marked as `@internal`)
+
+## [1.0.0] - 2020-07-22
+
+* Initial release
+
+[2.0.2]: https://github.com/sebastianbergmann/complexity/compare/2.0.1...2.0.2
+[2.0.1]: https://github.com/sebastianbergmann/complexity/compare/2.0.0...2.0.1
+[2.0.0]: https://github.com/sebastianbergmann/complexity/compare/1.0.0...2.0.0
+[1.0.0]: https://github.com/sebastianbergmann/complexity/compare/70ee0ad32d9e2be3f85beffa3e2eb474193f2487...1.0.0
diff --git a/vendor/sebastian/complexity/LICENSE b/vendor/sebastian/complexity/LICENSE
new file mode 100644
index 0000000000000000000000000000000000000000..5f818df69502e98c923d4d077fb485ff462a6297
--- /dev/null
+++ b/vendor/sebastian/complexity/LICENSE
@@ -0,0 +1,33 @@
+sebastian/complexity
+
+Copyright (c) 2020, Sebastian Bergmann <sebastian@phpunit.de>.
+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 Sebastian Bergmann nor the names of his
+   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/sebastian/complexity/README.md b/vendor/sebastian/complexity/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..5f53b0b5dd5e222d14ea7be053457f86c96bf12f
--- /dev/null
+++ b/vendor/sebastian/complexity/README.md
@@ -0,0 +1,22 @@
+# sebastian/complexity
+
+Library for calculating the complexity of PHP code units.
+
+[![Latest Stable Version](https://img.shields.io/packagist/v/sebastian/complexity.svg?style=flat-square)](https://packagist.org/packages/sebastian/complexity)
+[![Minimum PHP Version](https://img.shields.io/badge/php-%3E%3D%207.3-8892BF.svg?style=flat-square)](https://php.net/)
+[![CI Status](https://github.com/sebastianbergmann/complexity/workflows/CI/badge.svg?branch=master&event=push)](https://phpunit.de/build-status.html)
+[![Type Coverage](https://shepherd.dev/github/sebastianbergmann/complexity/coverage.svg)](https://shepherd.dev/github/sebastianbergmann/complexity)
+
+## Installation
+
+You can add this library as a local, per-project dependency to your project using [Composer](https://getcomposer.org/):
+
+```
+composer require sebastian/complexity
+```
+
+If you only need this library during development, for instance to run your project's test suite, then you should add it as a development-time dependency:
+
+```
+composer require --dev sebastian/complexity
+```
diff --git a/vendor/sebastian/complexity/composer.json b/vendor/sebastian/complexity/composer.json
new file mode 100644
index 0000000000000000000000000000000000000000..7aa38314eced55b3093e169f9a75972bddd34a85
--- /dev/null
+++ b/vendor/sebastian/complexity/composer.json
@@ -0,0 +1,41 @@
+{
+    "name": "sebastian/complexity",
+    "description": "Library for calculating the complexity of PHP code units",
+    "type": "library",
+    "homepage": "https://github.com/sebastianbergmann/complexity",
+    "license": "BSD-3-Clause",
+    "authors": [
+        {
+            "name": "Sebastian Bergmann",
+            "email": "sebastian@phpunit.de",
+            "role": "lead"
+        }
+    ],
+    "support": {
+        "issues": "https://github.com/sebastianbergmann/complexity/issues"
+    },
+    "require": {
+        "php": ">=7.3",
+        "nikic/php-parser": "^4.7"
+    },
+    "require-dev": {
+        "phpunit/phpunit": "^9.3"
+    },
+    "config": {
+        "platform": {
+            "php": "7.3.0"
+        },
+        "optimize-autoloader": true,
+        "sort-packages": true
+    },
+    "autoload": {
+        "classmap": [
+            "src/"
+        ]
+    },
+    "extra": {
+        "branch-alias": {
+            "dev-master": "2.0-dev"
+        }
+    }
+}
diff --git a/vendor/sebastian/complexity/src/Calculator.php b/vendor/sebastian/complexity/src/Calculator.php
new file mode 100644
index 0000000000000000000000000000000000000000..9abdcd1691de3ccb99548b87cfc2b801ddfff0c4
--- /dev/null
+++ b/vendor/sebastian/complexity/src/Calculator.php
@@ -0,0 +1,88 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of sebastian/complexity.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\Complexity;
+
+use PhpParser\Error;
+use PhpParser\Lexer;
+use PhpParser\Node;
+use PhpParser\NodeTraverser;
+use PhpParser\NodeVisitor\NameResolver;
+use PhpParser\NodeVisitor\ParentConnectingVisitor;
+use PhpParser\Parser;
+use PhpParser\ParserFactory;
+
+final class Calculator
+{
+    /**
+     * @throws RuntimeException
+     */
+    public function calculateForSourceFile(string $sourceFile): ComplexityCollection
+    {
+        return $this->calculateForSourceString(file_get_contents($sourceFile));
+    }
+
+    /**
+     * @throws RuntimeException
+     */
+    public function calculateForSourceString(string $source): ComplexityCollection
+    {
+        try {
+            $nodes = $this->parser()->parse($source);
+
+            assert($nodes !== null);
+
+            return $this->calculateForAbstractSyntaxTree($nodes);
+
+            // @codeCoverageIgnoreStart
+        } catch (Error $error) {
+            throw new RuntimeException(
+                $error->getMessage(),
+                (int) $error->getCode(),
+                $error
+            );
+        }
+        // @codeCoverageIgnoreEnd
+    }
+
+    /**
+     * @param Node[] $nodes
+     *
+     * @throws RuntimeException
+     */
+    public function calculateForAbstractSyntaxTree(array $nodes): ComplexityCollection
+    {
+        $traverser                    = new NodeTraverser;
+        $complexityCalculatingVisitor = new ComplexityCalculatingVisitor(true);
+
+        $traverser->addVisitor(new NameResolver);
+        $traverser->addVisitor(new ParentConnectingVisitor);
+        $traverser->addVisitor($complexityCalculatingVisitor);
+
+        try {
+            /* @noinspection UnusedFunctionResultInspection */
+            $traverser->traverse($nodes);
+            // @codeCoverageIgnoreStart
+        } catch (Error $error) {
+            throw new RuntimeException(
+                $error->getMessage(),
+                (int) $error->getCode(),
+                $error
+            );
+        }
+        // @codeCoverageIgnoreEnd
+
+        return $complexityCalculatingVisitor->result();
+    }
+
+    private function parser(): Parser
+    {
+        return (new ParserFactory)->create(ParserFactory::PREFER_PHP7, new Lexer);
+    }
+}
diff --git a/vendor/sebastian/complexity/src/Complexity/Complexity.php b/vendor/sebastian/complexity/src/Complexity/Complexity.php
new file mode 100644
index 0000000000000000000000000000000000000000..dc6708ddef5fd224359b4feae4f342bd37dc8467
--- /dev/null
+++ b/vendor/sebastian/complexity/src/Complexity/Complexity.php
@@ -0,0 +1,42 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of sebastian/complexity.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\Complexity;
+
+/**
+ * @psalm-immutable
+ */
+final class Complexity
+{
+    /**
+     * @var string
+     */
+    private $name;
+
+    /**
+     * @var int
+     */
+    private $cyclomaticComplexity;
+
+    public function __construct(string $name, int $cyclomaticComplexity)
+    {
+        $this->name                 = $name;
+        $this->cyclomaticComplexity = $cyclomaticComplexity;
+    }
+
+    public function name(): string
+    {
+        return $this->name;
+    }
+
+    public function cyclomaticComplexity(): int
+    {
+        return $this->cyclomaticComplexity;
+    }
+}
diff --git a/vendor/sebastian/complexity/src/Complexity/ComplexityCollection.php b/vendor/sebastian/complexity/src/Complexity/ComplexityCollection.php
new file mode 100644
index 0000000000000000000000000000000000000000..ccbddbf7742680ee8ee081370767edfe4fe79bd9
--- /dev/null
+++ b/vendor/sebastian/complexity/src/Complexity/ComplexityCollection.php
@@ -0,0 +1,72 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of sebastian/complexity.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\Complexity;
+
+use function count;
+use Countable;
+use IteratorAggregate;
+
+/**
+ * @psalm-immutable
+ */
+final class ComplexityCollection implements Countable, IteratorAggregate
+{
+    /**
+     * @psalm-var list<Complexity>
+     */
+    private $items = [];
+
+    public static function fromList(Complexity ...$items): self
+    {
+        return new self($items);
+    }
+
+    /**
+     * @psalm-param list<Complexity> $items
+     */
+    private function __construct(array $items)
+    {
+        $this->items = $items;
+    }
+
+    /**
+     * @psalm-return list<Complexity>
+     */
+    public function asArray(): array
+    {
+        return $this->items;
+    }
+
+    public function getIterator(): ComplexityCollectionIterator
+    {
+        return new ComplexityCollectionIterator($this);
+    }
+
+    public function count(): int
+    {
+        return count($this->items);
+    }
+
+    public function isEmpty(): bool
+    {
+        return empty($this->items);
+    }
+
+    public function cyclomaticComplexity(): int
+    {
+        $cyclomaticComplexity = 0;
+
+        foreach ($this as $item) {
+            $cyclomaticComplexity += $item->cyclomaticComplexity();
+        }
+
+        return $cyclomaticComplexity;
+    }
+}
diff --git a/vendor/sebastian/complexity/src/Complexity/ComplexityCollectionIterator.php b/vendor/sebastian/complexity/src/Complexity/ComplexityCollectionIterator.php
new file mode 100644
index 0000000000000000000000000000000000000000..ec39e199fef8c843017cc0558c59d63b7b1e25d6
--- /dev/null
+++ b/vendor/sebastian/complexity/src/Complexity/ComplexityCollectionIterator.php
@@ -0,0 +1,55 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of sebastian/complexity.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\Complexity;
+
+use Iterator;
+
+final class ComplexityCollectionIterator implements Iterator
+{
+    /**
+     * @psalm-var list<Complexity>
+     */
+    private $items;
+
+    /**
+     * @var int
+     */
+    private $position = 0;
+
+    public function __construct(ComplexityCollection $items)
+    {
+        $this->items = $items->asArray();
+    }
+
+    public function rewind(): void
+    {
+        $this->position = 0;
+    }
+
+    public function valid(): bool
+    {
+        return isset($this->items[$this->position]);
+    }
+
+    public function key(): int
+    {
+        return $this->position;
+    }
+
+    public function current(): Complexity
+    {
+        return $this->items[$this->position];
+    }
+
+    public function next(): void
+    {
+        $this->position++;
+    }
+}
diff --git a/vendor/sebastian/complexity/src/Exception/Exception.php b/vendor/sebastian/complexity/src/Exception/Exception.php
new file mode 100644
index 0000000000000000000000000000000000000000..897ecdcf79129835aef324e01927e785305417ba
--- /dev/null
+++ b/vendor/sebastian/complexity/src/Exception/Exception.php
@@ -0,0 +1,16 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of sebastian/complexity.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\Complexity;
+
+use Throwable;
+
+interface Exception extends Throwable
+{
+}
diff --git a/vendor/sebastian/complexity/src/Exception/RuntimeException.php b/vendor/sebastian/complexity/src/Exception/RuntimeException.php
new file mode 100644
index 0000000000000000000000000000000000000000..6c68a6f0f1d3183a5f9d3a32257f1d54d25b1d1e
--- /dev/null
+++ b/vendor/sebastian/complexity/src/Exception/RuntimeException.php
@@ -0,0 +1,14 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of sebastian/complexity.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\Complexity;
+
+final class RuntimeException extends \RuntimeException implements Exception
+{
+}
diff --git a/vendor/sebastian/complexity/src/Visitor/ComplexityCalculatingVisitor.php b/vendor/sebastian/complexity/src/Visitor/ComplexityCalculatingVisitor.php
new file mode 100644
index 0000000000000000000000000000000000000000..b69f2b09f6dde59b6039f07764c0c527d885a2c0
--- /dev/null
+++ b/vendor/sebastian/complexity/src/Visitor/ComplexityCalculatingVisitor.php
@@ -0,0 +1,109 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of sebastian/complexity.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\Complexity;
+
+use function assert;
+use function is_array;
+use PhpParser\Node;
+use PhpParser\Node\Name;
+use PhpParser\Node\Stmt;
+use PhpParser\Node\Stmt\Class_;
+use PhpParser\Node\Stmt\ClassMethod;
+use PhpParser\Node\Stmt\Function_;
+use PhpParser\Node\Stmt\Trait_;
+use PhpParser\NodeTraverser;
+use PhpParser\NodeVisitorAbstract;
+
+final class ComplexityCalculatingVisitor extends NodeVisitorAbstract
+{
+    /**
+     * @psalm-var list<Complexity>
+     */
+    private $result = [];
+
+    /**
+     * @var bool
+     */
+    private $shortCircuitTraversal;
+
+    public function __construct(bool $shortCircuitTraversal)
+    {
+        $this->shortCircuitTraversal = $shortCircuitTraversal;
+    }
+
+    public function enterNode(Node $node): ?int
+    {
+        if (!$node instanceof ClassMethod && !$node instanceof Function_) {
+            return null;
+        }
+
+        if ($node instanceof ClassMethod) {
+            $name = $this->classMethodName($node);
+        } else {
+            $name = $this->functionName($node);
+        }
+
+        $statements = $node->getStmts();
+
+        assert(is_array($statements));
+
+        $this->result[] = new Complexity(
+            $name,
+            $this->cyclomaticComplexity($statements)
+        );
+
+        if ($this->shortCircuitTraversal) {
+            return NodeTraverser::DONT_TRAVERSE_CHILDREN;
+        }
+
+        return null;
+    }
+
+    public function result(): ComplexityCollection
+    {
+        return ComplexityCollection::fromList(...$this->result);
+    }
+
+    /**
+     * @param Stmt[] $statements
+     */
+    private function cyclomaticComplexity(array $statements): int
+    {
+        $traverser = new NodeTraverser;
+
+        $cyclomaticComplexityCalculatingVisitor = new CyclomaticComplexityCalculatingVisitor;
+
+        $traverser->addVisitor($cyclomaticComplexityCalculatingVisitor);
+
+        /* @noinspection UnusedFunctionResultInspection */
+        $traverser->traverse($statements);
+
+        return $cyclomaticComplexityCalculatingVisitor->cyclomaticComplexity();
+    }
+
+    private function classMethodName(ClassMethod $node): string
+    {
+        $parent = $node->getAttribute('parent');
+
+        assert($parent instanceof Class_ || $parent instanceof Trait_);
+        assert(isset($parent->namespacedName));
+        assert($parent->namespacedName instanceof Name);
+
+        return $parent->namespacedName->toString() . '::' . $node->name->toString();
+    }
+
+    private function functionName(Function_ $node): string
+    {
+        assert(isset($node->namespacedName));
+        assert($node->namespacedName instanceof Name);
+
+        return $node->namespacedName->toString();
+    }
+}
diff --git a/vendor/sebastian/complexity/src/Visitor/CyclomaticComplexityCalculatingVisitor.php b/vendor/sebastian/complexity/src/Visitor/CyclomaticComplexityCalculatingVisitor.php
new file mode 100644
index 0000000000000000000000000000000000000000..d4430876de0e4e5db04caec0d8ff5391acc86a7b
--- /dev/null
+++ b/vendor/sebastian/complexity/src/Visitor/CyclomaticComplexityCalculatingVisitor.php
@@ -0,0 +1,59 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of sebastian/complexity.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\Complexity;
+
+use function get_class;
+use PhpParser\Node;
+use PhpParser\Node\Expr\BinaryOp\BooleanAnd;
+use PhpParser\Node\Expr\BinaryOp\BooleanOr;
+use PhpParser\Node\Expr\BinaryOp\LogicalAnd;
+use PhpParser\Node\Expr\BinaryOp\LogicalOr;
+use PhpParser\Node\Expr\Ternary;
+use PhpParser\Node\Stmt\Case_;
+use PhpParser\Node\Stmt\Catch_;
+use PhpParser\Node\Stmt\ElseIf_;
+use PhpParser\Node\Stmt\For_;
+use PhpParser\Node\Stmt\Foreach_;
+use PhpParser\Node\Stmt\If_;
+use PhpParser\Node\Stmt\While_;
+use PhpParser\NodeVisitorAbstract;
+
+final class CyclomaticComplexityCalculatingVisitor extends NodeVisitorAbstract
+{
+    /**
+     * @var int
+     */
+    private $cyclomaticComplexity = 1;
+
+    public function enterNode(Node $node): void
+    {
+        /* @noinspection GetClassMissUseInspection */
+        switch (get_class($node)) {
+            case BooleanAnd::class:
+            case BooleanOr::class:
+            case Case_::class:
+            case Catch_::class:
+            case ElseIf_::class:
+            case For_::class:
+            case Foreach_::class:
+            case If_::class:
+            case LogicalAnd::class:
+            case LogicalOr::class:
+            case Ternary::class:
+            case While_::class:
+                $this->cyclomaticComplexity++;
+        }
+    }
+
+    public function cyclomaticComplexity(): int
+    {
+        return $this->cyclomaticComplexity;
+    }
+}
diff --git a/vendor/sebastian/diff/ChangeLog.md b/vendor/sebastian/diff/ChangeLog.md
new file mode 100644
index 0000000000000000000000000000000000000000..9bdcc5b6d72ed7e88cc472e7a82a4e985f7f244d
--- /dev/null
+++ b/vendor/sebastian/diff/ChangeLog.md
@@ -0,0 +1,88 @@
+# ChangeLog
+
+All notable changes are documented in this file using the [Keep a CHANGELOG](http://keepachangelog.com/) principles.
+
+## [4.0.4] - 2020-10-26
+
+### Fixed
+
+* `SebastianBergmann\Diff\Exception` now correctly extends `\Throwable`
+
+## [4.0.3] - 2020-09-28
+
+### Changed
+
+* Changed PHP version constraint in `composer.json` from `^7.3 || ^8.0` to `>=7.3`
+
+## [4.0.2] - 2020-06-30
+
+### Added
+
+* This component is now supported on PHP 8
+
+## [4.0.1] - 2020-05-08
+
+### Fixed
+
+* [#99](https://github.com/sebastianbergmann/diff/pull/99): Regression in unified diff output of identical strings
+
+## [4.0.0] - 2020-02-07
+
+### Removed
+
+* Removed support for PHP 7.1 and PHP 7.2
+
+## [3.0.2] - 2019-02-04
+
+### Changed
+
+* `Chunk::setLines()` now ensures that the `$lines` array only contains `Line` objects
+
+## [3.0.1] - 2018-06-10
+
+### Fixed
+
+* Removed `"minimum-stability": "dev",` from `composer.json`
+
+## [3.0.0] - 2018-02-01
+
+* The `StrictUnifiedDiffOutputBuilder` implementation of the `DiffOutputBuilderInterface` was added
+
+### Changed
+
+* The default `DiffOutputBuilderInterface` implementation now generates context lines (unchanged lines)
+
+### Removed
+
+* Removed support for PHP 7.0
+
+### Fixed
+
+* [#70](https://github.com/sebastianbergmann/diff/issues/70): Diffing of arrays no longer works
+
+## [2.0.1] - 2017-08-03
+
+### Fixed
+
+* [#66](https://github.com/sebastianbergmann/diff/pull/66): Restored backwards compatibility for PHPUnit 6.1.4, 6.2.0, 6.2.1, 6.2.2, and 6.2.3
+
+## [2.0.0] - 2017-07-11 [YANKED]
+
+### Added
+
+* [#64](https://github.com/sebastianbergmann/diff/pull/64): Show line numbers for chunks of a diff
+
+### Removed
+
+* This component is no longer supported on PHP 5.6
+
+[4.0.4]: https://github.com/sebastianbergmann/diff/compare/4.0.3...4.0.4
+[4.0.3]: https://github.com/sebastianbergmann/diff/compare/4.0.2...4.0.3
+[4.0.2]: https://github.com/sebastianbergmann/diff/compare/4.0.1...4.0.2
+[4.0.1]: https://github.com/sebastianbergmann/diff/compare/4.0.0...4.0.1
+[4.0.0]: https://github.com/sebastianbergmann/diff/compare/3.0.2...4.0.0
+[3.0.2]: https://github.com/sebastianbergmann/diff/compare/3.0.1...3.0.2
+[3.0.1]: https://github.com/sebastianbergmann/diff/compare/3.0.0...3.0.1
+[3.0.0]: https://github.com/sebastianbergmann/diff/compare/2.0...3.0.0
+[2.0.1]: https://github.com/sebastianbergmann/diff/compare/c341c98ce083db77f896a0aa64f5ee7652915970...2.0.1
+[2.0.0]: https://github.com/sebastianbergmann/diff/compare/1.4...c341c98ce083db77f896a0aa64f5ee7652915970
diff --git a/vendor/sebastian/diff/LICENSE b/vendor/sebastian/diff/LICENSE
new file mode 100644
index 0000000000000000000000000000000000000000..f22f31cf0cf7433dad9af78d870e63a976a135c2
--- /dev/null
+++ b/vendor/sebastian/diff/LICENSE
@@ -0,0 +1,33 @@
+sebastian/diff
+
+Copyright (c) 2002-2020, Sebastian Bergmann <sebastian@phpunit.de>.
+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 Sebastian Bergmann nor the names of his
+   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/sebastian/diff/README.md b/vendor/sebastian/diff/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..734b852de7c68d165a44a2a81dd02764ba7c4534
--- /dev/null
+++ b/vendor/sebastian/diff/README.md
@@ -0,0 +1,202 @@
+# sebastian/diff
+
+[![CI Status](https://github.com/sebastianbergmann/diff/workflows/CI/badge.svg)](https://github.com/sebastianbergmann/diff/actions)
+[![Type Coverage](https://shepherd.dev/github/sebastianbergmann/diff/coverage.svg)](https://shepherd.dev/github/sebastianbergmann/diff)
+
+Diff implementation for PHP, factored out of PHPUnit into a stand-alone component.
+
+## Installation
+
+You can add this library as a local, per-project dependency to your project using [Composer](https://getcomposer.org/):
+
+```
+composer require sebastian/diff
+```
+
+If you only need this library during development, for instance to run your project's test suite, then you should add it as a development-time dependency:
+
+```
+composer require --dev sebastian/diff
+```
+
+### Usage
+
+#### Generating diff
+
+The `Differ` class can be used to generate a textual representation of the difference between two strings:
+
+```php
+<?php
+use SebastianBergmann\Diff\Differ;
+
+$differ = new Differ;
+print $differ->diff('foo', 'bar');
+```
+
+The code above yields the output below:
+```diff
+--- Original
++++ New
+@@ @@
+-foo
++bar
+```
+
+There are three output builders available in this package:
+
+#### UnifiedDiffOutputBuilder
+
+This is default builder, which generates the output close to udiff and is used by PHPUnit.
+
+```php
+<?php
+
+use SebastianBergmann\Diff\Differ;
+use SebastianBergmann\Diff\Output\UnifiedDiffOutputBuilder;
+
+$builder = new UnifiedDiffOutputBuilder(
+    "--- Original\n+++ New\n", // custom header
+    false                      // do not add line numbers to the diff 
+);
+
+$differ = new Differ($builder);
+print $differ->diff('foo', 'bar');
+```
+
+#### StrictUnifiedDiffOutputBuilder
+
+Generates (strict) Unified diff's (unidiffs) with hunks,
+similar to `diff -u` and compatible with `patch` and `git apply`.
+
+```php
+<?php
+
+use SebastianBergmann\Diff\Differ;
+use SebastianBergmann\Diff\Output\StrictUnifiedDiffOutputBuilder;
+
+$builder = new StrictUnifiedDiffOutputBuilder([
+    'collapseRanges'      => true, // ranges of length one are rendered with the trailing `,1`
+    'commonLineThreshold' => 6,    // number of same lines before ending a new hunk and creating a new one (if needed)
+    'contextLines'        => 3,    // like `diff:  -u, -U NUM, --unified[=NUM]`, for patch/git apply compatibility best to keep at least @ 3
+    'fromFile'            => null,
+    'fromFileDate'        => null,
+    'toFile'              => null,
+    'toFileDate'          => null,
+]);
+
+$differ = new Differ($builder);
+print $differ->diff('foo', 'bar');
+```
+
+#### DiffOnlyOutputBuilder
+
+Output only the lines that differ.
+
+```php
+<?php
+
+use SebastianBergmann\Diff\Differ;
+use SebastianBergmann\Diff\Output\DiffOnlyOutputBuilder;
+
+$builder = new DiffOnlyOutputBuilder(
+    "--- Original\n+++ New\n"
+);
+
+$differ = new Differ($builder);
+print $differ->diff('foo', 'bar');
+```
+
+#### DiffOutputBuilderInterface
+
+You can pass any output builder to the `Differ` class as longs as it implements the `DiffOutputBuilderInterface`.
+
+#### Parsing diff
+
+The `Parser` class can be used to parse a unified diff into an object graph:
+
+```php
+use SebastianBergmann\Diff\Parser;
+use SebastianBergmann\Git;
+
+$git = new Git('/usr/local/src/money');
+
+$diff = $git->getDiff(
+  '948a1a07768d8edd10dcefa8315c1cbeffb31833',
+  'c07a373d2399f3e686234c4f7f088d635eb9641b'
+);
+
+$parser = new Parser;
+
+print_r($parser->parse($diff));
+```
+
+The code above yields the output below:
+
+    Array
+    (
+        [0] => SebastianBergmann\Diff\Diff Object
+            (
+                [from:SebastianBergmann\Diff\Diff:private] => a/tests/MoneyTest.php
+                [to:SebastianBergmann\Diff\Diff:private] => b/tests/MoneyTest.php
+                [chunks:SebastianBergmann\Diff\Diff:private] => Array
+                    (
+                        [0] => SebastianBergmann\Diff\Chunk Object
+                            (
+                                [start:SebastianBergmann\Diff\Chunk:private] => 87
+                                [startRange:SebastianBergmann\Diff\Chunk:private] => 7
+                                [end:SebastianBergmann\Diff\Chunk:private] => 87
+                                [endRange:SebastianBergmann\Diff\Chunk:private] => 7
+                                [lines:SebastianBergmann\Diff\Chunk:private] => Array
+                                    (
+                                        [0] => SebastianBergmann\Diff\Line Object
+                                            (
+                                                [type:SebastianBergmann\Diff\Line:private] => 3
+                                                [content:SebastianBergmann\Diff\Line:private] =>      * @covers SebastianBergmann\Money\Money::add
+                                            )
+
+                                        [1] => SebastianBergmann\Diff\Line Object
+                                            (
+                                                [type:SebastianBergmann\Diff\Line:private] => 3
+                                                [content:SebastianBergmann\Diff\Line:private] =>      * @covers SebastianBergmann\Money\Money::newMoney
+                                            )
+
+                                        [2] => SebastianBergmann\Diff\Line Object
+                                            (
+                                                [type:SebastianBergmann\Diff\Line:private] => 3
+                                                [content:SebastianBergmann\Diff\Line:private] =>      */
+                                            )
+
+                                        [3] => SebastianBergmann\Diff\Line Object
+                                            (
+                                                [type:SebastianBergmann\Diff\Line:private] => 2
+                                                [content:SebastianBergmann\Diff\Line:private] =>     public function testAnotherMoneyWithSameCurrencyObjectCanBeAdded()
+                                            )
+
+                                        [4] => SebastianBergmann\Diff\Line Object
+                                            (
+                                                [type:SebastianBergmann\Diff\Line:private] => 1
+                                                [content:SebastianBergmann\Diff\Line:private] =>     public function testAnotherMoneyObjectWithSameCurrencyCanBeAdded()
+                                            )
+
+                                        [5] => SebastianBergmann\Diff\Line Object
+                                            (
+                                                [type:SebastianBergmann\Diff\Line:private] => 3
+                                                [content:SebastianBergmann\Diff\Line:private] =>     {
+                                            )
+
+                                        [6] => SebastianBergmann\Diff\Line Object
+                                            (
+                                                [type:SebastianBergmann\Diff\Line:private] => 3
+                                                [content:SebastianBergmann\Diff\Line:private] =>         $a = new Money(1, new Currency('EUR'));
+                                            )
+
+                                        [7] => SebastianBergmann\Diff\Line Object
+                                            (
+                                                [type:SebastianBergmann\Diff\Line:private] => 3
+                                                [content:SebastianBergmann\Diff\Line:private] =>         $b = new Money(2, new Currency('EUR'));
+                                            )
+                                    )
+                            )
+                    )
+            )
+    )
diff --git a/vendor/sebastian/diff/composer.json b/vendor/sebastian/diff/composer.json
new file mode 100644
index 0000000000000000000000000000000000000000..cf92202ba3cb08162c8058e7ea85b4002443c145
--- /dev/null
+++ b/vendor/sebastian/diff/composer.json
@@ -0,0 +1,47 @@
+{
+    "name": "sebastian/diff",
+    "description": "Diff implementation",
+    "keywords": ["diff", "udiff", "unidiff", "unified diff"],
+    "homepage": "https://github.com/sebastianbergmann/diff",
+    "license": "BSD-3-Clause",
+    "authors": [
+        {
+            "name": "Sebastian Bergmann",
+            "email": "sebastian@phpunit.de"
+        },
+        {
+            "name": "Kore Nordmann",
+            "email": "mail@kore-nordmann.de"
+        }
+    ],
+    "prefer-stable": true,
+    "config": {
+        "platform": {
+            "php": "7.3.0"
+        },
+        "optimize-autoloader": true,
+        "sort-packages": true
+    },
+    "require": {
+        "php": ">=7.3"
+    },
+    "require-dev": {
+        "phpunit/phpunit": "^9.3",
+        "symfony/process": "^4.2 || ^5"
+    },
+    "autoload": {
+        "classmap": [
+            "src/"
+        ]
+    },
+    "autoload-dev": {
+        "classmap": [
+            "tests/"
+        ]
+    },
+    "extra": {
+        "branch-alias": {
+            "dev-master": "4.0-dev"
+        }
+    }
+}
diff --git a/vendor/sebastian/diff/src/Chunk.php b/vendor/sebastian/diff/src/Chunk.php
new file mode 100644
index 0000000000000000000000000000000000000000..16ae34f41484fa83494bb07ad0a5167ad6737d03
--- /dev/null
+++ b/vendor/sebastian/diff/src/Chunk.php
@@ -0,0 +1,89 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of sebastian/diff.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\Diff;
+
+final class Chunk
+{
+    /**
+     * @var int
+     */
+    private $start;
+
+    /**
+     * @var int
+     */
+    private $startRange;
+
+    /**
+     * @var int
+     */
+    private $end;
+
+    /**
+     * @var int
+     */
+    private $endRange;
+
+    /**
+     * @var Line[]
+     */
+    private $lines;
+
+    public function __construct(int $start = 0, int $startRange = 1, int $end = 0, int $endRange = 1, array $lines = [])
+    {
+        $this->start      = $start;
+        $this->startRange = $startRange;
+        $this->end        = $end;
+        $this->endRange   = $endRange;
+        $this->lines      = $lines;
+    }
+
+    public function getStart(): int
+    {
+        return $this->start;
+    }
+
+    public function getStartRange(): int
+    {
+        return $this->startRange;
+    }
+
+    public function getEnd(): int
+    {
+        return $this->end;
+    }
+
+    public function getEndRange(): int
+    {
+        return $this->endRange;
+    }
+
+    /**
+     * @return Line[]
+     */
+    public function getLines(): array
+    {
+        return $this->lines;
+    }
+
+    /**
+     * @param Line[] $lines
+     */
+    public function setLines(array $lines): void
+    {
+        foreach ($lines as $line) {
+            if (!$line instanceof Line) {
+                throw new InvalidArgumentException;
+            }
+        }
+
+        $this->lines = $lines;
+    }
+}
diff --git a/vendor/sebastian/diff/src/Diff.php b/vendor/sebastian/diff/src/Diff.php
new file mode 100644
index 0000000000000000000000000000000000000000..17b2084f9062bc0fb1016a1c18c9c85da3d167e9
--- /dev/null
+++ b/vendor/sebastian/diff/src/Diff.php
@@ -0,0 +1,64 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of sebastian/diff.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\Diff;
+
+final class Diff
+{
+    /**
+     * @var string
+     */
+    private $from;
+
+    /**
+     * @var string
+     */
+    private $to;
+
+    /**
+     * @var Chunk[]
+     */
+    private $chunks;
+
+    /**
+     * @param Chunk[] $chunks
+     */
+    public function __construct(string $from, string $to, array $chunks = [])
+    {
+        $this->from   = $from;
+        $this->to     = $to;
+        $this->chunks = $chunks;
+    }
+
+    public function getFrom(): string
+    {
+        return $this->from;
+    }
+
+    public function getTo(): string
+    {
+        return $this->to;
+    }
+
+    /**
+     * @return Chunk[]
+     */
+    public function getChunks(): array
+    {
+        return $this->chunks;
+    }
+
+    /**
+     * @param Chunk[] $chunks
+     */
+    public function setChunks(array $chunks): void
+    {
+        $this->chunks = $chunks;
+    }
+}
diff --git a/vendor/sebastian/diff/src/Differ.php b/vendor/sebastian/diff/src/Differ.php
new file mode 100644
index 0000000000000000000000000000000000000000..5a4d9d10242ad565e170a81dc4575def7cbf0878
--- /dev/null
+++ b/vendor/sebastian/diff/src/Differ.php
@@ -0,0 +1,327 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of sebastian/diff.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\Diff;
+
+use const PHP_INT_SIZE;
+use const PREG_SPLIT_DELIM_CAPTURE;
+use const PREG_SPLIT_NO_EMPTY;
+use function array_shift;
+use function array_unshift;
+use function array_values;
+use function count;
+use function current;
+use function end;
+use function get_class;
+use function gettype;
+use function is_array;
+use function is_object;
+use function is_string;
+use function key;
+use function min;
+use function preg_split;
+use function prev;
+use function reset;
+use function sprintf;
+use function substr;
+use SebastianBergmann\Diff\Output\DiffOutputBuilderInterface;
+use SebastianBergmann\Diff\Output\UnifiedDiffOutputBuilder;
+
+final class Differ
+{
+    public const OLD                     = 0;
+
+    public const ADDED                   = 1;
+
+    public const REMOVED                 = 2;
+
+    public const DIFF_LINE_END_WARNING   = 3;
+
+    public const NO_LINE_END_EOF_WARNING = 4;
+
+    /**
+     * @var DiffOutputBuilderInterface
+     */
+    private $outputBuilder;
+
+    /**
+     * @param DiffOutputBuilderInterface $outputBuilder
+     *
+     * @throws InvalidArgumentException
+     */
+    public function __construct($outputBuilder = null)
+    {
+        if ($outputBuilder instanceof DiffOutputBuilderInterface) {
+            $this->outputBuilder = $outputBuilder;
+        } elseif (null === $outputBuilder) {
+            $this->outputBuilder = new UnifiedDiffOutputBuilder;
+        } elseif (is_string($outputBuilder)) {
+            // PHPUnit 6.1.4, 6.2.0, 6.2.1, 6.2.2, and 6.2.3 support
+            // @see https://github.com/sebastianbergmann/phpunit/issues/2734#issuecomment-314514056
+            // @deprecated
+            $this->outputBuilder = new UnifiedDiffOutputBuilder($outputBuilder);
+        } else {
+            throw new InvalidArgumentException(
+                sprintf(
+                    'Expected builder to be an instance of DiffOutputBuilderInterface, <null> or a string, got %s.',
+                    is_object($outputBuilder) ? 'instance of "' . get_class($outputBuilder) . '"' : gettype($outputBuilder) . ' "' . $outputBuilder . '"'
+                )
+            );
+        }
+    }
+
+    /**
+     * Returns the diff between two arrays or strings as string.
+     *
+     * @param array|string $from
+     * @param array|string $to
+     */
+    public function diff($from, $to, LongestCommonSubsequenceCalculator $lcs = null): string
+    {
+        $diff = $this->diffToArray(
+            $this->normalizeDiffInput($from),
+            $this->normalizeDiffInput($to),
+            $lcs
+        );
+
+        return $this->outputBuilder->getDiff($diff);
+    }
+
+    /**
+     * Returns the diff between two arrays or strings as array.
+     *
+     * Each array element contains two elements:
+     *   - [0] => mixed $token
+     *   - [1] => 2|1|0
+     *
+     * - 2: REMOVED: $token was removed from $from
+     * - 1: ADDED: $token was added to $from
+     * - 0: OLD: $token is not changed in $to
+     *
+     * @param array|string                       $from
+     * @param array|string                       $to
+     * @param LongestCommonSubsequenceCalculator $lcs
+     */
+    public function diffToArray($from, $to, LongestCommonSubsequenceCalculator $lcs = null): array
+    {
+        if (is_string($from)) {
+            $from = $this->splitStringByLines($from);
+        } elseif (!is_array($from)) {
+            throw new InvalidArgumentException('"from" must be an array or string.');
+        }
+
+        if (is_string($to)) {
+            $to = $this->splitStringByLines($to);
+        } elseif (!is_array($to)) {
+            throw new InvalidArgumentException('"to" must be an array or string.');
+        }
+
+        [$from, $to, $start, $end] = self::getArrayDiffParted($from, $to);
+
+        if ($lcs === null) {
+            $lcs = $this->selectLcsImplementation($from, $to);
+        }
+
+        $common = $lcs->calculate(array_values($from), array_values($to));
+        $diff   = [];
+
+        foreach ($start as $token) {
+            $diff[] = [$token, self::OLD];
+        }
+
+        reset($from);
+        reset($to);
+
+        foreach ($common as $token) {
+            while (($fromToken = reset($from)) !== $token) {
+                $diff[] = [array_shift($from), self::REMOVED];
+            }
+
+            while (($toToken = reset($to)) !== $token) {
+                $diff[] = [array_shift($to), self::ADDED];
+            }
+
+            $diff[] = [$token, self::OLD];
+
+            array_shift($from);
+            array_shift($to);
+        }
+
+        while (($token = array_shift($from)) !== null) {
+            $diff[] = [$token, self::REMOVED];
+        }
+
+        while (($token = array_shift($to)) !== null) {
+            $diff[] = [$token, self::ADDED];
+        }
+
+        foreach ($end as $token) {
+            $diff[] = [$token, self::OLD];
+        }
+
+        if ($this->detectUnmatchedLineEndings($diff)) {
+            array_unshift($diff, ["#Warning: Strings contain different line endings!\n", self::DIFF_LINE_END_WARNING]);
+        }
+
+        return $diff;
+    }
+
+    /**
+     * Casts variable to string if it is not a string or array.
+     *
+     * @return array|string
+     */
+    private function normalizeDiffInput($input)
+    {
+        if (!is_array($input) && !is_string($input)) {
+            return (string) $input;
+        }
+
+        return $input;
+    }
+
+    /**
+     * Checks if input is string, if so it will split it line-by-line.
+     */
+    private function splitStringByLines(string $input): array
+    {
+        return preg_split('/(.*\R)/', $input, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY);
+    }
+
+    private function selectLcsImplementation(array $from, array $to): LongestCommonSubsequenceCalculator
+    {
+        // We do not want to use the time-efficient implementation if its memory
+        // footprint will probably exceed this value. Note that the footprint
+        // calculation is only an estimation for the matrix and the LCS method
+        // will typically allocate a bit more memory than this.
+        $memoryLimit = 100 * 1024 * 1024;
+
+        if ($this->calculateEstimatedFootprint($from, $to) > $memoryLimit) {
+            return new MemoryEfficientLongestCommonSubsequenceCalculator;
+        }
+
+        return new TimeEfficientLongestCommonSubsequenceCalculator;
+    }
+
+    /**
+     * Calculates the estimated memory footprint for the DP-based method.
+     *
+     * @return float|int
+     */
+    private function calculateEstimatedFootprint(array $from, array $to)
+    {
+        $itemSize = PHP_INT_SIZE === 4 ? 76 : 144;
+
+        return $itemSize * min(count($from), count($to)) ** 2;
+    }
+
+    /**
+     * Returns true if line ends don't match in a diff.
+     */
+    private function detectUnmatchedLineEndings(array $diff): bool
+    {
+        $newLineBreaks = ['' => true];
+        $oldLineBreaks = ['' => true];
+
+        foreach ($diff as $entry) {
+            if (self::OLD === $entry[1]) {
+                $ln                 = $this->getLinebreak($entry[0]);
+                $oldLineBreaks[$ln] = true;
+                $newLineBreaks[$ln] = true;
+            } elseif (self::ADDED === $entry[1]) {
+                $newLineBreaks[$this->getLinebreak($entry[0])] = true;
+            } elseif (self::REMOVED === $entry[1]) {
+                $oldLineBreaks[$this->getLinebreak($entry[0])] = true;
+            }
+        }
+
+        // if either input or output is a single line without breaks than no warning should be raised
+        if (['' => true] === $newLineBreaks || ['' => true] === $oldLineBreaks) {
+            return false;
+        }
+
+        // two way compare
+        foreach ($newLineBreaks as $break => $set) {
+            if (!isset($oldLineBreaks[$break])) {
+                return true;
+            }
+        }
+
+        foreach ($oldLineBreaks as $break => $set) {
+            if (!isset($newLineBreaks[$break])) {
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+    private function getLinebreak($line): string
+    {
+        if (!is_string($line)) {
+            return '';
+        }
+
+        $lc = substr($line, -1);
+
+        if ("\r" === $lc) {
+            return "\r";
+        }
+
+        if ("\n" !== $lc) {
+            return '';
+        }
+
+        if ("\r\n" === substr($line, -2)) {
+            return "\r\n";
+        }
+
+        return "\n";
+    }
+
+    private static function getArrayDiffParted(array &$from, array &$to): array
+    {
+        $start = [];
+        $end   = [];
+
+        reset($to);
+
+        foreach ($from as $k => $v) {
+            $toK = key($to);
+
+            if ($toK === $k && $v === $to[$k]) {
+                $start[$k] = $v;
+
+                unset($from[$k], $to[$k]);
+            } else {
+                break;
+            }
+        }
+
+        end($from);
+        end($to);
+
+        do {
+            $fromK = key($from);
+            $toK   = key($to);
+
+            if (null === $fromK || null === $toK || current($from) !== current($to)) {
+                break;
+            }
+
+            prev($from);
+            prev($to);
+
+            $end = [$fromK => $from[$fromK]] + $end;
+            unset($from[$fromK], $to[$toK]);
+        } while (true);
+
+        return [$from, $to, $start, $end];
+    }
+}
diff --git a/vendor/sebastian/diff/src/Exception/ConfigurationException.php b/vendor/sebastian/diff/src/Exception/ConfigurationException.php
new file mode 100644
index 0000000000000000000000000000000000000000..b767b2194a2742374c16cbf2189f2b5256d303a9
--- /dev/null
+++ b/vendor/sebastian/diff/src/Exception/ConfigurationException.php
@@ -0,0 +1,38 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of sebastian/diff.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\Diff;
+
+use function get_class;
+use function gettype;
+use function is_object;
+use function sprintf;
+use Exception;
+
+final class ConfigurationException extends InvalidArgumentException
+{
+    public function __construct(
+        string $option,
+        string $expected,
+        $value,
+        int $code = 0,
+        Exception $previous = null
+    ) {
+        parent::__construct(
+            sprintf(
+                'Option "%s" must be %s, got "%s".',
+                $option,
+                $expected,
+                is_object($value) ? get_class($value) : (null === $value ? '<null>' : gettype($value) . '#' . $value)
+            ),
+            $code,
+            $previous
+        );
+    }
+}
diff --git a/vendor/sebastian/diff/src/Exception/Exception.php b/vendor/sebastian/diff/src/Exception/Exception.php
new file mode 100644
index 0000000000000000000000000000000000000000..e20d32036966447f244554a94fe9e8c0bf3ba817
--- /dev/null
+++ b/vendor/sebastian/diff/src/Exception/Exception.php
@@ -0,0 +1,16 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of sebastian/diff.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\Diff;
+
+use Throwable;
+
+interface Exception extends Throwable
+{
+}
diff --git a/vendor/sebastian/diff/src/Exception/InvalidArgumentException.php b/vendor/sebastian/diff/src/Exception/InvalidArgumentException.php
new file mode 100644
index 0000000000000000000000000000000000000000..846ac3fbd6e7d4348a57609cdb375523ae555f3f
--- /dev/null
+++ b/vendor/sebastian/diff/src/Exception/InvalidArgumentException.php
@@ -0,0 +1,14 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of sebastian/diff.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\Diff;
+
+class InvalidArgumentException extends \InvalidArgumentException implements Exception
+{
+}
diff --git a/vendor/sebastian/diff/src/Line.php b/vendor/sebastian/diff/src/Line.php
new file mode 100644
index 0000000000000000000000000000000000000000..3596ed264c26e246b68135297b2a3f51c0b71cf7
--- /dev/null
+++ b/vendor/sebastian/diff/src/Line.php
@@ -0,0 +1,45 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of sebastian/diff.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\Diff;
+
+final class Line
+{
+    public const ADDED     = 1;
+
+    public const REMOVED   = 2;
+
+    public const UNCHANGED = 3;
+
+    /**
+     * @var int
+     */
+    private $type;
+
+    /**
+     * @var string
+     */
+    private $content;
+
+    public function __construct(int $type = self::UNCHANGED, string $content = '')
+    {
+        $this->type    = $type;
+        $this->content = $content;
+    }
+
+    public function getContent(): string
+    {
+        return $this->content;
+    }
+
+    public function getType(): int
+    {
+        return $this->type;
+    }
+}
diff --git a/vendor/sebastian/diff/src/LongestCommonSubsequenceCalculator.php b/vendor/sebastian/diff/src/LongestCommonSubsequenceCalculator.php
new file mode 100644
index 0000000000000000000000000000000000000000..dea8fe1cb8b265360c7fe02be78749ed960dc5de
--- /dev/null
+++ b/vendor/sebastian/diff/src/LongestCommonSubsequenceCalculator.php
@@ -0,0 +1,18 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of sebastian/diff.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\Diff;
+
+interface LongestCommonSubsequenceCalculator
+{
+    /**
+     * Calculates the longest common subsequence of two arrays.
+     */
+    public function calculate(array $from, array $to): array;
+}
diff --git a/vendor/sebastian/diff/src/MemoryEfficientLongestCommonSubsequenceCalculator.php b/vendor/sebastian/diff/src/MemoryEfficientLongestCommonSubsequenceCalculator.php
new file mode 100644
index 0000000000000000000000000000000000000000..0b626eaff9240dd380abc6baf18fdfdaafa47e48
--- /dev/null
+++ b/vendor/sebastian/diff/src/MemoryEfficientLongestCommonSubsequenceCalculator.php
@@ -0,0 +1,88 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of sebastian/diff.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\Diff;
+
+use function array_fill;
+use function array_merge;
+use function array_reverse;
+use function array_slice;
+use function count;
+use function in_array;
+use function max;
+
+final class MemoryEfficientLongestCommonSubsequenceCalculator implements LongestCommonSubsequenceCalculator
+{
+    /**
+     * {@inheritdoc}
+     */
+    public function calculate(array $from, array $to): array
+    {
+        $cFrom = count($from);
+        $cTo   = count($to);
+
+        if ($cFrom === 0) {
+            return [];
+        }
+
+        if ($cFrom === 1) {
+            if (in_array($from[0], $to, true)) {
+                return [$from[0]];
+            }
+
+            return [];
+        }
+
+        $i         = (int) ($cFrom / 2);
+        $fromStart = array_slice($from, 0, $i);
+        $fromEnd   = array_slice($from, $i);
+        $llB       = $this->length($fromStart, $to);
+        $llE       = $this->length(array_reverse($fromEnd), array_reverse($to));
+        $jMax      = 0;
+        $max       = 0;
+
+        for ($j = 0; $j <= $cTo; $j++) {
+            $m = $llB[$j] + $llE[$cTo - $j];
+
+            if ($m >= $max) {
+                $max  = $m;
+                $jMax = $j;
+            }
+        }
+
+        $toStart = array_slice($to, 0, $jMax);
+        $toEnd   = array_slice($to, $jMax);
+
+        return array_merge(
+            $this->calculate($fromStart, $toStart),
+            $this->calculate($fromEnd, $toEnd)
+        );
+    }
+
+    private function length(array $from, array $to): array
+    {
+        $current = array_fill(0, count($to) + 1, 0);
+        $cFrom   = count($from);
+        $cTo     = count($to);
+
+        for ($i = 0; $i < $cFrom; $i++) {
+            $prev = $current;
+
+            for ($j = 0; $j < $cTo; $j++) {
+                if ($from[$i] === $to[$j]) {
+                    $current[$j + 1] = $prev[$j] + 1;
+                } else {
+                    $current[$j + 1] = max($current[$j], $prev[$j + 1]);
+                }
+            }
+        }
+
+        return $current;
+    }
+}
diff --git a/vendor/sebastian/diff/src/Output/AbstractChunkOutputBuilder.php b/vendor/sebastian/diff/src/Output/AbstractChunkOutputBuilder.php
new file mode 100644
index 0000000000000000000000000000000000000000..e55757c3800c9b22f0817db367d45b9816056832
--- /dev/null
+++ b/vendor/sebastian/diff/src/Output/AbstractChunkOutputBuilder.php
@@ -0,0 +1,52 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of sebastian/diff.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\Diff\Output;
+
+use function count;
+
+abstract class AbstractChunkOutputBuilder implements DiffOutputBuilderInterface
+{
+    /**
+     * Takes input of the diff array and returns the common parts.
+     * Iterates through diff line by line.
+     */
+    protected function getCommonChunks(array $diff, int $lineThreshold = 5): array
+    {
+        $diffSize     = count($diff);
+        $capturing    = false;
+        $chunkStart   = 0;
+        $chunkSize    = 0;
+        $commonChunks = [];
+
+        for ($i = 0; $i < $diffSize; ++$i) {
+            if ($diff[$i][1] === 0 /* OLD */) {
+                if ($capturing === false) {
+                    $capturing  = true;
+                    $chunkStart = $i;
+                    $chunkSize  = 0;
+                } else {
+                    ++$chunkSize;
+                }
+            } elseif ($capturing !== false) {
+                if ($chunkSize >= $lineThreshold) {
+                    $commonChunks[$chunkStart] = $chunkStart + $chunkSize;
+                }
+
+                $capturing = false;
+            }
+        }
+
+        if ($capturing !== false && $chunkSize >= $lineThreshold) {
+            $commonChunks[$chunkStart] = $chunkStart + $chunkSize;
+        }
+
+        return $commonChunks;
+    }
+}
diff --git a/vendor/sebastian/diff/src/Output/DiffOnlyOutputBuilder.php b/vendor/sebastian/diff/src/Output/DiffOnlyOutputBuilder.php
new file mode 100644
index 0000000000000000000000000000000000000000..f79a935cb822ca35fa6ebaf660ed7ce531556c24
--- /dev/null
+++ b/vendor/sebastian/diff/src/Output/DiffOnlyOutputBuilder.php
@@ -0,0 +1,72 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of sebastian/diff.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\Diff\Output;
+
+use function fclose;
+use function fopen;
+use function fwrite;
+use function stream_get_contents;
+use function substr;
+use SebastianBergmann\Diff\Differ;
+
+/**
+ * Builds a diff string representation in a loose unified diff format
+ * listing only changes lines. Does not include line numbers.
+ */
+final class DiffOnlyOutputBuilder implements DiffOutputBuilderInterface
+{
+    /**
+     * @var string
+     */
+    private $header;
+
+    public function __construct(string $header = "--- Original\n+++ New\n")
+    {
+        $this->header = $header;
+    }
+
+    public function getDiff(array $diff): string
+    {
+        $buffer = fopen('php://memory', 'r+b');
+
+        if ('' !== $this->header) {
+            fwrite($buffer, $this->header);
+
+            if ("\n" !== substr($this->header, -1, 1)) {
+                fwrite($buffer, "\n");
+            }
+        }
+
+        foreach ($diff as $diffEntry) {
+            if ($diffEntry[1] === Differ::ADDED) {
+                fwrite($buffer, '+' . $diffEntry[0]);
+            } elseif ($diffEntry[1] === Differ::REMOVED) {
+                fwrite($buffer, '-' . $diffEntry[0]);
+            } elseif ($diffEntry[1] === Differ::DIFF_LINE_END_WARNING) {
+                fwrite($buffer, ' ' . $diffEntry[0]);
+
+                continue; // Warnings should not be tested for line break, it will always be there
+            } else { /* Not changed (old) 0 */
+                continue; // we didn't write the non changs line, so do not add a line break either
+            }
+
+            $lc = substr($diffEntry[0], -1);
+
+            if ($lc !== "\n" && $lc !== "\r") {
+                fwrite($buffer, "\n"); // \No newline at end of file
+            }
+        }
+
+        $diff = stream_get_contents($buffer, -1, 0);
+        fclose($buffer);
+
+        return $diff;
+    }
+}
diff --git a/vendor/sebastian/diff/src/Output/DiffOutputBuilderInterface.php b/vendor/sebastian/diff/src/Output/DiffOutputBuilderInterface.php
new file mode 100644
index 0000000000000000000000000000000000000000..0e18f9f2e65286db1b76f9d8081c7c4b538d45d7
--- /dev/null
+++ b/vendor/sebastian/diff/src/Output/DiffOutputBuilderInterface.php
@@ -0,0 +1,19 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of sebastian/diff.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\Diff\Output;
+
+/**
+ * Defines how an output builder should take a generated
+ * diff array and return a string representation of that diff.
+ */
+interface DiffOutputBuilderInterface
+{
+    public function getDiff(array $diff): string;
+}
diff --git a/vendor/sebastian/diff/src/Output/StrictUnifiedDiffOutputBuilder.php b/vendor/sebastian/diff/src/Output/StrictUnifiedDiffOutputBuilder.php
new file mode 100644
index 0000000000000000000000000000000000000000..9c55ab2aafd16abc2206933aa3f21e80f2211fa3
--- /dev/null
+++ b/vendor/sebastian/diff/src/Output/StrictUnifiedDiffOutputBuilder.php
@@ -0,0 +1,338 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of sebastian/diff.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\Diff\Output;
+
+use function array_merge;
+use function array_splice;
+use function count;
+use function fclose;
+use function fopen;
+use function fwrite;
+use function is_bool;
+use function is_int;
+use function is_string;
+use function max;
+use function min;
+use function sprintf;
+use function stream_get_contents;
+use function substr;
+use SebastianBergmann\Diff\ConfigurationException;
+use SebastianBergmann\Diff\Differ;
+
+/**
+ * Strict Unified diff output builder.
+ *
+ * Generates (strict) Unified diff's (unidiffs) with hunks.
+ */
+final class StrictUnifiedDiffOutputBuilder implements DiffOutputBuilderInterface
+{
+    private static $default = [
+        'collapseRanges'      => true, // ranges of length one are rendered with the trailing `,1`
+        'commonLineThreshold' => 6,    // number of same lines before ending a new hunk and creating a new one (if needed)
+        'contextLines'        => 3,    // like `diff:  -u, -U NUM, --unified[=NUM]`, for patch/git apply compatibility best to keep at least @ 3
+        'fromFile'            => null,
+        'fromFileDate'        => null,
+        'toFile'              => null,
+        'toFileDate'          => null,
+    ];
+
+    /**
+     * @var bool
+     */
+    private $changed;
+
+    /**
+     * @var bool
+     */
+    private $collapseRanges;
+
+    /**
+     * @var int >= 0
+     */
+    private $commonLineThreshold;
+
+    /**
+     * @var string
+     */
+    private $header;
+
+    /**
+     * @var int >= 0
+     */
+    private $contextLines;
+
+    public function __construct(array $options = [])
+    {
+        $options = array_merge(self::$default, $options);
+
+        if (!is_bool($options['collapseRanges'])) {
+            throw new ConfigurationException('collapseRanges', 'a bool', $options['collapseRanges']);
+        }
+
+        if (!is_int($options['contextLines']) || $options['contextLines'] < 0) {
+            throw new ConfigurationException('contextLines', 'an int >= 0', $options['contextLines']);
+        }
+
+        if (!is_int($options['commonLineThreshold']) || $options['commonLineThreshold'] <= 0) {
+            throw new ConfigurationException('commonLineThreshold', 'an int > 0', $options['commonLineThreshold']);
+        }
+
+        $this->assertString($options, 'fromFile');
+        $this->assertString($options, 'toFile');
+        $this->assertStringOrNull($options, 'fromFileDate');
+        $this->assertStringOrNull($options, 'toFileDate');
+
+        $this->header = sprintf(
+            "--- %s%s\n+++ %s%s\n",
+            $options['fromFile'],
+            null === $options['fromFileDate'] ? '' : "\t" . $options['fromFileDate'],
+            $options['toFile'],
+            null === $options['toFileDate'] ? '' : "\t" . $options['toFileDate']
+        );
+
+        $this->collapseRanges      = $options['collapseRanges'];
+        $this->commonLineThreshold = $options['commonLineThreshold'];
+        $this->contextLines        = $options['contextLines'];
+    }
+
+    public function getDiff(array $diff): string
+    {
+        if (0 === count($diff)) {
+            return '';
+        }
+
+        $this->changed = false;
+
+        $buffer = fopen('php://memory', 'r+b');
+        fwrite($buffer, $this->header);
+
+        $this->writeDiffHunks($buffer, $diff);
+
+        if (!$this->changed) {
+            fclose($buffer);
+
+            return '';
+        }
+
+        $diff = stream_get_contents($buffer, -1, 0);
+
+        fclose($buffer);
+
+        // If the last char is not a linebreak: add it.
+        // This might happen when both the `from` and `to` do not have a trailing linebreak
+        $last = substr($diff, -1);
+
+        return "\n" !== $last && "\r" !== $last
+            ? $diff . "\n"
+            : $diff;
+    }
+
+    private function writeDiffHunks($output, array $diff): void
+    {
+        // detect "No newline at end of file" and insert into `$diff` if needed
+
+        $upperLimit = count($diff);
+
+        if (0 === $diff[$upperLimit - 1][1]) {
+            $lc = substr($diff[$upperLimit - 1][0], -1);
+
+            if ("\n" !== $lc) {
+                array_splice($diff, $upperLimit, 0, [["\n\\ No newline at end of file\n", Differ::NO_LINE_END_EOF_WARNING]]);
+            }
+        } else {
+            // search back for the last `+` and `-` line,
+            // check if has trailing linebreak, else add under it warning under it
+            $toFind = [1 => true, 2 => true];
+
+            for ($i = $upperLimit - 1; $i >= 0; --$i) {
+                if (isset($toFind[$diff[$i][1]])) {
+                    unset($toFind[$diff[$i][1]]);
+                    $lc = substr($diff[$i][0], -1);
+
+                    if ("\n" !== $lc) {
+                        array_splice($diff, $i + 1, 0, [["\n\\ No newline at end of file\n", Differ::NO_LINE_END_EOF_WARNING]]);
+                    }
+
+                    if (!count($toFind)) {
+                        break;
+                    }
+                }
+            }
+        }
+
+        // write hunks to output buffer
+
+        $cutOff      = max($this->commonLineThreshold, $this->contextLines);
+        $hunkCapture = false;
+        $sameCount   = $toRange = $fromRange = 0;
+        $toStart     = $fromStart = 1;
+        $i           = 0;
+
+        /** @var int $i */
+        foreach ($diff as $i => $entry) {
+            if (0 === $entry[1]) { // same
+                if (false === $hunkCapture) {
+                    ++$fromStart;
+                    ++$toStart;
+
+                    continue;
+                }
+
+                ++$sameCount;
+                ++$toRange;
+                ++$fromRange;
+
+                if ($sameCount === $cutOff) {
+                    $contextStartOffset = ($hunkCapture - $this->contextLines) < 0
+                        ? $hunkCapture
+                        : $this->contextLines;
+
+                    // note: $contextEndOffset = $this->contextLines;
+                    //
+                    // because we never go beyond the end of the diff.
+                    // with the cutoff/contextlines here the follow is never true;
+                    //
+                    // if ($i - $cutOff + $this->contextLines + 1 > \count($diff)) {
+                    //    $contextEndOffset = count($diff) - 1;
+                    // }
+                    //
+                    // ; that would be true for a trailing incomplete hunk case which is dealt with after this loop
+
+                    $this->writeHunk(
+                        $diff,
+                        $hunkCapture - $contextStartOffset,
+                        $i - $cutOff + $this->contextLines + 1,
+                        $fromStart - $contextStartOffset,
+                        $fromRange - $cutOff + $contextStartOffset + $this->contextLines,
+                        $toStart - $contextStartOffset,
+                        $toRange - $cutOff + $contextStartOffset + $this->contextLines,
+                        $output
+                    );
+
+                    $fromStart += $fromRange;
+                    $toStart += $toRange;
+
+                    $hunkCapture = false;
+                    $sameCount   = $toRange = $fromRange = 0;
+                }
+
+                continue;
+            }
+
+            $sameCount = 0;
+
+            if ($entry[1] === Differ::NO_LINE_END_EOF_WARNING) {
+                continue;
+            }
+
+            $this->changed = true;
+
+            if (false === $hunkCapture) {
+                $hunkCapture = $i;
+            }
+
+            if (Differ::ADDED === $entry[1]) { // added
+                ++$toRange;
+            }
+
+            if (Differ::REMOVED === $entry[1]) { // removed
+                ++$fromRange;
+            }
+        }
+
+        if (false === $hunkCapture) {
+            return;
+        }
+
+        // we end here when cutoff (commonLineThreshold) was not reached, but we where capturing a hunk,
+        // do not render hunk till end automatically because the number of context lines might be less than the commonLineThreshold
+
+        $contextStartOffset = $hunkCapture - $this->contextLines < 0
+            ? $hunkCapture
+            : $this->contextLines;
+
+        // prevent trying to write out more common lines than there are in the diff _and_
+        // do not write more than configured through the context lines
+        $contextEndOffset = min($sameCount, $this->contextLines);
+
+        $fromRange -= $sameCount;
+        $toRange -= $sameCount;
+
+        $this->writeHunk(
+            $diff,
+            $hunkCapture - $contextStartOffset,
+            $i - $sameCount + $contextEndOffset + 1,
+            $fromStart - $contextStartOffset,
+            $fromRange + $contextStartOffset + $contextEndOffset,
+            $toStart - $contextStartOffset,
+            $toRange + $contextStartOffset + $contextEndOffset,
+            $output
+        );
+    }
+
+    private function writeHunk(
+        array $diff,
+        int $diffStartIndex,
+        int $diffEndIndex,
+        int $fromStart,
+        int $fromRange,
+        int $toStart,
+        int $toRange,
+        $output
+    ): void {
+        fwrite($output, '@@ -' . $fromStart);
+
+        if (!$this->collapseRanges || 1 !== $fromRange) {
+            fwrite($output, ',' . $fromRange);
+        }
+
+        fwrite($output, ' +' . $toStart);
+
+        if (!$this->collapseRanges || 1 !== $toRange) {
+            fwrite($output, ',' . $toRange);
+        }
+
+        fwrite($output, " @@\n");
+
+        for ($i = $diffStartIndex; $i < $diffEndIndex; ++$i) {
+            if ($diff[$i][1] === Differ::ADDED) {
+                $this->changed = true;
+                fwrite($output, '+' . $diff[$i][0]);
+            } elseif ($diff[$i][1] === Differ::REMOVED) {
+                $this->changed = true;
+                fwrite($output, '-' . $diff[$i][0]);
+            } elseif ($diff[$i][1] === Differ::OLD) {
+                fwrite($output, ' ' . $diff[$i][0]);
+            } elseif ($diff[$i][1] === Differ::NO_LINE_END_EOF_WARNING) {
+                $this->changed = true;
+                fwrite($output, $diff[$i][0]);
+            }
+            //} elseif ($diff[$i][1] === Differ::DIFF_LINE_END_WARNING) { // custom comment inserted by PHPUnit/diff package
+                //  skip
+            //} else {
+                //  unknown/invalid
+            //}
+        }
+    }
+
+    private function assertString(array $options, string $option): void
+    {
+        if (!is_string($options[$option])) {
+            throw new ConfigurationException($option, 'a string', $options[$option]);
+        }
+    }
+
+    private function assertStringOrNull(array $options, string $option): void
+    {
+        if (null !== $options[$option] && !is_string($options[$option])) {
+            throw new ConfigurationException($option, 'a string or <null>', $options[$option]);
+        }
+    }
+}
diff --git a/vendor/sebastian/diff/src/Output/UnifiedDiffOutputBuilder.php b/vendor/sebastian/diff/src/Output/UnifiedDiffOutputBuilder.php
new file mode 100644
index 0000000000000000000000000000000000000000..8aae645043fe557b18aad5477f61f898e1499ae4
--- /dev/null
+++ b/vendor/sebastian/diff/src/Output/UnifiedDiffOutputBuilder.php
@@ -0,0 +1,272 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of sebastian/diff.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\Diff\Output;
+
+use function array_splice;
+use function count;
+use function fclose;
+use function fopen;
+use function fwrite;
+use function max;
+use function min;
+use function stream_get_contents;
+use function strlen;
+use function substr;
+use SebastianBergmann\Diff\Differ;
+
+/**
+ * Builds a diff string representation in unified diff format in chunks.
+ */
+final class UnifiedDiffOutputBuilder extends AbstractChunkOutputBuilder
+{
+    /**
+     * @var bool
+     */
+    private $collapseRanges = true;
+
+    /**
+     * @var int >= 0
+     */
+    private $commonLineThreshold = 6;
+
+    /**
+     * @var int >= 0
+     */
+    private $contextLines = 3;
+
+    /**
+     * @var string
+     */
+    private $header;
+
+    /**
+     * @var bool
+     */
+    private $addLineNumbers;
+
+    public function __construct(string $header = "--- Original\n+++ New\n", bool $addLineNumbers = false)
+    {
+        $this->header         = $header;
+        $this->addLineNumbers = $addLineNumbers;
+    }
+
+    public function getDiff(array $diff): string
+    {
+        $buffer = fopen('php://memory', 'r+b');
+
+        if ('' !== $this->header) {
+            fwrite($buffer, $this->header);
+
+            if ("\n" !== substr($this->header, -1, 1)) {
+                fwrite($buffer, "\n");
+            }
+        }
+
+        if (0 !== count($diff)) {
+            $this->writeDiffHunks($buffer, $diff);
+        }
+
+        $diff = stream_get_contents($buffer, -1, 0);
+
+        fclose($buffer);
+
+        // If the diff is non-empty and last char is not a linebreak: add it.
+        // This might happen when both the `from` and `to` do not have a trailing linebreak
+        $last = substr($diff, -1);
+
+        return 0 !== strlen($diff) && "\n" !== $last && "\r" !== $last
+            ? $diff . "\n"
+            : $diff;
+    }
+
+    private function writeDiffHunks($output, array $diff): void
+    {
+        // detect "No newline at end of file" and insert into `$diff` if needed
+
+        $upperLimit = count($diff);
+
+        if (0 === $diff[$upperLimit - 1][1]) {
+            $lc = substr($diff[$upperLimit - 1][0], -1);
+
+            if ("\n" !== $lc) {
+                array_splice($diff, $upperLimit, 0, [["\n\\ No newline at end of file\n", Differ::NO_LINE_END_EOF_WARNING]]);
+            }
+        } else {
+            // search back for the last `+` and `-` line,
+            // check if has trailing linebreak, else add under it warning under it
+            $toFind = [1 => true, 2 => true];
+
+            for ($i = $upperLimit - 1; $i >= 0; --$i) {
+                if (isset($toFind[$diff[$i][1]])) {
+                    unset($toFind[$diff[$i][1]]);
+                    $lc = substr($diff[$i][0], -1);
+
+                    if ("\n" !== $lc) {
+                        array_splice($diff, $i + 1, 0, [["\n\\ No newline at end of file\n", Differ::NO_LINE_END_EOF_WARNING]]);
+                    }
+
+                    if (!count($toFind)) {
+                        break;
+                    }
+                }
+            }
+        }
+
+        // write hunks to output buffer
+
+        $cutOff      = max($this->commonLineThreshold, $this->contextLines);
+        $hunkCapture = false;
+        $sameCount   = $toRange   = $fromRange = 0;
+        $toStart     = $fromStart = 1;
+        $i           = 0;
+
+        /** @var int $i */
+        foreach ($diff as $i => $entry) {
+            if (0 === $entry[1]) { // same
+                if (false === $hunkCapture) {
+                    ++$fromStart;
+                    ++$toStart;
+
+                    continue;
+                }
+
+                ++$sameCount;
+                ++$toRange;
+                ++$fromRange;
+
+                if ($sameCount === $cutOff) {
+                    $contextStartOffset = ($hunkCapture - $this->contextLines) < 0
+                        ? $hunkCapture
+                        : $this->contextLines;
+
+                    // note: $contextEndOffset = $this->contextLines;
+                    //
+                    // because we never go beyond the end of the diff.
+                    // with the cutoff/contextlines here the follow is never true;
+                    //
+                    // if ($i - $cutOff + $this->contextLines + 1 > \count($diff)) {
+                    //    $contextEndOffset = count($diff) - 1;
+                    // }
+                    //
+                    // ; that would be true for a trailing incomplete hunk case which is dealt with after this loop
+
+                    $this->writeHunk(
+                        $diff,
+                        $hunkCapture - $contextStartOffset,
+                        $i - $cutOff + $this->contextLines + 1,
+                        $fromStart - $contextStartOffset,
+                        $fromRange - $cutOff + $contextStartOffset + $this->contextLines,
+                        $toStart - $contextStartOffset,
+                        $toRange - $cutOff + $contextStartOffset + $this->contextLines,
+                        $output
+                    );
+
+                    $fromStart += $fromRange;
+                    $toStart += $toRange;
+
+                    $hunkCapture = false;
+                    $sameCount   = $toRange = $fromRange = 0;
+                }
+
+                continue;
+            }
+
+            $sameCount = 0;
+
+            if ($entry[1] === Differ::NO_LINE_END_EOF_WARNING) {
+                continue;
+            }
+
+            if (false === $hunkCapture) {
+                $hunkCapture = $i;
+            }
+
+            if (Differ::ADDED === $entry[1]) {
+                ++$toRange;
+            }
+
+            if (Differ::REMOVED === $entry[1]) {
+                ++$fromRange;
+            }
+        }
+
+        if (false === $hunkCapture) {
+            return;
+        }
+
+        // we end here when cutoff (commonLineThreshold) was not reached, but we where capturing a hunk,
+        // do not render hunk till end automatically because the number of context lines might be less than the commonLineThreshold
+
+        $contextStartOffset = $hunkCapture - $this->contextLines < 0
+            ? $hunkCapture
+            : $this->contextLines;
+
+        // prevent trying to write out more common lines than there are in the diff _and_
+        // do not write more than configured through the context lines
+        $contextEndOffset = min($sameCount, $this->contextLines);
+
+        $fromRange -= $sameCount;
+        $toRange -= $sameCount;
+
+        $this->writeHunk(
+            $diff,
+            $hunkCapture - $contextStartOffset,
+            $i - $sameCount + $contextEndOffset + 1,
+            $fromStart - $contextStartOffset,
+            $fromRange + $contextStartOffset + $contextEndOffset,
+            $toStart - $contextStartOffset,
+            $toRange + $contextStartOffset + $contextEndOffset,
+            $output
+        );
+    }
+
+    private function writeHunk(
+        array $diff,
+        int $diffStartIndex,
+        int $diffEndIndex,
+        int $fromStart,
+        int $fromRange,
+        int $toStart,
+        int $toRange,
+        $output
+    ): void {
+        if ($this->addLineNumbers) {
+            fwrite($output, '@@ -' . $fromStart);
+
+            if (!$this->collapseRanges || 1 !== $fromRange) {
+                fwrite($output, ',' . $fromRange);
+            }
+
+            fwrite($output, ' +' . $toStart);
+
+            if (!$this->collapseRanges || 1 !== $toRange) {
+                fwrite($output, ',' . $toRange);
+            }
+
+            fwrite($output, " @@\n");
+        } else {
+            fwrite($output, "@@ @@\n");
+        }
+
+        for ($i = $diffStartIndex; $i < $diffEndIndex; ++$i) {
+            if ($diff[$i][1] === Differ::ADDED) {
+                fwrite($output, '+' . $diff[$i][0]);
+            } elseif ($diff[$i][1] === Differ::REMOVED) {
+                fwrite($output, '-' . $diff[$i][0]);
+            } elseif ($diff[$i][1] === Differ::OLD) {
+                fwrite($output, ' ' . $diff[$i][0]);
+            } elseif ($diff[$i][1] === Differ::NO_LINE_END_EOF_WARNING) {
+                fwrite($output, "\n"); // $diff[$i][0]
+            } else { /* Not changed (old) Differ::OLD or Warning Differ::DIFF_LINE_END_WARNING */
+                fwrite($output, ' ' . $diff[$i][0]);
+            }
+        }
+    }
+}
diff --git a/vendor/sebastian/diff/src/Parser.php b/vendor/sebastian/diff/src/Parser.php
new file mode 100644
index 0000000000000000000000000000000000000000..cc9e388712f57eb035044f483ec2848d1e36090d
--- /dev/null
+++ b/vendor/sebastian/diff/src/Parser.php
@@ -0,0 +1,110 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of sebastian/diff.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\Diff;
+
+use function array_pop;
+use function count;
+use function max;
+use function preg_match;
+use function preg_split;
+
+/**
+ * Unified diff parser.
+ */
+final class Parser
+{
+    /**
+     * @return Diff[]
+     */
+    public function parse(string $string): array
+    {
+        $lines = preg_split('(\r\n|\r|\n)', $string);
+
+        if (!empty($lines) && $lines[count($lines) - 1] === '') {
+            array_pop($lines);
+        }
+
+        $lineCount = count($lines);
+        $diffs     = [];
+        $diff      = null;
+        $collected = [];
+
+        for ($i = 0; $i < $lineCount; ++$i) {
+            if (preg_match('#^---\h+"?(?P<file>[^\\v\\t"]+)#', $lines[$i], $fromMatch) &&
+                preg_match('#^\\+\\+\\+\\h+"?(?P<file>[^\\v\\t"]+)#', $lines[$i + 1], $toMatch)) {
+                if ($diff !== null) {
+                    $this->parseFileDiff($diff, $collected);
+
+                    $diffs[]   = $diff;
+                    $collected = [];
+                }
+
+                $diff = new Diff($fromMatch['file'], $toMatch['file']);
+
+                ++$i;
+            } else {
+                if (preg_match('/^(?:diff --git |index [\da-f\.]+|[+-]{3} [ab])/', $lines[$i])) {
+                    continue;
+                }
+
+                $collected[] = $lines[$i];
+            }
+        }
+
+        if ($diff !== null && count($collected)) {
+            $this->parseFileDiff($diff, $collected);
+
+            $diffs[] = $diff;
+        }
+
+        return $diffs;
+    }
+
+    private function parseFileDiff(Diff $diff, array $lines): void
+    {
+        $chunks    = [];
+        $chunk     = null;
+        $diffLines = [];
+
+        foreach ($lines as $line) {
+            if (preg_match('/^@@\s+-(?P<start>\d+)(?:,\s*(?P<startrange>\d+))?\s+\+(?P<end>\d+)(?:,\s*(?P<endrange>\d+))?\s+@@/', $line, $match)) {
+                $chunk = new Chunk(
+                    (int) $match['start'],
+                    isset($match['startrange']) ? max(1, (int) $match['startrange']) : 1,
+                    (int) $match['end'],
+                    isset($match['endrange']) ? max(1, (int) $match['endrange']) : 1
+                );
+
+                $chunks[]  = $chunk;
+                $diffLines = [];
+
+                continue;
+            }
+
+            if (preg_match('/^(?P<type>[+ -])?(?P<line>.*)/', $line, $match)) {
+                $type = Line::UNCHANGED;
+
+                if ($match['type'] === '+') {
+                    $type = Line::ADDED;
+                } elseif ($match['type'] === '-') {
+                    $type = Line::REMOVED;
+                }
+
+                $diffLines[] = new Line($type, $match['line']);
+
+                if (null !== $chunk) {
+                    $chunk->setLines($diffLines);
+                }
+            }
+        }
+
+        $diff->setChunks($chunks);
+    }
+}
diff --git a/vendor/sebastian/diff/src/TimeEfficientLongestCommonSubsequenceCalculator.php b/vendor/sebastian/diff/src/TimeEfficientLongestCommonSubsequenceCalculator.php
new file mode 100644
index 0000000000000000000000000000000000000000..fd19cac76393c91f86671bedba2a774fd2a223b6
--- /dev/null
+++ b/vendor/sebastian/diff/src/TimeEfficientLongestCommonSubsequenceCalculator.php
@@ -0,0 +1,70 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of sebastian/diff.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\Diff;
+
+use function array_reverse;
+use function count;
+use function max;
+use SplFixedArray;
+
+final class TimeEfficientLongestCommonSubsequenceCalculator implements LongestCommonSubsequenceCalculator
+{
+    /**
+     * {@inheritdoc}
+     */
+    public function calculate(array $from, array $to): array
+    {
+        $common     = [];
+        $fromLength = count($from);
+        $toLength   = count($to);
+        $width      = $fromLength + 1;
+        $matrix     = new SplFixedArray($width * ($toLength + 1));
+
+        for ($i = 0; $i <= $fromLength; ++$i) {
+            $matrix[$i] = 0;
+        }
+
+        for ($j = 0; $j <= $toLength; ++$j) {
+            $matrix[$j * $width] = 0;
+        }
+
+        for ($i = 1; $i <= $fromLength; ++$i) {
+            for ($j = 1; $j <= $toLength; ++$j) {
+                $o          = ($j * $width) + $i;
+                $matrix[$o] = max(
+                    $matrix[$o - 1],
+                    $matrix[$o - $width],
+                    $from[$i - 1] === $to[$j - 1] ? $matrix[$o - $width - 1] + 1 : 0
+                );
+            }
+        }
+
+        $i = $fromLength;
+        $j = $toLength;
+
+        while ($i > 0 && $j > 0) {
+            if ($from[$i - 1] === $to[$j - 1]) {
+                $common[] = $from[$i - 1];
+                --$i;
+                --$j;
+            } else {
+                $o = ($j * $width) + $i;
+
+                if ($matrix[$o - $width] > $matrix[$o - 1]) {
+                    --$j;
+                } else {
+                    --$i;
+                }
+            }
+        }
+
+        return array_reverse($common);
+    }
+}
diff --git a/vendor/sebastian/environment/ChangeLog.md b/vendor/sebastian/environment/ChangeLog.md
new file mode 100644
index 0000000000000000000000000000000000000000..67daf03565c0beae2640b862105abea6b869459f
--- /dev/null
+++ b/vendor/sebastian/environment/ChangeLog.md
@@ -0,0 +1,169 @@
+# Changes in sebastianbergmann/environment
+
+All notable changes in `sebastianbergmann/environment` are documented in this file using the [Keep a CHANGELOG](http://keepachangelog.com/) principles.
+
+## [5.1.3] - 2020-09-28
+
+### Changed
+
+* Changed PHP version constraint in `composer.json` from `^7.3 || ^8.0` to `>=7.3`
+
+## [5.1.2] - 2020-06-26
+
+### Added
+
+* This component is now supported on PHP 8
+
+## [5.1.1] - 2020-06-15
+
+### Changed
+
+* Tests etc. are now ignored for archive exports
+
+## [5.1.0] - 2020-04-14
+
+### Added
+
+* `Runtime::performsJustInTimeCompilation()` returns `true` if PHP 8's JIT is active, `false` otherwise
+
+## [5.0.2] - 2020-03-31
+
+### Fixed
+
+* [#55](https://github.com/sebastianbergmann/environment/issues/55): `stty` command is executed even if no tty is available
+
+## [5.0.1] - 2020-02-19
+
+### Changed
+
+* `Runtime::getNameWithVersionAndCodeCoverageDriver()` now prioritizes PCOV over Xdebug when both extensions are loaded (just like php-code-coverage does)
+
+## [5.0.0] - 2020-02-07
+
+### Removed
+
+* This component is no longer supported on PHP 7.1 and PHP 7.2
+
+## [4.2.3] - 2019-11-20
+
+### Changed
+
+* [#50](https://github.com/sebastianbergmann/environment/pull/50): Windows improvements to console capabilities
+
+### Fixed
+
+* [#49](https://github.com/sebastianbergmann/environment/issues/49): Detection how OpCache handles docblocks does not work correctly when PHPDBG is used
+
+## [4.2.2] - 2019-05-05
+
+### Fixed
+
+* [#44](https://github.com/sebastianbergmann/environment/pull/44): `TypeError` in `Console::getNumberOfColumnsInteractive()`
+
+## [4.2.1] - 2019-04-25
+
+### Fixed
+
+* Fixed an issue in `Runtime::getCurrentSettings()`
+
+## [4.2.0] - 2019-04-25
+
+### Added
+
+* [#36](https://github.com/sebastianbergmann/environment/pull/36): `Runtime::getCurrentSettings()`
+
+## [4.1.0] - 2019-02-01
+
+### Added
+
+* Implemented `Runtime::getNameWithVersionAndCodeCoverageDriver()` method
+* [#34](https://github.com/sebastianbergmann/environment/pull/34): Support for PCOV extension
+
+## [4.0.2] - 2019-01-28
+
+### Fixed
+
+* [#33](https://github.com/sebastianbergmann/environment/issues/33): `Runtime::discardsComments()` returns true too eagerly
+
+### Removed
+
+* Removed support for Zend Optimizer+ in `Runtime::discardsComments()`
+
+## [4.0.1] - 2018-11-25
+
+### Fixed
+
+* [#31](https://github.com/sebastianbergmann/environment/issues/31): Regressions in `Console` class
+
+## [4.0.0] - 2018-10-23 [YANKED]
+
+### Fixed
+
+* [#25](https://github.com/sebastianbergmann/environment/pull/25): `Console::hasColorSupport()` does not work on Windows
+
+### Removed
+
+* This component is no longer supported on PHP 7.0
+
+## [3.1.0] - 2017-07-01
+
+### Added
+
+* [#21](https://github.com/sebastianbergmann/environment/issues/21): Equivalent of `PHP_OS_FAMILY` (for PHP < 7.2) 
+
+## [3.0.4] - 2017-06-20
+
+### Fixed
+
+* [#20](https://github.com/sebastianbergmann/environment/pull/20): PHP 7 mode of HHVM not forced
+
+## [3.0.3] - 2017-05-18
+
+### Fixed
+
+* [#18](https://github.com/sebastianbergmann/environment/issues/18): `Uncaught TypeError: preg_match() expects parameter 2 to be string, null given`
+
+## [3.0.2] - 2017-04-21
+
+### Fixed
+
+* [#17](https://github.com/sebastianbergmann/environment/issues/17): `Uncaught TypeError: trim() expects parameter 1 to be string, boolean given`
+
+## [3.0.1] - 2017-04-21
+
+### Fixed
+
+* Fixed inverted logic in `Runtime::discardsComments()`
+
+## [3.0.0] - 2017-04-21
+
+### Added
+
+* Implemented `Runtime::discardsComments()` for querying whether the PHP runtime discards annotations
+
+### Removed
+
+* This component is no longer supported on PHP 5.6
+
+[5.1.3]: https://github.com/sebastianbergmann/environment/compare/5.1.2...5.1.3
+[5.1.2]: https://github.com/sebastianbergmann/environment/compare/5.1.1...5.1.2
+[5.1.1]: https://github.com/sebastianbergmann/environment/compare/5.1.0...5.1.1
+[5.1.0]: https://github.com/sebastianbergmann/environment/compare/5.0.2...5.1.0
+[5.0.2]: https://github.com/sebastianbergmann/environment/compare/5.0.1...5.0.2
+[5.0.1]: https://github.com/sebastianbergmann/environment/compare/5.0.0...5.0.1
+[5.0.0]: https://github.com/sebastianbergmann/environment/compare/4.2.3...5.0.0
+[4.2.3]: https://github.com/sebastianbergmann/environment/compare/4.2.2...4.2.3
+[4.2.2]: https://github.com/sebastianbergmann/environment/compare/4.2.1...4.2.2
+[4.2.1]: https://github.com/sebastianbergmann/environment/compare/4.2.0...4.2.1
+[4.2.0]: https://github.com/sebastianbergmann/environment/compare/4.1.0...4.2.0
+[4.1.0]: https://github.com/sebastianbergmann/environment/compare/4.0.2...4.1.0
+[4.0.2]: https://github.com/sebastianbergmann/environment/compare/4.0.1...4.0.2
+[4.0.1]: https://github.com/sebastianbergmann/environment/compare/66691f8e2dc4641909166b275a9a4f45c0e89092...4.0.1
+[4.0.0]: https://github.com/sebastianbergmann/environment/compare/3.1.0...66691f8e2dc4641909166b275a9a4f45c0e89092
+[3.1.0]: https://github.com/sebastianbergmann/environment/compare/3.0...3.1.0
+[3.0.4]: https://github.com/sebastianbergmann/environment/compare/3.0.3...3.0.4
+[3.0.3]: https://github.com/sebastianbergmann/environment/compare/3.0.2...3.0.3
+[3.0.2]: https://github.com/sebastianbergmann/environment/compare/3.0.1...3.0.2
+[3.0.1]: https://github.com/sebastianbergmann/environment/compare/3.0.0...3.0.1
+[3.0.0]: https://github.com/sebastianbergmann/environment/compare/2.0...3.0.0
+
diff --git a/vendor/sebastian/environment/LICENSE b/vendor/sebastian/environment/LICENSE
new file mode 100644
index 0000000000000000000000000000000000000000..c580939915af8f85793be214029cf5f9badcd712
--- /dev/null
+++ b/vendor/sebastian/environment/LICENSE
@@ -0,0 +1,33 @@
+sebastian/environment
+
+Copyright (c) 2014-2020, Sebastian Bergmann <sebastian@phpunit.de>.
+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 Sebastian Bergmann nor the names of his
+   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/sebastian/environment/README.md b/vendor/sebastian/environment/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..24a9831e4feb769fd948221cdd1a571c1c1b2f52
--- /dev/null
+++ b/vendor/sebastian/environment/README.md
@@ -0,0 +1,22 @@
+# sebastian/environment
+
+[![Latest Stable Version](https://img.shields.io/packagist/v/sebastian/environment.svg?style=flat-square)](https://packagist.org/packages/sebastian/environment)
+[![Minimum PHP Version](https://img.shields.io/badge/php-%3E%3D%207.1-8892BF.svg?style=flat-square)](https://php.net/)
+[![CI Status](https://github.com/sebastianbergmann/environment/workflows/CI/badge.svg)](https://github.com/sebastianbergmann/environment/actions)
+[![Type Coverage](https://shepherd.dev/github/sebastianbergmann/environment/coverage.svg)](https://shepherd.dev/github/sebastianbergmann/environment)
+
+This component provides functionality that helps writing PHP code that has runtime-specific (PHP / HHVM) execution paths.
+
+## Installation
+
+You can add this library as a local, per-project dependency to your project using [Composer](https://getcomposer.org/):
+
+```
+composer require sebastian/environment
+```
+
+If you only need this library during development, for instance to run your project's test suite, then you should add it as a development-time dependency:
+
+```
+composer require --dev sebastian/environment
+```
diff --git a/vendor/sebastian/environment/composer.json b/vendor/sebastian/environment/composer.json
new file mode 100644
index 0000000000000000000000000000000000000000..d50dcfd781ed4cf6debc85034762aca5312a601f
--- /dev/null
+++ b/vendor/sebastian/environment/composer.json
@@ -0,0 +1,40 @@
+{
+    "name": "sebastian/environment",
+    "description": "Provides functionality to handle HHVM/PHP environments",
+    "keywords": ["environment","hhvm","xdebug"],
+    "homepage": "http://www.github.com/sebastianbergmann/environment",
+    "license": "BSD-3-Clause",
+    "authors": [
+        {
+            "name": "Sebastian Bergmann",
+            "email": "sebastian@phpunit.de"
+        }
+    ],
+    "config": {
+        "platform": {
+            "php": "7.3.0"
+        },
+        "optimize-autoloader": true,
+        "sort-packages": true
+    },
+    "prefer-stable": true,
+    "require": {
+        "php": ">=7.3"
+    },
+    "require-dev": {
+        "phpunit/phpunit": "^9.3"
+    },
+    "suggest": {
+        "ext-posix": "*"
+    },
+    "autoload": {
+        "classmap": [
+            "src/"
+        ]
+    },
+    "extra": {
+        "branch-alias": {
+            "dev-master": "5.1-dev"
+        }
+    }
+}
diff --git a/vendor/sebastian/environment/src/Console.php b/vendor/sebastian/environment/src/Console.php
new file mode 100644
index 0000000000000000000000000000000000000000..c4a2348f06aed03de9cd5b22676e71350ab31b59
--- /dev/null
+++ b/vendor/sebastian/environment/src/Console.php
@@ -0,0 +1,189 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of sebastian/environment.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\Environment;
+
+use const DIRECTORY_SEPARATOR;
+use const STDIN;
+use const STDOUT;
+use function defined;
+use function fclose;
+use function fstat;
+use function function_exists;
+use function getenv;
+use function is_resource;
+use function is_string;
+use function posix_isatty;
+use function preg_match;
+use function proc_close;
+use function proc_open;
+use function sapi_windows_vt100_support;
+use function shell_exec;
+use function stream_get_contents;
+use function stream_isatty;
+use function trim;
+
+final class Console
+{
+    /**
+     * @var int
+     */
+    public const STDIN  = 0;
+
+    /**
+     * @var int
+     */
+    public const STDOUT = 1;
+
+    /**
+     * @var int
+     */
+    public const STDERR = 2;
+
+    /**
+     * Returns true if STDOUT supports colorization.
+     *
+     * This code has been copied and adapted from
+     * Symfony\Component\Console\Output\StreamOutput.
+     */
+    public function hasColorSupport(): bool
+    {
+        if ('Hyper' === getenv('TERM_PROGRAM')) {
+            return true;
+        }
+
+        if ($this->isWindows()) {
+            // @codeCoverageIgnoreStart
+            return (defined('STDOUT') && function_exists('sapi_windows_vt100_support') && @sapi_windows_vt100_support(STDOUT))
+                || false !== getenv('ANSICON')
+                || 'ON' === getenv('ConEmuANSI')
+                || 'xterm' === getenv('TERM');
+            // @codeCoverageIgnoreEnd
+        }
+
+        if (!defined('STDOUT')) {
+            // @codeCoverageIgnoreStart
+            return false;
+            // @codeCoverageIgnoreEnd
+        }
+
+        return $this->isInteractive(STDOUT);
+    }
+
+    /**
+     * Returns the number of columns of the terminal.
+     *
+     * @codeCoverageIgnore
+     */
+    public function getNumberOfColumns(): int
+    {
+        if (!$this->isInteractive(defined('STDIN') ? STDIN : self::STDIN)) {
+            return 80;
+        }
+
+        if ($this->isWindows()) {
+            return $this->getNumberOfColumnsWindows();
+        }
+
+        return $this->getNumberOfColumnsInteractive();
+    }
+
+    /**
+     * Returns if the file descriptor is an interactive terminal or not.
+     *
+     * Normally, we want to use a resource as a parameter, yet sadly it's not always awailable,
+     * eg when running code in interactive console (`php -a`), STDIN/STDOUT/STDERR constants are not defined.
+     *
+     * @param int|resource $fileDescriptor
+     */
+    public function isInteractive($fileDescriptor = self::STDOUT): bool
+    {
+        if (is_resource($fileDescriptor)) {
+            // These functions require a descriptor that is a real resource, not a numeric ID of it
+            if (function_exists('stream_isatty') && @stream_isatty($fileDescriptor)) {
+                return true;
+            }
+
+            // Check if formatted mode is S_IFCHR
+            if (function_exists('fstat') && @stream_isatty($fileDescriptor)) {
+                $stat = @fstat(STDOUT);
+
+                return $stat ? 0020000 === ($stat['mode'] & 0170000) : false;
+            }
+
+            return false;
+        }
+
+        return function_exists('posix_isatty') && @posix_isatty($fileDescriptor);
+    }
+
+    private function isWindows(): bool
+    {
+        return DIRECTORY_SEPARATOR === '\\';
+    }
+
+    /**
+     * @codeCoverageIgnore
+     */
+    private function getNumberOfColumnsInteractive(): int
+    {
+        if (function_exists('shell_exec') && preg_match('#\d+ (\d+)#', shell_exec('stty size') ?: '', $match) === 1) {
+            if ((int) $match[1] > 0) {
+                return (int) $match[1];
+            }
+        }
+
+        if (function_exists('shell_exec') && preg_match('#columns = (\d+);#', shell_exec('stty') ?: '', $match) === 1) {
+            if ((int) $match[1] > 0) {
+                return (int) $match[1];
+            }
+        }
+
+        return 80;
+    }
+
+    /**
+     * @codeCoverageIgnore
+     */
+    private function getNumberOfColumnsWindows(): int
+    {
+        $ansicon = getenv('ANSICON');
+        $columns = 80;
+
+        if (is_string($ansicon) && preg_match('/^(\d+)x\d+ \(\d+x(\d+)\)$/', trim($ansicon), $matches)) {
+            $columns = (int) $matches[1];
+        } elseif (function_exists('proc_open')) {
+            $process = proc_open(
+                'mode CON',
+                [
+                    1 => ['pipe', 'w'],
+                    2 => ['pipe', 'w'],
+                ],
+                $pipes,
+                null,
+                null,
+                ['suppress_errors' => true]
+            );
+
+            if (is_resource($process)) {
+                $info = stream_get_contents($pipes[1]);
+
+                fclose($pipes[1]);
+                fclose($pipes[2]);
+                proc_close($process);
+
+                if (preg_match('/--------+\r?\n.+?(\d+)\r?\n.+?(\d+)\r?\n/', $info, $matches)) {
+                    $columns = (int) $matches[2];
+                }
+            }
+        }
+
+        return $columns - 1;
+    }
+}
diff --git a/vendor/sebastian/environment/src/OperatingSystem.php b/vendor/sebastian/environment/src/OperatingSystem.php
new file mode 100644
index 0000000000000000000000000000000000000000..1f3ebca7c68f64ebb1adcfd6d71c37b6e85fa7e7
--- /dev/null
+++ b/vendor/sebastian/environment/src/OperatingSystem.php
@@ -0,0 +1,53 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of sebastian/environment.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\Environment;
+
+use const DIRECTORY_SEPARATOR;
+use const PHP_OS;
+use const PHP_OS_FAMILY;
+use function defined;
+
+final class OperatingSystem
+{
+    /**
+     * Returns PHP_OS_FAMILY (if defined (which it is on PHP >= 7.2)).
+     * Returns a string (compatible with PHP_OS_FAMILY) derived from PHP_OS otherwise.
+     */
+    public function getFamily(): string
+    {
+        if (defined('PHP_OS_FAMILY')) {
+            return PHP_OS_FAMILY;
+        }
+
+        if (DIRECTORY_SEPARATOR === '\\') {
+            return 'Windows';
+        }
+
+        switch (PHP_OS) {
+            case 'Darwin':
+                return 'Darwin';
+
+            case 'DragonFly':
+            case 'FreeBSD':
+            case 'NetBSD':
+            case 'OpenBSD':
+                return 'BSD';
+
+            case 'Linux':
+                return 'Linux';
+
+            case 'SunOS':
+                return 'Solaris';
+
+            default:
+                return 'Unknown';
+        }
+    }
+}
diff --git a/vendor/sebastian/environment/src/Runtime.php b/vendor/sebastian/environment/src/Runtime.php
new file mode 100644
index 0000000000000000000000000000000000000000..311aefcb636080c6028a684e7ddea99963ae4224
--- /dev/null
+++ b/vendor/sebastian/environment/src/Runtime.php
@@ -0,0 +1,317 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of sebastian/environment.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\Environment;
+
+use const PHP_BINARY;
+use const PHP_BINDIR;
+use const PHP_MAJOR_VERSION;
+use const PHP_SAPI;
+use const PHP_VERSION;
+use function array_map;
+use function array_merge;
+use function defined;
+use function escapeshellarg;
+use function explode;
+use function extension_loaded;
+use function getenv;
+use function ini_get;
+use function is_readable;
+use function parse_ini_file;
+use function php_ini_loaded_file;
+use function php_ini_scanned_files;
+use function phpversion;
+use function sprintf;
+use function strpos;
+
+/**
+ * Utility class for HHVM/PHP environment handling.
+ */
+final class Runtime
+{
+    /**
+     * @var string
+     */
+    private static $binary;
+
+    /**
+     * Returns true when Xdebug or PCOV is available or
+     * the runtime used is PHPDBG.
+     */
+    public function canCollectCodeCoverage(): bool
+    {
+        return $this->hasXdebug() || $this->hasPCOV() || $this->hasPHPDBGCodeCoverage();
+    }
+
+    /**
+     * Returns true when Zend OPcache is loaded, enabled,
+     * and is configured to discard comments.
+     */
+    public function discardsComments(): bool
+    {
+        if (!$this->isOpcacheActive()) {
+            return false;
+        }
+
+        if (ini_get('opcache.save_comments') !== '0') {
+            return false;
+        }
+
+        return true;
+    }
+
+    /**
+     * Returns true when Zend OPcache is loaded, enabled,
+     * and is configured to perform just-in-time compilation.
+     */
+    public function performsJustInTimeCompilation(): bool
+    {
+        if (PHP_MAJOR_VERSION < 8) {
+            return false;
+        }
+
+        if (!$this->isOpcacheActive()) {
+            return false;
+        }
+
+        if (strpos(ini_get('opcache.jit'), '0') === 0) {
+            return false;
+        }
+
+        return true;
+    }
+
+    /**
+     * Returns the path to the binary of the current runtime.
+     * Appends ' --php' to the path when the runtime is HHVM.
+     */
+    public function getBinary(): string
+    {
+        // HHVM
+        if (self::$binary === null && $this->isHHVM()) {
+            // @codeCoverageIgnoreStart
+            if ((self::$binary = getenv('PHP_BINARY')) === false) {
+                self::$binary = PHP_BINARY;
+            }
+
+            self::$binary = escapeshellarg(self::$binary) . ' --php' .
+                ' -d hhvm.php7.all=1';
+            // @codeCoverageIgnoreEnd
+        }
+
+        if (self::$binary === null && PHP_BINARY !== '') {
+            self::$binary = escapeshellarg(PHP_BINARY);
+        }
+
+        if (self::$binary === null) {
+            // @codeCoverageIgnoreStart
+            $possibleBinaryLocations = [
+                PHP_BINDIR . '/php',
+                PHP_BINDIR . '/php-cli.exe',
+                PHP_BINDIR . '/php.exe',
+            ];
+
+            foreach ($possibleBinaryLocations as $binary) {
+                if (is_readable($binary)) {
+                    self::$binary = escapeshellarg($binary);
+
+                    break;
+                }
+            }
+            // @codeCoverageIgnoreEnd
+        }
+
+        if (self::$binary === null) {
+            // @codeCoverageIgnoreStart
+            self::$binary = 'php';
+            // @codeCoverageIgnoreEnd
+        }
+
+        return self::$binary;
+    }
+
+    public function getNameWithVersion(): string
+    {
+        return $this->getName() . ' ' . $this->getVersion();
+    }
+
+    public function getNameWithVersionAndCodeCoverageDriver(): string
+    {
+        if (!$this->canCollectCodeCoverage() || $this->hasPHPDBGCodeCoverage()) {
+            return $this->getNameWithVersion();
+        }
+
+        if ($this->hasPCOV()) {
+            return sprintf(
+                '%s with PCOV %s',
+                $this->getNameWithVersion(),
+                phpversion('pcov')
+            );
+        }
+
+        if ($this->hasXdebug()) {
+            return sprintf(
+                '%s with Xdebug %s',
+                $this->getNameWithVersion(),
+                phpversion('xdebug')
+            );
+        }
+    }
+
+    public function getName(): string
+    {
+        if ($this->isHHVM()) {
+            // @codeCoverageIgnoreStart
+            return 'HHVM';
+            // @codeCoverageIgnoreEnd
+        }
+
+        if ($this->isPHPDBG()) {
+            // @codeCoverageIgnoreStart
+            return 'PHPDBG';
+            // @codeCoverageIgnoreEnd
+        }
+
+        return 'PHP';
+    }
+
+    public function getVendorUrl(): string
+    {
+        if ($this->isHHVM()) {
+            // @codeCoverageIgnoreStart
+            return 'http://hhvm.com/';
+            // @codeCoverageIgnoreEnd
+        }
+
+        return 'https://secure.php.net/';
+    }
+
+    public function getVersion(): string
+    {
+        if ($this->isHHVM()) {
+            // @codeCoverageIgnoreStart
+            return HHVM_VERSION;
+            // @codeCoverageIgnoreEnd
+        }
+
+        return PHP_VERSION;
+    }
+
+    /**
+     * Returns true when the runtime used is PHP and Xdebug is loaded.
+     */
+    public function hasXdebug(): bool
+    {
+        return ($this->isPHP() || $this->isHHVM()) && extension_loaded('xdebug');
+    }
+
+    /**
+     * Returns true when the runtime used is HHVM.
+     */
+    public function isHHVM(): bool
+    {
+        return defined('HHVM_VERSION');
+    }
+
+    /**
+     * Returns true when the runtime used is PHP without the PHPDBG SAPI.
+     */
+    public function isPHP(): bool
+    {
+        return !$this->isHHVM() && !$this->isPHPDBG();
+    }
+
+    /**
+     * Returns true when the runtime used is PHP with the PHPDBG SAPI.
+     */
+    public function isPHPDBG(): bool
+    {
+        return PHP_SAPI === 'phpdbg' && !$this->isHHVM();
+    }
+
+    /**
+     * Returns true when the runtime used is PHP with the PHPDBG SAPI
+     * and the phpdbg_*_oplog() functions are available (PHP >= 7.0).
+     */
+    public function hasPHPDBGCodeCoverage(): bool
+    {
+        return $this->isPHPDBG();
+    }
+
+    /**
+     * Returns true when the runtime used is PHP with PCOV loaded and enabled.
+     */
+    public function hasPCOV(): bool
+    {
+        return $this->isPHP() && extension_loaded('pcov') && ini_get('pcov.enabled');
+    }
+
+    /**
+     * Parses the loaded php.ini file (if any) as well as all
+     * additional php.ini files from the additional ini dir for
+     * a list of all configuration settings loaded from files
+     * at startup. Then checks for each php.ini setting passed
+     * via the `$values` parameter whether this setting has
+     * been changed at runtime. Returns an array of strings
+     * where each string has the format `key=value` denoting
+     * the name of a changed php.ini setting with its new value.
+     *
+     * @return string[]
+     */
+    public function getCurrentSettings(array $values): array
+    {
+        $diff  = [];
+        $files = [];
+
+        if ($file = php_ini_loaded_file()) {
+            $files[] = $file;
+        }
+
+        if ($scanned = php_ini_scanned_files()) {
+            $files = array_merge(
+                $files,
+                array_map(
+                    'trim',
+                    explode(",\n", $scanned)
+                )
+            );
+        }
+
+        foreach ($files as $ini) {
+            $config = parse_ini_file($ini, true);
+
+            foreach ($values as $value) {
+                $set = ini_get($value);
+
+                if (isset($config[$value]) && $set != $config[$value]) {
+                    $diff[] = sprintf('%s=%s', $value, $set);
+                }
+            }
+        }
+
+        return $diff;
+    }
+
+    private function isOpcacheActive(): bool
+    {
+        if (!extension_loaded('Zend OPcache')) {
+            return false;
+        }
+
+        if ((PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') && ini_get('opcache.enable_cli') === '1') {
+            return true;
+        }
+
+        if (PHP_SAPI !== 'cli' && PHP_SAPI !== 'phpdbg' && ini_get('opcache.enable') === '1') {
+            return true;
+        }
+
+        return false;
+    }
+}
diff --git a/vendor/sebastian/exporter/ChangeLog.md b/vendor/sebastian/exporter/ChangeLog.md
new file mode 100644
index 0000000000000000000000000000000000000000..913912c59d07922858ee13eff1c0be8c2c4189a6
--- /dev/null
+++ b/vendor/sebastian/exporter/ChangeLog.md
@@ -0,0 +1,43 @@
+# ChangeLog
+
+All notable changes are documented in this file using the [Keep a CHANGELOG](https://keepachangelog.com/) principles.
+
+## [4.0.3] - 2020-09-28
+
+### Changed
+
+* Changed PHP version constraint in `composer.json` from `^7.3 || ^8.0` to `>=7.3`
+
+## [4.0.2] - 2020-06-26
+
+### Added
+
+* This component is now supported on PHP 8
+
+## [4.0.1] - 2020-06-15
+
+### Changed
+
+* Tests etc. are now ignored for archive exports
+
+## [4.0.0] - 2020-02-07
+
+### Removed
+
+* This component is no longer supported on PHP 7.0, PHP 7.1, and PHP 7.2
+
+## [3.1.2] - 2019-09-14
+
+### Fixed
+
+* Fixed [#29](https://github.com/sebastianbergmann/exporter/pull/29): Second parameter for `str_repeat()` must be an integer
+
+### Removed
+
+* Remove HHVM-specific code that is no longer needed
+
+[4.0.3]: https://github.com/sebastianbergmann/exporter/compare/4.0.2...4.0.3
+[4.0.2]: https://github.com/sebastianbergmann/exporter/compare/4.0.1...4.0.2
+[4.0.1]: https://github.com/sebastianbergmann/exporter/compare/4.0.0...4.0.1
+[4.0.0]: https://github.com/sebastianbergmann/exporter/compare/3.1.2...4.0.0
+[3.1.2]: https://github.com/sebastianbergmann/exporter/compare/3.1.1...3.1.2
diff --git a/vendor/sebastian/exporter/LICENSE b/vendor/sebastian/exporter/LICENSE
new file mode 100644
index 0000000000000000000000000000000000000000..aa33509cf72a89f632f3643a9e2c19864c422fbc
--- /dev/null
+++ b/vendor/sebastian/exporter/LICENSE
@@ -0,0 +1,33 @@
+Exporter
+
+Copyright (c) 2002-2020, Sebastian Bergmann <sebastian@phpunit.de>.
+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 Sebastian Bergmann nor the names of his
+   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/sebastian/exporter/README.md b/vendor/sebastian/exporter/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..ed8719f564470e5a6414ac4c339903f849dac981
--- /dev/null
+++ b/vendor/sebastian/exporter/README.md
@@ -0,0 +1,174 @@
+# sebastian/exporter
+
+[![CI Status](https://github.com/sebastianbergmann/exporter/workflows/CI/badge.svg)](https://github.com/sebastianbergmann/exporter/actions)
+[![Type Coverage](https://shepherd.dev/github/sebastianbergmann/exporter/coverage.svg)](https://shepherd.dev/github/sebastianbergmann/exporter)
+
+This component provides the functionality to export PHP variables for visualization.
+
+## Installation
+
+You can add this library as a local, per-project dependency to your project using [Composer](https://getcomposer.org/):
+
+```
+composer require sebastian/exporter
+```
+
+If you only need this library during development, for instance to run your project's test suite, then you should add it as a development-time dependency:
+
+```
+composer require --dev sebastian/exporter
+```
+
+## Usage
+
+Exporting:
+
+```php
+<?php
+use SebastianBergmann\Exporter\Exporter;
+
+$exporter = new Exporter;
+
+/*
+Exception Object &0000000078de0f0d000000002003a261 (
+    'message' => ''
+    'string' => ''
+    'code' => 0
+    'file' => '/home/sebastianbergmann/test.php'
+    'line' => 34
+    'previous' => null
+)
+*/
+
+print $exporter->export(new Exception);
+```
+
+## Data Types
+
+Exporting simple types:
+
+```php
+<?php
+use SebastianBergmann\Exporter\Exporter;
+
+$exporter = new Exporter;
+
+// 46
+print $exporter->export(46);
+
+// 4.0
+print $exporter->export(4.0);
+
+// 'hello, world!'
+print $exporter->export('hello, world!');
+
+// false
+print $exporter->export(false);
+
+// NAN
+print $exporter->export(acos(8));
+
+// -INF
+print $exporter->export(log(0));
+
+// null
+print $exporter->export(null);
+
+// resource(13) of type (stream)
+print $exporter->export(fopen('php://stderr', 'w'));
+
+// Binary String: 0x000102030405
+print $exporter->export(chr(0) . chr(1) . chr(2) . chr(3) . chr(4) . chr(5));
+```
+
+Exporting complex types:
+
+```php
+<?php
+use SebastianBergmann\Exporter\Exporter;
+
+$exporter = new Exporter;
+
+/*
+Array &0 (
+    0 => Array &1 (
+        0 => 1
+        1 => 2
+        2 => 3
+    )
+    1 => Array &2 (
+        0 => ''
+        1 => 0
+        2 => false
+    )
+)
+*/
+
+print $exporter->export(array(array(1,2,3), array("",0,FALSE)));
+
+/*
+Array &0 (
+    'self' => Array &1 (
+        'self' => Array &1
+    )
+)
+*/
+
+$array = array();
+$array['self'] = &$array;
+print $exporter->export($array);
+
+/*
+stdClass Object &0000000003a66dcc0000000025e723e2 (
+    'self' => stdClass Object &0000000003a66dcc0000000025e723e2
+)
+*/
+
+$obj = new stdClass();
+$obj->self = $obj;
+print $exporter->export($obj);
+```
+
+Compact exports:
+
+```php
+<?php
+use SebastianBergmann\Exporter\Exporter;
+
+$exporter = new Exporter;
+
+// Array ()
+print $exporter->shortenedExport(array());
+
+// Array (...)
+print $exporter->shortenedExport(array(1,2,3,4,5));
+
+// stdClass Object ()
+print $exporter->shortenedExport(new stdClass);
+
+// Exception Object (...)
+print $exporter->shortenedExport(new Exception);
+
+// this\nis\na\nsuper\nlong\nstring\nt...\nspace
+print $exporter->shortenedExport(
+<<<LONG_STRING
+this
+is
+a
+super
+long
+string
+that
+wraps
+a
+lot
+and
+eats
+up
+a
+lot
+of
+space
+LONG_STRING
+);
+```
diff --git a/vendor/sebastian/exporter/composer.json b/vendor/sebastian/exporter/composer.json
new file mode 100644
index 0000000000000000000000000000000000000000..477d5edd19117ecd600fb582b2540b407b908d44
--- /dev/null
+++ b/vendor/sebastian/exporter/composer.json
@@ -0,0 +1,56 @@
+{
+    "name": "sebastian/exporter",
+    "description": "Provides the functionality to export PHP variables for visualization",
+    "keywords": ["exporter","export"],
+    "homepage": "http://www.github.com/sebastianbergmann/exporter",
+    "license": "BSD-3-Clause",
+    "authors": [
+        {
+            "name": "Sebastian Bergmann",
+            "email": "sebastian@phpunit.de"
+        },
+        {
+            "name": "Jeff Welch",
+            "email": "whatthejeff@gmail.com"
+        },
+        {
+            "name": "Volker Dusch",
+            "email": "github@wallbash.com"
+        },
+        {
+            "name": "Adam Harvey",
+            "email": "aharvey@php.net"
+        },
+        {
+            "name": "Bernhard Schussek",
+            "email": "bschussek@gmail.com"
+        }
+    ],
+    "config": {
+        "platform": {
+            "php": "7.3.0"
+        },
+        "optimize-autoloader": true,
+        "sort-packages": true
+    },
+    "prefer-stable": true,
+    "require": {
+        "php": ">=7.3",
+        "sebastian/recursion-context": "^4.0"
+    },
+    "require-dev": {
+        "phpunit/phpunit": "^9.3",
+        "ext-mbstring": "*"
+    },
+    "autoload": {
+        "classmap": [
+            "src/"
+        ]
+    },
+    "extra": {
+        "branch-alias": {
+            "dev-master": "4.0-dev"
+        }
+    }
+}
+
diff --git a/vendor/sebastian/exporter/src/Exporter.php b/vendor/sebastian/exporter/src/Exporter.php
new file mode 100644
index 0000000000000000000000000000000000000000..e6fff5a49fb50474911462868662290897ec017d
--- /dev/null
+++ b/vendor/sebastian/exporter/src/Exporter.php
@@ -0,0 +1,325 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of sebastian/exporter.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\Exporter;
+
+use function bin2hex;
+use function count;
+use function function_exists;
+use function get_class;
+use function get_resource_type;
+use function implode;
+use function is_array;
+use function is_float;
+use function is_object;
+use function is_resource;
+use function is_string;
+use function mb_strlen;
+use function mb_substr;
+use function preg_match;
+use function spl_object_hash;
+use function sprintf;
+use function str_repeat;
+use function str_replace;
+use function strlen;
+use function substr;
+use function var_export;
+use SebastianBergmann\RecursionContext\Context;
+use SplObjectStorage;
+
+/**
+ * A nifty utility for visualizing PHP variables.
+ *
+ * <code>
+ * <?php
+ * use SebastianBergmann\Exporter\Exporter;
+ *
+ * $exporter = new Exporter;
+ * print $exporter->export(new Exception);
+ * </code>
+ */
+class Exporter
+{
+    /**
+     * Exports a value as a string.
+     *
+     * The output of this method is similar to the output of print_r(), but
+     * improved in various aspects:
+     *
+     *  - NULL is rendered as "null" (instead of "")
+     *  - TRUE is rendered as "true" (instead of "1")
+     *  - FALSE is rendered as "false" (instead of "")
+     *  - Strings are always quoted with single quotes
+     *  - Carriage returns and newlines are normalized to \n
+     *  - Recursion and repeated rendering is treated properly
+     *
+     * @param int $indentation The indentation level of the 2nd+ line
+     *
+     * @return string
+     */
+    public function export($value, $indentation = 0)
+    {
+        return $this->recursiveExport($value, $indentation);
+    }
+
+    /**
+     * @param array<mixed> $data
+     * @param Context      $context
+     *
+     * @return string
+     */
+    public function shortenedRecursiveExport(&$data, Context $context = null)
+    {
+        $result   = [];
+        $exporter = new self();
+
+        if (!$context) {
+            $context = new Context;
+        }
+
+        $array = $data;
+        $context->add($data);
+
+        foreach ($array as $key => $value) {
+            if (is_array($value)) {
+                if ($context->contains($data[$key]) !== false) {
+                    $result[] = '*RECURSION*';
+                } else {
+                    $result[] = sprintf(
+                        'array(%s)',
+                        $this->shortenedRecursiveExport($data[$key], $context)
+                    );
+                }
+            } else {
+                $result[] = $exporter->shortenedExport($value);
+            }
+        }
+
+        return implode(', ', $result);
+    }
+
+    /**
+     * Exports a value into a single-line string.
+     *
+     * The output of this method is similar to the output of
+     * SebastianBergmann\Exporter\Exporter::export().
+     *
+     * Newlines are replaced by the visible string '\n'.
+     * Contents of arrays and objects (if any) are replaced by '...'.
+     *
+     * @return string
+     *
+     * @see    SebastianBergmann\Exporter\Exporter::export
+     */
+    public function shortenedExport($value)
+    {
+        if (is_string($value)) {
+            $string = str_replace("\n", '', $this->export($value));
+
+            if (function_exists('mb_strlen')) {
+                if (mb_strlen($string) > 40) {
+                    $string = mb_substr($string, 0, 30) . '...' . mb_substr($string, -7);
+                }
+            } else {
+                if (strlen($string) > 40) {
+                    $string = substr($string, 0, 30) . '...' . substr($string, -7);
+                }
+            }
+
+            return $string;
+        }
+
+        if (is_object($value)) {
+            return sprintf(
+                '%s Object (%s)',
+                get_class($value),
+                count($this->toArray($value)) > 0 ? '...' : ''
+            );
+        }
+
+        if (is_array($value)) {
+            return sprintf(
+                'Array (%s)',
+                count($value) > 0 ? '...' : ''
+            );
+        }
+
+        return $this->export($value);
+    }
+
+    /**
+     * Converts an object to an array containing all of its private, protected
+     * and public properties.
+     *
+     * @return array
+     */
+    public function toArray($value)
+    {
+        if (!is_object($value)) {
+            return (array) $value;
+        }
+
+        $array = [];
+
+        foreach ((array) $value as $key => $val) {
+            // Exception traces commonly reference hundreds to thousands of
+            // objects currently loaded in memory. Including them in the result
+            // has a severe negative performance impact.
+            if ("\0Error\0trace" === $key || "\0Exception\0trace" === $key) {
+                continue;
+            }
+
+            // properties are transformed to keys in the following way:
+            // private   $property => "\0Classname\0property"
+            // protected $property => "\0*\0property"
+            // public    $property => "property"
+            if (preg_match('/^\0.+\0(.+)$/', (string) $key, $matches)) {
+                $key = $matches[1];
+            }
+
+            // See https://github.com/php/php-src/commit/5721132
+            if ($key === "\0gcdata") {
+                continue;
+            }
+
+            $array[$key] = $val;
+        }
+
+        // Some internal classes like SplObjectStorage don't work with the
+        // above (fast) mechanism nor with reflection in Zend.
+        // Format the output similarly to print_r() in this case
+        if ($value instanceof SplObjectStorage) {
+            foreach ($value as $key => $val) {
+                $array[spl_object_hash($val)] = [
+                    'obj' => $val,
+                    'inf' => $value->getInfo(),
+                ];
+            }
+        }
+
+        return $array;
+    }
+
+    /**
+     * Recursive implementation of export.
+     *
+     * @param mixed                                       $value       The value to export
+     * @param int                                         $indentation The indentation level of the 2nd+ line
+     * @param \SebastianBergmann\RecursionContext\Context $processed   Previously processed objects
+     *
+     * @return string
+     *
+     * @see    SebastianBergmann\Exporter\Exporter::export
+     */
+    protected function recursiveExport(&$value, $indentation, $processed = null)
+    {
+        if ($value === null) {
+            return 'null';
+        }
+
+        if ($value === true) {
+            return 'true';
+        }
+
+        if ($value === false) {
+            return 'false';
+        }
+
+        if (is_float($value) && (float) ((int) $value) === $value) {
+            return "$value.0";
+        }
+
+        if (is_resource($value)) {
+            return sprintf(
+                'resource(%d) of type (%s)',
+                $value,
+                get_resource_type($value)
+            );
+        }
+
+        if (is_string($value)) {
+            // Match for most non printable chars somewhat taking multibyte chars into account
+            if (preg_match('/[^\x09-\x0d\x1b\x20-\xff]/', $value)) {
+                return 'Binary String: 0x' . bin2hex($value);
+            }
+
+            return "'" .
+            str_replace(
+                '<lf>',
+                "\n",
+                str_replace(
+                    ["\r\n", "\n\r", "\r", "\n"],
+                    ['\r\n<lf>', '\n\r<lf>', '\r<lf>', '\n<lf>'],
+                    $value
+                )
+            ) .
+            "'";
+        }
+
+        $whitespace = str_repeat(' ', (int) (4 * $indentation));
+
+        if (!$processed) {
+            $processed = new Context;
+        }
+
+        if (is_array($value)) {
+            if (($key = $processed->contains($value)) !== false) {
+                return 'Array &' . $key;
+            }
+
+            $array  = $value;
+            $key    = $processed->add($value);
+            $values = '';
+
+            if (count($array) > 0) {
+                foreach ($array as $k => $v) {
+                    $values .= sprintf(
+                        '%s    %s => %s' . "\n",
+                        $whitespace,
+                        $this->recursiveExport($k, $indentation),
+                        $this->recursiveExport($value[$k], $indentation + 1, $processed)
+                    );
+                }
+
+                $values = "\n" . $values . $whitespace;
+            }
+
+            return sprintf('Array &%s (%s)', $key, $values);
+        }
+
+        if (is_object($value)) {
+            $class = get_class($value);
+
+            if ($hash = $processed->contains($value)) {
+                return sprintf('%s Object &%s', $class, $hash);
+            }
+
+            $hash   = $processed->add($value);
+            $values = '';
+            $array  = $this->toArray($value);
+
+            if (count($array) > 0) {
+                foreach ($array as $k => $v) {
+                    $values .= sprintf(
+                        '%s    %s => %s' . "\n",
+                        $whitespace,
+                        $this->recursiveExport($k, $indentation),
+                        $this->recursiveExport($v, $indentation + 1, $processed)
+                    );
+                }
+
+                $values = "\n" . $values . $whitespace;
+            }
+
+            return sprintf('%s Object &%s (%s)', $class, $hash, $values);
+        }
+
+        return var_export($value, true);
+    }
+}
diff --git a/vendor/sebastian/global-state/ChangeLog.md b/vendor/sebastian/global-state/ChangeLog.md
new file mode 100644
index 0000000000000000000000000000000000000000..e6114f903854ce51cc9fdbb66f9efced04643747
--- /dev/null
+++ b/vendor/sebastian/global-state/ChangeLog.md
@@ -0,0 +1,44 @@
+# Changes in sebastian/global-state
+
+All notable changes in `sebastian/global-state` are documented in this file using the [Keep a CHANGELOG](https://keepachangelog.com/) principles.
+
+## [5.0.2] - 2020-10-26
+
+### Fixed
+
+* `SebastianBergmann\GlobalState\Exception` now correctly extends `\Throwable`
+
+## [5.0.1] - 2020-09-28
+
+### Changed
+
+* Changed PHP version constraint in `composer.json` from `^7.3 || ^8.0` to `>=7.3`
+
+## [5.0.0] - 2020-08-07
+
+### Changed
+
+* The `SebastianBergmann\GlobalState\Blacklist` class has been renamed to `SebastianBergmann\GlobalState\ExcludeList`
+
+## [4.0.0] - 2020-02-07
+
+### Removed
+
+* This component is no longer supported on PHP 7.2
+
+## [3.0.0] - 2019-02-01
+
+### Changed
+
+* `Snapshot::canBeSerialized()` now recursively checks arrays and object graphs for variables that cannot be serialized
+
+### Removed
+
+* This component is no longer supported on PHP 7.0 and PHP 7.1
+
+[5.0.2]: https://github.com/sebastianbergmann/global-state/compare/5.0.1...5.0.2
+[5.0.1]: https://github.com/sebastianbergmann/global-state/compare/5.0.0...5.0.1
+[5.0.0]: https://github.com/sebastianbergmann/global-state/compare/4.0.0...5.0.0
+[4.0.0]: https://github.com/sebastianbergmann/global-state/compare/3.0.0...4.0.0
+[3.0.0]: https://github.com/sebastianbergmann/global-state/compare/2.0.0...3.0.0
+
diff --git a/vendor/sebastian/global-state/LICENSE b/vendor/sebastian/global-state/LICENSE
new file mode 100644
index 0000000000000000000000000000000000000000..f492960e63727c70a70bc65de48f38a6daf284ba
--- /dev/null
+++ b/vendor/sebastian/global-state/LICENSE
@@ -0,0 +1,33 @@
+sebastian/global-state
+
+Copyright (c) 2001-2020, Sebastian Bergmann <sebastian@phpunit.de>.
+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 Sebastian Bergmann nor the names of his
+   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/sebastian/global-state/README.md b/vendor/sebastian/global-state/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..af15bedde08a588b8a049d7b321e191b317cb21e
--- /dev/null
+++ b/vendor/sebastian/global-state/README.md
@@ -0,0 +1,20 @@
+# sebastian/global-state
+
+[![CI Status](https://github.com/sebastianbergmann/global-state/workflows/CI/badge.svg)](https://github.com/sebastianbergmann/global-state/actions)
+[![Type Coverage](https://shepherd.dev/github/sebastianbergmann/global-state/coverage.svg)](https://shepherd.dev/github/sebastianbergmann/global-state)
+
+Snapshotting of global state, factored out of PHPUnit into a stand-alone component.
+
+## Installation
+
+You can add this library as a local, per-project dependency to your project using [Composer](https://getcomposer.org/):
+
+```
+composer require sebastian/global-state
+```
+
+If you only need this library during development, for instance to run your project's test suite, then you should add it as a development-time dependency:
+
+```
+composer require --dev sebastian/global-state
+```
diff --git a/vendor/sebastian/global-state/composer.json b/vendor/sebastian/global-state/composer.json
new file mode 100644
index 0000000000000000000000000000000000000000..0fef446a65264ccb9a7a80de8cdd95abb4200bab
--- /dev/null
+++ b/vendor/sebastian/global-state/composer.json
@@ -0,0 +1,51 @@
+{
+    "name": "sebastian/global-state",
+    "description": "Snapshotting of global state",
+    "keywords": ["global state"],
+    "homepage": "http://www.github.com/sebastianbergmann/global-state",
+    "license": "BSD-3-Clause",
+    "authors": [
+        {
+            "name": "Sebastian Bergmann",
+            "email": "sebastian@phpunit.de"
+        }
+    ],
+    "prefer-stable": true,
+    "config": {
+        "platform": {
+            "php": "7.3.0"
+        },
+        "optimize-autoloader": true,
+        "sort-packages": true
+    },
+    "require": {
+        "php": ">=7.3",
+        "sebastian/object-reflector": "^2.0",
+        "sebastian/recursion-context": "^4.0"
+    },
+    "require-dev": {
+        "ext-dom": "*",
+        "phpunit/phpunit": "^9.3"
+    },
+    "suggest": {
+        "ext-uopz": "*"
+    },
+    "autoload": {
+        "classmap": [
+            "src/"
+        ]
+    },
+    "autoload-dev": {
+        "classmap": [
+            "tests/_fixture/"
+        ],
+        "files": [
+            "tests/_fixture/SnapshotFunctions.php"
+        ]
+    },
+    "extra": {
+        "branch-alias": {
+            "dev-master": "5.0-dev"
+        }
+    }
+}
diff --git a/vendor/sebastian/global-state/src/CodeExporter.php b/vendor/sebastian/global-state/src/CodeExporter.php
new file mode 100644
index 0000000000000000000000000000000000000000..8e1f23f0510fa67bfcdf3535759c7af188e645a5
--- /dev/null
+++ b/vendor/sebastian/global-state/src/CodeExporter.php
@@ -0,0 +1,98 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of sebastian/global-state.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\GlobalState;
+
+use const PHP_EOL;
+use function is_array;
+use function is_scalar;
+use function serialize;
+use function sprintf;
+use function var_export;
+
+/**
+ * Exports parts of a Snapshot as PHP code.
+ */
+final class CodeExporter
+{
+    public function constants(Snapshot $snapshot): string
+    {
+        $result = '';
+
+        foreach ($snapshot->constants() as $name => $value) {
+            $result .= sprintf(
+                'if (!defined(\'%s\')) define(\'%s\', %s);' . "\n",
+                $name,
+                $name,
+                $this->exportVariable($value)
+            );
+        }
+
+        return $result;
+    }
+
+    public function globalVariables(Snapshot $snapshot): string
+    {
+        $result = '$GLOBALS = [];' . PHP_EOL;
+
+        foreach ($snapshot->globalVariables() as $name => $value) {
+            $result .= sprintf(
+                '$GLOBALS[%s] = %s;' . PHP_EOL,
+                $this->exportVariable($name),
+                $this->exportVariable($value)
+            );
+        }
+
+        return $result;
+    }
+
+    public function iniSettings(Snapshot $snapshot): string
+    {
+        $result = '';
+
+        foreach ($snapshot->iniSettings() as $key => $value) {
+            $result .= sprintf(
+                '@ini_set(%s, %s);' . "\n",
+                $this->exportVariable($key),
+                $this->exportVariable($value)
+            );
+        }
+
+        return $result;
+    }
+
+    private function exportVariable($variable): string
+    {
+        if (is_scalar($variable) || null === $variable ||
+            (is_array($variable) && $this->arrayOnlyContainsScalars($variable))) {
+            return var_export($variable, true);
+        }
+
+        return 'unserialize(' . var_export(serialize($variable), true) . ')';
+    }
+
+    private function arrayOnlyContainsScalars(array $array): bool
+    {
+        $result = true;
+
+        foreach ($array as $element) {
+            if (is_array($element)) {
+                $result = $this->arrayOnlyContainsScalars($element);
+            } elseif (!is_scalar($element) && null !== $element) {
+                $result = false;
+            }
+
+            if ($result === false) {
+                break;
+            }
+        }
+
+        return $result;
+    }
+}
diff --git a/vendor/sebastian/global-state/src/ExcludeList.php b/vendor/sebastian/global-state/src/ExcludeList.php
new file mode 100644
index 0000000000000000000000000000000000000000..424385d2b403ee7f5dc9fcec30cdaaf927d2cde2
--- /dev/null
+++ b/vendor/sebastian/global-state/src/ExcludeList.php
@@ -0,0 +1,119 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of sebastian/global-state.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\GlobalState;
+
+use function in_array;
+use function strpos;
+use ReflectionClass;
+
+final class ExcludeList
+{
+    /**
+     * @var array
+     */
+    private $globalVariables = [];
+
+    /**
+     * @var string[]
+     */
+    private $classes = [];
+
+    /**
+     * @var string[]
+     */
+    private $classNamePrefixes = [];
+
+    /**
+     * @var string[]
+     */
+    private $parentClasses = [];
+
+    /**
+     * @var string[]
+     */
+    private $interfaces = [];
+
+    /**
+     * @var array
+     */
+    private $staticAttributes = [];
+
+    public function addGlobalVariable(string $variableName): void
+    {
+        $this->globalVariables[$variableName] = true;
+    }
+
+    public function addClass(string $className): void
+    {
+        $this->classes[] = $className;
+    }
+
+    public function addSubclassesOf(string $className): void
+    {
+        $this->parentClasses[] = $className;
+    }
+
+    public function addImplementorsOf(string $interfaceName): void
+    {
+        $this->interfaces[] = $interfaceName;
+    }
+
+    public function addClassNamePrefix(string $classNamePrefix): void
+    {
+        $this->classNamePrefixes[] = $classNamePrefix;
+    }
+
+    public function addStaticAttribute(string $className, string $attributeName): void
+    {
+        if (!isset($this->staticAttributes[$className])) {
+            $this->staticAttributes[$className] = [];
+        }
+
+        $this->staticAttributes[$className][$attributeName] = true;
+    }
+
+    public function isGlobalVariableExcluded(string $variableName): bool
+    {
+        return isset($this->globalVariables[$variableName]);
+    }
+
+    public function isStaticAttributeExcluded(string $className, string $attributeName): bool
+    {
+        if (in_array($className, $this->classes)) {
+            return true;
+        }
+
+        foreach ($this->classNamePrefixes as $prefix) {
+            if (strpos($className, $prefix) === 0) {
+                return true;
+            }
+        }
+
+        $class = new ReflectionClass($className);
+
+        foreach ($this->parentClasses as $type) {
+            if ($class->isSubclassOf($type)) {
+                return true;
+            }
+        }
+
+        foreach ($this->interfaces as $type) {
+            if ($class->implementsInterface($type)) {
+                return true;
+            }
+        }
+
+        if (isset($this->staticAttributes[$className][$attributeName])) {
+            return true;
+        }
+
+        return false;
+    }
+}
diff --git a/vendor/sebastian/global-state/src/Restorer.php b/vendor/sebastian/global-state/src/Restorer.php
new file mode 100644
index 0000000000000000000000000000000000000000..99cc4a69e603a73cd6221b2b235ae16292e44029
--- /dev/null
+++ b/vendor/sebastian/global-state/src/Restorer.php
@@ -0,0 +1,143 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of sebastian/global-state.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\GlobalState;
+
+use function array_diff;
+use function array_key_exists;
+use function array_keys;
+use function array_merge;
+use function function_exists;
+use function get_defined_functions;
+use function in_array;
+use function is_array;
+use ReflectionClass;
+use ReflectionProperty;
+
+/**
+ * Restorer of snapshots of global state.
+ */
+class Restorer
+{
+    /**
+     * Deletes function definitions that are not defined in a snapshot.
+     *
+     * @throws RuntimeException when the uopz_delete() function is not available
+     *
+     * @see https://github.com/krakjoe/uopz
+     */
+    public function restoreFunctions(Snapshot $snapshot): void
+    {
+        if (!function_exists('uopz_delete')) {
+            throw new RuntimeException('The uopz_delete() function is required for this operation');
+        }
+
+        $functions = get_defined_functions();
+
+        foreach (array_diff($functions['user'], $snapshot->functions()) as $function) {
+            uopz_delete($function);
+        }
+    }
+
+    /**
+     * Restores all global and super-global variables from a snapshot.
+     */
+    public function restoreGlobalVariables(Snapshot $snapshot): void
+    {
+        $superGlobalArrays = $snapshot->superGlobalArrays();
+
+        foreach ($superGlobalArrays as $superGlobalArray) {
+            $this->restoreSuperGlobalArray($snapshot, $superGlobalArray);
+        }
+
+        $globalVariables = $snapshot->globalVariables();
+
+        foreach (array_keys($GLOBALS) as $key) {
+            if ($key !== 'GLOBALS' &&
+                !in_array($key, $superGlobalArrays) &&
+                !$snapshot->excludeList()->isGlobalVariableExcluded($key)) {
+                if (array_key_exists($key, $globalVariables)) {
+                    $GLOBALS[$key] = $globalVariables[$key];
+                } else {
+                    unset($GLOBALS[$key]);
+                }
+            }
+        }
+    }
+
+    /**
+     * Restores all static attributes in user-defined classes from this snapshot.
+     */
+    public function restoreStaticAttributes(Snapshot $snapshot): void
+    {
+        $current    = new Snapshot($snapshot->excludeList(), false, false, false, false, true, false, false, false, false);
+        $newClasses = array_diff($current->classes(), $snapshot->classes());
+
+        unset($current);
+
+        foreach ($snapshot->staticAttributes() as $className => $staticAttributes) {
+            foreach ($staticAttributes as $name => $value) {
+                $reflector = new ReflectionProperty($className, $name);
+                $reflector->setAccessible(true);
+                $reflector->setValue($value);
+            }
+        }
+
+        foreach ($newClasses as $className) {
+            $class    = new ReflectionClass($className);
+            $defaults = $class->getDefaultProperties();
+
+            foreach ($class->getProperties() as $attribute) {
+                if (!$attribute->isStatic()) {
+                    continue;
+                }
+
+                $name = $attribute->getName();
+
+                if ($snapshot->excludeList()->isStaticAttributeExcluded($className, $name)) {
+                    continue;
+                }
+
+                if (!isset($defaults[$name])) {
+                    continue;
+                }
+
+                $attribute->setAccessible(true);
+                $attribute->setValue($defaults[$name]);
+            }
+        }
+    }
+
+    /**
+     * Restores a super-global variable array from this snapshot.
+     */
+    private function restoreSuperGlobalArray(Snapshot $snapshot, string $superGlobalArray): void
+    {
+        $superGlobalVariables = $snapshot->superGlobalVariables();
+
+        if (isset($GLOBALS[$superGlobalArray]) &&
+            is_array($GLOBALS[$superGlobalArray]) &&
+            isset($superGlobalVariables[$superGlobalArray])) {
+            $keys = array_keys(
+                array_merge(
+                    $GLOBALS[$superGlobalArray],
+                    $superGlobalVariables[$superGlobalArray]
+                )
+            );
+
+            foreach ($keys as $key) {
+                if (isset($superGlobalVariables[$superGlobalArray][$key])) {
+                    $GLOBALS[$superGlobalArray][$key] = $superGlobalVariables[$superGlobalArray][$key];
+                } else {
+                    unset($GLOBALS[$superGlobalArray][$key]);
+                }
+            }
+        }
+    }
+}
diff --git a/vendor/sebastian/global-state/src/Snapshot.php b/vendor/sebastian/global-state/src/Snapshot.php
new file mode 100644
index 0000000000000000000000000000000000000000..e7bdf2469176c2463e1e161a647c8ca1f2711361
--- /dev/null
+++ b/vendor/sebastian/global-state/src/Snapshot.php
@@ -0,0 +1,435 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of sebastian/global-state.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\GlobalState;
+
+use function array_keys;
+use function array_merge;
+use function array_reverse;
+use function func_get_args;
+use function get_declared_classes;
+use function get_declared_interfaces;
+use function get_declared_traits;
+use function get_defined_constants;
+use function get_defined_functions;
+use function get_included_files;
+use function in_array;
+use function ini_get_all;
+use function is_array;
+use function is_object;
+use function is_resource;
+use function is_scalar;
+use function serialize;
+use function unserialize;
+use ReflectionClass;
+use SebastianBergmann\ObjectReflector\ObjectReflector;
+use SebastianBergmann\RecursionContext\Context;
+use Throwable;
+
+/**
+ * A snapshot of global state.
+ */
+class Snapshot
+{
+    /**
+     * @var ExcludeList
+     */
+    private $excludeList;
+
+    /**
+     * @var array
+     */
+    private $globalVariables = [];
+
+    /**
+     * @var array
+     */
+    private $superGlobalArrays = [];
+
+    /**
+     * @var array
+     */
+    private $superGlobalVariables = [];
+
+    /**
+     * @var array
+     */
+    private $staticAttributes = [];
+
+    /**
+     * @var array
+     */
+    private $iniSettings = [];
+
+    /**
+     * @var array
+     */
+    private $includedFiles = [];
+
+    /**
+     * @var array
+     */
+    private $constants = [];
+
+    /**
+     * @var array
+     */
+    private $functions = [];
+
+    /**
+     * @var array
+     */
+    private $interfaces = [];
+
+    /**
+     * @var array
+     */
+    private $classes = [];
+
+    /**
+     * @var array
+     */
+    private $traits = [];
+
+    /**
+     * Creates a snapshot of the current global state.
+     */
+    public function __construct(ExcludeList $excludeList = null, bool $includeGlobalVariables = true, bool $includeStaticAttributes = true, bool $includeConstants = true, bool $includeFunctions = true, bool $includeClasses = true, bool $includeInterfaces = true, bool $includeTraits = true, bool $includeIniSettings = true, bool $includeIncludedFiles = true)
+    {
+        $this->excludeList = $excludeList ?: new ExcludeList;
+
+        if ($includeConstants) {
+            $this->snapshotConstants();
+        }
+
+        if ($includeFunctions) {
+            $this->snapshotFunctions();
+        }
+
+        if ($includeClasses || $includeStaticAttributes) {
+            $this->snapshotClasses();
+        }
+
+        if ($includeInterfaces) {
+            $this->snapshotInterfaces();
+        }
+
+        if ($includeGlobalVariables) {
+            $this->setupSuperGlobalArrays();
+            $this->snapshotGlobals();
+        }
+
+        if ($includeStaticAttributes) {
+            $this->snapshotStaticAttributes();
+        }
+
+        if ($includeIniSettings) {
+            $this->iniSettings = ini_get_all(null, false);
+        }
+
+        if ($includeIncludedFiles) {
+            $this->includedFiles = get_included_files();
+        }
+
+        $this->traits = get_declared_traits();
+    }
+
+    public function excludeList(): ExcludeList
+    {
+        return $this->excludeList;
+    }
+
+    public function globalVariables(): array
+    {
+        return $this->globalVariables;
+    }
+
+    public function superGlobalVariables(): array
+    {
+        return $this->superGlobalVariables;
+    }
+
+    public function superGlobalArrays(): array
+    {
+        return $this->superGlobalArrays;
+    }
+
+    public function staticAttributes(): array
+    {
+        return $this->staticAttributes;
+    }
+
+    public function iniSettings(): array
+    {
+        return $this->iniSettings;
+    }
+
+    public function includedFiles(): array
+    {
+        return $this->includedFiles;
+    }
+
+    public function constants(): array
+    {
+        return $this->constants;
+    }
+
+    public function functions(): array
+    {
+        return $this->functions;
+    }
+
+    public function interfaces(): array
+    {
+        return $this->interfaces;
+    }
+
+    public function classes(): array
+    {
+        return $this->classes;
+    }
+
+    public function traits(): array
+    {
+        return $this->traits;
+    }
+
+    /**
+     * Creates a snapshot user-defined constants.
+     */
+    private function snapshotConstants(): void
+    {
+        $constants = get_defined_constants(true);
+
+        if (isset($constants['user'])) {
+            $this->constants = $constants['user'];
+        }
+    }
+
+    /**
+     * Creates a snapshot user-defined functions.
+     */
+    private function snapshotFunctions(): void
+    {
+        $functions = get_defined_functions();
+
+        $this->functions = $functions['user'];
+    }
+
+    /**
+     * Creates a snapshot user-defined classes.
+     */
+    private function snapshotClasses(): void
+    {
+        foreach (array_reverse(get_declared_classes()) as $className) {
+            $class = new ReflectionClass($className);
+
+            if (!$class->isUserDefined()) {
+                break;
+            }
+
+            $this->classes[] = $className;
+        }
+
+        $this->classes = array_reverse($this->classes);
+    }
+
+    /**
+     * Creates a snapshot user-defined interfaces.
+     */
+    private function snapshotInterfaces(): void
+    {
+        foreach (array_reverse(get_declared_interfaces()) as $interfaceName) {
+            $class = new ReflectionClass($interfaceName);
+
+            if (!$class->isUserDefined()) {
+                break;
+            }
+
+            $this->interfaces[] = $interfaceName;
+        }
+
+        $this->interfaces = array_reverse($this->interfaces);
+    }
+
+    /**
+     * Creates a snapshot of all global and super-global variables.
+     */
+    private function snapshotGlobals(): void
+    {
+        $superGlobalArrays = $this->superGlobalArrays();
+
+        foreach ($superGlobalArrays as $superGlobalArray) {
+            $this->snapshotSuperGlobalArray($superGlobalArray);
+        }
+
+        foreach (array_keys($GLOBALS) as $key) {
+            if ($key !== 'GLOBALS' &&
+                !in_array($key, $superGlobalArrays) &&
+                $this->canBeSerialized($GLOBALS[$key]) &&
+                !$this->excludeList->isGlobalVariableExcluded($key)) {
+                /* @noinspection UnserializeExploitsInspection */
+                $this->globalVariables[$key] = unserialize(serialize($GLOBALS[$key]));
+            }
+        }
+    }
+
+    /**
+     * Creates a snapshot a super-global variable array.
+     */
+    private function snapshotSuperGlobalArray(string $superGlobalArray): void
+    {
+        $this->superGlobalVariables[$superGlobalArray] = [];
+
+        if (isset($GLOBALS[$superGlobalArray]) && is_array($GLOBALS[$superGlobalArray])) {
+            foreach ($GLOBALS[$superGlobalArray] as $key => $value) {
+                /* @noinspection UnserializeExploitsInspection */
+                $this->superGlobalVariables[$superGlobalArray][$key] = unserialize(serialize($value));
+            }
+        }
+    }
+
+    /**
+     * Creates a snapshot of all static attributes in user-defined classes.
+     */
+    private function snapshotStaticAttributes(): void
+    {
+        foreach ($this->classes as $className) {
+            $class    = new ReflectionClass($className);
+            $snapshot = [];
+
+            foreach ($class->getProperties() as $attribute) {
+                if ($attribute->isStatic()) {
+                    $name = $attribute->getName();
+
+                    if ($this->excludeList->isStaticAttributeExcluded($className, $name)) {
+                        continue;
+                    }
+
+                    $attribute->setAccessible(true);
+                    $value = $attribute->getValue();
+
+                    if ($this->canBeSerialized($value)) {
+                        /* @noinspection UnserializeExploitsInspection */
+                        $snapshot[$name] = unserialize(serialize($value));
+                    }
+                }
+            }
+
+            if (!empty($snapshot)) {
+                $this->staticAttributes[$className] = $snapshot;
+            }
+        }
+    }
+
+    /**
+     * Returns a list of all super-global variable arrays.
+     */
+    private function setupSuperGlobalArrays(): void
+    {
+        $this->superGlobalArrays = [
+            '_ENV',
+            '_POST',
+            '_GET',
+            '_COOKIE',
+            '_SERVER',
+            '_FILES',
+            '_REQUEST',
+        ];
+    }
+
+    private function canBeSerialized($variable): bool
+    {
+        if (is_scalar($variable) || $variable === null) {
+            return true;
+        }
+
+        if (is_resource($variable)) {
+            return false;
+        }
+
+        foreach ($this->enumerateObjectsAndResources($variable) as $value) {
+            if (is_resource($value)) {
+                return false;
+            }
+
+            if (is_object($value)) {
+                $class = new ReflectionClass($value);
+
+                if ($class->isAnonymous()) {
+                    return false;
+                }
+
+                try {
+                    @serialize($value);
+                } catch (Throwable $t) {
+                    return false;
+                }
+            }
+        }
+
+        return true;
+    }
+
+    private function enumerateObjectsAndResources($variable): array
+    {
+        if (isset(func_get_args()[1])) {
+            $processed = func_get_args()[1];
+        } else {
+            $processed = new Context;
+        }
+
+        $result = [];
+
+        if ($processed->contains($variable)) {
+            return $result;
+        }
+
+        $array = $variable;
+        $processed->add($variable);
+
+        if (is_array($variable)) {
+            foreach ($array as $element) {
+                if (!is_array($element) && !is_object($element) && !is_resource($element)) {
+                    continue;
+                }
+
+                if (!is_resource($element)) {
+                    /** @noinspection SlowArrayOperationsInLoopInspection */
+                    $result = array_merge(
+                        $result,
+                        $this->enumerateObjectsAndResources($element, $processed)
+                    );
+                } else {
+                    $result[] = $element;
+                }
+            }
+        } else {
+            $result[] = $variable;
+
+            foreach ((new ObjectReflector)->getAttributes($variable) as $value) {
+                if (!is_array($value) && !is_object($value) && !is_resource($value)) {
+                    continue;
+                }
+
+                if (!is_resource($value)) {
+                    /** @noinspection SlowArrayOperationsInLoopInspection */
+                    $result = array_merge(
+                        $result,
+                        $this->enumerateObjectsAndResources($value, $processed)
+                    );
+                } else {
+                    $result[] = $value;
+                }
+            }
+        }
+
+        return $result;
+    }
+}
diff --git a/vendor/sebastian/global-state/src/exceptions/Exception.php b/vendor/sebastian/global-state/src/exceptions/Exception.php
new file mode 100644
index 0000000000000000000000000000000000000000..94432008e5d665afb7cf292fa420e487571b82e2
--- /dev/null
+++ b/vendor/sebastian/global-state/src/exceptions/Exception.php
@@ -0,0 +1,16 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of sebastian/global-state.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\GlobalState;
+
+use Throwable;
+
+interface Exception extends Throwable
+{
+}
diff --git a/vendor/sebastian/global-state/src/exceptions/RuntimeException.php b/vendor/sebastian/global-state/src/exceptions/RuntimeException.php
new file mode 100644
index 0000000000000000000000000000000000000000..79f02a114102708d779faab631865b64570a4c8b
--- /dev/null
+++ b/vendor/sebastian/global-state/src/exceptions/RuntimeException.php
@@ -0,0 +1,14 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of sebastian/global-state.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\GlobalState;
+
+final class RuntimeException extends \RuntimeException implements Exception
+{
+}
diff --git a/vendor/sebastian/lines-of-code/.psalm/baseline.xml b/vendor/sebastian/lines-of-code/.psalm/baseline.xml
new file mode 100644
index 0000000000000000000000000000000000000000..77e688e07efe46415e5eaee84fbc946c36b82bcb
--- /dev/null
+++ b/vendor/sebastian/lines-of-code/.psalm/baseline.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<files psalm-version="4.0.1@b1e2e30026936ef8d5bf6a354d1c3959b6231f44"/>
diff --git a/vendor/sebastian/lines-of-code/.psalm/config.xml b/vendor/sebastian/lines-of-code/.psalm/config.xml
new file mode 100644
index 0000000000000000000000000000000000000000..15abef0580abbfdf63baa1a91ead072ce3fed20a
--- /dev/null
+++ b/vendor/sebastian/lines-of-code/.psalm/config.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0"?>
+<psalm
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xmlns="https://getpsalm.org/schema/config"
+    xsi:schemaLocation="https://getpsalm.org/schema/config vendor/vimeo/psalm/config.xsd"
+    resolveFromConfigFile="false"
+    totallyTyped="true"
+    errorBaseline=".psalm/baseline.xml"
+>
+    <projectFiles>
+        <directory name="src" />
+        <ignoreFiles>
+            <directory name="vendor" />
+        </ignoreFiles>
+    </projectFiles>
+</psalm>
diff --git a/vendor/sebastian/lines-of-code/ChangeLog.md b/vendor/sebastian/lines-of-code/ChangeLog.md
new file mode 100644
index 0000000000000000000000000000000000000000..39bcaad49006f0cc52ccf270d37919de6efb1c9a
--- /dev/null
+++ b/vendor/sebastian/lines-of-code/ChangeLog.md
@@ -0,0 +1,34 @@
+# ChangeLog
+
+All notable changes are documented in this file using the [Keep a CHANGELOG](https://keepachangelog.com/) principles.
+
+## [1.0.3] - 2020-11-28
+
+### Fixed
+
+* Files that do not contain a newline were not handled correctly
+
+### Changed
+
+* A line of code is no longer considered to be a Logical Line of Code if it does not contain an `Expr` node
+
+## [1.0.2] - 2020-10-26
+
+### Fixed
+
+* `SebastianBergmann\LinesOfCode\Exception` now correctly extends `\Throwable`
+
+## [1.0.1] - 2020-09-28
+
+### Changed
+
+* Changed PHP version constraint in `composer.json` from `^7.3 || ^8.0` to `>=7.3`
+
+## [1.0.0] - 2020-07-22
+
+* Initial release
+
+[1.0.3]: https://github.com/sebastianbergmann/lines-of-code/compare/1.0.2...1.0.3
+[1.0.2]: https://github.com/sebastianbergmann/lines-of-code/compare/1.0.1...1.0.2
+[1.0.1]: https://github.com/sebastianbergmann/lines-of-code/compare/1.0.0...1.0.1
+[1.0.0]: https://github.com/sebastianbergmann/lines-of-code/compare/f959e71f00e591288acc024afe9cb966c6cf9bd6...1.0.0
diff --git a/vendor/sebastian/lines-of-code/LICENSE b/vendor/sebastian/lines-of-code/LICENSE
new file mode 100644
index 0000000000000000000000000000000000000000..d170181fa37efb41e3212b2cbe10578e4a167b80
--- /dev/null
+++ b/vendor/sebastian/lines-of-code/LICENSE
@@ -0,0 +1,33 @@
+sebastian/lines-of-code
+
+Copyright (c) 2020, Sebastian Bergmann <sebastian@phpunit.de>.
+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 Sebastian Bergmann nor the names of his
+   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/sebastian/lines-of-code/README.md b/vendor/sebastian/lines-of-code/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..9457ef5a7767827a9f0eb1e6abea2b556778efe8
--- /dev/null
+++ b/vendor/sebastian/lines-of-code/README.md
@@ -0,0 +1,22 @@
+# sebastian/lines-of-code
+
+Library for counting the lines of code in PHP source code.
+
+[![Latest Stable Version](https://img.shields.io/packagist/v/sebastian/lines-of-code.svg?style=flat-square)](https://packagist.org/packages/sebastian/lines-of-code)
+[![Minimum PHP Version](https://img.shields.io/badge/php-%3E%3D%207.3-8892BF.svg?style=flat-square)](https://php.net/)
+[![CI Status](https://github.com/sebastianbergmann/lines-of-code/workflows/CI/badge.svg?branch=master&event=push)](https://phpunit.de/build-status.html)
+[![Type Coverage](https://shepherd.dev/github/sebastianbergmann/lines-of-code/coverage.svg)](https://shepherd.dev/github/sebastianbergmann/lines-of-code)
+
+## Installation
+
+You can add this library as a local, per-project dependency to your project using [Composer](https://getcomposer.org/):
+
+```
+composer require sebastian/lines-of-code
+```
+
+If you only need this library during development, for instance to run your project's test suite, then you should add it as a development-time dependency:
+
+```
+composer require --dev sebastian/lines-of-code
+```
diff --git a/vendor/sebastian/lines-of-code/composer.json b/vendor/sebastian/lines-of-code/composer.json
new file mode 100644
index 0000000000000000000000000000000000000000..95bb9e3632486646c92d73e56a05885c3198aad6
--- /dev/null
+++ b/vendor/sebastian/lines-of-code/composer.json
@@ -0,0 +1,42 @@
+{
+    "name": "sebastian/lines-of-code",
+    "description": "Library for counting the lines of code in PHP source code",
+    "type": "library",
+    "homepage": "https://github.com/sebastianbergmann/lines-of-code",
+    "license": "BSD-3-Clause",
+    "authors": [
+        {
+            "name": "Sebastian Bergmann",
+            "email": "sebastian@phpunit.de",
+            "role": "lead"
+        }
+    ],
+    "support": {
+        "issues": "https://github.com/sebastianbergmann/lines-of-code/issues"
+    },
+    "prefer-stable": true,
+    "require": {
+        "php": ">=7.3",
+        "nikic/php-parser": "^4.6"
+    },
+    "require-dev": {
+        "phpunit/phpunit": "^9.3"
+    },
+    "config": {
+        "platform": {
+            "php": "7.3.0"
+        },
+        "optimize-autoloader": true,
+        "sort-packages": true
+    },
+    "autoload": {
+        "classmap": [
+            "src/"
+        ]
+    },
+    "extra": {
+        "branch-alias": {
+            "dev-master": "1.0-dev"
+        }
+    }
+}
diff --git a/vendor/sebastian/lines-of-code/src/Counter.php b/vendor/sebastian/lines-of-code/src/Counter.php
new file mode 100644
index 0000000000000000000000000000000000000000..cfe5e20a78468fdfe20b3923a52b463329f227fa
--- /dev/null
+++ b/vendor/sebastian/lines-of-code/src/Counter.php
@@ -0,0 +1,91 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of sebastian/lines-of-code.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\LinesOfCode;
+
+use function substr_count;
+use PhpParser\Error;
+use PhpParser\Lexer;
+use PhpParser\Node;
+use PhpParser\NodeTraverser;
+use PhpParser\Parser;
+use PhpParser\ParserFactory;
+
+final class Counter
+{
+    /**
+     * @throws RuntimeException
+     */
+    public function countInSourceFile(string $sourceFile): LinesOfCode
+    {
+        return $this->countInSourceString(file_get_contents($sourceFile));
+    }
+
+    /**
+     * @throws RuntimeException
+     */
+    public function countInSourceString(string $source): LinesOfCode
+    {
+        $linesOfCode = substr_count($source, "\n");
+
+        if ($linesOfCode === 0 && !empty($source)) {
+            $linesOfCode = 1;
+        }
+
+        try {
+            $nodes = $this->parser()->parse($source);
+
+            assert($nodes !== null);
+
+            return $this->countInAbstractSyntaxTree($linesOfCode, $nodes);
+
+            // @codeCoverageIgnoreStart
+        } catch (Error $error) {
+            throw new RuntimeException(
+                $error->getMessage(),
+                (int) $error->getCode(),
+                $error
+            );
+        }
+        // @codeCoverageIgnoreEnd
+    }
+
+    /**
+     * @param Node[] $nodes
+     *
+     * @throws RuntimeException
+     */
+    public function countInAbstractSyntaxTree(int $linesOfCode, array $nodes): LinesOfCode
+    {
+        $traverser = new NodeTraverser;
+        $visitor   = new LineCountingVisitor($linesOfCode);
+
+        $traverser->addVisitor($visitor);
+
+        try {
+            /* @noinspection UnusedFunctionResultInspection */
+            $traverser->traverse($nodes);
+            // @codeCoverageIgnoreStart
+        } catch (Error $error) {
+            throw new RuntimeException(
+                $error->getMessage(),
+                (int) $error->getCode(),
+                $error
+            );
+        }
+        // @codeCoverageIgnoreEnd
+
+        return $visitor->result();
+    }
+
+    private function parser(): Parser
+    {
+        return (new ParserFactory)->create(ParserFactory::PREFER_PHP7, new Lexer);
+    }
+}
diff --git a/vendor/sebastian/lines-of-code/src/Exception/Exception.php b/vendor/sebastian/lines-of-code/src/Exception/Exception.php
new file mode 100644
index 0000000000000000000000000000000000000000..11d543aa79e8c6a1aa503f6d017e1c3d3313b83c
--- /dev/null
+++ b/vendor/sebastian/lines-of-code/src/Exception/Exception.php
@@ -0,0 +1,16 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of sebastian/lines-of-code.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\LinesOfCode;
+
+use Throwable;
+
+interface Exception extends Throwable
+{
+}
diff --git a/vendor/sebastian/lines-of-code/src/Exception/IllogicalValuesException.php b/vendor/sebastian/lines-of-code/src/Exception/IllogicalValuesException.php
new file mode 100644
index 0000000000000000000000000000000000000000..46a5c1b1f6e1491a8abac102fda8596fb039a0ef
--- /dev/null
+++ b/vendor/sebastian/lines-of-code/src/Exception/IllogicalValuesException.php
@@ -0,0 +1,16 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of sebastian/lines-of-code.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\LinesOfCode;
+
+use LogicException;
+
+final class IllogicalValuesException extends LogicException implements Exception
+{
+}
diff --git a/vendor/sebastian/lines-of-code/src/Exception/NegativeValueException.php b/vendor/sebastian/lines-of-code/src/Exception/NegativeValueException.php
new file mode 100644
index 0000000000000000000000000000000000000000..40d27e1f0f05ef4221fcc9c84e76689eb717c249
--- /dev/null
+++ b/vendor/sebastian/lines-of-code/src/Exception/NegativeValueException.php
@@ -0,0 +1,16 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of sebastian/lines-of-code.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\LinesOfCode;
+
+use InvalidArgumentException;
+
+final class NegativeValueException extends InvalidArgumentException implements Exception
+{
+}
diff --git a/vendor/sebastian/lines-of-code/src/Exception/RuntimeException.php b/vendor/sebastian/lines-of-code/src/Exception/RuntimeException.php
new file mode 100644
index 0000000000000000000000000000000000000000..4e6d66d0d45dfe677ef10ce63c653ec43447bdfa
--- /dev/null
+++ b/vendor/sebastian/lines-of-code/src/Exception/RuntimeException.php
@@ -0,0 +1,14 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of sebastian/lines-of-code.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\LinesOfCode;
+
+final class RuntimeException extends \RuntimeException implements Exception
+{
+}
diff --git a/vendor/sebastian/lines-of-code/src/LineCountingVisitor.php b/vendor/sebastian/lines-of-code/src/LineCountingVisitor.php
new file mode 100644
index 0000000000000000000000000000000000000000..ff433b2fcd858771fcd520004c95bf1322602fc1
--- /dev/null
+++ b/vendor/sebastian/lines-of-code/src/LineCountingVisitor.php
@@ -0,0 +1,82 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of sebastian/lines-of-code.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\LinesOfCode;
+
+use function array_merge;
+use function array_unique;
+use function count;
+use PhpParser\Comment;
+use PhpParser\Node;
+use PhpParser\Node\Expr;
+use PhpParser\NodeVisitorAbstract;
+
+final class LineCountingVisitor extends NodeVisitorAbstract
+{
+    /**
+     * @var int
+     */
+    private $linesOfCode;
+
+    /**
+     * @var Comment[]
+     */
+    private $comments = [];
+
+    /**
+     * @var int[]
+     */
+    private $linesWithStatements = [];
+
+    public function __construct(int $linesOfCode)
+    {
+        $this->linesOfCode = $linesOfCode;
+    }
+
+    public function enterNode(Node $node): void
+    {
+        $this->comments = array_merge($this->comments, $node->getComments());
+
+        if (!$node instanceof Expr) {
+            return;
+        }
+
+        $this->linesWithStatements[] = $node->getStartLine();
+    }
+
+    public function result(): LinesOfCode
+    {
+        $commentLinesOfCode = 0;
+
+        foreach ($this->comments() as $comment) {
+            $commentLinesOfCode += ($comment->getEndLine() - $comment->getStartLine() + 1);
+        }
+
+        return new LinesOfCode(
+            $this->linesOfCode,
+            $commentLinesOfCode,
+            $this->linesOfCode - $commentLinesOfCode,
+            count(array_unique($this->linesWithStatements))
+        );
+    }
+
+    /**
+     * @return Comment[]
+     */
+    private function comments(): array
+    {
+        $comments = [];
+
+        foreach ($this->comments as $comment) {
+            $comments[$comment->getStartLine() . '_' . $comment->getStartTokenPos() . '_' . $comment->getEndLine() . '_' . $comment->getEndTokenPos()] = $comment;
+        }
+
+        return $comments;
+    }
+}
diff --git a/vendor/sebastian/lines-of-code/src/LinesOfCode.php b/vendor/sebastian/lines-of-code/src/LinesOfCode.php
new file mode 100644
index 0000000000000000000000000000000000000000..41829981a7316ac20086baa0e6e75a9dd5322f75
--- /dev/null
+++ b/vendor/sebastian/lines-of-code/src/LinesOfCode.php
@@ -0,0 +1,98 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of sebastian/lines-of-code.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\LinesOfCode;
+
+/**
+ * @psalm-immutable
+ */
+final class LinesOfCode
+{
+    /**
+     * @var int
+     */
+    private $linesOfCode;
+
+    /**
+     * @var int
+     */
+    private $commentLinesOfCode;
+
+    /**
+     * @var int
+     */
+    private $nonCommentLinesOfCode;
+
+    /**
+     * @var int
+     */
+    private $logicalLinesOfCode;
+
+    /**
+     * @throws IllogicalValuesException
+     * @throws NegativeValueException
+     */
+    public function __construct(int $linesOfCode, int $commentLinesOfCode, int $nonCommentLinesOfCode, int $logicalLinesOfCode)
+    {
+        if ($linesOfCode < 0) {
+            throw new NegativeValueException('$linesOfCode must not be negative');
+        }
+
+        if ($commentLinesOfCode < 0) {
+            throw new NegativeValueException('$commentLinesOfCode must not be negative');
+        }
+
+        if ($nonCommentLinesOfCode < 0) {
+            throw new NegativeValueException('$nonCommentLinesOfCode must not be negative');
+        }
+
+        if ($logicalLinesOfCode < 0) {
+            throw new NegativeValueException('$logicalLinesOfCode must not be negative');
+        }
+
+        if ($linesOfCode - $commentLinesOfCode !== $nonCommentLinesOfCode) {
+            throw new IllogicalValuesException('$linesOfCode !== $commentLinesOfCode + $nonCommentLinesOfCode');
+        }
+
+        $this->linesOfCode           = $linesOfCode;
+        $this->commentLinesOfCode    = $commentLinesOfCode;
+        $this->nonCommentLinesOfCode = $nonCommentLinesOfCode;
+        $this->logicalLinesOfCode    = $logicalLinesOfCode;
+    }
+
+    public function linesOfCode(): int
+    {
+        return $this->linesOfCode;
+    }
+
+    public function commentLinesOfCode(): int
+    {
+        return $this->commentLinesOfCode;
+    }
+
+    public function nonCommentLinesOfCode(): int
+    {
+        return $this->nonCommentLinesOfCode;
+    }
+
+    public function logicalLinesOfCode(): int
+    {
+        return $this->logicalLinesOfCode;
+    }
+
+    public function plus(self $other): self
+    {
+        return new self(
+            $this->linesOfCode() + $other->linesOfCode(),
+            $this->commentLinesOfCode() + $other->commentLinesOfCode(),
+            $this->nonCommentLinesOfCode() + $other->nonCommentLinesOfCode(),
+            $this->logicalLinesOfCode() + $other->logicalLinesOfCode(),
+        );
+    }
+}
diff --git a/vendor/sebastian/object-enumerator/.psalm/baseline.xml b/vendor/sebastian/object-enumerator/.psalm/baseline.xml
new file mode 100644
index 0000000000000000000000000000000000000000..180b3f803fcd07e78ca207b6065a871f0b523efe
--- /dev/null
+++ b/vendor/sebastian/object-enumerator/.psalm/baseline.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<files psalm-version="4.0.1@b1e2e30026936ef8d5bf6a354d1c3959b6231f44">
+  <file src="src/Enumerator.php">
+    <DocblockTypeContradiction occurrences="2">
+      <code>!is_array($variable) &amp;&amp; !is_object($variable)</code>
+      <code>is_object($variable)</code>
+    </DocblockTypeContradiction>
+  </file>
+</files>
diff --git a/vendor/sebastian/object-enumerator/.psalm/config.xml b/vendor/sebastian/object-enumerator/.psalm/config.xml
new file mode 100644
index 0000000000000000000000000000000000000000..2a4b16f22703e24e4e45137a9fe06d144561c492
--- /dev/null
+++ b/vendor/sebastian/object-enumerator/.psalm/config.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0"?>
+<psalm
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xmlns="https://getpsalm.org/schema/config"
+    xsi:schemaLocation="https://getpsalm.org/schema/config vendor/vimeo/psalm/config.xsd"
+    resolveFromConfigFile="false"
+    totallyTyped="false"
+    errorBaseline=".psalm/baseline.xml"
+>
+    <projectFiles>
+        <directory name="src" />
+        <ignoreFiles>
+            <directory name="vendor" />
+        </ignoreFiles>
+    </projectFiles>
+</psalm>
diff --git a/vendor/sebastian/object-enumerator/ChangeLog.md b/vendor/sebastian/object-enumerator/ChangeLog.md
new file mode 100644
index 0000000000000000000000000000000000000000..886554189a823966db61a31339d36c6fb6ef652f
--- /dev/null
+++ b/vendor/sebastian/object-enumerator/ChangeLog.md
@@ -0,0 +1,88 @@
+# Change Log
+
+All notable changes to `sebastianbergmann/object-enumerator` are documented in this file using the [Keep a CHANGELOG](http://keepachangelog.com/) principles.
+
+## [4.0.4] - 2020-10-26
+
+### Fixed
+
+* `SebastianBergmann\ObjectEnumerator\Exception` now correctly extends `\Throwable`
+
+## [4.0.3] - 2020-09-28
+
+### Changed
+
+* Changed PHP version constraint in `composer.json` from `^7.3 || ^8.0` to `>=7.3`
+
+## [4.0.2] - 2020-06-26
+
+### Added
+
+* This component is now supported on PHP 8
+
+## [4.0.1] - 2020-06-15
+
+### Changed
+
+* Tests etc. are now ignored for archive exports
+
+## [4.0.0] - 2020-02-07
+
+### Removed
+
+* This component is no longer supported on PHP 7.0, PHP 7.1, and PHP 7.2
+
+## [3.0.3] - 2017-08-03
+
+### Changed
+
+* Bumped required version of `sebastian/object-reflector`
+
+## [3.0.2] - 2017-03-12
+
+### Changed
+
+* `sebastian/object-reflector` is now a dependency
+
+## [3.0.1] - 2017-03-12
+
+### Fixed
+
+* Objects aggregated in inherited attributes are not enumerated
+
+## [3.0.0] - 2017-03-03
+
+### Removed
+
+* This component is no longer supported on PHP 5.6
+
+## [2.0.1] - 2017-02-18
+
+### Fixed
+
+* Fixed [#2](https://github.com/sebastianbergmann/phpunit/pull/2): Exceptions in `ReflectionProperty::getValue()` are not handled
+
+## [2.0.0] - 2016-11-19
+
+### Changed
+
+* This component is now compatible with `sebastian/recursion-context: ~1.0.4`
+
+## 1.0.0 - 2016-02-04
+
+### Added
+
+* Initial release
+
+[4.0.4]: https://github.com/sebastianbergmann/object-enumerator/compare/4.0.3...4.0.4
+[4.0.3]: https://github.com/sebastianbergmann/object-enumerator/compare/4.0.2...4.0.3
+[4.0.2]: https://github.com/sebastianbergmann/object-enumerator/compare/4.0.1...4.0.2
+[4.0.1]: https://github.com/sebastianbergmann/object-enumerator/compare/4.0.0...4.0.1
+[4.0.0]: https://github.com/sebastianbergmann/object-enumerator/compare/3.0.3...4.0.0
+[3.0.3]: https://github.com/sebastianbergmann/object-enumerator/compare/3.0.2...3.0.3
+[3.0.2]: https://github.com/sebastianbergmann/object-enumerator/compare/3.0.1...3.0.2
+[3.0.1]: https://github.com/sebastianbergmann/object-enumerator/compare/3.0.0...3.0.1
+[3.0.0]: https://github.com/sebastianbergmann/object-enumerator/compare/2.0...3.0.0
+[2.0.1]: https://github.com/sebastianbergmann/object-enumerator/compare/2.0.0...2.0.1
+[2.0.0]: https://github.com/sebastianbergmann/object-enumerator/compare/1.0...2.0.0
+
diff --git a/vendor/sebastian/object-enumerator/LICENSE b/vendor/sebastian/object-enumerator/LICENSE
new file mode 100644
index 0000000000000000000000000000000000000000..1389ad3964ea53591b792794f597b30c02c88c9e
--- /dev/null
+++ b/vendor/sebastian/object-enumerator/LICENSE
@@ -0,0 +1,33 @@
+Object Enumerator
+
+Copyright (c) 2016-2020, Sebastian Bergmann <sebastian@phpunit.de>.
+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 Sebastian Bergmann nor the names of his
+   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/sebastian/object-enumerator/README.md b/vendor/sebastian/object-enumerator/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..afca0177b7f7090e07f9e30a0b03ecdba302466e
--- /dev/null
+++ b/vendor/sebastian/object-enumerator/README.md
@@ -0,0 +1,20 @@
+# sebastian/object-enumerator
+
+[![CI Status](https://github.com/sebastianbergmann/object-enumerator/workflows/CI/badge.svg)](https://github.com/sebastianbergmann/object-enumerator/actions)
+[![Type Coverage](https://shepherd.dev/github/sebastianbergmann/object-enumerator/coverage.svg)](https://shepherd.dev/github/sebastianbergmann/object-enumerator)
+
+Traverses array structures and object graphs to enumerate all referenced objects.
+
+## Installation
+
+You can add this library as a local, per-project dependency to your project using [Composer](https://getcomposer.org/):
+
+```
+composer require sebastian/object-enumerator
+```
+
+If you only need this library during development, for instance to run your project's test suite, then you should add it as a development-time dependency:
+
+```
+composer require --dev sebastian/object-enumerator
+```
diff --git a/vendor/sebastian/object-enumerator/composer.json b/vendor/sebastian/object-enumerator/composer.json
new file mode 100644
index 0000000000000000000000000000000000000000..d68a21330e2b314ad2cb852bb442b09f069e21bf
--- /dev/null
+++ b/vendor/sebastian/object-enumerator/composer.json
@@ -0,0 +1,43 @@
+{
+    "name": "sebastian/object-enumerator",
+    "description": "Traverses array structures and object graphs to enumerate all referenced objects",
+    "homepage": "https://github.com/sebastianbergmann/object-enumerator/",
+    "license": "BSD-3-Clause",
+    "authors": [
+        {
+            "name": "Sebastian Bergmann",
+            "email": "sebastian@phpunit.de"
+        }
+    ],
+    "prefer-stable": true,
+    "config": {
+        "platform": {
+            "php": "7.3.0"
+        },
+        "optimize-autoloader": true,
+        "sort-packages": true
+    },
+    "require": {
+        "php": ">=7.3",
+        "sebastian/object-reflector": "^2.0",
+        "sebastian/recursion-context": "^4.0"
+    },
+    "require-dev": {
+        "phpunit/phpunit": "^9.3"
+    },
+    "autoload": {
+        "classmap": [
+            "src/"
+        ]
+    },
+    "autoload-dev": {
+        "classmap": [
+            "tests/_fixture/"
+        ]
+    },
+    "extra": {
+        "branch-alias": {
+            "dev-master": "4.0-dev"
+        }
+    }
+}
diff --git a/vendor/sebastian/object-enumerator/phpunit.xml b/vendor/sebastian/object-enumerator/phpunit.xml
new file mode 100644
index 0000000000000000000000000000000000000000..7be976b13c41a05b04e2ff5428d5f5a7283a60f0
--- /dev/null
+++ b/vendor/sebastian/object-enumerator/phpunit.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/9.3/phpunit.xsd"
+         bootstrap="vendor/autoload.php"
+         executionOrder="depends,defects"
+         forceCoversAnnotation="true"
+         beStrictAboutCoversAnnotation="true"
+         beStrictAboutOutputDuringTests="true"
+         beStrictAboutTodoAnnotatedTests="true"
+         failOnRisky="true"
+         failOnWarning="true"
+         verbose="true">
+    <testsuites>
+        <testsuite name="default">
+            <directory suffix="Test.php">tests</directory>
+        </testsuite>
+    </testsuites>
+
+    <coverage processUncoveredFiles="true">
+        <include>
+            <directory suffix=".php">src</directory>
+        </include>
+    </coverage>
+</phpunit>
diff --git a/vendor/sebastian/object-enumerator/src/Enumerator.php b/vendor/sebastian/object-enumerator/src/Enumerator.php
new file mode 100644
index 0000000000000000000000000000000000000000..de75d17c59207cb4457cd377bd5618785988f1e0
--- /dev/null
+++ b/vendor/sebastian/object-enumerator/src/Enumerator.php
@@ -0,0 +1,88 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of sebastian/object-enumerator.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\ObjectEnumerator;
+
+use function array_merge;
+use function func_get_args;
+use function is_array;
+use function is_object;
+use SebastianBergmann\ObjectReflector\ObjectReflector;
+use SebastianBergmann\RecursionContext\Context;
+
+/**
+ * Traverses array structures and object graphs
+ * to enumerate all referenced objects.
+ */
+class Enumerator
+{
+    /**
+     * Returns an array of all objects referenced either
+     * directly or indirectly by a variable.
+     *
+     * @param array|object $variable
+     *
+     * @return object[]
+     */
+    public function enumerate($variable)
+    {
+        if (!is_array($variable) && !is_object($variable)) {
+            throw new InvalidArgumentException;
+        }
+
+        if (isset(func_get_args()[1])) {
+            if (!func_get_args()[1] instanceof Context) {
+                throw new InvalidArgumentException;
+            }
+
+            $processed = func_get_args()[1];
+        } else {
+            $processed = new Context;
+        }
+
+        $objects = [];
+
+        if ($processed->contains($variable)) {
+            return $objects;
+        }
+
+        $array = $variable;
+        $processed->add($variable);
+
+        if (is_array($variable)) {
+            foreach ($array as $element) {
+                if (!is_array($element) && !is_object($element)) {
+                    continue;
+                }
+
+                $objects = array_merge(
+                    $objects,
+                    $this->enumerate($element, $processed)
+                );
+            }
+        } else {
+            $objects[] = $variable;
+
+            $reflector = new ObjectReflector;
+
+            foreach ($reflector->getAttributes($variable) as $value) {
+                if (!is_array($value) && !is_object($value)) {
+                    continue;
+                }
+
+                $objects = array_merge(
+                    $objects,
+                    $this->enumerate($value, $processed)
+                );
+            }
+        }
+
+        return $objects;
+    }
+}
diff --git a/vendor/sebastian/object-enumerator/src/Exception.php b/vendor/sebastian/object-enumerator/src/Exception.php
new file mode 100644
index 0000000000000000000000000000000000000000..2f09d70aade2ff46fe3b383d633560f931140888
--- /dev/null
+++ b/vendor/sebastian/object-enumerator/src/Exception.php
@@ -0,0 +1,16 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of sebastian/object-enumerator.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\ObjectEnumerator;
+
+use Throwable;
+
+interface Exception extends Throwable
+{
+}
diff --git a/vendor/sebastian/object-enumerator/src/InvalidArgumentException.php b/vendor/sebastian/object-enumerator/src/InvalidArgumentException.php
new file mode 100644
index 0000000000000000000000000000000000000000..ce2037cdba81f4fb2336940c8219e149acb77d14
--- /dev/null
+++ b/vendor/sebastian/object-enumerator/src/InvalidArgumentException.php
@@ -0,0 +1,14 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of sebastian/object-enumerator.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\ObjectEnumerator;
+
+class InvalidArgumentException extends \InvalidArgumentException implements Exception
+{
+}
diff --git a/vendor/sebastian/object-reflector/.psalm/baseline.xml b/vendor/sebastian/object-reflector/.psalm/baseline.xml
new file mode 100644
index 0000000000000000000000000000000000000000..965c127579a6acde35c94a5299ff0080ccce4986
--- /dev/null
+++ b/vendor/sebastian/object-reflector/.psalm/baseline.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<files psalm-version="4.0.1@b1e2e30026936ef8d5bf6a354d1c3959b6231f44">
+  <file src="src/ObjectReflector.php">
+    <DocblockTypeContradiction occurrences="1">
+      <code>is_object($object)</code>
+    </DocblockTypeContradiction>
+  </file>
+</files>
diff --git a/vendor/sebastian/object-reflector/.psalm/config.xml b/vendor/sebastian/object-reflector/.psalm/config.xml
new file mode 100644
index 0000000000000000000000000000000000000000..2a4b16f22703e24e4e45137a9fe06d144561c492
--- /dev/null
+++ b/vendor/sebastian/object-reflector/.psalm/config.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0"?>
+<psalm
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xmlns="https://getpsalm.org/schema/config"
+    xsi:schemaLocation="https://getpsalm.org/schema/config vendor/vimeo/psalm/config.xsd"
+    resolveFromConfigFile="false"
+    totallyTyped="false"
+    errorBaseline=".psalm/baseline.xml"
+>
+    <projectFiles>
+        <directory name="src" />
+        <ignoreFiles>
+            <directory name="vendor" />
+        </ignoreFiles>
+    </projectFiles>
+</psalm>
diff --git a/vendor/sebastian/object-reflector/ChangeLog.md b/vendor/sebastian/object-reflector/ChangeLog.md
new file mode 100644
index 0000000000000000000000000000000000000000..7fa62e90f635672d40887379d8de00935c878a82
--- /dev/null
+++ b/vendor/sebastian/object-reflector/ChangeLog.md
@@ -0,0 +1,55 @@
+# Change Log
+
+All notable changes to `sebastianbergmann/object-reflector` are documented in this file using the [Keep a CHANGELOG](http://keepachangelog.com/) principles.
+
+## [2.0.4] - 2020-10-26
+
+### Fixed
+
+* `SebastianBergmann\ObjectReflector\Exception` now correctly extends `\Throwable`
+
+## [2.0.3] - 2020-09-28
+
+### Changed
+
+* Changed PHP version constraint in `composer.json` from `^7.3 || ^8.0` to `>=7.3`
+
+## [2.0.2] - 2020-06-26
+
+### Added
+
+* This component is now supported on PHP 8
+
+## [2.0.1] - 2020-06-15
+
+### Changed
+
+* Tests etc. are now ignored for archive exports
+
+## [2.0.0] - 2020-02-07
+
+### Removed
+
+* This component is no longer supported on PHP 7.0, PHP 7.1, and PHP 7.2
+
+## [1.1.1] - 2017-03-29
+
+* Fixed [#1](https://github.com/sebastianbergmann/object-reflector/issues/1): Attributes with non-string names are not handled correctly
+
+## [1.1.0] - 2017-03-16
+
+### Changed
+
+* Changed implementation of `ObjectReflector::getattributes()` to use `(array)` cast instead of `ReflectionObject`
+
+## 1.0.0 - 2017-03-12
+
+* Initial release
+
+[2.0.4]: https://github.com/sebastianbergmann/object-reflector/compare/2.0.3...2.0.4
+[2.0.3]: https://github.com/sebastianbergmann/object-reflector/compare/2.0.2...2.0.3
+[2.0.2]: https://github.com/sebastianbergmann/object-reflector/compare/2.0.1...2.0.2
+[2.0.1]: https://github.com/sebastianbergmann/object-reflector/compare/2.0.0...2.0.1
+[2.0.0]: https://github.com/sebastianbergmann/object-reflector/compare/1.1.1...2.0.0
+[1.1.1]: https://github.com/sebastianbergmann/object-reflector/compare/1.1.0...1.1.1
+[1.1.0]: https://github.com/sebastianbergmann/object-reflector/compare/1.0.0...1.1.0
diff --git a/vendor/sebastian/object-reflector/LICENSE b/vendor/sebastian/object-reflector/LICENSE
new file mode 100644
index 0000000000000000000000000000000000000000..a80c16192cc3edb121308c58784da7ff56e5540a
--- /dev/null
+++ b/vendor/sebastian/object-reflector/LICENSE
@@ -0,0 +1,33 @@
+Object Reflector
+
+Copyright (c) 2017-2020, Sebastian Bergmann <sebastian@phpunit.de>.
+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 Sebastian Bergmann nor the names of his
+   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/sebastian/object-reflector/README.md b/vendor/sebastian/object-reflector/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..b7d5ae95fd85ad4084857b86b48104c39a35885f
--- /dev/null
+++ b/vendor/sebastian/object-reflector/README.md
@@ -0,0 +1,20 @@
+# sebastian/object-reflector
+
+[![CI Status](https://github.com/sebastianbergmann/object-reflector/workflows/CI/badge.svg)](https://github.com/sebastianbergmann/object-reflector/actions)
+[![Type Coverage](https://shepherd.dev/github/sebastianbergmann/object-reflector/coverage.svg)](https://shepherd.dev/github/sebastianbergmann/object-reflector)
+
+Allows reflection of object attributes, including inherited and non-public ones.
+
+## Installation
+
+You can add this library as a local, per-project dependency to your project using [Composer](https://getcomposer.org/):
+
+```
+composer require sebastian/object-reflector
+```
+
+If you only need this library during development, for instance to run your project's test suite, then you should add it as a development-time dependency:
+
+```
+composer require --dev sebastian/object-reflector
+```
diff --git a/vendor/sebastian/object-reflector/composer.json b/vendor/sebastian/object-reflector/composer.json
new file mode 100644
index 0000000000000000000000000000000000000000..36a337885e05e5e76aad4fd86740e5e877137343
--- /dev/null
+++ b/vendor/sebastian/object-reflector/composer.json
@@ -0,0 +1,41 @@
+{
+    "name": "sebastian/object-reflector",
+    "description": "Allows reflection of object attributes, including inherited and non-public ones",
+    "homepage": "https://github.com/sebastianbergmann/object-reflector/",
+    "license": "BSD-3-Clause",
+    "authors": [
+        {
+            "name": "Sebastian Bergmann",
+            "email": "sebastian@phpunit.de"
+        }
+    ],
+    "prefer-stable": true,
+    "config": {
+        "platform": {
+            "php": "7.3.0"
+        },
+        "optimize-autoloader": true,
+        "sort-packages": true
+    },
+    "require": {
+        "php": ">=7.3"
+    },
+    "require-dev": {
+        "phpunit/phpunit": "^9.3"
+    },
+    "autoload": {
+        "classmap": [
+            "src/"
+        ]
+    },
+    "autoload-dev": {
+        "classmap": [
+            "tests/_fixture/"
+        ]
+    },
+    "extra": {
+        "branch-alias": {
+            "dev-master": "2.0-dev"
+        }
+    }
+}
diff --git a/vendor/sebastian/object-reflector/src/Exception.php b/vendor/sebastian/object-reflector/src/Exception.php
new file mode 100644
index 0000000000000000000000000000000000000000..36f8efecaf93503ebb338b4f82646cd3690850a6
--- /dev/null
+++ b/vendor/sebastian/object-reflector/src/Exception.php
@@ -0,0 +1,16 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of sebastian/object-reflector.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\ObjectReflector;
+
+use Throwable;
+
+interface Exception extends Throwable
+{
+}
diff --git a/vendor/sebastian/object-reflector/src/InvalidArgumentException.php b/vendor/sebastian/object-reflector/src/InvalidArgumentException.php
new file mode 100644
index 0000000000000000000000000000000000000000..34b4cca19e8b58c8efc92100fc42f9720b175cec
--- /dev/null
+++ b/vendor/sebastian/object-reflector/src/InvalidArgumentException.php
@@ -0,0 +1,14 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of sebastian/object-reflector.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\ObjectReflector;
+
+class InvalidArgumentException extends \InvalidArgumentException implements Exception
+{
+}
diff --git a/vendor/sebastian/object-reflector/src/ObjectReflector.php b/vendor/sebastian/object-reflector/src/ObjectReflector.php
new file mode 100644
index 0000000000000000000000000000000000000000..4abb5f55f5616b037952a4c303a96872ab8b0631
--- /dev/null
+++ b/vendor/sebastian/object-reflector/src/ObjectReflector.php
@@ -0,0 +1,51 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of sebastian/object-reflector.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\ObjectReflector;
+
+use function count;
+use function explode;
+use function get_class;
+use function is_object;
+
+class ObjectReflector
+{
+    /**
+     * @param object $object
+     *
+     * @throws InvalidArgumentException
+     */
+    public function getAttributes($object): array
+    {
+        if (!is_object($object)) {
+            throw new InvalidArgumentException;
+        }
+
+        $attributes = [];
+        $className  = get_class($object);
+
+        foreach ((array) $object as $name => $value) {
+            $name = explode("\0", (string) $name);
+
+            if (count($name) === 1) {
+                $name = $name[0];
+            } else {
+                if ($name[1] !== $className) {
+                    $name = $name[1] . '::' . $name[2];
+                } else {
+                    $name = $name[2];
+                }
+            }
+
+            $attributes[$name] = $value;
+        }
+
+        return $attributes;
+    }
+}
diff --git a/vendor/sebastian/recursion-context/.psalm/baseline.xml b/vendor/sebastian/recursion-context/.psalm/baseline.xml
new file mode 100644
index 0000000000000000000000000000000000000000..b946db1a54a5456ae24df1d46733fb950f7f2775
--- /dev/null
+++ b/vendor/sebastian/recursion-context/.psalm/baseline.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<files psalm-version="4.0.1@b1e2e30026936ef8d5bf6a354d1c3959b6231f44">
+  <file src="src/Context.php">
+    <RedundantConditionGivenDocblockType occurrences="1">
+      <code>is_array($array)</code>
+    </RedundantConditionGivenDocblockType>
+  </file>
+</files>
diff --git a/vendor/sebastian/recursion-context/.psalm/config.xml b/vendor/sebastian/recursion-context/.psalm/config.xml
new file mode 100644
index 0000000000000000000000000000000000000000..2a4b16f22703e24e4e45137a9fe06d144561c492
--- /dev/null
+++ b/vendor/sebastian/recursion-context/.psalm/config.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0"?>
+<psalm
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xmlns="https://getpsalm.org/schema/config"
+    xsi:schemaLocation="https://getpsalm.org/schema/config vendor/vimeo/psalm/config.xsd"
+    resolveFromConfigFile="false"
+    totallyTyped="false"
+    errorBaseline=".psalm/baseline.xml"
+>
+    <projectFiles>
+        <directory name="src" />
+        <ignoreFiles>
+            <directory name="vendor" />
+        </ignoreFiles>
+    </projectFiles>
+</psalm>
diff --git a/vendor/sebastian/recursion-context/ChangeLog.md b/vendor/sebastian/recursion-context/ChangeLog.md
new file mode 100644
index 0000000000000000000000000000000000000000..2fbacc2c3f14651cc46097fba46124e18c6e798e
--- /dev/null
+++ b/vendor/sebastian/recursion-context/ChangeLog.md
@@ -0,0 +1,33 @@
+# ChangeLog
+
+All notable changes are documented in this file using the [Keep a CHANGELOG](https://keepachangelog.com/) principles.
+
+## [4.0.4] - 2020-10-26
+
+### Fixed
+
+* `SebastianBergmann\RecursionContext\Exception` now correctly extends `\Throwable`
+
+## [4.0.3] - 2020-09-28
+
+### Changed
+
+* [#21](https://github.com/sebastianbergmann/recursion-context/pull/21): Add type annotations for in/out parameters
+* Changed PHP version constraint in `composer.json` from `^7.3 || ^8.0` to `>=7.3`
+
+## [4.0.2] - 2020-06-26
+
+### Added
+
+* This component is now supported on PHP 8
+
+## [4.0.1] - 2020-06-15
+
+### Changed
+
+* Tests etc. are now ignored for archive exports
+
+[4.0.4]: https://github.com/sebastianbergmann/recursion-context/compare/4.0.3...4.0.4
+[4.0.3]: https://github.com/sebastianbergmann/recursion-context/compare/4.0.2...4.0.3
+[4.0.2]: https://github.com/sebastianbergmann/recursion-context/compare/4.0.1...4.0.2
+[4.0.1]: https://github.com/sebastianbergmann/recursion-context/compare/4.0.0...4.0.1
diff --git a/vendor/sebastian/recursion-context/LICENSE b/vendor/sebastian/recursion-context/LICENSE
new file mode 100644
index 0000000000000000000000000000000000000000..0faffbbb2f9f5a6433744100a6d644c55af645bc
--- /dev/null
+++ b/vendor/sebastian/recursion-context/LICENSE
@@ -0,0 +1,33 @@
+Recursion Context
+
+Copyright (c) 2002-2020, Sebastian Bergmann <sebastian@phpunit.de>.
+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 Sebastian Bergmann nor the names of his
+   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/sebastian/recursion-context/README.md b/vendor/sebastian/recursion-context/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..8e4d2a084e6910c3b31809b7d681e2ef7ffaec68
--- /dev/null
+++ b/vendor/sebastian/recursion-context/README.md
@@ -0,0 +1,18 @@
+# sebastian/recursion-context
+
+[![CI Status](https://github.com/sebastianbergmann/recursion-context/workflows/CI/badge.svg)](https://github.com/sebastianbergmann/recursion-context/actions)
+[![Type Coverage](https://shepherd.dev/github/sebastianbergmann/recursion-context/coverage.svg)](https://shepherd.dev/github/sebastianbergmann/recursion-context)
+
+## Installation
+
+You can add this library as a local, per-project dependency to your project using [Composer](https://getcomposer.org/):
+
+```
+composer require sebastian/recursion-context
+```
+
+If you only need this library during development, for instance to run your project's test suite, then you should add it as a development-time dependency:
+
+```
+composer require --dev sebastian/recursion-context
+```
diff --git a/vendor/sebastian/recursion-context/composer.json b/vendor/sebastian/recursion-context/composer.json
new file mode 100644
index 0000000000000000000000000000000000000000..8a54082327018c69b7681667cc33d89fdb51fcd0
--- /dev/null
+++ b/vendor/sebastian/recursion-context/composer.json
@@ -0,0 +1,44 @@
+{
+    "name": "sebastian/recursion-context",
+    "description": "Provides functionality to recursively process PHP variables",
+    "homepage": "http://www.github.com/sebastianbergmann/recursion-context",
+    "license": "BSD-3-Clause",
+    "authors": [
+        {
+            "name": "Sebastian Bergmann",
+            "email": "sebastian@phpunit.de"
+        },
+        {
+            "name": "Jeff Welch",
+            "email": "whatthejeff@gmail.com"
+        },
+        {
+            "name": "Adam Harvey",
+            "email": "aharvey@php.net"
+        }
+    ],
+    "prefer-stable": true,
+    "config": {
+        "platform": {
+            "php": "7.3.0"
+        },
+        "optimize-autoloader": true,
+        "sort-packages": true
+    },
+    "require": {
+        "php": ">=7.3"
+    },
+    "require-dev": {
+        "phpunit/phpunit": "^9.3"
+    },
+    "autoload": {
+        "classmap": [
+            "src/"
+        ]
+    },
+    "extra": {
+        "branch-alias": {
+            "dev-master": "4.0-dev"
+        }
+    }
+}
diff --git a/vendor/sebastian/recursion-context/src/Context.php b/vendor/sebastian/recursion-context/src/Context.php
new file mode 100644
index 0000000000000000000000000000000000000000..87fe7b04f5decbb96253b33ade9bcf138e02a064
--- /dev/null
+++ b/vendor/sebastian/recursion-context/src/Context.php
@@ -0,0 +1,186 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of the Recursion Context package.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\RecursionContext;
+
+use const PHP_INT_MAX;
+use const PHP_INT_MIN;
+use function array_pop;
+use function array_slice;
+use function count;
+use function is_array;
+use function is_object;
+use function random_int;
+use function spl_object_hash;
+use SplObjectStorage;
+
+/**
+ * A context containing previously processed arrays and objects
+ * when recursively processing a value.
+ */
+final class Context
+{
+    /**
+     * @var array[]
+     */
+    private $arrays;
+
+    /**
+     * @var SplObjectStorage
+     */
+    private $objects;
+
+    /**
+     * Initialises the context.
+     */
+    public function __construct()
+    {
+        $this->arrays  = [];
+        $this->objects = new SplObjectStorage;
+    }
+
+    /**
+     * @codeCoverageIgnore
+     */
+    public function __destruct()
+    {
+        foreach ($this->arrays as &$array) {
+            if (is_array($array)) {
+                array_pop($array);
+                array_pop($array);
+            }
+        }
+    }
+
+    /**
+     * Adds a value to the context.
+     *
+     * @param array|object $value the value to add
+     *
+     * @throws InvalidArgumentException Thrown if $value is not an array or object
+     *
+     * @return bool|int|string the ID of the stored value, either as a string or integer
+     *
+     * @psalm-template T
+     * @psalm-param T $value
+     * @param-out T $value
+     */
+    public function add(&$value)
+    {
+        if (is_array($value)) {
+            return $this->addArray($value);
+        }
+
+        if (is_object($value)) {
+            return $this->addObject($value);
+        }
+
+        throw new InvalidArgumentException(
+            'Only arrays and objects are supported'
+        );
+    }
+
+    /**
+     * Checks if the given value exists within the context.
+     *
+     * @param array|object $value the value to check
+     *
+     * @throws InvalidArgumentException Thrown if $value is not an array or object
+     *
+     * @return false|int|string the string or integer ID of the stored value if it has already been seen, or false if the value is not stored
+     *
+     * @psalm-template T
+     * @psalm-param T $value
+     * @param-out T $value
+     */
+    public function contains(&$value)
+    {
+        if (is_array($value)) {
+            return $this->containsArray($value);
+        }
+
+        if (is_object($value)) {
+            return $this->containsObject($value);
+        }
+
+        throw new InvalidArgumentException(
+            'Only arrays and objects are supported'
+        );
+    }
+
+    /**
+     * @return bool|int
+     */
+    private function addArray(array &$array)
+    {
+        $key = $this->containsArray($array);
+
+        if ($key !== false) {
+            return $key;
+        }
+
+        $key            = count($this->arrays);
+        $this->arrays[] = &$array;
+
+        if (!isset($array[PHP_INT_MAX]) && !isset($array[PHP_INT_MAX - 1])) {
+            $array[] = $key;
+            $array[] = $this->objects;
+        } else { /* cover the improbable case too */
+            do {
+                $key = random_int(PHP_INT_MIN, PHP_INT_MAX);
+            } while (isset($array[$key]));
+
+            $array[$key] = $key;
+
+            do {
+                $key = random_int(PHP_INT_MIN, PHP_INT_MAX);
+            } while (isset($array[$key]));
+
+            $array[$key] = $this->objects;
+        }
+
+        return $key;
+    }
+
+    /**
+     * @param object $object
+     */
+    private function addObject($object): string
+    {
+        if (!$this->objects->contains($object)) {
+            $this->objects->attach($object);
+        }
+
+        return spl_object_hash($object);
+    }
+
+    /**
+     * @return false|int
+     */
+    private function containsArray(array &$array)
+    {
+        $end = array_slice($array, -2);
+
+        return isset($end[1]) && $end[1] === $this->objects ? $end[0] : false;
+    }
+
+    /**
+     * @param object $value
+     *
+     * @return false|string
+     */
+    private function containsObject($value)
+    {
+        if ($this->objects->contains($value)) {
+            return spl_object_hash($value);
+        }
+
+        return false;
+    }
+}
diff --git a/vendor/sebastian/recursion-context/src/Exception.php b/vendor/sebastian/recursion-context/src/Exception.php
new file mode 100644
index 0000000000000000000000000000000000000000..e3a9c017dc5cf160cbe6db8c3030a05ccfa6e20d
--- /dev/null
+++ b/vendor/sebastian/recursion-context/src/Exception.php
@@ -0,0 +1,16 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of the Recursion Context package.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\RecursionContext;
+
+use Throwable;
+
+interface Exception extends Throwable
+{
+}
diff --git a/vendor/sebastian/recursion-context/src/InvalidArgumentException.php b/vendor/sebastian/recursion-context/src/InvalidArgumentException.php
new file mode 100644
index 0000000000000000000000000000000000000000..627c8bdf43c7667d57482dd02ce789b7859ca841
--- /dev/null
+++ b/vendor/sebastian/recursion-context/src/InvalidArgumentException.php
@@ -0,0 +1,14 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of the Recursion Context package.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\RecursionContext;
+
+final class InvalidArgumentException extends \InvalidArgumentException implements Exception
+{
+}
diff --git a/vendor/sebastian/resource-operations/.gitattributes b/vendor/sebastian/resource-operations/.gitattributes
new file mode 100644
index 0000000000000000000000000000000000000000..85e55ebcaabdbf032f2da3e9815fed45ff2db6c4
--- /dev/null
+++ b/vendor/sebastian/resource-operations/.gitattributes
@@ -0,0 +1,7 @@
+/.github        export-ignore
+/.php_cs.dist   export-ignore
+/build.xml      export-ignore
+/phpunit.xml    export-ignore
+/tests          export-ignore
+
+*.php diff=php
diff --git a/vendor/sebastian/resource-operations/.gitignore b/vendor/sebastian/resource-operations/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..a086c781905c17c56b92590bc2ee92ef52ae256c
--- /dev/null
+++ b/vendor/sebastian/resource-operations/.gitignore
@@ -0,0 +1,6 @@
+/.idea
+/.php_cs.cache
+/build/FunctionSignatureMap.php
+/composer.lock
+/vendor
+/.phpunit.result.cache
diff --git a/vendor/sebastian/resource-operations/ChangeLog.md b/vendor/sebastian/resource-operations/ChangeLog.md
new file mode 100644
index 0000000000000000000000000000000000000000..e6dc739226c2871ef5ba92b71fda12fa302d9e71
--- /dev/null
+++ b/vendor/sebastian/resource-operations/ChangeLog.md
@@ -0,0 +1,54 @@
+# ChangeLog
+
+All notable changes are documented in this file using the [Keep a CHANGELOG](https://keepachangelog.com/) principles.
+
+## [3.0.3] - 2020-09-28
+
+### Changed
+
+* Changed PHP version constraint in `composer.json` from `^7.3 || ^8.0` to `>=7.3`
+
+## [3.0.2] - 2020-06-26
+
+### Added
+
+* This component is now supported on PHP 8
+
+## [3.0.1] - 2020-06-15
+
+### Changed
+
+* Tests etc. are now ignored for archive exports
+
+## [3.0.0] - 2020-02-07
+
+### Removed
+
+* This component is no longer supported on PHP 7.1 and PHP 7.2
+
+## [2.0.1] - 2018-10-04
+
+### Fixed
+
+* Functions and methods with nullable parameters of type `resource` are now also considered
+
+## [2.0.0] - 2018-09-27
+
+### Changed
+
+* [FunctionSignatureMap.php](https://raw.githubusercontent.com/phan/phan/master/src/Phan/Language/Internal/FunctionSignatureMap.php) from `phan/phan` is now used instead of [arginfo.php](https://raw.githubusercontent.com/rlerdorf/phan/master/includes/arginfo.php) from `rlerdorf/phan`
+
+### Removed
+
+* This component is no longer supported on PHP 5.6 and PHP 7.0
+
+## 1.0.0 - 2015-07-28
+
+* Initial release
+
+[3.0.3]: https://github.com/sebastianbergmann/comparator/resource-operations/3.0.2...3.0.3
+[3.0.2]: https://github.com/sebastianbergmann/comparator/resource-operations/3.0.1...3.0.2
+[3.0.1]: https://github.com/sebastianbergmann/comparator/resource-operations/3.0.0...3.0.1
+[3.0.0]: https://github.com/sebastianbergmann/comparator/resource-operations/2.0.1...3.0.0
+[2.0.1]: https://github.com/sebastianbergmann/comparator/resource-operations/2.0.0...2.0.1
+[2.0.0]: https://github.com/sebastianbergmann/comparator/resource-operations/1.0.0...2.0.0
diff --git a/vendor/sebastian/resource-operations/LICENSE b/vendor/sebastian/resource-operations/LICENSE
new file mode 100644
index 0000000000000000000000000000000000000000..dccd6b074b5f464945c0633696d6fa72d257c834
--- /dev/null
+++ b/vendor/sebastian/resource-operations/LICENSE
@@ -0,0 +1,33 @@
+Resource Operations
+
+Copyright (c) 2015-2020, Sebastian Bergmann <sebastian@phpunit.de>.
+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 Sebastian Bergmann nor the names of his
+   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/sebastian/resource-operations/README.md b/vendor/sebastian/resource-operations/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..88b05ccb619947035f46062f174f1a4de869d108
--- /dev/null
+++ b/vendor/sebastian/resource-operations/README.md
@@ -0,0 +1,14 @@
+# Resource Operations
+
+Provides a list of PHP built-in functions that operate on resources.
+
+## Installation
+
+You can add this library as a local, per-project dependency to your project using [Composer](https://getcomposer.org/):
+
+    composer require sebastian/resource-operations
+
+If you only need this library during development, for instance to run your project's test suite, then you should add it as a development-time dependency:
+
+    composer require --dev sebastian/resource-operations
+
diff --git a/vendor/sebastian/resource-operations/build/generate.php b/vendor/sebastian/resource-operations/build/generate.php
new file mode 100755
index 0000000000000000000000000000000000000000..0354dc45f9a816de9a578990519b662712aba5ce
--- /dev/null
+++ b/vendor/sebastian/resource-operations/build/generate.php
@@ -0,0 +1,65 @@
+#!/usr/bin/env php
+<?php declare(strict_types=1);
+/*
+ * This file is part of resource-operations.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+$functions         = require __DIR__ . '/FunctionSignatureMap.php';
+$resourceFunctions = [];
+
+foreach ($functions as $function => $arguments) {
+    foreach ($arguments as $argument) {
+        if (strpos($argument, '?') === 0) {
+            $argument = substr($argument, 1);
+        }
+
+        if ($argument === 'resource') {
+            $resourceFunctions[] = explode('\'', $function)[0];
+        }
+    }
+}
+
+$resourceFunctions = array_unique($resourceFunctions);
+sort($resourceFunctions);
+
+$buffer = <<<EOT
+<?php declare(strict_types=1);
+/*
+ * This file is part of resource-operations.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\ResourceOperations;
+
+final class ResourceOperations
+{
+    /**
+     * @return string[]
+     */
+    public static function getFunctions(): array
+    {
+        return [
+
+EOT;
+
+foreach ($resourceFunctions as $function) {
+    $buffer .= sprintf("            '%s',\n", $function);
+}
+
+$buffer .= <<< EOT
+        ];
+    }
+}
+
+EOT;
+
+file_put_contents(__DIR__ . '/../src/ResourceOperations.php', $buffer);
+
diff --git a/vendor/sebastian/resource-operations/composer.json b/vendor/sebastian/resource-operations/composer.json
new file mode 100644
index 0000000000000000000000000000000000000000..870be3c12269b0be23ebdefc09a0770c4bfac0b1
--- /dev/null
+++ b/vendor/sebastian/resource-operations/composer.json
@@ -0,0 +1,37 @@
+{
+    "name": "sebastian/resource-operations",
+    "description": "Provides a list of PHP built-in functions that operate on resources",
+    "homepage": "https://www.github.com/sebastianbergmann/resource-operations",
+    "license": "BSD-3-Clause",
+    "authors": [
+        {
+            "name": "Sebastian Bergmann",
+            "email": "sebastian@phpunit.de"
+        }
+    ],
+    "prefer-stable": true,
+    "require": {
+        "php": ">=7.3"
+    },
+    "require-dev": {
+        "phpunit/phpunit": "^9.0"
+    },
+    "autoload": {
+        "classmap": [
+            "src/"
+        ]
+    },
+    "config": {
+        "platform": {
+            "php": "7.3.0"
+        },
+        "optimize-autoloader": true,
+        "sort-packages": true
+    },
+    "extra": {
+        "branch-alias": {
+            "dev-master": "3.0-dev"
+        }
+    }
+}
+
diff --git a/vendor/sebastian/resource-operations/src/ResourceOperations.php b/vendor/sebastian/resource-operations/src/ResourceOperations.php
new file mode 100644
index 0000000000000000000000000000000000000000..f3911f36c7a99e4b19c962f1c0f8153b9c6d0d40
--- /dev/null
+++ b/vendor/sebastian/resource-operations/src/ResourceOperations.php
@@ -0,0 +1,2232 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of resource-operations.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\ResourceOperations;
+
+final class ResourceOperations
+{
+    /**
+     * @return string[]
+     */
+    public static function getFunctions(): array
+    {
+        return [
+            'Directory::close',
+            'Directory::read',
+            'Directory::rewind',
+            'DirectoryIterator::openFile',
+            'FilesystemIterator::openFile',
+            'Gmagick::readimagefile',
+            'HttpResponse::getRequestBodyStream',
+            'HttpResponse::getStream',
+            'HttpResponse::setStream',
+            'Imagick::pingImageFile',
+            'Imagick::readImageFile',
+            'Imagick::writeImageFile',
+            'Imagick::writeImagesFile',
+            'MongoGridFSCursor::__construct',
+            'MongoGridFSFile::getResource',
+            'MysqlndUhConnection::stmtInit',
+            'MysqlndUhConnection::storeResult',
+            'MysqlndUhConnection::useResult',
+            'PDF_activate_item',
+            'PDF_add_launchlink',
+            'PDF_add_locallink',
+            'PDF_add_nameddest',
+            'PDF_add_note',
+            'PDF_add_pdflink',
+            'PDF_add_table_cell',
+            'PDF_add_textflow',
+            'PDF_add_thumbnail',
+            'PDF_add_weblink',
+            'PDF_arc',
+            'PDF_arcn',
+            'PDF_attach_file',
+            'PDF_begin_document',
+            'PDF_begin_font',
+            'PDF_begin_glyph',
+            'PDF_begin_item',
+            'PDF_begin_layer',
+            'PDF_begin_page',
+            'PDF_begin_page_ext',
+            'PDF_begin_pattern',
+            'PDF_begin_template',
+            'PDF_begin_template_ext',
+            'PDF_circle',
+            'PDF_clip',
+            'PDF_close',
+            'PDF_close_image',
+            'PDF_close_pdi',
+            'PDF_close_pdi_page',
+            'PDF_closepath',
+            'PDF_closepath_fill_stroke',
+            'PDF_closepath_stroke',
+            'PDF_concat',
+            'PDF_continue_text',
+            'PDF_create_3dview',
+            'PDF_create_action',
+            'PDF_create_annotation',
+            'PDF_create_bookmark',
+            'PDF_create_field',
+            'PDF_create_fieldgroup',
+            'PDF_create_gstate',
+            'PDF_create_pvf',
+            'PDF_create_textflow',
+            'PDF_curveto',
+            'PDF_define_layer',
+            'PDF_delete',
+            'PDF_delete_pvf',
+            'PDF_delete_table',
+            'PDF_delete_textflow',
+            'PDF_encoding_set_char',
+            'PDF_end_document',
+            'PDF_end_font',
+            'PDF_end_glyph',
+            'PDF_end_item',
+            'PDF_end_layer',
+            'PDF_end_page',
+            'PDF_end_page_ext',
+            'PDF_end_pattern',
+            'PDF_end_template',
+            'PDF_endpath',
+            'PDF_fill',
+            'PDF_fill_imageblock',
+            'PDF_fill_pdfblock',
+            'PDF_fill_stroke',
+            'PDF_fill_textblock',
+            'PDF_findfont',
+            'PDF_fit_image',
+            'PDF_fit_pdi_page',
+            'PDF_fit_table',
+            'PDF_fit_textflow',
+            'PDF_fit_textline',
+            'PDF_get_apiname',
+            'PDF_get_buffer',
+            'PDF_get_errmsg',
+            'PDF_get_errnum',
+            'PDF_get_parameter',
+            'PDF_get_pdi_parameter',
+            'PDF_get_pdi_value',
+            'PDF_get_value',
+            'PDF_info_font',
+            'PDF_info_matchbox',
+            'PDF_info_table',
+            'PDF_info_textflow',
+            'PDF_info_textline',
+            'PDF_initgraphics',
+            'PDF_lineto',
+            'PDF_load_3ddata',
+            'PDF_load_font',
+            'PDF_load_iccprofile',
+            'PDF_load_image',
+            'PDF_makespotcolor',
+            'PDF_moveto',
+            'PDF_new',
+            'PDF_open_ccitt',
+            'PDF_open_file',
+            'PDF_open_image',
+            'PDF_open_image_file',
+            'PDF_open_memory_image',
+            'PDF_open_pdi',
+            'PDF_open_pdi_document',
+            'PDF_open_pdi_page',
+            'PDF_pcos_get_number',
+            'PDF_pcos_get_stream',
+            'PDF_pcos_get_string',
+            'PDF_place_image',
+            'PDF_place_pdi_page',
+            'PDF_process_pdi',
+            'PDF_rect',
+            'PDF_restore',
+            'PDF_resume_page',
+            'PDF_rotate',
+            'PDF_save',
+            'PDF_scale',
+            'PDF_set_border_color',
+            'PDF_set_border_dash',
+            'PDF_set_border_style',
+            'PDF_set_gstate',
+            'PDF_set_info',
+            'PDF_set_layer_dependency',
+            'PDF_set_parameter',
+            'PDF_set_text_pos',
+            'PDF_set_value',
+            'PDF_setcolor',
+            'PDF_setdash',
+            'PDF_setdashpattern',
+            'PDF_setflat',
+            'PDF_setfont',
+            'PDF_setgray',
+            'PDF_setgray_fill',
+            'PDF_setgray_stroke',
+            'PDF_setlinecap',
+            'PDF_setlinejoin',
+            'PDF_setlinewidth',
+            'PDF_setmatrix',
+            'PDF_setmiterlimit',
+            'PDF_setrgbcolor',
+            'PDF_setrgbcolor_fill',
+            'PDF_setrgbcolor_stroke',
+            'PDF_shading',
+            'PDF_shading_pattern',
+            'PDF_shfill',
+            'PDF_show',
+            'PDF_show_boxed',
+            'PDF_show_xy',
+            'PDF_skew',
+            'PDF_stringwidth',
+            'PDF_stroke',
+            'PDF_suspend_page',
+            'PDF_translate',
+            'PDF_utf16_to_utf8',
+            'PDF_utf32_to_utf16',
+            'PDF_utf8_to_utf16',
+            'PDO::pgsqlLOBOpen',
+            'RarEntry::getStream',
+            'SQLite3::openBlob',
+            'SWFMovie::saveToFile',
+            'SplFileInfo::openFile',
+            'SplFileObject::openFile',
+            'SplTempFileObject::openFile',
+            'V8Js::compileString',
+            'V8Js::executeScript',
+            'Vtiful\Kernel\Excel::setColumn',
+            'Vtiful\Kernel\Excel::setRow',
+            'Vtiful\Kernel\Format::align',
+            'Vtiful\Kernel\Format::bold',
+            'Vtiful\Kernel\Format::italic',
+            'Vtiful\Kernel\Format::underline',
+            'XMLWriter::openMemory',
+            'XMLWriter::openURI',
+            'ZipArchive::getStream',
+            'Zookeeper::setLogStream',
+            'apc_bin_dumpfile',
+            'apc_bin_loadfile',
+            'bbcode_add_element',
+            'bbcode_add_smiley',
+            'bbcode_create',
+            'bbcode_destroy',
+            'bbcode_parse',
+            'bbcode_set_arg_parser',
+            'bbcode_set_flags',
+            'bcompiler_read',
+            'bcompiler_write_class',
+            'bcompiler_write_constant',
+            'bcompiler_write_exe_footer',
+            'bcompiler_write_file',
+            'bcompiler_write_footer',
+            'bcompiler_write_function',
+            'bcompiler_write_functions_from_file',
+            'bcompiler_write_header',
+            'bcompiler_write_included_filename',
+            'bzclose',
+            'bzerrno',
+            'bzerror',
+            'bzerrstr',
+            'bzflush',
+            'bzopen',
+            'bzread',
+            'bzwrite',
+            'cairo_surface_write_to_png',
+            'closedir',
+            'copy',
+            'crack_closedict',
+            'crack_opendict',
+            'cubrid_bind',
+            'cubrid_close_prepare',
+            'cubrid_close_request',
+            'cubrid_col_get',
+            'cubrid_col_size',
+            'cubrid_column_names',
+            'cubrid_column_types',
+            'cubrid_commit',
+            'cubrid_connect',
+            'cubrid_connect_with_url',
+            'cubrid_current_oid',
+            'cubrid_db_parameter',
+            'cubrid_disconnect',
+            'cubrid_drop',
+            'cubrid_fetch',
+            'cubrid_free_result',
+            'cubrid_get',
+            'cubrid_get_autocommit',
+            'cubrid_get_charset',
+            'cubrid_get_class_name',
+            'cubrid_get_db_parameter',
+            'cubrid_get_query_timeout',
+            'cubrid_get_server_info',
+            'cubrid_insert_id',
+            'cubrid_is_instance',
+            'cubrid_lob2_bind',
+            'cubrid_lob2_close',
+            'cubrid_lob2_export',
+            'cubrid_lob2_import',
+            'cubrid_lob2_new',
+            'cubrid_lob2_read',
+            'cubrid_lob2_seek',
+            'cubrid_lob2_seek64',
+            'cubrid_lob2_size',
+            'cubrid_lob2_size64',
+            'cubrid_lob2_tell',
+            'cubrid_lob2_tell64',
+            'cubrid_lob2_write',
+            'cubrid_lob_export',
+            'cubrid_lob_get',
+            'cubrid_lob_send',
+            'cubrid_lob_size',
+            'cubrid_lock_read',
+            'cubrid_lock_write',
+            'cubrid_move_cursor',
+            'cubrid_next_result',
+            'cubrid_num_cols',
+            'cubrid_num_rows',
+            'cubrid_pconnect',
+            'cubrid_pconnect_with_url',
+            'cubrid_prepare',
+            'cubrid_put',
+            'cubrid_query',
+            'cubrid_rollback',
+            'cubrid_schema',
+            'cubrid_seq_add',
+            'cubrid_seq_drop',
+            'cubrid_seq_insert',
+            'cubrid_seq_put',
+            'cubrid_set_add',
+            'cubrid_set_autocommit',
+            'cubrid_set_db_parameter',
+            'cubrid_set_drop',
+            'cubrid_set_query_timeout',
+            'cubrid_unbuffered_query',
+            'curl_close',
+            'curl_copy_handle',
+            'curl_errno',
+            'curl_error',
+            'curl_escape',
+            'curl_exec',
+            'curl_getinfo',
+            'curl_multi_add_handle',
+            'curl_multi_close',
+            'curl_multi_errno',
+            'curl_multi_exec',
+            'curl_multi_getcontent',
+            'curl_multi_info_read',
+            'curl_multi_remove_handle',
+            'curl_multi_select',
+            'curl_multi_setopt',
+            'curl_pause',
+            'curl_reset',
+            'curl_setopt',
+            'curl_setopt_array',
+            'curl_share_close',
+            'curl_share_errno',
+            'curl_share_init',
+            'curl_share_setopt',
+            'curl_unescape',
+            'cyrus_authenticate',
+            'cyrus_bind',
+            'cyrus_close',
+            'cyrus_connect',
+            'cyrus_query',
+            'cyrus_unbind',
+            'db2_autocommit',
+            'db2_bind_param',
+            'db2_client_info',
+            'db2_close',
+            'db2_column_privileges',
+            'db2_columns',
+            'db2_commit',
+            'db2_conn_error',
+            'db2_conn_errormsg',
+            'db2_connect',
+            'db2_cursor_type',
+            'db2_exec',
+            'db2_execute',
+            'db2_fetch_array',
+            'db2_fetch_assoc',
+            'db2_fetch_both',
+            'db2_fetch_object',
+            'db2_fetch_row',
+            'db2_field_display_size',
+            'db2_field_name',
+            'db2_field_num',
+            'db2_field_precision',
+            'db2_field_scale',
+            'db2_field_type',
+            'db2_field_width',
+            'db2_foreign_keys',
+            'db2_free_result',
+            'db2_free_stmt',
+            'db2_get_option',
+            'db2_last_insert_id',
+            'db2_lob_read',
+            'db2_next_result',
+            'db2_num_fields',
+            'db2_num_rows',
+            'db2_pclose',
+            'db2_pconnect',
+            'db2_prepare',
+            'db2_primary_keys',
+            'db2_procedure_columns',
+            'db2_procedures',
+            'db2_result',
+            'db2_rollback',
+            'db2_server_info',
+            'db2_set_option',
+            'db2_special_columns',
+            'db2_statistics',
+            'db2_stmt_error',
+            'db2_stmt_errormsg',
+            'db2_table_privileges',
+            'db2_tables',
+            'dba_close',
+            'dba_delete',
+            'dba_exists',
+            'dba_fetch',
+            'dba_firstkey',
+            'dba_insert',
+            'dba_nextkey',
+            'dba_open',
+            'dba_optimize',
+            'dba_popen',
+            'dba_replace',
+            'dba_sync',
+            'dbplus_add',
+            'dbplus_aql',
+            'dbplus_close',
+            'dbplus_curr',
+            'dbplus_find',
+            'dbplus_first',
+            'dbplus_flush',
+            'dbplus_freelock',
+            'dbplus_freerlocks',
+            'dbplus_getlock',
+            'dbplus_getunique',
+            'dbplus_info',
+            'dbplus_last',
+            'dbplus_lockrel',
+            'dbplus_next',
+            'dbplus_open',
+            'dbplus_prev',
+            'dbplus_rchperm',
+            'dbplus_rcreate',
+            'dbplus_rcrtexact',
+            'dbplus_rcrtlike',
+            'dbplus_restorepos',
+            'dbplus_rkeys',
+            'dbplus_ropen',
+            'dbplus_rquery',
+            'dbplus_rrename',
+            'dbplus_rsecindex',
+            'dbplus_runlink',
+            'dbplus_rzap',
+            'dbplus_savepos',
+            'dbplus_setindex',
+            'dbplus_setindexbynumber',
+            'dbplus_sql',
+            'dbplus_tremove',
+            'dbplus_undo',
+            'dbplus_undoprepare',
+            'dbplus_unlockrel',
+            'dbplus_unselect',
+            'dbplus_update',
+            'dbplus_xlockrel',
+            'dbplus_xunlockrel',
+            'deflate_add',
+            'dio_close',
+            'dio_fcntl',
+            'dio_open',
+            'dio_read',
+            'dio_seek',
+            'dio_stat',
+            'dio_tcsetattr',
+            'dio_truncate',
+            'dio_write',
+            'dir',
+            'eio_busy',
+            'eio_cancel',
+            'eio_chmod',
+            'eio_chown',
+            'eio_close',
+            'eio_custom',
+            'eio_dup2',
+            'eio_fallocate',
+            'eio_fchmod',
+            'eio_fchown',
+            'eio_fdatasync',
+            'eio_fstat',
+            'eio_fstatvfs',
+            'eio_fsync',
+            'eio_ftruncate',
+            'eio_futime',
+            'eio_get_last_error',
+            'eio_grp',
+            'eio_grp_add',
+            'eio_grp_cancel',
+            'eio_grp_limit',
+            'eio_link',
+            'eio_lstat',
+            'eio_mkdir',
+            'eio_mknod',
+            'eio_nop',
+            'eio_open',
+            'eio_read',
+            'eio_readahead',
+            'eio_readdir',
+            'eio_readlink',
+            'eio_realpath',
+            'eio_rename',
+            'eio_rmdir',
+            'eio_seek',
+            'eio_sendfile',
+            'eio_stat',
+            'eio_statvfs',
+            'eio_symlink',
+            'eio_sync',
+            'eio_sync_file_range',
+            'eio_syncfs',
+            'eio_truncate',
+            'eio_unlink',
+            'eio_utime',
+            'eio_write',
+            'enchant_broker_describe',
+            'enchant_broker_dict_exists',
+            'enchant_broker_free',
+            'enchant_broker_free_dict',
+            'enchant_broker_get_dict_path',
+            'enchant_broker_get_error',
+            'enchant_broker_init',
+            'enchant_broker_list_dicts',
+            'enchant_broker_request_dict',
+            'enchant_broker_request_pwl_dict',
+            'enchant_broker_set_dict_path',
+            'enchant_broker_set_ordering',
+            'enchant_dict_add_to_personal',
+            'enchant_dict_add_to_session',
+            'enchant_dict_check',
+            'enchant_dict_describe',
+            'enchant_dict_get_error',
+            'enchant_dict_is_in_session',
+            'enchant_dict_quick_check',
+            'enchant_dict_store_replacement',
+            'enchant_dict_suggest',
+            'event_add',
+            'event_base_free',
+            'event_base_loop',
+            'event_base_loopbreak',
+            'event_base_loopexit',
+            'event_base_new',
+            'event_base_priority_init',
+            'event_base_reinit',
+            'event_base_set',
+            'event_buffer_base_set',
+            'event_buffer_disable',
+            'event_buffer_enable',
+            'event_buffer_fd_set',
+            'event_buffer_free',
+            'event_buffer_new',
+            'event_buffer_priority_set',
+            'event_buffer_read',
+            'event_buffer_set_callback',
+            'event_buffer_timeout_set',
+            'event_buffer_watermark_set',
+            'event_buffer_write',
+            'event_del',
+            'event_free',
+            'event_new',
+            'event_priority_set',
+            'event_set',
+            'event_timer_add',
+            'event_timer_del',
+            'event_timer_pending',
+            'event_timer_set',
+            'expect_expectl',
+            'expect_popen',
+            'fam_cancel_monitor',
+            'fam_close',
+            'fam_monitor_collection',
+            'fam_monitor_directory',
+            'fam_monitor_file',
+            'fam_next_event',
+            'fam_open',
+            'fam_pending',
+            'fam_resume_monitor',
+            'fam_suspend_monitor',
+            'fann_cascadetrain_on_data',
+            'fann_cascadetrain_on_file',
+            'fann_clear_scaling_params',
+            'fann_copy',
+            'fann_create_from_file',
+            'fann_create_shortcut_array',
+            'fann_create_standard',
+            'fann_create_standard_array',
+            'fann_create_train',
+            'fann_create_train_from_callback',
+            'fann_descale_input',
+            'fann_descale_output',
+            'fann_descale_train',
+            'fann_destroy',
+            'fann_destroy_train',
+            'fann_duplicate_train_data',
+            'fann_get_MSE',
+            'fann_get_activation_function',
+            'fann_get_activation_steepness',
+            'fann_get_bias_array',
+            'fann_get_bit_fail',
+            'fann_get_bit_fail_limit',
+            'fann_get_cascade_activation_functions',
+            'fann_get_cascade_activation_functions_count',
+            'fann_get_cascade_activation_steepnesses',
+            'fann_get_cascade_activation_steepnesses_count',
+            'fann_get_cascade_candidate_change_fraction',
+            'fann_get_cascade_candidate_limit',
+            'fann_get_cascade_candidate_stagnation_epochs',
+            'fann_get_cascade_max_cand_epochs',
+            'fann_get_cascade_max_out_epochs',
+            'fann_get_cascade_min_cand_epochs',
+            'fann_get_cascade_min_out_epochs',
+            'fann_get_cascade_num_candidate_groups',
+            'fann_get_cascade_num_candidates',
+            'fann_get_cascade_output_change_fraction',
+            'fann_get_cascade_output_stagnation_epochs',
+            'fann_get_cascade_weight_multiplier',
+            'fann_get_connection_array',
+            'fann_get_connection_rate',
+            'fann_get_errno',
+            'fann_get_errstr',
+            'fann_get_layer_array',
+            'fann_get_learning_momentum',
+            'fann_get_learning_rate',
+            'fann_get_network_type',
+            'fann_get_num_input',
+            'fann_get_num_layers',
+            'fann_get_num_output',
+            'fann_get_quickprop_decay',
+            'fann_get_quickprop_mu',
+            'fann_get_rprop_decrease_factor',
+            'fann_get_rprop_delta_max',
+            'fann_get_rprop_delta_min',
+            'fann_get_rprop_delta_zero',
+            'fann_get_rprop_increase_factor',
+            'fann_get_sarprop_step_error_shift',
+            'fann_get_sarprop_step_error_threshold_factor',
+            'fann_get_sarprop_temperature',
+            'fann_get_sarprop_weight_decay_shift',
+            'fann_get_total_connections',
+            'fann_get_total_neurons',
+            'fann_get_train_error_function',
+            'fann_get_train_stop_function',
+            'fann_get_training_algorithm',
+            'fann_init_weights',
+            'fann_length_train_data',
+            'fann_merge_train_data',
+            'fann_num_input_train_data',
+            'fann_num_output_train_data',
+            'fann_randomize_weights',
+            'fann_read_train_from_file',
+            'fann_reset_errno',
+            'fann_reset_errstr',
+            'fann_run',
+            'fann_save',
+            'fann_save_train',
+            'fann_scale_input',
+            'fann_scale_input_train_data',
+            'fann_scale_output',
+            'fann_scale_output_train_data',
+            'fann_scale_train',
+            'fann_scale_train_data',
+            'fann_set_activation_function',
+            'fann_set_activation_function_hidden',
+            'fann_set_activation_function_layer',
+            'fann_set_activation_function_output',
+            'fann_set_activation_steepness',
+            'fann_set_activation_steepness_hidden',
+            'fann_set_activation_steepness_layer',
+            'fann_set_activation_steepness_output',
+            'fann_set_bit_fail_limit',
+            'fann_set_callback',
+            'fann_set_cascade_activation_functions',
+            'fann_set_cascade_activation_steepnesses',
+            'fann_set_cascade_candidate_change_fraction',
+            'fann_set_cascade_candidate_limit',
+            'fann_set_cascade_candidate_stagnation_epochs',
+            'fann_set_cascade_max_cand_epochs',
+            'fann_set_cascade_max_out_epochs',
+            'fann_set_cascade_min_cand_epochs',
+            'fann_set_cascade_min_out_epochs',
+            'fann_set_cascade_num_candidate_groups',
+            'fann_set_cascade_output_change_fraction',
+            'fann_set_cascade_output_stagnation_epochs',
+            'fann_set_cascade_weight_multiplier',
+            'fann_set_error_log',
+            'fann_set_input_scaling_params',
+            'fann_set_learning_momentum',
+            'fann_set_learning_rate',
+            'fann_set_output_scaling_params',
+            'fann_set_quickprop_decay',
+            'fann_set_quickprop_mu',
+            'fann_set_rprop_decrease_factor',
+            'fann_set_rprop_delta_max',
+            'fann_set_rprop_delta_min',
+            'fann_set_rprop_delta_zero',
+            'fann_set_rprop_increase_factor',
+            'fann_set_sarprop_step_error_shift',
+            'fann_set_sarprop_step_error_threshold_factor',
+            'fann_set_sarprop_temperature',
+            'fann_set_sarprop_weight_decay_shift',
+            'fann_set_scaling_params',
+            'fann_set_train_error_function',
+            'fann_set_train_stop_function',
+            'fann_set_training_algorithm',
+            'fann_set_weight',
+            'fann_set_weight_array',
+            'fann_shuffle_train_data',
+            'fann_subset_train_data',
+            'fann_test',
+            'fann_test_data',
+            'fann_train',
+            'fann_train_epoch',
+            'fann_train_on_data',
+            'fann_train_on_file',
+            'fbsql_affected_rows',
+            'fbsql_autocommit',
+            'fbsql_blob_size',
+            'fbsql_change_user',
+            'fbsql_clob_size',
+            'fbsql_close',
+            'fbsql_commit',
+            'fbsql_connect',
+            'fbsql_create_blob',
+            'fbsql_create_clob',
+            'fbsql_create_db',
+            'fbsql_data_seek',
+            'fbsql_database',
+            'fbsql_database_password',
+            'fbsql_db_query',
+            'fbsql_db_status',
+            'fbsql_drop_db',
+            'fbsql_errno',
+            'fbsql_error',
+            'fbsql_fetch_array',
+            'fbsql_fetch_assoc',
+            'fbsql_fetch_field',
+            'fbsql_fetch_lengths',
+            'fbsql_fetch_object',
+            'fbsql_fetch_row',
+            'fbsql_field_flags',
+            'fbsql_field_len',
+            'fbsql_field_name',
+            'fbsql_field_seek',
+            'fbsql_field_table',
+            'fbsql_field_type',
+            'fbsql_free_result',
+            'fbsql_get_autostart_info',
+            'fbsql_hostname',
+            'fbsql_insert_id',
+            'fbsql_list_dbs',
+            'fbsql_list_fields',
+            'fbsql_list_tables',
+            'fbsql_next_result',
+            'fbsql_num_fields',
+            'fbsql_num_rows',
+            'fbsql_password',
+            'fbsql_pconnect',
+            'fbsql_query',
+            'fbsql_read_blob',
+            'fbsql_read_clob',
+            'fbsql_result',
+            'fbsql_rollback',
+            'fbsql_rows_fetched',
+            'fbsql_select_db',
+            'fbsql_set_characterset',
+            'fbsql_set_lob_mode',
+            'fbsql_set_password',
+            'fbsql_set_transaction',
+            'fbsql_start_db',
+            'fbsql_stop_db',
+            'fbsql_table_name',
+            'fbsql_username',
+            'fclose',
+            'fdf_add_doc_javascript',
+            'fdf_add_template',
+            'fdf_close',
+            'fdf_create',
+            'fdf_enum_values',
+            'fdf_get_ap',
+            'fdf_get_attachment',
+            'fdf_get_encoding',
+            'fdf_get_file',
+            'fdf_get_flags',
+            'fdf_get_opt',
+            'fdf_get_status',
+            'fdf_get_value',
+            'fdf_get_version',
+            'fdf_next_field_name',
+            'fdf_open',
+            'fdf_open_string',
+            'fdf_remove_item',
+            'fdf_save',
+            'fdf_save_string',
+            'fdf_set_ap',
+            'fdf_set_encoding',
+            'fdf_set_file',
+            'fdf_set_flags',
+            'fdf_set_javascript_action',
+            'fdf_set_on_import_javascript',
+            'fdf_set_opt',
+            'fdf_set_status',
+            'fdf_set_submit_form_action',
+            'fdf_set_target_frame',
+            'fdf_set_value',
+            'fdf_set_version',
+            'feof',
+            'fflush',
+            'ffmpeg_frame::__construct',
+            'ffmpeg_frame::toGDImage',
+            'fgetc',
+            'fgetcsv',
+            'fgets',
+            'fgetss',
+            'file',
+            'file_get_contents',
+            'file_put_contents',
+            'finfo::buffer',
+            'finfo::file',
+            'finfo_buffer',
+            'finfo_close',
+            'finfo_file',
+            'finfo_open',
+            'finfo_set_flags',
+            'flock',
+            'fopen',
+            'fpassthru',
+            'fprintf',
+            'fputcsv',
+            'fputs',
+            'fread',
+            'fscanf',
+            'fseek',
+            'fstat',
+            'ftell',
+            'ftp_alloc',
+            'ftp_append',
+            'ftp_cdup',
+            'ftp_chdir',
+            'ftp_chmod',
+            'ftp_close',
+            'ftp_delete',
+            'ftp_exec',
+            'ftp_fget',
+            'ftp_fput',
+            'ftp_get',
+            'ftp_get_option',
+            'ftp_login',
+            'ftp_mdtm',
+            'ftp_mkdir',
+            'ftp_mlsd',
+            'ftp_nb_continue',
+            'ftp_nb_fget',
+            'ftp_nb_fput',
+            'ftp_nb_get',
+            'ftp_nb_put',
+            'ftp_nlist',
+            'ftp_pasv',
+            'ftp_put',
+            'ftp_pwd',
+            'ftp_quit',
+            'ftp_raw',
+            'ftp_rawlist',
+            'ftp_rename',
+            'ftp_rmdir',
+            'ftp_set_option',
+            'ftp_site',
+            'ftp_size',
+            'ftp_systype',
+            'ftruncate',
+            'fwrite',
+            'get_resource_type',
+            'gmp_div',
+            'gnupg::init',
+            'gnupg_adddecryptkey',
+            'gnupg_addencryptkey',
+            'gnupg_addsignkey',
+            'gnupg_cleardecryptkeys',
+            'gnupg_clearencryptkeys',
+            'gnupg_clearsignkeys',
+            'gnupg_decrypt',
+            'gnupg_decryptverify',
+            'gnupg_encrypt',
+            'gnupg_encryptsign',
+            'gnupg_export',
+            'gnupg_geterror',
+            'gnupg_getprotocol',
+            'gnupg_import',
+            'gnupg_init',
+            'gnupg_keyinfo',
+            'gnupg_setarmor',
+            'gnupg_seterrormode',
+            'gnupg_setsignmode',
+            'gnupg_sign',
+            'gnupg_verify',
+            'gupnp_context_get_host_ip',
+            'gupnp_context_get_port',
+            'gupnp_context_get_subscription_timeout',
+            'gupnp_context_host_path',
+            'gupnp_context_new',
+            'gupnp_context_set_subscription_timeout',
+            'gupnp_context_timeout_add',
+            'gupnp_context_unhost_path',
+            'gupnp_control_point_browse_start',
+            'gupnp_control_point_browse_stop',
+            'gupnp_control_point_callback_set',
+            'gupnp_control_point_new',
+            'gupnp_device_action_callback_set',
+            'gupnp_device_info_get',
+            'gupnp_device_info_get_service',
+            'gupnp_root_device_get_available',
+            'gupnp_root_device_get_relative_location',
+            'gupnp_root_device_new',
+            'gupnp_root_device_set_available',
+            'gupnp_root_device_start',
+            'gupnp_root_device_stop',
+            'gupnp_service_action_get',
+            'gupnp_service_action_return',
+            'gupnp_service_action_return_error',
+            'gupnp_service_action_set',
+            'gupnp_service_freeze_notify',
+            'gupnp_service_info_get',
+            'gupnp_service_info_get_introspection',
+            'gupnp_service_introspection_get_state_variable',
+            'gupnp_service_notify',
+            'gupnp_service_proxy_action_get',
+            'gupnp_service_proxy_action_set',
+            'gupnp_service_proxy_add_notify',
+            'gupnp_service_proxy_callback_set',
+            'gupnp_service_proxy_get_subscribed',
+            'gupnp_service_proxy_remove_notify',
+            'gupnp_service_proxy_send_action',
+            'gupnp_service_proxy_set_subscribed',
+            'gupnp_service_thaw_notify',
+            'gzclose',
+            'gzeof',
+            'gzgetc',
+            'gzgets',
+            'gzgetss',
+            'gzpassthru',
+            'gzputs',
+            'gzread',
+            'gzrewind',
+            'gzseek',
+            'gztell',
+            'gzwrite',
+            'hash_update_stream',
+            'http\Env\Response::send',
+            'http_get_request_body_stream',
+            'ibase_add_user',
+            'ibase_affected_rows',
+            'ibase_backup',
+            'ibase_blob_add',
+            'ibase_blob_cancel',
+            'ibase_blob_close',
+            'ibase_blob_create',
+            'ibase_blob_get',
+            'ibase_blob_open',
+            'ibase_close',
+            'ibase_commit',
+            'ibase_commit_ret',
+            'ibase_connect',
+            'ibase_db_info',
+            'ibase_delete_user',
+            'ibase_drop_db',
+            'ibase_execute',
+            'ibase_fetch_assoc',
+            'ibase_fetch_object',
+            'ibase_fetch_row',
+            'ibase_field_info',
+            'ibase_free_event_handler',
+            'ibase_free_query',
+            'ibase_free_result',
+            'ibase_gen_id',
+            'ibase_maintain_db',
+            'ibase_modify_user',
+            'ibase_name_result',
+            'ibase_num_fields',
+            'ibase_num_params',
+            'ibase_param_info',
+            'ibase_pconnect',
+            'ibase_prepare',
+            'ibase_query',
+            'ibase_restore',
+            'ibase_rollback',
+            'ibase_rollback_ret',
+            'ibase_server_info',
+            'ibase_service_attach',
+            'ibase_service_detach',
+            'ibase_set_event_handler',
+            'ibase_trans',
+            'ifx_affected_rows',
+            'ifx_close',
+            'ifx_connect',
+            'ifx_do',
+            'ifx_error',
+            'ifx_fetch_row',
+            'ifx_fieldproperties',
+            'ifx_fieldtypes',
+            'ifx_free_result',
+            'ifx_getsqlca',
+            'ifx_htmltbl_result',
+            'ifx_num_fields',
+            'ifx_num_rows',
+            'ifx_pconnect',
+            'ifx_prepare',
+            'ifx_query',
+            'image2wbmp',
+            'imageaffine',
+            'imagealphablending',
+            'imageantialias',
+            'imagearc',
+            'imagebmp',
+            'imagechar',
+            'imagecharup',
+            'imagecolorallocate',
+            'imagecolorallocatealpha',
+            'imagecolorat',
+            'imagecolorclosest',
+            'imagecolorclosestalpha',
+            'imagecolorclosesthwb',
+            'imagecolordeallocate',
+            'imagecolorexact',
+            'imagecolorexactalpha',
+            'imagecolormatch',
+            'imagecolorresolve',
+            'imagecolorresolvealpha',
+            'imagecolorset',
+            'imagecolorsforindex',
+            'imagecolorstotal',
+            'imagecolortransparent',
+            'imageconvolution',
+            'imagecopy',
+            'imagecopymerge',
+            'imagecopymergegray',
+            'imagecopyresampled',
+            'imagecopyresized',
+            'imagecrop',
+            'imagecropauto',
+            'imagedashedline',
+            'imagedestroy',
+            'imageellipse',
+            'imagefill',
+            'imagefilledarc',
+            'imagefilledellipse',
+            'imagefilledpolygon',
+            'imagefilledrectangle',
+            'imagefilltoborder',
+            'imagefilter',
+            'imageflip',
+            'imagefttext',
+            'imagegammacorrect',
+            'imagegd',
+            'imagegd2',
+            'imagegetclip',
+            'imagegif',
+            'imagegrabscreen',
+            'imagegrabwindow',
+            'imageinterlace',
+            'imageistruecolor',
+            'imagejpeg',
+            'imagelayereffect',
+            'imageline',
+            'imageopenpolygon',
+            'imagepalettecopy',
+            'imagepalettetotruecolor',
+            'imagepng',
+            'imagepolygon',
+            'imagepsencodefont',
+            'imagepsextendfont',
+            'imagepsfreefont',
+            'imagepsloadfont',
+            'imagepsslantfont',
+            'imagepstext',
+            'imagerectangle',
+            'imageresolution',
+            'imagerotate',
+            'imagesavealpha',
+            'imagescale',
+            'imagesetbrush',
+            'imagesetclip',
+            'imagesetinterpolation',
+            'imagesetpixel',
+            'imagesetstyle',
+            'imagesetthickness',
+            'imagesettile',
+            'imagestring',
+            'imagestringup',
+            'imagesx',
+            'imagesy',
+            'imagetruecolortopalette',
+            'imagettftext',
+            'imagewbmp',
+            'imagewebp',
+            'imagexbm',
+            'imap_append',
+            'imap_body',
+            'imap_bodystruct',
+            'imap_check',
+            'imap_clearflag_full',
+            'imap_close',
+            'imap_create',
+            'imap_createmailbox',
+            'imap_delete',
+            'imap_deletemailbox',
+            'imap_expunge',
+            'imap_fetch_overview',
+            'imap_fetchbody',
+            'imap_fetchheader',
+            'imap_fetchmime',
+            'imap_fetchstructure',
+            'imap_fetchtext',
+            'imap_gc',
+            'imap_get_quota',
+            'imap_get_quotaroot',
+            'imap_getacl',
+            'imap_getmailboxes',
+            'imap_getsubscribed',
+            'imap_header',
+            'imap_headerinfo',
+            'imap_headers',
+            'imap_list',
+            'imap_listmailbox',
+            'imap_listscan',
+            'imap_listsubscribed',
+            'imap_lsub',
+            'imap_mail_copy',
+            'imap_mail_move',
+            'imap_mailboxmsginfo',
+            'imap_msgno',
+            'imap_num_msg',
+            'imap_num_recent',
+            'imap_ping',
+            'imap_rename',
+            'imap_renamemailbox',
+            'imap_reopen',
+            'imap_savebody',
+            'imap_scan',
+            'imap_scanmailbox',
+            'imap_search',
+            'imap_set_quota',
+            'imap_setacl',
+            'imap_setflag_full',
+            'imap_sort',
+            'imap_status',
+            'imap_subscribe',
+            'imap_thread',
+            'imap_uid',
+            'imap_undelete',
+            'imap_unsubscribe',
+            'inflate_add',
+            'inflate_get_read_len',
+            'inflate_get_status',
+            'ingres_autocommit',
+            'ingres_autocommit_state',
+            'ingres_charset',
+            'ingres_close',
+            'ingres_commit',
+            'ingres_connect',
+            'ingres_cursor',
+            'ingres_errno',
+            'ingres_error',
+            'ingres_errsqlstate',
+            'ingres_escape_string',
+            'ingres_execute',
+            'ingres_fetch_array',
+            'ingres_fetch_assoc',
+            'ingres_fetch_object',
+            'ingres_fetch_proc_return',
+            'ingres_fetch_row',
+            'ingres_field_length',
+            'ingres_field_name',
+            'ingres_field_nullable',
+            'ingres_field_precision',
+            'ingres_field_scale',
+            'ingres_field_type',
+            'ingres_free_result',
+            'ingres_next_error',
+            'ingres_num_fields',
+            'ingres_num_rows',
+            'ingres_pconnect',
+            'ingres_prepare',
+            'ingres_query',
+            'ingres_result_seek',
+            'ingres_rollback',
+            'ingres_set_environment',
+            'ingres_unbuffered_query',
+            'inotify_add_watch',
+            'inotify_init',
+            'inotify_queue_len',
+            'inotify_read',
+            'inotify_rm_watch',
+            'kadm5_chpass_principal',
+            'kadm5_create_principal',
+            'kadm5_delete_principal',
+            'kadm5_destroy',
+            'kadm5_flush',
+            'kadm5_get_policies',
+            'kadm5_get_principal',
+            'kadm5_get_principals',
+            'kadm5_init_with_password',
+            'kadm5_modify_principal',
+            'ldap_add',
+            'ldap_bind',
+            'ldap_close',
+            'ldap_compare',
+            'ldap_control_paged_result',
+            'ldap_control_paged_result_response',
+            'ldap_count_entries',
+            'ldap_delete',
+            'ldap_errno',
+            'ldap_error',
+            'ldap_exop',
+            'ldap_exop_passwd',
+            'ldap_exop_refresh',
+            'ldap_exop_whoami',
+            'ldap_first_attribute',
+            'ldap_first_entry',
+            'ldap_first_reference',
+            'ldap_free_result',
+            'ldap_get_attributes',
+            'ldap_get_dn',
+            'ldap_get_entries',
+            'ldap_get_option',
+            'ldap_get_values',
+            'ldap_get_values_len',
+            'ldap_mod_add',
+            'ldap_mod_del',
+            'ldap_mod_replace',
+            'ldap_modify',
+            'ldap_modify_batch',
+            'ldap_next_attribute',
+            'ldap_next_entry',
+            'ldap_next_reference',
+            'ldap_parse_exop',
+            'ldap_parse_reference',
+            'ldap_parse_result',
+            'ldap_rename',
+            'ldap_sasl_bind',
+            'ldap_set_option',
+            'ldap_set_rebind_proc',
+            'ldap_sort',
+            'ldap_start_tls',
+            'ldap_unbind',
+            'libxml_set_streams_context',
+            'm_checkstatus',
+            'm_completeauthorizations',
+            'm_connect',
+            'm_connectionerror',
+            'm_deletetrans',
+            'm_destroyconn',
+            'm_getcell',
+            'm_getcellbynum',
+            'm_getcommadelimited',
+            'm_getheader',
+            'm_initconn',
+            'm_iscommadelimited',
+            'm_maxconntimeout',
+            'm_monitor',
+            'm_numcolumns',
+            'm_numrows',
+            'm_parsecommadelimited',
+            'm_responsekeys',
+            'm_responseparam',
+            'm_returnstatus',
+            'm_setblocking',
+            'm_setdropfile',
+            'm_setip',
+            'm_setssl',
+            'm_setssl_cafile',
+            'm_setssl_files',
+            'm_settimeout',
+            'm_transactionssent',
+            'm_transinqueue',
+            'm_transkeyval',
+            'm_transnew',
+            'm_transsend',
+            'm_validateidentifier',
+            'm_verifyconnection',
+            'm_verifysslcert',
+            'mailparse_determine_best_xfer_encoding',
+            'mailparse_msg_create',
+            'mailparse_msg_extract_part',
+            'mailparse_msg_extract_part_file',
+            'mailparse_msg_extract_whole_part_file',
+            'mailparse_msg_free',
+            'mailparse_msg_get_part',
+            'mailparse_msg_get_part_data',
+            'mailparse_msg_get_structure',
+            'mailparse_msg_parse',
+            'mailparse_msg_parse_file',
+            'mailparse_stream_encode',
+            'mailparse_uudecode_all',
+            'maxdb::use_result',
+            'maxdb_affected_rows',
+            'maxdb_connect',
+            'maxdb_disable_rpl_parse',
+            'maxdb_dump_debug_info',
+            'maxdb_embedded_connect',
+            'maxdb_enable_reads_from_master',
+            'maxdb_enable_rpl_parse',
+            'maxdb_errno',
+            'maxdb_error',
+            'maxdb_fetch_lengths',
+            'maxdb_field_tell',
+            'maxdb_get_host_info',
+            'maxdb_get_proto_info',
+            'maxdb_get_server_info',
+            'maxdb_get_server_version',
+            'maxdb_info',
+            'maxdb_init',
+            'maxdb_insert_id',
+            'maxdb_master_query',
+            'maxdb_more_results',
+            'maxdb_next_result',
+            'maxdb_num_fields',
+            'maxdb_num_rows',
+            'maxdb_rpl_parse_enabled',
+            'maxdb_rpl_probe',
+            'maxdb_select_db',
+            'maxdb_sqlstate',
+            'maxdb_stmt::result_metadata',
+            'maxdb_stmt_affected_rows',
+            'maxdb_stmt_errno',
+            'maxdb_stmt_error',
+            'maxdb_stmt_num_rows',
+            'maxdb_stmt_param_count',
+            'maxdb_stmt_result_metadata',
+            'maxdb_stmt_sqlstate',
+            'maxdb_thread_id',
+            'maxdb_use_result',
+            'maxdb_warning_count',
+            'mcrypt_enc_get_algorithms_name',
+            'mcrypt_enc_get_block_size',
+            'mcrypt_enc_get_iv_size',
+            'mcrypt_enc_get_key_size',
+            'mcrypt_enc_get_modes_name',
+            'mcrypt_enc_get_supported_key_sizes',
+            'mcrypt_enc_is_block_algorithm',
+            'mcrypt_enc_is_block_algorithm_mode',
+            'mcrypt_enc_is_block_mode',
+            'mcrypt_enc_self_test',
+            'mcrypt_generic',
+            'mcrypt_generic_deinit',
+            'mcrypt_generic_end',
+            'mcrypt_generic_init',
+            'mcrypt_module_close',
+            'mcrypt_module_open',
+            'mdecrypt_generic',
+            'mkdir',
+            'mqseries_back',
+            'mqseries_begin',
+            'mqseries_close',
+            'mqseries_cmit',
+            'mqseries_conn',
+            'mqseries_connx',
+            'mqseries_disc',
+            'mqseries_get',
+            'mqseries_inq',
+            'mqseries_open',
+            'mqseries_put',
+            'mqseries_put1',
+            'mqseries_set',
+            'msg_get_queue',
+            'msg_receive',
+            'msg_remove_queue',
+            'msg_send',
+            'msg_set_queue',
+            'msg_stat_queue',
+            'msql_affected_rows',
+            'msql_close',
+            'msql_connect',
+            'msql_create_db',
+            'msql_data_seek',
+            'msql_db_query',
+            'msql_drop_db',
+            'msql_fetch_array',
+            'msql_fetch_field',
+            'msql_fetch_object',
+            'msql_fetch_row',
+            'msql_field_flags',
+            'msql_field_len',
+            'msql_field_name',
+            'msql_field_seek',
+            'msql_field_table',
+            'msql_field_type',
+            'msql_free_result',
+            'msql_list_dbs',
+            'msql_list_fields',
+            'msql_list_tables',
+            'msql_num_fields',
+            'msql_num_rows',
+            'msql_pconnect',
+            'msql_query',
+            'msql_result',
+            'msql_select_db',
+            'mssql_bind',
+            'mssql_close',
+            'mssql_connect',
+            'mssql_data_seek',
+            'mssql_execute',
+            'mssql_fetch_array',
+            'mssql_fetch_assoc',
+            'mssql_fetch_batch',
+            'mssql_fetch_field',
+            'mssql_fetch_object',
+            'mssql_fetch_row',
+            'mssql_field_length',
+            'mssql_field_name',
+            'mssql_field_seek',
+            'mssql_field_type',
+            'mssql_free_result',
+            'mssql_free_statement',
+            'mssql_init',
+            'mssql_next_result',
+            'mssql_num_fields',
+            'mssql_num_rows',
+            'mssql_pconnect',
+            'mssql_query',
+            'mssql_result',
+            'mssql_rows_affected',
+            'mssql_select_db',
+            'mysql_affected_rows',
+            'mysql_client_encoding',
+            'mysql_close',
+            'mysql_connect',
+            'mysql_create_db',
+            'mysql_data_seek',
+            'mysql_db_name',
+            'mysql_db_query',
+            'mysql_drop_db',
+            'mysql_errno',
+            'mysql_error',
+            'mysql_fetch_array',
+            'mysql_fetch_assoc',
+            'mysql_fetch_field',
+            'mysql_fetch_lengths',
+            'mysql_fetch_object',
+            'mysql_fetch_row',
+            'mysql_field_flags',
+            'mysql_field_len',
+            'mysql_field_name',
+            'mysql_field_seek',
+            'mysql_field_table',
+            'mysql_field_type',
+            'mysql_free_result',
+            'mysql_get_host_info',
+            'mysql_get_proto_info',
+            'mysql_get_server_info',
+            'mysql_info',
+            'mysql_insert_id',
+            'mysql_list_dbs',
+            'mysql_list_fields',
+            'mysql_list_processes',
+            'mysql_list_tables',
+            'mysql_num_fields',
+            'mysql_num_rows',
+            'mysql_pconnect',
+            'mysql_ping',
+            'mysql_query',
+            'mysql_real_escape_string',
+            'mysql_result',
+            'mysql_select_db',
+            'mysql_set_charset',
+            'mysql_stat',
+            'mysql_tablename',
+            'mysql_thread_id',
+            'mysql_unbuffered_query',
+            'mysqlnd_uh_convert_to_mysqlnd',
+            'ncurses_bottom_panel',
+            'ncurses_del_panel',
+            'ncurses_delwin',
+            'ncurses_getmaxyx',
+            'ncurses_getyx',
+            'ncurses_hide_panel',
+            'ncurses_keypad',
+            'ncurses_meta',
+            'ncurses_move_panel',
+            'ncurses_mvwaddstr',
+            'ncurses_new_panel',
+            'ncurses_newpad',
+            'ncurses_newwin',
+            'ncurses_panel_above',
+            'ncurses_panel_below',
+            'ncurses_panel_window',
+            'ncurses_pnoutrefresh',
+            'ncurses_prefresh',
+            'ncurses_replace_panel',
+            'ncurses_show_panel',
+            'ncurses_top_panel',
+            'ncurses_waddch',
+            'ncurses_waddstr',
+            'ncurses_wattroff',
+            'ncurses_wattron',
+            'ncurses_wattrset',
+            'ncurses_wborder',
+            'ncurses_wclear',
+            'ncurses_wcolor_set',
+            'ncurses_werase',
+            'ncurses_wgetch',
+            'ncurses_whline',
+            'ncurses_wmouse_trafo',
+            'ncurses_wmove',
+            'ncurses_wnoutrefresh',
+            'ncurses_wrefresh',
+            'ncurses_wstandend',
+            'ncurses_wstandout',
+            'ncurses_wvline',
+            'newt_button',
+            'newt_button_bar',
+            'newt_checkbox',
+            'newt_checkbox_get_value',
+            'newt_checkbox_set_flags',
+            'newt_checkbox_set_value',
+            'newt_checkbox_tree',
+            'newt_checkbox_tree_add_item',
+            'newt_checkbox_tree_find_item',
+            'newt_checkbox_tree_get_current',
+            'newt_checkbox_tree_get_entry_value',
+            'newt_checkbox_tree_get_multi_selection',
+            'newt_checkbox_tree_get_selection',
+            'newt_checkbox_tree_multi',
+            'newt_checkbox_tree_set_current',
+            'newt_checkbox_tree_set_entry',
+            'newt_checkbox_tree_set_entry_value',
+            'newt_checkbox_tree_set_width',
+            'newt_compact_button',
+            'newt_component_add_callback',
+            'newt_component_takes_focus',
+            'newt_create_grid',
+            'newt_draw_form',
+            'newt_entry',
+            'newt_entry_get_value',
+            'newt_entry_set',
+            'newt_entry_set_filter',
+            'newt_entry_set_flags',
+            'newt_form',
+            'newt_form_add_component',
+            'newt_form_add_components',
+            'newt_form_add_hot_key',
+            'newt_form_destroy',
+            'newt_form_get_current',
+            'newt_form_run',
+            'newt_form_set_background',
+            'newt_form_set_height',
+            'newt_form_set_size',
+            'newt_form_set_timer',
+            'newt_form_set_width',
+            'newt_form_watch_fd',
+            'newt_grid_add_components_to_form',
+            'newt_grid_basic_window',
+            'newt_grid_free',
+            'newt_grid_get_size',
+            'newt_grid_h_close_stacked',
+            'newt_grid_h_stacked',
+            'newt_grid_place',
+            'newt_grid_set_field',
+            'newt_grid_simple_window',
+            'newt_grid_v_close_stacked',
+            'newt_grid_v_stacked',
+            'newt_grid_wrapped_window',
+            'newt_grid_wrapped_window_at',
+            'newt_label',
+            'newt_label_set_text',
+            'newt_listbox',
+            'newt_listbox_append_entry',
+            'newt_listbox_clear',
+            'newt_listbox_clear_selection',
+            'newt_listbox_delete_entry',
+            'newt_listbox_get_current',
+            'newt_listbox_get_selection',
+            'newt_listbox_insert_entry',
+            'newt_listbox_item_count',
+            'newt_listbox_select_item',
+            'newt_listbox_set_current',
+            'newt_listbox_set_current_by_key',
+            'newt_listbox_set_data',
+            'newt_listbox_set_entry',
+            'newt_listbox_set_width',
+            'newt_listitem',
+            'newt_listitem_get_data',
+            'newt_listitem_set',
+            'newt_radio_get_current',
+            'newt_radiobutton',
+            'newt_run_form',
+            'newt_scale',
+            'newt_scale_set',
+            'newt_scrollbar_set',
+            'newt_textbox',
+            'newt_textbox_get_num_lines',
+            'newt_textbox_reflowed',
+            'newt_textbox_set_height',
+            'newt_textbox_set_text',
+            'newt_vertical_scrollbar',
+            'oci_bind_array_by_name',
+            'oci_bind_by_name',
+            'oci_cancel',
+            'oci_close',
+            'oci_commit',
+            'oci_connect',
+            'oci_define_by_name',
+            'oci_error',
+            'oci_execute',
+            'oci_fetch',
+            'oci_fetch_all',
+            'oci_fetch_array',
+            'oci_fetch_assoc',
+            'oci_fetch_object',
+            'oci_fetch_row',
+            'oci_field_is_null',
+            'oci_field_name',
+            'oci_field_precision',
+            'oci_field_scale',
+            'oci_field_size',
+            'oci_field_type',
+            'oci_field_type_raw',
+            'oci_free_cursor',
+            'oci_free_statement',
+            'oci_get_implicit_resultset',
+            'oci_new_collection',
+            'oci_new_connect',
+            'oci_new_cursor',
+            'oci_new_descriptor',
+            'oci_num_fields',
+            'oci_num_rows',
+            'oci_parse',
+            'oci_pconnect',
+            'oci_register_taf_callback',
+            'oci_result',
+            'oci_rollback',
+            'oci_server_version',
+            'oci_set_action',
+            'oci_set_client_identifier',
+            'oci_set_client_info',
+            'oci_set_module_name',
+            'oci_set_prefetch',
+            'oci_statement_type',
+            'oci_unregister_taf_callback',
+            'odbc_autocommit',
+            'odbc_close',
+            'odbc_columnprivileges',
+            'odbc_columns',
+            'odbc_commit',
+            'odbc_connect',
+            'odbc_cursor',
+            'odbc_data_source',
+            'odbc_do',
+            'odbc_error',
+            'odbc_errormsg',
+            'odbc_exec',
+            'odbc_execute',
+            'odbc_fetch_array',
+            'odbc_fetch_into',
+            'odbc_fetch_row',
+            'odbc_field_len',
+            'odbc_field_name',
+            'odbc_field_num',
+            'odbc_field_precision',
+            'odbc_field_scale',
+            'odbc_field_type',
+            'odbc_foreignkeys',
+            'odbc_free_result',
+            'odbc_gettypeinfo',
+            'odbc_next_result',
+            'odbc_num_fields',
+            'odbc_num_rows',
+            'odbc_pconnect',
+            'odbc_prepare',
+            'odbc_primarykeys',
+            'odbc_procedurecolumns',
+            'odbc_procedures',
+            'odbc_result',
+            'odbc_result_all',
+            'odbc_rollback',
+            'odbc_setoption',
+            'odbc_specialcolumns',
+            'odbc_statistics',
+            'odbc_tableprivileges',
+            'odbc_tables',
+            'openal_buffer_create',
+            'openal_buffer_data',
+            'openal_buffer_destroy',
+            'openal_buffer_get',
+            'openal_buffer_loadwav',
+            'openal_context_create',
+            'openal_context_current',
+            'openal_context_destroy',
+            'openal_context_process',
+            'openal_context_suspend',
+            'openal_device_close',
+            'openal_device_open',
+            'openal_source_create',
+            'openal_source_destroy',
+            'openal_source_get',
+            'openal_source_pause',
+            'openal_source_play',
+            'openal_source_rewind',
+            'openal_source_set',
+            'openal_source_stop',
+            'openal_stream',
+            'opendir',
+            'openssl_csr_new',
+            'openssl_dh_compute_key',
+            'openssl_free_key',
+            'openssl_pkey_export',
+            'openssl_pkey_free',
+            'openssl_pkey_get_details',
+            'openssl_spki_new',
+            'openssl_x509_free',
+            'pclose',
+            'pfsockopen',
+            'pg_affected_rows',
+            'pg_cancel_query',
+            'pg_client_encoding',
+            'pg_close',
+            'pg_connect_poll',
+            'pg_connection_busy',
+            'pg_connection_reset',
+            'pg_connection_status',
+            'pg_consume_input',
+            'pg_convert',
+            'pg_copy_from',
+            'pg_copy_to',
+            'pg_dbname',
+            'pg_delete',
+            'pg_end_copy',
+            'pg_escape_bytea',
+            'pg_escape_identifier',
+            'pg_escape_literal',
+            'pg_escape_string',
+            'pg_execute',
+            'pg_fetch_all',
+            'pg_fetch_all_columns',
+            'pg_fetch_array',
+            'pg_fetch_assoc',
+            'pg_fetch_row',
+            'pg_field_name',
+            'pg_field_num',
+            'pg_field_size',
+            'pg_field_table',
+            'pg_field_type',
+            'pg_field_type_oid',
+            'pg_flush',
+            'pg_free_result',
+            'pg_get_notify',
+            'pg_get_pid',
+            'pg_get_result',
+            'pg_host',
+            'pg_insert',
+            'pg_last_error',
+            'pg_last_notice',
+            'pg_last_oid',
+            'pg_lo_close',
+            'pg_lo_create',
+            'pg_lo_export',
+            'pg_lo_import',
+            'pg_lo_open',
+            'pg_lo_read',
+            'pg_lo_read_all',
+            'pg_lo_seek',
+            'pg_lo_tell',
+            'pg_lo_truncate',
+            'pg_lo_unlink',
+            'pg_lo_write',
+            'pg_meta_data',
+            'pg_num_fields',
+            'pg_num_rows',
+            'pg_options',
+            'pg_parameter_status',
+            'pg_ping',
+            'pg_port',
+            'pg_prepare',
+            'pg_put_line',
+            'pg_query',
+            'pg_query_params',
+            'pg_result_error',
+            'pg_result_error_field',
+            'pg_result_seek',
+            'pg_result_status',
+            'pg_select',
+            'pg_send_execute',
+            'pg_send_prepare',
+            'pg_send_query',
+            'pg_send_query_params',
+            'pg_set_client_encoding',
+            'pg_set_error_verbosity',
+            'pg_socket',
+            'pg_trace',
+            'pg_transaction_status',
+            'pg_tty',
+            'pg_untrace',
+            'pg_update',
+            'pg_version',
+            'php_user_filter::filter',
+            'proc_close',
+            'proc_get_status',
+            'proc_terminate',
+            'ps_add_bookmark',
+            'ps_add_launchlink',
+            'ps_add_locallink',
+            'ps_add_note',
+            'ps_add_pdflink',
+            'ps_add_weblink',
+            'ps_arc',
+            'ps_arcn',
+            'ps_begin_page',
+            'ps_begin_pattern',
+            'ps_begin_template',
+            'ps_circle',
+            'ps_clip',
+            'ps_close',
+            'ps_close_image',
+            'ps_closepath',
+            'ps_closepath_stroke',
+            'ps_continue_text',
+            'ps_curveto',
+            'ps_delete',
+            'ps_end_page',
+            'ps_end_pattern',
+            'ps_end_template',
+            'ps_fill',
+            'ps_fill_stroke',
+            'ps_findfont',
+            'ps_get_buffer',
+            'ps_get_parameter',
+            'ps_get_value',
+            'ps_hyphenate',
+            'ps_include_file',
+            'ps_lineto',
+            'ps_makespotcolor',
+            'ps_moveto',
+            'ps_new',
+            'ps_open_file',
+            'ps_open_image',
+            'ps_open_image_file',
+            'ps_open_memory_image',
+            'ps_place_image',
+            'ps_rect',
+            'ps_restore',
+            'ps_rotate',
+            'ps_save',
+            'ps_scale',
+            'ps_set_border_color',
+            'ps_set_border_dash',
+            'ps_set_border_style',
+            'ps_set_info',
+            'ps_set_parameter',
+            'ps_set_text_pos',
+            'ps_set_value',
+            'ps_setcolor',
+            'ps_setdash',
+            'ps_setflat',
+            'ps_setfont',
+            'ps_setgray',
+            'ps_setlinecap',
+            'ps_setlinejoin',
+            'ps_setlinewidth',
+            'ps_setmiterlimit',
+            'ps_setoverprintmode',
+            'ps_setpolydash',
+            'ps_shading',
+            'ps_shading_pattern',
+            'ps_shfill',
+            'ps_show',
+            'ps_show2',
+            'ps_show_boxed',
+            'ps_show_xy',
+            'ps_show_xy2',
+            'ps_string_geometry',
+            'ps_stringwidth',
+            'ps_stroke',
+            'ps_symbol',
+            'ps_symbol_name',
+            'ps_symbol_width',
+            'ps_translate',
+            'px_close',
+            'px_create_fp',
+            'px_date2string',
+            'px_delete',
+            'px_delete_record',
+            'px_get_field',
+            'px_get_info',
+            'px_get_parameter',
+            'px_get_record',
+            'px_get_schema',
+            'px_get_value',
+            'px_insert_record',
+            'px_new',
+            'px_numfields',
+            'px_numrecords',
+            'px_open_fp',
+            'px_put_record',
+            'px_retrieve_record',
+            'px_set_blob_file',
+            'px_set_parameter',
+            'px_set_tablename',
+            'px_set_targetencoding',
+            'px_set_value',
+            'px_timestamp2string',
+            'px_update_record',
+            'radius_acct_open',
+            'radius_add_server',
+            'radius_auth_open',
+            'radius_close',
+            'radius_config',
+            'radius_create_request',
+            'radius_demangle',
+            'radius_demangle_mppe_key',
+            'radius_get_attr',
+            'radius_put_addr',
+            'radius_put_attr',
+            'radius_put_int',
+            'radius_put_string',
+            'radius_put_vendor_addr',
+            'radius_put_vendor_attr',
+            'radius_put_vendor_int',
+            'radius_put_vendor_string',
+            'radius_request_authenticator',
+            'radius_salt_encrypt_attr',
+            'radius_send_request',
+            'radius_server_secret',
+            'radius_strerror',
+            'readdir',
+            'readfile',
+            'recode_file',
+            'rename',
+            'rewind',
+            'rewinddir',
+            'rmdir',
+            'rpm_close',
+            'rpm_get_tag',
+            'rpm_open',
+            'sapi_windows_vt100_support',
+            'scandir',
+            'sem_acquire',
+            'sem_get',
+            'sem_release',
+            'sem_remove',
+            'set_file_buffer',
+            'shm_attach',
+            'shm_detach',
+            'shm_get_var',
+            'shm_has_var',
+            'shm_put_var',
+            'shm_remove',
+            'shm_remove_var',
+            'shmop_close',
+            'shmop_delete',
+            'shmop_open',
+            'shmop_read',
+            'shmop_size',
+            'shmop_write',
+            'socket_accept',
+            'socket_addrinfo_bind',
+            'socket_addrinfo_connect',
+            'socket_addrinfo_explain',
+            'socket_bind',
+            'socket_clear_error',
+            'socket_close',
+            'socket_connect',
+            'socket_export_stream',
+            'socket_get_option',
+            'socket_get_status',
+            'socket_getopt',
+            'socket_getpeername',
+            'socket_getsockname',
+            'socket_import_stream',
+            'socket_last_error',
+            'socket_listen',
+            'socket_read',
+            'socket_recv',
+            'socket_recvfrom',
+            'socket_recvmsg',
+            'socket_send',
+            'socket_sendmsg',
+            'socket_sendto',
+            'socket_set_block',
+            'socket_set_blocking',
+            'socket_set_nonblock',
+            'socket_set_option',
+            'socket_set_timeout',
+            'socket_shutdown',
+            'socket_write',
+            'sqlite_close',
+            'sqlite_fetch_string',
+            'sqlite_has_more',
+            'sqlite_open',
+            'sqlite_popen',
+            'sqlsrv_begin_transaction',
+            'sqlsrv_cancel',
+            'sqlsrv_client_info',
+            'sqlsrv_close',
+            'sqlsrv_commit',
+            'sqlsrv_connect',
+            'sqlsrv_execute',
+            'sqlsrv_fetch',
+            'sqlsrv_fetch_array',
+            'sqlsrv_fetch_object',
+            'sqlsrv_field_metadata',
+            'sqlsrv_free_stmt',
+            'sqlsrv_get_field',
+            'sqlsrv_has_rows',
+            'sqlsrv_next_result',
+            'sqlsrv_num_fields',
+            'sqlsrv_num_rows',
+            'sqlsrv_prepare',
+            'sqlsrv_query',
+            'sqlsrv_rollback',
+            'sqlsrv_rows_affected',
+            'sqlsrv_send_stream_data',
+            'sqlsrv_server_info',
+            'ssh2_auth_agent',
+            'ssh2_auth_hostbased_file',
+            'ssh2_auth_none',
+            'ssh2_auth_password',
+            'ssh2_auth_pubkey_file',
+            'ssh2_disconnect',
+            'ssh2_exec',
+            'ssh2_fetch_stream',
+            'ssh2_fingerprint',
+            'ssh2_methods_negotiated',
+            'ssh2_publickey_add',
+            'ssh2_publickey_init',
+            'ssh2_publickey_list',
+            'ssh2_publickey_remove',
+            'ssh2_scp_recv',
+            'ssh2_scp_send',
+            'ssh2_sftp',
+            'ssh2_sftp_chmod',
+            'ssh2_sftp_lstat',
+            'ssh2_sftp_mkdir',
+            'ssh2_sftp_readlink',
+            'ssh2_sftp_realpath',
+            'ssh2_sftp_rename',
+            'ssh2_sftp_rmdir',
+            'ssh2_sftp_stat',
+            'ssh2_sftp_symlink',
+            'ssh2_sftp_unlink',
+            'ssh2_shell',
+            'ssh2_tunnel',
+            'stomp_connect',
+            'streamWrapper::stream_cast',
+            'stream_bucket_append',
+            'stream_bucket_make_writeable',
+            'stream_bucket_new',
+            'stream_bucket_prepend',
+            'stream_context_create',
+            'stream_context_get_default',
+            'stream_context_get_options',
+            'stream_context_get_params',
+            'stream_context_set_default',
+            'stream_context_set_params',
+            'stream_copy_to_stream',
+            'stream_encoding',
+            'stream_filter_append',
+            'stream_filter_prepend',
+            'stream_filter_remove',
+            'stream_get_contents',
+            'stream_get_line',
+            'stream_get_meta_data',
+            'stream_isatty',
+            'stream_set_blocking',
+            'stream_set_chunk_size',
+            'stream_set_read_buffer',
+            'stream_set_timeout',
+            'stream_set_write_buffer',
+            'stream_socket_accept',
+            'stream_socket_client',
+            'stream_socket_enable_crypto',
+            'stream_socket_get_name',
+            'stream_socket_recvfrom',
+            'stream_socket_sendto',
+            'stream_socket_server',
+            'stream_socket_shutdown',
+            'stream_supports_lock',
+            'svn_fs_abort_txn',
+            'svn_fs_apply_text',
+            'svn_fs_begin_txn2',
+            'svn_fs_change_node_prop',
+            'svn_fs_check_path',
+            'svn_fs_contents_changed',
+            'svn_fs_copy',
+            'svn_fs_delete',
+            'svn_fs_dir_entries',
+            'svn_fs_file_contents',
+            'svn_fs_file_length',
+            'svn_fs_is_dir',
+            'svn_fs_is_file',
+            'svn_fs_make_dir',
+            'svn_fs_make_file',
+            'svn_fs_node_created_rev',
+            'svn_fs_node_prop',
+            'svn_fs_props_changed',
+            'svn_fs_revision_prop',
+            'svn_fs_revision_root',
+            'svn_fs_txn_root',
+            'svn_fs_youngest_rev',
+            'svn_repos_create',
+            'svn_repos_fs',
+            'svn_repos_fs_begin_txn_for_commit',
+            'svn_repos_fs_commit_txn',
+            'svn_repos_open',
+            'sybase_affected_rows',
+            'sybase_close',
+            'sybase_connect',
+            'sybase_data_seek',
+            'sybase_fetch_array',
+            'sybase_fetch_assoc',
+            'sybase_fetch_field',
+            'sybase_fetch_object',
+            'sybase_fetch_row',
+            'sybase_field_seek',
+            'sybase_free_result',
+            'sybase_num_fields',
+            'sybase_num_rows',
+            'sybase_pconnect',
+            'sybase_query',
+            'sybase_result',
+            'sybase_select_db',
+            'sybase_set_message_handler',
+            'sybase_unbuffered_query',
+            'tmpfile',
+            'udm_add_search_limit',
+            'udm_alloc_agent',
+            'udm_alloc_agent_array',
+            'udm_cat_list',
+            'udm_cat_path',
+            'udm_check_charset',
+            'udm_clear_search_limits',
+            'udm_crc32',
+            'udm_errno',
+            'udm_error',
+            'udm_find',
+            'udm_free_agent',
+            'udm_free_res',
+            'udm_get_doc_count',
+            'udm_get_res_field',
+            'udm_get_res_param',
+            'udm_hash32',
+            'udm_load_ispell_data',
+            'udm_set_agent_param',
+            'unlink',
+            'vfprintf',
+            'w32api_init_dtype',
+            'wddx_add_vars',
+            'wddx_packet_end',
+            'wddx_packet_start',
+            'xml_get_current_byte_index',
+            'xml_get_current_column_number',
+            'xml_get_current_line_number',
+            'xml_get_error_code',
+            'xml_parse',
+            'xml_parse_into_struct',
+            'xml_parser_create',
+            'xml_parser_create_ns',
+            'xml_parser_free',
+            'xml_parser_get_option',
+            'xml_parser_set_option',
+            'xml_set_character_data_handler',
+            'xml_set_default_handler',
+            'xml_set_element_handler',
+            'xml_set_end_namespace_decl_handler',
+            'xml_set_external_entity_ref_handler',
+            'xml_set_notation_decl_handler',
+            'xml_set_object',
+            'xml_set_processing_instruction_handler',
+            'xml_set_start_namespace_decl_handler',
+            'xml_set_unparsed_entity_decl_handler',
+            'xmlrpc_server_add_introspection_data',
+            'xmlrpc_server_call_method',
+            'xmlrpc_server_create',
+            'xmlrpc_server_destroy',
+            'xmlrpc_server_register_introspection_callback',
+            'xmlrpc_server_register_method',
+            'xmlwriter_end_attribute',
+            'xmlwriter_end_cdata',
+            'xmlwriter_end_comment',
+            'xmlwriter_end_document',
+            'xmlwriter_end_dtd',
+            'xmlwriter_end_dtd_attlist',
+            'xmlwriter_end_dtd_element',
+            'xmlwriter_end_dtd_entity',
+            'xmlwriter_end_element',
+            'xmlwriter_end_pi',
+            'xmlwriter_flush',
+            'xmlwriter_full_end_element',
+            'xmlwriter_open_memory',
+            'xmlwriter_open_uri',
+            'xmlwriter_output_memory',
+            'xmlwriter_set_indent',
+            'xmlwriter_set_indent_string',
+            'xmlwriter_start_attribute',
+            'xmlwriter_start_attribute_ns',
+            'xmlwriter_start_cdata',
+            'xmlwriter_start_comment',
+            'xmlwriter_start_document',
+            'xmlwriter_start_dtd',
+            'xmlwriter_start_dtd_attlist',
+            'xmlwriter_start_dtd_element',
+            'xmlwriter_start_dtd_entity',
+            'xmlwriter_start_element',
+            'xmlwriter_start_element_ns',
+            'xmlwriter_start_pi',
+            'xmlwriter_text',
+            'xmlwriter_write_attribute',
+            'xmlwriter_write_attribute_ns',
+            'xmlwriter_write_cdata',
+            'xmlwriter_write_comment',
+            'xmlwriter_write_dtd',
+            'xmlwriter_write_dtd_attlist',
+            'xmlwriter_write_dtd_element',
+            'xmlwriter_write_dtd_entity',
+            'xmlwriter_write_element',
+            'xmlwriter_write_element_ns',
+            'xmlwriter_write_pi',
+            'xmlwriter_write_raw',
+            'xslt_create',
+            'yaz_addinfo',
+            'yaz_ccl_conf',
+            'yaz_ccl_parse',
+            'yaz_close',
+            'yaz_database',
+            'yaz_element',
+            'yaz_errno',
+            'yaz_error',
+            'yaz_es',
+            'yaz_es_result',
+            'yaz_get_option',
+            'yaz_hits',
+            'yaz_itemorder',
+            'yaz_present',
+            'yaz_range',
+            'yaz_record',
+            'yaz_scan',
+            'yaz_scan_result',
+            'yaz_schema',
+            'yaz_search',
+            'yaz_sort',
+            'yaz_syntax',
+            'zip_close',
+            'zip_entry_close',
+            'zip_entry_compressedsize',
+            'zip_entry_compressionmethod',
+            'zip_entry_filesize',
+            'zip_entry_name',
+            'zip_entry_open',
+            'zip_entry_read',
+            'zip_open',
+            'zip_read',
+        ];
+    }
+}
diff --git a/vendor/sebastian/type/ChangeLog.md b/vendor/sebastian/type/ChangeLog.md
new file mode 100644
index 0000000000000000000000000000000000000000..a8aff5534bf6c352c621b1a89b9116a78a4ab5d3
--- /dev/null
+++ b/vendor/sebastian/type/ChangeLog.md
@@ -0,0 +1,104 @@
+# ChangeLog
+
+All notable changes are documented in this file using the [Keep a CHANGELOG](http://keepachangelog.com/) principles.
+
+## [2.3.1] - 2020-10-26
+
+### Fixed
+
+* `SebastianBergmann\Type\Exception` now correctly extends `\Throwable`
+
+## [2.3.0] - 2020-10-06
+
+### Added
+
+* [#14](https://github.com/sebastianbergmann/type/issues/14): Support for `static` return type that is introduced in PHP 8
+
+## [2.2.2] - 2020-09-28
+
+### Changed
+
+* Changed PHP version constraint in `composer.json` from `^7.3 || ^8.0` to `>=7.3`
+
+## [2.2.1] - 2020-07-05
+
+### Fixed
+
+* Fixed handling of `mixed` type in `ReflectionMapper::fromMethodReturnType()`
+
+## [2.2.0] - 2020-07-05
+
+### Added
+
+* Added `MixedType` object for representing PHP 8's `mixed` type
+
+## [2.1.1] - 2020-06-26
+
+### Added
+
+* This component is now supported on PHP 8
+
+## [2.1.0] - 2020-06-01
+
+### Added
+
+* Added `UnionType` object for representing PHP 8's Union Types
+* Added `ReflectionMapper::fromMethodReturnType()` for mapping `\ReflectionMethod::getReturnType()` to a `Type` object
+* Added `Type::name()` for retrieving the name of a type
+* Added `Type::asString()` for retrieving a textual representation of a type
+
+### Changed
+
+* Deprecated `Type::getReturnTypeDeclaration()` (use `Type::asString()` instead and prefix its result with `': '`)
+* Deprecated `TypeName::getNamespaceName()` (use `TypeName::namespaceName()` instead)
+* Deprecated `TypeName::getSimpleName()` (use `TypeName::simpleName()` instead)
+* Deprecated `TypeName::getQualifiedName()` (use `TypeName::qualifiedName()` instead)
+
+## [2.0.0] - 2020-02-07
+
+### Removed
+
+* This component is no longer supported on PHP 7.2
+
+## [1.1.3] - 2019-07-02
+
+### Fixed
+
+* Fixed class name comparison in `ObjectType` to be case-insensitive
+
+## [1.1.2] - 2019-06-19
+
+### Fixed
+
+* Fixed handling of `object` type
+
+## [1.1.1] - 2019-06-08
+
+### Fixed
+
+* Fixed autoloading of `callback_function.php` fixture file
+
+## [1.1.0] - 2019-06-07
+
+### Added
+
+* Added support for `callable` type
+* Added support for `iterable` type
+
+## [1.0.0] - 2019-06-06
+
+* Initial release based on [code contributed by Michel Hartmann to PHPUnit](https://github.com/sebastianbergmann/phpunit/pull/3673)
+
+[2.3.1]: https://github.com/sebastianbergmann/type/compare/2.3.0...2.3.1
+[2.3.0]: https://github.com/sebastianbergmann/type/compare/2.2.2...2.3.0
+[2.2.2]: https://github.com/sebastianbergmann/type/compare/2.2.1...2.2.2
+[2.2.1]: https://github.com/sebastianbergmann/type/compare/2.2.0...2.2.1
+[2.2.0]: https://github.com/sebastianbergmann/type/compare/2.1.1...2.2.0
+[2.1.1]: https://github.com/sebastianbergmann/type/compare/2.1.0...2.1.1
+[2.1.0]: https://github.com/sebastianbergmann/type/compare/2.0.0...2.1.0
+[2.0.0]: https://github.com/sebastianbergmann/type/compare/1.1.3...2.0.0
+[1.1.3]: https://github.com/sebastianbergmann/type/compare/1.1.2...1.1.3
+[1.1.2]: https://github.com/sebastianbergmann/type/compare/1.1.1...1.1.2
+[1.1.1]: https://github.com/sebastianbergmann/type/compare/1.1.0...1.1.1
+[1.1.0]: https://github.com/sebastianbergmann/type/compare/1.0.0...1.1.0
+[1.0.0]: https://github.com/sebastianbergmann/type/compare/ff74aa41746bd8d10e931843ebf37d42da513ede...1.0.0
diff --git a/vendor/sebastian/type/LICENSE b/vendor/sebastian/type/LICENSE
new file mode 100644
index 0000000000000000000000000000000000000000..b840591a9265d83ecaf81f847953e495c21609b4
--- /dev/null
+++ b/vendor/sebastian/type/LICENSE
@@ -0,0 +1,33 @@
+sebastian/type
+
+Copyright (c) 2019-2020, Sebastian Bergmann <sebastian@phpunit.de>.
+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 Sebastian Bergmann nor the names of his
+   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/sebastian/type/README.md b/vendor/sebastian/type/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..1036ce7a7054279e9bce063454f859453017bc31
--- /dev/null
+++ b/vendor/sebastian/type/README.md
@@ -0,0 +1,20 @@
+# sebastian/type
+
+[![CI Status](https://github.com/sebastianbergmann/type/workflows/CI/badge.svg)](https://github.com/sebastianbergmann/type/actions)
+[![Type Coverage](https://shepherd.dev/github/sebastianbergmann/type/coverage.svg)](https://shepherd.dev/github/sebastianbergmann/type)
+
+Collection of value objects that represent the types of the PHP type system.
+
+## Installation
+
+You can add this library as a local, per-project dependency to your project using [Composer](https://getcomposer.org/):
+
+```
+composer require sebastian/type
+```
+
+If you only need this library during development, for instance to run your project's test suite, then you should add it as a development-time dependency:
+
+```
+composer require --dev sebastian/type
+```
diff --git a/vendor/sebastian/type/composer.json b/vendor/sebastian/type/composer.json
new file mode 100644
index 0000000000000000000000000000000000000000..b02d8e92aeb48f9229256fc7a4d64d16f78f438f
--- /dev/null
+++ b/vendor/sebastian/type/composer.json
@@ -0,0 +1,49 @@
+{
+    "name": "sebastian/type",
+    "description": "Collection of value objects that represent the types of the PHP type system",
+    "type": "library",
+    "homepage": "https://github.com/sebastianbergmann/type",
+    "license": "BSD-3-Clause",
+    "authors": [
+        {
+            "name": "Sebastian Bergmann",
+            "email": "sebastian@phpunit.de",
+            "role": "lead"
+        }
+    ],
+    "support": {
+        "issues": "https://github.com/sebastianbergmann/type/issues"
+    },
+    "prefer-stable": true,
+    "require": {
+        "php": ">=7.3"
+    },
+    "require-dev": {
+        "phpunit/phpunit": "^9.3"
+    },
+    "config": {
+        "platform": {
+            "php": "7.3.0"
+        },
+        "optimize-autoloader": true,
+        "sort-packages": true
+    },
+    "autoload": {
+        "classmap": [
+            "src/"
+        ]
+    },
+    "autoload-dev": {
+        "classmap": [
+            "tests/_fixture"
+        ],
+        "files": [
+            "tests/_fixture/callback_function.php"
+        ]
+    },
+    "extra": {
+        "branch-alias": {
+            "dev-master": "2.3-dev"
+        }
+    }
+}
diff --git a/vendor/sebastian/type/src/CallableType.php b/vendor/sebastian/type/src/CallableType.php
new file mode 100644
index 0000000000000000000000000000000000000000..026762eaf270e743ee018c56a38615892daa67f7
--- /dev/null
+++ b/vendor/sebastian/type/src/CallableType.php
@@ -0,0 +1,197 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of sebastian/type.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\Type;
+
+use function assert;
+use function class_exists;
+use function count;
+use function explode;
+use function function_exists;
+use function is_array;
+use function is_object;
+use function is_string;
+use function strpos;
+use Closure;
+use ReflectionClass;
+use ReflectionException;
+use ReflectionObject;
+
+final class CallableType extends Type
+{
+    /**
+     * @var bool
+     */
+    private $allowsNull;
+
+    public function __construct(bool $nullable)
+    {
+        $this->allowsNull = $nullable;
+    }
+
+    /**
+     * @throws RuntimeException
+     */
+    public function isAssignable(Type $other): bool
+    {
+        if ($this->allowsNull && $other instanceof NullType) {
+            return true;
+        }
+
+        if ($other instanceof self) {
+            return true;
+        }
+
+        if ($other instanceof ObjectType) {
+            if ($this->isClosure($other)) {
+                return true;
+            }
+
+            if ($this->hasInvokeMethod($other)) {
+                return true;
+            }
+        }
+
+        if ($other instanceof SimpleType) {
+            if ($this->isFunction($other)) {
+                return true;
+            }
+
+            if ($this->isClassCallback($other)) {
+                return true;
+            }
+
+            if ($this->isObjectCallback($other)) {
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+    public function name(): string
+    {
+        return 'callable';
+    }
+
+    public function allowsNull(): bool
+    {
+        return $this->allowsNull;
+    }
+
+    private function isClosure(ObjectType $type): bool
+    {
+        return !$type->className()->isNamespaced() && $type->className()->simpleName() === Closure::class;
+    }
+
+    /**
+     * @throws RuntimeException
+     */
+    private function hasInvokeMethod(ObjectType $type): bool
+    {
+        $className = $type->className()->qualifiedName();
+        assert(class_exists($className));
+
+        try {
+            $class = new ReflectionClass($className);
+            // @codeCoverageIgnoreStart
+        } catch (ReflectionException $e) {
+            throw new RuntimeException(
+                $e->getMessage(),
+                (int) $e->getCode(),
+                $e
+            );
+            // @codeCoverageIgnoreEnd
+        }
+
+        if ($class->hasMethod('__invoke')) {
+            return true;
+        }
+
+        return false;
+    }
+
+    private function isFunction(SimpleType $type): bool
+    {
+        if (!is_string($type->value())) {
+            return false;
+        }
+
+        return function_exists($type->value());
+    }
+
+    private function isObjectCallback(SimpleType $type): bool
+    {
+        if (!is_array($type->value())) {
+            return false;
+        }
+
+        if (count($type->value()) !== 2) {
+            return false;
+        }
+
+        if (!is_object($type->value()[0]) || !is_string($type->value()[1])) {
+            return false;
+        }
+
+        [$object, $methodName] = $type->value();
+
+        return (new ReflectionObject($object))->hasMethod($methodName);
+    }
+
+    private function isClassCallback(SimpleType $type): bool
+    {
+        if (!is_string($type->value()) && !is_array($type->value())) {
+            return false;
+        }
+
+        if (is_string($type->value())) {
+            if (strpos($type->value(), '::') === false) {
+                return false;
+            }
+
+            [$className, $methodName] = explode('::', $type->value());
+        }
+
+        if (is_array($type->value())) {
+            if (count($type->value()) !== 2) {
+                return false;
+            }
+
+            if (!is_string($type->value()[0]) || !is_string($type->value()[1])) {
+                return false;
+            }
+
+            [$className, $methodName] = $type->value();
+        }
+
+        assert(isset($className) && is_string($className) && class_exists($className));
+        assert(isset($methodName) && is_string($methodName));
+
+        try {
+            $class = new ReflectionClass($className);
+
+            if ($class->hasMethod($methodName)) {
+                $method = $class->getMethod($methodName);
+
+                return $method->isPublic() && $method->isStatic();
+            }
+            // @codeCoverageIgnoreStart
+        } catch (ReflectionException $e) {
+            throw new RuntimeException(
+                $e->getMessage(),
+                (int) $e->getCode(),
+                $e
+            );
+            // @codeCoverageIgnoreEnd
+        }
+
+        return false;
+    }
+}
diff --git a/vendor/sebastian/type/src/GenericObjectType.php b/vendor/sebastian/type/src/GenericObjectType.php
new file mode 100644
index 0000000000000000000000000000000000000000..6871008bdbd6bbcfc37364f8837b797d6b8d2143
--- /dev/null
+++ b/vendor/sebastian/type/src/GenericObjectType.php
@@ -0,0 +1,46 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of sebastian/type.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\Type;
+
+final class GenericObjectType extends Type
+{
+    /**
+     * @var bool
+     */
+    private $allowsNull;
+
+    public function __construct(bool $nullable)
+    {
+        $this->allowsNull = $nullable;
+    }
+
+    public function isAssignable(Type $other): bool
+    {
+        if ($this->allowsNull && $other instanceof NullType) {
+            return true;
+        }
+
+        if (!$other instanceof ObjectType) {
+            return false;
+        }
+
+        return true;
+    }
+
+    public function name(): string
+    {
+        return 'object';
+    }
+
+    public function allowsNull(): bool
+    {
+        return $this->allowsNull;
+    }
+}
diff --git a/vendor/sebastian/type/src/IterableType.php b/vendor/sebastian/type/src/IterableType.php
new file mode 100644
index 0000000000000000000000000000000000000000..c5bc6627b73895ac142f918037852d4ac3704d2d
--- /dev/null
+++ b/vendor/sebastian/type/src/IterableType.php
@@ -0,0 +1,76 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of sebastian/type.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\Type;
+
+use function assert;
+use function class_exists;
+use function is_iterable;
+use ReflectionClass;
+use ReflectionException;
+
+final class IterableType extends Type
+{
+    /**
+     * @var bool
+     */
+    private $allowsNull;
+
+    public function __construct(bool $nullable)
+    {
+        $this->allowsNull = $nullable;
+    }
+
+    /**
+     * @throws RuntimeException
+     */
+    public function isAssignable(Type $other): bool
+    {
+        if ($this->allowsNull && $other instanceof NullType) {
+            return true;
+        }
+
+        if ($other instanceof self) {
+            return true;
+        }
+
+        if ($other instanceof SimpleType) {
+            return is_iterable($other->value());
+        }
+
+        if ($other instanceof ObjectType) {
+            $className = $other->className()->qualifiedName();
+            assert(class_exists($className));
+
+            try {
+                return (new ReflectionClass($className))->isIterable();
+                // @codeCoverageIgnoreStart
+            } catch (ReflectionException $e) {
+                throw new RuntimeException(
+                    $e->getMessage(),
+                    (int) $e->getCode(),
+                    $e
+                );
+                // @codeCoverageIgnoreEnd
+            }
+        }
+
+        return false;
+    }
+
+    public function name(): string
+    {
+        return 'iterable';
+    }
+
+    public function allowsNull(): bool
+    {
+        return $this->allowsNull;
+    }
+}
diff --git a/vendor/sebastian/type/src/MixedType.php b/vendor/sebastian/type/src/MixedType.php
new file mode 100644
index 0000000000000000000000000000000000000000..7ad9191da3b7b13da3ccbfaf4a2772716f31eade
--- /dev/null
+++ b/vendor/sebastian/type/src/MixedType.php
@@ -0,0 +1,33 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of sebastian/type.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\Type;
+
+final class MixedType extends Type
+{
+    public function isAssignable(Type $other): bool
+    {
+        return !$other instanceof VoidType;
+    }
+
+    public function asString(): string
+    {
+        return 'mixed';
+    }
+
+    public function name(): string
+    {
+        return 'mixed';
+    }
+
+    public function allowsNull(): bool
+    {
+        return true;
+    }
+}
diff --git a/vendor/sebastian/type/src/NullType.php b/vendor/sebastian/type/src/NullType.php
new file mode 100644
index 0000000000000000000000000000000000000000..8481fceb8e8ff3f257f81a0e65c708650ad44c1b
--- /dev/null
+++ b/vendor/sebastian/type/src/NullType.php
@@ -0,0 +1,43 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of sebastian/type.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\Type;
+
+final class NullType extends Type
+{
+    public function isAssignable(Type $other): bool
+    {
+        return !($other instanceof VoidType);
+    }
+
+    public function name(): string
+    {
+        return 'null';
+    }
+
+    public function asString(): string
+    {
+        return 'null';
+    }
+
+    /**
+     * @deprecated
+     *
+     * @codeCoverageIgnore
+     */
+    public function getReturnTypeDeclaration(): string
+    {
+        return '';
+    }
+
+    public function allowsNull(): bool
+    {
+        return true;
+    }
+}
diff --git a/vendor/sebastian/type/src/ObjectType.php b/vendor/sebastian/type/src/ObjectType.php
new file mode 100644
index 0000000000000000000000000000000000000000..c71273cb441f31dc1387217ec20a14f48c6ca65e
--- /dev/null
+++ b/vendor/sebastian/type/src/ObjectType.php
@@ -0,0 +1,66 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of sebastian/type.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\Type;
+
+use function is_subclass_of;
+use function strcasecmp;
+
+final class ObjectType extends Type
+{
+    /**
+     * @var TypeName
+     */
+    private $className;
+
+    /**
+     * @var bool
+     */
+    private $allowsNull;
+
+    public function __construct(TypeName $className, bool $allowsNull)
+    {
+        $this->className  = $className;
+        $this->allowsNull = $allowsNull;
+    }
+
+    public function isAssignable(Type $other): bool
+    {
+        if ($this->allowsNull && $other instanceof NullType) {
+            return true;
+        }
+
+        if ($other instanceof self) {
+            if (0 === strcasecmp($this->className->qualifiedName(), $other->className->qualifiedName())) {
+                return true;
+            }
+
+            if (is_subclass_of($other->className->qualifiedName(), $this->className->qualifiedName(), true)) {
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+    public function name(): string
+    {
+        return $this->className->qualifiedName();
+    }
+
+    public function allowsNull(): bool
+    {
+        return $this->allowsNull;
+    }
+
+    public function className(): TypeName
+    {
+        return $this->className;
+    }
+}
diff --git a/vendor/sebastian/type/src/ReflectionMapper.php b/vendor/sebastian/type/src/ReflectionMapper.php
new file mode 100644
index 0000000000000000000000000000000000000000..c3dc9b9a43c8e1f4e5dc09dde053cede0d41a102
--- /dev/null
+++ b/vendor/sebastian/type/src/ReflectionMapper.php
@@ -0,0 +1,96 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of sebastian/type.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\Type;
+
+use function assert;
+use function sprintf;
+use ReflectionMethod;
+use ReflectionNamedType;
+use ReflectionUnionType;
+
+final class ReflectionMapper
+{
+    public function fromMethodReturnType(ReflectionMethod $method): Type
+    {
+        if (!$method->hasReturnType()) {
+            return new UnknownType;
+        }
+
+        $returnType = $method->getReturnType();
+
+        assert($returnType instanceof ReflectionNamedType || $returnType instanceof ReflectionUnionType);
+
+        if ($returnType instanceof ReflectionNamedType) {
+            if ($returnType->getName() === 'self') {
+                return ObjectType::fromName(
+                    $method->getDeclaringClass()->getName(),
+                    $returnType->allowsNull()
+                );
+            }
+
+            if ($returnType->getName() === 'static') {
+                return new StaticType(
+                    TypeName::fromReflection($method->getDeclaringClass()),
+                    $returnType->allowsNull()
+                );
+            }
+
+            if ($returnType->getName() === 'mixed') {
+                return new MixedType;
+            }
+
+            if ($returnType->getName() === 'parent') {
+                $parentClass = $method->getDeclaringClass()->getParentClass();
+
+                // @codeCoverageIgnoreStart
+                if ($parentClass === false) {
+                    throw new RuntimeException(
+                        sprintf(
+                            '%s::%s() has a "parent" return type declaration but %s does not have a parent class',
+                            $method->getDeclaringClass()->getName(),
+                            $method->getName(),
+                            $method->getDeclaringClass()->getName()
+                        )
+                    );
+                }
+                // @codeCoverageIgnoreEnd
+
+                return ObjectType::fromName(
+                    $parentClass->getName(),
+                    $returnType->allowsNull()
+                );
+            }
+
+            return Type::fromName(
+                $returnType->getName(),
+                $returnType->allowsNull()
+            );
+        }
+
+        assert($returnType instanceof ReflectionUnionType);
+
+        $types = [];
+
+        foreach ($returnType->getTypes() as $type) {
+            assert($type instanceof ReflectionNamedType);
+
+            if ($type->getName() === 'self') {
+                $types[] = ObjectType::fromName(
+                    $method->getDeclaringClass()->getName(),
+                    false
+                );
+            } else {
+                $types[] = Type::fromName($type->getName(), false);
+            }
+        }
+
+        return new UnionType(...$types);
+    }
+}
diff --git a/vendor/sebastian/type/src/SimpleType.php b/vendor/sebastian/type/src/SimpleType.php
new file mode 100644
index 0000000000000000000000000000000000000000..dbb4f0c4e4ccd1a573e32f03b765e121be67c4a7
--- /dev/null
+++ b/vendor/sebastian/type/src/SimpleType.php
@@ -0,0 +1,88 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of sebastian/type.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\Type;
+
+use function strtolower;
+
+final class SimpleType extends Type
+{
+    /**
+     * @var string
+     */
+    private $name;
+
+    /**
+     * @var bool
+     */
+    private $allowsNull;
+
+    /**
+     * @var mixed
+     */
+    private $value;
+
+    public function __construct(string $name, bool $nullable, $value = null)
+    {
+        $this->name       = $this->normalize($name);
+        $this->allowsNull = $nullable;
+        $this->value      = $value;
+    }
+
+    public function isAssignable(Type $other): bool
+    {
+        if ($this->allowsNull && $other instanceof NullType) {
+            return true;
+        }
+
+        if ($other instanceof self) {
+            return $this->name === $other->name;
+        }
+
+        return false;
+    }
+
+    public function name(): string
+    {
+        return $this->name;
+    }
+
+    public function allowsNull(): bool
+    {
+        return $this->allowsNull;
+    }
+
+    public function value()
+    {
+        return $this->value;
+    }
+
+    private function normalize(string $name): string
+    {
+        $name = strtolower($name);
+
+        switch ($name) {
+            case 'boolean':
+                return 'bool';
+
+            case 'real':
+            case 'double':
+                return 'float';
+
+            case 'integer':
+                return 'int';
+
+            case '[]':
+                return 'array';
+
+            default:
+                return $name;
+        }
+    }
+}
diff --git a/vendor/sebastian/type/src/StaticType.php b/vendor/sebastian/type/src/StaticType.php
new file mode 100644
index 0000000000000000000000000000000000000000..6833094d157fec6cce28a568209b170b68b55bcf
--- /dev/null
+++ b/vendor/sebastian/type/src/StaticType.php
@@ -0,0 +1,60 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of sebastian/type.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\Type;
+
+final class StaticType extends Type
+{
+    /**
+     * @var TypeName
+     */
+    private $className;
+
+    /**
+     * @var bool
+     */
+    private $allowsNull;
+
+    public function __construct(TypeName $className, bool $allowsNull)
+    {
+        $this->className  = $className;
+        $this->allowsNull = $allowsNull;
+    }
+
+    public function isAssignable(Type $other): bool
+    {
+        if ($this->allowsNull && $other instanceof NullType) {
+            return true;
+        }
+
+        if (!$other instanceof ObjectType) {
+            return false;
+        }
+
+        if (0 === strcasecmp($this->className->qualifiedName(), $other->className()->qualifiedName())) {
+            return true;
+        }
+
+        if (is_subclass_of($other->className()->qualifiedName(), $this->className->qualifiedName(), true)) {
+            return true;
+        }
+
+        return false;
+    }
+
+    public function name(): string
+    {
+        return 'static';
+    }
+
+    public function allowsNull(): bool
+    {
+        return $this->allowsNull;
+    }
+}
diff --git a/vendor/sebastian/type/src/Type.php b/vendor/sebastian/type/src/Type.php
new file mode 100644
index 0000000000000000000000000000000000000000..cf64923b44e8839a28d801d474153f341e10a4ff
--- /dev/null
+++ b/vendor/sebastian/type/src/Type.php
@@ -0,0 +1,94 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of sebastian/type.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\Type;
+
+use function get_class;
+use function gettype;
+use function strtolower;
+
+abstract class Type
+{
+    public static function fromValue($value, bool $allowsNull): self
+    {
+        $typeName = gettype($value);
+
+        if ($typeName === 'object') {
+            return new ObjectType(TypeName::fromQualifiedName(get_class($value)), $allowsNull);
+        }
+
+        $type = self::fromName($typeName, $allowsNull);
+
+        if ($type instanceof SimpleType) {
+            $type = new SimpleType($typeName, $allowsNull, $value);
+        }
+
+        return $type;
+    }
+
+    public static function fromName(string $typeName, bool $allowsNull): self
+    {
+        switch (strtolower($typeName)) {
+            case 'callable':
+                return new CallableType($allowsNull);
+
+            case 'iterable':
+                return new IterableType($allowsNull);
+
+            case 'null':
+                return new NullType;
+
+            case 'object':
+                return new GenericObjectType($allowsNull);
+
+            case 'unknown type':
+                return new UnknownType;
+
+            case 'void':
+                return new VoidType;
+
+            case 'array':
+            case 'bool':
+            case 'boolean':
+            case 'double':
+            case 'float':
+            case 'int':
+            case 'integer':
+            case 'real':
+            case 'resource':
+            case 'resource (closed)':
+            case 'string':
+                return new SimpleType($typeName, $allowsNull);
+
+            default:
+                return new ObjectType(TypeName::fromQualifiedName($typeName), $allowsNull);
+        }
+    }
+
+    public function asString(): string
+    {
+        return ($this->allowsNull() ? '?' : '') . $this->name();
+    }
+
+    /**
+     * @deprecated
+     *
+     * @codeCoverageIgnore
+     */
+    public function getReturnTypeDeclaration(): string
+    {
+        return ': ' . $this->asString();
+    }
+
+    abstract public function isAssignable(Type $other): bool;
+
+    abstract public function name(): string;
+
+    abstract public function allowsNull(): bool;
+}
diff --git a/vendor/sebastian/type/src/TypeName.php b/vendor/sebastian/type/src/TypeName.php
new file mode 100644
index 0000000000000000000000000000000000000000..b076e89e036244b7adab9020582fcabefcdf2f9b
--- /dev/null
+++ b/vendor/sebastian/type/src/TypeName.php
@@ -0,0 +1,113 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of sebastian/type.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\Type;
+
+use function array_pop;
+use function explode;
+use function implode;
+use function substr;
+use ReflectionClass;
+
+final class TypeName
+{
+    /**
+     * @var ?string
+     */
+    private $namespaceName;
+
+    /**
+     * @var string
+     */
+    private $simpleName;
+
+    public static function fromQualifiedName(string $fullClassName): self
+    {
+        if ($fullClassName[0] === '\\') {
+            $fullClassName = substr($fullClassName, 1);
+        }
+
+        $classNameParts = explode('\\', $fullClassName);
+
+        $simpleName    = array_pop($classNameParts);
+        $namespaceName = implode('\\', $classNameParts);
+
+        return new self($namespaceName, $simpleName);
+    }
+
+    public static function fromReflection(ReflectionClass $type): self
+    {
+        return new self(
+            $type->getNamespaceName(),
+            $type->getShortName()
+        );
+    }
+
+    public function __construct(?string $namespaceName, string $simpleName)
+    {
+        if ($namespaceName === '') {
+            $namespaceName = null;
+        }
+
+        $this->namespaceName = $namespaceName;
+        $this->simpleName    = $simpleName;
+    }
+
+    public function namespaceName(): ?string
+    {
+        return $this->namespaceName;
+    }
+
+    public function simpleName(): string
+    {
+        return $this->simpleName;
+    }
+
+    public function qualifiedName(): string
+    {
+        return $this->namespaceName === null
+             ? $this->simpleName
+             : $this->namespaceName . '\\' . $this->simpleName;
+    }
+
+    /**
+     * @deprecated Use namespaceName() instead
+     *
+     * @codeCoverageIgnore
+     */
+    public function getNamespaceName(): ?string
+    {
+        return $this->namespaceName();
+    }
+
+    /**
+     * @deprecated Use simpleName() instead
+     *
+     * @codeCoverageIgnore
+     */
+    public function getSimpleName(): string
+    {
+        return $this->simpleName();
+    }
+
+    /**
+     * @deprecated Use qualifiedName() instead
+     *
+     * @codeCoverageIgnore
+     */
+    public function getQualifiedName(): string
+    {
+        return $this->qualifiedName();
+    }
+
+    public function isNamespaced(): bool
+    {
+        return $this->namespaceName !== null;
+    }
+}
diff --git a/vendor/sebastian/type/src/UnionType.php b/vendor/sebastian/type/src/UnionType.php
new file mode 100644
index 0000000000000000000000000000000000000000..10c4a49b533bea3c51e50bb01637471964596e97
--- /dev/null
+++ b/vendor/sebastian/type/src/UnionType.php
@@ -0,0 +1,115 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of sebastian/type.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\Type;
+
+use function count;
+use function implode;
+use function sort;
+
+final class UnionType extends Type
+{
+    /**
+     * @psalm-var list<Type>
+     */
+    private $types;
+
+    /**
+     * @throws RuntimeException
+     */
+    public function __construct(Type ...$types)
+    {
+        $this->ensureMinimumOfTwoTypes(...$types);
+        $this->ensureOnlyValidTypes(...$types);
+
+        $this->types = $types;
+    }
+
+    public function isAssignable(Type $other): bool
+    {
+        foreach ($this->types as $type) {
+            if ($type->isAssignable($other)) {
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+    public function asString(): string
+    {
+        return $this->name();
+    }
+
+    /**
+     * @deprecated
+     *
+     * @codeCoverageIgnore
+     */
+    public function getReturnTypeDeclaration(): string
+    {
+        return ': ' . $this->name();
+    }
+
+    public function name(): string
+    {
+        $types = [];
+
+        foreach ($this->types as $type) {
+            $types[] = $type->name();
+        }
+
+        sort($types);
+
+        return implode('|', $types);
+    }
+
+    public function allowsNull(): bool
+    {
+        foreach ($this->types as $type) {
+            if ($type instanceof NullType) {
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+    /**
+     * @throws RuntimeException
+     */
+    private function ensureMinimumOfTwoTypes(Type ...$types): void
+    {
+        if (count($types) < 2) {
+            throw new RuntimeException(
+                'A union type must be composed of at least two types'
+            );
+        }
+    }
+
+    /**
+     * @throws RuntimeException
+     */
+    private function ensureOnlyValidTypes(Type ...$types): void
+    {
+        foreach ($types as $type) {
+            if ($type instanceof UnknownType) {
+                throw new RuntimeException(
+                    'A union type must not be composed of an unknown type'
+                );
+            }
+
+            if ($type instanceof VoidType) {
+                throw new RuntimeException(
+                    'A union type must not be composed of a void type'
+                );
+            }
+        }
+    }
+}
diff --git a/vendor/sebastian/type/src/UnknownType.php b/vendor/sebastian/type/src/UnknownType.php
new file mode 100644
index 0000000000000000000000000000000000000000..dde4c6788a743b88fd8d21fea0f04f51f5a81f11
--- /dev/null
+++ b/vendor/sebastian/type/src/UnknownType.php
@@ -0,0 +1,43 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of sebastian/type.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\Type;
+
+final class UnknownType extends Type
+{
+    public function isAssignable(Type $other): bool
+    {
+        return true;
+    }
+
+    public function name(): string
+    {
+        return 'unknown type';
+    }
+
+    public function asString(): string
+    {
+        return '';
+    }
+
+    /**
+     * @deprecated
+     *
+     * @codeCoverageIgnore
+     */
+    public function getReturnTypeDeclaration(): string
+    {
+        return '';
+    }
+
+    public function allowsNull(): bool
+    {
+        return true;
+    }
+}
diff --git a/vendor/sebastian/type/src/VoidType.php b/vendor/sebastian/type/src/VoidType.php
new file mode 100644
index 0000000000000000000000000000000000000000..18c0175648f7b799ebc376262194cd9ead89b410
--- /dev/null
+++ b/vendor/sebastian/type/src/VoidType.php
@@ -0,0 +1,28 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of sebastian/type.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\Type;
+
+final class VoidType extends Type
+{
+    public function isAssignable(Type $other): bool
+    {
+        return $other instanceof self;
+    }
+
+    public function name(): string
+    {
+        return 'void';
+    }
+
+    public function allowsNull(): bool
+    {
+        return false;
+    }
+}
diff --git a/vendor/sebastian/type/src/exception/Exception.php b/vendor/sebastian/type/src/exception/Exception.php
new file mode 100644
index 0000000000000000000000000000000000000000..e0e7ee57957f04a7c221d747ac212af19070eec6
--- /dev/null
+++ b/vendor/sebastian/type/src/exception/Exception.php
@@ -0,0 +1,16 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of sebastian/type.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\Type;
+
+use Throwable;
+
+interface Exception extends Throwable
+{
+}
diff --git a/vendor/sebastian/type/src/exception/RuntimeException.php b/vendor/sebastian/type/src/exception/RuntimeException.php
new file mode 100644
index 0000000000000000000000000000000000000000..4dfea6a6a81df47aca3560f3a2e817c1ded5fa44
--- /dev/null
+++ b/vendor/sebastian/type/src/exception/RuntimeException.php
@@ -0,0 +1,14 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of sebastian/type.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace SebastianBergmann\Type;
+
+final class RuntimeException extends \RuntimeException implements Exception
+{
+}
diff --git a/vendor/sebastian/version/.gitattributes b/vendor/sebastian/version/.gitattributes
new file mode 100644
index 0000000000000000000000000000000000000000..54b8953058f176c15c8ce499b4cd95477f6e6056
--- /dev/null
+++ b/vendor/sebastian/version/.gitattributes
@@ -0,0 +1,4 @@
+/.github        export-ignore
+/.php_cs.dist   export-ignore
+
+*.php diff=php
diff --git a/vendor/sebastian/version/.gitignore b/vendor/sebastian/version/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..ff5ec9a0ef01f1cc52473bac689c8c0ba8201cf2
--- /dev/null
+++ b/vendor/sebastian/version/.gitignore
@@ -0,0 +1,2 @@
+/.php_cs.cache
+/.idea
diff --git a/vendor/sebastian/version/ChangeLog.md b/vendor/sebastian/version/ChangeLog.md
new file mode 100644
index 0000000000000000000000000000000000000000..10fd9a1a5635cbe075cc5bcac6a3463145500531
--- /dev/null
+++ b/vendor/sebastian/version/ChangeLog.md
@@ -0,0 +1,25 @@
+# ChangeLog
+
+All notable changes are documented in this file using the [Keep a CHANGELOG](https://keepachangelog.com/) principles.
+
+## [3.0.2] - 2020-09-28
+
+### Changed
+
+* Changed PHP version constraint in `composer.json` from `^7.3 || ^8.0` to `>=7.3`
+
+## [3.0.1] - 2020-06-26
+
+### Added
+
+* This component is now supported on PHP 8
+
+## [3.0.0] - 2020-01-21
+
+### Removed
+
+* This component is no longer supported on PHP 7.1 and PHP 7.2
+
+[3.0.2]: https://github.com/sebastianbergmann/version/compare/3.0.1...3.0.2
+[3.0.1]: https://github.com/sebastianbergmann/version/compare/3.0.0...3.0.1
+[3.0.0]: https://github.com/sebastianbergmann/version/compare/2.0.1...3.0.0
diff --git a/vendor/sebastian/version/LICENSE b/vendor/sebastian/version/LICENSE
new file mode 100644
index 0000000000000000000000000000000000000000..aa6bca299062bba623b19d7b6c09eba7973acd89
--- /dev/null
+++ b/vendor/sebastian/version/LICENSE
@@ -0,0 +1,33 @@
+Version
+
+Copyright (c) 2013-2020, Sebastian Bergmann <sebastian@phpunit.de>.
+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 Sebastian Bergmann nor the names of his
+   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/sebastian/version/README.md b/vendor/sebastian/version/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..2864c81269785d331c1a0c2b3d87f413dc6f51e7
--- /dev/null
+++ b/vendor/sebastian/version/README.md
@@ -0,0 +1,43 @@
+# Version
+
+**Version** is a library that helps with managing the version number of Git-hosted PHP projects.
+
+## Installation
+
+You can add this library as a local, per-project dependency to your project using [Composer](https://getcomposer.org/):
+
+    composer require sebastian/version
+
+If you only need this library during development, for instance to run your project's test suite, then you should add it as a development-time dependency:
+
+    composer require --dev sebastian/version
+
+## Usage
+
+The constructor of the `SebastianBergmann\Version` class expects two parameters:
+
+* `$release` is the version number of the latest release (`X.Y.Z`, for instance) or the name of the release series (`X.Y`) when no release has been made from that branch / for that release series yet.
+* `$path` is the path to the directory (or a subdirectory thereof) where the sourcecode of the project can be found. Simply passing `__DIR__` here usually suffices.
+
+Apart from the constructor, the `SebastianBergmann\Version` class has a single public method: `getVersion()`.
+
+Here is a contrived example that shows the basic usage:
+
+    <?php
+    $version = new SebastianBergmann\Version(
+      '3.7.10', '/usr/local/src/phpunit'
+    );
+
+    var_dump($version->getVersion());
+    ?>
+
+    string(18) "3.7.10-17-g00f3408"
+
+When a new release is prepared, the string that is passed to the constructor as the first argument needs to be updated.
+
+### How SebastianBergmann\Version::getVersion() works
+
+* If `$path` is not (part of) a Git repository and `$release` is in `X.Y.Z` format then `$release` is returned as-is.
+* If `$path` is not (part of) a Git repository and `$release` is in `X.Y` format then `$release` is returned suffixed with `-dev`.
+* If `$path` is (part of) a Git repository and `$release` is in `X.Y.Z` format then the output of `git describe --tags` is returned as-is.
+* If `$path` is (part of) a Git repository and `$release` is in `X.Y` format then a string is returned that begins with `X.Y` and ends with information from `git describe --tags`.
diff --git a/vendor/sebastian/version/composer.json b/vendor/sebastian/version/composer.json
new file mode 100644
index 0000000000000000000000000000000000000000..e76dbf4121f2a82d49e41bd445c16f19e5971ebb
--- /dev/null
+++ b/vendor/sebastian/version/composer.json
@@ -0,0 +1,37 @@
+{
+    "name": "sebastian/version",
+    "description": "Library that helps with managing the version number of Git-hosted PHP projects",
+    "homepage": "https://github.com/sebastianbergmann/version",
+    "license": "BSD-3-Clause",
+    "authors": [
+        {
+            "name": "Sebastian Bergmann",
+            "email": "sebastian@phpunit.de",
+            "role": "lead"
+        }
+    ],
+    "support": {
+        "issues": "https://github.com/sebastianbergmann/version/issues"
+    },
+    "config": {
+        "platform": {
+            "php": "7.3.0"
+        },
+        "optimize-autoloader": true,
+        "sort-packages": true
+    },
+    "prefer-stable": true,
+    "require": {
+        "php": ">=7.3"
+    },
+    "autoload": {
+        "classmap": [
+            "src/"
+        ]
+    },
+    "extra": {
+        "branch-alias": {
+            "dev-master": "3.0-dev"
+        }
+    }
+}
diff --git a/vendor/sebastian/version/src/Version.php b/vendor/sebastian/version/src/Version.php
new file mode 100644
index 0000000000000000000000000000000000000000..53ae7894e498457c1e78906ac816a91c086b6c20
--- /dev/null
+++ b/vendor/sebastian/version/src/Version.php
@@ -0,0 +1,97 @@
+<?php
+/*
+ * This file is part of sebastian/version.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace SebastianBergmann;
+
+final class Version
+{
+    /**
+     * @var string
+     */
+    private $path;
+
+    /**
+     * @var string
+     */
+    private $release;
+
+    /**
+     * @var string
+     */
+    private $version;
+
+    public function __construct(string $release, string $path)
+    {
+        $this->release = $release;
+        $this->path    = $path;
+    }
+
+    public function getVersion(): string
+    {
+        if ($this->version === null) {
+            if (\substr_count($this->release, '.') + 1 === 3) {
+                $this->version = $this->release;
+            } else {
+                $this->version = $this->release . '-dev';
+            }
+
+            $git = $this->getGitInformation($this->path);
+
+            if ($git) {
+                if (\substr_count($this->release, '.') + 1 === 3) {
+                    $this->version = $git;
+                } else {
+                    $git = \explode('-', $git);
+
+                    $this->version = $this->release . '-' . \end($git);
+                }
+            }
+        }
+
+        return $this->version;
+    }
+
+    /**
+     * @return bool|string
+     */
+    private function getGitInformation(string $path)
+    {
+        if (!\is_dir($path . DIRECTORY_SEPARATOR . '.git')) {
+            return false;
+        }
+
+        $process = \proc_open(
+            'git describe --tags',
+            [
+                1 => ['pipe', 'w'],
+                2 => ['pipe', 'w'],
+            ],
+            $pipes,
+            $path
+        );
+
+        if (!\is_resource($process)) {
+            return false;
+        }
+
+        $result = \trim(\stream_get_contents($pipes[1]));
+
+        \fclose($pipes[1]);
+        \fclose($pipes[2]);
+
+        $returnCode = \proc_close($process);
+
+        if ($returnCode !== 0) {
+            return false;
+        }
+
+        return $result;
+    }
+}
diff --git a/vendor/setasign/fpdi-tcpdf/LICENSE.txt b/vendor/setasign/fpdi-tcpdf/LICENSE.txt
index 7e7585002f954be628bb31dfaa6fc9576b798357..633a59b9f402558f1b4cb1a3cb04e1bb5c53d9d5 100644
--- a/vendor/setasign/fpdi-tcpdf/LICENSE.txt
+++ b/vendor/setasign/fpdi-tcpdf/LICENSE.txt
@@ -1,6 +1,6 @@
 The MIT License (MIT)
 
-Copyright (c) 2017 Setasign - Jan Slabon, https://www.setasign.com
+Copyright (c) 2020 Setasign GmbH & Co. KG, https://www.setasign.com
 
 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal
@@ -18,4 +18,4 @@ 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.
\ No newline at end of file
+THE SOFTWARE.
diff --git a/vendor/setasign/fpdi-tcpdf/README.md b/vendor/setasign/fpdi-tcpdf/README.md
index b64c3ca67d2ef7c2263ee5fb320a26287b2647ee..d6e9d42786de1b2724cc817268150d7f1d4c70ee 100644
--- a/vendor/setasign/fpdi-tcpdf/README.md
+++ b/vendor/setasign/fpdi-tcpdf/README.md
@@ -4,7 +4,7 @@ A kind of metadata package for Composer with fixed dependencies for the latest v
 ## Installation with [Composer](https://packagist.org/packages/setasign/fpdi-tcpdf)
 
 ```bash
-$ composer require setasign/fpdi-tcpdf:2.1
+$ composer require setasign/fpdi-tcpdf:2.3
 ```
 
 or you can include the following in your composer.json file:
@@ -12,7 +12,7 @@ or you can include the following in your composer.json file:
 ```json
 {
     "require": {
-        "setasign/fpdi-tcpdf": "^2.1"
+        "setasign/fpdi-tcpdf": "^2.3"
     }
 }
 ```
diff --git a/vendor/setasign/fpdi-tcpdf/composer.json b/vendor/setasign/fpdi-tcpdf/composer.json
index 52b32517614ab7f38ddd0e24e00018b1d9480c7d..d3f1b3d35301a50442ef44e208b6cf0610f0096a 100644
--- a/vendor/setasign/fpdi-tcpdf/composer.json
+++ b/vendor/setasign/fpdi-tcpdf/composer.json
@@ -13,7 +13,7 @@
         }
     ],
     "require": {
-        "tecnickcom/tcpdf": "^6.2",
-        "setasign/fpdi": "^2.1"
+        "tecnickcom/tcpdf": "^6.3.5",
+        "setasign/fpdi": "^2.3"
     }
 }
diff --git a/vendor/setasign/fpdi/LICENSE.txt b/vendor/setasign/fpdi/LICENSE.txt
index 7e7585002f954be628bb31dfaa6fc9576b798357..45672fab8540ee50b8e6c9778c293db3760b53dd 100644
--- a/vendor/setasign/fpdi/LICENSE.txt
+++ b/vendor/setasign/fpdi/LICENSE.txt
@@ -1,6 +1,6 @@
 The MIT License (MIT)
 
-Copyright (c) 2017 Setasign - Jan Slabon, https://www.setasign.com
+Copyright (c) 2020 Setasign GmbH & Co. KG, https://www.setasign.com
 
 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal
diff --git a/vendor/setasign/fpdi/README.md b/vendor/setasign/fpdi/README.md
index 42856df3e52d6ae9b9428d69adf83bae69a2f0ac..082122ff968dd6efa58302a14b85b1659335ae44 100644
--- a/vendor/setasign/fpdi/README.md
+++ b/vendor/setasign/fpdi/README.md
@@ -18,75 +18,39 @@ FPDI can also be used as an extension for [TCPDF](https://github.com/tecnickcom/
 
 ## Installation with [Composer](https://packagist.org/packages/setasign/fpdi)
 
-Because FPDI can be used with FPDF, TCPDF or tFPDF we didn't added a fixed dependency in the main
-composer.json file but we added metadata packages for 
-[FPDF](https://github.com/Setasign/FPDI-FPDF), 
-[TCPDF](https://github.com/Setasign/FPDI-TCPDF) and
-[tFPDF](https://github.com/Setasign/FPDI-tFPDF).
-
-### Evaluate Dependencies Automatically
-
-For FPDF add following [package](https://github.com/Setasign/FPDI-FPDF) to your composer.json:
-```json
-{
-    "require": {
-        "setasign/fpdi-fpdf": "^2.0"
-    }
-}
-```
-
-For TCPDF add following [package](https://github.com/Setasign/FPDI-TCPDF) to your composer.json:
-```json
-{
-    "require": {
-        "setasign/fpdi-tcpdf": "^2.0"
-    }
-}
-```
-
-For tFPDF add following [package](https://github.com/Setasign/FPDI-tFPDF) to your composer.json:
-```json
-{
-    "require": {
-        "setasign/fpdi-tfpdf": "^2.1"
-    }
-}
-```
-
-### Manual Dependencies
-
-If you don't want to use the metadata packages, it is up to you to add the dependencies to your
-composer.json file.
+Because FPDI can be used with FPDF, TCPDF or tFPDF we haven't added a fixed dependency in the main
+composer.json file. You need to add the dependency to the PDF generation library of your choice
+yourself.
 
 To use FPDI with FPDF include following in your composer.json file:
 
 ```json
 {
     "require": {
-        "setasign/fpdf": "^1.8",
+        "setasign/fpdf": "1.8.*",
         "setasign/fpdi": "^2.0"
     }
 }
 ```
 
-If you want to use TCPDF, your have to update your composer.json respectively to:
+If you want to use TCPDF, you have to update your composer.json to:
 
 ```json
 {
     "require": {
-        "tecnickcom/tcpdf": "^6.2",
+        "tecnickcom/tcpdf": "6.2.*",
         "setasign/fpdi": "^2.0"
     }
 }
 ```
 
-If you want to use tFPDF, your have to update your composer.json respectively to:
+If you want to use tFPDF, you have to update your composer.json to:
 
 ```json
 {
     "require": {
-        "tecnickcom/tfpdf": "1.25",
-        "setasign/fpdi": "^2.1"
+        "setasign/tfpdf": "1.31.*",
+        "setasign/fpdi": "^2.3"
     }
 }
 ```
diff --git a/vendor/setasign/fpdi/SECURITY.md b/vendor/setasign/fpdi/SECURITY.md
new file mode 100644
index 0000000000000000000000000000000000000000..da9c516dd744b6c88dd8c91f58f7bcf8f7e8341b
--- /dev/null
+++ b/vendor/setasign/fpdi/SECURITY.md
@@ -0,0 +1,5 @@
+## Security contact information
+
+To report a security vulnerability, please use the
+[Tidelift security contact](https://tidelift.com/security).
+Tidelift will coordinate the fix and disclosure.
diff --git a/vendor/setasign/fpdi/composer.json b/vendor/setasign/fpdi/composer.json
index 58f79315dd98f3ae08ab88240a4450ca6355a230..72ea24e06dc0e2b436c4cc1a8c68c1034f25d55a 100644
--- a/vendor/setasign/fpdi/composer.json
+++ b/vendor/setasign/fpdi/composer.json
@@ -18,6 +18,9 @@
         "php": "^5.6 || ^7.0",
         "ext-zlib": "*"
     },
+    "conflict": {
+        "setasign/tfpdf": "<1.31"
+    },
     "authors": [
         {
             "name": "Jan Slabon",
@@ -31,16 +34,13 @@
         }
     ],
     "suggest": {
-        "setasign/fpdf": "FPDI will extend this class but as it is also possible to use TCPDF or tFPDF as an alternative. There's no fixed dependency configured.",
-        "setasign/fpdi-fpdf": "Use this package to automatically evaluate dependencies to FPDF.",
-        "setasign/fpdi-tcpdf": "Use this package to automatically evaluate dependencies to TCPDF.",
-        "setasign/fpdi-tfpdf": "Use this package to automatically evaluate dependencies to tFPDF."
+        "setasign/fpdf": "FPDI will extend this class but as it is also possible to use TCPDF or tFPDF as an alternative. There's no fixed dependency configured."
     },
     "require-dev": {
         "phpunit/phpunit": "~5.7",
         "setasign/fpdf": "~1.8",
         "tecnickcom/tcpdf": "~6.2",
-        "setasign/tfpdf": "1.25"
+        "setasign/tfpdf": "1.31"
     },
     "autoload-dev": {
         "psr-4": {
diff --git a/vendor/setasign/fpdi/src/FpdfTpl.php b/vendor/setasign/fpdi/src/FpdfTpl.php
index 86672e59370b228b5b52cf82f9c64001fd0705de..d70583d4f2cea1b2e5fb9300aebca1fc5fcf6f68 100644
--- a/vendor/setasign/fpdi/src/FpdfTpl.php
+++ b/vendor/setasign/fpdi/src/FpdfTpl.php
@@ -3,9 +3,9 @@
  * This file is part of FPDI
  *
  * @package   setasign\Fpdi
- * @copyright Copyright (c) 2018 Setasign - Jan Slabon (https://www.setasign.com)
+ * @copyright Copyright (c) 2020 Setasign GmbH & Co. KG (https://www.setasign.com)
  * @license   http://opensource.org/licenses/mit-license The MIT License
-  */
+ */
 
 namespace setasign\Fpdi;
 
diff --git a/vendor/setasign/fpdi/src/FpdfTplTrait.php b/vendor/setasign/fpdi/src/FpdfTplTrait.php
index 11796b1f5ccff76673892c4f65a7aea085d91e50..10f9d5cc8461bc00560f89972f12f364b96cbeca 100644
--- a/vendor/setasign/fpdi/src/FpdfTplTrait.php
+++ b/vendor/setasign/fpdi/src/FpdfTplTrait.php
@@ -3,9 +3,9 @@
  * This file is part of FPDI
  *
  * @package   setasign\Fpdi
- * @copyright Copyright (c) 2018 Setasign - Jan Slabon (https://www.setasign.com)
+ * @copyright Copyright (c) 2020 Setasign GmbH & Co. KG (https://www.setasign.com)
  * @license   http://opensource.org/licenses/mit-license The MIT License
-  */
+ */
 
 namespace setasign\Fpdi;
 
@@ -86,8 +86,8 @@ trait FpdfTplTrait
     /**
      * Draws a template onto the page or another template.
      *
-     * Omit one of the size parameters (width, height) to calculate the other one automatically in view to the aspect
-     * ratio.
+     * Give only one of the size parameters (width, height) to calculate the other one automatically in view to the
+     * aspect ratio.
      *
      * @param mixed $tpl The template id
      * @param array|float|int $x The abscissa of upper-left corner. Alternatively you could use an assoc array
@@ -141,8 +141,8 @@ trait FpdfTplTrait
     /**
      * Get the size of a template.
      *
-     * Omit one of the size parameters (width, height) to calculate the other one automatically in view to the aspect
-     * ratio.
+     * Give only one of the size parameters (width, height) to calculate the other one automatically in view to the
+     * aspect ratio.
      *
      * @param mixed $tpl The template id
      * @param float|int|null $width The width.
diff --git a/vendor/setasign/fpdi/src/Fpdi.php b/vendor/setasign/fpdi/src/Fpdi.php
index 1a39c95afaee67d8781056175b0a7671fdb85c46..3db4b55a8b52f6d867f6009179021f2a2b9b5509 100644
--- a/vendor/setasign/fpdi/src/Fpdi.php
+++ b/vendor/setasign/fpdi/src/Fpdi.php
@@ -3,9 +3,9 @@
  * This file is part of FPDI
  *
  * @package   setasign\Fpdi
- * @copyright Copyright (c) 2018 Setasign - Jan Slabon (https://www.setasign.com)
+ * @copyright Copyright (c) 2020 Setasign GmbH & Co. KG (https://www.setasign.com)
  * @license   http://opensource.org/licenses/mit-license The MIT License
-  */
+ */
 
 namespace setasign\Fpdi;
 
@@ -30,13 +30,19 @@ class Fpdi extends FpdfTpl
      *
      * @string
      */
-    const VERSION = '2.1.1';
+    const VERSION = '2.3.1';
+
+    protected function _enddoc()
+    {
+        parent::_enddoc();
+        $this->cleanUp();
+    }
 
     /**
      * Draws an imported page or a template onto the page or another template.
      *
-     * Omit one of the size parameters (width, height) to calculate the other one automatically in view to the aspect
-     * ratio.
+     * Give only one of the size parameters (width, height) to calculate the other one automatically in view to the
+     * aspect ratio.
      *
      * @param mixed $tpl The template id
      * @param float|int|array $x The abscissa of upper-left corner. Alternatively you could use an assoc array
@@ -64,8 +70,8 @@ class Fpdi extends FpdfTpl
     /**
      * Get the size of an imported page or template.
      *
-     * Omit one of the size parameters (width, height) to calculate the other one automatically in view to the aspect
-     * ratio.
+     * Give only one of the size parameters (width, height) to calculate the other one automatically in view to the
+     * aspect ratio.
      *
      * @param mixed $tpl The template id
      * @param float|int|null $width The width.
diff --git a/vendor/setasign/fpdi/src/FpdiException.php b/vendor/setasign/fpdi/src/FpdiException.php
index e9522f53bfd10200a222b70847dc2cd4a0586f53..dcd52c9b59b558076060f8cc03df9588c0ba343f 100644
--- a/vendor/setasign/fpdi/src/FpdiException.php
+++ b/vendor/setasign/fpdi/src/FpdiException.php
@@ -3,9 +3,9 @@
  * This file is part of FPDI
  *
  * @package   setasign\Fpdi
- * @copyright Copyright (c) 2018 Setasign - Jan Slabon (https://www.setasign.com)
+ * @copyright Copyright (c) 2020 Setasign GmbH & Co. KG (https://www.setasign.com)
  * @license   http://opensource.org/licenses/mit-license The MIT License
-  */
+ */
 
 namespace setasign\Fpdi;
 
diff --git a/vendor/setasign/fpdi/src/FpdiTrait.php b/vendor/setasign/fpdi/src/FpdiTrait.php
index f5702e550d1ff78d3d9953f38f637b9761b24f3c..86c1e80251ae554686eafd6c114e792ba3a41d65 100644
--- a/vendor/setasign/fpdi/src/FpdiTrait.php
+++ b/vendor/setasign/fpdi/src/FpdiTrait.php
@@ -3,9 +3,9 @@
  * This file is part of FPDI
  *
  * @package   setasign\Fpdi
- * @copyright Copyright (c) 2018 Setasign - Jan Slabon (https://www.setasign.com)
+ * @copyright Copyright (c) 2020 Setasign GmbH & Co. KG (https://www.setasign.com)
  * @license   http://opensource.org/licenses/mit-license The MIT License
-  */
+ */
 
 namespace setasign\Fpdi;
 
@@ -53,6 +53,13 @@ trait FpdiTrait
      */
     protected $readers = [];
 
+    /**
+     * Instances created internally.
+     *
+     * @var array
+     */
+    protected $createdReaders = [];
+
     /**
      * The current reader id.
      *
@@ -81,6 +88,25 @@ trait FpdiTrait
      */
     protected $objectsToCopy = [];
 
+    /**
+     * Release resources and file handles.
+     *
+     * This method is called internally when the document is created successfully. By default it only cleans up
+     * stream reader instances which were created internally.
+     *
+     * @param bool $allReaders
+     */
+    public function cleanUp($allReaders = false)
+    {
+        $readers = $allReaders ? array_keys($this->readers) : $this->createdReaders;
+        foreach ($readers as $id) {
+            $this->readers[$id]->getParser()->getStreamReader()->cleanUp();
+            unset($this->readers[$id]);
+        }
+
+        $this->createdReaders= [];
+    }
+
     /**
      * Set the minimal PDF version.
      *
@@ -144,6 +170,7 @@ trait FpdiTrait
             $streamReader = new StreamReader($file);
         } elseif (\is_string($file)) {
             $streamReader = StreamReader::createByFile($file);
+            $this->createdReaders[] = $id;
         } else {
             $streamReader = $file;
         }
@@ -358,8 +385,8 @@ trait FpdiTrait
     /**
      * Draws an imported page onto the page.
      *
-     * Omit one of the size parameters (width, height) to calculate the other one automatically in view to the aspect
-     * ratio.
+     * Give only one of the size parameters (width, height) to calculate the other one automatically in view to the
+     * aspect ratio.
      *
      * @param mixed $pageId The page id
      * @param float|int|array $x The abscissa of upper-left corner. Alternatively you could use an assoc array
@@ -413,8 +440,8 @@ trait FpdiTrait
     /**
      * Get the size of an imported page.
      *
-     * Omit one of the size parameters (width, height) to calculate the other one automatically in view to the aspect
-     * ratio.
+     * Give only one of the size parameters (width, height) to calculate the other one automatically in view to the
+     * aspect ratio.
      *
      * @param mixed $tpl The template id
      * @param float|int|null $width The width.
diff --git a/vendor/setasign/fpdi/src/PdfParser/CrossReference/AbstractReader.php b/vendor/setasign/fpdi/src/PdfParser/CrossReference/AbstractReader.php
index 4bd6a16fa82c56d5b8fb0d6a23ab8b3045a4f06b..d314c6de2dff30a255d2cc354dd72db5d0376106 100644
--- a/vendor/setasign/fpdi/src/PdfParser/CrossReference/AbstractReader.php
+++ b/vendor/setasign/fpdi/src/PdfParser/CrossReference/AbstractReader.php
@@ -3,9 +3,9 @@
  * This file is part of FPDI
  *
  * @package   setasign\Fpdi
- * @copyright Copyright (c) 2018 Setasign - Jan Slabon (https://www.setasign.com)
+ * @copyright Copyright (c) 2020 Setasign GmbH & Co. KG (https://www.setasign.com)
  * @license   http://opensource.org/licenses/mit-license The MIT License
-  */
+ */
 
 namespace setasign\Fpdi\PdfParser\CrossReference;
 
diff --git a/vendor/setasign/fpdi/src/PdfParser/CrossReference/CrossReference.php b/vendor/setasign/fpdi/src/PdfParser/CrossReference/CrossReference.php
index 620411962cad2e269136aee233aea3381a42e17a..fe1ed71a19987b2030ad8898bc3c30cfd16f9d98 100644
--- a/vendor/setasign/fpdi/src/PdfParser/CrossReference/CrossReference.php
+++ b/vendor/setasign/fpdi/src/PdfParser/CrossReference/CrossReference.php
@@ -3,9 +3,9 @@
  * This file is part of FPDI
  *
  * @package   setasign\Fpdi
- * @copyright Copyright (c) 2018 Setasign - Jan Slabon (https://www.setasign.com)
+ * @copyright Copyright (c) 2020 Setasign GmbH & Co. KG (https://www.setasign.com)
  * @license   http://opensource.org/licenses/mit-license The MIT License
-  */
+ */
 
 namespace setasign\Fpdi\PdfParser\CrossReference;
 
@@ -64,7 +64,18 @@ class CrossReference
         $reader = null;
         /** @noinspection TypeUnsafeComparisonInspection */
         while ($offset != false) { // By doing an unsafe comparsion we ignore faulty references to byte offset 0
-            $reader = $this->readXref($offset + $this->fileHeaderOffset);
+            try {
+                $reader = $this->readXref($offset + $this->fileHeaderOffset);
+            } catch (CrossReferenceException $e) {
+                // sometimes the file header offset is part of the byte offsets, so let's retry by resetting it to zero.
+                if ($e->getCode() === CrossReferenceException::INVALID_DATA && $this->fileHeaderOffset !== 0) {
+                    $this->fileHeaderOffset = 0;
+                    $reader = $this->readXref($offset + $this->fileHeaderOffset);
+                } else {
+                    throw $e;
+                }
+            }
+
             $trailer = $reader->getTrailer();
             $this->checkForEncryption($trailer);
             $this->readers[] = $reader;
@@ -224,8 +235,16 @@ class CrossReference
         }
 
         if ($initValue instanceof PdfIndirectObject) {
-            // check for encryption
-            $stream = PdfStream::ensure($initValue->value);
+            try {
+                $stream = PdfStream::ensure($initValue->value);
+
+            } catch (PdfTypeException $e) {
+                throw new CrossReferenceException(
+                    'Invalid object type at xref reference offset.',
+                    CrossReferenceException::INVALID_DATA,
+                    $e
+                );
+            }
 
             $type = PdfDictionary::get($stream->value, 'Type');
             if ($type->value !== 'XRef') {
diff --git a/vendor/setasign/fpdi/src/PdfParser/CrossReference/CrossReferenceException.php b/vendor/setasign/fpdi/src/PdfParser/CrossReference/CrossReferenceException.php
index faffdcb990b5ca4f6c7df5f301500024bb09d9f4..ff8f11f2e22dc2da73b34897e2876f2e698361dd 100644
--- a/vendor/setasign/fpdi/src/PdfParser/CrossReference/CrossReferenceException.php
+++ b/vendor/setasign/fpdi/src/PdfParser/CrossReference/CrossReferenceException.php
@@ -3,9 +3,9 @@
  * This file is part of FPDI
  *
  * @package   setasign\Fpdi
- * @copyright Copyright (c) 2018 Setasign - Jan Slabon (https://www.setasign.com)
+ * @copyright Copyright (c) 2020 Setasign GmbH & Co. KG (https://www.setasign.com)
  * @license   http://opensource.org/licenses/mit-license The MIT License
-  */
+ */
 
 namespace setasign\Fpdi\PdfParser\CrossReference;
 
diff --git a/vendor/setasign/fpdi/src/PdfParser/CrossReference/FixedReader.php b/vendor/setasign/fpdi/src/PdfParser/CrossReference/FixedReader.php
index b77bcbbcb6670e132e9120d928aa6eff9e273e16..0faec1a8c8bddda55518d26bf941915811d23d0b 100644
--- a/vendor/setasign/fpdi/src/PdfParser/CrossReference/FixedReader.php
+++ b/vendor/setasign/fpdi/src/PdfParser/CrossReference/FixedReader.php
@@ -3,9 +3,9 @@
  * This file is part of FPDI
  *
  * @package   setasign\Fpdi
- * @copyright Copyright (c) 2018 Setasign - Jan Slabon (https://www.setasign.com)
+ * @copyright Copyright (c) 2020 Setasign GmbH & Co. KG (https://www.setasign.com)
  * @license   http://opensource.org/licenses/mit-license The MIT License
-  */
+ */
 
 namespace setasign\Fpdi\PdfParser\CrossReference;
 
diff --git a/vendor/setasign/fpdi/src/PdfParser/CrossReference/LineReader.php b/vendor/setasign/fpdi/src/PdfParser/CrossReference/LineReader.php
index 6e9939c96190aa81533c94d8b4ee94d70721d97a..7b4a129b0b09e36cdfa25fac0abb679b2cdb8d12 100644
--- a/vendor/setasign/fpdi/src/PdfParser/CrossReference/LineReader.php
+++ b/vendor/setasign/fpdi/src/PdfParser/CrossReference/LineReader.php
@@ -3,9 +3,9 @@
  * This file is part of FPDI
  *
  * @package   setasign\Fpdi
- * @copyright Copyright (c) 2018 Setasign - Jan Slabon (https://www.setasign.com)
+ * @copyright Copyright (c) 2020 Setasign GmbH & Co. KG (https://www.setasign.com)
  * @license   http://opensource.org/licenses/mit-license The MIT License
-  */
+ */
 
 namespace setasign\Fpdi\PdfParser\CrossReference;
 
diff --git a/vendor/setasign/fpdi/src/PdfParser/CrossReference/ReaderInterface.php b/vendor/setasign/fpdi/src/PdfParser/CrossReference/ReaderInterface.php
index ca2ef8fde1807a18440c43348f34fc4443a60e47..9a99b0020e367d4ed288225117496ccc5daf045e 100644
--- a/vendor/setasign/fpdi/src/PdfParser/CrossReference/ReaderInterface.php
+++ b/vendor/setasign/fpdi/src/PdfParser/CrossReference/ReaderInterface.php
@@ -3,9 +3,9 @@
  * This file is part of FPDI
  *
  * @package   setasign\Fpdi
- * @copyright Copyright (c) 2018 Setasign - Jan Slabon (https://www.setasign.com)
+ * @copyright Copyright (c) 2020 Setasign GmbH & Co. KG (https://www.setasign.com)
  * @license   http://opensource.org/licenses/mit-license The MIT License
-  */
+ */
 
 namespace setasign\Fpdi\PdfParser\CrossReference;
 
diff --git a/vendor/setasign/fpdi/src/PdfParser/Filter/Ascii85.php b/vendor/setasign/fpdi/src/PdfParser/Filter/Ascii85.php
index 74a11fcb66bfa567cdcd6607e3dfbca2e5a5fff5..eeb0698c2d7c206f781716d78a765062346eedb7 100644
--- a/vendor/setasign/fpdi/src/PdfParser/Filter/Ascii85.php
+++ b/vendor/setasign/fpdi/src/PdfParser/Filter/Ascii85.php
@@ -3,9 +3,9 @@
  * This file is part of FPDI
  *
  * @package   setasign\Fpdi
- * @copyright Copyright (c) 2018 Setasign - Jan Slabon (https://www.setasign.com)
+ * @copyright Copyright (c) 2020 Setasign GmbH & Co. KG (https://www.setasign.com)
  * @license   http://opensource.org/licenses/mit-license The MIT License
-  */
+ */
 
 namespace setasign\Fpdi\PdfParser\Filter;
 
@@ -29,6 +29,8 @@ class Ascii85 implements FilterInterface
         $state = 0;
         $chn = null;
 
+        $data = \preg_replace('/\s/', '', $data);
+
         $l = \strlen($data);
 
         /** @noinspection ForeachInvariantsInspection */
@@ -44,13 +46,12 @@ class Ascii85 implements FilterInterface
             if ($ch === 126 && isset($data[$k + 1]) && (\ord($data[$k + 1]) & 0xFF) === 62) {
                 break;
             }
-            if (\preg_match('/^\s$/', \chr($ch))) {
-                continue;
-            }
+
             if ($ch === 122 /* z */ && $state === 0) {
                 $out .= \chr(0) . \chr(0) . \chr(0) . \chr(0);
                 continue;
             }
+
             if ($ch < 33 /* ! */ || $ch > 117 /* u */) {
                 throw new Ascii85Exception(
                     'Illegal character found while ASCII85 decode.',
diff --git a/vendor/setasign/fpdi/src/PdfParser/Filter/Ascii85Exception.php b/vendor/setasign/fpdi/src/PdfParser/Filter/Ascii85Exception.php
index ac2a003133f3662cd11659107873d58f5b0351b4..a4b494a3e22e29023a2d88d83474efbf858c4cb8 100644
--- a/vendor/setasign/fpdi/src/PdfParser/Filter/Ascii85Exception.php
+++ b/vendor/setasign/fpdi/src/PdfParser/Filter/Ascii85Exception.php
@@ -3,9 +3,9 @@
  * This file is part of FPDI
  *
  * @package   setasign\Fpdi
- * @copyright Copyright (c) 2018 Setasign - Jan Slabon (https://www.setasign.com)
+ * @copyright Copyright (c) 2020 Setasign GmbH & Co. KG (https://www.setasign.com)
  * @license   http://opensource.org/licenses/mit-license The MIT License
-  */
+ */
 
 namespace setasign\Fpdi\PdfParser\Filter;
 
diff --git a/vendor/setasign/fpdi/src/PdfParser/Filter/AsciiHex.php b/vendor/setasign/fpdi/src/PdfParser/Filter/AsciiHex.php
index 9c9e401cb0436a5ed0d6c752508b02740d5e61b1..efa8b56852939cb055b8c11f2cbc538bc0a16811 100644
--- a/vendor/setasign/fpdi/src/PdfParser/Filter/AsciiHex.php
+++ b/vendor/setasign/fpdi/src/PdfParser/Filter/AsciiHex.php
@@ -3,9 +3,9 @@
  * This file is part of FPDI
  *
  * @package   setasign\Fpdi
- * @copyright Copyright (c) 2018 Setasign - Jan Slabon (https://www.setasign.com)
+ * @copyright Copyright (c) 2020 Setasign GmbH & Co. KG (https://www.setasign.com)
  * @license   http://opensource.org/licenses/mit-license The MIT License
-  */
+ */
 
 namespace setasign\Fpdi\PdfParser\Filter;
 
diff --git a/vendor/setasign/fpdi/src/PdfParser/Filter/FilterException.php b/vendor/setasign/fpdi/src/PdfParser/Filter/FilterException.php
index e7e189cda4960cf2353744bf23966bc74392322c..e3d19e1cb9d24a17e90d6f7020c1bb1fc4acbc9b 100644
--- a/vendor/setasign/fpdi/src/PdfParser/Filter/FilterException.php
+++ b/vendor/setasign/fpdi/src/PdfParser/Filter/FilterException.php
@@ -3,9 +3,9 @@
  * This file is part of FPDI
  *
  * @package   setasign\Fpdi
- * @copyright Copyright (c) 2018 Setasign - Jan Slabon (https://www.setasign.com)
+ * @copyright Copyright (c) 2020 Setasign GmbH & Co. KG (https://www.setasign.com)
  * @license   http://opensource.org/licenses/mit-license The MIT License
-  */
+ */
 
 namespace setasign\Fpdi\PdfParser\Filter;
 
diff --git a/vendor/setasign/fpdi/src/PdfParser/Filter/FilterInterface.php b/vendor/setasign/fpdi/src/PdfParser/Filter/FilterInterface.php
index 3177a3497f0e36dc2cd9c8da970c87c80bc7fc18..475f7ece18525d8811dfad4295a28cc99a8b2ed8 100644
--- a/vendor/setasign/fpdi/src/PdfParser/Filter/FilterInterface.php
+++ b/vendor/setasign/fpdi/src/PdfParser/Filter/FilterInterface.php
@@ -3,9 +3,9 @@
  * This file is part of FPDI
  *
  * @package   setasign\Fpdi
- * @copyright Copyright (c) 2018 Setasign - Jan Slabon (https://www.setasign.com)
+ * @copyright Copyright (c) 2020 Setasign GmbH & Co. KG (https://www.setasign.com)
  * @license   http://opensource.org/licenses/mit-license The MIT License
-  */
+ */
 
 namespace setasign\Fpdi\PdfParser\Filter;
 
diff --git a/vendor/setasign/fpdi/src/PdfParser/Filter/Flate.php b/vendor/setasign/fpdi/src/PdfParser/Filter/Flate.php
index 13d61970ff40cafea177ba4b2a1b4ea8ef3e2f49..f34353ef4e1f3336a5945e9baa6aab6e44ab3cac 100644
--- a/vendor/setasign/fpdi/src/PdfParser/Filter/Flate.php
+++ b/vendor/setasign/fpdi/src/PdfParser/Filter/Flate.php
@@ -3,9 +3,9 @@
  * This file is part of FPDI
  *
  * @package   setasign\Fpdi
- * @copyright Copyright (c) 2018 Setasign - Jan Slabon (https://www.setasign.com)
+ * @copyright Copyright (c) 2020 Setasign GmbH & Co. KG (https://www.setasign.com)
  * @license   http://opensource.org/licenses/mit-license The MIT License
-  */
+ */
 
 namespace setasign\Fpdi\PdfParser\Filter;
 
@@ -42,14 +42,33 @@ class Flate implements FilterInterface
             $oData = $data;
             $data = @((\strlen($data) > 0) ? \gzuncompress($data) : '');
             if ($data === false) {
+                // let's try if the checksum is CRC32
+                $fh = fopen('php://temp', 'w+b');
+                fwrite($fh, "\x1f\x8b\x08\x00\x00\x00\x00\x00" . $oData);
+                stream_filter_append($fh, 'zlib.inflate', STREAM_FILTER_READ, ['window' => 30]);
+                fseek($fh, 0);
+                $data = stream_get_contents($fh);
+                fclose($fh);
+
+                if ($data) {
+                    return $data;
+                }
+
                 // Try this fallback
-                $tries = 1;
-                while ($tries < 10 && ($data === false || \strlen($data) < (\strlen($oData) - $tries - 1))) {
-                    $data = @(\gzinflate(\substr($oData, $tries)));
+                $tries = 0;
+
+                $oDataLen = strlen($oData);
+                while ($tries < 6 && ($data === false || (strlen($data) < (strlen($oDataLen) - $tries - 1)))) {
+                    $data = @(gzinflate(substr($oData, $tries)));
                     $tries++;
                 }
 
-                if ($data === false) {
+                // let's use this fallback only if the $data is longer than the original data
+                if (strlen($data) > ($oDataLen - $tries - 1)) {
+                    return $data;
+                }
+
+                if (!$data) {
                     throw new FlateException(
                         'Error while decompressing stream.',
                         FlateException::DECOMPRESS_ERROR
diff --git a/vendor/setasign/fpdi/src/PdfParser/Filter/FlateException.php b/vendor/setasign/fpdi/src/PdfParser/Filter/FlateException.php
index c87ac342fc24db57eba9d8ae9c550f33d732c792..3488f99037fb3ad9c30279c7eddafb9d1db5230b 100644
--- a/vendor/setasign/fpdi/src/PdfParser/Filter/FlateException.php
+++ b/vendor/setasign/fpdi/src/PdfParser/Filter/FlateException.php
@@ -3,9 +3,9 @@
  * This file is part of FPDI
  *
  * @package   setasign\Fpdi
- * @copyright Copyright (c) 2018 Setasign - Jan Slabon (https://www.setasign.com)
+ * @copyright Copyright (c) 2020 Setasign GmbH & Co. KG (https://www.setasign.com)
  * @license   http://opensource.org/licenses/mit-license The MIT License
-  */
+ */
 
 namespace setasign\Fpdi\PdfParser\Filter;
 
diff --git a/vendor/setasign/fpdi/src/PdfParser/Filter/Lzw.php b/vendor/setasign/fpdi/src/PdfParser/Filter/Lzw.php
index df10bad73875c529ae2540935baa23e53990c3e0..77848eacfe166ab6fed74a5da31768e34db92f72 100644
--- a/vendor/setasign/fpdi/src/PdfParser/Filter/Lzw.php
+++ b/vendor/setasign/fpdi/src/PdfParser/Filter/Lzw.php
@@ -3,9 +3,9 @@
  * This file is part of FPDI
  *
  * @package   setasign\Fpdi
- * @copyright Copyright (c) 2018 Setasign - Jan Slabon (https://www.setasign.com)
+ * @copyright Copyright (c) 2020 Setasign GmbH & Co. KG (https://www.setasign.com)
  * @license   http://opensource.org/licenses/mit-license The MIT License
-  */
+ */
 
 namespace setasign\Fpdi\PdfParser\Filter;
 
diff --git a/vendor/setasign/fpdi/src/PdfParser/Filter/LzwException.php b/vendor/setasign/fpdi/src/PdfParser/Filter/LzwException.php
index 4d88616d20a6daf788be26044caae145a737c879..0eaa3be54534eff19334d54a6833147d84127c0a 100644
--- a/vendor/setasign/fpdi/src/PdfParser/Filter/LzwException.php
+++ b/vendor/setasign/fpdi/src/PdfParser/Filter/LzwException.php
@@ -3,9 +3,9 @@
  * This file is part of FPDI
  *
  * @package   setasign\Fpdi
- * @copyright Copyright (c) 2018 Setasign - Jan Slabon (https://www.setasign.com)
+ * @copyright Copyright (c) 2020 Setasign GmbH & Co. KG (https://www.setasign.com)
  * @license   http://opensource.org/licenses/mit-license The MIT License
-  */
+ */
 
 namespace setasign\Fpdi\PdfParser\Filter;
 
diff --git a/vendor/setasign/fpdi/src/PdfParser/PdfParser.php b/vendor/setasign/fpdi/src/PdfParser/PdfParser.php
index c6759c56e405960564b07024db06f2e9c8665221..64efb1cdb7edea811d793d7ab1e5119be0d6dc76 100644
--- a/vendor/setasign/fpdi/src/PdfParser/PdfParser.php
+++ b/vendor/setasign/fpdi/src/PdfParser/PdfParser.php
@@ -3,9 +3,9 @@
  * This file is part of FPDI
  *
  * @package   setasign\Fpdi
- * @copyright Copyright (c) 2018 Setasign - Jan Slabon (https://www.setasign.com)
+ * @copyright Copyright (c) 2020 Setasign GmbH & Co. KG (https://www.setasign.com)
  * @license   http://opensource.org/licenses/mit-license The MIT License
-  */
+ */
 
 namespace setasign\Fpdi\PdfParser;
 
@@ -112,6 +112,7 @@ class PdfParser
      * Resolves the file header.
      *
      * @throws PdfParserException
+     * @return int
      */
     protected function resolveFileHeader()
     {
diff --git a/vendor/setasign/fpdi/src/PdfParser/PdfParserException.php b/vendor/setasign/fpdi/src/PdfParser/PdfParserException.php
index 86f73c9b3bacefb11943fc686142ada6ccd4253b..56c731f5f15dfb73ff8fae6d7c60a5eb6812efc8 100644
--- a/vendor/setasign/fpdi/src/PdfParser/PdfParserException.php
+++ b/vendor/setasign/fpdi/src/PdfParser/PdfParserException.php
@@ -3,9 +3,9 @@
  * This file is part of FPDI
  *
  * @package   setasign\Fpdi
- * @copyright Copyright (c) 2018 Setasign - Jan Slabon (https://www.setasign.com)
+ * @copyright Copyright (c) 2020 Setasign GmbH & Co. KG (https://www.setasign.com)
  * @license   http://opensource.org/licenses/mit-license The MIT License
-  */
+ */
 
 namespace setasign\Fpdi\PdfParser;
 
diff --git a/vendor/setasign/fpdi/src/PdfParser/StreamReader.php b/vendor/setasign/fpdi/src/PdfParser/StreamReader.php
index bda71a4c87692dd489d5e6c1c6849c8c18d31048..65089a886a0ad5a6ee36b2a5c3151029ab1c1744 100644
--- a/vendor/setasign/fpdi/src/PdfParser/StreamReader.php
+++ b/vendor/setasign/fpdi/src/PdfParser/StreamReader.php
@@ -3,9 +3,9 @@
  * This file is part of FPDI
  *
  * @package   setasign\Fpdi
- * @copyright Copyright (c) 2018 Setasign - Jan Slabon (https://www.setasign.com)
+ * @copyright Copyright (c) 2020 Setasign GmbH & Co. KG (https://www.setasign.com)
  * @license   http://opensource.org/licenses/mit-license The MIT License
-  */
+ */
 
 namespace setasign\Fpdi\PdfParser;
 
@@ -124,7 +124,15 @@ class StreamReader
      */
     public function __destruct()
     {
-        if ($this->closeStream) {
+        $this->cleanUp();
+    }
+
+    /**
+     * Closes the file handle.
+     */
+    public function cleanUp()
+    {
+        if ($this->closeStream && is_resource($this->stream)) {
             \fclose($this->stream);
         }
     }
diff --git a/vendor/setasign/fpdi/src/PdfParser/Tokenizer.php b/vendor/setasign/fpdi/src/PdfParser/Tokenizer.php
index f49f62e357b245ec9cc65ca02a814a73aa09b433..b2bbf708296d4f0d54f5b7dad0557b3025f47378 100644
--- a/vendor/setasign/fpdi/src/PdfParser/Tokenizer.php
+++ b/vendor/setasign/fpdi/src/PdfParser/Tokenizer.php
@@ -3,9 +3,9 @@
  * This file is part of FPDI
  *
  * @package   setasign\Fpdi
- * @copyright Copyright (c) 2018 Setasign - Jan Slabon (https://www.setasign.com)
+ * @copyright Copyright (c) 2020 Setasign GmbH & Co. KG (https://www.setasign.com)
  * @license   http://opensource.org/licenses/mit-license The MIT License
-  */
+ */
 
 namespace setasign\Fpdi\PdfParser;
 
diff --git a/vendor/setasign/fpdi/src/PdfParser/Type/PdfArray.php b/vendor/setasign/fpdi/src/PdfParser/Type/PdfArray.php
index bb203de4c8401dbfea0af286499a7a02f9414654..906cd3adda7481822c377c82ef32514b78ef8cbf 100644
--- a/vendor/setasign/fpdi/src/PdfParser/Type/PdfArray.php
+++ b/vendor/setasign/fpdi/src/PdfParser/Type/PdfArray.php
@@ -3,9 +3,9 @@
  * This file is part of FPDI
  *
  * @package   setasign\Fpdi
- * @copyright Copyright (c) 2018 Setasign - Jan Slabon (https://www.setasign.com)
+ * @copyright Copyright (c) 2020 Setasign GmbH & Co. KG (https://www.setasign.com)
  * @license   http://opensource.org/licenses/mit-license The MIT License
-  */
+ */
 
 namespace setasign\Fpdi\PdfParser\Type;
 
diff --git a/vendor/setasign/fpdi/src/PdfParser/Type/PdfBoolean.php b/vendor/setasign/fpdi/src/PdfParser/Type/PdfBoolean.php
index 6fd42abf144114f23ed1cd03c95dfe8ae499e3ce..07ab0fe429a105066097fb77388dd7957c1e57c1 100644
--- a/vendor/setasign/fpdi/src/PdfParser/Type/PdfBoolean.php
+++ b/vendor/setasign/fpdi/src/PdfParser/Type/PdfBoolean.php
@@ -3,9 +3,9 @@
  * This file is part of FPDI
  *
  * @package   setasign\Fpdi
- * @copyright Copyright (c) 2018 Setasign - Jan Slabon (https://www.setasign.com)
+ * @copyright Copyright (c) 2020 Setasign GmbH & Co. KG (https://www.setasign.com)
  * @license   http://opensource.org/licenses/mit-license The MIT License
-  */
+ */
 
 namespace setasign\Fpdi\PdfParser\Type;
 
diff --git a/vendor/setasign/fpdi/src/PdfParser/Type/PdfDictionary.php b/vendor/setasign/fpdi/src/PdfParser/Type/PdfDictionary.php
index 49267ff9c6de426532f8072a4d0851baaaf69509..0f07dc5900102e80d63cca00fef8980a783cb979 100644
--- a/vendor/setasign/fpdi/src/PdfParser/Type/PdfDictionary.php
+++ b/vendor/setasign/fpdi/src/PdfParser/Type/PdfDictionary.php
@@ -3,9 +3,9 @@
  * This file is part of FPDI
  *
  * @package   setasign\Fpdi
- * @copyright Copyright (c) 2018 Setasign - Jan Slabon (https://www.setasign.com)
+ * @copyright Copyright (c) 2020 Setasign GmbH & Co. KG (https://www.setasign.com)
  * @license   http://opensource.org/licenses/mit-license The MIT License
-  */
+ */
 
 namespace setasign\Fpdi\PdfParser\Type;
 
diff --git a/vendor/setasign/fpdi/src/PdfParser/Type/PdfHexString.php b/vendor/setasign/fpdi/src/PdfParser/Type/PdfHexString.php
index 2eb9539c25a81bb325e4a230c9688f4050682904..8a0cb23c90b878c549a38ead716ed8a0803c7b29 100644
--- a/vendor/setasign/fpdi/src/PdfParser/Type/PdfHexString.php
+++ b/vendor/setasign/fpdi/src/PdfParser/Type/PdfHexString.php
@@ -3,9 +3,9 @@
  * This file is part of FPDI
  *
  * @package   setasign\Fpdi
- * @copyright Copyright (c) 2018 Setasign - Jan Slabon (https://www.setasign.com)
+ * @copyright Copyright (c) 2020 Setasign GmbH & Co. KG (https://www.setasign.com)
  * @license   http://opensource.org/licenses/mit-license The MIT License
-  */
+ */
 
 namespace setasign\Fpdi\PdfParser\Type;
 
diff --git a/vendor/setasign/fpdi/src/PdfParser/Type/PdfIndirectObject.php b/vendor/setasign/fpdi/src/PdfParser/Type/PdfIndirectObject.php
index 046616a28d3ffde6644442f4d403b5ce3773e453..188fe0da9ebe75ead6302f46ad442ba79422fc40 100644
--- a/vendor/setasign/fpdi/src/PdfParser/Type/PdfIndirectObject.php
+++ b/vendor/setasign/fpdi/src/PdfParser/Type/PdfIndirectObject.php
@@ -3,9 +3,9 @@
  * This file is part of FPDI
  *
  * @package   setasign\Fpdi
- * @copyright Copyright (c) 2018 Setasign - Jan Slabon (https://www.setasign.com)
+ * @copyright Copyright (c) 2020 Setasign GmbH & Co. KG (https://www.setasign.com)
  * @license   http://opensource.org/licenses/mit-license The MIT License
-  */
+ */
 
 namespace setasign\Fpdi\PdfParser\Type;
 
@@ -45,7 +45,7 @@ class PdfIndirectObject extends PdfType
 
         $nextToken = $tokenizer->getNextToken();
         if ($nextToken === 'stream') {
-            $value = PdfStream::parse($value, $reader);
+            $value = PdfStream::parse($value, $reader, $parser);
         } elseif ($nextToken !== false) {
             $tokenizer->pushStack($nextToken);
         }
diff --git a/vendor/setasign/fpdi/src/PdfParser/Type/PdfIndirectObjectReference.php b/vendor/setasign/fpdi/src/PdfParser/Type/PdfIndirectObjectReference.php
index 517199d558b3334c89ab85b2f6476930335d9856..08928980ccea7182544d43f58cb6f2954b58f716 100644
--- a/vendor/setasign/fpdi/src/PdfParser/Type/PdfIndirectObjectReference.php
+++ b/vendor/setasign/fpdi/src/PdfParser/Type/PdfIndirectObjectReference.php
@@ -3,9 +3,9 @@
  * This file is part of FPDI
  *
  * @package   setasign\Fpdi
- * @copyright Copyright (c) 2018 Setasign - Jan Slabon (https://www.setasign.com)
+ * @copyright Copyright (c) 2020 Setasign GmbH & Co. KG (https://www.setasign.com)
  * @license   http://opensource.org/licenses/mit-license The MIT License
-  */
+ */
 
 namespace setasign\Fpdi\PdfParser\Type;
 
diff --git a/vendor/setasign/fpdi/src/PdfParser/Type/PdfName.php b/vendor/setasign/fpdi/src/PdfParser/Type/PdfName.php
index cb3ad51e901ed94a9fcfe74eb09432fa70a5d913..cbf18337b225a5aea8c48b9351ca9943566f92e8 100644
--- a/vendor/setasign/fpdi/src/PdfParser/Type/PdfName.php
+++ b/vendor/setasign/fpdi/src/PdfParser/Type/PdfName.php
@@ -3,9 +3,9 @@
  * This file is part of FPDI
  *
  * @package   setasign\Fpdi
- * @copyright Copyright (c) 2018 Setasign - Jan Slabon (https://www.setasign.com)
+ * @copyright Copyright (c) 2020 Setasign GmbH & Co. KG (https://www.setasign.com)
  * @license   http://opensource.org/licenses/mit-license The MIT License
-  */
+ */
 
 namespace setasign\Fpdi\PdfParser\Type;
 
@@ -49,8 +49,8 @@ class PdfName extends PdfType
         if (strpos($value, '#') === false)
             return $value;
 
-        return preg_replace_callback('/#[a-fA-F\d]{2}/', function($matches) {
-            return chr(hexdec($matches[0]));
+        return preg_replace_callback('/#([a-fA-F\d]{2})/', function($matches) {
+            return chr(hexdec($matches[1]));
         }, $value);
     }
 
diff --git a/vendor/setasign/fpdi/src/PdfParser/Type/PdfNull.php b/vendor/setasign/fpdi/src/PdfParser/Type/PdfNull.php
index 6d040a6b7a7d900244097e9aebd966964941bff8..762a52c0ffd259f98a0f46188bb8aaf97304cba0 100644
--- a/vendor/setasign/fpdi/src/PdfParser/Type/PdfNull.php
+++ b/vendor/setasign/fpdi/src/PdfParser/Type/PdfNull.php
@@ -3,9 +3,9 @@
  * This file is part of FPDI
  *
  * @package   setasign\Fpdi
- * @copyright Copyright (c) 2018 Setasign - Jan Slabon (https://www.setasign.com)
+ * @copyright Copyright (c) 2020 Setasign GmbH & Co. KG (https://www.setasign.com)
  * @license   http://opensource.org/licenses/mit-license The MIT License
-  */
+ */
 
 namespace setasign\Fpdi\PdfParser\Type;
 
diff --git a/vendor/setasign/fpdi/src/PdfParser/Type/PdfNumeric.php b/vendor/setasign/fpdi/src/PdfParser/Type/PdfNumeric.php
index fc3a4e112a63d6ce35bd53775bfd89e589014ea0..5146fc6716ba010463f850590e79643517395863 100644
--- a/vendor/setasign/fpdi/src/PdfParser/Type/PdfNumeric.php
+++ b/vendor/setasign/fpdi/src/PdfParser/Type/PdfNumeric.php
@@ -3,9 +3,9 @@
  * This file is part of FPDI
  *
  * @package   setasign\Fpdi
- * @copyright Copyright (c) 2018 Setasign - Jan Slabon (https://www.setasign.com)
+ * @copyright Copyright (c) 2020 Setasign GmbH & Co. KG (https://www.setasign.com)
  * @license   http://opensource.org/licenses/mit-license The MIT License
-  */
+ */
 
 namespace setasign\Fpdi\PdfParser\Type;
 
diff --git a/vendor/setasign/fpdi/src/PdfParser/Type/PdfStream.php b/vendor/setasign/fpdi/src/PdfParser/Type/PdfStream.php
index eeec67f515d5cb170affc3ed5b736a612ee879fd..615ac50aed38b4da0b9a73f5b79a635e26cb87e1 100644
--- a/vendor/setasign/fpdi/src/PdfParser/Type/PdfStream.php
+++ b/vendor/setasign/fpdi/src/PdfParser/Type/PdfStream.php
@@ -3,17 +3,19 @@
  * This file is part of FPDI
  *
  * @package   setasign\Fpdi
- * @copyright Copyright (c) 2018 Setasign - Jan Slabon (https://www.setasign.com)
+ * @copyright Copyright (c) 2020 Setasign GmbH & Co. KG (https://www.setasign.com)
  * @license   http://opensource.org/licenses/mit-license The MIT License
-  */
+ */
 
 namespace setasign\Fpdi\PdfParser\Type;
 
+use setasign\Fpdi\PdfParser\CrossReference\CrossReferenceException;
 use setasign\Fpdi\PdfParser\Filter\Ascii85;
 use setasign\Fpdi\PdfParser\Filter\AsciiHex;
 use setasign\Fpdi\PdfParser\Filter\FilterException;
 use setasign\Fpdi\PdfParser\Filter\Flate;
 use setasign\Fpdi\PdfParser\Filter\Lzw;
+use setasign\Fpdi\PdfParser\PdfParser;
 use setasign\Fpdi\PdfParser\PdfParserException;
 use setasign\Fpdi\PdfParser\StreamReader;
 use setasign\FpdiPdfParser\PdfParser\Filter\Predictor;
@@ -30,14 +32,16 @@ class PdfStream extends PdfType
      *
      * @param PdfDictionary $dictionary
      * @param StreamReader $reader
+     * @param PdfParser $parser Optional to keep backwards compatibility
      * @return self
      * @throws PdfTypeException
      */
-    public static function parse(PdfDictionary $dictionary, StreamReader $reader)
+    public static function parse(PdfDictionary $dictionary, StreamReader $reader, PdfParser $parser = null)
     {
         $v = new self;
         $v->value = $dictionary;
         $v->reader = $reader;
+        $v->parser = $parser;
 
         $offset = $reader->getOffset();
 
@@ -115,47 +119,48 @@ class PdfStream extends PdfType
      */
     protected $reader;
 
+    /**
+     * The PDF parser instance.
+     *
+     * @var PdfParser
+     */
+    protected $parser;
+
     /**
      * Get the stream data.
      *
      * @param bool $cache Whether cache the stream data or not.
      * @return bool|string
      * @throws PdfTypeException
+     * @throws CrossReferenceException
+     * @throws PdfParserException
      */
     public function getStream($cache = false)
     {
         if (\is_int($this->stream)) {
             $length = PdfDictionary::get($this->value, 'Length');
-            $this->reader->reset($this->stream, $length->value);
-            if (!($length instanceof PdfNumeric) || $length->value === 0) {
-                while (true) {
-                    $buffer = $this->reader->getBuffer(false);
-                    $length = \strpos($buffer, 'endstream');
-                    if ($length === false) {
-                        if (!$this->reader->increaseLength(100000)) {
-                            return false;
-                        }
-                        continue;
-                    }
-                    break;
-                }
-
-                $buffer = \substr($buffer, 0, $length);
-                $lastByte = \substr($buffer, -1);
-
-                // Check for EOL
-                if ($lastByte === "\n") {
-                    $buffer = \substr($buffer, 0, -1);
-                }
-
-                $lastByte = \substr($buffer, -1);
-                if ($lastByte === "\r") {
-                    $buffer = \substr($buffer, 0, -1);
-                }
+            if ($this->parser !== null) {
+                $length = PdfType::resolve($length, $this->parser);
+            }
 
+            if (!($length instanceof PdfNumeric) || $length->value === 0) {
+                $this->reader->reset($this->stream, 100000);
+                $buffer = $this->extractStream();
             } else {
+                $this->reader->reset($this->stream, $length->value);
                 $buffer = $this->reader->getBuffer(false);
+                if ($this->parser !== null) {
+                    $this->reader->reset($this->stream + strlen($buffer));
+                    $this->parser->getTokenizer()->clearStack();
+                    $token = $this->parser->readValue();
+                    if ($token === false || !($token instanceof PdfToken) || $token->value !== 'endstream') {
+                        $this->reader->reset($this->stream, 100000);
+                        $buffer = $this->extractStream();
+                        $this->reader->reset($this->stream + strlen($buffer));
+                    }
+                }
             }
+
             if ($cache === false) {
                 return $buffer;
             }
@@ -167,6 +172,52 @@ class PdfStream extends PdfType
         return $this->stream;
     }
 
+    /**
+     * Extract the stream "manually".
+     *
+     * @return string
+     * @throws PdfTypeException
+     */
+    protected function extractStream()
+    {
+        while (true) {
+            $buffer = $this->reader->getBuffer(false);
+            $length = \strpos($buffer, 'endstream');
+            if ($length === false) {
+                if (!$this->reader->increaseLength(100000)) {
+                    throw new PdfTypeException('Cannot extract stream.');
+                }
+                continue;
+            }
+            break;
+        }
+
+        $buffer = \substr($buffer, 0, $length);
+        $lastByte = \substr($buffer, -1);
+
+        /* Check for EOL marker =
+         *   CARRIAGE RETURN (\r) and a LINE FEED (\n) or just a LINE FEED (\n},
+         *   and not by a CARRIAGE RETURN (\r) alone
+         */
+        if ($lastByte === "\n") {
+            $buffer = \substr($buffer, 0, -1);
+
+            $lastByte = \substr($buffer, -1);
+            if ($lastByte === "\r") {
+                $buffer = \substr($buffer, 0, -1);
+            }
+        }
+
+        // There are streams in the wild, which have only white signs in them but need to be parsed manually due
+        // to a problem encountered before (e.g. Length === 0). We should set them to empty streams to avoid problems
+        // in further processing (e.g. applying of filters).
+        if (trim($buffer) === '') {
+            $buffer = '';
+        }
+
+        return $buffer;
+    }
+
     /**
      * Get the unfiltered stream data.
      *
diff --git a/vendor/setasign/fpdi/src/PdfParser/Type/PdfString.php b/vendor/setasign/fpdi/src/PdfParser/Type/PdfString.php
index 9a3bb47eec09aabfa42b904dd0c5fadb67406d7f..e6011acd02e9ae90275b7b2ae3b9076c04f36e42 100644
--- a/vendor/setasign/fpdi/src/PdfParser/Type/PdfString.php
+++ b/vendor/setasign/fpdi/src/PdfParser/Type/PdfString.php
@@ -3,9 +3,9 @@
  * This file is part of FPDI
  *
  * @package   setasign\Fpdi
- * @copyright Copyright (c) 2018 Setasign - Jan Slabon (https://www.setasign.com)
+ * @copyright Copyright (c) 2020 Setasign GmbH & Co. KG (https://www.setasign.com)
  * @license   http://opensource.org/licenses/mit-license The MIT License
-  */
+ */
 
 namespace setasign\Fpdi\PdfParser\Type;
 
diff --git a/vendor/setasign/fpdi/src/PdfParser/Type/PdfToken.php b/vendor/setasign/fpdi/src/PdfParser/Type/PdfToken.php
index 89cf113fb18a005eadc31a5cc72dcf2a76de299d..c5329381df3b5a9754f89c0ed1d88ca389672d0d 100644
--- a/vendor/setasign/fpdi/src/PdfParser/Type/PdfToken.php
+++ b/vendor/setasign/fpdi/src/PdfParser/Type/PdfToken.php
@@ -3,9 +3,9 @@
  * This file is part of FPDI
  *
  * @package   setasign\Fpdi
- * @copyright Copyright (c) 2018 Setasign - Jan Slabon (https://www.setasign.com)
+ * @copyright Copyright (c) 2020 Setasign GmbH & Co. KG (https://www.setasign.com)
  * @license   http://opensource.org/licenses/mit-license The MIT License
-  */
+ */
 
 namespace setasign\Fpdi\PdfParser\Type;
 
diff --git a/vendor/setasign/fpdi/src/PdfParser/Type/PdfType.php b/vendor/setasign/fpdi/src/PdfParser/Type/PdfType.php
index 61aeb6ee919fb86af8c6c59a91cec79f561eb8d9..548dba2cfac4e4361a1da30a3ce5c10de9f5e94b 100644
--- a/vendor/setasign/fpdi/src/PdfParser/Type/PdfType.php
+++ b/vendor/setasign/fpdi/src/PdfParser/Type/PdfType.php
@@ -3,9 +3,9 @@
  * This file is part of FPDI
  *
  * @package   setasign\Fpdi
- * @copyright Copyright (c) 2018 Setasign - Jan Slabon (https://www.setasign.com)
+ * @copyright Copyright (c) 2020 Setasign GmbH & Co. KG (https://www.setasign.com)
  * @license   http://opensource.org/licenses/mit-license The MIT License
-  */
+ */
 
 namespace setasign\Fpdi\PdfParser\Type;
 
diff --git a/vendor/setasign/fpdi/src/PdfParser/Type/PdfTypeException.php b/vendor/setasign/fpdi/src/PdfParser/Type/PdfTypeException.php
index 97de6463d5ef373c5fd7f939db4f295ae0735578..1ee20ecf034419641167a3b5060b265b8f54fa98 100644
--- a/vendor/setasign/fpdi/src/PdfParser/Type/PdfTypeException.php
+++ b/vendor/setasign/fpdi/src/PdfParser/Type/PdfTypeException.php
@@ -3,9 +3,9 @@
  * This file is part of FPDI
  *
  * @package   setasign\Fpdi
- * @copyright Copyright (c) 2018 Setasign - Jan Slabon (https://www.setasign.com)
+ * @copyright Copyright (c) 2020 Setasign GmbH & Co. KG (https://www.setasign.com)
  * @license   http://opensource.org/licenses/mit-license The MIT License
-  */
+ */
 
 namespace setasign\Fpdi\PdfParser\Type;
 
diff --git a/vendor/setasign/fpdi/src/PdfReader/DataStructure/Rectangle.php b/vendor/setasign/fpdi/src/PdfReader/DataStructure/Rectangle.php
index 8ffa956237bfc3fc47f96d5940b7e3ec39b4a0d4..8774f9ffb551c3e904fd8bda539d65c3a00bb020 100644
--- a/vendor/setasign/fpdi/src/PdfReader/DataStructure/Rectangle.php
+++ b/vendor/setasign/fpdi/src/PdfReader/DataStructure/Rectangle.php
@@ -3,9 +3,9 @@
  * This file is part of FPDI
  *
  * @package   setasign\Fpdi
- * @copyright Copyright (c) 2018 Setasign - Jan Slabon (https://www.setasign.com)
+ * @copyright Copyright (c) 2020 Setasign GmbH & Co. KG (https://www.setasign.com)
  * @license   http://opensource.org/licenses/mit-license The MIT License
-  */
+ */
 
 namespace setasign\Fpdi\PdfReader\DataStructure;
 
diff --git a/vendor/setasign/fpdi/src/PdfReader/Page.php b/vendor/setasign/fpdi/src/PdfReader/Page.php
index 64668297bb02446b2b20ca9c38081bb4d7a1bfd9..645f8d0e228154ecdca720a656b948967ea0d422 100644
--- a/vendor/setasign/fpdi/src/PdfReader/Page.php
+++ b/vendor/setasign/fpdi/src/PdfReader/Page.php
@@ -3,9 +3,9 @@
  * This file is part of FPDI
  *
  * @package   setasign\Fpdi
- * @copyright Copyright (c) 2018 Setasign - Jan Slabon (https://www.setasign.com)
+ * @copyright Copyright (c) 2020 Setasign GmbH & Co. KG (https://www.setasign.com)
  * @license   http://opensource.org/licenses/mit-license The MIT License
-  */
+ */
 
 namespace setasign\Fpdi\PdfReader;
 
diff --git a/vendor/setasign/fpdi/src/PdfReader/PageBoundaries.php b/vendor/setasign/fpdi/src/PdfReader/PageBoundaries.php
index 08e4224eaf1a11cc5167843c80ab9f86195c79e8..3842c88884df49399b1af97139f85a4599dd9296 100644
--- a/vendor/setasign/fpdi/src/PdfReader/PageBoundaries.php
+++ b/vendor/setasign/fpdi/src/PdfReader/PageBoundaries.php
@@ -3,9 +3,9 @@
  * This file is part of FPDI
  *
  * @package   setasign\Fpdi
- * @copyright Copyright (c) 2018 Setasign - Jan Slabon (https://www.setasign.com)
+ * @copyright Copyright (c) 2020 Setasign GmbH & Co. KG (https://www.setasign.com)
  * @license   http://opensource.org/licenses/mit-license The MIT License
-  */
+ */
 
 namespace setasign\Fpdi\PdfReader;
 
diff --git a/vendor/setasign/fpdi/src/PdfReader/PdfReader.php b/vendor/setasign/fpdi/src/PdfReader/PdfReader.php
index f8f3419205597ea50ffb40b95bb79ea04cb2bbd6..0b39407b4c944008bc6f2450aaa5efda7afa912b 100644
--- a/vendor/setasign/fpdi/src/PdfReader/PdfReader.php
+++ b/vendor/setasign/fpdi/src/PdfReader/PdfReader.php
@@ -3,9 +3,9 @@
  * This file is part of FPDI
  *
  * @package   setasign\Fpdi
- * @copyright Copyright (c) 2018 Setasign - Jan Slabon (https://www.setasign.com)
+ * @copyright Copyright (c) 2020 Setasign GmbH & Co. KG (https://www.setasign.com)
  * @license   http://opensource.org/licenses/mit-license The MIT License
-  */
+ */
 
 namespace setasign\Fpdi\PdfReader;
 
@@ -14,6 +14,7 @@ use setasign\Fpdi\PdfParser\PdfParser;
 use setasign\Fpdi\PdfParser\PdfParserException;
 use setasign\Fpdi\PdfParser\Type\PdfArray;
 use setasign\Fpdi\PdfParser\Type\PdfDictionary;
+use setasign\Fpdi\PdfParser\Type\PdfIndirectObject;
 use setasign\Fpdi\PdfParser\Type\PdfIndirectObjectReference;
 use setasign\Fpdi\PdfParser\Type\PdfNumeric;
 use setasign\Fpdi\PdfParser\Type\PdfType;
@@ -39,7 +40,7 @@ class PdfReader
     /**
      * Indirect objects of resolved pages.
      *
-     * @var PdfIndirectObjectReference[]
+     * @var PdfIndirectObjectReference[]|PdfIndirectObject[]
      */
     protected $pages = [];
 
@@ -59,7 +60,6 @@ class PdfReader
     public function __destruct()
     {
         if ($this->parser !== null) {
-            /** @noinspection PhpInternalEntityUsedInspection */
             $this->parser->cleanUp();
         }
     }
@@ -165,9 +165,21 @@ class PdfReader
             $page = $this->parser->getIndirectObject($page->value);
             $dict = PdfType::resolve($page, $this->parser);
             $type = PdfDictionary::get($dict, 'Type');
+
             if ($type->value === 'Pages') {
                 $kids = PdfType::resolve(PdfDictionary::get($dict, 'Kids'), $this->parser);
-                $page = $this->pages[$pageNumber - 1] = $readPages($kids);
+                try {
+                    $page = $this->pages[$pageNumber - 1] = $readPages($kids);
+                } catch (PdfReaderException $e) {
+                    if ($e->getCode() !== PdfReaderException::KIDS_EMPTY) {
+                        throw $e;
+                    }
+
+                    // let's reset the pages array and read all page objects
+                    $this->pages = [];
+                    $this->readPages(true);
+                    $page = $this->pages[$pageNumber - 1];
+                }
             } else {
                 $this->pages[$pageNumber - 1] = $page;
             }
@@ -179,24 +191,25 @@ class PdfReader
     /**
      * Walk the page tree and resolve all indirect objects of all pages.
      *
-     * @throws PdfTypeException
+     * @param bool $readAll
      * @throws CrossReferenceException
      * @throws PdfParserException
+     * @throws PdfTypeException
      */
-    protected function readPages()
+    protected function readPages($readAll = false)
     {
         if (\count($this->pages) > 0) {
             return;
         }
 
-        $readPages = function ($kids, $count) use (&$readPages) {
+        $readPages = function ($kids, $count) use (&$readPages, $readAll) {
             $kids = PdfArray::ensure($kids);
-            $isLeaf = $count->value === \count($kids->value);
+            $isLeaf = ($count->value === \count($kids->value));
 
             foreach ($kids->value as $reference) {
                 $reference = PdfIndirectObjectReference::ensure($reference);
 
-                if ($isLeaf) {
+                if (!$readAll && $isLeaf) {
                     $this->pages[] = $reference;
                     continue;
                 }
diff --git a/vendor/setasign/fpdi/src/PdfReader/PdfReaderException.php b/vendor/setasign/fpdi/src/PdfReader/PdfReaderException.php
index 20413acced6e08ce882fea7d2b65ceb8180e2db8..c33d5678fa269465f53e581b6048bf673ed02bf5 100644
--- a/vendor/setasign/fpdi/src/PdfReader/PdfReaderException.php
+++ b/vendor/setasign/fpdi/src/PdfReader/PdfReaderException.php
@@ -3,9 +3,9 @@
  * This file is part of FPDI
  *
  * @package   setasign\Fpdi
- * @copyright Copyright (c) 2018 Setasign - Jan Slabon (https://www.setasign.com)
+ * @copyright Copyright (c) 2020 Setasign GmbH & Co. KG (https://www.setasign.com)
  * @license   http://opensource.org/licenses/mit-license The MIT License
-  */
+ */
 
 namespace setasign\Fpdi\PdfReader;
 
diff --git a/vendor/setasign/fpdi/src/Tcpdf/Fpdi.php b/vendor/setasign/fpdi/src/Tcpdf/Fpdi.php
index e2ee634670ef9f8752087158277693dc75fd02e2..b0486b1301a271b6349ae9341d577546f5a5b0bf 100644
--- a/vendor/setasign/fpdi/src/Tcpdf/Fpdi.php
+++ b/vendor/setasign/fpdi/src/Tcpdf/Fpdi.php
@@ -34,7 +34,7 @@ class Fpdi extends \TCPDF
      *
      * @string
      */
-    const VERSION = '2.1.1';
+    const VERSION = '2.3.1';
 
     /**
      * A counter for template ids.
@@ -50,6 +50,12 @@ class Fpdi extends \TCPDF
      */
     protected $currentObjectNumber;
 
+    protected function _enddoc()
+    {
+        parent::_enddoc();
+        $this->cleanUp();
+    }
+
     /**
      * Get the next template id.
      *
@@ -63,8 +69,8 @@ class Fpdi extends \TCPDF
     /**
      * Draws an imported page onto the page or another template.
      *
-     * Omit one of the size parameters (width, height) to calculate the other one automatically in view to the aspect
-     * ratio.
+     * Give only one of the size parameters (width, height) to calculate the other one automatically in view to the
+     * aspect ratio.
      *
      * @param mixed $tpl The template id
      * @param float|int|array $x The abscissa of upper-left corner. Alternatively you could use an assoc array
@@ -84,8 +90,8 @@ class Fpdi extends \TCPDF
     /**
      * Draws an imported page onto the page.
      *
-     * Omit one of the size parameters (width, height) to calculate the other one automatically in view to the aspect
-     * ratio.
+     * Give only one of the size parameters (width, height) to calculate the other one automatically in view to the
+     * aspect ratio.
      *
      * @param mixed $pageId The page id
      * @param float|int|array $x The abscissa of upper-left corner. Alternatively you could use an assoc array
@@ -111,8 +117,8 @@ class Fpdi extends \TCPDF
     /**
      * Get the size of an imported page.
      *
-     * Omit one of the size parameters (width, height) to calculate the other one automatically in view to the aspect
-     * ratio.
+     * Give only one of the size parameters (width, height) to calculate the other one automatically in view to the
+     * aspect ratio.
      *
      * @param mixed $tpl The template id
      * @param float|int|null $width The width.
diff --git a/vendor/setasign/fpdi/src/TcpdfFpdi.php b/vendor/setasign/fpdi/src/TcpdfFpdi.php
index e71dc9d4ee9868823f96baf08d88d659cbb8b5de..b366daabddda226d34f64aa6c50234c28b507af9 100644
--- a/vendor/setasign/fpdi/src/TcpdfFpdi.php
+++ b/vendor/setasign/fpdi/src/TcpdfFpdi.php
@@ -3,9 +3,9 @@
  * This file is part of FPDI
  *
  * @package   setasign\Fpdi
- * @copyright Copyright (c) 2018 Setasign - Jan Slabon (https://www.setasign.com)
+ * @copyright Copyright (c) 2020 Setasign GmbH & Co. KG (https://www.setasign.com)
  * @license   http://opensource.org/licenses/mit-license The MIT License
-  */
+ */
 
 namespace setasign\Fpdi;
 
diff --git a/vendor/setasign/fpdi/src/Tfpdf/FpdfTpl.php b/vendor/setasign/fpdi/src/Tfpdf/FpdfTpl.php
index 0b527a783febd3c498f2a144b92b5c4ce265c4e0..bf374844eb775f9ff790a830f3079e36e30bc4cb 100644
--- a/vendor/setasign/fpdi/src/Tfpdf/FpdfTpl.php
+++ b/vendor/setasign/fpdi/src/Tfpdf/FpdfTpl.php
@@ -3,9 +3,9 @@
  * This file is part of FPDI
  *
  * @package   setasign\Fpdi
- * @copyright Copyright (c) 2018 Setasign - Jan Slabon (https://www.setasign.com)
+ * @copyright Copyright (c) 2020 Setasign GmbH & Co. KG (https://www.setasign.com)
  * @license   http://opensource.org/licenses/mit-license The MIT License
-  */
+ */
 
 namespace setasign\Fpdi\Tfpdf;
 
@@ -20,80 +20,5 @@ use setasign\Fpdi\FpdfTplTrait;
  */
 class FpdfTpl extends \tFPDF
 {
-    use FpdfTplTrait {
-        _putimages as _protectedPutimages;
-        _putxobjectdict as _protectedPutxobjectdict;
-    }
-
-    /**
-     * Make the method public as in tFPDF.
-     */
-    public function _putimages()
-    {
-        $this->_protectedPutimages();
-    }
-
-    /**
-     * Make the method public as in tFPDF.
-     */
-    public function _putxobjectdict()
-    {
-        $this->_protectedPutxobjectdict();
-    }
-
-    /**
-     * Set the page format of the current page.
-     *
-     * @param array $size An array with two values defining the size.
-     * @param string $orientation "L" for landscape, "P" for portrait.
-     * @throws \BadMethodCallException
-     */
-    public function setPageFormat($size, $orientation)
-    {
-        if ($this->currentTemplateId !== null) {
-            throw new \BadMethodCallException('The page format cannot be changed when writing to a template.');
-        }
-
-        if (!\in_array($orientation, ['P', 'L'], true)) {
-            throw new \InvalidArgumentException(\sprintf(
-                'Invalid page orientation "%s"! Only "P" and "L" are allowed!',
-                $orientation
-            ));
-        }
-
-        $size = $this->_getpagesize($size);
-
-        if ($orientation != $this->CurOrientation
-            || $size[0] != $this->CurPageSize[0]
-            || $size[1] != $this->CurPageSize[1]
-        ) {
-            // New size or orientation
-            if ($orientation === 'P') {
-                $this->w = $size[0];
-                $this->h = $size[1];
-            } else {
-                $this->w = $size[1];
-                $this->h = $size[0];
-            }
-            $this->wPt = $this->w * $this->k;
-            $this->hPt = $this->h * $this->k;
-            $this->PageBreakTrigger = $this->h - $this->bMargin;
-            $this->CurOrientation = $orientation;
-            $this->CurPageSize = $size;
-
-            $this->PageSizes[$this->page] = array($this->wPt, $this->hPt);
-        }
-    }
-
-    /**
-     * @inheritdoc
-     */
-    protected function _put($s, $newLine = true)
-    {
-        if ($newLine) {
-            $this->buffer .= $s . "\n";
-        } else {
-            $this->buffer .= $s;
-        }
-    }
+    use FpdfTplTrait;
 }
\ No newline at end of file
diff --git a/vendor/setasign/fpdi/src/Tfpdf/Fpdi.php b/vendor/setasign/fpdi/src/Tfpdf/Fpdi.php
index 3fc4b22f3d0c292973259e976a627887ee7f0213..37e0f44fe7918a6f3749645716f25d0bf71321eb 100644
--- a/vendor/setasign/fpdi/src/Tfpdf/Fpdi.php
+++ b/vendor/setasign/fpdi/src/Tfpdf/Fpdi.php
@@ -3,9 +3,9 @@
  * This file is part of FPDI
  *
  * @package   setasign\Fpdi
- * @copyright Copyright (c) 2018 Setasign - Jan Slabon (https://www.setasign.com)
+ * @copyright Copyright (c) 2020 Setasign GmbH & Co. KG (https://www.setasign.com)
  * @license   http://opensource.org/licenses/mit-license The MIT License
-  */
+ */
 
 namespace setasign\Fpdi\Tfpdf;
 
@@ -31,13 +31,19 @@ class Fpdi extends FpdfTpl
      *
      * @string
      */
-    const VERSION = '2.1.1';
+    const VERSION = '2.3.1';
+
+    public function _enddoc()
+    {
+        parent::_enddoc();
+        $this->cleanUp();
+    }
 
     /**
      * Draws an imported page or a template onto the page or another template.
      *
-     * Omit one of the size parameters (width, height) to calculate the other one automatically in view to the aspect
-     * ratio.
+     * Give only one of the size parameters (width, height) to calculate the other one automatically in view to the
+     * aspect ratio.
      *
      * @param mixed $tpl The template id
      * @param float|int|array $x The abscissa of upper-left corner. Alternatively you could use an assoc array
@@ -65,8 +71,8 @@ class Fpdi extends FpdfTpl
     /**
      * Get the size of an imported page or template.
      *
-     * Omit one of the size parameters (width, height) to calculate the other one automatically in view to the aspect
-     * ratio.
+     * Give only one of the size parameters (width, height) to calculate the other one automatically in view to the
+     * aspect ratio.
      *
      * @param mixed $tpl The template id
      * @param float|int|null $width The width.
@@ -127,7 +133,7 @@ class Fpdi extends FpdfTpl
     /**
      * @inheritdoc
      */
-    public function _putxobjectdict()
+    protected function _putxobjectdict()
     {
         foreach ($this->importedPages as $key => $pageData) {
             $this->_put('/' . $pageData['id'] . ' ' . $pageData['objectNumber'] . ' 0 R');
@@ -139,20 +145,12 @@ class Fpdi extends FpdfTpl
     /**
      * @inheritdoc
      */
-    public function _newobj($n = null)
+    protected function _put($s, $newLine = true)
     {
-        // Begin a new object
-        if($n === null)
-            $n = ++$this->n;
-        $this->offsets[$n] = $this->_getoffset();
-        $this->_put($n.' 0 obj');
-    }
-
-    /**
-     * @inheritdoc
-     */
-    protected function _getoffset()
-    {
-        return strlen($this->buffer);
+        if ($newLine) {
+            $this->buffer .= $s . "\n";
+        } else {
+            $this->buffer .= $s;
+        }
     }
 }
\ No newline at end of file
diff --git a/vendor/setasign/fpdi/src/autoload.php b/vendor/setasign/fpdi/src/autoload.php
index 5fed74df1ca8340f386dcc3814417ffd1cfa04a0..b649e8b9d97001ba562a3322bbadfd19e6839589 100644
--- a/vendor/setasign/fpdi/src/autoload.php
+++ b/vendor/setasign/fpdi/src/autoload.php
@@ -3,9 +3,9 @@
  * This file is part of FPDI
  *
  * @package   setasign\Fpdi
- * @copyright Copyright (c) 2018 Setasign - Jan Slabon (https://www.setasign.com)
+ * @copyright Copyright (c) 2020 Setasign GmbH & Co. KG (https://www.setasign.com)
  * @license   http://opensource.org/licenses/mit-license The MIT License
-  */
+ */
 
 spl_autoload_register(function ($class) {
     if (strpos($class, 'setasign\Fpdi\\') === 0) {
diff --git a/vendor/slim/slim/CODE_OF_CONDUCT.md b/vendor/slim/slim/CODE_OF_CONDUCT.md
deleted file mode 100644
index 7fcbf4e76d1d28d9ef723877c0c85ddba4aa1a39..0000000000000000000000000000000000000000
--- a/vendor/slim/slim/CODE_OF_CONDUCT.md
+++ /dev/null
@@ -1,8 +0,0 @@
-# Code of Conduct
-
-The Slim Framework code of conduct is derived from the Ruby code of conduct. This document provides community guidelines for a safe, respectful, productive, and collaborative place for any person who is willing to contribute to the Slim Framework community. It applies to all “collaborative space”, which is defined as community communications channels (such as mailing lists, IRC, Slack, forums, submitted patches, commit comments, etc.). Any violations of the code of conduct may be reported by contacting one or more of the project maintainers either directly or via email to maintainers@slimframework.com.
-
-* Participants will be tolerant of opposing views.
-* Participants must ensure that their language and actions are free of personal attacks and disparaging personal remarks.
-* When interpreting the words and actions of others, participants should always assume good intentions.
-* Behaviour that the project maintainers consider to be harassment will not be tolerated.
diff --git a/vendor/slim/slim/LICENSE.md b/vendor/slim/slim/LICENSE.md
index 682c21dc7a47e3e960c936946e4c184d1059c5cb..116e902f0150842161ed29c413978335e7d2666e 100644
--- a/vendor/slim/slim/LICENSE.md
+++ b/vendor/slim/slim/LICENSE.md
@@ -1,4 +1,4 @@
-Copyright (c) 2011-2017 Josh Lockhart
+Copyright (c) 2011-2019 Josh Lockhart
 
 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal
diff --git a/vendor/slim/slim/MAINTAINERS.md b/vendor/slim/slim/MAINTAINERS.md
new file mode 100644
index 0000000000000000000000000000000000000000..2b8ad04964bc6b670c8086f4c5baacd91fab93dc
--- /dev/null
+++ b/vendor/slim/slim/MAINTAINERS.md
@@ -0,0 +1,17 @@
+# Maintainers
+
+There aren't many rules for maintainers of Slim to remember; what we have is listed here.
+
+## We don't merge our own PRs
+
+Our code is better if more than one set of eyes looks at it. Therefore we do not merge our own pull requests unless there is an exceptional circumstance. This helps to spot errors in the patch and also enables us to share information about the project around the maintainer team.
+
+## PRs tagged `WIP` are not ready to be merged
+
+Sometimes it's helpful to collaborate on a patch before it's ready to be merged. We use the text `WIP` (for _Work in Progress_) in the title to mark these PRs. 
+
+If a PR has `WIP` in its title, then it is not to be merged. The person who raised the PR will remove the `WIP` text when they are ready for a full review and merge.
+
+## Assign a merged PR to a milestone
+
+By ensuring that all merged PRs are assigned to a milestone, we can easily find which PRs were in which release.
diff --git a/vendor/slim/slim/Slim/App.php b/vendor/slim/slim/Slim/App.php
index 6bf64a0f904b3da4a710eb258f06d5ac99fdc97c..8d39c9d5a9d30b2250414ec9109733ea6be410c4 100644
--- a/vendor/slim/slim/Slim/App.php
+++ b/vendor/slim/slim/Slim/App.php
@@ -2,47 +2,36 @@
 /**
  * Slim Framework (https://slimframework.com)
  *
- * @link      https://github.com/slimphp/Slim
- * @copyright Copyright (c) 2011-2017 Josh Lockhart
- * @license   https://github.com/slimphp/Slim/blob/3.x/LICENSE.md (MIT License)
+ * @license https://github.com/slimphp/Slim/blob/3.x/LICENSE.md (MIT License)
  */
+
 namespace Slim;
 
-use Exception;
-use Slim\Exception\InvalidMethodException;
-use Slim\Http\Response;
-use Throwable;
+use BadMethodCallException;
 use Closure;
+use Exception;
+use FastRoute\Dispatcher;
+use Psr\Container\ContainerExceptionInterface as ContainerException;
 use InvalidArgumentException;
+use Psr\Container\ContainerInterface;
 use Psr\Http\Message\RequestInterface;
-use Psr\Http\Message\ServerRequestInterface;
 use Psr\Http\Message\ResponseInterface;
-use Psr\Container\ContainerInterface;
-use FastRoute\Dispatcher;
-use Slim\Exception\SlimException;
+use Psr\Http\Message\ServerRequestInterface;
+use Psr\Http\Message\UriInterface;
+use RuntimeException;
+use Slim\Exception\InvalidMethodException;
 use Slim\Exception\MethodNotAllowedException;
 use Slim\Exception\NotFoundException;
-use Slim\Http\Uri;
-use Slim\Http\Headers;
+use Slim\Exception\SlimException;
 use Slim\Http\Body;
+use Slim\Http\Headers;
 use Slim\Http\Request;
-use Slim\Interfaces\Http\EnvironmentInterface;
+use Slim\Http\Uri;
 use Slim\Interfaces\RouteGroupInterface;
 use Slim\Interfaces\RouteInterface;
 use Slim\Interfaces\RouterInterface;
+use Throwable;
 
-/**
- * App
- *
- * This is the primary class with which you instantiate,
- * configure, and run a Slim Framework application.
- * The \Slim\App class also accepts Slim Framework middleware.
- *
- * @property-read callable $errorHandler
- * @property-read callable $phpErrorHandler
- * @property-read callable $notFoundHandler function($request, $response)
- * @property-read callable $notAllowedHandler function($request, $response, $allowedHttpMethods)
- */
 class App
 {
     use MiddlewareAwareTrait;
@@ -52,38 +41,33 @@ class App
      *
      * @var string
      */
-    const VERSION = '3.11.0';
+    const VERSION = '3.12.3';
 
     /**
-     * Container
-     *
      * @var ContainerInterface
      */
     private $container;
 
-    /********************************************************************************
-     * Constructor
-     *******************************************************************************/
-
     /**
-     * Create new application
+     * @param ContainerInterface|array $container
      *
-     * @param ContainerInterface|array $container Either a ContainerInterface or an associative array of app settings
-     * @throws InvalidArgumentException when no container is provided that implements ContainerInterface
+     * @throws InvalidArgumentException When no container is provided that implements ContainerInterface
      */
     public function __construct($container = [])
     {
         if (is_array($container)) {
             $container = new Container($container);
         }
+
         if (!$container instanceof ContainerInterface) {
             throw new InvalidArgumentException('Expected a ContainerInterface');
         }
+
         $this->container = $container;
     }
 
     /**
-     * Enable access to the DI container by consumers of $app
+     * Get container
      *
      * @return ContainerInterface
      */
@@ -97,7 +81,7 @@ class App
      *
      * This method prepends new middleware to the app's middleware stack.
      *
-     * @param  callable|string    $callable The callback routine
+     * @param  callable|string $callable The callback routine
      *
      * @return static
      */
@@ -107,12 +91,15 @@ class App
     }
 
     /**
-     * Calling a non-existant method on App checks to see if there's an item
+     * Calling a non-existent method on App checks to see if there's an item
      * in the container that is callable and if so, calls it.
      *
      * @param  string $method
-     * @param  array $args
+     * @param  array  $args
+     *
      * @return mixed
+     *
+     * @throws BadMethodCallException
      */
     public function __call($method, $args)
     {
@@ -123,20 +110,16 @@ class App
             }
         }
 
-        throw new \BadMethodCallException("Method $method is not a valid method");
+        throw new BadMethodCallException("Method $method is not a valid method");
     }
 
-    /********************************************************************************
-     * Router proxy methods
-     *******************************************************************************/
-
     /**
      * Add GET route
      *
-     * @param  string $pattern  The route URI pattern
-     * @param  callable|string  $callable The route callback routine
+     * @param  string          $pattern  The route URI pattern
+     * @param  callable|string $callable The route callback routine
      *
-     * @return \Slim\Interfaces\RouteInterface
+     * @return RouteInterface
      */
     public function get($pattern, $callable)
     {
@@ -146,10 +129,10 @@ class App
     /**
      * Add POST route
      *
-     * @param  string $pattern  The route URI pattern
-     * @param  callable|string  $callable The route callback routine
+     * @param  string          $pattern  The route URI pattern
+     * @param  callable|string $callable The route callback routine
      *
-     * @return \Slim\Interfaces\RouteInterface
+     * @return RouteInterface
      */
     public function post($pattern, $callable)
     {
@@ -159,10 +142,10 @@ class App
     /**
      * Add PUT route
      *
-     * @param  string $pattern  The route URI pattern
-     * @param  callable|string  $callable The route callback routine
+     * @param  string          $pattern  The route URI pattern
+     * @param  callable|string $callable The route callback routine
      *
-     * @return \Slim\Interfaces\RouteInterface
+     * @return RouteInterface
      */
     public function put($pattern, $callable)
     {
@@ -172,10 +155,10 @@ class App
     /**
      * Add PATCH route
      *
-     * @param  string $pattern  The route URI pattern
-     * @param  callable|string  $callable The route callback routine
+     * @param  string          $pattern  The route URI pattern
+     * @param  callable|string $callable The route callback routine
      *
-     * @return \Slim\Interfaces\RouteInterface
+     * @return RouteInterface
      */
     public function patch($pattern, $callable)
     {
@@ -185,10 +168,10 @@ class App
     /**
      * Add DELETE route
      *
-     * @param  string $pattern  The route URI pattern
-     * @param  callable|string  $callable The route callback routine
+     * @param  string          $pattern  The route URI pattern
+     * @param  callable|string $callable The route callback routine
      *
-     * @return \Slim\Interfaces\RouteInterface
+     * @return RouteInterface
      */
     public function delete($pattern, $callable)
     {
@@ -198,10 +181,10 @@ class App
     /**
      * Add OPTIONS route
      *
-     * @param  string $pattern  The route URI pattern
-     * @param  callable|string  $callable The route callback routine
+     * @param  string          $pattern  The route URI pattern
+     * @param  callable|string $callable The route callback routine
      *
-     * @return \Slim\Interfaces\RouteInterface
+     * @return RouteInterface
      */
     public function options($pattern, $callable)
     {
@@ -211,10 +194,10 @@ class App
     /**
      * Add route for any HTTP method
      *
-     * @param  string $pattern  The route URI pattern
-     * @param  callable|string  $callable The route callback routine
+     * @param  string $pattern The route URI pattern
+     * @param  callable|string $callable The route callback routine
      *
-     * @return \Slim\Interfaces\RouteInterface
+     * @return RouteInterface
      */
     public function any($pattern, $callable)
     {
@@ -224,9 +207,9 @@ class App
     /**
      * Add route with multiple methods
      *
-     * @param  string[] $methods  Numeric array of HTTP method names
-     * @param  string   $pattern  The route URI pattern
-     * @param  callable|string    $callable The route callback routine
+     * @param  string[]        $methods  Numeric array of HTTP method names
+     * @param  string          $pattern  The route URI pattern
+     * @param  callable|string $callable The route callback routine
      *
      * @return RouteInterface
      */
@@ -267,31 +250,31 @@ class App
     }
 
     /**
-     * Route Groups
+     * Add a route group
      *
      * This method accepts a route pattern and a callback. All route
      * declarations in the callback will be prepended by the group(s)
      * that it is in.
      *
-     * @param string   $pattern
-     * @param callable $callable
+     * @param string           $pattern
+     * @param callable|Closure $callable
      *
      * @return RouteGroupInterface
      */
     public function group($pattern, $callable)
     {
+        /** @var RouterInterface $router */
+        $router = $this->container->get('router');
+
         /** @var RouteGroup $group */
-        $group = $this->container->get('router')->pushGroup($pattern, $callable);
+        $group = $router->pushGroup($pattern, $callable);
         $group->setContainer($this->container);
         $group($this);
-        $this->container->get('router')->popGroup();
+
+        $router->popGroup();
         return $group;
     }
 
-    /********************************************************************************
-     * Runner
-     *******************************************************************************/
-
     /**
      * Run application
      *
@@ -299,11 +282,11 @@ class App
      * resultant Response object to the HTTP client.
      *
      * @param bool|false $silent
+     *
      * @return ResponseInterface
      *
      * @throws Exception
-     * @throws MethodNotAllowedException
-     * @throws NotFoundException
+     * @throws Throwable
      */
     public function run($silent = false)
     {
@@ -350,7 +333,10 @@ class App
      *
      * @param ServerRequestInterface $request
      * @param ResponseInterface $response
+     *
      * @return ResponseInterface
+     *
+     * @throws ContainerException
      */
     protected function processInvalidMethod(ServerRequestInterface $request, ResponseInterface $response)
     {
@@ -381,11 +367,11 @@ class App
      *
      * @param ServerRequestInterface $request
      * @param ResponseInterface $response
+     *
      * @return ResponseInterface
      *
      * @throws Exception
-     * @throws MethodNotAllowedException
-     * @throws NotFoundException
+     * @throws Throwable
      */
     public function process(ServerRequestInterface $request, ResponseInterface $response)
     {
@@ -444,15 +430,16 @@ class App
         }
 
         // Body
-        if (!$this->isEmptyResponse($response)) {
+        $request = $this->container->get('request');
+        if (!$this->isEmptyResponse($response) && !$this->isHeadRequest($request)) {
             $body = $response->getBody();
             if ($body->isSeekable()) {
                 $body->rewind();
             }
-            $settings       = $this->container->get('settings');
-            $chunkSize      = $settings['responseChunkSize'];
+            $settings = $this->container->get('settings');
+            $chunkSize = $settings['responseChunkSize'];
 
-            $contentLength  = $response->getHeaderLine('Content-Length');
+            $contentLength = $response->getHeaderLine('Content-Length');
             if (!$contentLength) {
                 $contentLength = $body->getSize();
             }
@@ -461,7 +448,7 @@ class App
             if (isset($contentLength)) {
                 $amountToRead = $contentLength;
                 while ($amountToRead > 0 && !$body->eof()) {
-                    $data = $body->read(min($chunkSize, $amountToRead));
+                    $data = $body->read(min((int)$chunkSize, (int)$amountToRead));
                     echo $data;
 
                     $amountToRead -= strlen($data);
@@ -472,7 +459,7 @@ class App
                 }
             } else {
                 while (!$body->eof()) {
-                    echo $body->read($chunkSize);
+                    echo $body->read((int)$chunkSize);
                     if (connection_status() != CONNECTION_NORMAL) {
                         break;
                     }
@@ -493,6 +480,7 @@ class App
      * @param  ResponseInterface      $response The most recent Response object
      *
      * @return ResponseInterface
+     *
      * @throws MethodNotAllowedException
      * @throws NotFoundException
      */
@@ -501,7 +489,7 @@ class App
         // Get the route info
         $routeInfo = $request->getAttribute('routeInfo');
 
-        /** @var \Slim\Interfaces\RouterInterface $router */
+        /** @var RouterInterface $router */
         $router = $this->container->get('router');
 
         // If router hasn't been dispatched or the URI changed then dispatch
@@ -546,7 +534,11 @@ class App
      * @param  array             $cookies     The request cookies (key-value array)
      * @param  string            $bodyContent The request body
      * @param  ResponseInterface $response     The response object (optional)
+     *
      * @return ResponseInterface
+     *
+     * @throws MethodNotAllowedException
+     * @throws NotFoundException
      */
     public function subRequest(
         $method,
@@ -578,6 +570,7 @@ class App
      *
      * @param ServerRequestInterface $request
      * @param RouterInterface        $router
+     *
      * @return ServerRequestInterface
      */
     protected function dispatchRouterAndPrepareRoute(ServerRequestInterface $request, RouterInterface $router)
@@ -606,14 +599,18 @@ class App
      * Finalize response
      *
      * @param ResponseInterface $response
+     *
      * @return ResponseInterface
+     *
+     * @throws RuntimeException
      */
     protected function finalize(ResponseInterface $response)
     {
         // stop PHP sending a Content-Type automatically
         ini_set('default_mimetype', '');
 
-        if ($this->isEmptyResponse($response)) {
+        $request = $this->container->get('request');
+        if ($this->isEmptyResponse($response) && !$this->isHeadRequest($request)) {
             return $response->withoutHeader('Content-Type')->withoutHeader('Content-Length');
         }
 
@@ -621,7 +618,7 @@ class App
         if (isset($this->container->get('settings')['addContentLengthHeader']) &&
             $this->container->get('settings')['addContentLengthHeader'] == true) {
             if (ob_get_length() > 0) {
-                throw new \RuntimeException("Unexpected data in output buffer. " .
+                throw new RuntimeException("Unexpected data in output buffer. " .
                     "Maybe you have characters before an opening <?php tag?");
             }
             $size = $response->getBody()->getSize();
@@ -630,6 +627,11 @@ class App
             }
         }
 
+        // clear the body if this is a HEAD request
+        if ($this->isHeadRequest($request)) {
+            return $response->withBody(new Body(fopen('php://temp', 'r+')));
+        }
+
         return $response;
     }
 
@@ -640,6 +642,7 @@ class App
      * @see https://tools.ietf.org/html/rfc7231
      *
      * @param ResponseInterface $response
+     *
      * @return bool
      */
     protected function isEmptyResponse(ResponseInterface $response)
@@ -651,16 +654,29 @@ class App
         return in_array($response->getStatusCode(), [204, 205, 304]);
     }
 
+    /**
+     * Helper method to check if the current request is a HEAD request
+     *
+     * @param RequestInterface $request
+     *
+     * @return bool
+     */
+    protected function isHeadRequest(RequestInterface $request)
+    {
+        return strtoupper($request->getMethod()) === 'HEAD';
+    }
+
     /**
      * Call relevant handler from the Container if needed. If it doesn't exist,
      * then just re-throw.
      *
-     * @param  Exception $e
+     * @param  Exception              $e
      * @param  ServerRequestInterface $request
-     * @param  ResponseInterface $response
+     * @param  ResponseInterface      $response
      *
      * @return ResponseInterface
-     * @throws Exception if a handler is needed and not found
+     *
+     * @throws Exception If a handler is needed and not found
      */
     protected function handleException(Exception $e, ServerRequestInterface $request, ResponseInterface $response)
     {
@@ -696,7 +712,9 @@ class App
      * @param  Throwable $e
      * @param  ServerRequestInterface $request
      * @param  ResponseInterface $response
+     *
      * @return ResponseInterface
+     *
      * @throws Throwable
      */
     protected function handlePhpError(Throwable $e, ServerRequestInterface $request, ResponseInterface $response)
diff --git a/vendor/slim/slim/Slim/CallableResolver.php b/vendor/slim/slim/Slim/CallableResolver.php
index 2211a32918788edbe42119726cf1b9c2029b9686..577e9df22436c1ccec6930fcf6b6c62f67e6f12d 100644
--- a/vendor/slim/slim/Slim/CallableResolver.php
+++ b/vendor/slim/slim/Slim/CallableResolver.php
@@ -2,14 +2,13 @@
 /**
  * Slim Framework (https://slimframework.com)
  *
- * @link      https://github.com/slimphp/Slim
- * @copyright Copyright (c) 2011-2017 Josh Lockhart
- * @license   https://github.com/slimphp/Slim/blob/3.x/LICENSE.md (MIT License)
+ * @license https://github.com/slimphp/Slim/blob/3.x/LICENSE.md (MIT License)
  */
+
 namespace Slim;
 
-use RuntimeException;
 use Psr\Container\ContainerInterface;
+use RuntimeException;
 use Slim\Interfaces\CallableResolverInterface;
 
 /**
@@ -39,12 +38,12 @@ final class CallableResolver implements CallableResolverInterface
      * If toResolve is of the format 'class:method', then try to extract 'class'
      * from the container otherwise instantiate it and then dispatch 'method'.
      *
-     * @param mixed $toResolve
+     * @param callable|string $toResolve
      *
      * @return callable
      *
-     * @throws RuntimeException if the callable does not exist
-     * @throws RuntimeException if the callable is not resolvable
+     * @throws RuntimeException If the callable does not exist
+     * @throws RuntimeException If the callable is not resolvable
      */
     public function resolve($toResolve)
     {
@@ -52,35 +51,45 @@ final class CallableResolver implements CallableResolverInterface
             return $toResolve;
         }
 
-        if (!is_string($toResolve)) {
-            $this->assertCallable($toResolve);
-        }
+        $resolved = $toResolve;
 
-        // check for slim callable as "class:method"
-        if (preg_match(self::CALLABLE_PATTERN, $toResolve, $matches)) {
-            $resolved = $this->resolveCallable($matches[1], $matches[2]);
-            $this->assertCallable($resolved);
-
-            return $resolved;
+        if (is_string($toResolve)) {
+            list($class, $method) = $this->parseCallable($toResolve);
+            $resolved = $this->resolveCallable($class, $method);
         }
 
-        $resolved = $this->resolveCallable($toResolve);
         $this->assertCallable($resolved);
-
         return $resolved;
     }
 
+    /**
+     * Extract class and method from toResolve
+     *
+     * @param string $toResolve
+     *
+     * @return array
+     */
+    protected function parseCallable($toResolve)
+    {
+        if (preg_match(self::CALLABLE_PATTERN, $toResolve, $matches)) {
+            return [$matches[1], $matches[2]];
+        }
+
+        return [$toResolve, '__invoke'];
+    }
+
     /**
      * Check if string is something in the DIC
      * that's callable or is a class name which has an __invoke() method.
      *
      * @param string $class
      * @param string $method
+     *
      * @return callable
      *
-     * @throws \RuntimeException if the callable does not exist
+     * @throws RuntimeException if the callable does not exist
      */
-    protected function resolveCallable($class, $method = '__invoke')
+    protected function resolveCallable($class, $method)
     {
         if ($this->container->has($class)) {
             return [$this->container->get($class), $method];
@@ -96,7 +105,7 @@ final class CallableResolver implements CallableResolverInterface
     /**
      * @param Callable $callable
      *
-     * @throws \RuntimeException if the callable is not resolvable
+     * @throws RuntimeException if the callable is not resolvable
      */
     protected function assertCallable($callable)
     {
diff --git a/vendor/slim/slim/Slim/CallableResolverAwareTrait.php b/vendor/slim/slim/Slim/CallableResolverAwareTrait.php
index ffb4eb28a43964a1b0eae97947e7271aed8e9de0..cdf7367b0e593d13ca4b73f38980d9e55b194590 100644
--- a/vendor/slim/slim/Slim/CallableResolverAwareTrait.php
+++ b/vendor/slim/slim/Slim/CallableResolverAwareTrait.php
@@ -2,24 +2,20 @@
 /**
  * Slim Framework (https://slimframework.com)
  *
- * @link      https://github.com/slimphp/Slim
- * @copyright Copyright (c) 2011-2017 Josh Lockhart
- * @license   https://github.com/slimphp/Slim/blob/3.x/LICENSE.md (MIT License)
+ * @license https://github.com/slimphp/Slim/blob/3.x/LICENSE.md (MIT License)
  */
+
 namespace Slim;
 
-use RuntimeException;
+use Closure;
 use Psr\Container\ContainerInterface;
+use RuntimeException;
 use Slim\Interfaces\CallableResolverInterface;
 
 /**
- * ResolveCallable
- *
  * This is an internal class that enables resolution of 'class:method' strings
  * into a closure. This class is an implementation detail and is used only inside
  * of the Slim application.
- *
- * @property ContainerInterface $container
  */
 trait CallableResolverAwareTrait
 {
@@ -29,7 +25,7 @@ trait CallableResolverAwareTrait
      *
      * @param callable|string $callable
      *
-     * @return \Closure
+     * @return Closure
      *
      * @throws RuntimeException If the string cannot be resolved as a callable
      */
diff --git a/vendor/slim/slim/Slim/Collection.php b/vendor/slim/slim/Slim/Collection.php
index 728bb73e08b18577d9bc35473faaed834bc31d16..2eaec44a3322f4814d1a7755ce5733f95253eb68 100644
--- a/vendor/slim/slim/Slim/Collection.php
+++ b/vendor/slim/slim/Slim/Collection.php
@@ -2,10 +2,9 @@
 /**
  * Slim Framework (https://slimframework.com)
  *
- * @link      https://github.com/slimphp/Slim
- * @copyright Copyright (c) 2011-2017 Josh Lockhart
- * @license   https://github.com/slimphp/Slim/blob/3.x/LICENSE.md (MIT License)
+ * @license https://github.com/slimphp/Slim/blob/3.x/LICENSE.md (MIT License)
  */
+
 namespace Slim;
 
 use ArrayIterator;
@@ -28,8 +27,6 @@ class Collection implements CollectionInterface
     protected $data = [];
 
     /**
-     * Create new collection
-     *
      * @param array $items Pre-populate collection with this key-value array
      */
     public function __construct(array $items = [])
@@ -37,15 +34,8 @@ class Collection implements CollectionInterface
         $this->replace($items);
     }
 
-    /********************************************************************************
-     * Collection interface
-     *******************************************************************************/
-
     /**
-     * Set collection item
-     *
-     * @param string $key   The data key
-     * @param mixed  $value The data value
+     * {@inheritdoc}
      */
     public function set($key, $value)
     {
@@ -53,12 +43,7 @@ class Collection implements CollectionInterface
     }
 
     /**
-     * Get collection item for key
-     *
-     * @param string $key     The data key
-     * @param mixed  $default The default value to return if data key does not exist
-     *
-     * @return mixed The key's value, or the default value
+     * {@inheritdoc}
      */
     public function get($key, $default = null)
     {
@@ -66,9 +51,7 @@ class Collection implements CollectionInterface
     }
 
     /**
-     * Add item to collection, replacing existing items with the same data key
-     *
-     * @param array $items Key-value array of data to append to this collection
+     * {@inheritdoc}
      */
     public function replace(array $items)
     {
@@ -78,9 +61,7 @@ class Collection implements CollectionInterface
     }
 
     /**
-     * Get all items in collection
-     *
-     * @return array The collection's source data
+     * {@inheritdoc}
      */
     public function all()
     {
@@ -98,11 +79,7 @@ class Collection implements CollectionInterface
     }
 
     /**
-     * Does this collection have a given key?
-     *
-     * @param string $key The data key
-     *
-     * @return bool
+     * {@inheritdoc}
      */
     public function has($key)
     {
@@ -110,9 +87,7 @@ class Collection implements CollectionInterface
     }
 
     /**
-     * Remove item from collection
-     *
-     * @param string $key The data key
+     * {@inheritdoc}
      */
     public function remove($key)
     {
@@ -120,17 +95,13 @@ class Collection implements CollectionInterface
     }
 
     /**
-     * Remove all items from collection
+     * {@inheritdoc}
      */
     public function clear()
     {
         $this->data = [];
     }
 
-    /********************************************************************************
-     * ArrayAccess interface
-     *******************************************************************************/
-
     /**
      * Does this collection have a given key?
      *
@@ -186,14 +157,10 @@ class Collection implements CollectionInterface
         return count($this->data);
     }
 
-    /********************************************************************************
-     * IteratorAggregate interface
-     *******************************************************************************/
-
     /**
      * Get collection iterator
      *
-     * @return \ArrayIterator
+     * @return ArrayIterator
      */
     public function getIterator()
     {
diff --git a/vendor/slim/slim/Slim/Container.php b/vendor/slim/slim/Slim/Container.php
index 1f713ac4eabbd29e917c8951c785e3c040a19cd1..4641f6871af668ad6a8abb9345cdec86bba5a3f6 100644
--- a/vendor/slim/slim/Slim/Container.php
+++ b/vendor/slim/slim/Slim/Container.php
@@ -2,17 +2,18 @@
 /**
  * Slim Framework (https://slimframework.com)
  *
- * @link      https://github.com/slimphp/Slim
- * @copyright Copyright (c) 2011-2017 Josh Lockhart
- * @license   https://github.com/slimphp/Slim/blob/3.x/LICENSE.md (MIT License)
+ * @license https://github.com/slimphp/Slim/blob/3.x/LICENSE.md (MIT License)
  */
+
 namespace Slim;
 
-use Interop\Container\ContainerInterface;
-use Interop\Container\Exception\ContainerException;
+use ArrayAccess;
+use Psr\Container\ContainerInterface;
+use Psr\Container\ContainerExceptionInterface;
+use InvalidArgumentException;
 use Pimple\Container as PimpleContainer;
-use Slim\Exception\ContainerValueNotFoundException;
 use Slim\Exception\ContainerException as SlimContainerException;
+use Slim\Exception\ContainerValueNotFoundException;
 
 /**
  * Slim's default DI container is Pimple.
@@ -20,27 +21,16 @@ use Slim\Exception\ContainerException as SlimContainerException;
  * Slim\App expects a container that implements Psr\Container\ContainerInterface
  * with these service keys configured and ready for use:
  *
- *  - settings: an array or instance of \ArrayAccess
- *  - environment: an instance of \Slim\Interfaces\Http\EnvironmentInterface
- *  - request: an instance of \Psr\Http\Message\ServerRequestInterface
- *  - response: an instance of \Psr\Http\Message\ResponseInterface
- *  - router: an instance of \Slim\Interfaces\RouterInterface
- *  - foundHandler: an instance of \Slim\Interfaces\InvocationStrategyInterface
- *  - errorHandler: a callable with the signature: function($request, $response, $exception)
- *  - notFoundHandler: a callable with the signature: function($request, $response)
- *  - notAllowedHandler: a callable with the signature: function($request, $response, $allowedHttpMethods)
- *  - callableResolver: an instance of \Slim\Interfaces\CallableResolverInterface
- *
- * @property-read array settings
- * @property-read \Slim\Interfaces\Http\EnvironmentInterface environment
- * @property-read \Psr\Http\Message\ServerRequestInterface request
- * @property-read \Psr\Http\Message\ResponseInterface response
- * @property-read \Slim\Interfaces\RouterInterface router
- * @property-read \Slim\Interfaces\InvocationStrategyInterface foundHandler
- * @property-read callable errorHandler
- * @property-read callable notFoundHandler
- * @property-read callable notAllowedHandler
- * @property-read \Slim\Interfaces\CallableResolverInterface callableResolver
+ *  `settings`          an array or instance of \ArrayAccess
+ *  `environment`       an instance of \Slim\Http\Environment
+ *  `request`           an instance of \Psr\Http\Message\ServerRequestInterface
+ *  `response`          an instance of \Psr\Http\Message\ResponseInterface
+ *  `router`            an instance of \Slim\Interfaces\RouterInterface
+ *  `foundHandler`      an instance of \Slim\Interfaces\InvocationStrategyInterface
+ *  `errorHandler`      a callable with the signature: function($request, $response, $exception)
+ *  `notFoundHandler`   a callable with the signature: function($request, $response)
+ *  `notAllowedHandler` a callable with the signature: function($request, $response, $allowedHttpMethods)
+ *  `callableResolver`  an instance of \Slim\Interfaces\CallableResolverInterface
  */
 class Container extends PimpleContainer implements ContainerInterface
 {
@@ -60,8 +50,6 @@ class Container extends PimpleContainer implements ContainerInterface
     ];
 
     /**
-     * Create new container
-     *
      * @param array $values The parameters or objects.
      */
     public function __construct(array $values = [])
@@ -75,7 +63,7 @@ class Container extends PimpleContainer implements ContainerInterface
     /**
      * This function registers the default services that Slim needs to work.
      *
-     * All services are shared - that is, they are registered such that the
+     * All services are shared, they are registered such that the
      * same instance is returned on subsequent calls.
      *
      * @param array $userSettings Associative array of application settings
@@ -87,10 +75,9 @@ class Container extends PimpleContainer implements ContainerInterface
         $defaultSettings = $this->defaultSettings;
 
         /**
-         * This service MUST return an array or an
-         * instance of \ArrayAccess.
+         * This service MUST return an array or an instance of ArrayAccess.
          *
-         * @return array|\ArrayAccess
+         * @return array|ArrayAccess
          */
         $this['settings'] = function () use ($userSettings, $defaultSettings) {
             return new Collection(array_merge($defaultSettings, $userSettings));
@@ -100,19 +87,18 @@ class Container extends PimpleContainer implements ContainerInterface
         $defaultProvider->register($this);
     }
 
-    /********************************************************************************
-     * Methods to satisfy Psr\Container\ContainerInterface
-     *******************************************************************************/
-
     /**
      * Finds an entry of the container by its identifier and returns it.
      *
      * @param string $id Identifier of the entry to look for.
      *
-     * @throws ContainerValueNotFoundException  No entry was found for this identifier.
-     * @throws ContainerException               Error while retrieving the entry.
+     * @return mixed
      *
-     * @return mixed Entry.
+     * @throws InvalidArgumentException         Thrown when an offset cannot be found in the Pimple container
+     * @throws SlimContainerException           Thrown when an exception is
+     *         not an instance of ContainerExceptionInterface
+     * @throws ContainerValueNotFoundException  No entry was found for this identifier.
+     * @throws ContainerExceptionInterface      Error while retrieving the entry.
      */
     public function get($id)
     {
@@ -121,7 +107,7 @@ class Container extends PimpleContainer implements ContainerInterface
         }
         try {
             return $this->offsetGet($id);
-        } catch (\InvalidArgumentException $exception) {
+        } catch (InvalidArgumentException $exception) {
             if ($this->exceptionThrownByContainer($exception)) {
                 throw new SlimContainerException(
                     sprintf('Container error while retrieving "%s"', $id),
@@ -135,14 +121,14 @@ class Container extends PimpleContainer implements ContainerInterface
     }
 
     /**
-     * Tests whether an exception needs to be recast for compliance with Container-Interop.  This will be if the
+     * Tests whether an exception needs to be recast for compliance with psr/container.  This will be if the
      * exception was thrown by Pimple.
      *
-     * @param \InvalidArgumentException $exception
+     * @param InvalidArgumentException $exception
      *
      * @return bool
      */
-    private function exceptionThrownByContainer(\InvalidArgumentException $exception)
+    private function exceptionThrownByContainer(InvalidArgumentException $exception)
     {
         $trace = $exception->getTrace()[0];
 
@@ -162,16 +148,26 @@ class Container extends PimpleContainer implements ContainerInterface
         return $this->offsetExists($id);
     }
 
-
-    /********************************************************************************
-     * Magic methods for convenience
-     *******************************************************************************/
-
+    /**
+     * @param string $name
+     *
+     * @return mixed
+     *
+     * @throws InvalidArgumentException         Thrown when an offset cannot be found in the Pimple container
+     * @throws SlimContainerException           Thrown when an exception is not
+     *         an instance of ContainerExceptionInterface
+     * @throws ContainerValueNotFoundException  No entry was found for this identifier.
+     * @throws ContainerExceptionInterface      Error while retrieving the entry.
+     */
     public function __get($name)
     {
         return $this->get($name);
     }
 
+    /**
+     * @param string $name
+     * @return bool
+     */
     public function __isset($name)
     {
         return $this->has($name);
diff --git a/vendor/slim/slim/Slim/DefaultServicesProvider.php b/vendor/slim/slim/Slim/DefaultServicesProvider.php
index 13fe1fb31ce3f7e82eb307572a8d6f1e9569e985..48a8d6e08822e04b4cee0e8d18ee9f9d34f31820 100644
--- a/vendor/slim/slim/Slim/DefaultServicesProvider.php
+++ b/vendor/slim/slim/Slim/DefaultServicesProvider.php
@@ -2,46 +2,40 @@
 /**
  * Slim Framework (https://slimframework.com)
  *
- * @link      https://github.com/slimphp/Slim
- * @copyright Copyright (c) 2011-2017 Josh Lockhart
- * @license   https://github.com/slimphp/Slim/blob/3.x/LICENSE.md (MIT License)
+ * @license https://github.com/slimphp/Slim/blob/3.x/LICENSE.md (MIT License)
  */
+
 namespace Slim;
 
 use Psr\Http\Message\ResponseInterface;
 use Psr\Http\Message\ServerRequestInterface;
-use Slim\Handlers\PhpError;
 use Slim\Handlers\Error;
-use Slim\Handlers\NotFound;
 use Slim\Handlers\NotAllowed;
+use Slim\Handlers\NotFound;
+use Slim\Handlers\PhpError;
 use Slim\Handlers\Strategies\RequestResponse;
 use Slim\Http\Environment;
 use Slim\Http\Headers;
 use Slim\Http\Request;
 use Slim\Http\Response;
 use Slim\Interfaces\CallableResolverInterface;
-use Slim\Interfaces\Http\EnvironmentInterface;
 use Slim\Interfaces\InvocationStrategyInterface;
 use Slim\Interfaces\RouterInterface;
 
-/**
- * Slim's default Service Provider.
- */
 class DefaultServicesProvider
 {
     /**
      * Register Slim's default services.
      *
-     * @param Container $container A DI container implementing ArrayAccess and container-interop.
+     * @param Container $container A DI container implementing ArrayAccess and psr/container.
      */
     public function register($container)
     {
         if (!isset($container['environment'])) {
             /**
-             * This service MUST return a shared instance
-             * of \Slim\Interfaces\Http\EnvironmentInterface.
+             * This service MUST return a shared instance of \Slim\Http\Environment.
              *
-             * @return EnvironmentInterface
+             * @return Environment
              */
             $container['environment'] = function () {
                 return new Environment($_SERVER);
@@ -79,8 +73,7 @@ class DefaultServicesProvider
 
         if (!isset($container['router'])) {
             /**
-             * This service MUST return a SHARED instance
-             * of \Slim\Interfaces\RouterInterface.
+             * This service MUST return a shared instance of \Slim\Interfaces\RouterInterface.
              *
              * @param Container $container
              *
@@ -92,7 +85,6 @@ class DefaultServicesProvider
                     $routerCacheFile = $container->get('settings')['routerCacheFile'];
                 }
 
-
                 $router = (new Router)->setCacheFile($routerCacheFile);
                 if (method_exists($router, 'setContainer')) {
                     $router->setContainer($container);
@@ -104,8 +96,7 @@ class DefaultServicesProvider
 
         if (!isset($container['foundHandler'])) {
             /**
-             * This service MUST return a SHARED instance
-             * of \Slim\Interfaces\InvocationStrategyInterface.
+             * This service MUST return a SHARED instance InvocationStrategyInterface.
              *
              * @return InvocationStrategyInterface
              */
@@ -116,15 +107,13 @@ class DefaultServicesProvider
 
         if (!isset($container['phpErrorHandler'])) {
             /**
-             * This service MUST return a callable
-             * that accepts three arguments:
+             * This service MUST return a callable that accepts three arguments:
              *
-             * 1. Instance of \Psr\Http\Message\ServerRequestInterface
-             * 2. Instance of \Psr\Http\Message\ResponseInterface
-             * 3. Instance of \Error
+             * 1. Instance of ServerRequestInterface
+             * 2. Instance of ResponseInterface
+             * 3. Instance of Error
              *
-             * The callable MUST return an instance of
-             * \Psr\Http\Message\ResponseInterface.
+             * The callable MUST return an instance of ResponseInterface.
              *
              * @param Container $container
              *
@@ -137,15 +126,13 @@ class DefaultServicesProvider
 
         if (!isset($container['errorHandler'])) {
             /**
-             * This service MUST return a callable
-             * that accepts three arguments:
+             * This service MUST return a callable that accepts three arguments:
              *
              * 1. Instance of \Psr\Http\Message\ServerRequestInterface
              * 2. Instance of \Psr\Http\Message\ResponseInterface
              * 3. Instance of \Exception
              *
-             * The callable MUST return an instance of
-             * \Psr\Http\Message\ResponseInterface.
+             * The callable MUST return an instance of ResponseInterface.
              *
              * @param Container $container
              *
@@ -160,14 +147,12 @@ class DefaultServicesProvider
 
         if (!isset($container['notFoundHandler'])) {
             /**
-             * This service MUST return a callable
-             * that accepts two arguments:
+             * This service MUST return a callable that accepts two arguments:
              *
-             * 1. Instance of \Psr\Http\Message\ServerRequestInterface
-             * 2. Instance of \Psr\Http\Message\ResponseInterface
+             * 1. Instance of ServerRequestInterface
+             * 2. Instance of ResponseInterface
              *
-             * The callable MUST return an instance of
-             * \Psr\Http\Message\ResponseInterface.
+             * The callable MUST return an instance of ResponseInterface.
              *
              * @return callable
              */
@@ -178,15 +163,13 @@ class DefaultServicesProvider
 
         if (!isset($container['notAllowedHandler'])) {
             /**
-             * This service MUST return a callable
-             * that accepts three arguments:
+             * This service MUST return a callable that accepts three arguments:
              *
-             * 1. Instance of \Psr\Http\Message\ServerRequestInterface
-             * 2. Instance of \Psr\Http\Message\ResponseInterface
+             * 1. Instance of ServerRequestInterface
+             * 2. Instance of ResponseInterface
              * 3. Array of allowed HTTP methods
              *
-             * The callable MUST return an instance of
-             * \Psr\Http\Message\ResponseInterface.
+             * The callable MUST return an instance of ResponseInterface.
              *
              * @return callable
              */
@@ -197,7 +180,7 @@ class DefaultServicesProvider
 
         if (!isset($container['callableResolver'])) {
             /**
-             * Instance of \Slim\Interfaces\CallableResolverInterface
+             * Instance of CallableResolverInterface
              *
              * @param Container $container
              *
diff --git a/vendor/slim/slim/Slim/DeferredCallable.php b/vendor/slim/slim/Slim/DeferredCallable.php
index 22887c0fce637a218d440ca0db53d586a27c2e50..5f335841ca5b3040f4b4d0801e8e9b668b0f6deb 100644
--- a/vendor/slim/slim/Slim/DeferredCallable.php
+++ b/vendor/slim/slim/Slim/DeferredCallable.php
@@ -2,9 +2,7 @@
 /**
  * Slim Framework (https://slimframework.com)
  *
- * @link      https://github.com/slimphp/Slim
- * @copyright Copyright (c) 2011-2017 Josh Lockhart
- * @license   https://github.com/slimphp/Slim/blob/3.x/LICENSE.md (MIT License)
+ * @license https://github.com/slimphp/Slim/blob/3.x/LICENSE.md (MIT License)
  */
 
 namespace Slim;
@@ -16,12 +14,17 @@ class DeferredCallable
 {
     use CallableResolverAwareTrait;
 
+    /**
+     * @var callable|string
+     */
     private $callable;
-    /** @var  ContainerInterface */
+
+    /**
+     * @var ContainerInterface
+     */
     private $container;
 
     /**
-     * DeferredMiddleware constructor.
      * @param callable|string $callable
      * @param ContainerInterface $container
      */
@@ -31,6 +34,17 @@ class DeferredCallable
         $this->container = $container;
     }
 
+    /**
+     * @return callable|string
+     */
+    public function getCallable()
+    {
+        return $this->callable;
+    }
+
+    /**
+     * @return mixed
+     */
     public function __invoke()
     {
         $callable = $this->resolveCallable($this->callable);
diff --git a/vendor/slim/slim/Slim/Exception/ContainerException.php b/vendor/slim/slim/Slim/Exception/ContainerException.php
index 06163f1da059e918ab443f83d927c6d3e7bbec4e..fb0184986734b2a27a313b5a0c70b7f38a7329f6 100644
--- a/vendor/slim/slim/Slim/Exception/ContainerException.php
+++ b/vendor/slim/slim/Slim/Exception/ContainerException.php
@@ -2,19 +2,14 @@
 /**
  * Slim Framework (https://slimframework.com)
  *
- * @link      https://github.com/slimphp/Slim
- * @copyright Copyright (c) 2011-2017 Josh Lockhart
- * @license   https://github.com/slimphp/Slim/blob/3.x/LICENSE.md (MIT License)
+ * @license https://github.com/slimphp/Slim/blob/3.x/LICENSE.md (MIT License)
  */
+
 namespace Slim\Exception;
 
+use Psr\Container\ContainerExceptionInterface;
 use InvalidArgumentException;
-use Interop\Container\Exception\ContainerException as InteropContainerException;
 
-/**
- * Container Exception
- */
-class ContainerException extends InvalidArgumentException implements InteropContainerException
+class ContainerException extends InvalidArgumentException implements ContainerExceptionInterface
 {
-
 }
diff --git a/vendor/slim/slim/Slim/Exception/ContainerValueNotFoundException.php b/vendor/slim/slim/Slim/Exception/ContainerValueNotFoundException.php
index 33de07e38cf84635063dc9afb67df38f7e5fa2e7..0c715935b03f880c5b0978f989b05c862e0a1735 100644
--- a/vendor/slim/slim/Slim/Exception/ContainerValueNotFoundException.php
+++ b/vendor/slim/slim/Slim/Exception/ContainerValueNotFoundException.php
@@ -2,19 +2,14 @@
 /**
  * Slim Framework (https://slimframework.com)
  *
- * @link      https://github.com/slimphp/Slim
- * @copyright Copyright (c) 2011-2017 Josh Lockhart
- * @license   https://github.com/slimphp/Slim/blob/3.x/LICENSE.md (MIT License)
+ * @license https://github.com/slimphp/Slim/blob/3.x/LICENSE.md (MIT License)
  */
+
 namespace Slim\Exception;
 
+use Psr\Container\NotFoundExceptionInterface;
 use RuntimeException;
-use Interop\Container\Exception\NotFoundException as InteropNotFoundException;
 
-/**
- * Not Found Exception
- */
-class ContainerValueNotFoundException extends RuntimeException implements InteropNotFoundException
+class ContainerValueNotFoundException extends RuntimeException implements NotFoundExceptionInterface
 {
-
 }
diff --git a/vendor/slim/slim/Slim/Exception/InvalidMethodException.php b/vendor/slim/slim/Slim/Exception/InvalidMethodException.php
index 4aabf8337d36c55099f7b49ba1cbf0818e16237a..7bbc3fd8286a7d395c432648b914ef81e59d3a8f 100644
--- a/vendor/slim/slim/Slim/Exception/InvalidMethodException.php
+++ b/vendor/slim/slim/Slim/Exception/InvalidMethodException.php
@@ -2,24 +2,34 @@
 /**
  * Slim Framework (https://slimframework.com)
  *
- * @link      https://github.com/slimphp/Slim
- * @copyright Copyright (c) 2011-2017 Josh Lockhart
- * @license   https://github.com/slimphp/Slim/blob/3.x/LICENSE.md (MIT License)
+ * @license https://github.com/slimphp/Slim/blob/3.x/LICENSE.md (MIT License)
  */
+
 namespace Slim\Exception;
 
+use InvalidArgumentException;
 use Psr\Http\Message\ServerRequestInterface;
 
-class InvalidMethodException extends \InvalidArgumentException
+class InvalidMethodException extends InvalidArgumentException
 {
+    /**
+     * @var ServerRequestInterface
+     */
     protected $request;
 
+    /**
+     * @param ServerRequestInterface $request
+     * @param string                 $method
+     */
     public function __construct(ServerRequestInterface $request, $method)
     {
         $this->request = $request;
         parent::__construct(sprintf('Unsupported HTTP method "%s" provided', $method));
     }
 
+    /**
+     * @return ServerRequestInterface
+     */
     public function getRequest()
     {
         return $this->request;
diff --git a/vendor/slim/slim/Slim/Exception/MethodNotAllowedException.php b/vendor/slim/slim/Slim/Exception/MethodNotAllowedException.php
index 951f5dfbe1ab99fc9506a8d758da37621eb33b60..20d38248ff1b5ad6df3b4d8833d5c65a0389af5b 100644
--- a/vendor/slim/slim/Slim/Exception/MethodNotAllowedException.php
+++ b/vendor/slim/slim/Slim/Exception/MethodNotAllowedException.php
@@ -2,30 +2,25 @@
 /**
  * Slim Framework (https://slimframework.com)
  *
- * @link      https://github.com/slimphp/Slim
- * @copyright Copyright (c) 2011-2017 Josh Lockhart
- * @license   https://github.com/slimphp/Slim/blob/3.x/LICENSE.md (MIT License)
+ * @license https://github.com/slimphp/Slim/blob/3.x/LICENSE.md (MIT License)
  */
+
 namespace Slim\Exception;
 
-use Psr\Http\Message\ServerRequestInterface;
 use Psr\Http\Message\ResponseInterface;
+use Psr\Http\Message\ServerRequestInterface;
 
 class MethodNotAllowedException extends SlimException
 {
     /**
-     * HTTP methods allowed
-     *
      * @var string[]
      */
     protected $allowedMethods;
 
     /**
-     * Create new exception
-     *
      * @param ServerRequestInterface $request
-     * @param ResponseInterface $response
-     * @param string[] $allowedMethods
+     * @param ResponseInterface      $response
+     * @param string[]               $allowedMethods
      */
     public function __construct(ServerRequestInterface $request, ResponseInterface $response, array $allowedMethods)
     {
@@ -34,8 +29,6 @@ class MethodNotAllowedException extends SlimException
     }
 
     /**
-     * Get allowed methods
-     *
      * @return string[]
      */
     public function getAllowedMethods()
diff --git a/vendor/slim/slim/Slim/Exception/NotFoundException.php b/vendor/slim/slim/Slim/Exception/NotFoundException.php
index 9e72e14e63bcded6538f229f99047a20f13e08d8..5bbbbe69a8d64ba361f49ddd458412907fba374b 100644
--- a/vendor/slim/slim/Slim/Exception/NotFoundException.php
+++ b/vendor/slim/slim/Slim/Exception/NotFoundException.php
@@ -2,13 +2,11 @@
 /**
  * Slim Framework (https://slimframework.com)
  *
- * @link      https://github.com/slimphp/Slim
- * @copyright Copyright (c) 2011-2017 Josh Lockhart
- * @license   https://github.com/slimphp/Slim/blob/3.x/LICENSE.md (MIT License)
+ * @license https://github.com/slimphp/Slim/blob/3.x/LICENSE.md (MIT License)
  */
+
 namespace Slim\Exception;
 
 class NotFoundException extends SlimException
 {
-
 }
diff --git a/vendor/slim/slim/Slim/Exception/SlimException.php b/vendor/slim/slim/Slim/Exception/SlimException.php
index 2480d73b1c372acb26c3bb85598cd83511e2c399..5b15a4a02cf7c62ed5d7daf4ba33c9db0f65cfd9 100644
--- a/vendor/slim/slim/Slim/Exception/SlimException.php
+++ b/vendor/slim/slim/Slim/Exception/SlimException.php
@@ -2,43 +2,30 @@
 /**
  * Slim Framework (https://slimframework.com)
  *
- * @link      https://github.com/slimphp/Slim
- * @copyright Copyright (c) 2011-2017 Josh Lockhart
- * @license   https://github.com/slimphp/Slim/blob/3.x/LICENSE.md (MIT License)
+ * @license https://github.com/slimphp/Slim/blob/3.x/LICENSE.md (MIT License)
  */
+
 namespace Slim\Exception;
 
 use Exception;
-use Psr\Http\Message\ServerRequestInterface;
 use Psr\Http\Message\ResponseInterface;
+use Psr\Http\Message\ServerRequestInterface;
 
-/**
- * Stop Exception
- *
- * This Exception is thrown when the Slim application needs to abort
- * processing and return control flow to the outer PHP script.
- */
 class SlimException extends Exception
 {
     /**
-     * A request object
-     *
      * @var ServerRequestInterface
      */
     protected $request;
 
     /**
-     * A response object to send to the HTTP client
-     *
      * @var ResponseInterface
      */
     protected $response;
 
     /**
-     * Create new exception
-     *
      * @param ServerRequestInterface $request
-     * @param ResponseInterface $response
+     * @param ResponseInterface      $response
      */
     public function __construct(ServerRequestInterface $request, ResponseInterface $response)
     {
@@ -48,8 +35,6 @@ class SlimException extends Exception
     }
 
     /**
-     * Get request
-     *
      * @return ServerRequestInterface
      */
     public function getRequest()
@@ -58,8 +43,6 @@ class SlimException extends Exception
     }
 
     /**
-     * Get response
-     *
      * @return ResponseInterface
      */
     public function getResponse()
diff --git a/vendor/slim/slim/Slim/Handlers/AbstractError.php b/vendor/slim/slim/Slim/Handlers/AbstractError.php
index 42f8dde3df0661ce24625f227f2a3abe7764af13..256062f7bba880e4084318725d82fdf7d3734094 100644
--- a/vendor/slim/slim/Slim/Handlers/AbstractError.php
+++ b/vendor/slim/slim/Slim/Handlers/AbstractError.php
@@ -2,15 +2,14 @@
 /**
  * Slim Framework (https://slimframework.com)
  *
- * @link      https://github.com/slimphp/Slim
- * @copyright Copyright (c) 2011-2017 Josh Lockhart
- * @license   https://github.com/slimphp/Slim/blob/3.x/LICENSE.md (MIT License)
+ * @license https://github.com/slimphp/Slim/blob/3.x/LICENSE.md (MIT License)
  */
+
 namespace Slim\Handlers;
 
-/**
- * Abstract Slim application error handler
- */
+use Exception;
+use Throwable;
+
 abstract class AbstractError extends AbstractHandler
 {
     /**
@@ -19,8 +18,6 @@ abstract class AbstractError extends AbstractHandler
     protected $displayErrorDetails;
 
     /**
-     * Constructor
-     *
      * @param bool $displayErrorDetails Set to true to display full details
      */
     public function __construct($displayErrorDetails = false)
@@ -31,7 +28,7 @@ abstract class AbstractError extends AbstractHandler
     /**
      * Write to the error log if displayErrorDetails is false
      *
-     * @param \Exception|\Throwable $throwable
+     * @param Exception|Throwable $throwable
      *
      * @return void
      */
@@ -56,7 +53,7 @@ abstract class AbstractError extends AbstractHandler
     /**
      * Render error as Text.
      *
-     * @param \Exception|\Throwable $throwable
+     * @param Exception|Throwable $throwable
      *
      * @return string
      */
@@ -90,7 +87,7 @@ abstract class AbstractError extends AbstractHandler
     /**
      * Wraps the error_log function so that this can be easily tested
      *
-     * @param $message
+     * @param string $message
      */
     protected function logError($message)
     {
diff --git a/vendor/slim/slim/Slim/Handlers/AbstractHandler.php b/vendor/slim/slim/Slim/Handlers/AbstractHandler.php
index b166a1564431c2755e17a218c11b03ffd033c6ae..5ace9a0fe20f3af598fe486d75b9dc9e8592fd2d 100644
--- a/vendor/slim/slim/Slim/Handlers/AbstractHandler.php
+++ b/vendor/slim/slim/Slim/Handlers/AbstractHandler.php
@@ -2,17 +2,13 @@
 /**
  * Slim Framework (https://slimframework.com)
  *
- * @link      https://github.com/slimphp/Slim
- * @copyright Copyright (c) 2011-2017 Josh Lockhart
- * @license   https://github.com/slimphp/Slim/blob/3.x/LICENSE.md (MIT License)
+ * @license https://github.com/slimphp/Slim/blob/3.x/LICENSE.md (MIT License)
  */
+
 namespace Slim\Handlers;
 
 use Psr\Http\Message\ServerRequestInterface;
 
-/**
- * Abstract Slim application handler
- */
 abstract class AbstractHandler
 {
     /**
@@ -28,13 +24,14 @@ abstract class AbstractHandler
     ];
 
     /**
-     * Determine which content type we know about is wanted using Accept header
+     * Determine which content type we know about is wanted using `Accept` header
      *
      * Note: This method is a bare-bones implementation designed specifically for
      * Slim's error handling requirements. Consider a fully-feature solution such
      * as willdurand/negotiation for any other situation.
      *
      * @param ServerRequestInterface $request
+     *
      * @return string
      */
     protected function determineContentType(ServerRequestInterface $request)
diff --git a/vendor/slim/slim/Slim/Handlers/Error.php b/vendor/slim/slim/Slim/Handlers/Error.php
index dd0bc8d4e7a5cf14aa06ea30241806126327f98a..50ece96567690bb1b47276f7530e7a16f74f74d9 100644
--- a/vendor/slim/slim/Slim/Handlers/Error.php
+++ b/vendor/slim/slim/Slim/Handlers/Error.php
@@ -2,36 +2,30 @@
 /**
  * Slim Framework (https://slimframework.com)
  *
- * @link      https://github.com/slimphp/Slim
- * @copyright Copyright (c) 2011-2017 Josh Lockhart
- * @license   https://github.com/slimphp/Slim/blob/3.x/LICENSE.md (MIT License)
+ * @license https://github.com/slimphp/Slim/blob/3.x/LICENSE.md (MIT License)
  */
+
 namespace Slim\Handlers;
 
+use Exception;
 use Psr\Http\Message\ResponseInterface;
 use Psr\Http\Message\ServerRequestInterface;
+use RuntimeException;
 use Slim\Http\Body;
 use UnexpectedValueException;
 
-/**
- * Default Slim application error handler
- *
- * It outputs the error message and diagnostic information in either JSON, XML,
- * or HTML based on the Accept header.
- */
 class Error extends AbstractError
 {
     /**
-     * Invoke error handler
-     *
      * @param ServerRequestInterface $request   The most recent Request object
      * @param ResponseInterface      $response  The most recent Response object
-     * @param \Exception             $exception The caught Exception object
+     * @param Exception              $exception The caught Exception object
      *
      * @return ResponseInterface
+     *
      * @throws UnexpectedValueException
      */
-    public function __invoke(ServerRequestInterface $request, ResponseInterface $response, \Exception $exception)
+    public function __invoke(ServerRequestInterface $request, ResponseInterface $response, Exception $exception)
     {
         $contentType = $this->determineContentType($request);
         switch ($contentType) {
@@ -66,11 +60,11 @@ class Error extends AbstractError
     /**
      * Render HTML error page
      *
-     * @param  \Exception $exception
+     * @param  Exception $exception
      *
      * @return string
      */
-    protected function renderHtmlErrorMessage(\Exception $exception)
+    protected function renderHtmlErrorMessage(Exception $exception)
     {
         $title = 'Slim Application Error';
 
@@ -105,11 +99,11 @@ class Error extends AbstractError
      *
      * Provided for backwards compatibility; use renderHtmlExceptionOrError().
      *
-     * @param \Exception $exception
+     * @param Exception $exception
      *
      * @return string
      */
-    protected function renderHtmlException(\Exception $exception)
+    protected function renderHtmlException(Exception $exception)
     {
         return $this->renderHtmlExceptionOrError($exception);
     }
@@ -117,14 +111,16 @@ class Error extends AbstractError
     /**
      * Render exception or error as HTML.
      *
-     * @param \Exception|\Error $exception
+     * @param Exception|\Error $exception
      *
      * @return string
+     *
+     * @throws RuntimeException
      */
     protected function renderHtmlExceptionOrError($exception)
     {
-        if (!$exception instanceof \Exception && !$exception instanceof \Error) {
-            throw new \RuntimeException("Unexpected type. Expected Exception or Error.");
+        if (!$exception instanceof Exception && !$exception instanceof \Error) {
+            throw new RuntimeException("Unexpected type. Expected Exception or Error.");
         }
 
         $html = sprintf('<div><strong>Type:</strong> %s</div>', get_class($exception));
@@ -156,11 +152,11 @@ class Error extends AbstractError
     /**
      * Render JSON error
      *
-     * @param \Exception $exception
+     * @param Exception $exception
      *
      * @return string
      */
-    protected function renderJsonErrorMessage(\Exception $exception)
+    protected function renderJsonErrorMessage(Exception $exception)
     {
         $error = [
             'message' => 'Slim Application Error',
@@ -187,11 +183,11 @@ class Error extends AbstractError
     /**
      * Render XML error
      *
-     * @param \Exception $exception
+     * @param Exception $exception
      *
      * @return string
      */
-    protected function renderXmlErrorMessage(\Exception $exception)
+    protected function renderXmlErrorMessage(Exception $exception)
     {
         $xml = "<error>\n  <message>Slim Application Error</message>\n";
         if ($this->displayErrorDetails) {
@@ -215,6 +211,7 @@ class Error extends AbstractError
      * Returns a CDATA section with the given content.
      *
      * @param  string $content
+     *
      * @return string
      */
     private function createCdataSection($content)
diff --git a/vendor/slim/slim/Slim/Handlers/NotAllowed.php b/vendor/slim/slim/Slim/Handlers/NotAllowed.php
index 345f0ff8c42f1940c3e8e7f8ca9555e982c85211..5eba80bec5445397ba84364fcf481bcc431e34c9 100644
--- a/vendor/slim/slim/Slim/Handlers/NotAllowed.php
+++ b/vendor/slim/slim/Slim/Handlers/NotAllowed.php
@@ -2,33 +2,25 @@
 /**
  * Slim Framework (https://slimframework.com)
  *
- * @link      https://github.com/slimphp/Slim
- * @copyright Copyright (c) 2011-2017 Josh Lockhart
- * @license   https://github.com/slimphp/Slim/blob/3.x/LICENSE.md (MIT License)
+ * @license https://github.com/slimphp/Slim/blob/3.x/LICENSE.md (MIT License)
  */
+
 namespace Slim\Handlers;
 
-use Psr\Http\Message\ServerRequestInterface;
 use Psr\Http\Message\ResponseInterface;
+use Psr\Http\Message\ServerRequestInterface;
 use Slim\Http\Body;
 use UnexpectedValueException;
 
-/**
- * Default Slim application not allowed handler
- *
- * It outputs a simple message in either JSON, XML or HTML based on the
- * Accept header.
- */
 class NotAllowed extends AbstractHandler
 {
     /**
-     * Invoke error handler
-     *
      * @param  ServerRequestInterface $request  The most recent Request object
      * @param  ResponseInterface      $response The most recent Response object
      * @param  string[]               $methods  Allowed HTTP methods
      *
      * @return ResponseInterface
+     *
      * @throws UnexpectedValueException
      */
     public function __invoke(ServerRequestInterface $request, ResponseInterface $response, array $methods)
@@ -70,9 +62,10 @@ class NotAllowed extends AbstractHandler
     }
 
     /**
-     * Render PLAIN message for OPTIONS response
+     * Render plain message for OPTIONS response
+     *
+     * @param  string[] $methods
      *
-     * @param  array                  $methods
      * @return string
      */
     protected function renderPlainOptionsMessage($methods)
@@ -85,7 +78,8 @@ class NotAllowed extends AbstractHandler
     /**
      * Render JSON not allowed message
      *
-     * @param  array                  $methods
+     * @param  string[] $methods
+     *
      * @return string
      */
     protected function renderJsonNotAllowedMessage($methods)
@@ -98,7 +92,8 @@ class NotAllowed extends AbstractHandler
     /**
      * Render XML not allowed message
      *
-     * @param  array                  $methods
+     * @param  string[] $methods
+     *
      * @return string
      */
     protected function renderXmlNotAllowedMessage($methods)
@@ -111,7 +106,8 @@ class NotAllowed extends AbstractHandler
     /**
      * Render HTML not allowed message
      *
-     * @param  array                  $methods
+     * @param  string[] $methods
+     *
      * @return string
      */
     protected function renderHtmlNotAllowedMessage($methods)
diff --git a/vendor/slim/slim/Slim/Handlers/NotFound.php b/vendor/slim/slim/Slim/Handlers/NotFound.php
index b3330321ff38729d4547477c5d9f2e4cc434fbf4..f0d013c6961783931a7d0f7363e62cfa0ecb0ef0 100644
--- a/vendor/slim/slim/Slim/Handlers/NotFound.php
+++ b/vendor/slim/slim/Slim/Handlers/NotFound.php
@@ -2,32 +2,24 @@
 /**
  * Slim Framework (https://slimframework.com)
  *
- * @link      https://github.com/slimphp/Slim
- * @copyright Copyright (c) 2011-2017 Josh Lockhart
- * @license   https://github.com/slimphp/Slim/blob/3.x/LICENSE.md (MIT License)
+ * @license https://github.com/slimphp/Slim/blob/3.x/LICENSE.md (MIT License)
  */
+
 namespace Slim\Handlers;
 
-use Psr\Http\Message\ServerRequestInterface;
 use Psr\Http\Message\ResponseInterface;
+use Psr\Http\Message\ServerRequestInterface;
 use Slim\Http\Body;
 use UnexpectedValueException;
 
-/**
- * Default Slim application not found handler.
- *
- * It outputs a simple message in either JSON, XML or HTML based on the
- * Accept header.
- */
 class NotFound extends AbstractHandler
 {
     /**
-     * Invoke not found handler
-     *
      * @param  ServerRequestInterface $request  The most recent Request object
      * @param  ResponseInterface      $response The most recent Response object
      *
      * @return ResponseInterface
+     *
      * @throws UnexpectedValueException
      */
     public function __invoke(ServerRequestInterface $request, ResponseInterface $response)
@@ -67,7 +59,7 @@ class NotFound extends AbstractHandler
     /**
      * Render plain not found message
      *
-     * @return ResponseInterface
+     * @return string
      */
     protected function renderPlainNotFoundOutput()
     {
@@ -77,7 +69,7 @@ class NotFound extends AbstractHandler
     /**
      * Return a response for application/json content not found
      *
-     * @return ResponseInterface
+     * @return string
      */
     protected function renderJsonNotFoundOutput()
     {
@@ -87,7 +79,7 @@ class NotFound extends AbstractHandler
     /**
      * Return a response for xml content not found
      *
-     * @return ResponseInterface
+     * @return string
      */
     protected function renderXmlNotFoundOutput()
     {
@@ -97,9 +89,9 @@ class NotFound extends AbstractHandler
     /**
      * Return a response for text/html content not found
      *
-     * @param  ServerRequestInterface $request  The most recent Request object
+     * @param  ServerRequestInterface $request The most recent Request object
      *
-     * @return ResponseInterface
+     * @return string
      */
     protected function renderHtmlNotFoundOutput(ServerRequestInterface $request)
     {
diff --git a/vendor/slim/slim/Slim/Handlers/PhpError.php b/vendor/slim/slim/Slim/Handlers/PhpError.php
index 3ecce30cfaf05a953749a6a864f6b26e91cc1957..28c74162148ff3c3b9dffb361d4f617a2737a659 100644
--- a/vendor/slim/slim/Slim/Handlers/PhpError.php
+++ b/vendor/slim/slim/Slim/Handlers/PhpError.php
@@ -2,36 +2,29 @@
 /**
  * Slim Framework (https://slimframework.com)
  *
- * @link      https://github.com/slimphp/Slim
- * @copyright Copyright (c) 2011-2017 Josh Lockhart
- * @license   https://github.com/slimphp/Slim/blob/3.x/LICENSE.md (MIT License)
+ * @license https://github.com/slimphp/Slim/blob/3.x/LICENSE.md (MIT License)
  */
+
 namespace Slim\Handlers;
 
 use Psr\Http\Message\ResponseInterface;
 use Psr\Http\Message\ServerRequestInterface;
 use Slim\Http\Body;
+use Throwable;
 use UnexpectedValueException;
 
-/**
- * Default Slim application error handler for PHP 7+ Throwables
- *
- * It outputs the error message and diagnostic information in either JSON, XML,
- * or HTML based on the Accept header.
- */
 class PhpError extends AbstractError
 {
     /**
-     * Invoke error handler
-     *
-     * @param ServerRequestInterface $request   The most recent Request object
-     * @param ResponseInterface      $response  The most recent Response object
-     * @param \Throwable             $error     The caught Throwable object
+     * @param ServerRequestInterface $request  The most recent Request object
+     * @param ResponseInterface      $response The most recent Response object
+     * @param Throwable              $error    The caught Throwable object
      *
      * @return ResponseInterface
+     *
      * @throws UnexpectedValueException
      */
-    public function __invoke(ServerRequestInterface $request, ResponseInterface $response, \Throwable $error)
+    public function __invoke(ServerRequestInterface $request, ResponseInterface $response, Throwable $error)
     {
         $contentType = $this->determineContentType($request);
         switch ($contentType) {
@@ -65,11 +58,11 @@ class PhpError extends AbstractError
     /**
      * Render HTML error page
      *
-     * @param \Throwable $error
+     * @param Throwable $error
      *
      * @return string
      */
-    protected function renderHtmlErrorMessage(\Throwable $error)
+    protected function renderHtmlErrorMessage(Throwable $error)
     {
         $title = 'Slim Application Error';
 
@@ -102,11 +95,11 @@ class PhpError extends AbstractError
     /**
      * Render error as HTML.
      *
-     * @param \Throwable $error
+     * @param Throwable $error
      *
      * @return string
      */
-    protected function renderHtmlError(\Throwable $error)
+    protected function renderHtmlError(Throwable $error)
     {
         $html = sprintf('<div><strong>Type:</strong> %s</div>', get_class($error));
 
@@ -137,11 +130,11 @@ class PhpError extends AbstractError
     /**
      * Render JSON error
      *
-     * @param \Throwable $error
+     * @param Throwable $error
      *
      * @return string
      */
-    protected function renderJsonErrorMessage(\Throwable $error)
+    protected function renderJsonErrorMessage(Throwable $error)
     {
         $json = [
             'message' => 'Slim Application Error',
@@ -168,11 +161,11 @@ class PhpError extends AbstractError
     /**
      * Render XML error
      *
-     * @param \Throwable $error
+     * @param Throwable $error
      *
      * @return string
      */
-    protected function renderXmlErrorMessage(\Throwable $error)
+    protected function renderXmlErrorMessage(Throwable $error)
     {
         $xml = "<error>\n  <message>Slim Application Error</message>\n";
         if ($this->displayErrorDetails) {
@@ -196,6 +189,7 @@ class PhpError extends AbstractError
      * Returns a CDATA section with the given content.
      *
      * @param  string $content
+     *
      * @return string
      */
     private function createCdataSection($content)
diff --git a/vendor/slim/slim/Slim/Handlers/Strategies/RequestResponse.php b/vendor/slim/slim/Slim/Handlers/Strategies/RequestResponse.php
index ad99b56e865551ada283a85877e5eb7c5799dc99..d91b05aeb357da339dba5681ff1e289cb43d7f71 100644
--- a/vendor/slim/slim/Slim/Handlers/Strategies/RequestResponse.php
+++ b/vendor/slim/slim/Slim/Handlers/Strategies/RequestResponse.php
@@ -2,10 +2,9 @@
 /**
  * Slim Framework (https://slimframework.com)
  *
- * @link      https://github.com/slimphp/Slim
- * @copyright Copyright (c) 2011-2017 Josh Lockhart
- * @license   https://github.com/slimphp/Slim/blob/3.x/LICENSE.md (MIT License)
+ * @license https://github.com/slimphp/Slim/blob/3.x/LICENSE.md (MIT License)
  */
+
 namespace Slim\Handlers\Strategies;
 
 use Psr\Http\Message\ResponseInterface;
@@ -26,7 +25,7 @@ class RequestResponse implements InvocationStrategyInterface
      * @param ResponseInterface      $response
      * @param array                  $routeArguments
      *
-     * @return mixed
+     * @return ResponseInterface
      */
     public function __invoke(
         callable $callable,
diff --git a/vendor/slim/slim/Slim/Handlers/Strategies/RequestResponseArgs.php b/vendor/slim/slim/Slim/Handlers/Strategies/RequestResponseArgs.php
index 739cc7ee88f845fde8f8f0121497802d610cde28..d0729145e811f53957a283cc6acba5746018e858 100644
--- a/vendor/slim/slim/Slim/Handlers/Strategies/RequestResponseArgs.php
+++ b/vendor/slim/slim/Slim/Handlers/Strategies/RequestResponseArgs.php
@@ -2,10 +2,9 @@
 /**
  * Slim Framework (https://slimframework.com)
  *
- * @link      https://github.com/slimphp/Slim
- * @copyright Copyright (c) 2011-2017 Josh Lockhart
- * @license   https://github.com/slimphp/Slim/blob/3.x/LICENSE.md (MIT License)
+ * @license https://github.com/slimphp/Slim/blob/3.x/LICENSE.md (MIT License)
  */
+
 namespace Slim\Handlers\Strategies;
 
 use Psr\Http\Message\ResponseInterface;
@@ -27,7 +26,7 @@ class RequestResponseArgs implements InvocationStrategyInterface
      * @param ResponseInterface      $response
      * @param array                  $routeArguments
      *
-     * @return mixed
+     * @return ResponseInterface
      */
     public function __invoke(
         callable $callable,
diff --git a/vendor/slim/slim/Slim/Http/Body.php b/vendor/slim/slim/Slim/Http/Body.php
index 7a7b4df81e66f626cd80eb9fe0870fd54fbc774d..9d771cbdfd2588b8562ff393439ff180c181897a 100644
--- a/vendor/slim/slim/Slim/Http/Body.php
+++ b/vendor/slim/slim/Slim/Http/Body.php
@@ -2,21 +2,11 @@
 /**
  * Slim Framework (https://slimframework.com)
  *
- * @link      https://github.com/slimphp/Slim
- * @copyright Copyright (c) 2011-2017 Josh Lockhart
- * @license   https://github.com/slimphp/Slim/blob/3.x/LICENSE.md (MIT License)
+ * @license https://github.com/slimphp/Slim/blob/3.x/LICENSE.md (MIT License)
  */
+
 namespace Slim\Http;
 
-/**
- * Body
- *
- * This class represents an HTTP message body and encapsulates a
- * streamable resource according to the PSR-7 standard.
- *
- * @link https://github.com/php-fig/http-message/blob/master/src/StreamInterface.php
- */
 class Body extends Stream
 {
-
 }
diff --git a/vendor/slim/slim/Slim/Http/Cookies.php b/vendor/slim/slim/Slim/Http/Cookies.php
index 0ca0b0bfc3d7028d614e15aca1a2e5733b45a0b6..c186af0ce820552dd7e9ef6a756e120b81a2a346 100644
--- a/vendor/slim/slim/Slim/Http/Cookies.php
+++ b/vendor/slim/slim/Slim/Http/Cookies.php
@@ -2,18 +2,14 @@
 /**
  * Slim Framework (https://slimframework.com)
  *
- * @link      https://github.com/slimphp/Slim
- * @copyright Copyright (c) 2011-2017 Josh Lockhart
- * @license   https://github.com/slimphp/Slim/blob/3.x/LICENSE.md (MIT License)
+ * @license https://github.com/slimphp/Slim/blob/3.x/LICENSE.md (MIT License)
  */
+
 namespace Slim\Http;
 
 use InvalidArgumentException;
 use Slim\Interfaces\Http\CookiesInterface;
 
-/**
- * Cookie helper
- */
 class Cookies implements CookiesInterface
 {
     /**
@@ -47,8 +43,6 @@ class Cookies implements CookiesInterface
     ];
 
     /**
-     * Create new cookies helper
-     *
      * @param array $cookies
      */
     public function __construct(array $cookies = [])
@@ -67,12 +61,7 @@ class Cookies implements CookiesInterface
     }
 
     /**
-     * Get request cookie
-     *
-     * @param  string $name    Cookie name
-     * @param  mixed  $default Cookie default value
-     *
-     * @return mixed Cookie value if present, else default
+     * {@inheritdoc}
      */
     public function get($name, $default = null)
     {
@@ -80,10 +69,7 @@ class Cookies implements CookiesInterface
     }
 
     /**
-     * Set response cookie
-     *
-     * @param string       $name  Cookie name
-     * @param string|array $value Cookie value, or cookie properties
+     * {@inheritdoc}
      */
     public function set($name, $value)
     {
@@ -94,9 +80,7 @@ class Cookies implements CookiesInterface
     }
 
     /**
-     * Convert to `Set-Cookie` headers
-     *
-     * @return string[]
+     * {@inheritdoc}
      */
     public function toHeaders()
     {
@@ -160,14 +144,7 @@ class Cookies implements CookiesInterface
     }
 
     /**
-     * Parse HTTP request `Cookie:` header and extract
-     * into a PHP associative array.
-     *
-     * @param  string $header The raw HTTP request `Cookie:` header
-     *
-     * @return array Associative array of cookie names and values
-     *
-     * @throws InvalidArgumentException if the cookie data cannot be parsed
+     * {@inheritdoc}
      */
     public static function parseHeader($header)
     {
diff --git a/vendor/slim/slim/Slim/Http/Environment.php b/vendor/slim/slim/Slim/Http/Environment.php
index cd452fcff97e36a89310a864dd2bac510e1c503d..11089d98eddf5c7098d12f2391cc237a6322e5bb 100644
--- a/vendor/slim/slim/Slim/Http/Environment.php
+++ b/vendor/slim/slim/Slim/Http/Environment.php
@@ -2,18 +2,15 @@
 /**
  * Slim Framework (https://slimframework.com)
  *
- * @link      https://github.com/slimphp/Slim
- * @copyright Copyright (c) 2011-2017 Josh Lockhart
- * @license   https://github.com/slimphp/Slim/blob/3.x/LICENSE.md (MIT License)
+ * @license https://github.com/slimphp/Slim/blob/3.x/LICENSE.md (MIT License)
  */
+
 namespace Slim\Http;
 
 use Slim\Collection;
 use Slim\Interfaces\Http\EnvironmentInterface;
 
 /**
- * Environment
- *
  * This class decouples the Slim application from the global PHP environment.
  * This is particularly useful for unit testing, but it also lets us create
  * custom sub-requests.
@@ -21,17 +18,13 @@ use Slim\Interfaces\Http\EnvironmentInterface;
 class Environment extends Collection implements EnvironmentInterface
 {
     /**
-     * Create mock environment
-     *
-     * @param  array $userData Array of custom environment keys and values
-     *
-     * @return self
+     * {@inheritdoc}
      */
-    public static function mock(array $userData = [])
+    public static function mock(array $settings = [])
     {
         //Validates if default protocol is HTTPS to set default port 443
-        if ((isset($userData['HTTPS']) && $userData['HTTPS'] !== 'off') ||
-            ((isset($userData['REQUEST_SCHEME']) && $userData['REQUEST_SCHEME'] === 'https'))) {
+        if ((isset($settings['HTTPS']) && $settings['HTTPS'] !== 'off') ||
+            ((isset($settings['REQUEST_SCHEME']) && $settings['REQUEST_SCHEME'] === 'https'))) {
             $defscheme = 'https';
             $defport = 443;
         } else {
@@ -56,7 +49,7 @@ class Environment extends Collection implements EnvironmentInterface
             'REMOTE_ADDR'          => '127.0.0.1',
             'REQUEST_TIME'         => time(),
             'REQUEST_TIME_FLOAT'   => microtime(true),
-        ], $userData);
+        ], $settings);
 
         return new static($data);
     }
diff --git a/vendor/slim/slim/Slim/Http/Headers.php b/vendor/slim/slim/Slim/Http/Headers.php
index ef50f84b601503cd8067eafe804c9289adf46a99..f2eec7ceb34c34b7caf414324a8876882b49366f 100644
--- a/vendor/slim/slim/Slim/Http/Headers.php
+++ b/vendor/slim/slim/Slim/Http/Headers.php
@@ -2,18 +2,15 @@
 /**
  * Slim Framework (https://slimframework.com)
  *
- * @link      https://github.com/slimphp/Slim
- * @copyright Copyright (c) 2011-2017 Josh Lockhart
- * @license   https://github.com/slimphp/Slim/blob/3.x/LICENSE.md (MIT License)
+ * @license https://github.com/slimphp/Slim/blob/3.x/LICENSE.md (MIT License)
  */
+
 namespace Slim\Http;
 
 use Slim\Collection;
 use Slim\Interfaces\Http\HeadersInterface;
 
 /**
- * Headers
- *
  * This class represents a collection of HTTP headers
  * that is used in both the HTTP request and response objects.
  * It also enables header name case-insensitivity when
@@ -41,8 +38,7 @@ class Headers extends Collection implements HeadersInterface
     ];
 
     /**
-     * Create new headers collection with data extracted from
-     * the application Environment object
+     * Create new headers collection with data extracted from the application Environment object
      *
      * @param Environment $environment The Slim application Environment
      *
@@ -65,8 +61,7 @@ class Headers extends Collection implements HeadersInterface
     }
 
     /**
-     * If HTTP_AUTHORIZATION does not exist tries to get it from
-     * getallheaders() when available.
+     * If HTTP_AUTHORIZATION does not exist tries to get it from getallheaders() when available.
      *
      * @param Environment $environment The Slim application Environment
      *
@@ -76,13 +71,18 @@ class Headers extends Collection implements HeadersInterface
     public static function determineAuthorization(Environment $environment)
     {
         $authorization = $environment->get('HTTP_AUTHORIZATION');
+        if (!empty($authorization) || !is_callable('getallheaders')) {
+            return $environment;
+        }
 
-        if (empty($authorization) && is_callable('getallheaders')) {
-            $headers = getallheaders();
-            $headers = array_change_key_case($headers, CASE_LOWER);
-            if (isset($headers['authorization'])) {
-                $environment->set('HTTP_AUTHORIZATION', $headers['authorization']);
-            }
+        $headers = getallheaders();
+        if (!is_array($headers)) {
+            return $environment;
+        }
+
+        $headers = array_change_key_case($headers, CASE_LOWER);
+        if (isset($headers['authorization'])) {
+            $environment->set('HTTP_AUTHORIZATION', $headers['authorization']);
         }
 
         return $environment;
@@ -90,8 +90,7 @@ class Headers extends Collection implements HeadersInterface
 
     /**
      * Return array of HTTP header names and values.
-     * This method returns the _original_ header name
-     * as specified by the end user.
+     * This method returns the _original_ header name as specified by the end user.
      *
      * @return array
      */
@@ -112,8 +111,8 @@ class Headers extends Collection implements HeadersInterface
      * This method sets a header value. It replaces
      * any values that may already exist for the header name.
      *
-     * @param string $key   The case-insensitive header name
-     * @param string $value The header value
+     * @param string       $key   The case-insensitive header name
+     * @param array|string $value The header value
      */
     public function set($key, $value)
     {
@@ -161,14 +160,7 @@ class Headers extends Collection implements HeadersInterface
     }
 
     /**
-     * Add HTTP header value
-     *
-     * This method appends a header value. Unlike the set() method,
-     * this method _appends_ this new value to any values
-     * that already exist for this header name.
-     *
-     * @param string       $key   The case-insensitive header name
-     * @param array|string $value The new header value(s)
+     * {@inheritdoc}
      */
     public function add($key, $value)
     {
@@ -200,15 +192,7 @@ class Headers extends Collection implements HeadersInterface
     }
 
     /**
-     * Normalize header name
-     *
-     * This method transforms header names into a
-     * normalized form. This is how we enable case-insensitive
-     * header names in the other methods in this class.
-     *
-     * @param  string $key The case-insensitive header name
-     *
-     * @return string Normalized header name
+     * {@inheritdoc}
      */
     public function normalizeKey($key)
     {
diff --git a/vendor/slim/slim/Slim/Http/Message.php b/vendor/slim/slim/Slim/Http/Message.php
index 9195fb5b70fa4106c709b3aa7ac3f39627a7df2e..0dc7b4d60b4cd2fd804863fedbf3266bba4393d7 100644
--- a/vendor/slim/slim/Slim/Http/Message.php
+++ b/vendor/slim/slim/Slim/Http/Message.php
@@ -2,15 +2,15 @@
 /**
  * Slim Framework (https://slimframework.com)
  *
- * @link      https://github.com/slimphp/Slim
- * @copyright Copyright (c) 2011-2017 Josh Lockhart
- * @license   https://github.com/slimphp/Slim/blob/3.x/LICENSE.md (MIT License)
+ * @license https://github.com/slimphp/Slim/blob/3.x/LICENSE.md (MIT License)
  */
+
 namespace Slim\Http;
 
 use InvalidArgumentException;
 use Psr\Http\Message\MessageInterface;
 use Psr\Http\Message\StreamInterface;
+use Slim\Interfaces\Http\HeadersInterface;
 
 /**
  * Abstract message (base class for Request and Response)
@@ -19,21 +19,17 @@ use Psr\Http\Message\StreamInterface;
  * the HTTP request and response, as defined in the PSR-7 MessageInterface.
  *
  * @link https://github.com/php-fig/http-message/blob/master/src/MessageInterface.php
- * @see Slim\Http\Request
- * @see Slim\Http\Response
+ * @see \Slim\Http\Request
+ * @see \Slim\Http\Response
  */
 abstract class Message implements MessageInterface
 {
     /**
-     * Protocol version
-     *
      * @var string
      */
     protected $protocolVersion = '1.1';
 
     /**
-     * A map of valid protocol versions
-     *
      * @var array
      */
     protected static $validProtocolVersions = [
@@ -44,20 +40,15 @@ abstract class Message implements MessageInterface
     ];
 
     /**
-     * Headers
-     *
-     * @var \Slim\Interfaces\Http\HeadersInterface
+     * @var HeadersInterface
      */
     protected $headers;
 
     /**
-     * Body object
-     *
-     * @var \Psr\Http\Message\StreamInterface
+     * @var StreamInterface
      */
     protected $body;
 
-
     /**
      * Disable magic setter to ensure immutability
      */
@@ -66,16 +57,12 @@ abstract class Message implements MessageInterface
         // Do nothing
     }
 
-    /*******************************************************************************
-     * Protocol
-     ******************************************************************************/
-
     /**
      * Retrieves the HTTP protocol version as a string.
      *
      * The string MUST contain only the HTTP version number (e.g., "1.1", "1.0").
      *
-     * @return string HTTP protocol version.
+     * @return string
      */
     public function getProtocolVersion()
     {
@@ -93,7 +80,9 @@ abstract class Message implements MessageInterface
      * new protocol version.
      *
      * @param string $version HTTP protocol version
+     *
      * @return static
+     *
      * @throws InvalidArgumentException if the http version is an invalid number
      */
     public function withProtocolVersion($version)
@@ -110,13 +99,12 @@ abstract class Message implements MessageInterface
         return $clone;
     }
 
-    /*******************************************************************************
-     * Headers
-     ******************************************************************************/
-
     /**
      * Retrieves all message header values.
      *
+     * Returns an associative array of the message's headers.
+     * Each key MUST be a header name, and each value MUST be an array of strings for that header.
+     *
      * The keys represent the header name as it will be sent over the wire, and
      * each value is an array of strings associated with the header.
      *
@@ -135,9 +123,7 @@ abstract class Message implements MessageInterface
      * While header names are not case-sensitive, getHeaders() will preserve the
      * exact case in which headers were originally specified.
      *
-     * @return array Returns an associative array of the message's headers. Each
-     *     key MUST be a header name, and each value MUST be an array of strings
-     *     for that header.
+     * @return array
      */
     public function getHeaders()
     {
@@ -147,10 +133,12 @@ abstract class Message implements MessageInterface
     /**
      * Checks if a header exists by the given case-insensitive name.
      *
+     * Returns true if any header names match the given header name using a case-insensitive string comparison.
+     * Returns false if no matching header name is found in the message.
+     *
      * @param string $name Case-insensitive header field name.
-     * @return bool Returns true if any header names match the given header
-     *     name using a case-insensitive string comparison. Returns false if
-     *     no matching header name is found in the message.
+     *
+     * @return bool
      */
     public function hasHeader($name)
     {
@@ -167,9 +155,8 @@ abstract class Message implements MessageInterface
      * empty array.
      *
      * @param string $name Case-insensitive header field name.
-     * @return string[] An array of string values as provided for the given
-     *    header. If the header does not appear in the message, this method MUST
-     *    return an empty array.
+     *
+     * @return string[]
      */
     public function getHeader($name)
     {
@@ -179,7 +166,7 @@ abstract class Message implements MessageInterface
     /**
      * Retrieves a comma-separated string of the values for a single header.
      *
-     * This method returns all of the header values of the given
+     * This method returns a string of all of the header values of the given
      * case-insensitive header name as a string concatenated together using
      * a comma.
      *
@@ -191,9 +178,8 @@ abstract class Message implements MessageInterface
      * an empty string.
      *
      * @param string $name Case-insensitive header field name.
-     * @return string A string of values as provided for the given header
-     *    concatenated together using a comma. If the header does not appear in
-     *    the message, this method MUST return an empty string.
+     *
+     * @return string
      */
     public function getHeaderLine($name)
     {
@@ -212,8 +198,8 @@ abstract class Message implements MessageInterface
      *
      * @param string $name Case-insensitive header field name.
      * @param string|string[] $value Header value(s).
+     *
      * @return static
-     * @throws \InvalidArgumentException for invalid header names or values.
      */
     public function withHeader($name, $value)
     {
@@ -236,14 +222,18 @@ abstract class Message implements MessageInterface
      *
      * @param string $name Case-insensitive header field name to add.
      * @param string|string[] $value Header value(s).
+     *
      * @return static
-     * @throws \InvalidArgumentException for invalid header names or values.
      */
     public function withAddedHeader($name, $value)
     {
         $clone = clone $this;
         $clone->headers->add($name, $value);
 
+        if ($this instanceof Response && $this->body instanceof NonBufferedBody) {
+            header(sprintf('%s: %s', $name, $clone->getHeaderLine($name)));
+        }
+
         return $clone;
     }
 
@@ -257,6 +247,7 @@ abstract class Message implements MessageInterface
      * the named header.
      *
      * @param string $name Case-insensitive header field name to remove.
+     *
      * @return static
      */
     public function withoutHeader($name)
@@ -264,13 +255,13 @@ abstract class Message implements MessageInterface
         $clone = clone $this;
         $clone->headers->remove($name);
 
+        if ($this instanceof Response && $this->body instanceof NonBufferedBody) {
+            header_remove($name);
+        }
+
         return $clone;
     }
 
-    /*******************************************************************************
-     * Body
-     ******************************************************************************/
-
     /**
      * Gets the body of the message.
      *
@@ -291,12 +282,11 @@ abstract class Message implements MessageInterface
      * new body stream.
      *
      * @param StreamInterface $body Body.
+     *
      * @return static
-     * @throws \InvalidArgumentException When the body is not valid.
      */
     public function withBody(StreamInterface $body)
     {
-        // TODO: Test for invalid body?
         $clone = clone $this;
         $clone->body = $body;
 
diff --git a/vendor/slim/slim/Slim/Http/NonBufferedBody.php b/vendor/slim/slim/Slim/Http/NonBufferedBody.php
new file mode 100644
index 0000000000000000000000000000000000000000..352ff590ea23a68afa3d705b1f8dc8c41964ffc0
--- /dev/null
+++ b/vendor/slim/slim/Slim/Http/NonBufferedBody.php
@@ -0,0 +1,143 @@
+<?php
+/**
+ * Slim Framework (https://slimframework.com)
+ *
+ * @license https://github.com/slimphp/Slim/blob/3.x/LICENSE.md (MIT License)
+ */
+
+namespace Slim\Http;
+
+use Psr\Http\Message\StreamInterface;
+
+/**
+ * Represents a non-readable stream that whenever it is written pushes
+ * the data back to the browser immediately.
+ */
+class NonBufferedBody implements StreamInterface
+{
+    /**
+     * {@inheritdoc}
+     */
+    public function __toString()
+    {
+        return '';
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function close()
+    {
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function detach()
+    {
+        return null;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getSize()
+    {
+        return null;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function tell()
+    {
+        return 0;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function eof()
+    {
+        return true;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function isSeekable()
+    {
+        return false;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function seek($offset, $whence = SEEK_SET)
+    {
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function rewind()
+    {
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function isWritable()
+    {
+        return true;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function write($string)
+    {
+        $buffered = '';
+        while (0 < ob_get_level()) {
+            $buffered = ob_get_clean() . $buffered;
+        }
+
+        echo $buffered . $string;
+
+        flush();
+
+        return strlen($string) + strlen($buffered);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function isReadable()
+    {
+        return false;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function read($length)
+    {
+        return '';
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getContents()
+    {
+        return '';
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getMetadata($key = null)
+    {
+        return null;
+    }
+}
diff --git a/vendor/slim/slim/Slim/Http/Request.php b/vendor/slim/slim/Slim/Http/Request.php
index 2762ffc555054a64eb586fcdd59ca0ca22e8d973..b75676b8c362d3a6ddf1a3434a6be1c506414c0d 100644
--- a/vendor/slim/slim/Slim/Http/Request.php
+++ b/vendor/slim/slim/Slim/Http/Request.php
@@ -2,29 +2,25 @@
 /**
  * Slim Framework (https://slimframework.com)
  *
- * @link      https://github.com/slimphp/Slim
- * @copyright Copyright (c) 2011-2017 Josh Lockhart
- * @license   https://github.com/slimphp/Slim/blob/3.x/LICENSE.md (MIT License)
+ * @license https://github.com/slimphp/Slim/blob/3.x/LICENSE.md (MIT License)
  */
+
 namespace Slim\Http;
 
 use Closure;
 use InvalidArgumentException;
-use Psr\Http\Message\UploadedFileInterface;
-use RuntimeException;
 use Psr\Http\Message\ServerRequestInterface;
-use Psr\Http\Message\UriInterface;
 use Psr\Http\Message\StreamInterface;
+use Psr\Http\Message\UploadedFileInterface;
+use Psr\Http\Message\UriInterface;
+use RuntimeException;
 use Slim\Collection;
 use Slim\Exception\InvalidMethodException;
 use Slim\Interfaces\Http\HeadersInterface;
 
 /**
- * Request
- *
- * This class represents an HTTP request. It manages
- * the request method, URI, headers, cookies, and body
- * according to the PSR-7 standard.
+ * This class represents an HTTP request.
+ * It manages the request method, URI, headers, cookies, and body according to the PSR-7 standard.
  *
  * @link https://github.com/php-fig/http-message/blob/master/src/MessageInterface.php
  * @link https://github.com/php-fig/http-message/blob/master/src/RequestInterface.php
@@ -49,7 +45,7 @@ class Request extends Message implements ServerRequestInterface
     /**
      * The request URI object
      *
-     * @var \Psr\Http\Message\UriInterface
+     * @var UriInterface
      */
     protected $uri;
 
@@ -84,7 +80,7 @@ class Request extends Message implements ServerRequestInterface
     /**
      * The request attributes (route segment names and values)
      *
-     * @var \Slim\Collection
+     * @var Collection
      */
     protected $attributes;
 
@@ -157,10 +153,6 @@ class Request extends Message implements ServerRequestInterface
     }
 
     /**
-     * Create new HTTP request.
-     *
-     * Adds a host header when none was provided and a host is defined in uri.
-     *
      * @param string           $method        The request method
      * @param UriInterface     $uri           The request URI object
      * @param HeadersInterface $headers       The request headers collection
@@ -168,6 +160,7 @@ class Request extends Message implements ServerRequestInterface
      * @param array            $serverParams  The server environment variables
      * @param StreamInterface  $body          The request body object
      * @param array            $uploadedFiles The request uploadedFiles collection
+     *
      * @throws InvalidMethodException on invalid HTTP method
      */
     public function __construct(
@@ -249,10 +242,8 @@ class Request extends Message implements ServerRequestInterface
     }
 
     /**
-     * This method is applied to the cloned object
-     * after PHP performs an initial shallow-copy. This
-     * method completes a deep-copy by creating new objects
-     * for the cloned object's internal reference pointers.
+     * This method is applied to the cloned object after PHP performs an initial shallow-copy.
+     * This method completes a deep-copy by creating new objects for the cloned object's internal reference pointers.
      */
     public function __clone()
     {
@@ -261,14 +252,10 @@ class Request extends Message implements ServerRequestInterface
         $this->body = clone $this->body;
     }
 
-    /*******************************************************************************
-     * Method
-     ******************************************************************************/
-
     /**
      * Retrieves the HTTP method of the request.
      *
-     * @return string Returns the request method.
+     * @return string
      */
     public function getMethod()
     {
@@ -317,8 +304,10 @@ class Request extends Message implements ServerRequestInterface
      * changed request method.
      *
      * @param string $method Case-sensitive method.
+     *
      * @return static
-     * @throws \InvalidArgumentException for invalid HTTP methods.
+     *
+     * @throws InvalidArgumentException for invalid HTTP methods.
      */
     public function withMethod($method)
     {
@@ -334,8 +323,10 @@ class Request extends Message implements ServerRequestInterface
      * Validate the HTTP method
      *
      * @param  null|string $method
+     *
      * @return null|string
-     * @throws \InvalidArgumentException on invalid HTTP method.
+     *
+     * @throws InvalidArgumentException on invalid HTTP method.
      */
     protected function filterMethod($method)
     {
@@ -364,6 +355,7 @@ class Request extends Message implements ServerRequestInterface
      * Note: This method is not part of the PSR-7 standard.
      *
      * @param  string $method HTTP method
+     *
      * @return bool
      */
     public function isMethod($method)
@@ -467,10 +459,6 @@ class Request extends Message implements ServerRequestInterface
         return $this->getHeaderLine('X-Requested-With') === 'XMLHttpRequest';
     }
 
-    /*******************************************************************************
-     * URI
-     ******************************************************************************/
-
     /**
      * Retrieves the message's request target.
      *
@@ -497,7 +485,11 @@ class Request extends Message implements ServerRequestInterface
             return '/';
         }
 
-        $basePath = $this->uri->getBasePath();
+        if ($this->uri instanceof Uri) {
+            $basePath = $this->uri->getBasePath();
+        } else {
+            $basePath = '';
+        }
         $path = $this->uri->getPath();
         $path = $basePath . '/' . ltrim($path, '/');
 
@@ -522,10 +514,13 @@ class Request extends Message implements ServerRequestInterface
      * immutability of the message, and MUST return an instance that has the
      * changed request target.
      *
-     * @link http://tools.ietf.org/html/rfc7230#section-2.7 (for the various
-     *     request-target forms allowed in request messages)
-     * @param mixed $requestTarget
+     * @link http://tools.ietf.org/html/rfc7230#section-2.7
+     * (for the various request-target forms allowed in request messages)
+     *
+     * @param string $requestTarget
+     *
      * @return static
+     *
      * @throws InvalidArgumentException if the request target is invalid
      */
     public function withRequestTarget($requestTarget)
@@ -547,8 +542,8 @@ class Request extends Message implements ServerRequestInterface
      * This method MUST return a UriInterface instance.
      *
      * @link http://tools.ietf.org/html/rfc3986#section-4.3
-     * @return UriInterface Returns a UriInterface instance
-     *     representing the URI of the request.
+     *
+     * @return UriInterface
      */
     public function getUri()
     {
@@ -581,8 +576,10 @@ class Request extends Message implements ServerRequestInterface
      * new UriInterface instance.
      *
      * @link http://tools.ietf.org/html/rfc3986#section-4.3
-     * @param UriInterface $uri New request URI to use.
-     * @param bool $preserveHost Preserve the original state of the Host header.
+     *
+     * @param UriInterface $uri          New request URI to use.
+     * @param bool         $preserveHost Preserve the original state of the Host header.
+     *
      * @return static
      */
     public function withUri(UriInterface $uri, $preserveHost = false)
@@ -608,7 +605,7 @@ class Request extends Message implements ServerRequestInterface
      *
      * Note: This method is not part of the PSR-7 standard.
      *
-     * @return string|null The request content type, if known
+     * @return string|null
      */
     public function getContentType()
     {
@@ -622,7 +619,7 @@ class Request extends Message implements ServerRequestInterface
      *
      * Note: This method is not part of the PSR-7 standard.
      *
-     * @return string|null The request media type, minus content-type params
+     * @return string|null
      */
     public function getMediaType()
     {
@@ -641,7 +638,7 @@ class Request extends Message implements ServerRequestInterface
      *
      * Note: This method is not part of the PSR-7 standard.
      *
-     * @return array
+     * @return string[]
      */
     public function getMediaTypeParams()
     {
@@ -690,17 +687,12 @@ class Request extends Message implements ServerRequestInterface
         return $result ? (int)$result[0] : null;
     }
 
-    /*******************************************************************************
-     * Cookies
-     ******************************************************************************/
-
     /**
      * Retrieve cookies.
      *
      * Retrieves cookies sent by the client to the server.
      *
-     * The data MUST be compatible with the structure of the $_COOKIE
-     * superglobal.
+     * The data MUST be compatible with the structure of the $_COOKIE superglobal.
      *
      * @return array
      */
@@ -745,6 +737,7 @@ class Request extends Message implements ServerRequestInterface
      * updated cookie values.
      *
      * @param array $cookies Array of key/value pairs representing cookies.
+     *
      * @return static
      */
     public function withCookieParams(array $cookies)
@@ -755,10 +748,6 @@ class Request extends Message implements ServerRequestInterface
         return $clone;
     }
 
-    /*******************************************************************************
-     * Query Params
-     ******************************************************************************/
-
     /**
      * Retrieve query string arguments.
      *
@@ -806,6 +795,7 @@ class Request extends Message implements ServerRequestInterface
      *
      * @param array $query Array of query string arguments, typically from
      *     $_GET.
+     *
      * @return static
      */
     public function withQueryParams(array $query)
@@ -816,10 +806,6 @@ class Request extends Message implements ServerRequestInterface
         return $clone;
     }
 
-    /*******************************************************************************
-     * File Params
-     ******************************************************************************/
-
     /**
      * Retrieve normalized file upload data.
      *
@@ -829,8 +815,7 @@ class Request extends Message implements ServerRequestInterface
      * These values MAY be prepared from $_FILES or the message body during
      * instantiation, or MAY be injected via withUploadedFiles().
      *
-     * @return array An array tree of UploadedFileInterface instances; an empty
-     *     array MUST be returned if no data is present.
+     * @return array
      */
     public function getUploadedFiles()
     {
@@ -845,8 +830,10 @@ class Request extends Message implements ServerRequestInterface
      * updated body parameters.
      *
      * @param array $uploadedFiles An array tree of UploadedFileInterface instances.
+     *
      * @return static
-     * @throws \InvalidArgumentException if an invalid structure is provided.
+     *
+     * @throws InvalidArgumentException if an invalid structure is provided.
      */
     public function withUploadedFiles(array $uploadedFiles)
     {
@@ -856,10 +843,6 @@ class Request extends Message implements ServerRequestInterface
         return $clone;
     }
 
-    /*******************************************************************************
-     * Server Params
-     ******************************************************************************/
-
     /**
      * Retrieve server parameters.
      *
@@ -881,6 +864,7 @@ class Request extends Message implements ServerRequestInterface
      *
      * @param  string $key
      * @param  mixed  $default
+     *
      * @return mixed
      */
     public function getServerParam($key, $default = null)
@@ -890,10 +874,6 @@ class Request extends Message implements ServerRequestInterface
         return isset($serverParams[$key]) ? $serverParams[$key] : $default;
     }
 
-    /*******************************************************************************
-     * Attributes
-     ******************************************************************************/
-
     /**
      * Retrieve attributes derived from the request.
      *
@@ -903,7 +883,7 @@ class Request extends Message implements ServerRequestInterface
      * deserializing non-form-encoded message bodies; etc. Attributes
      * will be application and request specific, and CAN be mutable.
      *
-     * @return array Attributes derived from the request.
+     * @return array
      */
     public function getAttributes()
     {
@@ -921,8 +901,10 @@ class Request extends Message implements ServerRequestInterface
      * specifying a default value to return if the attribute is not found.
      *
      * @see getAttributes()
+     *
      * @param string $name The attribute name.
      * @param mixed $default Default value to return if the attribute does not exist.
+     *
      * @return mixed
      */
     public function getAttribute($name, $default = null)
@@ -941,8 +923,10 @@ class Request extends Message implements ServerRequestInterface
      * updated attribute.
      *
      * @see getAttributes()
+     *
      * @param string $name The attribute name.
      * @param mixed $value The value of the attribute.
+     *
      * @return static
      */
     public function withAttribute($name, $value)
@@ -966,6 +950,7 @@ class Request extends Message implements ServerRequestInterface
      * updated attributes.
      *
      * @param  array $attributes New attributes
+     *
      * @return static
      */
     public function withAttributes(array $attributes)
@@ -987,7 +972,9 @@ class Request extends Message implements ServerRequestInterface
      * the attribute.
      *
      * @see getAttributes()
+     *
      * @param string $name The attribute name.
+     *
      * @return static
      */
     public function withoutAttribute($name)
@@ -998,10 +985,6 @@ class Request extends Message implements ServerRequestInterface
         return $clone;
     }
 
-    /*******************************************************************************
-     * Body
-     ******************************************************************************/
-
     /**
      * Retrieve any parameters provided in the request body.
      *
@@ -1014,8 +997,8 @@ class Request extends Message implements ServerRequestInterface
      * potential types MUST be arrays or objects only. A null value indicates
      * the absence of body content.
      *
-     * @return null|array|object The deserialized body parameters, if any.
-     *     These will typically be an array or object.
+     * @return null|array|object
+     *
      * @throws RuntimeException if the request body media type parser returns an invalid value
      */
     public function getParsedBody()
@@ -1030,13 +1013,16 @@ class Request extends Message implements ServerRequestInterface
 
         $mediaType = $this->getMediaType();
 
-        // look for a media type with a structured syntax suffix (RFC 6839)
-        $parts = explode('+', $mediaType);
-        if (count($parts) >= 2) {
-            $mediaType = 'application/' . $parts[count($parts)-1];
+        // Check if this specific media type has a parser registered first
+        if (!isset($this->bodyParsers[$mediaType])) {
+            // If not, look for a media type with a structured syntax suffix (RFC 6839)
+            $parts = explode('+', $mediaType);
+            if (count($parts) >= 2) {
+                $mediaType = 'application/' . $parts[count($parts)-1];
+            }
         }
 
-        if (isset($this->bodyParsers[$mediaType]) === true) {
+        if (isset($this->bodyParsers[$mediaType])) {
             $body = (string)$this->getBody();
             $parsed = $this->bodyParsers[$mediaType]($body);
 
@@ -1074,10 +1060,11 @@ class Request extends Message implements ServerRequestInterface
      * immutability of the message, and MUST return an instance that has the
      * updated body parameters.
      *
-     * @param null|array|object $data The deserialized body data. This will
-     *     typically be in an array or object.
+     * @param null|array|object $data The deserialized body data. This will typically be in an array or object.
+     *
      * @return static
-     * @throws \InvalidArgumentException if an unsupported argument type is
+     *
+     * @throws InvalidArgumentException if an unsupported argument type is
      *     provided.
      */
     public function withParsedBody($data)
@@ -1111,10 +1098,8 @@ class Request extends Message implements ServerRequestInterface
      *
      * Note: This method is not part of the PSR-7 standard.
      *
-     * @param string   $mediaType A HTTP media type (excluding content-type
-     *     params).
-     * @param callable $callable  A callable that returns parsed contents for
-     *     media type.
+     * @param string   $mediaType A HTTP media type (excluding content-type params).
+     * @param callable $callable  A callable that returns parsed contents for media type.
      */
     public function registerMediaTypeParser($mediaType, callable $callable)
     {
@@ -1124,19 +1109,15 @@ class Request extends Message implements ServerRequestInterface
         $this->bodyParsers[(string)$mediaType] = $callable;
     }
 
-    /*******************************************************************************
-     * Parameters (e.g., POST and GET data)
-     ******************************************************************************/
-
     /**
      * Fetch request parameter value from body or query string (in that order).
      *
      * Note: This method is not part of the PSR-7 standard.
      *
-     * @param  string $key The parameter key.
-     * @param  mixed $default The default value.
+     * @param  string $key     The parameter key.
+     * @param  mixed  $default The default value.
      *
-     * @return mixed The parameter value.
+     * @return mixed
      */
     public function getParam($key, $default = null)
     {
@@ -1160,7 +1141,7 @@ class Request extends Message implements ServerRequestInterface
      * Note: This method is not part of the PSR-7 standard.
      *
      * @param string $key
-     * @param mixed $default
+     * @param mixed  $default
      *
      * @return mixed
      */
@@ -1183,7 +1164,7 @@ class Request extends Message implements ServerRequestInterface
      * Note: This method is not part of the PSR-7 standard.
      *
      * @param string $key
-     * @param mixed $default
+     * @param mixed  $default
      *
      * @return mixed
      */
@@ -1204,6 +1185,7 @@ class Request extends Message implements ServerRequestInterface
      * Note: This method is not part of the PSR-7 standard.
      *
      * @param array|null $only list the keys to retrieve.
+     *
      * @return array|null
      */
     public function getParams(array $only = null)
diff --git a/vendor/slim/slim/Slim/Http/RequestBody.php b/vendor/slim/slim/Slim/Http/RequestBody.php
index 50887fddc23be99fa6530bbb7e7b08ca6ce2942e..48e1cc6cb35ac026078b5d5d5e0eaae05872dd4f 100644
--- a/vendor/slim/slim/Slim/Http/RequestBody.php
+++ b/vendor/slim/slim/Slim/Http/RequestBody.php
@@ -2,10 +2,9 @@
 /**
  * Slim Framework (https://slimframework.com)
  *
- * @link      https://github.com/slimphp/Slim
- * @copyright Copyright (c) 2011-2017 Josh Lockhart
- * @license   https://github.com/slimphp/Slim/blob/3.x/LICENSE.md (MIT License)
+ * @license https://github.com/slimphp/Slim/blob/3.x/LICENSE.md (MIT License)
  */
+
 namespace Slim\Http;
 
 /**
@@ -13,9 +12,6 @@ namespace Slim\Http;
  */
 class RequestBody extends Body
 {
-    /**
-     * Create a new RequestBody.
-     */
     public function __construct()
     {
         $stream = fopen('php://temp', 'w+');
diff --git a/vendor/slim/slim/Slim/Http/Response.php b/vendor/slim/slim/Slim/Http/Response.php
index 9b5272e648c00c5e88155c9a7a794e1e7a735028..8ad475d4469d8404008e40b5ae675859d53f1c51 100644
--- a/vendor/slim/slim/Slim/Http/Response.php
+++ b/vendor/slim/slim/Slim/Http/Response.php
@@ -2,16 +2,16 @@
 /**
  * Slim Framework (https://slimframework.com)
  *
- * @link      https://github.com/slimphp/Slim
- * @copyright Copyright (c) 2011-2017 Josh Lockhart
- * @license   https://github.com/slimphp/Slim/blob/3.x/LICENSE.md (MIT License)
+ * @license https://github.com/slimphp/Slim/blob/3.x/LICENSE.md (MIT License)
  */
+
 namespace Slim\Http;
 
 use InvalidArgumentException;
 use Psr\Http\Message\ResponseInterface;
 use Psr\Http\Message\StreamInterface;
 use Psr\Http\Message\UriInterface;
+use RuntimeException;
 use Slim\Interfaces\Http\HeadersInterface;
 
 /**
@@ -125,8 +125,6 @@ class Response extends Message implements ResponseInterface
     const EOL = "\r\n";
 
     /**
-     * Create new HTTP response.
-     *
      * @param int                   $status  The response status code.
      * @param HeadersInterface|null $headers The response headers.
      * @param StreamInterface|null  $body    The response body.
@@ -152,17 +150,13 @@ class Response extends Message implements ResponseInterface
         $this->headers = clone $this->headers;
     }
 
-    /*******************************************************************************
-     * Status
-     ******************************************************************************/
-
     /**
      * Gets the response status code.
      *
      * The status code is a 3-digit integer result code of the server's attempt
      * to understand and satisfy the request.
      *
-     * @return int Status code.
+     * @return int
      */
     public function getStatusCode()
     {
@@ -182,12 +176,15 @@ class Response extends Message implements ResponseInterface
      *
      * @link http://tools.ietf.org/html/rfc7231#section-6
      * @link http://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml
+     *
      * @param int $code The 3-digit integer result code to set.
      * @param string $reasonPhrase The reason phrase to use with the
      *     provided status code; if none is provided, implementations MAY
      *     use the defaults as suggested in the HTTP specification.
+     *
      * @return static
-     * @throws \InvalidArgumentException For invalid status code arguments.
+     *
+     * @throws InvalidArgumentException For invalid status code arguments.
      */
     public function withStatus($code, $reasonPhrase = '')
     {
@@ -216,8 +213,10 @@ class Response extends Message implements ResponseInterface
      * Filter HTTP status code.
      *
      * @param  int $status HTTP status code.
+     *
      * @return int
-     * @throws \InvalidArgumentException If an invalid HTTP status code is provided.
+     *
+     * @throws InvalidArgumentException If an invalid HTTP status code is provided.
      */
     protected function filterStatus($status)
     {
@@ -242,6 +241,7 @@ class Response extends Message implements ResponseInterface
      *
      * @link http://tools.ietf.org/html/rfc7231#section-6
      * @link http://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml
+     *
      * @return string Reason phrase; must return an empty string if none present.
      */
     public function getReasonPhrase()
@@ -255,10 +255,6 @@ class Response extends Message implements ResponseInterface
         return '';
     }
 
-    /*******************************************************************************
-     * Headers
-     ******************************************************************************/
-
     /**
      * Return an instance with the provided value replacing the specified header.
      *
@@ -267,14 +263,20 @@ class Response extends Message implements ResponseInterface
      *
      * @param string $name Case-insensitive header field name.
      * @param string|string[] $value Header value(s).
+     *
      * @return static
-     * @throws \InvalidArgumentException for invalid header names or values.
+     *
+     * @throws InvalidArgumentException For invalid header names or values.
      */
     public function withHeader($name, $value)
     {
         $clone = clone $this;
         $clone->headers->set($name, $value);
 
+        if ($this->body instanceof NonBufferedBody) {
+            header(sprintf('%s: %s', $name, $clone->getHeaderLine($name)));
+        }
+
         if ($clone->getStatusCode() === StatusCode::HTTP_OK && strtolower($name) === 'location') {
             $clone = $clone->withStatus(StatusCode::HTTP_FOUND);
         }
@@ -282,11 +284,6 @@ class Response extends Message implements ResponseInterface
         return $clone;
     }
 
-
-    /*******************************************************************************
-     * Body
-     ******************************************************************************/
-
     /**
      * Write data to the response body.
      *
@@ -295,7 +292,8 @@ class Response extends Message implements ResponseInterface
      * Proxies to the underlying stream and writes the provided data to it.
      *
      * @param string $data
-     * @return $this
+     *
+     * @return static
      */
     public function write($data)
     {
@@ -304,10 +302,6 @@ class Response extends Message implements ResponseInterface
         return $this;
     }
 
-    /*******************************************************************************
-     * Response Helpers
-     ******************************************************************************/
-
     /**
      * Redirect.
      *
@@ -318,6 +312,7 @@ class Response extends Message implements ResponseInterface
      *
      * @param  string|UriInterface $url    The redirect destination.
      * @param  int|null            $status The redirect HTTP status code.
+     *
      * @return static
      */
     public function withRedirect($url, $status = null)
@@ -343,11 +338,13 @@ class Response extends Message implements ResponseInterface
      * This method prepares the response object to return an HTTP Json
      * response to the client.
      *
-     * @param  mixed  $data   The data
-     * @param  int    $status The HTTP status code.
-     * @param  int    $encodingOptions Json encoding options
-     * @throws \RuntimeException
+     * @param  mixed $data   The data
+     * @param  int   $status The HTTP status code.
+     * @param  int   $encodingOptions Json encoding options
+     *
      * @return static
+     *
+     * @throws RuntimeException
      */
     public function withJson($data, $status = null, $encodingOptions = 0)
     {
@@ -356,10 +353,10 @@ class Response extends Message implements ResponseInterface
 
         // Ensure that the json encoding passed successfully
         if ($json === false) {
-            throw new \RuntimeException(json_last_error_msg(), json_last_error());
+            throw new RuntimeException(json_last_error_msg(), json_last_error());
         }
 
-        $responseWithJson = $response->withHeader('Content-Type', 'application/json;charset=utf-8');
+        $responseWithJson = $response->withHeader('Content-Type', 'application/json');
         if (isset($status)) {
             return $responseWithJson->withStatus($status);
         }
@@ -458,7 +455,6 @@ class Response extends Message implements ResponseInterface
      * Note: This method is not part of the PSR-7 standard.
      *
      * @return bool
-     * @api
      */
     public function isForbidden()
     {
@@ -477,6 +473,18 @@ class Response extends Message implements ResponseInterface
         return $this->getStatusCode() === StatusCode::HTTP_NOT_FOUND;
     }
 
+    /**
+     * Is this a bad request?
+     *
+     * Note: This method is not part of the PSR-7 standard.
+     *
+     * @return bool
+     */
+    public function isBadRequest()
+    {
+        return $this->getStatusCode() === StatusCode::HTTP_BAD_REQUEST;
+    }
+
     /**
      * Is this response a client error?
      *
diff --git a/vendor/slim/slim/Slim/Http/StatusCode.php b/vendor/slim/slim/Slim/Http/StatusCode.php
index 301bdd932f46307050d7621a4b98b9d63cb9fbda..8a0899ad1a6e02b7491100d874a98256420b9f49 100644
--- a/vendor/slim/slim/Slim/Http/StatusCode.php
+++ b/vendor/slim/slim/Slim/Http/StatusCode.php
@@ -2,10 +2,9 @@
 /**
  * Slim Framework (https://slimframework.com)
  *
- * @link      https://github.com/slimphp/Slim
- * @copyright Copyright (c) 2011-2017 Josh Lockhart
- * @license   https://github.com/slimphp/Slim/blob/3.x/LICENSE.md (MIT License)
+ * @license https://github.com/slimphp/Slim/blob/3.x/LICENSE.md (MIT License)
  */
+
 namespace Slim\Http;
 
 class StatusCode
diff --git a/vendor/slim/slim/Slim/Http/Stream.php b/vendor/slim/slim/Slim/Http/Stream.php
index 27c7a7645bf65ba54e7e0968474670ec8b09a09a..f405dc710b8768606f8582924cd50587962d5817 100644
--- a/vendor/slim/slim/Slim/Http/Stream.php
+++ b/vendor/slim/slim/Slim/Http/Stream.php
@@ -2,10 +2,9 @@
 /**
  * Slim Framework (https://slimframework.com)
  *
- * @link      https://github.com/slimphp/Slim
- * @copyright Copyright (c) 2011-2017 Josh Lockhart
- * @license   https://github.com/slimphp/Slim/blob/3.x/LICENSE.md (MIT License)
+ * @license https://github.com/slimphp/Slim/blob/3.x/LICENSE.md (MIT License)
  */
+
 namespace Slim\Http;
 
 use InvalidArgumentException;
@@ -87,8 +86,6 @@ class Stream implements StreamInterface
     protected $isPipe;
 
     /**
-     * Create a new Stream.
-     *
      * @param  resource $stream A PHP resource handle.
      *
      * @throws InvalidArgumentException If argument is not a resource.
@@ -101,8 +98,7 @@ class Stream implements StreamInterface
     /**
      * Get stream metadata as an associative array or retrieve a specific key.
      *
-     * The keys returned are identical to the keys returned from PHP's
-     * stream_get_meta_data() function.
+     * The keys returned are identical to the keys returned from PHP's stream_get_meta_data() function.
      *
      * @link http://php.net/manual/en/function.stream-get-meta-data.php
      *
@@ -189,6 +185,7 @@ class Stream implements StreamInterface
      * string casting operations.
      *
      * @see http://php.net/manual/en/language.oop5.magic.php#object.tostring
+     *
      * @return string
      */
     public function __toString()
@@ -342,7 +339,7 @@ class Stream implements StreamInterface
      *     offset bytes SEEK_CUR: Set position to current location plus offset
      *     SEEK_END: Set position to end-of-stream plus offset.
      *
-     * @throws RuntimeException on failure.
+     * @throws RuntimeException If stream is not seekable
      */
     public function seek($offset, $whence = SEEK_SET)
     {
@@ -378,8 +375,7 @@ class Stream implements StreamInterface
      *     them. Fewer than $length bytes may be returned if underlying stream
      *     call returns fewer bytes.
      *
-     * @return string Returns the data read from the stream, or an empty string
-     *     if no bytes are available.
+     * @return string Returns the data read from the stream, or an empty string if no bytes are available.
      *
      * @throws RuntimeException if an error occurs.
      */
@@ -399,7 +395,7 @@ class Stream implements StreamInterface
      *
      * @return int Returns the number of bytes written to the stream.
      *
-     * @throws RuntimeException on failure.
+     * @throws RuntimeException If stream is not writable
      */
     public function write($string)
     {
@@ -418,8 +414,7 @@ class Stream implements StreamInterface
      *
      * @return string
      *
-     * @throws RuntimeException if unable to read or an error occurs while
-     *     reading.
+     * @throws RuntimeException If stream is not readable
      */
     public function getContents()
     {
diff --git a/vendor/slim/slim/Slim/Http/UploadedFile.php b/vendor/slim/slim/Slim/Http/UploadedFile.php
index 431ef2d3faf24c5b198609c28db4df66b3560e96..401440dbc7e13ebcf1d91ba82883baa687c708e0 100644
--- a/vendor/slim/slim/Slim/Http/UploadedFile.php
+++ b/vendor/slim/slim/Slim/Http/UploadedFile.php
@@ -2,21 +2,18 @@
 /**
  * Slim Framework (https://slimframework.com)
  *
- * @link      https://github.com/slimphp/Slim
- * @copyright Copyright (c) 2011-2017 Josh Lockhart
- * @license   https://github.com/slimphp/Slim/blob/3.x/LICENSE.md (MIT License)
+ * @license https://github.com/slimphp/Slim/blob/3.x/LICENSE.md (MIT License)
  */
+
 namespace Slim\Http;
 
-use RuntimeException;
 use InvalidArgumentException;
 use Psr\Http\Message\StreamInterface;
 use Psr\Http\Message\UploadedFileInterface;
+use RuntimeException;
 
 /**
- * Represents Uploaded Files.
- *
- * It manages and normalizes uploaded files according to the PSR-7 standard.
+ * Represents an uploaded file according to the PSR-7 standard.
  *
  * @link https://github.com/php-fig/http-message/blob/master/src/UploadedFileInterface.php
  * @link https://github.com/php-fig/http-message/blob/master/src/StreamInterface.php
@@ -31,42 +28,49 @@ class UploadedFile implements UploadedFileInterface
      * @var string
      */
     public $file;
+
     /**
      * The client-provided file name.
      *
      * @var string
      */
     protected $name;
+
     /**
      * The client-provided media type of the file.
      *
      * @var string
      */
     protected $type;
+
     /**
      * The size of the file in bytes.
      *
      * @var int
      */
     protected $size;
+
     /**
      * A valid PHP UPLOAD_ERR_xxx code for the file upload.
      *
      * @var int
      */
     protected $error = UPLOAD_ERR_OK;
+
     /**
      * Indicates if the upload is from a SAPI environment.
      *
      * @var bool
      */
     protected $sapi = false;
+
     /**
      * An optional StreamInterface wrapping the file resource.
      *
      * @var StreamInterface
      */
     protected $stream;
+
     /**
      * Indicates if the uploaded file has already been moved.
      *
@@ -77,15 +81,17 @@ class UploadedFile implements UploadedFileInterface
     /**
      * Create a normalized tree of UploadedFile instances from the Environment.
      *
+     * Returns a normalized tree of UploadedFile instances or null if none are provided.
+     *
      * @param Environment $env The environment
      *
-     * @return array|null A normalized tree of UploadedFile instances or null if none are provided.
+     * @return array|null
      */
     public static function createFromEnvironment(Environment $env)
     {
         if (is_array($env['slim.files']) && $env->has('slim.files')) {
             return $env['slim.files'];
-        } elseif (isset($_FILES)) {
+        } elseif (! empty($_FILES)) {
             return static::parseUploadedFiles($_FILES);
         }
 
@@ -95,9 +101,11 @@ class UploadedFile implements UploadedFileInterface
     /**
      * Parse a non-normalized, i.e. $_FILES superglobal, tree of uploaded file data.
      *
+     * Returns a normalized tree of UploadedFile instances.
+     *
      * @param array $uploadedFiles The non-normalized tree of uploaded file data.
      *
-     * @return array A normalized tree of UploadedFile instances.
+     * @return array
      */
     private static function parseUploadedFiles(array $uploadedFiles)
     {
@@ -139,8 +147,6 @@ class UploadedFile implements UploadedFileInterface
     }
 
     /**
-     * Construct a new UploadedFile instance.
-     *
      * @param string      $file The full path to the uploaded file provided by the client.
      * @param string|null $name The file name.
      * @param string|null $type The file media type.
@@ -170,14 +176,14 @@ class UploadedFile implements UploadedFileInterface
      * If the moveTo() method has been called previously, this method MUST raise
      * an exception.
      *
-     * @return StreamInterface Stream representation of the uploaded file.
-     * @throws \RuntimeException in cases when no stream is available or can be
-     *     created.
+     * @return StreamInterface
+     *
+     * @throws RuntimeException in cases when no stream is available or can be created.
      */
     public function getStream()
     {
         if ($this->moved) {
-            throw new \RuntimeException(sprintf('Uploaded file %s has already been moved', $this->name));
+            throw new RuntimeException(sprintf('Uploaded file %s has already been moved', $this->name));
         }
         if ($this->stream === null) {
             $this->stream = new Stream(fopen($this->file, 'r'));
@@ -216,9 +222,8 @@ class UploadedFile implements UploadedFileInterface
      *
      * @param string $targetPath Path to which to move the uploaded file.
      *
-     * @throws InvalidArgumentException if the $path specified is invalid.
-     * @throws RuntimeException on any error during the move operation, or on
-     *     the second or subsequent call to the method.
+     * @throws InvalidArgumentException If the $path specified is invalid.
+     * @throws RuntimeException On any error during the move operation or on the second subsequent call to the method.
      */
     public function moveTo($targetPath)
     {
@@ -268,7 +273,7 @@ class UploadedFile implements UploadedFileInterface
      *
      * @see http://php.net/manual/en/features.file-upload.errors.php
      *
-     * @return int One of PHP's UPLOAD_ERR_XXX constants.
+     * @return int
      */
     public function getError()
     {
@@ -285,8 +290,7 @@ class UploadedFile implements UploadedFileInterface
      * Implementations SHOULD return the value stored in the "name" key of
      * the file in the $_FILES array.
      *
-     * @return string|null The filename sent by the client or null if none
-     *     was provided.
+     * @return string|null
      */
     public function getClientFilename()
     {
@@ -303,8 +307,7 @@ class UploadedFile implements UploadedFileInterface
      * Implementations SHOULD return the value stored in the "type" key of
      * the file in the $_FILES array.
      *
-     * @return string|null The media type sent by the client or null if none
-     *     was provided.
+     * @return string|null
      */
     public function getClientMediaType()
     {
@@ -318,7 +321,7 @@ class UploadedFile implements UploadedFileInterface
      * the file in the $_FILES array if available, as PHP calculates this based
      * on the actual size transmitted.
      *
-     * @return int|null The file size in bytes or null if unknown.
+     * @return int|null
      */
     public function getSize()
     {
diff --git a/vendor/slim/slim/Slim/Http/Uri.php b/vendor/slim/slim/Slim/Http/Uri.php
index 7e168a66013327f78cc5e0ef81390a899125660f..5c67ec8cdf6309e0d413351fd41d7caafcbed4d5 100644
--- a/vendor/slim/slim/Slim/Http/Uri.php
+++ b/vendor/slim/slim/Slim/Http/Uri.php
@@ -2,15 +2,13 @@
 /**
  * Slim Framework (https://slimframework.com)
  *
- * @link      https://github.com/slimphp/Slim
- * @copyright Copyright (c) 2011-2017 Josh Lockhart
- * @license   https://github.com/slimphp/Slim/blob/3.x/LICENSE.md (MIT License)
+ * @license https://github.com/slimphp/Slim/blob/3.x/LICENSE.md (MIT License)
  */
+
 namespace Slim\Http;
 
 use InvalidArgumentException;
-use \Psr\Http\Message\UriInterface;
-use Slim\Http\Environment;
+use Psr\Http\Message\UriInterface;
 
 /**
  * Value object representing a URI.
@@ -98,8 +96,6 @@ class Uri implements UriInterface
     protected $fragment = '';
 
     /**
-     * Create new Uri.
-     *
      * @param string $scheme   Uri scheme.
      * @param string $host     Uri host.
      * @param int    $port     Uri port number.
@@ -122,7 +118,7 @@ class Uri implements UriInterface
         $this->scheme = $this->filterScheme($scheme);
         $this->host = $host;
         $this->port = $this->filterPort($port);
-        $this->path = empty($path) ? '/' : $this->filterPath($path);
+        $this->path = ($path === null || !strlen($path)) ? '/' : $this->filterPath($path);
         $this->query = $this->filterQuery($query);
         $this->fragment = $this->filterQuery($fragment);
         $this->user = $user;
@@ -132,8 +128,7 @@ class Uri implements UriInterface
     /**
      * Create new Uri from string.
      *
-     * @param  string $uri Complete Uri string
-     *     (i.e., https://user:pass@host:443/path?query).
+     * @param  string $uri Complete Uri string (i.e., https://user:pass@host:443/path?query).
      *
      * @return self
      */
@@ -199,12 +194,12 @@ class Uri implements UriInterface
         }
 
         // Path
-        $requestScriptName = parse_url($env->get('SCRIPT_NAME'), PHP_URL_PATH);
+        $requestScriptName = (string) parse_url($env->get('SCRIPT_NAME'), PHP_URL_PATH);
         $requestScriptDir = dirname($requestScriptName);
 
         // parse_url() requires a full URL. As we don't extract the domain name or scheme,
         // we use a stand-in.
-        $requestUri = parse_url('http://example.com' . $env->get('REQUEST_URI'), PHP_URL_PATH);
+        $requestUri = (string) parse_url('http://example.com' . $env->get('REQUEST_URI'), PHP_URL_PATH);
 
         $basePath = '';
         $virtualPath = $requestUri;
@@ -236,10 +231,6 @@ class Uri implements UriInterface
         return $uri;
     }
 
-    /********************************************************************************
-     * Scheme
-     *******************************************************************************/
-
     /**
      * Retrieve the scheme component of the URI.
      *
@@ -252,6 +243,7 @@ class Uri implements UriInterface
      * added.
      *
      * @see https://tools.ietf.org/html/rfc3986#section-3.1
+     *
      * @return string The URI scheme.
      */
     public function getScheme()
@@ -271,8 +263,10 @@ class Uri implements UriInterface
      * An empty scheme is equivalent to removing the scheme.
      *
      * @param string $scheme The scheme to use with the new instance.
+     *
      * @return self A new instance with the specified scheme.
-     * @throws \InvalidArgumentException for invalid or unsupported schemes.
+     *
+     * @throws InvalidArgumentException for invalid or unsupported schemes.
      */
     public function withScheme($scheme)
     {
@@ -312,10 +306,6 @@ class Uri implements UriInterface
         return $scheme;
     }
 
-    /********************************************************************************
-     * Authority
-     *******************************************************************************/
-
     /**
      * Retrieve the authority component of the URI.
      *
@@ -332,6 +322,7 @@ class Uri implements UriInterface
      * scheme, it SHOULD NOT be included.
      *
      * @see https://tools.ietf.org/html/rfc3986#section-3.2
+     *
      * @return string The URI authority, in "[user-info@]host[:port]" format.
      */
     public function getAuthority()
@@ -375,6 +366,7 @@ class Uri implements UriInterface
      *
      * @param string $user The user name to use for authority.
      * @param null|string $password The password associated with $user.
+     *
      * @return self A new instance with the specified user information.
      */
     public function withUserInfo($user, $password = null)
@@ -394,6 +386,7 @@ class Uri implements UriInterface
      * Filters the user info string.
      *
      * @param string $query The raw uri query string.
+     *
      * @return string The percent-encoded query string.
      */
     protected function filterUserInfo($query)
@@ -416,6 +409,7 @@ class Uri implements UriInterface
      * Section 3.2.2.
      *
      * @see http://tools.ietf.org/html/rfc3986#section-3.2.2
+     *
      * @return string The URI host.
      */
     public function getHost()
@@ -432,8 +426,8 @@ class Uri implements UriInterface
      * An empty host value is equivalent to removing the host.
      *
      * @param string $host The hostname to use with the new instance.
+     *
      * @return self A new instance with the specified host.
-     * @throws \InvalidArgumentException for invalid hostnames.
      */
     public function withHost($host)
     {
@@ -477,8 +471,8 @@ class Uri implements UriInterface
      *
      * @param null|int $port The port to use with the new instance; a null value
      *     removes the port information.
+     *
      * @return self A new instance with the specified port.
-     * @throws \InvalidArgumentException for invalid ports.
      */
     public function withPort($port)
     {
@@ -516,10 +510,6 @@ class Uri implements UriInterface
         throw new InvalidArgumentException('Uri port must be null or an integer between 1 and 65535 (inclusive)');
     }
 
-    /********************************************************************************
-     * Path
-     *******************************************************************************/
-
     /**
      * Retrieve the path component of the URI.
      *
@@ -543,6 +533,7 @@ class Uri implements UriInterface
      *
      * @see https://tools.ietf.org/html/rfc3986#section-2
      * @see https://tools.ietf.org/html/rfc3986#section-3.3
+     *
      * @return string The URI path.
      */
     public function getPath()
@@ -557,8 +548,7 @@ class Uri implements UriInterface
      * an instance that contains the specified path.
      *
      * The path can either be empty or absolute (starting with a slash) or
-     * rootless (not starting with a slash). Implementations MUST support all
-     * three syntaxes.
+     * rootless (not starting with a slash). Implementations MUST support all three syntaxes.
      *
      * If the path is intended to be domain-relative rather than path relative then
      * it must begin with a slash ("/"). Paths not starting with a slash ("/")
@@ -569,8 +559,10 @@ class Uri implements UriInterface
      * Implementations ensure the correct encoding as outlined in getPath().
      *
      * @param string $path The path to use with the new instance.
-     * @return self A new instance with the specified path.
-     * @throws \InvalidArgumentException for invalid paths.
+     *
+     * @return static A new instance with the specified path.
+     *
+     * @throws InvalidArgumentException For invalid paths.
      */
     public function withPath($path)
     {
@@ -610,7 +602,8 @@ class Uri implements UriInterface
      * Note: This method is not part of the PSR-7 standard.
      *
      * @param  string $basePath
-     * @return self
+     *
+     * @return static
      */
     public function withBasePath($basePath)
     {
@@ -632,13 +625,17 @@ class Uri implements UriInterface
     /**
      * Filter Uri path.
      *
+     * Returns a RFC 3986 percent-encoded uri path.
+     *
      * This method percent-encodes all reserved
      * characters in the provided path string. This method
      * will NOT double-encode characters that are already
      * percent-encoded.
      *
      * @param  string $path The raw uri path.
-     * @return string       The RFC 3986 percent-encoded uri path.
+     *
+     * @return string
+     *
      * @link   http://www.faqs.org/rfcs/rfc3986.html
      */
     protected function filterPath($path)
@@ -652,10 +649,6 @@ class Uri implements UriInterface
         );
     }
 
-    /********************************************************************************
-     * Query
-     *******************************************************************************/
-
     /**
      * Retrieve the query string of the URI.
      *
@@ -674,7 +667,8 @@ class Uri implements UriInterface
      *
      * @see https://tools.ietf.org/html/rfc3986#section-2
      * @see https://tools.ietf.org/html/rfc3986#section-3.4
-     * @return string The URI query string.
+     *
+     * @return string
      */
     public function getQuery()
     {
@@ -693,8 +687,10 @@ class Uri implements UriInterface
      * An empty query string value is equivalent to removing the query string.
      *
      * @param string $query The query string to use with the new instance.
+     *
      * @return self A new instance with the specified query string.
-     * @throws \InvalidArgumentException for invalid query strings.
+     *
+     * @throws InvalidArgumentException For invalid query strings.
      */
     public function withQuery($query)
     {
@@ -712,6 +708,7 @@ class Uri implements UriInterface
      * Filters the query string or fragment of a URI.
      *
      * @param string $query The raw uri query string.
+     *
      * @return string The percent-encoded query string.
      */
     protected function filterQuery($query)
@@ -725,10 +722,6 @@ class Uri implements UriInterface
         );
     }
 
-    /********************************************************************************
-     * Fragment
-     *******************************************************************************/
-
     /**
      * Retrieve the fragment component of the URI.
      *
@@ -743,6 +736,7 @@ class Uri implements UriInterface
      *
      * @see https://tools.ietf.org/html/rfc3986#section-2
      * @see https://tools.ietf.org/html/rfc3986#section-3.5
+     *
      * @return string The URI fragment.
      */
     public function getFragment()
@@ -762,7 +756,8 @@ class Uri implements UriInterface
      * An empty fragment value is equivalent to removing the fragment.
      *
      * @param string $fragment The fragment to use with the new instance.
-     * @return self A new instance with the specified fragment.
+     *
+     * @return static A new instance with the specified fragment.
      */
     public function withFragment($fragment)
     {
@@ -776,10 +771,6 @@ class Uri implements UriInterface
         return $clone;
     }
 
-    /********************************************************************************
-     * Helpers
-     *******************************************************************************/
-
     /**
      * Return the string representation as a URI reference.
      *
@@ -801,6 +792,7 @@ class Uri implements UriInterface
      * - If a fragment is present, it MUST be prefixed by "#".
      *
      * @see http://tools.ietf.org/html/rfc3986#section-4.1
+     *
      * @return string
      */
     public function __toString()
diff --git a/vendor/slim/slim/Slim/Interfaces/CallableResolverInterface.php b/vendor/slim/slim/Slim/Interfaces/CallableResolverInterface.php
index 17d81dbe84ea3e3b576b28c12fb7148358362a63..b3fd3fa9be9be005865f87b810fde4451686148c 100644
--- a/vendor/slim/slim/Slim/Interfaces/CallableResolverInterface.php
+++ b/vendor/slim/slim/Slim/Interfaces/CallableResolverInterface.php
@@ -2,26 +2,23 @@
 /**
  * Slim Framework (https://slimframework.com)
  *
- * @link      https://github.com/slimphp/Slim
- * @copyright Copyright (c) 2011-2017 Josh Lockhart
- * @license   https://github.com/slimphp/Slim/blob/3.x/LICENSE.md (MIT License)
+ * @license https://github.com/slimphp/Slim/blob/3.x/LICENSE.md (MIT License)
  */
+
 namespace Slim\Interfaces;
 
-/**
- * Resolves a callable.
- *
- * @package Slim
- * @since 3.0.0
- */
+use RuntimeException;
+
 interface CallableResolverInterface
 {
     /**
      * Invoke the resolved callable.
      *
-     * @param mixed $toResolve
+     * @param callable|string $toResolve
      *
      * @return callable
+     *
+     * @throws RuntimeException
      */
     public function resolve($toResolve);
 }
diff --git a/vendor/slim/slim/Slim/Interfaces/CollectionInterface.php b/vendor/slim/slim/Slim/Interfaces/CollectionInterface.php
index be995bf46e7ca503e6457f7ddc62f82b62f8b432..9af5890236f0631dce1a4c4391d56a5df65ea27b 100644
--- a/vendor/slim/slim/Slim/Interfaces/CollectionInterface.php
+++ b/vendor/slim/slim/Slim/Interfaces/CollectionInterface.php
@@ -2,31 +2,67 @@
 /**
  * Slim Framework (https://slimframework.com)
  *
- * @link      https://github.com/slimphp/Slim
- * @copyright Copyright (c) 2011-2017 Josh Lockhart
- * @license   https://github.com/slimphp/Slim/blob/3.x/LICENSE.md (MIT License)
+ * @license https://github.com/slimphp/Slim/blob/3.x/LICENSE.md (MIT License)
  */
+
 namespace Slim\Interfaces;
 
-/**
- * Collection Interface
- *
- * @package Slim
- * @since   3.0.0
- */
-interface CollectionInterface extends \ArrayAccess, \Countable, \IteratorAggregate
+use ArrayAccess;
+use Countable;
+use IteratorAggregate;
+
+interface CollectionInterface extends ArrayAccess, Countable, IteratorAggregate
 {
+    /**
+     * Set collection item
+     *
+     * @param string $key   The data key
+     * @param mixed  $value The data value
+     */
     public function set($key, $value);
 
+    /**
+     * Get collection item for key
+     *
+     * @param string $key     The data key
+     * @param mixed  $default The default value to return if data key does not exist
+     *
+     * @return mixed The key's value, or the default value
+     */
     public function get($key, $default = null);
 
+    /**
+     * Add item to collection, replacing existing items with the same data key
+     *
+     * @param array $items Key-value array of data to append to this collection
+     */
     public function replace(array $items);
 
+    /**
+     * Get all items in collection
+     *
+     * @return array The collection's source data
+     */
     public function all();
 
+    /**
+     * Does this collection have a given key?
+     *
+     * @param string $key The data key
+     *
+     * @return bool
+     */
     public function has($key);
 
+    /**
+     * Remove item from collection
+     *
+     * @param string $key The data key
+     */
     public function remove($key);
 
+    /**
+     * Remove all items from collection
+     */
     public function clear();
 }
diff --git a/vendor/slim/slim/Slim/Interfaces/Http/CookiesInterface.php b/vendor/slim/slim/Slim/Interfaces/Http/CookiesInterface.php
index 206175adba7a8349d6b9f325003266d52d66bed1..a1673a1823640c0ce539454bb6accf5d896631c0 100644
--- a/vendor/slim/slim/Slim/Interfaces/Http/CookiesInterface.php
+++ b/vendor/slim/slim/Slim/Interfaces/Http/CookiesInterface.php
@@ -2,22 +2,48 @@
 /**
  * Slim Framework (https://slimframework.com)
  *
- * @link      https://github.com/slimphp/Slim
- * @copyright Copyright (c) 2011-2017 Josh Lockhart
- * @license   https://github.com/slimphp/Slim/blob/3.x/LICENSE.md (MIT License)
+ * @license https://github.com/slimphp/Slim/blob/3.x/LICENSE.md (MIT License)
  */
+
 namespace Slim\Interfaces\Http;
 
-/**
- * Cookies Interface
- *
- * @package Slim
- * @since   3.0.0
- */
+use InvalidArgumentException;
+
 interface CookiesInterface
 {
+    /**
+     * Get request cookie
+     *
+     * @param  string $name    Cookie name
+     * @param  mixed  $default Cookie default value
+     *
+     * @return mixed Cookie value if present, else default
+     */
     public function get($name, $default = null);
+
+    /**
+     * Set response cookie
+     *
+     * @param string       $name  Cookie name
+     * @param string|array $value Cookie value, or cookie properties
+     */
     public function set($name, $value);
+
+    /**
+     * Convert to array of `Set-Cookie` headers
+     *
+     * @return string[]
+     */
     public function toHeaders();
+
+    /**
+     * Parse HTTP request `Cookie:` header and extract into a PHP associative array.
+     *
+     * @param  string $header The raw HTTP request `Cookie:` header
+     *
+     * @return array Associative array of cookie names and values
+     *
+     * @throws InvalidArgumentException if the cookie data cannot be parsed
+     */
     public static function parseHeader($header);
 }
diff --git a/vendor/slim/slim/Slim/Interfaces/Http/EnvironmentInterface.php b/vendor/slim/slim/Slim/Interfaces/Http/EnvironmentInterface.php
index af19d28b532f45a38427a52170f67fbf89c56aca..49eae5b602870634abb85a85340beb403e88806d 100644
--- a/vendor/slim/slim/Slim/Interfaces/Http/EnvironmentInterface.php
+++ b/vendor/slim/slim/Slim/Interfaces/Http/EnvironmentInterface.php
@@ -2,19 +2,19 @@
 /**
  * Slim Framework (https://slimframework.com)
  *
- * @link      https://github.com/slimphp/Slim
- * @copyright Copyright (c) 2011-2017 Josh Lockhart
- * @license   https://github.com/slimphp/Slim/blob/3.x/LICENSE.md (MIT License)
+ * @license https://github.com/slimphp/Slim/blob/3.x/LICENSE.md (MIT License)
  */
+
 namespace Slim\Interfaces\Http;
 
-/**
- * Environment Interface
- *
- * @package Slim
- * @since   3.0.0
- */
 interface EnvironmentInterface
 {
+    /**
+     * Create mock environment
+     *
+     * @param  array $settings Array of custom environment keys and values
+     *
+     * @return static
+     */
     public static function mock(array $settings = []);
 }
diff --git a/vendor/slim/slim/Slim/Interfaces/Http/HeadersInterface.php b/vendor/slim/slim/Slim/Interfaces/Http/HeadersInterface.php
index b737705a207e59909e8fe7c10e1f8098c2ce2691..f86cab5e2aec9b8c5370fde0b9cb9377e70cfd2b 100644
--- a/vendor/slim/slim/Slim/Interfaces/Http/HeadersInterface.php
+++ b/vendor/slim/slim/Slim/Interfaces/Http/HeadersInterface.php
@@ -2,23 +2,37 @@
 /**
  * Slim Framework (https://slimframework.com)
  *
- * @link      https://github.com/slimphp/Slim
- * @copyright Copyright (c) 2011-2017 Josh Lockhart
- * @license   https://github.com/slimphp/Slim/blob/3.x/LICENSE.md (MIT License)
+ * @license https://github.com/slimphp/Slim/blob/3.x/LICENSE.md (MIT License)
  */
+
 namespace Slim\Interfaces\Http;
 
 use Slim\Interfaces\CollectionInterface;
 
-/**
- * Headers Interface
- *
- * @package Slim
- * @since   3.0.0
- */
 interface HeadersInterface extends CollectionInterface
 {
+    /**
+     * Add HTTP header value
+     *
+     * This method appends a header value. Unlike the set() method,
+     * this method _appends_ this new value to any values
+     * that already exist for this header name.
+     *
+     * @param string          $key   The case-insensitive header name
+     * @param string|string[] $value The new header value(s)
+     */
     public function add($key, $value);
 
+    /**
+     * Normalize header name
+     *
+     * This method transforms header names into a
+     * normalized form. This is how we enable case-insensitive
+     * header names in the other methods in this class.
+     *
+     * @param  string $key The case-insensitive header name
+     *
+     * @return string Normalized header name
+     */
     public function normalizeKey($key);
 }
diff --git a/vendor/slim/slim/Slim/Interfaces/InvocationStrategyInterface.php b/vendor/slim/slim/Slim/Interfaces/InvocationStrategyInterface.php
index 14a92c1de6c01cca10b90c33f07ea0b2691907ac..0e73a42d100e2da05299f175e251145719cd5f4e 100644
--- a/vendor/slim/slim/Slim/Interfaces/InvocationStrategyInterface.php
+++ b/vendor/slim/slim/Slim/Interfaces/InvocationStrategyInterface.php
@@ -2,29 +2,23 @@
 /**
  * Slim Framework (https://slimframework.com)
  *
- * @link      https://github.com/slimphp/Slim
- * @copyright Copyright (c) 2011-2017 Josh Lockhart
- * @license   https://github.com/slimphp/Slim/blob/3.x/LICENSE.md (MIT License)
+ * @license https://github.com/slimphp/Slim/blob/3.x/LICENSE.md (MIT License)
  */
+
 namespace Slim\Interfaces;
 
 use Psr\Http\Message\ResponseInterface;
 use Psr\Http\Message\ServerRequestInterface;
 
-/**
- * Defines a contract for invoking a route callable.
- */
 interface InvocationStrategyInterface
 {
     /**
-     * Invoke a route callable.
-     *
      * @param callable               $callable The callable to invoke using the strategy.
      * @param ServerRequestInterface $request The request object.
      * @param ResponseInterface      $response The response object.
-     * @param array                  $routeArguments The route's placholder arguments
+     * @param array                  $routeArguments The route's placeholder arguments
      *
-     * @return ResponseInterface|string The response from the callable.
+     * @return ResponseInterface|string
      */
     public function __invoke(
         callable $callable,
diff --git a/vendor/slim/slim/Slim/Interfaces/RouteGroupInterface.php b/vendor/slim/slim/Slim/Interfaces/RouteGroupInterface.php
index 5ed33037e146d34deabab48ea5c732025bfe7fcf..31340b13e7c6ff35b5384bd32598990722133f38 100644
--- a/vendor/slim/slim/Slim/Interfaces/RouteGroupInterface.php
+++ b/vendor/slim/slim/Slim/Interfaces/RouteGroupInterface.php
@@ -2,20 +2,13 @@
 /**
  * Slim Framework (https://slimframework.com)
  *
- * @link      https://github.com/slimphp/Slim
- * @copyright Copyright (c) 2011-2017 Josh Lockhart
- * @license   https://github.com/slimphp/Slim/blob/3.x/LICENSE.md (MIT License)
+ * @license https://github.com/slimphp/Slim/blob/3.x/LICENSE.md (MIT License)
  */
+
 namespace Slim\Interfaces;
 
 use Slim\App;
 
-/**
- * RouteGroup Interface
- *
- * @package Slim
- * @since   3.0.0
- */
 interface RouteGroupInterface
 {
     /**
diff --git a/vendor/slim/slim/Slim/Interfaces/RouteInterface.php b/vendor/slim/slim/Slim/Interfaces/RouteInterface.php
index 64be5341999b710fdabd08dba39e379539816828..8d0f4f05fc0c7e6fb62c34db594acb5569042ae8 100644
--- a/vendor/slim/slim/Slim/Interfaces/RouteInterface.php
+++ b/vendor/slim/slim/Slim/Interfaces/RouteInterface.php
@@ -2,29 +2,21 @@
 /**
  * Slim Framework (https://slimframework.com)
  *
- * @link      https://github.com/slimphp/Slim
- * @copyright Copyright (c) 2011-2017 Josh Lockhart
- * @license   https://github.com/slimphp/Slim/blob/3.x/LICENSE.md (MIT License)
+ * @license https://github.com/slimphp/Slim/blob/3.x/LICENSE.md (MIT License)
  */
+
 namespace Slim\Interfaces;
 
 use InvalidArgumentException;
-use Psr\Http\Message\ServerRequestInterface;
 use Psr\Http\Message\ResponseInterface;
+use Psr\Http\Message\ServerRequestInterface;
 
-/**
- * Route Interface
- *
- * @package Slim
- * @since   3.0.0
- */
 interface RouteInterface
 {
-
     /**
      * Retrieve a specific route argument
      *
-     * @param string $name
+     * @param string      $name
      * @param string|null $default
      *
      * @return string|null
@@ -58,7 +50,7 @@ interface RouteInterface
      * @param string $name
      * @param string $value
      *
-     * @return self
+     * @return RouteInterface
      */
     public function setArgument($name, $value);
 
@@ -67,7 +59,7 @@ interface RouteInterface
      *
      * @param string[] $arguments
      *
-     * @return self
+     * @return RouteInterface
      */
     public function setArguments(array $arguments);
 
@@ -87,7 +79,8 @@ interface RouteInterface
      *
      * @param string $name
      *
-     * @return static
+     * @return RouteInterface
+     *
      * @throws InvalidArgumentException if the route name is not a string
      */
     public function setName($name);
@@ -107,7 +100,7 @@ interface RouteInterface
      * Prepare the route for use
      *
      * @param ServerRequestInterface $request
-     * @param array $arguments
+     * @param array                  $arguments
      */
     public function prepare(ServerRequestInterface $request, array $arguments);
 
@@ -119,7 +112,8 @@ interface RouteInterface
      * back to the Application.
      *
      * @param ServerRequestInterface $request
-     * @param ResponseInterface $response
+     * @param ResponseInterface      $response
+     *
      * @return ResponseInterface
      */
     public function run(ServerRequestInterface $request, ResponseInterface $response);
diff --git a/vendor/slim/slim/Slim/Interfaces/RouterInterface.php b/vendor/slim/slim/Slim/Interfaces/RouterInterface.php
index 2ab8b678f0434f658156486d577cad8070b376e2..767699a642014985546f28132232f2b31b3eb6ed 100644
--- a/vendor/slim/slim/Slim/Interfaces/RouterInterface.php
+++ b/vendor/slim/slim/Slim/Interfaces/RouterInterface.php
@@ -2,25 +2,20 @@
 /**
  * Slim Framework (https://slimframework.com)
  *
- * @link      https://github.com/slimphp/Slim
- * @copyright Copyright (c) 2011-2017 Josh Lockhart
- * @license   https://github.com/slimphp/Slim/blob/3.x/LICENSE.md (MIT License)
+ * @license https://github.com/slimphp/Slim/blob/3.x/LICENSE.md (MIT License)
  */
+
 namespace Slim\Interfaces;
 
-use RuntimeException;
 use InvalidArgumentException;
 use Psr\Http\Message\ServerRequestInterface;
+use RuntimeException;
 
-/**
- * Router Interface
- *
- * @package Slim
- * @since   3.0.0
- */
 interface RouterInterface
 {
-    // array keys from route result
+    /**
+     * Route result constants
+     */
     const DISPATCH_STATUS = 0;
     const ALLOWED_METHODS = 1;
 
@@ -68,16 +63,16 @@ interface RouterInterface
      *
      * @param string $name        Route name
      *
-     * @return \Slim\Interfaces\RouteInterface
+     * @return RouteInterface
      *
      * @throws RuntimeException   If named route does not exist
      */
     public function getNamedRoute($name);
 
     /**
-     * @param $identifier
+     * @param string $identifier
      *
-     * @return \Slim\Interfaces\RouteInterface
+     * @return RouteInterface
      */
     public function lookupRoute($identifier);
 
diff --git a/vendor/slim/slim/Slim/MiddlewareAwareTrait.php b/vendor/slim/slim/Slim/MiddlewareAwareTrait.php
index 8b8a1755d227cce2d6942a8db2b971de3a735b71..3f3236616e33caaf719b55e9b5ca86427a5305d2 100644
--- a/vendor/slim/slim/Slim/MiddlewareAwareTrait.php
+++ b/vendor/slim/slim/Slim/MiddlewareAwareTrait.php
@@ -2,15 +2,14 @@
 /**
  * Slim Framework (https://slimframework.com)
  *
- * @link      https://github.com/slimphp/Slim
- * @copyright Copyright (c) 2011-2017 Josh Lockhart
- * @license   https://github.com/slimphp/Slim/blob/3.x/LICENSE.md (MIT License)
+ * @license https://github.com/slimphp/Slim/blob/3.x/LICENSE.md (MIT License)
  */
+
 namespace Slim;
 
-use RuntimeException;
-use Psr\Http\Message\ServerRequestInterface;
 use Psr\Http\Message\ResponseInterface;
+use Psr\Http\Message\ServerRequestInterface;
+use RuntimeException;
 use UnexpectedValueException;
 
 /**
@@ -42,9 +41,10 @@ trait MiddlewareAwareTrait
      * This method prepends new middleware to the application middleware stack.
      *
      * @param callable $callable Any callable that accepts three arguments:
-     *                           1. A Request object
-     *                           2. A Response object
-     *                           3. A "next" middleware callable
+     * 1. A Request object
+     * 2. A Response object
+     * 3. A "next" middleware callable
+     *
      * @return static
      *
      * @throws RuntimeException         If middleware is added while the stack is dequeuing
diff --git a/vendor/slim/slim/Slim/Routable.php b/vendor/slim/slim/Slim/Routable.php
index c912db433a144810c408c068e6bca7ee9d882f25..2563e05358c6ac227adefc7fd4871419d63b0c53 100644
--- a/vendor/slim/slim/Slim/Routable.php
+++ b/vendor/slim/slim/Slim/Routable.php
@@ -2,20 +2,13 @@
 /**
  * Slim Framework (https://slimframework.com)
  *
- * @link      https://github.com/slimphp/Slim
- * @copyright Copyright (c) 2011-2017 Josh Lockhart
- * @license   https://github.com/slimphp/Slim/blob/3.x/LICENSE.md (MIT License)
+ * @license https://github.com/slimphp/Slim/blob/3.x/LICENSE.md (MIT License)
  */
+
 namespace Slim;
 
 use Psr\Container\ContainerInterface;
 
-/**
- * A routable, middleware-aware object
- *
- * @package Slim
- * @since   3.0.0
- */
 abstract class Routable
 {
     use CallableResolverAwareTrait;
@@ -48,6 +41,16 @@ abstract class Routable
      */
     protected $pattern;
 
+    /**
+     * @param string   $pattern
+     * @param callable $callable
+     */
+    public function __construct($pattern, $callable)
+    {
+        $this->pattern = $pattern;
+        $this->callable = $callable;
+    }
+
     /**
      * Get the middleware registered for the group
      *
@@ -73,7 +76,7 @@ abstract class Routable
      *
      * @param ContainerInterface $container
      *
-     * @return self
+     * @return static
      */
     public function setContainer(ContainerInterface $container)
     {
diff --git a/vendor/slim/slim/Slim/Route.php b/vendor/slim/slim/Slim/Route.php
index 117c0998397492c8a296d24e92457af40364e9fd..7af218ccd15a0bbc6477641db5423bbf49dea191 100644
--- a/vendor/slim/slim/Slim/Route.php
+++ b/vendor/slim/slim/Slim/Route.php
@@ -2,22 +2,19 @@
 /**
  * Slim Framework (https://slimframework.com)
  *
- * @link      https://github.com/slimphp/Slim
- * @copyright Copyright (c) 2011-2017 Josh Lockhart
- * @license   https://github.com/slimphp/Slim/blob/3.x/LICENSE.md (MIT License)
+ * @license https://github.com/slimphp/Slim/blob/3.x/LICENSE.md (MIT License)
  */
+
 namespace Slim;
 
+use Closure;
 use InvalidArgumentException;
-use Psr\Http\Message\ServerRequestInterface;
 use Psr\Http\Message\ResponseInterface;
+use Psr\Http\Message\ServerRequestInterface;
 use Slim\Handlers\Strategies\RequestResponse;
 use Slim\Interfaces\InvocationStrategyInterface;
 use Slim\Interfaces\RouteInterface;
 
-/**
- * Route
- */
 class Route extends Routable implements RouteInterface
 {
     use MiddlewareAwareTrait;
@@ -76,33 +73,20 @@ class Route extends Routable implements RouteInterface
     protected $savedArguments = [];
 
     /**
-     * The callable payload
-     *
-     * @var callable
-     */
-    protected $callable;
-
-    /**
-     * Create new route
-     *
-     * @param string|string[]   $methods The route HTTP methods
-     * @param string            $pattern The route pattern
-     * @param callable          $callable The route callable
-     * @param RouteGroup[]      $groups The parent route groups
-     * @param int               $identifier The route identifier
+     * @param string|string[] $methods The route HTTP methods
+     * @param string          $pattern The route pattern
+     * @param callable        $callable The route callable
+     * @param RouteGroup[]    $groups The parent route groups
+     * @param int             $identifier The route identifier
      */
     public function __construct($methods, $pattern, $callable, $groups = [], $identifier = 0)
     {
+        parent::__construct($pattern, $callable);
         $this->methods  = is_string($methods) ? [$methods] : $methods;
-        $this->pattern  = $pattern;
-        $this->callable = $callable;
         $this->groups   = $groups;
         $this->identifier = 'route' . $identifier;
     }
 
-    /**
-     * Finalize the route in preparation for dispatching
-     */
     public function finalize()
     {
         if ($this->finalized) {
@@ -136,7 +120,7 @@ class Route extends Routable implements RouteInterface
     /**
      * This method enables you to override the Route's callable
      *
-     * @param string|\Closure $callable
+     * @param string|Closure $callable
      */
     public function setCallable($callable)
     {
@@ -164,9 +148,7 @@ class Route extends Routable implements RouteInterface
     }
 
     /**
-     * Get route name
-     *
-     * @return null|string
+     * {@inheritdoc}
      */
     public function getName()
     {
@@ -194,15 +176,7 @@ class Route extends Routable implements RouteInterface
     }
 
     /**
-     * Set output buffering mode
-     *
-     * One of: false, 'prepend' or 'append'
-     *
-     * @param boolean|string $mode
-     *
-     * @return self
-     *
-     * @throws InvalidArgumentException If an unknown buffering mode is specified
+     * {@inheritdoc}
      */
     public function setOutputBuffering($mode)
     {
@@ -214,13 +188,7 @@ class Route extends Routable implements RouteInterface
     }
 
     /**
-     * Set route name
-     *
-     * @param string $name
-     *
-     * @return self
-     *
-     * @throws InvalidArgumentException if the route name is not a string
+     * {@inheritdoc}
      */
     public function setName($name)
     {
@@ -232,13 +200,7 @@ class Route extends Routable implements RouteInterface
     }
 
     /**
-     * Set a route argument
-     *
-     * @param string $name
-     * @param string $value
-     * @param bool $includeInSavedArguments
-     *
-     * @return self
+     * {@inheritdoc}
      */
     public function setArgument($name, $value, $includeInSavedArguments = true)
     {
@@ -250,12 +212,7 @@ class Route extends Routable implements RouteInterface
     }
 
     /**
-     * Replace route arguments
-     *
-     * @param array $arguments
-     * @param bool $includeInSavedArguments
-     *
-     * @return self
+     * {@inheritdoc}
      */
     public function setArguments(array $arguments, $includeInSavedArguments = true)
     {
@@ -267,9 +224,7 @@ class Route extends Routable implements RouteInterface
     }
 
     /**
-     * Retrieve route arguments
-     *
-     * @return array
+     * {@inheritdoc}
      */
     public function getArguments()
     {
@@ -277,12 +232,7 @@ class Route extends Routable implements RouteInterface
     }
 
     /**
-     * Retrieve a specific route argument
-     *
-     * @param string $name
-     * @param string|null $default
-     *
-     * @return mixed
+     * {@inheritdoc}
      */
     public function getArgument($name, $default = null)
     {
@@ -292,15 +242,8 @@ class Route extends Routable implements RouteInterface
         return $default;
     }
 
-    /********************************************************************************
-     * Route Runner
-     *******************************************************************************/
-
     /**
-     * Prepare the route for use
-     *
-     * @param ServerRequestInterface $request
-     * @param array $arguments
+     * {@inheritdoc}
      */
     public function prepare(ServerRequestInterface $request, array $arguments)
     {
@@ -314,16 +257,7 @@ class Route extends Routable implements RouteInterface
     }
 
     /**
-     * Run route
-     *
-     * This method traverses the middleware stack, including the route's callable
-     * and captures the resultant HTTP response object. It then sends the response
-     * back to the Application.
-     *
-     * @param ServerRequestInterface $request
-     * @param ResponseInterface      $response
-     *
-     * @return ResponseInterface
+     * {@inheritdoc}
      */
     public function run(ServerRequestInterface $request, ResponseInterface $response)
     {
@@ -335,16 +269,7 @@ class Route extends Routable implements RouteInterface
     }
 
     /**
-     * Dispatch route callable against current Request and Response objects
-     *
-     * This method invokes the route object's callable. If middleware is
-     * registered for the route, each callable middleware is invoked in
-     * the order specified.
-     *
-     * @param ServerRequestInterface $request  The current Request object
-     * @param ResponseInterface      $response The current Response object
-     * @return \Psr\Http\Message\ResponseInterface
-     * @throws \Exception  if the route callable throws an exception
+     * {@inheritdoc}
      */
     public function __invoke(ServerRequestInterface $request, ResponseInterface $response)
     {
diff --git a/vendor/slim/slim/Slim/RouteGroup.php b/vendor/slim/slim/Slim/RouteGroup.php
index 8260bbd6c7608ae8ae722458ddac257d19c6a7df..26fe5c073563d700b4a4659860700c3ed7dc4d6d 100644
--- a/vendor/slim/slim/Slim/RouteGroup.php
+++ b/vendor/slim/slim/Slim/RouteGroup.php
@@ -2,38 +2,18 @@
 /**
  * Slim Framework (https://slimframework.com)
  *
- * @link      https://github.com/slimphp/Slim
- * @copyright Copyright (c) 2011-2017 Josh Lockhart
- * @license   https://github.com/slimphp/Slim/blob/3.x/LICENSE.md (MIT License)
+ * @license https://github.com/slimphp/Slim/blob/3.x/LICENSE.md (MIT License)
  */
+
 namespace Slim;
 
 use Closure;
 use Slim\Interfaces\RouteGroupInterface;
 
-/**
- * A collector for Routable objects with a common middleware stack
- *
- * @package Slim
- */
 class RouteGroup extends Routable implements RouteGroupInterface
 {
     /**
-     * Create a new RouteGroup
-     *
-     * @param string   $pattern  The pattern prefix for the group
-     * @param callable $callable The group callable
-     */
-    public function __construct($pattern, $callable)
-    {
-        $this->pattern = $pattern;
-        $this->callable = $callable;
-    }
-
-    /**
-     * Invoke the group to register any Routable objects within it.
-     *
-     * @param App $app The App instance to bind/pass to the group callable
+     * {@inheritdoc}
      */
     public function __invoke(App $app = null)
     {
diff --git a/vendor/slim/slim/Slim/Router.php b/vendor/slim/slim/Slim/Router.php
index 83116288c68c605a513eaacdb8a75e597164724d..08a95018294bc51b4161961ce634ed94686041b9 100644
--- a/vendor/slim/slim/Slim/Router.php
+++ b/vendor/slim/slim/Slim/Router.php
@@ -2,27 +2,24 @@
 /**
  * Slim Framework (https://slimframework.com)
  *
- * @link      https://github.com/slimphp/Slim
- * @copyright Copyright (c) 2011-2017 Josh Lockhart
- * @license   https://github.com/slimphp/Slim/blob/3.x/LICENSE.md (MIT License)
+ * @license https://github.com/slimphp/Slim/blob/3.x/LICENSE.md (MIT License)
  */
+
 namespace Slim;
 
 use FastRoute\Dispatcher;
-use Psr\Container\ContainerInterface;
-use InvalidArgumentException;
-use RuntimeException;
-use Psr\Http\Message\ServerRequestInterface;
 use FastRoute\RouteCollector;
 use FastRoute\RouteParser;
 use FastRoute\RouteParser\Std as StdParser;
-use Slim\Interfaces\RouteGroupInterface;
-use Slim\Interfaces\RouterInterface;
+use InvalidArgumentException;
+use Psr\Container\ContainerInterface;
+use Psr\Http\Message\ServerRequestInterface;
+use Psr\Http\Message\UriInterface;
+use RuntimeException;
 use Slim\Interfaces\RouteInterface;
+use Slim\Interfaces\RouterInterface;
 
 /**
- * Router
- *
  * This class organizes Slim application route objects. It is responsible
  * for registering route objects, assigning names to route objects,
  * finding routes that match the current HTTP request, and creating
@@ -40,7 +37,7 @@ class Router implements RouterInterface
     /**
      * Parser
      *
-     * @var \FastRoute\RouteParser
+     * @var RouteParser
      */
     protected $routeParser;
 
@@ -79,13 +76,11 @@ class Router implements RouterInterface
     protected $routeGroups = [];
 
     /**
-     * @var \FastRoute\Dispatcher
+     * @var Dispatcher
      */
     protected $dispatcher;
 
     /**
-     * Create new router
-     *
      * @param RouteParser   $parser
      */
     public function __construct(RouteParser $parser = null)
@@ -98,7 +93,8 @@ class Router implements RouterInterface
      *
      * @param string $basePath
      *
-     * @return self
+     * @return static
+     * @throws InvalidArgumentException
      */
     public function setBasePath($basePath)
     {
@@ -111,26 +107,45 @@ class Router implements RouterInterface
         return $this;
     }
 
+    /**
+     * Get the base path used in pathFor()
+     *
+     * @return string
+     */
+    public function getBasePath()
+    {
+        return $this->basePath;
+    }
+
     /**
      * Set path to fast route cache file. If this is false then route caching is disabled.
      *
      * @param string|false $cacheFile
      *
-     * @return self
+     * @return static
+     *
+     * @throws InvalidArgumentException If cacheFile is not a string or not false
+     * @throws RuntimeException         If cacheFile directory is not writable
      */
     public function setCacheFile($cacheFile)
     {
         if (!is_string($cacheFile) && $cacheFile !== false) {
-            throw new InvalidArgumentException('Router cacheFile must be a string or false');
+            throw new InvalidArgumentException('Router cache file must be a string or false');
         }
 
-        $this->cacheFile = $cacheFile;
-
-        if ($cacheFile !== false && !is_writable(dirname($cacheFile))) {
-            throw new RuntimeException('Router cacheFile directory must be writable');
+        if ($cacheFile && file_exists($cacheFile) && !is_readable($cacheFile)) {
+            throw new RuntimeException(
+                sprintf('Router cache file `%s` is not readable', $cacheFile)
+            );
         }
 
+        if ($cacheFile && !file_exists($cacheFile) && !is_writable(dirname($cacheFile))) {
+            throw new RuntimeException(
+                sprintf('Router cache file directory `%s` is not writable', dirname($cacheFile))
+            );
+        }
 
+        $this->cacheFile = $cacheFile;
         return $this;
     }
 
@@ -143,15 +158,7 @@ class Router implements RouterInterface
     }
 
     /**
-     * Add route
-     *
-     * @param  string[] $methods Array of HTTP methods
-     * @param  string   $pattern The route pattern
-     * @param  callable $handler The route callable
-     *
-     * @return RouteInterface
-     *
-     * @throws InvalidArgumentException if the route pattern isn't a string
+     * {@inheritdoc}
      */
     public function map($methods, $pattern, $handler)
     {
@@ -167,8 +174,9 @@ class Router implements RouterInterface
         // According to RFC methods are defined in uppercase (See RFC 7231)
         $methods = array_map("strtoupper", $methods);
 
-        // Add route
+        /** @var Route $route */
         $route = $this->createRoute($methods, $pattern, $handler);
+
         $this->routes[$route->getIdentifier()] = $route;
         $this->routeCounter++;
 
@@ -176,13 +184,7 @@ class Router implements RouterInterface
     }
 
     /**
-     * Dispatch router for HTTP request
-     *
-     * @param  ServerRequestInterface $request The current HTTP request object
-     *
-     * @return array
-     *
-     * @link   https://github.com/nikic/FastRoute/blob/master/src/Dispatcher.php
+     * {@inheritdoc}
      */
     public function dispatch(ServerRequestInterface $request)
     {
@@ -201,7 +203,7 @@ class Router implements RouterInterface
      * @param  string   $pattern The route pattern
      * @param  callable $callable The route callable
      *
-     * @return \Slim\Interfaces\RouteInterface
+     * @return RouteInterface
      */
     protected function createRoute($methods, $pattern, $callable)
     {
@@ -214,7 +216,7 @@ class Router implements RouterInterface
     }
 
     /**
-     * @return \FastRoute\Dispatcher
+     * @return Dispatcher
      */
     protected function createDispatcher()
     {
@@ -243,7 +245,7 @@ class Router implements RouterInterface
     }
 
     /**
-     * @param \FastRoute\Dispatcher $dispatcher
+     * @param Dispatcher $dispatcher
      */
     public function setDispatcher(Dispatcher $dispatcher)
     {
@@ -261,13 +263,7 @@ class Router implements RouterInterface
     }
 
     /**
-     * Get named route object
-     *
-     * @param string $name        Route name
-     *
-     * @return Route
-     *
-     * @throws RuntimeException   If named route does not exist
+     * {@inheritdoc}
      */
     public function getNamedRoute($name)
     {
@@ -309,12 +305,7 @@ class Router implements RouterInterface
     }
 
     /**
-     * Add a route group to the array
-     *
-     * @param string   $pattern
-     * @param callable $callable
-     *
-     * @return RouteGroupInterface
+     * {@inheritdoc}
      */
     public function pushGroup($pattern, $callable)
     {
@@ -324,9 +315,7 @@ class Router implements RouterInterface
     }
 
     /**
-     * Removes the last route group from the array
-     *
-     * @return RouteGroup|bool The RouteGroup if successful, else False
+     * {@inheritdoc}
      */
     public function popGroup()
     {
@@ -335,8 +324,7 @@ class Router implements RouterInterface
     }
 
     /**
-     * @param $identifier
-     * @return \Slim\Interfaces\RouteInterface
+     * {@inheritdoc}
      */
     public function lookupRoute($identifier)
     {
@@ -347,16 +335,7 @@ class Router implements RouterInterface
     }
 
     /**
-     * Build the path for a named route excluding the base path
-     *
-     * @param string $name        Route name
-     * @param array  $data        Named argument replacement data
-     * @param array  $queryParams Optional query string parameters
-     *
-     * @return string
-     *
-     * @throws RuntimeException         If named route does not exist
-     * @throws InvalidArgumentException If required data not provided
+     * {@inheritdoc}
      */
     public function relativePathFor($name, array $data = [], array $queryParams = [])
     {
@@ -371,6 +350,7 @@ class Router implements RouterInterface
         $routeDatas = array_reverse($routeDatas);
 
         $segments = [];
+        $segmentName = '';
         foreach ($routeDatas as $routeData) {
             foreach ($routeData as $item) {
                 if (is_string($item)) {
@@ -402,13 +382,24 @@ class Router implements RouterInterface
         }
         $url = implode('', $segments);
 
-        if ($queryParams) {
+        $hasQueryParams = array_filter($queryParams, function ($value) {
+            return $value !== null;
+        }) !== [];
+
+        if ($hasQueryParams) {
             $url .= '?' . http_build_query($queryParams);
         }
 
         return $url;
     }
 
+    /**
+     * {@inheritdoc}
+     */
+    public function pathFor($name, array $data = [], array $queryParams = [])
+    {
+        return $this->urlFor($name, $data, $queryParams);
+    }
 
     /**
      * Build the path for a named route including the base path
@@ -422,7 +413,7 @@ class Router implements RouterInterface
      * @throws RuntimeException         If named route does not exist
      * @throws InvalidArgumentException If required data not provided
      */
-    public function pathFor($name, array $data = [], array $queryParams = [])
+    public function urlFor($name, array $data = [], array $queryParams = [])
     {
         $url = $this->relativePathFor($name, $data, $queryParams);
 
@@ -434,22 +425,25 @@ class Router implements RouterInterface
     }
 
     /**
-     * Build the path for a named route.
+     * Get fully qualified URL for named route
      *
-     * This method is deprecated. Use pathFor() from now on.
-     *
-     * @param string $name        Route name
-     * @param array  $data        Named argument replacement data
-     * @param array  $queryParams Optional query string parameters
+     * @param UriInterface $uri
+     * @param string $routeName
+     * @param array $data Named argument replacement data
+     * @param array $queryParams Optional query string parameters
      *
      * @return string
      *
      * @throws RuntimeException         If named route does not exist
      * @throws InvalidArgumentException If required data not provided
      */
-    public function urlFor($name, array $data = [], array $queryParams = [])
+    public function fullUrlFor(UriInterface $uri, $routeName, array $data = [], array $queryParams = [])
     {
-        trigger_error('urlFor() is deprecated. Use pathFor() instead.', E_USER_DEPRECATED);
-        return $this->pathFor($name, $data, $queryParams);
+        $path = $this->urlFor($routeName, $data, $queryParams);
+        $scheme = $uri->getScheme();
+        $authority = $uri->getAuthority();
+        $protocol = ($scheme ? $scheme . ':' : '') . ($authority ? '//' . $authority : '');
+
+        return $protocol . $path;
     }
 }
diff --git a/vendor/slim/slim/composer.json b/vendor/slim/slim/composer.json
index db3a11a974045159eba743ff7d1856668f6f023e..7be1584bf81a517a97aefc4f50d5101ef196ba77 100644
--- a/vendor/slim/slim/composer.json
+++ b/vendor/slim/slim/composer.json
@@ -29,10 +29,12 @@
     ],
     "require": {
         "php": ">=5.5.0",
+        "ext-json": "*",
+        "ext-libxml": "*",
+        "ext-simplexml": "*",
         "pimple/pimple": "^3.0",
         "psr/http-message": "^1.0",
         "nikic/fast-route": "^1.0",
-        "container-interop/container-interop": "^1.2",
         "psr/container": "^1.0"
     },
     "require-dev": {
@@ -48,9 +50,9 @@
         }
     },
     "autoload-dev": {
-        "files": [
-          "tests/Assets/HeaderFunctions.php"
-        ]
+        "psr-4": {
+            "Slim\\Tests\\": "tests"
+        }
     },
     "scripts": {
         "test": [
diff --git a/vendor/slim/slim/phpstan.neon.dist b/vendor/slim/slim/phpstan.neon.dist
new file mode 100644
index 0000000000000000000000000000000000000000..2fc56e798b0ff32715423873750609bc993f62f5
--- /dev/null
+++ b/vendor/slim/slim/phpstan.neon.dist
@@ -0,0 +1,2 @@
+parameters:
+    level: 1
diff --git a/vendor/symfony/polyfill-ctype/Ctype.php b/vendor/symfony/polyfill-ctype/Ctype.php
new file mode 100644
index 0000000000000000000000000000000000000000..58414dc73bd45b931b73a05a040d9ca23a61acf6
--- /dev/null
+++ b/vendor/symfony/polyfill-ctype/Ctype.php
@@ -0,0 +1,227 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Polyfill\Ctype;
+
+/**
+ * Ctype implementation through regex.
+ *
+ * @internal
+ *
+ * @author Gert de Pagter <BackEndTea@gmail.com>
+ */
+final class Ctype
+{
+    /**
+     * Returns TRUE if every character in text is either a letter or a digit, FALSE otherwise.
+     *
+     * @see https://php.net/ctype-alnum
+     *
+     * @param string|int $text
+     *
+     * @return bool
+     */
+    public static function ctype_alnum($text)
+    {
+        $text = self::convert_int_to_char_for_ctype($text);
+
+        return \is_string($text) && '' !== $text && !preg_match('/[^A-Za-z0-9]/', $text);
+    }
+
+    /**
+     * Returns TRUE if every character in text is a letter, FALSE otherwise.
+     *
+     * @see https://php.net/ctype-alpha
+     *
+     * @param string|int $text
+     *
+     * @return bool
+     */
+    public static function ctype_alpha($text)
+    {
+        $text = self::convert_int_to_char_for_ctype($text);
+
+        return \is_string($text) && '' !== $text && !preg_match('/[^A-Za-z]/', $text);
+    }
+
+    /**
+     * Returns TRUE if every character in text is a control character from the current locale, FALSE otherwise.
+     *
+     * @see https://php.net/ctype-cntrl
+     *
+     * @param string|int $text
+     *
+     * @return bool
+     */
+    public static function ctype_cntrl($text)
+    {
+        $text = self::convert_int_to_char_for_ctype($text);
+
+        return \is_string($text) && '' !== $text && !preg_match('/[^\x00-\x1f\x7f]/', $text);
+    }
+
+    /**
+     * Returns TRUE if every character in the string text is a decimal digit, FALSE otherwise.
+     *
+     * @see https://php.net/ctype-digit
+     *
+     * @param string|int $text
+     *
+     * @return bool
+     */
+    public static function ctype_digit($text)
+    {
+        $text = self::convert_int_to_char_for_ctype($text);
+
+        return \is_string($text) && '' !== $text && !preg_match('/[^0-9]/', $text);
+    }
+
+    /**
+     * Returns TRUE if every character in text is printable and actually creates visible output (no white space), FALSE otherwise.
+     *
+     * @see https://php.net/ctype-graph
+     *
+     * @param string|int $text
+     *
+     * @return bool
+     */
+    public static function ctype_graph($text)
+    {
+        $text = self::convert_int_to_char_for_ctype($text);
+
+        return \is_string($text) && '' !== $text && !preg_match('/[^!-~]/', $text);
+    }
+
+    /**
+     * Returns TRUE if every character in text is a lowercase letter.
+     *
+     * @see https://php.net/ctype-lower
+     *
+     * @param string|int $text
+     *
+     * @return bool
+     */
+    public static function ctype_lower($text)
+    {
+        $text = self::convert_int_to_char_for_ctype($text);
+
+        return \is_string($text) && '' !== $text && !preg_match('/[^a-z]/', $text);
+    }
+
+    /**
+     * Returns TRUE if every character in text will actually create output (including blanks). Returns FALSE if text contains control characters or characters that do not have any output or control function at all.
+     *
+     * @see https://php.net/ctype-print
+     *
+     * @param string|int $text
+     *
+     * @return bool
+     */
+    public static function ctype_print($text)
+    {
+        $text = self::convert_int_to_char_for_ctype($text);
+
+        return \is_string($text) && '' !== $text && !preg_match('/[^ -~]/', $text);
+    }
+
+    /**
+     * Returns TRUE if every character in text is printable, but neither letter, digit or blank, FALSE otherwise.
+     *
+     * @see https://php.net/ctype-punct
+     *
+     * @param string|int $text
+     *
+     * @return bool
+     */
+    public static function ctype_punct($text)
+    {
+        $text = self::convert_int_to_char_for_ctype($text);
+
+        return \is_string($text) && '' !== $text && !preg_match('/[^!-\/\:-@\[-`\{-~]/', $text);
+    }
+
+    /**
+     * Returns TRUE if every character in text creates some sort of white space, FALSE otherwise. Besides the blank character this also includes tab, vertical tab, line feed, carriage return and form feed characters.
+     *
+     * @see https://php.net/ctype-space
+     *
+     * @param string|int $text
+     *
+     * @return bool
+     */
+    public static function ctype_space($text)
+    {
+        $text = self::convert_int_to_char_for_ctype($text);
+
+        return \is_string($text) && '' !== $text && !preg_match('/[^\s]/', $text);
+    }
+
+    /**
+     * Returns TRUE if every character in text is an uppercase letter.
+     *
+     * @see https://php.net/ctype-upper
+     *
+     * @param string|int $text
+     *
+     * @return bool
+     */
+    public static function ctype_upper($text)
+    {
+        $text = self::convert_int_to_char_for_ctype($text);
+
+        return \is_string($text) && '' !== $text && !preg_match('/[^A-Z]/', $text);
+    }
+
+    /**
+     * Returns TRUE if every character in text is a hexadecimal 'digit', that is a decimal digit or a character from [A-Fa-f] , FALSE otherwise.
+     *
+     * @see https://php.net/ctype-xdigit
+     *
+     * @param string|int $text
+     *
+     * @return bool
+     */
+    public static function ctype_xdigit($text)
+    {
+        $text = self::convert_int_to_char_for_ctype($text);
+
+        return \is_string($text) && '' !== $text && !preg_match('/[^A-Fa-f0-9]/', $text);
+    }
+
+    /**
+     * Converts integers to their char versions according to normal ctype behaviour, if needed.
+     *
+     * If an integer between -128 and 255 inclusive is provided,
+     * it is interpreted as the ASCII value of a single character
+     * (negative values have 256 added in order to allow characters in the Extended ASCII range).
+     * Any other integer is interpreted as a string containing the decimal digits of the integer.
+     *
+     * @param string|int $int
+     *
+     * @return mixed
+     */
+    private static function convert_int_to_char_for_ctype($int)
+    {
+        if (!\is_int($int)) {
+            return $int;
+        }
+
+        if ($int < -128 || $int > 255) {
+            return (string) $int;
+        }
+
+        if ($int < 0) {
+            $int += 256;
+        }
+
+        return \chr($int);
+    }
+}
diff --git a/vendor/symfony/polyfill-ctype/LICENSE b/vendor/symfony/polyfill-ctype/LICENSE
new file mode 100644
index 0000000000000000000000000000000000000000..3f853aaf35fe186d4016761eb6e8a403de3e6e0d
--- /dev/null
+++ b/vendor/symfony/polyfill-ctype/LICENSE
@@ -0,0 +1,19 @@
+Copyright (c) 2018-2019 Fabien Potencier
+
+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/symfony/polyfill-ctype/README.md b/vendor/symfony/polyfill-ctype/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..8add1ab0096e7e7ca60829b87266d2c5a884ac26
--- /dev/null
+++ b/vendor/symfony/polyfill-ctype/README.md
@@ -0,0 +1,12 @@
+Symfony Polyfill / Ctype
+========================
+
+This component provides `ctype_*` functions to users who run php versions without the ctype extension.
+
+More information can be found in the
+[main Polyfill README](https://github.com/symfony/polyfill/blob/master/README.md).
+
+License
+=======
+
+This library is released under the [MIT license](LICENSE).
diff --git a/vendor/symfony/polyfill-ctype/bootstrap.php b/vendor/symfony/polyfill-ctype/bootstrap.php
new file mode 100644
index 0000000000000000000000000000000000000000..d54524b31b4b3873d18b9615ed661c1c239144a6
--- /dev/null
+++ b/vendor/symfony/polyfill-ctype/bootstrap.php
@@ -0,0 +1,50 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+use Symfony\Polyfill\Ctype as p;
+
+if (\PHP_VERSION_ID >= 80000) {
+    return require __DIR__.'/bootstrap80.php';
+}
+
+if (!function_exists('ctype_alnum')) {
+    function ctype_alnum($text) { return p\Ctype::ctype_alnum($text); }
+}
+if (!function_exists('ctype_alpha')) {
+    function ctype_alpha($text) { return p\Ctype::ctype_alpha($text); }
+}
+if (!function_exists('ctype_cntrl')) {
+    function ctype_cntrl($text) { return p\Ctype::ctype_cntrl($text); }
+}
+if (!function_exists('ctype_digit')) {
+    function ctype_digit($text) { return p\Ctype::ctype_digit($text); }
+}
+if (!function_exists('ctype_graph')) {
+    function ctype_graph($text) { return p\Ctype::ctype_graph($text); }
+}
+if (!function_exists('ctype_lower')) {
+    function ctype_lower($text) { return p\Ctype::ctype_lower($text); }
+}
+if (!function_exists('ctype_print')) {
+    function ctype_print($text) { return p\Ctype::ctype_print($text); }
+}
+if (!function_exists('ctype_punct')) {
+    function ctype_punct($text) { return p\Ctype::ctype_punct($text); }
+}
+if (!function_exists('ctype_space')) {
+    function ctype_space($text) { return p\Ctype::ctype_space($text); }
+}
+if (!function_exists('ctype_upper')) {
+    function ctype_upper($text) { return p\Ctype::ctype_upper($text); }
+}
+if (!function_exists('ctype_xdigit')) {
+    function ctype_xdigit($text) { return p\Ctype::ctype_xdigit($text); }
+}
diff --git a/vendor/symfony/polyfill-ctype/bootstrap80.php b/vendor/symfony/polyfill-ctype/bootstrap80.php
new file mode 100644
index 0000000000000000000000000000000000000000..ab2f8611dacaaa93e8431c7fe9b246c376a9dcab
--- /dev/null
+++ b/vendor/symfony/polyfill-ctype/bootstrap80.php
@@ -0,0 +1,46 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+use Symfony\Polyfill\Ctype as p;
+
+if (!function_exists('ctype_alnum')) {
+    function ctype_alnum(mixed $text): bool { return p\Ctype::ctype_alnum($text); }
+}
+if (!function_exists('ctype_alpha')) {
+    function ctype_alpha(mixed $text): bool { return p\Ctype::ctype_alpha($text); }
+}
+if (!function_exists('ctype_cntrl')) {
+    function ctype_cntrl(mixed $text): bool { return p\Ctype::ctype_cntrl($text); }
+}
+if (!function_exists('ctype_digit')) {
+    function ctype_digit(mixed $text): bool { return p\Ctype::ctype_digit($text); }
+}
+if (!function_exists('ctype_graph')) {
+    function ctype_graph(mixed $text): bool { return p\Ctype::ctype_graph($text); }
+}
+if (!function_exists('ctype_lower')) {
+    function ctype_lower(mixed $text): bool { return p\Ctype::ctype_lower($text); }
+}
+if (!function_exists('ctype_print')) {
+    function ctype_print(mixed $text): bool { return p\Ctype::ctype_print($text); }
+}
+if (!function_exists('ctype_punct')) {
+    function ctype_punct(mixed $text): bool { return p\Ctype::ctype_punct($text); }
+}
+if (!function_exists('ctype_space')) {
+    function ctype_space(mixed $text): bool { return p\Ctype::ctype_space($text); }
+}
+if (!function_exists('ctype_upper')) {
+    function ctype_upper(mixed $text): bool { return p\Ctype::ctype_upper($text); }
+}
+if (!function_exists('ctype_xdigit')) {
+    function ctype_xdigit(mixed $text): bool { return p\Ctype::ctype_xdigit($text); }
+}
diff --git a/vendor/symfony/polyfill-ctype/composer.json b/vendor/symfony/polyfill-ctype/composer.json
new file mode 100644
index 0000000000000000000000000000000000000000..995978c0a790fab8d80245a62d221e4002f66617
--- /dev/null
+++ b/vendor/symfony/polyfill-ctype/composer.json
@@ -0,0 +1,38 @@
+{
+    "name": "symfony/polyfill-ctype",
+    "type": "library",
+    "description": "Symfony polyfill for ctype functions",
+    "keywords": ["polyfill", "compatibility", "portable", "ctype"],
+    "homepage": "https://symfony.com",
+    "license": "MIT",
+    "authors": [
+        {
+            "name": "Gert de Pagter",
+            "email": "BackEndTea@gmail.com"
+        },
+        {
+            "name": "Symfony Community",
+            "homepage": "https://symfony.com/contributors"
+        }
+    ],
+    "require": {
+        "php": ">=7.1"
+    },
+    "autoload": {
+        "psr-4": { "Symfony\\Polyfill\\Ctype\\": "" },
+        "files": [ "bootstrap.php" ]
+    },
+    "suggest": {
+        "ext-ctype": "For best performance"
+    },
+    "minimum-stability": "dev",
+    "extra": {
+        "branch-alias": {
+            "dev-main": "1.22-dev"
+        },
+        "thanks": {
+            "name": "symfony/polyfill",
+            "url": "https://github.com/symfony/polyfill"
+        }
+    }
+}
diff --git a/vendor/symfony/polyfill-mbstring/LICENSE b/vendor/symfony/polyfill-mbstring/LICENSE
index 24fa32c2e9b27aef3eac523f0042b8ab9ba81944..4cd8bdd3007da4d62985ec9e5ca81a1e18ae34d1 100644
--- a/vendor/symfony/polyfill-mbstring/LICENSE
+++ b/vendor/symfony/polyfill-mbstring/LICENSE
@@ -1,4 +1,4 @@
-Copyright (c) 2015-2018 Fabien Potencier
+Copyright (c) 2015-2019 Fabien Potencier
 
 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal
diff --git a/vendor/symfony/polyfill-mbstring/Mbstring.php b/vendor/symfony/polyfill-mbstring/Mbstring.php
index a5e4a8fde4bdee4cd0036a1bf85490c6fdb9d789..15503bc9dd3a0ca943356e84cffcd69069ec4566 100644
--- a/vendor/symfony/polyfill-mbstring/Mbstring.php
+++ b/vendor/symfony/polyfill-mbstring/Mbstring.php
@@ -35,6 +35,7 @@ namespace Symfony\Polyfill\Mbstring;
  * - mb_strlen               - Get string length
  * - mb_strpos               - Find position of first occurrence of string in a string
  * - mb_strrpos              - Find position of last occurrence of a string in a string
+ * - mb_str_split            - Convert a string to an array
  * - mb_strtolower           - Make a string lowercase
  * - mb_strtoupper           - Make a string uppercase
  * - mb_substitute_character - Set/Get substitution character
@@ -511,7 +512,9 @@ final class Mbstring
             $offset = 0;
         } elseif ($offset = (int) $offset) {
             if ($offset < 0) {
-                $haystack = self::mb_substr($haystack, 0, $offset, $encoding);
+                if (0 > $offset += self::mb_strlen($needle)) {
+                    $haystack = self::mb_substr($haystack, 0, $offset, $encoding);
+                }
                 $offset = 0;
             } else {
                 $haystack = self::mb_substr($haystack, $offset, 2147483647, $encoding);
@@ -523,6 +526,45 @@ final class Mbstring
         return false !== $pos ? $offset + $pos : false;
     }
 
+    public static function mb_str_split($string, $split_length = 1, $encoding = null)
+    {
+        if (null !== $string && !\is_scalar($string) && !(\is_object($string) && \method_exists($string, '__toString'))) {
+            trigger_error('mb_str_split() expects parameter 1 to be string, '.\gettype($string).' given', E_USER_WARNING);
+
+            return null;
+        }
+
+        if (1 > $split_length = (int) $split_length) {
+            trigger_error('The length of each segment must be greater than zero', E_USER_WARNING);
+
+            return false;
+        }
+
+        if (null === $encoding) {
+            $encoding = mb_internal_encoding();
+        }
+
+        if ('UTF-8' === $encoding = self::getEncoding($encoding)) {
+            $rx = '/(';
+            while (65535 < $split_length) {
+                $rx .= '.{65535}';
+                $split_length -= 65535;
+            }
+            $rx .= '.{'.$split_length.'})/us';
+
+            return preg_split($rx, $string, null, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY);
+        }
+
+        $result = array();
+        $length = mb_strlen($string, $encoding);
+
+        for ($i = 0; $i < $length; $i += $split_length) {
+            $result[] = mb_substr($string, $i, $split_length, $encoding);
+        }
+
+        return $result;
+    }
+
     public static function mb_strtolower($s, $encoding = null)
     {
         return self::mb_convert_case($s, MB_CASE_LOWER, $encoding);
@@ -546,7 +588,7 @@ final class Mbstring
     {
         $encoding = self::getEncoding($encoding);
         if ('CP850' === $encoding || 'ASCII' === $encoding) {
-            return substr($s, $start, null === $length ? 2147483647 : $length);
+            return (string) substr($s, $start, null === $length ? 2147483647 : $length);
         }
 
         if ($start < 0) {
@@ -786,11 +828,16 @@ final class Mbstring
             return self::$internalEncoding;
         }
 
+        if ('UTF-8' === $encoding) {
+            return 'UTF-8';
+        }
+
         $encoding = strtoupper($encoding);
 
         if ('8BIT' === $encoding || 'BINARY' === $encoding) {
             return 'CP850';
         }
+
         if ('UTF8' === $encoding) {
             return 'UTF-8';
         }
diff --git a/vendor/symfony/polyfill-mbstring/README.md b/vendor/symfony/polyfill-mbstring/README.md
index 342e8286dbf694422c31e61b1a5bdf16f71785b4..4efb599d81fcc2374cbf42273628660f40c6c683 100644
--- a/vendor/symfony/polyfill-mbstring/README.md
+++ b/vendor/symfony/polyfill-mbstring/README.md
@@ -2,7 +2,7 @@ Symfony Polyfill / Mbstring
 ===========================
 
 This component provides a partial, native PHP implementation for the
-[Mbstring](http://php.net/mbstring) extension.
+[Mbstring](https://php.net/mbstring) extension.
 
 More information can be found in the
 [main Polyfill README](https://github.com/symfony/polyfill/blob/master/README.md).
diff --git a/vendor/symfony/polyfill-mbstring/Resources/unidata/lowerCase.php b/vendor/symfony/polyfill-mbstring/Resources/unidata/lowerCase.php
index e6fbfa64e6215a3e572d3d99f794cc6a85ea8af8..a22eca57bd99cc09a64162b32de0b143bf31be52 100644
--- a/vendor/symfony/polyfill-mbstring/Resources/unidata/lowerCase.php
+++ b/vendor/symfony/polyfill-mbstring/Resources/unidata/lowerCase.php
@@ -1,6 +1,6 @@
 <?php
 
-return array(
+return array (
   'A' => 'a',
   'B' => 'b',
   'C' => 'c',
@@ -510,6 +510,138 @@ return array(
   'Ⴥ' => 'ⴥ',
   'Ⴧ' => 'ⴧ',
   'Ⴭ' => 'ⴭ',
+  'Ꭰ' => 'ꭰ',
+  'Ꭱ' => 'ꭱ',
+  'Ꭲ' => 'ꭲ',
+  'Ꭳ' => 'ꭳ',
+  'Ꭴ' => 'ꭴ',
+  'Ꭵ' => 'ꭵ',
+  'Ꭶ' => 'ꭶ',
+  'Ꭷ' => 'ꭷ',
+  'Ꭸ' => 'ꭸ',
+  'Ꭹ' => 'ꭹ',
+  'Ꭺ' => 'ꭺ',
+  'Ꭻ' => 'ꭻ',
+  'Ꭼ' => 'ꭼ',
+  'Ꭽ' => 'ꭽ',
+  'Ꭾ' => 'ꭾ',
+  'Ꭿ' => 'ꭿ',
+  'Ꮀ' => 'ꮀ',
+  'Ꮁ' => 'ꮁ',
+  'Ꮂ' => 'ꮂ',
+  'Ꮃ' => 'ꮃ',
+  'Ꮄ' => 'ꮄ',
+  'Ꮅ' => 'ꮅ',
+  'Ꮆ' => 'ꮆ',
+  'Ꮇ' => 'ꮇ',
+  'Ꮈ' => 'ꮈ',
+  'Ꮉ' => 'ꮉ',
+  'Ꮊ' => 'ꮊ',
+  'Ꮋ' => 'ꮋ',
+  'Ꮌ' => 'ꮌ',
+  'Ꮍ' => 'ꮍ',
+  'Ꮎ' => 'ꮎ',
+  'Ꮏ' => 'ꮏ',
+  'Ꮐ' => 'ꮐ',
+  'Ꮑ' => 'ꮑ',
+  'Ꮒ' => 'ꮒ',
+  'Ꮓ' => 'ꮓ',
+  'Ꮔ' => 'ꮔ',
+  'Ꮕ' => 'ꮕ',
+  'Ꮖ' => 'ꮖ',
+  'Ꮗ' => 'ꮗ',
+  'Ꮘ' => 'ꮘ',
+  'Ꮙ' => 'ꮙ',
+  'Ꮚ' => 'ꮚ',
+  'Ꮛ' => 'ꮛ',
+  'Ꮜ' => 'ꮜ',
+  'Ꮝ' => 'ꮝ',
+  'Ꮞ' => 'ꮞ',
+  'Ꮟ' => 'ꮟ',
+  'Ꮠ' => 'ꮠ',
+  'Ꮡ' => 'ꮡ',
+  'Ꮢ' => 'ꮢ',
+  'Ꮣ' => 'ꮣ',
+  'Ꮤ' => 'ꮤ',
+  'Ꮥ' => 'ꮥ',
+  'Ꮦ' => 'ꮦ',
+  'Ꮧ' => 'ꮧ',
+  'Ꮨ' => 'ꮨ',
+  'Ꮩ' => 'ꮩ',
+  'Ꮪ' => 'ꮪ',
+  'Ꮫ' => 'ꮫ',
+  'Ꮬ' => 'ꮬ',
+  'Ꮭ' => 'ꮭ',
+  'Ꮮ' => 'ꮮ',
+  'Ꮯ' => 'ꮯ',
+  'Ꮰ' => 'ꮰ',
+  'Ꮱ' => 'ꮱ',
+  'Ꮲ' => 'ꮲ',
+  'Ꮳ' => 'ꮳ',
+  'Ꮴ' => 'ꮴ',
+  'Ꮵ' => 'ꮵ',
+  'Ꮶ' => 'ꮶ',
+  'Ꮷ' => 'ꮷ',
+  'Ꮸ' => 'ꮸ',
+  'Ꮹ' => 'ꮹ',
+  'Ꮺ' => 'ꮺ',
+  'Ꮻ' => 'ꮻ',
+  'Ꮼ' => 'ꮼ',
+  'Ꮽ' => 'ꮽ',
+  'Ꮾ' => 'ꮾ',
+  'Ꮿ' => 'ꮿ',
+  'Ᏸ' => 'ᏸ',
+  'Ᏹ' => 'ᏹ',
+  'Ᏺ' => 'ᏺ',
+  'Ᏻ' => 'ᏻ',
+  'Ᏼ' => 'ᏼ',
+  'Ᏽ' => 'ᏽ',
+  'Ა' => 'ა',
+  'Ბ' => 'ბ',
+  'Გ' => 'გ',
+  'Დ' => 'დ',
+  'Ე' => 'ე',
+  'Ვ' => 'ვ',
+  'Ზ' => 'ზ',
+  'Თ' => 'თ',
+  'Ი' => 'ი',
+  'Კ' => 'კ',
+  'Ლ' => 'ლ',
+  'Მ' => 'მ',
+  'Ნ' => 'ნ',
+  'Ო' => 'ო',
+  'Პ' => 'პ',
+  'Ჟ' => 'ჟ',
+  'Რ' => 'რ',
+  'Ს' => 'ს',
+  'Ტ' => 'ტ',
+  'Უ' => 'უ',
+  'Ფ' => 'ფ',
+  'Ქ' => 'ქ',
+  'Ღ' => 'ღ',
+  'Ყ' => 'ყ',
+  'Შ' => 'შ',
+  'Ჩ' => 'ჩ',
+  'Ც' => 'ც',
+  'Ძ' => 'ძ',
+  'Წ' => 'წ',
+  'Ჭ' => 'ჭ',
+  'Ხ' => 'ხ',
+  'Ჯ' => 'ჯ',
+  'Ჰ' => 'ჰ',
+  'Ჱ' => 'ჱ',
+  'Ჲ' => 'ჲ',
+  'Ჳ' => 'ჳ',
+  'Ჴ' => 'ჴ',
+  'Ჵ' => 'ჵ',
+  'Ჶ' => 'ჶ',
+  'Ჷ' => 'ჷ',
+  'Ჸ' => 'ჸ',
+  'Ჹ' => 'ჹ',
+  'Ჺ' => 'ჺ',
+  'Ჽ' => 'ჽ',
+  'Ჾ' => 'ჾ',
+  'Ჿ' => 'ჿ',
   'Ḁ' => 'ḁ',
   'Ḃ' => 'ḃ',
   'Ḅ' => 'ḅ',
@@ -993,8 +1125,24 @@ return array(
   'Ɜ' => 'ɜ',
   'Ɡ' => 'ɡ',
   'Ɬ' => 'ɬ',
+  'Ɪ' => 'ɪ',
   'êž°' => 'Êž',
   'Ʇ' => 'ʇ',
+  'Ʝ' => 'ʝ',
+  'êž³' => 'ê­“',
+  'êž´' => 'êžµ',
+  'Ꞷ' => 'ꞷ',
+  'Ꞹ' => 'ꞹ',
+  'Ꞻ' => 'ꞻ',
+  'êž¼' => 'êž½',
+  'êž¾' => 'êž¿',
+  'Ꟃ' => 'ꟃ',
+  'Ꞔ' => 'ꞔ',
+  'Ʂ' => 'ʂ',
+  'Ᶎ' => 'ᶎ',
+  'Ꟈ' => 'ꟈ',
+  'Ꟊ' => 'ꟊ',
+  'Ꟶ' => 'ꟶ',
   'A' => 'a',
   'B' => 'b',
   'C' => 'c',
@@ -1061,6 +1209,93 @@ return array(
   '𐐥' => '𐑍',
   '𐐦' => '𐑎',
   '𐐧' => '𐑏',
+  '𐒰' => '𐓘',
+  '𐒱' => '𐓙',
+  '𐒲' => '𐓚',
+  '𐒳' => '𐓛',
+  '𐒴' => '𐓜',
+  '𐒵' => '𐓝',
+  '𐒶' => '𐓞',
+  '𐒷' => '𐓟',
+  '𐒸' => '𐓠',
+  '𐒹' => '𐓡',
+  '𐒺' => '𐓢',
+  '𐒻' => '𐓣',
+  '𐒼' => '𐓤',
+  '𐒽' => '𐓥',
+  '𐒾' => '𐓦',
+  '𐒿' => '𐓧',
+  '𐓀' => '𐓨',
+  '𐓁' => '𐓩',
+  '𐓂' => '𐓪',
+  '𐓃' => '𐓫',
+  '𐓄' => '𐓬',
+  '𐓅' => '𐓭',
+  '𐓆' => '𐓮',
+  '𐓇' => '𐓯',
+  '𐓈' => '𐓰',
+  '𐓉' => '𐓱',
+  '𐓊' => '𐓲',
+  '𐓋' => '𐓳',
+  '𐓌' => '𐓴',
+  '𐓍' => '𐓵',
+  '𐓎' => '𐓶',
+  '𐓏' => '𐓷',
+  '𐓐' => '𐓸',
+  '𐓑' => '𐓹',
+  '𐓒' => '𐓺',
+  '𐓓' => '𐓻',
+  '𐲀' => '𐳀',
+  '𐲁' => '𐳁',
+  '𐲂' => '𐳂',
+  '𐲃' => '𐳃',
+  '𐲄' => '𐳄',
+  '𐲅' => '𐳅',
+  '𐲆' => '𐳆',
+  '𐲇' => '𐳇',
+  '𐲈' => '𐳈',
+  '𐲉' => '𐳉',
+  '𐲊' => '𐳊',
+  '𐲋' => '𐳋',
+  '𐲌' => '𐳌',
+  '𐲍' => '𐳍',
+  '𐲎' => '𐳎',
+  '𐲏' => '𐳏',
+  '𐲐' => '𐳐',
+  '𐲑' => '𐳑',
+  '𐲒' => '𐳒',
+  '𐲓' => '𐳓',
+  '𐲔' => '𐳔',
+  '𐲕' => '𐳕',
+  '𐲖' => '𐳖',
+  '𐲗' => '𐳗',
+  '𐲘' => '𐳘',
+  '𐲙' => '𐳙',
+  '𐲚' => '𐳚',
+  '𐲛' => '𐳛',
+  '𐲜' => '𐳜',
+  '𐲝' => '𐳝',
+  '𐲞' => '𐳞',
+  '𐲟' => '𐳟',
+  '𐲠' => '𐳠',
+  '𐲡' => '𐳡',
+  '𐲢' => '𐳢',
+  '𐲣' => '𐳣',
+  '𐲤' => '𐳤',
+  '𐲥' => '𐳥',
+  '𐲦' => '𐳦',
+  '𐲧' => '𐳧',
+  '𐲨' => '𐳨',
+  '𐲩' => '𐳩',
+  '𐲪' => '𐳪',
+  '𐲫' => '𐳫',
+  '𐲬' => '𐳬',
+  '𐲭' => '𐳭',
+  '𐲮' => '𐳮',
+  '𐲯' => '𐳯',
+  '𐲰' => '𐳰',
+  '𐲱' => '𐳱',
+  '𐲲' => '𐳲',
   'ð‘¢ ' => 'ð‘£€',
   '𑢡' => '𑣁',
   '𑢢' => '𑣂',
@@ -1093,4 +1328,70 @@ return array(
   '𑢽' => '𑣝',
   '𑢾' => '𑣞',
   '𑢿' => '𑣟',
+  'ð–¹€' => 'ð–¹ ',
+  '𖹁' => '𖹡',
+  '𖹂' => '𖹢',
+  '𖹃' => '𖹣',
+  '𖹄' => '𖹤',
+  'ð–¹…' => 'ð–¹¥',
+  '𖹆' => '𖹦',
+  '𖹇' => '𖹧',
+  '𖹈' => '𖹨',
+  '𖹉' => '𖹩',
+  '𖹊' => '𖹪',
+  '𖹋' => '𖹫',
+  '𖹌' => '𖹬',
+  '𖹍' => '𖹭',
+  '𖹎' => '𖹮',
+  '𖹏' => '𖹯',
+  '𖹐' => '𖹰',
+  '𖹑' => '𖹱',
+  'ð–¹’' => 'ð–¹²',
+  '𖹓' => '𖹳',
+  'ð–¹”' => 'ð–¹´',
+  '𖹕' => '𖹵',
+  '𖹖' => '𖹶',
+  'ð–¹—' => 'ð–¹·',
+  '𖹘' => '𖹸',
+  'ð–¹™' => 'ð–¹¹',
+  '𖹚' => '𖹺',
+  'ð–¹›' => 'ð–¹»',
+  '𖹜' => '𖹼',
+  '𖹝' => '𖹽',
+  '𖹞' => '𖹾',
+  '𖹟' => '𖹿',
+  '𞤀' => '𞤢',
+  '𞤁' => '𞤣',
+  '𞤂' => '𞤤',
+  '𞤃' => '𞤥',
+  '𞤄' => '𞤦',
+  '𞤅' => '𞤧',
+  '𞤆' => '𞤨',
+  '𞤇' => '𞤩',
+  '𞤈' => '𞤪',
+  '𞤉' => '𞤫',
+  '𞤊' => '𞤬',
+  '𞤋' => '𞤭',
+  '𞤌' => '𞤮',
+  '𞤍' => '𞤯',
+  '𞤎' => '𞤰',
+  '𞤏' => '𞤱',
+  '𞤐' => '𞤲',
+  '𞤑' => '𞤳',
+  '𞤒' => '𞤴',
+  '𞤓' => '𞤵',
+  '𞤔' => '𞤶',
+  '𞤕' => '𞤷',
+  '𞤖' => '𞤸',
+  '𞤗' => '𞤹',
+  '𞤘' => '𞤺',
+  '𞤙' => '𞤻',
+  '𞤚' => '𞤼',
+  '𞤛' => '𞤽',
+  '𞤜' => '𞤾',
+  '𞤝' => '𞤿',
+  '𞤞' => '𞥀',
+  '𞤟' => '𞥁',
+  '𞤠' => '𞥂',
+  '𞤡' => '𞥃',
 );
diff --git a/vendor/symfony/polyfill-mbstring/Resources/unidata/upperCase.php b/vendor/symfony/polyfill-mbstring/Resources/unidata/upperCase.php
index b8103b2e808dd0a670c04868f20edcc969ea7e70..ecbc15895eb71c7b92bb18bce90d955848b509a9 100644
--- a/vendor/symfony/polyfill-mbstring/Resources/unidata/upperCase.php
+++ b/vendor/symfony/polyfill-mbstring/Resources/unidata/upperCase.php
@@ -1,6 +1,6 @@
 <?php
 
-return array(
+return array (
   'a' => 'A',
   'b' => 'B',
   'c' => 'C',
@@ -225,6 +225,7 @@ return array(
   'ɦ' => 'Ɦ',
   'ɨ' => 'Ɨ',
   'É©' => 'Æ–',
+  'ɪ' => 'Ɪ',
   'É«' => 'â±¢',
   'ɬ' => 'Ɬ',
   'ɯ' => 'Ɯ',
@@ -233,6 +234,7 @@ return array(
   'ɵ' => 'Ɵ',
   'ɽ' => 'Ɽ',
   'ʀ' => 'Ʀ',
+  'ʂ' => 'Ʂ',
   'ʃ' => 'Ʃ',
   'ʇ' => 'Ʇ',
   'ʈ' => 'Ʈ',
@@ -241,6 +243,7 @@ return array(
   'ʋ' => 'Ʋ',
   'ʌ' => 'Ʌ',
   'Ê’' => 'Æ·',
+  'ʝ' => 'Ʝ',
   'Êž' => 'êž°',
   'ͅ' => 'Ι',
   'ͱ' => 'Ͱ',
@@ -493,8 +496,70 @@ return array(
   'Ö„' => 'Õ”',
   'Ö…' => 'Õ•',
   'Ö†' => 'Õ–',
+  'ა' => 'Ა',
+  'ბ' => 'Ბ',
+  'გ' => 'Გ',
+  'დ' => 'Დ',
+  'ე' => 'Ე',
+  'ვ' => 'Ვ',
+  'ზ' => 'Ზ',
+  'თ' => 'Თ',
+  'ი' => 'Ი',
+  'კ' => 'Კ',
+  'ლ' => 'Ლ',
+  'მ' => 'Მ',
+  'ნ' => 'Ნ',
+  'ო' => 'Ო',
+  'პ' => 'Პ',
+  'ჟ' => 'Ჟ',
+  'რ' => 'Რ',
+  'ს' => 'Ს',
+  'ტ' => 'Ტ',
+  'უ' => 'Უ',
+  'ფ' => 'Ფ',
+  'ქ' => 'Ქ',
+  'ღ' => 'Ღ',
+  'ყ' => 'Ყ',
+  'შ' => 'Შ',
+  'ჩ' => 'Ჩ',
+  'ც' => 'Ც',
+  'ძ' => 'Ძ',
+  'წ' => 'Წ',
+  'ჭ' => 'Ჭ',
+  'ხ' => 'Ხ',
+  'ჯ' => 'Ჯ',
+  'ჰ' => 'Ჰ',
+  'ჱ' => 'Ჱ',
+  'ჲ' => 'Ჲ',
+  'ჳ' => 'Ჳ',
+  'ჴ' => 'Ჴ',
+  'ჵ' => 'Ჵ',
+  'ჶ' => 'Ჶ',
+  'ჷ' => 'Ჷ',
+  'ჸ' => 'Ჸ',
+  'ჹ' => 'Ჹ',
+  'ჺ' => 'Ჺ',
+  'ჽ' => 'Ჽ',
+  'ჾ' => 'Ჾ',
+  'ჿ' => 'Ჿ',
+  'ᏸ' => 'Ᏸ',
+  'ᏹ' => 'Ᏹ',
+  'ᏺ' => 'Ᏺ',
+  'ᏻ' => 'Ᏻ',
+  'ᏼ' => 'Ᏼ',
+  'ᏽ' => 'Ᏽ',
+  'á²€' => 'Ð’',
+  'ᲁ' => 'Д',
+  'ᲂ' => 'О',
+  'ᲃ' => 'С',
+  'ᲄ' => 'Т',
+  'ᲅ' => 'Т',
+  'ᲆ' => 'Ъ',
+  'ᲇ' => 'Ѣ',
+  'ᲈ' => 'Ꙋ',
   'ᵹ' => 'Ᵹ',
   'áµ½' => 'â±£',
+  'ᶎ' => 'Ᶎ',
   'ḁ' => 'Ḁ',
   'ḃ' => 'Ḃ',
   'ḅ' => 'Ḅ',
@@ -993,6 +1058,7 @@ return array(
   'ꞌ' => 'Ꞌ',
   'ꞑ' => 'Ꞑ',
   'êž“' => 'êž’',
+  'ꞔ' => 'Ꞔ',
   'êž—' => 'êž–',
   'ꞙ' => 'Ꞙ',
   'êž›' => 'êžš',
@@ -1003,6 +1069,97 @@ return array(
   'ꞥ' => 'Ꞥ',
   'ꞧ' => 'Ꞧ',
   'ꞩ' => 'Ꞩ',
+  'êžµ' => 'êž´',
+  'ꞷ' => 'Ꞷ',
+  'ꞹ' => 'Ꞹ',
+  'ꞻ' => 'Ꞻ',
+  'êž½' => 'êž¼',
+  'êž¿' => 'êž¾',
+  'ꟃ' => 'Ꟃ',
+  'ꟈ' => 'Ꟈ',
+  'ꟊ' => 'Ꟊ',
+  'ꟶ' => 'Ꟶ',
+  'ê­“' => 'êž³',
+  'ꭰ' => 'Ꭰ',
+  'ꭱ' => 'Ꭱ',
+  'ꭲ' => 'Ꭲ',
+  'ꭳ' => 'Ꭳ',
+  'ꭴ' => 'Ꭴ',
+  'ꭵ' => 'Ꭵ',
+  'ꭶ' => 'Ꭶ',
+  'ꭷ' => 'Ꭷ',
+  'ꭸ' => 'Ꭸ',
+  'ꭹ' => 'Ꭹ',
+  'ꭺ' => 'Ꭺ',
+  'ꭻ' => 'Ꭻ',
+  'ꭼ' => 'Ꭼ',
+  'ꭽ' => 'Ꭽ',
+  'ꭾ' => 'Ꭾ',
+  'ꭿ' => 'Ꭿ',
+  'ꮀ' => 'Ꮀ',
+  'ꮁ' => 'Ꮁ',
+  'ꮂ' => 'Ꮂ',
+  'ꮃ' => 'Ꮃ',
+  'ꮄ' => 'Ꮄ',
+  'ꮅ' => 'Ꮅ',
+  'ꮆ' => 'Ꮆ',
+  'ꮇ' => 'Ꮇ',
+  'ꮈ' => 'Ꮈ',
+  'ꮉ' => 'Ꮉ',
+  'ꮊ' => 'Ꮊ',
+  'ꮋ' => 'Ꮋ',
+  'ꮌ' => 'Ꮌ',
+  'ꮍ' => 'Ꮍ',
+  'ꮎ' => 'Ꮎ',
+  'ꮏ' => 'Ꮏ',
+  'ꮐ' => 'Ꮐ',
+  'ꮑ' => 'Ꮑ',
+  'ꮒ' => 'Ꮒ',
+  'ꮓ' => 'Ꮓ',
+  'ꮔ' => 'Ꮔ',
+  'ꮕ' => 'Ꮕ',
+  'ꮖ' => 'Ꮖ',
+  'ꮗ' => 'Ꮗ',
+  'ꮘ' => 'Ꮘ',
+  'ꮙ' => 'Ꮙ',
+  'ꮚ' => 'Ꮚ',
+  'ꮛ' => 'Ꮛ',
+  'ꮜ' => 'Ꮜ',
+  'ꮝ' => 'Ꮝ',
+  'ꮞ' => 'Ꮞ',
+  'ꮟ' => 'Ꮟ',
+  'ꮠ' => 'Ꮠ',
+  'ꮡ' => 'Ꮡ',
+  'ꮢ' => 'Ꮢ',
+  'ꮣ' => 'Ꮣ',
+  'ꮤ' => 'Ꮤ',
+  'ꮥ' => 'Ꮥ',
+  'ꮦ' => 'Ꮦ',
+  'ꮧ' => 'Ꮧ',
+  'ꮨ' => 'Ꮨ',
+  'ꮩ' => 'Ꮩ',
+  'ꮪ' => 'Ꮪ',
+  'ꮫ' => 'Ꮫ',
+  'ꮬ' => 'Ꮬ',
+  'ꮭ' => 'Ꮭ',
+  'ꮮ' => 'Ꮮ',
+  'ꮯ' => 'Ꮯ',
+  'ꮰ' => 'Ꮰ',
+  'ꮱ' => 'Ꮱ',
+  'ꮲ' => 'Ꮲ',
+  'ꮳ' => 'Ꮳ',
+  'ꮴ' => 'Ꮴ',
+  'ꮵ' => 'Ꮵ',
+  'ꮶ' => 'Ꮶ',
+  'ꮷ' => 'Ꮷ',
+  'ꮸ' => 'Ꮸ',
+  'ꮹ' => 'Ꮹ',
+  'ꮺ' => 'Ꮺ',
+  'ꮻ' => 'Ꮻ',
+  'ꮼ' => 'Ꮼ',
+  'ꮽ' => 'Ꮽ',
+  'ꮾ' => 'Ꮾ',
+  'ꮿ' => 'Ꮿ',
   'a' => 'A',
   'b' => 'B',
   'c' => 'C',
@@ -1069,6 +1226,93 @@ return array(
   '𐑍' => '𐐥',
   '𐑎' => '𐐦',
   '𐑏' => '𐐧',
+  '𐓘' => '𐒰',
+  '𐓙' => '𐒱',
+  '𐓚' => '𐒲',
+  '𐓛' => '𐒳',
+  '𐓜' => '𐒴',
+  '𐓝' => '𐒵',
+  '𐓞' => '𐒶',
+  '𐓟' => '𐒷',
+  '𐓠' => '𐒸',
+  '𐓡' => '𐒹',
+  '𐓢' => '𐒺',
+  '𐓣' => '𐒻',
+  '𐓤' => '𐒼',
+  '𐓥' => '𐒽',
+  '𐓦' => '𐒾',
+  '𐓧' => '𐒿',
+  '𐓨' => '𐓀',
+  '𐓩' => '𐓁',
+  '𐓪' => '𐓂',
+  '𐓫' => '𐓃',
+  '𐓬' => '𐓄',
+  '𐓭' => '𐓅',
+  '𐓮' => '𐓆',
+  '𐓯' => '𐓇',
+  '𐓰' => '𐓈',
+  '𐓱' => '𐓉',
+  '𐓲' => '𐓊',
+  '𐓳' => '𐓋',
+  '𐓴' => '𐓌',
+  '𐓵' => '𐓍',
+  '𐓶' => '𐓎',
+  '𐓷' => '𐓏',
+  '𐓸' => '𐓐',
+  '𐓹' => '𐓑',
+  '𐓺' => '𐓒',
+  '𐓻' => '𐓓',
+  '𐳀' => '𐲀',
+  '𐳁' => '𐲁',
+  '𐳂' => '𐲂',
+  '𐳃' => '𐲃',
+  '𐳄' => '𐲄',
+  '𐳅' => '𐲅',
+  '𐳆' => '𐲆',
+  '𐳇' => '𐲇',
+  '𐳈' => '𐲈',
+  '𐳉' => '𐲉',
+  '𐳊' => '𐲊',
+  '𐳋' => '𐲋',
+  '𐳌' => '𐲌',
+  '𐳍' => '𐲍',
+  '𐳎' => '𐲎',
+  '𐳏' => '𐲏',
+  '𐳐' => '𐲐',
+  '𐳑' => '𐲑',
+  '𐳒' => '𐲒',
+  '𐳓' => '𐲓',
+  '𐳔' => '𐲔',
+  '𐳕' => '𐲕',
+  '𐳖' => '𐲖',
+  '𐳗' => '𐲗',
+  '𐳘' => '𐲘',
+  '𐳙' => '𐲙',
+  '𐳚' => '𐲚',
+  '𐳛' => '𐲛',
+  '𐳜' => '𐲜',
+  '𐳝' => '𐲝',
+  '𐳞' => '𐲞',
+  '𐳟' => '𐲟',
+  '𐳠' => '𐲠',
+  '𐳡' => '𐲡',
+  '𐳢' => '𐲢',
+  '𐳣' => '𐲣',
+  '𐳤' => '𐲤',
+  '𐳥' => '𐲥',
+  '𐳦' => '𐲦',
+  '𐳧' => '𐲧',
+  '𐳨' => '𐲨',
+  '𐳩' => '𐲩',
+  '𐳪' => '𐲪',
+  '𐳫' => '𐲫',
+  '𐳬' => '𐲬',
+  '𐳭' => '𐲭',
+  '𐳮' => '𐲮',
+  '𐳯' => '𐲯',
+  '𐳰' => '𐲰',
+  '𐳱' => '𐲱',
+  '𐳲' => '𐲲',
   'ð‘£€' => 'ð‘¢ ',
   '𑣁' => '𑢡',
   '𑣂' => '𑢢',
@@ -1101,4 +1345,70 @@ return array(
   '𑣝' => '𑢽',
   '𑣞' => '𑢾',
   '𑣟' => '𑢿',
+  'ð–¹ ' => 'ð–¹€',
+  '𖹡' => '𖹁',
+  '𖹢' => '𖹂',
+  '𖹣' => '𖹃',
+  '𖹤' => '𖹄',
+  'ð–¹¥' => 'ð–¹…',
+  '𖹦' => '𖹆',
+  '𖹧' => '𖹇',
+  '𖹨' => '𖹈',
+  '𖹩' => '𖹉',
+  '𖹪' => '𖹊',
+  '𖹫' => '𖹋',
+  '𖹬' => '𖹌',
+  '𖹭' => '𖹍',
+  '𖹮' => '𖹎',
+  '𖹯' => '𖹏',
+  '𖹰' => '𖹐',
+  '𖹱' => '𖹑',
+  'ð–¹²' => 'ð–¹’',
+  '𖹳' => '𖹓',
+  'ð–¹´' => 'ð–¹”',
+  '𖹵' => '𖹕',
+  '𖹶' => '𖹖',
+  'ð–¹·' => 'ð–¹—',
+  '𖹸' => '𖹘',
+  'ð–¹¹' => 'ð–¹™',
+  '𖹺' => '𖹚',
+  'ð–¹»' => 'ð–¹›',
+  '𖹼' => '𖹜',
+  '𖹽' => '𖹝',
+  '𖹾' => '𖹞',
+  '𖹿' => '𖹟',
+  '𞤢' => '𞤀',
+  '𞤣' => '𞤁',
+  '𞤤' => '𞤂',
+  '𞤥' => '𞤃',
+  '𞤦' => '𞤄',
+  '𞤧' => '𞤅',
+  '𞤨' => '𞤆',
+  '𞤩' => '𞤇',
+  '𞤪' => '𞤈',
+  '𞤫' => '𞤉',
+  '𞤬' => '𞤊',
+  '𞤭' => '𞤋',
+  '𞤮' => '𞤌',
+  '𞤯' => '𞤍',
+  '𞤰' => '𞤎',
+  '𞤱' => '𞤏',
+  '𞤲' => '𞤐',
+  '𞤳' => '𞤑',
+  '𞤴' => '𞤒',
+  '𞤵' => '𞤓',
+  '𞤶' => '𞤔',
+  '𞤷' => '𞤕',
+  '𞤸' => '𞤖',
+  '𞤹' => '𞤗',
+  '𞤺' => '𞤘',
+  '𞤻' => '𞤙',
+  '𞤼' => '𞤚',
+  '𞤽' => '𞤛',
+  '𞤾' => '𞤜',
+  '𞤿' => '𞤝',
+  '𞥀' => '𞤞',
+  '𞥁' => '𞤟',
+  '𞥂' => '𞤠',
+  '𞥃' => '𞤡',
 );
diff --git a/vendor/symfony/polyfill-mbstring/bootstrap.php b/vendor/symfony/polyfill-mbstring/bootstrap.php
index 2fdcc5a6f69ceb58f3e948cac4d99bb20edb4fbf..b36a0926f2038e0e51a3646e87f10d4590b53f3a 100644
--- a/vendor/symfony/polyfill-mbstring/bootstrap.php
+++ b/vendor/symfony/polyfill-mbstring/bootstrap.php
@@ -11,48 +11,131 @@
 
 use Symfony\Polyfill\Mbstring as p;
 
-if (!function_exists('mb_strlen')) {
-    define('MB_CASE_UPPER', 0);
-    define('MB_CASE_LOWER', 1);
-    define('MB_CASE_TITLE', 2);
-
+if (!function_exists('mb_convert_encoding')) {
     function mb_convert_encoding($s, $to, $from = null) { return p\Mbstring::mb_convert_encoding($s, $to, $from); }
+}
+if (!function_exists('mb_decode_mimeheader')) {
     function mb_decode_mimeheader($s) { return p\Mbstring::mb_decode_mimeheader($s); }
+}
+if (!function_exists('mb_encode_mimeheader')) {
     function mb_encode_mimeheader($s, $charset = null, $transferEnc = null, $lf = null, $indent = null) { return p\Mbstring::mb_encode_mimeheader($s, $charset, $transferEnc, $lf, $indent); }
+}
+if (!function_exists('mb_decode_numericentity')) {
     function mb_decode_numericentity($s, $convmap, $enc = null) { return p\Mbstring::mb_decode_numericentity($s, $convmap, $enc); }
+}
+if (!function_exists('mb_encode_numericentity')) {
     function mb_encode_numericentity($s, $convmap, $enc = null, $is_hex = false) { return p\Mbstring::mb_encode_numericentity($s, $convmap, $enc, $is_hex); }
+}
+if (!function_exists('mb_convert_case')) {
     function mb_convert_case($s, $mode, $enc = null) { return p\Mbstring::mb_convert_case($s, $mode, $enc); }
+}
+if (!function_exists('mb_internal_encoding')) {
     function mb_internal_encoding($enc = null) { return p\Mbstring::mb_internal_encoding($enc); }
+}
+if (!function_exists('mb_language')) {
     function mb_language($lang = null) { return p\Mbstring::mb_language($lang); }
+}
+if (!function_exists('mb_list_encodings')) {
     function mb_list_encodings() { return p\Mbstring::mb_list_encodings(); }
+}
+if (!function_exists('mb_encoding_aliases')) {
     function mb_encoding_aliases($encoding) { return p\Mbstring::mb_encoding_aliases($encoding); }
+}
+if (!function_exists('mb_check_encoding')) {
     function mb_check_encoding($var = null, $encoding = null) { return p\Mbstring::mb_check_encoding($var, $encoding); }
+}
+if (!function_exists('mb_detect_encoding')) {
     function mb_detect_encoding($str, $encodingList = null, $strict = false) { return p\Mbstring::mb_detect_encoding($str, $encodingList, $strict); }
+}
+if (!function_exists('mb_detect_order')) {
     function mb_detect_order($encodingList = null) { return p\Mbstring::mb_detect_order($encodingList); }
+}
+if (!function_exists('mb_parse_str')) {
     function mb_parse_str($s, &$result = array()) { parse_str($s, $result); }
+}
+if (!function_exists('mb_strlen')) {
     function mb_strlen($s, $enc = null) { return p\Mbstring::mb_strlen($s, $enc); }
+}
+if (!function_exists('mb_strpos')) {
     function mb_strpos($s, $needle, $offset = 0, $enc = null) { return p\Mbstring::mb_strpos($s, $needle, $offset, $enc); }
+}
+if (!function_exists('mb_strtolower')) {
     function mb_strtolower($s, $enc = null) { return p\Mbstring::mb_strtolower($s, $enc); }
+}
+if (!function_exists('mb_strtoupper')) {
     function mb_strtoupper($s, $enc = null) { return p\Mbstring::mb_strtoupper($s, $enc); }
+}
+if (!function_exists('mb_substitute_character')) {
     function mb_substitute_character($char = null) { return p\Mbstring::mb_substitute_character($char); }
+}
+if (!function_exists('mb_substr')) {
     function mb_substr($s, $start, $length = 2147483647, $enc = null) { return p\Mbstring::mb_substr($s, $start, $length, $enc); }
+}
+if (!function_exists('mb_stripos')) {
     function mb_stripos($s, $needle, $offset = 0, $enc = null) { return p\Mbstring::mb_stripos($s, $needle, $offset, $enc); }
+}
+if (!function_exists('mb_stristr')) {
     function mb_stristr($s, $needle, $part = false, $enc = null) { return p\Mbstring::mb_stristr($s, $needle, $part, $enc); }
+}
+if (!function_exists('mb_strrchr')) {
     function mb_strrchr($s, $needle, $part = false, $enc = null) { return p\Mbstring::mb_strrchr($s, $needle, $part, $enc); }
+}
+if (!function_exists('mb_strrichr')) {
     function mb_strrichr($s, $needle, $part = false, $enc = null) { return p\Mbstring::mb_strrichr($s, $needle, $part, $enc); }
+}
+if (!function_exists('mb_strripos')) {
     function mb_strripos($s, $needle, $offset = 0, $enc = null) { return p\Mbstring::mb_strripos($s, $needle, $offset, $enc); }
+}
+if (!function_exists('mb_strrpos')) {
     function mb_strrpos($s, $needle, $offset = 0, $enc = null) { return p\Mbstring::mb_strrpos($s, $needle, $offset, $enc); }
+}
+if (!function_exists('mb_strstr')) {
     function mb_strstr($s, $needle, $part = false, $enc = null) { return p\Mbstring::mb_strstr($s, $needle, $part, $enc); }
+}
+if (!function_exists('mb_get_info')) {
     function mb_get_info($type = 'all') { return p\Mbstring::mb_get_info($type); }
+}
+if (!function_exists('mb_http_output')) {
     function mb_http_output($enc = null) { return p\Mbstring::mb_http_output($enc); }
+}
+if (!function_exists('mb_strwidth')) {
     function mb_strwidth($s, $enc = null) { return p\Mbstring::mb_strwidth($s, $enc); }
+}
+if (!function_exists('mb_substr_count')) {
     function mb_substr_count($haystack, $needle, $enc = null) { return p\Mbstring::mb_substr_count($haystack, $needle, $enc); }
+}
+if (!function_exists('mb_output_handler')) {
     function mb_output_handler($contents, $status) { return p\Mbstring::mb_output_handler($contents, $status); }
+}
+if (!function_exists('mb_http_input')) {
     function mb_http_input($type = '') { return p\Mbstring::mb_http_input($type); }
+}
+if (!function_exists('mb_convert_variables')) {
     function mb_convert_variables($toEncoding, $fromEncoding, &$a = null, &$b = null, &$c = null, &$d = null, &$e = null, &$f = null) { return p\Mbstring::mb_convert_variables($toEncoding, $fromEncoding, $a, $b, $c, $d, $e, $f); }
 }
-if (!function_exists('mb_chr')) {
+if (!function_exists('mb_ord')) {
     function mb_ord($s, $enc = null) { return p\Mbstring::mb_ord($s, $enc); }
+}
+if (!function_exists('mb_chr')) {
     function mb_chr($code, $enc = null) { return p\Mbstring::mb_chr($code, $enc); }
+}
+if (!function_exists('mb_scrub')) {
     function mb_scrub($s, $enc = null) { $enc = null === $enc ? mb_internal_encoding() : $enc; return mb_convert_encoding($s, $enc, $enc); }
 }
+if (!function_exists('mb_str_split')) {
+    function mb_str_split($string, $split_length = 1, $encoding = null) { return p\Mbstring::mb_str_split($string, $split_length, $encoding); }
+}
+
+if (extension_loaded('mbstring')) {
+    return;
+}
+
+if (!defined('MB_CASE_UPPER')) {
+    define('MB_CASE_UPPER', 0);
+}
+if (!defined('MB_CASE_LOWER')) {
+    define('MB_CASE_LOWER', 1);
+}
+if (!defined('MB_CASE_TITLE')) {
+    define('MB_CASE_TITLE', 2);
+}
diff --git a/vendor/symfony/polyfill-mbstring/composer.json b/vendor/symfony/polyfill-mbstring/composer.json
index 50ea12f1bbb09226c9ee9abc9c3c33d8655af2b2..06e6b31a20f6b3e8b56ed76ba51142042ac69c7e 100644
--- a/vendor/symfony/polyfill-mbstring/composer.json
+++ b/vendor/symfony/polyfill-mbstring/composer.json
@@ -28,7 +28,11 @@
     "minimum-stability": "dev",
     "extra": {
         "branch-alias": {
-            "dev-master": "1.9-dev"
+            "dev-master": "1.18-dev"
+        },
+        "thanks": {
+            "name": "symfony/polyfill",
+            "url": "https://github.com/symfony/polyfill"
         }
     }
 }
diff --git a/vendor/symfony/polyfill-php56/LICENSE b/vendor/symfony/polyfill-php56/LICENSE
new file mode 100644
index 0000000000000000000000000000000000000000..4cd8bdd3007da4d62985ec9e5ca81a1e18ae34d1
--- /dev/null
+++ b/vendor/symfony/polyfill-php56/LICENSE
@@ -0,0 +1,19 @@
+Copyright (c) 2015-2019 Fabien Potencier
+
+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/symfony/polyfill-php56/Php56.php b/vendor/symfony/polyfill-php56/Php56.php
new file mode 100644
index 0000000000000000000000000000000000000000..dbbc0e13ad317fc1d4dcee91741f2a1c82dea532
--- /dev/null
+++ b/vendor/symfony/polyfill-php56/Php56.php
@@ -0,0 +1,138 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Polyfill\Php56;
+
+use Symfony\Polyfill\Util\Binary;
+
+/**
+ * @internal
+ */
+final class Php56
+{
+    const LDAP_ESCAPE_FILTER = 1;
+    const LDAP_ESCAPE_DN = 2;
+
+    public static function hash_equals($knownString, $userInput)
+    {
+        if (!\is_string($knownString)) {
+            trigger_error('Expected known_string to be a string, '.\gettype($knownString).' given', E_USER_WARNING);
+
+            return false;
+        }
+
+        if (!\is_string($userInput)) {
+            trigger_error('Expected user_input to be a string, '.\gettype($userInput).' given', E_USER_WARNING);
+
+            return false;
+        }
+
+        $knownLen = Binary::strlen($knownString);
+        $userLen = Binary::strlen($userInput);
+
+        if ($knownLen !== $userLen) {
+            return false;
+        }
+
+        $result = 0;
+
+        for ($i = 0; $i < $knownLen; ++$i) {
+            $result |= \ord($knownString[$i]) ^ \ord($userInput[$i]);
+        }
+
+        return 0 === $result;
+    }
+
+    /**
+     * Stub implementation of the {@link ldap_escape()} function of the ldap
+     * extension.
+     *
+     * Escape strings for safe use in LDAP filters and DNs.
+     *
+     * @author Chris Wright <ldapi@daverandom.com>
+     *
+     * @param string $subject
+     * @param string $ignore
+     * @param int    $flags
+     *
+     * @return string
+     *
+     * @see http://stackoverflow.com/a/8561604
+     */
+    public static function ldap_escape($subject, $ignore = '', $flags = 0)
+    {
+        static $charMaps = null;
+
+        if (null === $charMaps) {
+            $charMaps = array(
+                self::LDAP_ESCAPE_FILTER => array('\\', '*', '(', ')', "\x00"),
+                self::LDAP_ESCAPE_DN => array('\\', ',', '=', '+', '<', '>', ';', '"', '#', "\r"),
+            );
+
+            $charMaps[0] = array();
+
+            for ($i = 0; $i < 256; ++$i) {
+                $charMaps[0][\chr($i)] = sprintf('\\%02x', $i);
+            }
+
+            for ($i = 0, $l = \count($charMaps[self::LDAP_ESCAPE_FILTER]); $i < $l; ++$i) {
+                $chr = $charMaps[self::LDAP_ESCAPE_FILTER][$i];
+                unset($charMaps[self::LDAP_ESCAPE_FILTER][$i]);
+                $charMaps[self::LDAP_ESCAPE_FILTER][$chr] = $charMaps[0][$chr];
+            }
+
+            for ($i = 0, $l = \count($charMaps[self::LDAP_ESCAPE_DN]); $i < $l; ++$i) {
+                $chr = $charMaps[self::LDAP_ESCAPE_DN][$i];
+                unset($charMaps[self::LDAP_ESCAPE_DN][$i]);
+                $charMaps[self::LDAP_ESCAPE_DN][$chr] = $charMaps[0][$chr];
+            }
+        }
+
+        // Create the base char map to escape
+        $flags = (int) $flags;
+        $charMap = array();
+
+        if ($flags & self::LDAP_ESCAPE_FILTER) {
+            $charMap += $charMaps[self::LDAP_ESCAPE_FILTER];
+        }
+
+        if ($flags & self::LDAP_ESCAPE_DN) {
+            $charMap += $charMaps[self::LDAP_ESCAPE_DN];
+        }
+
+        if (!$charMap) {
+            $charMap = $charMaps[0];
+        }
+
+        // Remove any chars to ignore from the list
+        $ignore = (string) $ignore;
+
+        for ($i = 0, $l = \strlen($ignore); $i < $l; ++$i) {
+            unset($charMap[$ignore[$i]]);
+        }
+
+        // Do the main replacement
+        $result = strtr($subject, $charMap);
+
+        // Encode leading/trailing spaces if self::LDAP_ESCAPE_DN is passed
+        if ($flags & self::LDAP_ESCAPE_DN) {
+            if (' ' === $result[0]) {
+                $result = '\\20'.substr($result, 1);
+            }
+
+            if (' ' === $result[\strlen($result) - 1]) {
+                $result = substr($result, 0, -1).'\\20';
+            }
+        }
+
+        return $result;
+    }
+}
diff --git a/vendor/symfony/polyfill-php56/README.md b/vendor/symfony/polyfill-php56/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..5ad570be3225193f2a455790325f6f269f66007c
--- /dev/null
+++ b/vendor/symfony/polyfill-php56/README.md
@@ -0,0 +1,15 @@
+Symfony Polyfill / Php56
+========================
+
+This component provides functions unavailable in releases prior to PHP 5.6:
+
+- [`hash_equals`](https://php.net/hash_equals)  (part of [hash](https://php.net/hash) extension)
+- [`ldap_escape`](https://php.net/ldap_escape) (part of [ldap](https://php.net/ldap) extension)
+
+More information can be found in the
+[main Polyfill README](https://github.com/symfony/polyfill/blob/master/README.md).
+
+License
+=======
+
+This library is released under the [MIT license](LICENSE).
diff --git a/vendor/symfony/polyfill-php56/bootstrap.php b/vendor/symfony/polyfill-php56/bootstrap.php
new file mode 100644
index 0000000000000000000000000000000000000000..427dd2e4c8e34c197760c1109408daf3fd0d53ef
--- /dev/null
+++ b/vendor/symfony/polyfill-php56/bootstrap.php
@@ -0,0 +1,44 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+use Symfony\Polyfill\Php56 as p;
+
+if (PHP_VERSION_ID >= 50600) {
+    return;
+}
+
+if (!function_exists('hash_equals')) {
+    function hash_equals($knownString, $userInput) { return p\Php56::hash_equals($knownString, $userInput); }
+}
+if (extension_loaded('ldap') && !defined('LDAP_ESCAPE_FILTER')) {
+    define('LDAP_ESCAPE_FILTER', 1);
+}
+if (extension_loaded('ldap') && !defined('LDAP_ESCAPE_DN')) {
+    define('LDAP_ESCAPE_DN', 2);
+}
+
+if (extension_loaded('ldap') && !function_exists('ldap_escape')) {
+    function ldap_escape($subject, $ignore = '', $flags = 0) { return p\Php56::ldap_escape($subject, $ignore, $flags); }
+}
+
+if (50509 === PHP_VERSION_ID && 4 === PHP_INT_SIZE) {
+    // Missing functions in PHP 5.5.9 - affects 32 bit builds of Ubuntu 14.04LTS
+    // See https://bugs.launchpad.net/ubuntu/+source/php5/+bug/1315888
+    if (!function_exists('gzopen') && function_exists('gzopen64')) {
+        function gzopen($filename, $mode, $use_include_path = 0) { return gzopen64($filename, $mode, $use_include_path); }
+    }
+    if (!function_exists('gzseek') && function_exists('gzseek64')) {
+        function gzseek($zp, $offset, $whence = SEEK_SET) { return gzseek64($zp, $offset, $whence); }
+    }
+    if (!function_exists('gztell') && function_exists('gztell64')) {
+        function gztell($zp) { return gztell64($zp); }
+    }
+}
diff --git a/vendor/symfony/polyfill-php56/composer.json b/vendor/symfony/polyfill-php56/composer.json
new file mode 100644
index 0000000000000000000000000000000000000000..a60e5675ea8e20b45fc0fdb687af9814e07e7a78
--- /dev/null
+++ b/vendor/symfony/polyfill-php56/composer.json
@@ -0,0 +1,36 @@
+{
+    "name": "symfony/polyfill-php56",
+    "type": "library",
+    "description": "Symfony polyfill backporting some PHP 5.6+ features to lower PHP versions",
+    "keywords": ["polyfill", "shim", "compatibility", "portable"],
+    "homepage": "https://symfony.com",
+    "license": "MIT",
+    "authors": [
+        {
+            "name": "Nicolas Grekas",
+            "email": "p@tchwork.com"
+        },
+        {
+            "name": "Symfony Community",
+            "homepage": "https://symfony.com/contributors"
+        }
+    ],
+    "require": {
+        "php": ">=5.3.3",
+        "symfony/polyfill-util": "~1.0"
+    },
+    "autoload": {
+        "psr-4": { "Symfony\\Polyfill\\Php56\\": "" },
+        "files": [ "bootstrap.php" ]
+    },
+    "minimum-stability": "dev",
+    "extra": {
+        "branch-alias": {
+            "dev-master": "1.18-dev"
+        },
+        "thanks": {
+            "name": "symfony/polyfill",
+            "url": "https://github.com/symfony/polyfill"
+        }
+    }
+}
diff --git a/vendor/symfony/polyfill-util/Binary.php b/vendor/symfony/polyfill-util/Binary.php
new file mode 100644
index 0000000000000000000000000000000000000000..23ff974734f2e34095f461986e617daccba0fcb7
--- /dev/null
+++ b/vendor/symfony/polyfill-util/Binary.php
@@ -0,0 +1,22 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Polyfill\Util;
+
+if (\extension_loaded('mbstring')) {
+    class Binary extends BinaryOnFuncOverload
+    {
+    }
+} else {
+    class Binary extends BinaryNoFuncOverload
+    {
+    }
+}
diff --git a/vendor/symfony/polyfill-util/BinaryNoFuncOverload.php b/vendor/symfony/polyfill-util/BinaryNoFuncOverload.php
new file mode 100644
index 0000000000000000000000000000000000000000..800ad75d059822db49429b7b307b111e249a9685
--- /dev/null
+++ b/vendor/symfony/polyfill-util/BinaryNoFuncOverload.php
@@ -0,0 +1,65 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Polyfill\Util;
+
+/**
+ * @author Nicolas Grekas <p@tchwork.com>
+ *
+ * @internal
+ */
+class BinaryNoFuncOverload
+{
+    public static function strlen($s)
+    {
+        return \strlen($s);
+    }
+
+    public static function strpos($haystack, $needle, $offset = 0)
+    {
+        return strpos($haystack, $needle, $offset);
+    }
+
+    public static function strrpos($haystack, $needle, $offset = 0)
+    {
+        return strrpos($haystack, $needle, $offset);
+    }
+
+    public static function substr($string, $start, $length = PHP_INT_MAX)
+    {
+        return substr($string, $start, $length);
+    }
+
+    public static function stripos($s, $needle, $offset = 0)
+    {
+        return stripos($s, $needle, $offset);
+    }
+
+    public static function stristr($s, $needle, $part = false)
+    {
+        return stristr($s, $needle, $part);
+    }
+
+    public static function strrchr($s, $needle, $part = false)
+    {
+        return strrchr($s, $needle, $part);
+    }
+
+    public static function strripos($s, $needle, $offset = 0)
+    {
+        return strripos($s, $needle, $offset);
+    }
+
+    public static function strstr($s, $needle, $part = false)
+    {
+        return strstr($s, $needle, $part);
+    }
+}
diff --git a/vendor/symfony/polyfill-util/BinaryOnFuncOverload.php b/vendor/symfony/polyfill-util/BinaryOnFuncOverload.php
new file mode 100644
index 0000000000000000000000000000000000000000..e1b886eaca34879d62fc1291ba954bbc17216d49
--- /dev/null
+++ b/vendor/symfony/polyfill-util/BinaryOnFuncOverload.php
@@ -0,0 +1,67 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Polyfill\Util;
+
+/**
+ * Binary safe version of string functions overloaded when MB_OVERLOAD_STRING is enabled.
+ *
+ * @author Nicolas Grekas <p@tchwork.com>
+ *
+ * @internal
+ */
+class BinaryOnFuncOverload
+{
+    public static function strlen($s)
+    {
+        return mb_strlen($s, '8bit');
+    }
+
+    public static function strpos($haystack, $needle, $offset = 0)
+    {
+        return mb_strpos($haystack, $needle, $offset, '8bit');
+    }
+
+    public static function strrpos($haystack, $needle, $offset = 0)
+    {
+        return mb_strrpos($haystack, $needle, $offset, '8bit');
+    }
+
+    public static function substr($string, $start, $length = 2147483647)
+    {
+        return mb_substr($string, $start, $length, '8bit');
+    }
+
+    public static function stripos($s, $needle, $offset = 0)
+    {
+        return mb_stripos($s, $needle, $offset, '8bit');
+    }
+
+    public static function stristr($s, $needle, $part = false)
+    {
+        return mb_stristr($s, $needle, $part, '8bit');
+    }
+
+    public static function strrchr($s, $needle, $part = false)
+    {
+        return mb_strrchr($s, $needle, $part, '8bit');
+    }
+
+    public static function strripos($s, $needle, $offset = 0)
+    {
+        return mb_strripos($s, $needle, $offset, '8bit');
+    }
+
+    public static function strstr($s, $needle, $part = false)
+    {
+        return mb_strstr($s, $needle, $part, '8bit');
+    }
+}
diff --git a/vendor/symfony/polyfill-util/LICENSE b/vendor/symfony/polyfill-util/LICENSE
new file mode 100644
index 0000000000000000000000000000000000000000..4cd8bdd3007da4d62985ec9e5ca81a1e18ae34d1
--- /dev/null
+++ b/vendor/symfony/polyfill-util/LICENSE
@@ -0,0 +1,19 @@
+Copyright (c) 2015-2019 Fabien Potencier
+
+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/symfony/polyfill-util/README.md b/vendor/symfony/polyfill-util/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..1c655fce376c8a5532c763b44c85120817d7bba2
--- /dev/null
+++ b/vendor/symfony/polyfill-util/README.md
@@ -0,0 +1,13 @@
+Symfony Polyfill / Util
+=======================
+
+This component provides binary-safe string functions, using the
+[mbstring](https://php.net/mbstring) extension when available.
+
+More information can be found in the
+[main Polyfill README](https://github.com/symfony/polyfill/blob/master/README.md).
+
+License
+=======
+
+This library is released under the [MIT license](LICENSE).
diff --git a/vendor/symfony/polyfill-util/TestListener.php b/vendor/symfony/polyfill-util/TestListener.php
new file mode 100644
index 0000000000000000000000000000000000000000..6b17d45ccaadae99eb9527510591e7d3ec947510
--- /dev/null
+++ b/vendor/symfony/polyfill-util/TestListener.php
@@ -0,0 +1,28 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Polyfill\Util;
+
+if (class_exists('PHPUnit_Runner_Version') && version_compare(\PHPUnit_Runner_Version::id(), '6.0.0', '<')) {
+    class_alias('Symfony\Polyfill\Util\TestListenerForV5', 'Symfony\Polyfill\Util\TestListener');
+// Using an early return instead of a else does not work when using the PHPUnit phar due to some weird PHP behavior (the class
+// gets defined without executing the code before it and so the definition is not properly conditional)
+} elseif (version_compare(\PHPUnit\Runner\Version::id(), '7.0.0', '<')) {
+    class_alias('Symfony\Polyfill\Util\TestListenerForV6', 'Symfony\Polyfill\Util\TestListener');
+} else {
+    class_alias('Symfony\Polyfill\Util\TestListenerForV7', 'Symfony\Polyfill\Util\TestListener');
+}
+
+if (false) {
+    class TestListener
+    {
+    }
+}
diff --git a/vendor/symfony/polyfill-util/TestListenerForV5.php b/vendor/symfony/polyfill-util/TestListenerForV5.php
new file mode 100644
index 0000000000000000000000000000000000000000..501053dddfe7201f35aa13936e0a900fe6cf3215
--- /dev/null
+++ b/vendor/symfony/polyfill-util/TestListenerForV5.php
@@ -0,0 +1,89 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Polyfill\Util;
+
+/**
+ * @author Nicolas Grekas <p@tchwork.com>
+ */
+class TestListenerForV5 extends \PHPUnit_Framework_TestSuite implements \PHPUnit_Framework_TestListener
+{
+    private $suite;
+    private $trait;
+
+    public function __construct(\PHPUnit_Framework_TestSuite $suite = null)
+    {
+        if ($suite) {
+            $this->suite = $suite;
+            $this->setName($suite->getName().' with polyfills enabled');
+            $this->addTest($suite);
+        }
+        $this->trait = new TestListenerTrait();
+    }
+
+    public function startTestSuite(\PHPUnit_Framework_TestSuite $suite)
+    {
+        $this->trait->startTestSuite($suite);
+    }
+
+    public function addError(\PHPUnit_Framework_Test $test, \Exception $e, $time)
+    {
+        $this->trait->addError($test, $e, $time);
+    }
+
+    public function addWarning(\PHPUnit_Framework_Test $test, \PHPUnit_Framework_Warning $e, $time)
+    {
+    }
+
+    public function addFailure(\PHPUnit_Framework_Test $test, \PHPUnit_Framework_AssertionFailedError $e, $time)
+    {
+        $this->trait->addError($test, $e, $time);
+    }
+
+    public function addIncompleteTest(\PHPUnit_Framework_Test $test, \Exception $e, $time)
+    {
+    }
+
+    public function addRiskyTest(\PHPUnit_Framework_Test $test, \Exception $e, $time)
+    {
+    }
+
+    public function addSkippedTest(\PHPUnit_Framework_Test $test, \Exception $e, $time)
+    {
+    }
+
+    public function endTestSuite(\PHPUnit_Framework_TestSuite $suite)
+    {
+    }
+
+    public function startTest(\PHPUnit_Framework_Test $test)
+    {
+    }
+
+    public function endTest(\PHPUnit_Framework_Test $test, $time)
+    {
+    }
+
+    public static function warning($message)
+    {
+        return parent::warning($message);
+    }
+
+    protected function setUp()
+    {
+        TestListenerTrait::$enabledPolyfills = $this->suite->getName();
+    }
+
+    protected function tearDown()
+    {
+        TestListenerTrait::$enabledPolyfills = false;
+    }
+}
diff --git a/vendor/symfony/polyfill-util/TestListenerForV6.php b/vendor/symfony/polyfill-util/TestListenerForV6.php
new file mode 100644
index 0000000000000000000000000000000000000000..e9e87cbef758611ddf0f672934aeb9690efe2da1
--- /dev/null
+++ b/vendor/symfony/polyfill-util/TestListenerForV6.php
@@ -0,0 +1,95 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Polyfill\Util;
+
+use PHPUnit\Framework\AssertionFailedError;
+use PHPUnit\Framework\Test;
+use PHPUnit\Framework\TestListener as TestListenerInterface;
+use PHPUnit\Framework\TestSuite;
+use PHPUnit\Framework\Warning;
+
+/**
+ * @author Nicolas Grekas <p@tchwork.com>
+ */
+class TestListenerForV6 extends TestSuite implements TestListenerInterface
+{
+    private $suite;
+    private $trait;
+
+    public function __construct(TestSuite $suite = null)
+    {
+        if ($suite) {
+            $this->suite = $suite;
+            $this->setName($suite->getName().' with polyfills enabled');
+            $this->addTest($suite);
+        }
+        $this->trait = new TestListenerTrait();
+    }
+
+    public function startTestSuite(TestSuite $suite)
+    {
+        $this->trait->startTestSuite($suite);
+    }
+
+    public function addError(Test $test, \Exception $e, $time)
+    {
+        $this->trait->addError($test, $e, $time);
+    }
+
+    public function addWarning(Test $test, Warning $e, $time)
+    {
+    }
+
+    public function addFailure(Test $test, AssertionFailedError $e, $time)
+    {
+        $this->trait->addError($test, $e, $time);
+    }
+
+    public function addIncompleteTest(Test $test, \Exception $e, $time)
+    {
+    }
+
+    public function addRiskyTest(Test $test, \Exception $e, $time)
+    {
+    }
+
+    public function addSkippedTest(Test $test, \Exception $e, $time)
+    {
+    }
+
+    public function endTestSuite(TestSuite $suite)
+    {
+    }
+
+    public function startTest(Test $test)
+    {
+    }
+
+    public function endTest(Test $test, $time)
+    {
+    }
+
+    public static function warning($message)
+    {
+        return parent::warning($message);
+    }
+
+    protected function setUp()
+    {
+        TestListenerTrait::$enabledPolyfills = $this->suite->getName();
+    }
+
+    protected function tearDown()
+    {
+        TestListenerTrait::$enabledPolyfills = false;
+    }
+}
diff --git a/vendor/symfony/polyfill-util/TestListenerForV7.php b/vendor/symfony/polyfill-util/TestListenerForV7.php
new file mode 100644
index 0000000000000000000000000000000000000000..a5c3759b22e2b048c3eeb6b59267bcafe6a29ce1
--- /dev/null
+++ b/vendor/symfony/polyfill-util/TestListenerForV7.php
@@ -0,0 +1,96 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Polyfill\Util;
+
+use PHPUnit\Framework\AssertionFailedError;
+use PHPUnit\Framework\Test;
+use PHPUnit\Framework\TestListener as TestListenerInterface;
+use PHPUnit\Framework\TestSuite;
+use PHPUnit\Framework\Warning;
+use PHPUnit\Framework\WarningTestCase;
+
+/**
+ * @author Ion Bazan <ion.bazan@gmail.com>
+ */
+class TestListenerForV7 extends TestSuite implements TestListenerInterface
+{
+    private $suite;
+    private $trait;
+
+    public function __construct(TestSuite $suite = null)
+    {
+        if ($suite) {
+            $this->suite = $suite;
+            $this->setName($suite->getName().' with polyfills enabled');
+            $this->addTest($suite);
+        }
+        $this->trait = new TestListenerTrait();
+    }
+
+    public function startTestSuite(TestSuite $suite): void
+    {
+        $this->trait->startTestSuite($suite);
+    }
+
+    public function addError(Test $test, \Throwable $t, float $time): void
+    {
+        $this->trait->addError($test, $t, $time);
+    }
+
+    public function addWarning(Test $test, Warning $e, float $time): void
+    {
+    }
+
+    public function addFailure(Test $test, AssertionFailedError $e, float $time): void
+    {
+        $this->trait->addError($test, $e, $time);
+    }
+
+    public function addIncompleteTest(Test $test, \Throwable $t, float $time): void
+    {
+    }
+
+    public function addRiskyTest(Test $test, \Throwable $t, float $time): void
+    {
+    }
+
+    public function addSkippedTest(Test $test, \Throwable $t, float $time): void
+    {
+    }
+
+    public function endTestSuite(TestSuite $suite): void
+    {
+    }
+
+    public function startTest(Test $test): void
+    {
+    }
+
+    public function endTest(Test $test, float $time): void
+    {
+    }
+
+    public static function warning($message): WarningTestCase
+    {
+        return new WarningTestCase($message);
+    }
+
+    protected function setUp(): void
+    {
+        TestListenerTrait::$enabledPolyfills = $this->suite->getName();
+    }
+
+    protected function tearDown(): void
+    {
+        TestListenerTrait::$enabledPolyfills = false;
+    }
+}
diff --git a/vendor/symfony/polyfill-util/TestListenerTrait.php b/vendor/symfony/polyfill-util/TestListenerTrait.php
new file mode 100644
index 0000000000000000000000000000000000000000..777fb48439d4dd6ad6d4d6df7cb6fca7cafa40ea
--- /dev/null
+++ b/vendor/symfony/polyfill-util/TestListenerTrait.php
@@ -0,0 +1,129 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Polyfill\Util;
+
+/**
+ * @author Nicolas Grekas <p@tchwork.com>
+ */
+class TestListenerTrait
+{
+    public static $enabledPolyfills;
+
+    public function startTestSuite($mainSuite)
+    {
+        if (null !== self::$enabledPolyfills) {
+            return;
+        }
+        self::$enabledPolyfills = false;
+        $SkippedTestError = class_exists('PHPUnit\Framework\SkippedTestError') ? 'PHPUnit\Framework\SkippedTestError' : 'PHPUnit_Framework_SkippedTestError';
+
+        foreach ($mainSuite->tests() as $suite) {
+            $testClass = $suite->getName();
+            if (!$tests = $suite->tests()) {
+                continue;
+            }
+            $testedClass = new \ReflectionClass($testClass);
+            if (preg_match('{^ \* @requires PHP (.*)}mi', $testedClass->getDocComment(), $m) && version_compare($m[1], \PHP_VERSION, '>')) {
+                continue;
+            }
+            if (!preg_match('/^(.+)\\\\Tests(\\\\.*)Test$/', $testClass, $m)) {
+                $mainSuite->addTest(TestListener::warning('Unknown naming convention for '.$testClass));
+                continue;
+            }
+            if (!class_exists($m[1].$m[2])) {
+                continue;
+            }
+            $testedClass = new \ReflectionClass($m[1].$m[2]);
+            $bootstrap = new \SplFileObject(\dirname($testedClass->getFileName()).'/bootstrap.php');
+            $warnings = array();
+            $defLine = null;
+
+            foreach (new \RegexIterator($bootstrap, '/define\(\'/') as $defLine) {
+                preg_match('/define\(\'(?P<name>.+)\'/', $defLine, $matches);
+                if (\defined($matches['name'])) {
+                    continue;
+                }
+
+                try {
+                    eval($defLine);
+                } catch (\PHPUnit_Framework_Exception $ex){
+                    $warnings[] = TestListener::warning($ex->getMessage());
+                } catch (\PHPUnit\Framework\Exception $ex) {
+                    $warnings[] = TestListener::warning($ex->getMessage());
+                }
+            }
+
+            $bootstrap->rewind();
+
+            foreach (new \RegexIterator($bootstrap, '/return p\\\\'.$testedClass->getShortName().'::/') as $defLine) {
+                if (!preg_match('/^\s*function (?P<name>[^\(]++)(?P<signature>\(.*\)(?: ?: [^ ]++)?) \{ (?<return>return p\\\\'.$testedClass->getShortName().'::[^\(]++)(?P<args>\([^\)]*+\)); \}$/', $defLine, $f)) {
+                    $warnings[] = TestListener::warning('Invalid line in bootstrap.php: '.trim($defLine));
+                    continue;
+                }
+                $testNamespace = substr($testClass, 0, strrpos($testClass, '\\'));
+                if (\function_exists($testNamespace.'\\'.$f['name'])) {
+                    continue;
+                }
+
+                try {
+                    $r = new \ReflectionFunction($f['name']);
+                    if ($r->isUserDefined()) {
+                        throw new \ReflectionException();
+                    }
+                    if ('idn_to_ascii' === $f['name'] || 'idn_to_utf8' === $f['name']) {
+                        $defLine = sprintf('return INTL_IDNA_VARIANT_2003 === $variant ? \\%s($domain, $options, $variant) : \\%1$s%s', $f['name'], $f['args']);
+                    } elseif (false !== strpos($f['signature'], '&') && 'idn_to_ascii' !== $f['name'] && 'idn_to_utf8' !== $f['name']) {
+                        $defLine = sprintf('return \\%s%s', $f['name'], $f['args']);
+                    } else {
+                        $defLine = sprintf("return \\call_user_func_array('%s', \\func_get_args())", $f['name']);
+                    }
+                } catch (\ReflectionException $e) {
+                    $defLine = sprintf("throw new \\{$SkippedTestError}('Internal function not found: %s')", $f['name']);
+                }
+
+                eval(<<<EOPHP
+namespace {$testNamespace};
+
+use Symfony\Polyfill\Util\TestListenerTrait;
+use {$testedClass->getNamespaceName()} as p;
+
+function {$f['name']}{$f['signature']}
+{
+    if ('{$testClass}' === TestListenerTrait::\$enabledPolyfills) {
+        {$f['return']}{$f['args']};
+    }
+
+    {$defLine};
+}
+EOPHP
+                );
+            }
+            if (!$warnings && null === $defLine) {
+                $warnings[] = new $SkippedTestError('No Polyfills found in bootstrap.php for '.$testClass);
+            } else {
+                $mainSuite->addTest(new TestListener($suite));
+            }
+        }
+        foreach ($warnings as $w) {
+            $mainSuite->addTest($w);
+        }
+    }
+
+    public function addError($test, \Exception $e, $time)
+    {
+        if (false !== self::$enabledPolyfills) {
+            $r = new \ReflectionProperty('Exception', 'message');
+            $r->setAccessible(true);
+            $r->setValue($e, 'Polyfills enabled, '.$r->getValue($e));
+        }
+    }
+}
diff --git a/vendor/symfony/polyfill-util/composer.json b/vendor/symfony/polyfill-util/composer.json
new file mode 100644
index 0000000000000000000000000000000000000000..3343c669cc8cf448395b9d044847a0a0f83c2734
--- /dev/null
+++ b/vendor/symfony/polyfill-util/composer.json
@@ -0,0 +1,34 @@
+{
+    "name": "symfony/polyfill-util",
+    "type": "library",
+    "description": "Symfony utilities for portability of PHP codes",
+    "keywords": ["polyfill", "shim", "compat", "compatibility"],
+    "homepage": "https://symfony.com",
+    "license": "MIT",
+    "authors": [
+        {
+            "name": "Nicolas Grekas",
+            "email": "p@tchwork.com"
+        },
+        {
+            "name": "Symfony Community",
+            "homepage": "https://symfony.com/contributors"
+        }
+    ],
+    "require": {
+        "php": ">=5.3.3"
+    },
+    "autoload": {
+        "psr-4": { "Symfony\\Polyfill\\Util\\": "" }
+    },
+    "minimum-stability": "dev",
+    "extra": {
+        "branch-alias": {
+            "dev-master": "1.18-dev"
+        },
+        "thanks": {
+            "name": "symfony/polyfill",
+            "url": "https://github.com/symfony/polyfill"
+        }
+    }
+}
diff --git a/vendor/theseer/tokenizer/.php_cs.dist b/vendor/theseer/tokenizer/.php_cs.dist
new file mode 100644
index 0000000000000000000000000000000000000000..8ac26d0966c6e1411d9490d07e8da7b5bdb8bc5d
--- /dev/null
+++ b/vendor/theseer/tokenizer/.php_cs.dist
@@ -0,0 +1,213 @@
+<?php
+
+require __DIR__ . '/tools/php-cs-fixer.d/PhpdocSingleLineVarFixer.php';
+
+return PhpCsFixer\Config::create()
+    ->registerCustomFixers([
+        new \PharIo\CSFixer\PhpdocSingleLineVarFixer()
+    ])
+    ->setRiskyAllowed(true)
+    ->setRules(
+        [
+            'PharIo/phpdoc_single_line_var_fixer'           => true,
+
+            'align_multiline_comment'                       => true,
+            'array_indentation'                             => true,
+            'array_syntax'                                  => ['syntax' => 'short'],
+            'binary_operator_spaces'                        => [
+                'operators' => [
+                    '='  => 'align_single_space_minimal',
+                    '=>' => 'align',
+                ],
+            ],
+            'blank_line_after_namespace'                    => true,
+            'blank_line_after_opening_tag'                  => false,
+            'blank_line_before_statement'                   => [
+                'statements' => [
+                    'break',
+                    'continue',
+                    'declare',
+                    'do',
+                    'for',
+                    'foreach',
+                    'if',
+                    'include',
+                    'include_once',
+                    'require',
+                    'require_once',
+                    'return',
+                    'switch',
+                    'throw',
+                    'try',
+                    'while',
+                    'yield',
+                ],
+            ],
+            'braces'                                        => [
+                'allow_single_line_closure'                   => false,
+                'position_after_anonymous_constructs'         => 'same',
+                'position_after_control_structures'           => 'same',
+                'position_after_functions_and_oop_constructs' => 'same'
+            ],
+            'cast_spaces'                                   => ['space' => 'none'],
+
+            // This fixer removes the blank line at class start, no way to disable that, so we disable the fixer :(
+            //'class_attributes_separation'                   => ['elements' => ['const', 'method', 'property']],
+
+            'combine_consecutive_issets'                    => true,
+            'combine_consecutive_unsets'                    => true,
+            'compact_nullable_typehint'                     => true,
+            'concat_space'                                  => ['spacing' => 'one'],
+            'date_time_immutable'                           => true,
+            'declare_equal_normalize'                       => ['space' => 'single'],
+            'declare_strict_types'                          => true,
+            'dir_constant'                                  => true,
+            'elseif'                                        => true,
+            'encoding'                                      => true,
+            'full_opening_tag'                              => true,
+            'fully_qualified_strict_types'                  => true,
+            'function_declaration'                          => [
+                'closure_function_spacing' => 'one'
+            ],
+            'header_comment'                                => false,
+            'indentation_type'                              => true,
+            'is_null'                                       => true,
+            'line_ending'                                   => true,
+            'list_syntax'                                   => ['syntax' => 'short'],
+            'logical_operators'                             => true,
+            'lowercase_cast'                                => true,
+            'lowercase_constants'                           => true,
+            'lowercase_keywords'                            => true,
+            'lowercase_static_reference'                    => true,
+            'magic_constant_casing'                         => true,
+            'method_argument_space'                         => ['ensure_fully_multiline' => true],
+            'modernize_types_casting'                       => true,
+            'multiline_comment_opening_closing'             => true,
+            'multiline_whitespace_before_semicolons'        => true,
+            'native_constant_invocation'                    => true,
+            'native_function_casing'                        => true,
+            'native_function_invocation'                    => true,
+            'new_with_braces'                               => false,
+            'no_alias_functions'                            => true,
+            'no_alternative_syntax'                         => true,
+            'no_blank_lines_after_class_opening'            => false,
+            'no_blank_lines_after_phpdoc'                   => true,
+            'no_blank_lines_before_namespace'               => true,
+            'no_closing_tag'                                => true,
+            'no_empty_comment'                              => true,
+            'no_empty_phpdoc'                               => true,
+            'no_empty_statement'                            => true,
+            'no_extra_blank_lines'                          => true,
+            'no_homoglyph_names'                            => true,
+            'no_leading_import_slash'                       => true,
+            'no_leading_namespace_whitespace'               => true,
+            'no_mixed_echo_print'                           => ['use' => 'print'],
+            'no_multiline_whitespace_around_double_arrow'   => true,
+            'no_null_property_initialization'               => true,
+            'no_php4_constructor'                           => true,
+            'no_short_bool_cast'                            => true,
+            'no_short_echo_tag'                             => true,
+            'no_singleline_whitespace_before_semicolons'    => true,
+            'no_spaces_after_function_name'                 => true,
+            'no_spaces_inside_parenthesis'                  => true,
+            'no_superfluous_elseif'                         => true,
+            'no_superfluous_phpdoc_tags'                    => true,
+            'no_trailing_comma_in_list_call'                => true,
+            'no_trailing_comma_in_singleline_array'         => true,
+            'no_trailing_whitespace'                        => true,
+            'no_trailing_whitespace_in_comment'             => true,
+            'no_unneeded_control_parentheses'               => false,
+            'no_unneeded_curly_braces'                      => false,
+            'no_unneeded_final_method'                      => true,
+            'no_unreachable_default_argument_value'         => true,
+            'no_unset_on_property'                          => true,
+            'no_unused_imports'                             => true,
+            'no_useless_else'                               => true,
+            'no_useless_return'                             => true,
+            'no_whitespace_before_comma_in_array'           => true,
+            'no_whitespace_in_blank_line'                   => true,
+            'non_printable_character'                       => true,
+            'normalize_index_brace'                         => true,
+            'object_operator_without_whitespace'            => true,
+            'ordered_class_elements'                        => [
+                'order' => [
+                    'use_trait',
+                    'constant_public',
+                    'constant_protected',
+                    'constant_private',
+                    'property_public_static',
+                    'property_protected_static',
+                    'property_private_static',
+                    'property_public',
+                    'property_protected',
+                    'property_private',
+                    'method_public_static',
+                    'construct',
+                    'destruct',
+                    'magic',
+                    'phpunit',
+                    'method_public',
+                    'method_protected',
+                    'method_private',
+                    'method_protected_static',
+                    'method_private_static',
+                ],
+            ],
+            'ordered_imports'                               => true,
+            'phpdoc_add_missing_param_annotation'           => true,
+            'phpdoc_align'                                  => true,
+            'phpdoc_annotation_without_dot'                 => true,
+            'phpdoc_indent'                                 => true,
+            'phpdoc_no_access'                              => true,
+            'phpdoc_no_empty_return'                        => true,
+            'phpdoc_no_package'                             => true,
+            'phpdoc_order'                                  => true,
+            'phpdoc_return_self_reference'                  => true,
+            'phpdoc_scalar'                                 => true,
+            'phpdoc_separation'                             => true,
+            'phpdoc_single_line_var_spacing'                => true,
+            'phpdoc_to_comment'                             => false,
+            'phpdoc_trim'                                   => true,
+            'phpdoc_trim_consecutive_blank_line_separation' => true,
+            'phpdoc_types'                                  => ['groups' => ['simple', 'meta']],
+            'phpdoc_types_order'                            => true,
+            'phpdoc_to_return_type'                         => true,
+            'phpdoc_var_without_name'                       => true,
+            'pow_to_exponentiation'                         => true,
+            'protected_to_private'                          => true,
+            'return_assignment'                             => true,
+            'return_type_declaration'                       => ['space_before' => 'none'],
+            'self_accessor'                                 => false,
+            'semicolon_after_instruction'                   => true,
+            'set_type_to_cast'                              => true,
+            'short_scalar_cast'                             => true,
+            'simplified_null_return'                        => true,
+            'single_blank_line_at_eof'                      => true,
+            'single_import_per_statement'                   => true,
+            'single_line_after_imports'                     => true,
+            'single_quote'                                  => true,
+            'standardize_not_equals'                        => true,
+            'ternary_to_null_coalescing'                    => true,
+            'trailing_comma_in_multiline_array'             => false,
+            'trim_array_spaces'                             => true,
+            'unary_operator_spaces'                         => true,
+            'visibility_required'                           => [
+                'elements' => [
+                    'const',
+                    'method',
+                    'property',
+                ],
+            ],
+            'void_return'                                   => true,
+            'whitespace_after_comma_in_array'               => true,
+            'yoda_style'                                    => false
+        ]
+    )
+    ->setFinder(
+        PhpCsFixer\Finder::create()
+            ->files()
+            ->in(__DIR__ . '/src')
+            ->in(__DIR__ . '/tests')
+            ->notName('*.phpt')
+            ->notName('autoload.php')
+    );
diff --git a/vendor/theseer/tokenizer/CHANGELOG.md b/vendor/theseer/tokenizer/CHANGELOG.md
new file mode 100644
index 0000000000000000000000000000000000000000..314934f127c93756b7d45db858e80bbedd9f71ca
--- /dev/null
+++ b/vendor/theseer/tokenizer/CHANGELOG.md
@@ -0,0 +1,63 @@
+# Changelog
+
+All notable changes to Tokenizer are documented in this file using the [Keep a CHANGELOG](http://keepachangelog.com/) principles.
+
+## [1.2.0] - 2020-07-13
+
+This release is now PHP 8.0 compliant.
+
+### Fixed
+
+* Whitespace handling in general (only noticable in the intermediate `TokenCollection`) is now consitent  
+
+### Changed
+
+* Updated `Tokenizer` to deal with changed whitespace handling in PHP 8.0
+  The XMLSerializer was unaffected.
+
+
+## [1.1.3] - 2019-06-14
+
+### Changed
+
+* Ensure XMLSerializer can deal with empty token collections
+
+### Fixed
+
+* [#2](https://github.com/theseer/tokenizer/issues/2): Fatal error in infection / phpunit
+
+
+## [1.1.2] - 2019-04-04
+
+### Changed
+
+* Reverted PHPUnit 8 test update to stay PHP 7.0 compliant
+
+
+## [1.1.1] - 2019-04-03
+
+### Fixed
+
+* [#1](https://github.com/theseer/tokenizer/issues/1): Empty file causes invalid array read 
+
+### Changed
+
+* Tests should now be PHPUnit 8 compliant
+
+
+## [1.1.0] - 2017-04-07
+
+### Added
+
+* Allow use of custom namespace for XML serialization
+
+
+## [1.0.0] - 2017-04-05
+
+Initial Release
+
+[1.1.3]: https://github.com/theseer/tokenizer/compare/1.1.2...1.1.3
+[1.1.2]: https://github.com/theseer/tokenizer/compare/1.1.1...1.1.2
+[1.1.1]: https://github.com/theseer/tokenizer/compare/1.1.0...1.1.1
+[1.1.0]: https://github.com/theseer/tokenizer/compare/1.0.0...1.1.0
+[1.0.0]: https://github.com/theseer/tokenizer/compare/b2493e57de80c1b7414219b28503fa5c6b4d0a98...1.0.0
diff --git a/vendor/theseer/tokenizer/LICENSE b/vendor/theseer/tokenizer/LICENSE
new file mode 100644
index 0000000000000000000000000000000000000000..e9694ad6114db2b558f715c65e19d5a7c11658f0
--- /dev/null
+++ b/vendor/theseer/tokenizer/LICENSE
@@ -0,0 +1,30 @@
+Tokenizer
+
+Copyright (c) 2017 Arne Blankerts <arne@blankerts.de> and contributors
+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 Arne Blankerts nor the names of 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 HOLDER 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/theseer/tokenizer/README.md b/vendor/theseer/tokenizer/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..61ecaffac3b0460500b9482b2045e6fae73a7c07
--- /dev/null
+++ b/vendor/theseer/tokenizer/README.md
@@ -0,0 +1,49 @@
+# Tokenizer
+
+A small library for converting tokenized PHP source code into XML.
+
+[![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/theseer/tokenizer/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/theseer/tokenizer/?branch=master)
+[![Code Coverage](https://scrutinizer-ci.com/g/theseer/tokenizer/badges/coverage.png?b=master)](https://scrutinizer-ci.com/g/theseer/tokenizer/?branch=master)
+[![Build Status](https://scrutinizer-ci.com/g/theseer/tokenizer/badges/build.png?b=master)](https://scrutinizer-ci.com/g/theseer/tokenizer/build-status/master)
+
+## Installation
+
+You can add this library as a local, per-project dependency to your project using [Composer](https://getcomposer.org/):
+
+    composer require theseer/tokenizer
+
+If you only need this library during development, for instance to run your project's test suite, then you should add it as a development-time dependency:
+
+    composer require --dev theseer/tokenizer
+
+## Usage examples
+
+```php
+$tokenizer = new TheSeer\Tokenizer\Tokenizer();
+$tokens = $tokenizer->parse(file_get_contents(__DIR__ . '/src/XMLSerializer.php'));
+
+$serializer = new TheSeer\Tokenizer\XMLSerializer();
+$xml = $serializer->toXML($tokens);
+
+echo $xml;
+```
+
+The generated XML structure looks something like this:
+
+```xml
+<?xml version="1.0"?>
+<source xmlns="https://github.com/theseer/tokenizer">
+ <line no="1">
+  <token name="T_OPEN_TAG">&lt;?php </token>
+  <token name="T_DECLARE">declare</token>
+  <token name="T_OPEN_BRACKET">(</token>
+  <token name="T_STRING">strict_types</token>
+  <token name="T_WHITESPACE"> </token>
+  <token name="T_EQUAL">=</token>
+  <token name="T_WHITESPACE"> </token>
+  <token name="T_LNUMBER">1</token>
+  <token name="T_CLOSE_BRACKET">)</token>
+  <token name="T_SEMICOLON">;</token>
+ </line>
+</source>
+```
diff --git a/vendor/theseer/tokenizer/composer.json b/vendor/theseer/tokenizer/composer.json
new file mode 100644
index 0000000000000000000000000000000000000000..3f452a9fc7a5d048034fb157153bd90b6b7ab6e2
--- /dev/null
+++ b/vendor/theseer/tokenizer/composer.json
@@ -0,0 +1,27 @@
+{
+  "name": "theseer/tokenizer",
+  "description": "A small library for converting tokenized PHP source code into XML and potentially other formats",
+  "license": "BSD-3-Clause",
+  "authors": [
+    {
+      "name": "Arne Blankerts",
+      "email": "arne@blankerts.de",
+      "role": "Developer"
+    }
+  ],
+  "support": {
+    "issues": "https://github.com/theseer/tokenizer/issues"
+  },
+  "require": {
+    "php": "^7.2 || ^8.0",
+    "ext-xmlwriter": "*",
+    "ext-dom": "*",
+    "ext-tokenizer": "*"
+  },
+  "autoload": {
+    "classmap": [
+      "src/"
+    ]
+  }
+}
+
diff --git a/vendor/theseer/tokenizer/src/Exception.php b/vendor/theseer/tokenizer/src/Exception.php
new file mode 100644
index 0000000000000000000000000000000000000000..71fc117a51e51a03d36f2d12a4e73fb9fe0dadc7
--- /dev/null
+++ b/vendor/theseer/tokenizer/src/Exception.php
@@ -0,0 +1,5 @@
+<?php declare(strict_types = 1);
+namespace TheSeer\Tokenizer;
+
+class Exception extends \Exception {
+}
diff --git a/vendor/theseer/tokenizer/src/NamespaceUri.php b/vendor/theseer/tokenizer/src/NamespaceUri.php
new file mode 100644
index 0000000000000000000000000000000000000000..14e9f0c8ca92944e1ca7e504939caa66d9572e5e
--- /dev/null
+++ b/vendor/theseer/tokenizer/src/NamespaceUri.php
@@ -0,0 +1,25 @@
+<?php declare(strict_types = 1);
+namespace TheSeer\Tokenizer;
+
+class NamespaceUri {
+
+    /** @var string */
+    private $value;
+
+    public function __construct(string $value) {
+        $this->ensureValidUri($value);
+        $this->value = $value;
+    }
+
+    public function asString(): string {
+        return $this->value;
+    }
+
+    private function ensureValidUri($value): void {
+        if (\strpos($value, ':') === false) {
+            throw new NamespaceUriException(
+                \sprintf("Namespace URI '%s' must contain at least one colon", $value)
+            );
+        }
+    }
+}
diff --git a/vendor/theseer/tokenizer/src/NamespaceUriException.php b/vendor/theseer/tokenizer/src/NamespaceUriException.php
new file mode 100644
index 0000000000000000000000000000000000000000..ab1c48d299a14a470ce5410e0c89eae635654cf1
--- /dev/null
+++ b/vendor/theseer/tokenizer/src/NamespaceUriException.php
@@ -0,0 +1,5 @@
+<?php declare(strict_types = 1);
+namespace TheSeer\Tokenizer;
+
+class NamespaceUriException extends Exception {
+}
diff --git a/vendor/theseer/tokenizer/src/Token.php b/vendor/theseer/tokenizer/src/Token.php
new file mode 100644
index 0000000000000000000000000000000000000000..ffcbe40099fbe972ac150e984d1f7d166f546cbc
--- /dev/null
+++ b/vendor/theseer/tokenizer/src/Token.php
@@ -0,0 +1,35 @@
+<?php declare(strict_types = 1);
+namespace TheSeer\Tokenizer;
+
+class Token {
+
+    /** @var int */
+    private $line;
+
+    /** @var string */
+    private $name;
+
+    /** @var string */
+    private $value;
+
+    /**
+     * Token constructor.
+     */
+    public function __construct(int $line, string $name, string $value) {
+        $this->line  = $line;
+        $this->name  = $name;
+        $this->value = $value;
+    }
+
+    public function getLine(): int {
+        return $this->line;
+    }
+
+    public function getName(): string {
+        return $this->name;
+    }
+
+    public function getValue(): string {
+        return $this->value;
+    }
+}
diff --git a/vendor/theseer/tokenizer/src/TokenCollection.php b/vendor/theseer/tokenizer/src/TokenCollection.php
new file mode 100644
index 0000000000000000000000000000000000000000..e5e6e401cb607abe0493faf1e7c90380b291b264
--- /dev/null
+++ b/vendor/theseer/tokenizer/src/TokenCollection.php
@@ -0,0 +1,93 @@
+<?php declare(strict_types = 1);
+namespace TheSeer\Tokenizer;
+
+class TokenCollection implements \ArrayAccess, \Iterator, \Countable {
+
+    /** @var Token[] */
+    private $tokens = [];
+
+    /** @var int */
+    private $pos;
+
+    public function addToken(Token $token): void {
+        $this->tokens[] = $token;
+    }
+
+    public function current(): Token {
+        return \current($this->tokens);
+    }
+
+    public function key(): int {
+        return \key($this->tokens);
+    }
+
+    public function next(): void {
+        \next($this->tokens);
+        $this->pos++;
+    }
+
+    public function valid(): bool {
+        return $this->count() > $this->pos;
+    }
+
+    public function rewind(): void {
+        \reset($this->tokens);
+        $this->pos = 0;
+    }
+
+    public function count(): int {
+        return \count($this->tokens);
+    }
+
+    public function offsetExists($offset): bool {
+        return isset($this->tokens[$offset]);
+    }
+
+    /**
+     * @throws TokenCollectionException
+     */
+    public function offsetGet($offset): Token {
+        if (!$this->offsetExists($offset)) {
+            throw new TokenCollectionException(
+                \sprintf('No Token at offest %s', $offset)
+            );
+        }
+
+        return $this->tokens[$offset];
+    }
+
+    /**
+     * @param Token $value
+     *
+     * @throws TokenCollectionException
+     */
+    public function offsetSet($offset, $value): void {
+        if (!\is_int($offset)) {
+            $type = \gettype($offset);
+
+            throw new TokenCollectionException(
+                \sprintf(
+                    'Offset must be of type integer, %s given',
+                    $type === 'object' ? \get_class($value) : $type
+                )
+            );
+        }
+
+        if (!$value instanceof Token) {
+            $type = \gettype($value);
+
+            throw new TokenCollectionException(
+                \sprintf(
+                    'Value must be of type %s, %s given',
+                    Token::class,
+                    $type === 'object' ? \get_class($value) : $type
+                )
+            );
+        }
+        $this->tokens[$offset] = $value;
+    }
+
+    public function offsetUnset($offset): void {
+        unset($this->tokens[$offset]);
+    }
+}
diff --git a/vendor/theseer/tokenizer/src/TokenCollectionException.php b/vendor/theseer/tokenizer/src/TokenCollectionException.php
new file mode 100644
index 0000000000000000000000000000000000000000..4291ce0c4d7984686eda154a1e139cb50bce5fcc
--- /dev/null
+++ b/vendor/theseer/tokenizer/src/TokenCollectionException.php
@@ -0,0 +1,5 @@
+<?php declare(strict_types = 1);
+namespace TheSeer\Tokenizer;
+
+class TokenCollectionException extends Exception {
+}
diff --git a/vendor/theseer/tokenizer/src/Tokenizer.php b/vendor/theseer/tokenizer/src/Tokenizer.php
new file mode 100644
index 0000000000000000000000000000000000000000..df3f77b000172eb2eacea6eebe3195758d58ab74
--- /dev/null
+++ b/vendor/theseer/tokenizer/src/Tokenizer.php
@@ -0,0 +1,137 @@
+<?php declare(strict_types = 1);
+namespace TheSeer\Tokenizer;
+
+class Tokenizer {
+
+    /**
+     * Token Map for "non-tokens"
+     *
+     * @var array
+     */
+    private $map = [
+        '(' => 'T_OPEN_BRACKET',
+        ')' => 'T_CLOSE_BRACKET',
+        '[' => 'T_OPEN_SQUARE',
+        ']' => 'T_CLOSE_SQUARE',
+        '{' => 'T_OPEN_CURLY',
+        '}' => 'T_CLOSE_CURLY',
+        ';' => 'T_SEMICOLON',
+        '.' => 'T_DOT',
+        ',' => 'T_COMMA',
+        '=' => 'T_EQUAL',
+        '<' => 'T_LT',
+        '>' => 'T_GT',
+        '+' => 'T_PLUS',
+        '-' => 'T_MINUS',
+        '*' => 'T_MULT',
+        '/' => 'T_DIV',
+        '?' => 'T_QUESTION_MARK',
+        '!' => 'T_EXCLAMATION_MARK',
+        ':' => 'T_COLON',
+        '"' => 'T_DOUBLE_QUOTES',
+        '@' => 'T_AT',
+        '&' => 'T_AMPERSAND',
+        '%' => 'T_PERCENT',
+        '|' => 'T_PIPE',
+        '$' => 'T_DOLLAR',
+        '^' => 'T_CARET',
+        '~' => 'T_TILDE',
+        '`' => 'T_BACKTICK'
+    ];
+
+    public function parse(string $source): TokenCollection {
+        $result = new TokenCollection();
+
+        if ($source === '') {
+            return $result;
+        }
+
+        $tokens = \token_get_all($source);
+
+        $lastToken = new Token(
+            $tokens[0][2],
+            'Placeholder',
+            ''
+        );
+
+        foreach ($tokens as $pos => $tok) {
+            if (\is_string($tok)) {
+                $token = new Token(
+                    $lastToken->getLine(),
+                    $this->map[$tok],
+                    $tok
+                );
+                $result->addToken($token);
+                $lastToken = $token;
+
+                continue;
+            }
+
+            $line   = $tok[2];
+            $values = \preg_split('/\R+/Uu', $tok[1]);
+
+            foreach ($values as $v) {
+                $token = new Token(
+                    $line,
+                    \token_name($tok[0]),
+                    $v
+                );
+                $lastToken = $token;
+                $line++;
+
+                if ($v === '') {
+                    continue;
+                }
+                $result->addToken($token);
+            }
+        }
+
+        return $this->fillBlanks($result, $lastToken->getLine());
+    }
+
+    private function fillBlanks(TokenCollection $tokens, int $maxLine): TokenCollection {
+        /** @var Token $prev */
+        $prev  = null;
+        $final = new TokenCollection();
+
+        foreach ($tokens as $token) {
+            if ($prev === null) {
+                $final->addToken($token);
+                $prev = $token;
+
+                continue;
+            }
+
+            $gap = $token->getLine() - $prev->getLine();
+
+            while ($gap > 1) {
+                $linebreak = new Token(
+                    $prev->getLine() + 1,
+                    'T_WHITESPACE',
+                    ''
+                );
+                $final->addToken($linebreak);
+                $prev = $linebreak;
+                $gap--;
+            }
+
+            $final->addToken($token);
+            $prev = $token;
+        }
+
+        $gap = $maxLine - $prev->getLine();
+
+        while ($gap > 0) {
+            $linebreak = new Token(
+                $prev->getLine() + 1,
+                'T_WHITESPACE',
+                ''
+            );
+            $final->addToken($linebreak);
+            $prev = $linebreak;
+            $gap--;
+        }
+
+        return $final;
+    }
+}
diff --git a/vendor/theseer/tokenizer/src/XMLSerializer.php b/vendor/theseer/tokenizer/src/XMLSerializer.php
new file mode 100644
index 0000000000000000000000000000000000000000..e67a7fe8bfdfc33cecece4c48a845e31de36b866
--- /dev/null
+++ b/vendor/theseer/tokenizer/src/XMLSerializer.php
@@ -0,0 +1,79 @@
+<?php declare(strict_types = 1);
+namespace TheSeer\Tokenizer;
+
+use DOMDocument;
+
+class XMLSerializer {
+
+    /** @var \XMLWriter */
+    private $writer;
+
+    /** @var Token */
+    private $previousToken;
+
+    /** @var NamespaceUri */
+    private $xmlns;
+
+    /**
+     * XMLSerializer constructor.
+     *
+     * @param NamespaceUri $xmlns
+     */
+    public function __construct(NamespaceUri $xmlns = null) {
+        if ($xmlns === null) {
+            $xmlns = new NamespaceUri('https://github.com/theseer/tokenizer');
+        }
+        $this->xmlns = $xmlns;
+    }
+
+    public function toDom(TokenCollection $tokens): DOMDocument {
+        $dom                     = new DOMDocument();
+        $dom->preserveWhiteSpace = false;
+        $dom->loadXML($this->toXML($tokens));
+
+        return $dom;
+    }
+
+    public function toXML(TokenCollection $tokens): string {
+        $this->writer = new \XMLWriter();
+        $this->writer->openMemory();
+        $this->writer->setIndent(true);
+        $this->writer->startDocument();
+        $this->writer->startElement('source');
+        $this->writer->writeAttribute('xmlns', $this->xmlns->asString());
+
+        if (\count($tokens) > 0) {
+            $this->writer->startElement('line');
+            $this->writer->writeAttribute('no', '1');
+
+            $this->previousToken = $tokens[0];
+
+            foreach ($tokens as $token) {
+                $this->addToken($token);
+            }
+        }
+
+        $this->writer->endElement();
+        $this->writer->endElement();
+        $this->writer->endDocument();
+
+        return $this->writer->outputMemory();
+    }
+
+    private function addToken(Token $token): void {
+        if ($this->previousToken->getLine() < $token->getLine()) {
+            $this->writer->endElement();
+
+            $this->writer->startElement('line');
+            $this->writer->writeAttribute('no', (string)$token->getLine());
+            $this->previousToken = $token;
+        }
+
+        if ($token->getValue() !== '') {
+            $this->writer->startElement('token');
+            $this->writer->writeAttribute('name', $token->getName());
+            $this->writer->writeRaw(\htmlspecialchars($token->getValue(), \ENT_NOQUOTES | \ENT_DISALLOWED | \ENT_XML1));
+            $this->writer->endElement();
+        }
+    }
+}
diff --git a/vendor/webmozart/assert/.editorconfig b/vendor/webmozart/assert/.editorconfig
new file mode 100644
index 0000000000000000000000000000000000000000..384453bfb0859785abde2713b0c99ca6b679f1f1
--- /dev/null
+++ b/vendor/webmozart/assert/.editorconfig
@@ -0,0 +1,12 @@
+root = true
+
+[*]
+charset=utf-8
+end_of_line=lf
+trim_trailing_whitespace=true
+insert_final_newline=true
+indent_style=space
+indent_size=4
+
+[*.yml]
+indent_size=2
diff --git a/vendor/webmozart/assert/.github/workflows/ci.yaml b/vendor/webmozart/assert/.github/workflows/ci.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..636fc5ab517685ed396a999fca18375761e38670
--- /dev/null
+++ b/vendor/webmozart/assert/.github/workflows/ci.yaml
@@ -0,0 +1,120 @@
+# https://docs.github.com/en/actions
+
+name: "CI"
+
+on:
+    pull_request: ~
+    push:
+        branches:
+            - "master"
+
+env:
+    COMPOSER_ROOT_VERSION: 1.99
+
+jobs:
+    coding-standards:
+        name: "Coding Standards"
+
+        runs-on: "ubuntu-latest"
+
+        steps:
+            -   name: "Checkout"
+                uses: "actions/checkout@v2.3.4"
+
+            -   name: "Install PHP"
+                uses: "shivammathur/setup-php@2.9.0"
+                with:
+                    coverage: "none"
+                    extensions: "mbstring"
+                    php-version: "7.4"
+                    tools: "composer-normalize"
+
+            -   name: "Validate composer.json"
+                run: "composer validate --strict"
+
+            -   name: "Normalize composer.json"
+                run: "composer-normalize --dry-run"
+
+            - name: "PHP-CS-Fixer"
+              uses: "docker://oskarstark/php-cs-fixer-ga:2.18.0"
+              with:
+                args: "--dry-run --diff-format udiff"
+
+    static-code-analysis:
+        name: "Static Code Analysis"
+
+        runs-on: "ubuntu-latest"
+
+        steps:
+            -   name: "Checkout"
+                uses: "actions/checkout@v2.3.4"
+
+            -   name: "Install PHP"
+                uses: "shivammathur/setup-php@2.9.0"
+                with:
+                    coverage: "none"
+                    extensions: "mbstring"
+                    php-version: "7.4"
+
+            -   name: "Install dependencies with composer"
+                run: "composer update --no-interaction --no-progress && composer i --working-dir=ci"
+
+            -   name: "Run vimeo/psalm"
+                run: "ci/vendor/bin/psalm --threads=4"
+
+    tests:
+        name: "Tests"
+
+        runs-on: "ubuntu-latest"
+
+        strategy:
+            matrix:
+                php-version:
+                    - "7.2"
+                    - "7.3"
+                    - "7.4"
+                    - "8.0"
+
+        steps:
+            -   name: "Checkout"
+                uses: "actions/checkout@v2.3.4"
+
+            -   name: "Install PHP"
+                uses: "shivammathur/setup-php@2.9.0"
+                with:
+                    coverage: "none"
+                    extensions: "mbstring"
+                    php-version: "${{ matrix.php-version }}"
+
+            -   name: "Install dependencies with composer"
+                run: "composer update --no-interaction --no-progress"
+
+            -   name: "Run unit tests"
+                run: "vendor/bin/phpunit"
+
+    windows-tests:
+        name: "Windows tests"
+
+        runs-on: "windows-latest"
+
+        strategy:
+            matrix:
+                php-version:
+                    - "7.4"
+
+        steps:
+            -   name: "Checkout"
+                uses: "actions/checkout@v2.3.4"
+
+            -   name: "Install PHP"
+                uses: "shivammathur/setup-php@2.9.0"
+                with:
+                    coverage: "none"
+                    extensions: "mbstring"
+                    php-version: "${{ matrix.php-version }}"
+
+            -   name: "Install dependencies with composer"
+                run: "composer update --no-interaction --no-progress"
+
+            -   name: "Run unit tests"
+                run: "vendor/bin/phpunit tests/AssertTest.php"
diff --git a/vendor/webmozart/assert/.php_cs b/vendor/webmozart/assert/.php_cs
new file mode 100644
index 0000000000000000000000000000000000000000..f7afd3ed707a3321ca791e7ea6b0e8769cca560c
--- /dev/null
+++ b/vendor/webmozart/assert/.php_cs
@@ -0,0 +1,24 @@
+<?php
+
+$finder = PhpCsFixer\Finder::create()
+    ->in(__DIR__.'/src')
+    ->in(__DIR__.'/tests')
+;
+
+return PhpCsFixer\Config::create()
+    ->setRiskyAllowed(true)
+    ->setRules([
+        '@PSR2' => true,
+        '@Symfony' => true,
+        'ordered_imports' => true,
+        'array_syntax' => ['syntax' => 'long'],
+        'no_superfluous_phpdoc_tags' => false,
+        'phpdoc_annotation_without_dot' => false,
+        'phpdoc_types_order' => false,
+        'phpdoc_summary' => false,
+        'phpdoc_to_comment' => false,
+        'phpdoc_align' => false,
+        'yoda_style' => false,
+    ])
+    ->setFinder($finder)
+;
diff --git a/vendor/webmozart/assert/CHANGELOG.md b/vendor/webmozart/assert/CHANGELOG.md
new file mode 100644
index 0000000000000000000000000000000000000000..8629248bb2f91638e801a609071f2dbaa6b21b52
--- /dev/null
+++ b/vendor/webmozart/assert/CHANGELOG.md
@@ -0,0 +1,190 @@
+Changelog
+=========
+
+## UNRELEASED
+
+## 1.10.0
+
+### Added
+
+* On invalid assertion, we throw a `Webmozart\Assert\InvalidArgumentException`
+* Added `Assert::positiveInteger()`
+
+### Changed
+
+* Using a trait with real implementations of `all*()` and `nullOr*()` methods to improve psalm compatibility.
+
+### Removed
+
+* Support for PHP <7.2
+
+## 1.9.1
+
+## Fixed
+
+* provisional support for PHP 8.0
+
+## 1.9.0
+
+* added better Psalm support for `all*` & `nullOr*` methods
+* These methods are now understood by Psalm through a mixin. You may need a newer version of Psalm in order to use this
+* added `@psalm-pure` annotation to `Assert::notFalse()`
+* added more `@psalm-assert` annotations where appropriate
+
+## Changed
+
+* the `all*` & `nullOr*` methods are now declared on an interface, instead of `@method` annotations.
+This interface is linked to the `Assert` class with a `@mixin` annotation. Most IDE's have supported this
+for a long time, and you should not lose any autocompletion capabilities. PHPStan has supported this since
+version `0.12.20`. This package is marked incompatible (with a composer conflict) with phpstan version prior to that.
+If you do not use PHPStan than this does not matter.
+
+## 1.8.0
+
+### Added
+
+* added `Assert::notStartsWith()`
+* added `Assert::notEndsWith()`
+* added `Assert::inArray()`
+* added `@psalm-pure` annotations to pure assertions
+
+### Fixed
+
+* Exception messages of comparisons between `DateTime(Immutable)` objects now display their date & time.
+* Custom Exception messages for `Assert::count()` now use the values to render the exception message.
+
+## 1.7.0 (2020-02-14)
+
+### Added
+
+* added `Assert::notFalse()`
+* added `Assert::isAOf()`
+* added `Assert::isAnyOf()`
+* added `Assert::isNotA()`
+
+## 1.6.0 (2019-11-24)
+
+### Added
+
+* added `Assert::validArrayKey()`
+* added `Assert::isNonEmptyList()`
+* added `Assert::isNonEmptyMap()`
+* added `@throws InvalidArgumentException` annotations to all methods that throw.
+* added `@psalm-assert` for the list type to the `isList` assertion.
+
+### Fixed
+
+* `ResourceBundle` & `SimpleXMLElement` now pass the `isCountable` assertions.
+They are countable, without implementing the `Countable` interface.
+* The doc block of `range` now has the proper variables.
+* An empty array will now pass `isList` and `isMap`. As it is a valid form of both.
+If a non-empty variant is needed, use `isNonEmptyList` or `isNonEmptyMap`.
+
+### Changed
+
+* Removed some `@psalm-assert` annotations, that were 'side effect' assertions See:
+  * [#144](https://github.com/webmozart/assert/pull/144)
+  * [#145](https://github.com/webmozart/assert/issues/145)
+  * [#146](https://github.com/webmozart/assert/pull/146)
+  * [#150](https://github.com/webmozart/assert/pull/150)
+* If you use Psalm, the minimum version needed is `3.6.0`. Which is enforced through a composer conflict.
+If you don't use Psalm, then this has no impact.
+
+## 1.5.0 (2019-08-24)
+
+### Added
+
+* added `Assert::uniqueValues()`
+* added `Assert::unicodeLetters()`
+* added: `Assert::email()`
+* added support for [Psalm](https://github.com/vimeo/psalm), by adding `@psalm-assert` annotations where appropriate.
+
+### Fixed
+
+* `Assert::endsWith()` would not give the correct result when dealing with a multibyte suffix.
+* `Assert::length(), minLength, maxLength, lengthBetween` would not give the correct result when dealing with multibyte characters.
+
+**NOTE**: These 2 changes may break your assertions if you relied on the fact that multibyte characters didn't behave correctly.
+
+### Changed
+
+* The names of some variables have been updated to better reflect what they are.
+* All function calls are now in their FQN form, slightly increasing performance.
+* Tests are now properly ran against HHVM-3.30 and PHP nightly.
+
+### Deprecation
+
+* deprecated `Assert::isTraversable()` in favor of `Assert::isIterable()`
+  * This was already done in 1.3.0, but it was only done through a silenced `trigger_error`. It is now annotated as well.
+
+## 1.4.0 (2018-12-25)
+
+### Added
+
+* added `Assert::ip()`
+* added `Assert::ipv4()`
+* added `Assert::ipv6()`
+* added `Assert::notRegex()`
+* added `Assert::interfaceExists()`
+* added `Assert::isList()`
+* added `Assert::isMap()`
+* added polyfill for ctype
+
+### Fixed
+
+* Special case when comparing objects implementing `__toString()`
+
+## 1.3.0 (2018-01-29)
+
+### Added
+
+* added `Assert::minCount()`
+* added `Assert::maxCount()`
+* added `Assert::countBetween()`
+* added `Assert::isCountable()`
+* added `Assert::notWhitespaceOnly()`
+* added `Assert::natural()`
+* added `Assert::notContains()`
+* added `Assert::isArrayAccessible()`
+* added `Assert::isInstanceOfAny()`
+* added `Assert::isIterable()`
+
+### Fixed
+
+* `stringNotEmpty` will no longer report "0" is an empty string
+
+### Deprecation
+
+* deprecated `Assert::isTraversable()` in favor of `Assert::isIterable()`
+
+## 1.2.0 (2016-11-23)
+
+ * added `Assert::throws()`
+ * added `Assert::count()`
+ * added extension point `Assert::reportInvalidArgument()` for custom subclasses
+
+## 1.1.0 (2016-08-09)
+
+ * added `Assert::object()`
+ * added `Assert::propertyExists()`
+ * added `Assert::propertyNotExists()`
+ * added `Assert::methodExists()`
+ * added `Assert::methodNotExists()`
+ * added `Assert::uuid()`
+
+## 1.0.2 (2015-08-24)
+
+ * integrated Style CI
+ * add tests for minimum package dependencies on Travis CI
+
+## 1.0.1 (2015-05-12)
+
+ * added support for PHP 5.3.3
+
+## 1.0.0 (2015-05-12)
+
+ * first stable release
+
+## 1.0.0-beta (2015-03-19)
+
+ * first beta release
diff --git a/vendor/webmozart/assert/LICENSE b/vendor/webmozart/assert/LICENSE
new file mode 100644
index 0000000000000000000000000000000000000000..9e2e3075eb844a130a8532ed062169d8d06237a7
--- /dev/null
+++ b/vendor/webmozart/assert/LICENSE
@@ -0,0 +1,20 @@
+The MIT License (MIT)
+
+Copyright (c) 2014 Bernhard Schussek
+
+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/webmozart/assert/README.md b/vendor/webmozart/assert/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..b85d5981712820ac7eaa9f78352e30754ecdd2c6
--- /dev/null
+++ b/vendor/webmozart/assert/README.md
@@ -0,0 +1,287 @@
+Webmozart Assert
+================
+
+[![Latest Stable Version](https://poser.pugx.org/webmozart/assert/v/stable.svg)](https://packagist.org/packages/webmozart/assert)
+[![Total Downloads](https://poser.pugx.org/webmozart/assert/downloads.svg)](https://packagist.org/packages/webmozart/assert)
+
+This library contains efficient assertions to test the input and output of
+your methods. With these assertions, you can greatly reduce the amount of coding
+needed to write a safe implementation.
+
+All assertions in the [`Assert`] class throw an `Webmozart\Assert\InvalidArgumentException` if
+they fail.
+
+FAQ
+---
+
+**What's the difference to [beberlei/assert]?**
+
+This library is heavily inspired by Benjamin Eberlei's wonderful [assert package],
+but fixes a usability issue with error messages that can't be fixed there without
+breaking backwards compatibility.
+
+This package features usable error messages by default. However, you can also
+easily write custom error messages:
+
+```
+Assert::string($path, 'The path is expected to be a string. Got: %s');
+```
+
+In [beberlei/assert], the ordering of the `%s` placeholders is different for
+every assertion. This package, on the contrary, provides consistent placeholder
+ordering for all assertions:
+
+* `%s`: The tested value as string, e.g. `"/foo/bar"`.
+* `%2$s`, `%3$s`, ...: Additional assertion-specific values, e.g. the
+  minimum/maximum length, allowed values, etc.
+
+Check the source code of the assertions to find out details about the additional
+available placeholders.
+
+Installation
+------------
+
+Use [Composer] to install the package:
+
+```
+$ composer require webmozart/assert
+```
+
+Example
+-------
+
+```php
+use Webmozart\Assert\Assert;
+
+class Employee
+{
+    public function __construct($id)
+    {
+        Assert::integer($id, 'The employee ID must be an integer. Got: %s');
+        Assert::greaterThan($id, 0, 'The employee ID must be a positive integer. Got: %s');
+    }
+}
+```
+
+If you create an employee with an invalid ID, an exception is thrown:
+
+```php
+new Employee('foobar');
+// => Webmozart\Assert\InvalidArgumentException:
+//    The employee ID must be an integer. Got: string
+
+new Employee(-10);
+// => Webmozart\Assert\InvalidArgumentException:
+//    The employee ID must be a positive integer. Got: -10
+```
+
+Assertions
+----------
+
+The [`Assert`] class provides the following assertions:
+
+### Type Assertions
+
+Method                                                   | Description
+-------------------------------------------------------- | --------------------------------------------------
+`string($value, $message = '')`                          | Check that a value is a string
+`stringNotEmpty($value, $message = '')`                  | Check that a value is a non-empty string
+`integer($value, $message = '')`                         | Check that a value is an integer
+`integerish($value, $message = '')`                      | Check that a value casts to an integer
+`positiveInteger($value, $message = '')`                 | Check that a value is a positive (non-zero) integer
+`float($value, $message = '')`                           | Check that a value is a float
+`numeric($value, $message = '')`                         | Check that a value is numeric
+`natural($value, $message= ''')`                         | Check that a value is a non-negative integer
+`boolean($value, $message = '')`                         | Check that a value is a boolean
+`scalar($value, $message = '')`                          | Check that a value is a scalar
+`object($value, $message = '')`                          | Check that a value is an object
+`resource($value, $type = null, $message = '')`          | Check that a value is a resource
+`isCallable($value, $message = '')`                      | Check that a value is a callable
+`isArray($value, $message = '')`                         | Check that a value is an array
+`isTraversable($value, $message = '')`  (deprecated)     | Check that a value is an array or a `\Traversable`
+`isIterable($value, $message = '')`                      | Check that a value is an array or a `\Traversable`
+`isCountable($value, $message = '')`                     | Check that a value is an array or a `\Countable`
+`isInstanceOf($value, $class, $message = '')`            | Check that a value is an `instanceof` a class
+`isInstanceOfAny($value, array $classes, $message = '')` | Check that a value is an `instanceof` at least one class on the array of classes
+`notInstanceOf($value, $class, $message = '')`           | Check that a value is not an `instanceof` a class
+`isAOf($value, $class, $message = '')`                   | Check that a value is of the class or has one of its parents
+`isAnyOf($value, array $classes, $message = '')`         | Check that a value is of at least one of the classes or has one of its parents
+`isNotA($value, $class, $message = '')`                  | Check that a value is not of the class or has not one of its parents
+`isArrayAccessible($value, $message = '')`               | Check that a value can be accessed as an array
+`uniqueValues($values, $message = '')`                   | Check that the given array contains unique values
+
+### Comparison Assertions
+
+Method                                          | Description
+----------------------------------------------- | ------------------------------------------------------------------
+`true($value, $message = '')`                   | Check that a value is `true`
+`false($value, $message = '')`                  | Check that a value is `false`
+`notFalse($value, $message = '')`               | Check that a value is not `false`
+`null($value, $message = '')`                   | Check that a value is `null`
+`notNull($value, $message = '')`                | Check that a value is not `null`
+`isEmpty($value, $message = '')`                | Check that a value is `empty()`
+`notEmpty($value, $message = '')`               | Check that a value is not `empty()`
+`eq($value, $value2, $message = '')`            | Check that a value equals another (`==`)
+`notEq($value, $value2, $message = '')`         | Check that a value does not equal another (`!=`)
+`same($value, $value2, $message = '')`          | Check that a value is identical to another (`===`)
+`notSame($value, $value2, $message = '')`       | Check that a value is not identical to another (`!==`)
+`greaterThan($value, $value2, $message = '')`   | Check that a value is greater than another
+`greaterThanEq($value, $value2, $message = '')` | Check that a value is greater than or equal to another
+`lessThan($value, $value2, $message = '')`      | Check that a value is less than another
+`lessThanEq($value, $value2, $message = '')`    | Check that a value is less than or equal to another
+`range($value, $min, $max, $message = '')`      | Check that a value is within a range
+`inArray($value, array $values, $message = '')` | Check that a value is one of a list of values
+`oneOf($value, array $values, $message = '')`   | Check that a value is one of a list of values (alias of `inArray`)
+
+### String Assertions
+
+You should check that a value is a string with `Assert::string()` before making
+any of the following assertions.
+
+Method                                              | Description
+--------------------------------------------------- | -----------------------------------------------------------------
+`contains($value, $subString, $message = '')`       | Check that a string contains a substring
+`notContains($value, $subString, $message = '')`    | Check that a string does not contain a substring
+`startsWith($value, $prefix, $message = '')`        | Check that a string has a prefix
+`notStartsWith($value, $prefix, $message = '')`     | Check that a string does not have a prefix
+`startsWithLetter($value, $message = '')`           | Check that a string starts with a letter
+`endsWith($value, $suffix, $message = '')`          | Check that a string has a suffix
+`notEndsWith($value, $suffix, $message = '')`       | Check that a string does not have a suffix
+`regex($value, $pattern, $message = '')`            | Check that a string matches a regular expression
+`notRegex($value, $pattern, $message = '')`         | Check that a string does not match a regular expression
+`unicodeLetters($value, $message = '')`             | Check that a string contains Unicode letters only
+`alpha($value, $message = '')`                      | Check that a string contains letters only
+`digits($value, $message = '')`                     | Check that a string contains digits only
+`alnum($value, $message = '')`                      | Check that a string contains letters and digits only
+`lower($value, $message = '')`                      | Check that a string contains lowercase characters only
+`upper($value, $message = '')`                      | Check that a string contains uppercase characters only
+`length($value, $length, $message = '')`            | Check that a string has a certain number of characters
+`minLength($value, $min, $message = '')`            | Check that a string has at least a certain number of characters
+`maxLength($value, $max, $message = '')`            | Check that a string has at most a certain number of characters
+`lengthBetween($value, $min, $max, $message = '')`  | Check that a string has a length in the given range
+`uuid($value, $message = '')`                       | Check that a string is a valid UUID
+`ip($value, $message = '')`                         | Check that a string is a valid IP (either IPv4 or IPv6)
+`ipv4($value, $message = '')`                       | Check that a string is a valid IPv4
+`ipv6($value, $message = '')`                       | Check that a string is a valid IPv6
+`email($value, $message = '')`                      | Check that a string is a valid e-mail address
+`notWhitespaceOnly($value, $message = '')`          | Check that a string contains at least one non-whitespace character
+
+### File Assertions
+
+Method                              | Description
+----------------------------------- | --------------------------------------------------
+`fileExists($value, $message = '')` | Check that a value is an existing path
+`file($value, $message = '')`       | Check that a value is an existing file
+`directory($value, $message = '')`  | Check that a value is an existing directory
+`readable($value, $message = '')`   | Check that a value is a readable path
+`writable($value, $message = '')`   | Check that a value is a writable path
+
+### Object Assertions
+
+Method                                                | Description
+----------------------------------------------------- | --------------------------------------------------
+`classExists($value, $message = '')`                  | Check that a value is an existing class name
+`subclassOf($value, $class, $message = '')`           | Check that a class is a subclass of another
+`interfaceExists($value, $message = '')`              | Check that a value is an existing interface name
+`implementsInterface($value, $class, $message = '')`  | Check that a class implements an interface
+`propertyExists($value, $property, $message = '')`    | Check that a property exists in a class/object
+`propertyNotExists($value, $property, $message = '')` | Check that a property does not exist in a class/object
+`methodExists($value, $method, $message = '')`        | Check that a method exists in a class/object
+`methodNotExists($value, $method, $message = '')`     | Check that a method does not exist in a class/object
+
+### Array Assertions
+
+Method                                             | Description
+-------------------------------------------------- | ------------------------------------------------------------------
+`keyExists($array, $key, $message = '')`           | Check that a key exists in an array
+`keyNotExists($array, $key, $message = '')`        | Check that a key does not exist in an array
+`validArrayKey($key, $message = '')`               | Check that a value is a valid array key (int or string)
+`count($array, $number, $message = '')`            | Check that an array contains a specific number of elements
+`minCount($array, $min, $message = '')`            | Check that an array contains at least a certain number of elements
+`maxCount($array, $max, $message = '')`            | Check that an array contains at most a certain number of elements
+`countBetween($array, $min, $max, $message = '')`  | Check that an array has a count in the given range
+`isList($array, $message = '')`                    | Check that an array is a non-associative list
+`isNonEmptyList($array, $message = '')`            | Check that an array is a non-associative list, and not empty
+`isMap($array, $message = '')`                     | Check that an array is associative and has strings as keys
+`isNonEmptyMap($array, $message = '')`             | Check that an array is associative and has strings as keys, and is not empty
+
+### Function Assertions
+
+Method                                      | Description
+------------------------------------------- | -----------------------------------------------------------------------------------------------------
+`throws($closure, $class, $message = '')`   | Check that a function throws a certain exception. Subclasses of the exception class will be accepted.
+
+### Collection Assertions
+
+All of the above assertions can be prefixed with `all*()` to test the contents
+of an array or a `\Traversable`:
+
+```php
+Assert::allIsInstanceOf($employees, 'Acme\Employee');
+```
+
+### Nullable Assertions
+
+All of the above assertions can be prefixed with `nullOr*()` to run the
+assertion only if it the value is not `null`:
+
+```php
+Assert::nullOrString($middleName, 'The middle name must be a string or null. Got: %s');
+```
+
+### Extending Assert
+
+The `Assert` class comes with a few methods, which can be overridden to change the class behaviour. You can also extend it to
+add your own assertions.
+
+#### Overriding methods
+
+Overriding the following methods in your assertion class allows you to change the behaviour of the assertions:
+
+* `public static function __callStatic($name, $arguments)`
+  * This method is used to 'create' the `nullOr` and `all` versions of the assertions.
+* `protected static function valueToString($value)`
+  * This method is used for error messages, to convert the value to a string value for displaying. You could use this for representing a value object with a `__toString` method for example.
+* `protected static function typeToString($value)`
+  * This method is used for error messages, to convert the a value to a string representing its type.
+* `protected static function strlen($value)`
+  * This method is used to calculate string length for relevant methods, using the `mb_strlen` if available and useful.
+* `protected static function reportInvalidArgument($message)`
+  * This method is called when an assertion fails, with the specified error message. Here you can throw your own exception, or log something.
+
+## Static analysis support
+
+Where applicable, assertion functions are annotated to support Psalm's
+[Assertion syntax](https://psalm.dev/docs/annotating_code/assertion_syntax/).
+A dedicated [PHPStan Plugin](https://github.com/phpstan/phpstan-webmozart-assert) is
+required for proper type support.
+
+Authors
+-------
+
+* [Bernhard Schussek] a.k.a. [@webmozart]
+* [The Community Contributors]
+
+Contribute
+----------
+
+Contributions to the package are always welcome!
+
+* Report any bugs or issues you find on the [issue tracker].
+* You can grab the source code at the package's [Git repository].
+
+License
+-------
+
+All contents of this package are licensed under the [MIT license].
+
+[beberlei/assert]: https://github.com/beberlei/assert
+[assert package]: https://github.com/beberlei/assert
+[Composer]: https://getcomposer.org
+[Bernhard Schussek]: https://webmozarts.com
+[The Community Contributors]: https://github.com/webmozart/assert/graphs/contributors
+[issue tracker]: https://github.com/webmozart/assert/issues
+[Git repository]: https://github.com/webmozart/assert
+[@webmozart]: https://twitter.com/webmozart
+[MIT license]: LICENSE
+[`Assert`]: src/Assert.php
diff --git a/vendor/webmozart/assert/composer.json b/vendor/webmozart/assert/composer.json
new file mode 100644
index 0000000000000000000000000000000000000000..cfae60e5c7f3b9252df07c0dbabf0d7ac6046a38
--- /dev/null
+++ b/vendor/webmozart/assert/composer.json
@@ -0,0 +1,43 @@
+{
+    "name": "webmozart/assert",
+    "description": "Assertions to validate method input/output with nice error messages.",
+    "keywords": [
+        "assert",
+        "check",
+        "validate"
+    ],
+    "license": "MIT",
+    "authors": [
+        {
+            "name": "Bernhard Schussek",
+            "email": "bschussek@gmail.com"
+        }
+    ],
+    "require": {
+        "php": "^7.2 || ^8.0",
+        "symfony/polyfill-ctype": "^1.8"
+    },
+    "conflict": {
+        "phpstan/phpstan": "<0.12.20",
+        "vimeo/psalm": "<4.6.1 || 4.6.2"
+    },
+    "require-dev": {
+        "phpunit/phpunit": "^8.5.13"
+    },
+    "extra": {
+        "branch-alias": {
+            "dev-master": "1.10-dev"
+        }
+    },
+    "autoload": {
+        "psr-4": {
+            "Webmozart\\Assert\\": "src/"
+        }
+    },
+    "autoload-dev": {
+        "psr-4": {
+            "Webmozart\\Assert\\Tests\\": "tests/",
+            "Webmozart\\Assert\\Bin\\": "bin/src"
+        }
+    }
+}
diff --git a/vendor/webmozart/assert/psalm.xml b/vendor/webmozart/assert/psalm.xml
new file mode 100644
index 0000000000000000000000000000000000000000..9a430081953b6fc4aad55138fa3209f651661ad8
--- /dev/null
+++ b/vendor/webmozart/assert/psalm.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0"?>
+<psalm
+    totallyTyped="true"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xmlns="https://getpsalm.org/schema/config"
+    xsi:schemaLocation="https://getpsalm.org/schema/config ci/vendor/vimeo/psalm/config.xsd"
+    phpVersion="7.3"
+>
+    <projectFiles>
+        <directory name="bin" />
+        <directory name="tests/static-analysis" />
+    </projectFiles>
+
+</psalm>
diff --git a/vendor/webmozart/assert/src/Assert.php b/vendor/webmozart/assert/src/Assert.php
new file mode 100644
index 0000000000000000000000000000000000000000..e0fbabc86563c8a45a1df88ef4ed9efb695e13c8
--- /dev/null
+++ b/vendor/webmozart/assert/src/Assert.php
@@ -0,0 +1,2066 @@
+<?php
+
+/*
+ * This file is part of the webmozart/assert package.
+ *
+ * (c) Bernhard Schussek <bschussek@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Webmozart\Assert;
+
+use ArrayAccess;
+use BadMethodCallException;
+use Closure;
+use Countable;
+use DateTime;
+use DateTimeImmutable;
+use Exception;
+use ResourceBundle;
+use SimpleXMLElement;
+use Throwable;
+use Traversable;
+
+/**
+ * Efficient assertions to validate the input/output of your methods.
+ *
+ * @since  1.0
+ *
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ */
+class Assert
+{
+    use Mixin;
+
+    /**
+     * @psalm-pure
+     * @psalm-assert string $value
+     *
+     * @param mixed  $value
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     */
+    public static function string($value, $message = '')
+    {
+        if (!\is_string($value)) {
+            static::reportInvalidArgument(\sprintf(
+                $message ?: 'Expected a string. Got: %s',
+                static::typeToString($value)
+            ));
+        }
+    }
+
+    /**
+     * @psalm-pure
+     * @psalm-assert non-empty-string $value
+     *
+     * @param mixed  $value
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     */
+    public static function stringNotEmpty($value, $message = '')
+    {
+        static::string($value, $message);
+        static::notEq($value, '', $message);
+    }
+
+    /**
+     * @psalm-pure
+     * @psalm-assert int $value
+     *
+     * @param mixed  $value
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     */
+    public static function integer($value, $message = '')
+    {
+        if (!\is_int($value)) {
+            static::reportInvalidArgument(\sprintf(
+                $message ?: 'Expected an integer. Got: %s',
+                static::typeToString($value)
+            ));
+        }
+    }
+
+    /**
+     * @psalm-pure
+     * @psalm-assert numeric $value
+     *
+     * @param mixed  $value
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     */
+    public static function integerish($value, $message = '')
+    {
+        if (!\is_numeric($value) || $value != (int) $value) {
+            static::reportInvalidArgument(\sprintf(
+                $message ?: 'Expected an integerish value. Got: %s',
+                static::typeToString($value)
+            ));
+        }
+    }
+
+    /**
+     * @psalm-pure
+     * @psalm-assert positive-int $value
+     *
+     * @param mixed  $value
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     */
+    public static function positiveInteger($value, $message = '')
+    {
+        if (!(\is_int($value) && $value > 0)) {
+            static::reportInvalidArgument(\sprintf(
+                $message ?: 'Expected a positive integer. Got: %s',
+                static::valueToString($value)
+            ));
+        }
+    }
+
+    /**
+     * @psalm-pure
+     * @psalm-assert float $value
+     *
+     * @param mixed  $value
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     */
+    public static function float($value, $message = '')
+    {
+        if (!\is_float($value)) {
+            static::reportInvalidArgument(\sprintf(
+                $message ?: 'Expected a float. Got: %s',
+                static::typeToString($value)
+            ));
+        }
+    }
+
+    /**
+     * @psalm-pure
+     * @psalm-assert numeric $value
+     *
+     * @param mixed  $value
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     */
+    public static function numeric($value, $message = '')
+    {
+        if (!\is_numeric($value)) {
+            static::reportInvalidArgument(\sprintf(
+                $message ?: 'Expected a numeric. Got: %s',
+                static::typeToString($value)
+            ));
+        }
+    }
+
+    /**
+     * @psalm-pure
+     * @psalm-assert positive-int|0 $value
+     *
+     * @param mixed  $value
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     */
+    public static function natural($value, $message = '')
+    {
+        if (!\is_int($value) || $value < 0) {
+            static::reportInvalidArgument(\sprintf(
+                $message ?: 'Expected a non-negative integer. Got: %s',
+                static::valueToString($value)
+            ));
+        }
+    }
+
+    /**
+     * @psalm-pure
+     * @psalm-assert bool $value
+     *
+     * @param mixed  $value
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     */
+    public static function boolean($value, $message = '')
+    {
+        if (!\is_bool($value)) {
+            static::reportInvalidArgument(\sprintf(
+                $message ?: 'Expected a boolean. Got: %s',
+                static::typeToString($value)
+            ));
+        }
+    }
+
+    /**
+     * @psalm-pure
+     * @psalm-assert scalar $value
+     *
+     * @param mixed  $value
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     */
+    public static function scalar($value, $message = '')
+    {
+        if (!\is_scalar($value)) {
+            static::reportInvalidArgument(\sprintf(
+                $message ?: 'Expected a scalar. Got: %s',
+                static::typeToString($value)
+            ));
+        }
+    }
+
+    /**
+     * @psalm-pure
+     * @psalm-assert object $value
+     *
+     * @param mixed  $value
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     */
+    public static function object($value, $message = '')
+    {
+        if (!\is_object($value)) {
+            static::reportInvalidArgument(\sprintf(
+                $message ?: 'Expected an object. Got: %s',
+                static::typeToString($value)
+            ));
+        }
+    }
+
+    /**
+     * @psalm-pure
+     * @psalm-assert resource $value
+     *
+     * @param mixed       $value
+     * @param string|null $type    type of resource this should be. @see https://www.php.net/manual/en/function.get-resource-type.php
+     * @param string      $message
+     *
+     * @throws InvalidArgumentException
+     */
+    public static function resource($value, $type = null, $message = '')
+    {
+        if (!\is_resource($value)) {
+            static::reportInvalidArgument(\sprintf(
+                $message ?: 'Expected a resource. Got: %s',
+                static::typeToString($value)
+            ));
+        }
+
+        if ($type && $type !== \get_resource_type($value)) {
+            static::reportInvalidArgument(\sprintf(
+                $message ?: 'Expected a resource of type %2$s. Got: %s',
+                static::typeToString($value),
+                $type
+            ));
+        }
+    }
+
+    /**
+     * @psalm-pure
+     * @psalm-assert callable $value
+     *
+     * @param mixed  $value
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     */
+    public static function isCallable($value, $message = '')
+    {
+        if (!\is_callable($value)) {
+            static::reportInvalidArgument(\sprintf(
+                $message ?: 'Expected a callable. Got: %s',
+                static::typeToString($value)
+            ));
+        }
+    }
+
+    /**
+     * @psalm-pure
+     * @psalm-assert array $value
+     *
+     * @param mixed  $value
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     */
+    public static function isArray($value, $message = '')
+    {
+        if (!\is_array($value)) {
+            static::reportInvalidArgument(\sprintf(
+                $message ?: 'Expected an array. Got: %s',
+                static::typeToString($value)
+            ));
+        }
+    }
+
+    /**
+     * @psalm-pure
+     * @psalm-assert iterable $value
+     *
+     * @deprecated use "isIterable" or "isInstanceOf" instead
+     *
+     * @param mixed  $value
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     */
+    public static function isTraversable($value, $message = '')
+    {
+        @\trigger_error(
+            \sprintf(
+                'The "%s" assertion is deprecated. You should stop using it, as it will soon be removed in 2.0 version. Use "isIterable" or "isInstanceOf" instead.',
+                __METHOD__
+            ),
+            \E_USER_DEPRECATED
+        );
+
+        if (!\is_array($value) && !($value instanceof Traversable)) {
+            static::reportInvalidArgument(\sprintf(
+                $message ?: 'Expected a traversable. Got: %s',
+                static::typeToString($value)
+            ));
+        }
+    }
+
+    /**
+     * @psalm-pure
+     * @psalm-assert array|ArrayAccess $value
+     *
+     * @param mixed  $value
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     */
+    public static function isArrayAccessible($value, $message = '')
+    {
+        if (!\is_array($value) && !($value instanceof ArrayAccess)) {
+            static::reportInvalidArgument(\sprintf(
+                $message ?: 'Expected an array accessible. Got: %s',
+                static::typeToString($value)
+            ));
+        }
+    }
+
+    /**
+     * @psalm-pure
+     * @psalm-assert countable $value
+     *
+     * @param mixed  $value
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     */
+    public static function isCountable($value, $message = '')
+    {
+        if (
+            !\is_array($value)
+            && !($value instanceof Countable)
+            && !($value instanceof ResourceBundle)
+            && !($value instanceof SimpleXMLElement)
+        ) {
+            static::reportInvalidArgument(\sprintf(
+                $message ?: 'Expected a countable. Got: %s',
+                static::typeToString($value)
+            ));
+        }
+    }
+
+    /**
+     * @psalm-pure
+     * @psalm-assert iterable $value
+     *
+     * @param mixed  $value
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     */
+    public static function isIterable($value, $message = '')
+    {
+        if (!\is_array($value) && !($value instanceof Traversable)) {
+            static::reportInvalidArgument(\sprintf(
+                $message ?: 'Expected an iterable. Got: %s',
+                static::typeToString($value)
+            ));
+        }
+    }
+
+    /**
+     * @psalm-pure
+     * @psalm-template ExpectedType of object
+     * @psalm-param class-string<ExpectedType> $class
+     * @psalm-assert ExpectedType $value
+     *
+     * @param mixed         $value
+     * @param string|object $class
+     * @param string        $message
+     *
+     * @throws InvalidArgumentException
+     */
+    public static function isInstanceOf($value, $class, $message = '')
+    {
+        if (!($value instanceof $class)) {
+            static::reportInvalidArgument(\sprintf(
+                $message ?: 'Expected an instance of %2$s. Got: %s',
+                static::typeToString($value),
+                $class
+            ));
+        }
+    }
+
+    /**
+     * @psalm-pure
+     * @psalm-template ExpectedType of object
+     * @psalm-param class-string<ExpectedType> $class
+     * @psalm-assert !ExpectedType $value
+     *
+     * @param mixed         $value
+     * @param string|object $class
+     * @param string        $message
+     *
+     * @throws InvalidArgumentException
+     */
+    public static function notInstanceOf($value, $class, $message = '')
+    {
+        if ($value instanceof $class) {
+            static::reportInvalidArgument(\sprintf(
+                $message ?: 'Expected an instance other than %2$s. Got: %s',
+                static::typeToString($value),
+                $class
+            ));
+        }
+    }
+
+    /**
+     * @psalm-pure
+     * @psalm-param array<class-string> $classes
+     *
+     * @param mixed                $value
+     * @param array<object|string> $classes
+     * @param string               $message
+     *
+     * @throws InvalidArgumentException
+     */
+    public static function isInstanceOfAny($value, array $classes, $message = '')
+    {
+        foreach ($classes as $class) {
+            if ($value instanceof $class) {
+                return;
+            }
+        }
+
+        static::reportInvalidArgument(\sprintf(
+            $message ?: 'Expected an instance of any of %2$s. Got: %s',
+            static::typeToString($value),
+            \implode(', ', \array_map(array('static', 'valueToString'), $classes))
+        ));
+    }
+
+    /**
+     * @psalm-pure
+     * @psalm-template ExpectedType of object
+     * @psalm-param class-string<ExpectedType> $class
+     * @psalm-assert ExpectedType|class-string<ExpectedType> $value
+     *
+     * @param object|string $value
+     * @param string        $class
+     * @param string        $message
+     *
+     * @throws InvalidArgumentException
+     */
+    public static function isAOf($value, $class, $message = '')
+    {
+        static::string($class, 'Expected class as a string. Got: %s');
+
+        if (!\is_a($value, $class, \is_string($value))) {
+            static::reportInvalidArgument(sprintf(
+                $message ?: 'Expected an instance of this class or to this class among his parents %2$s. Got: %s',
+                static::typeToString($value),
+                $class
+            ));
+        }
+    }
+
+    /**
+     * @psalm-pure
+     * @psalm-template UnexpectedType of object
+     * @psalm-param class-string<UnexpectedType> $class
+     * @psalm-assert !UnexpectedType $value
+     * @psalm-assert !class-string<UnexpectedType> $value
+     *
+     * @param object|string $value
+     * @param string        $class
+     * @param string        $message
+     *
+     * @throws InvalidArgumentException
+     */
+    public static function isNotA($value, $class, $message = '')
+    {
+        static::string($class, 'Expected class as a string. Got: %s');
+
+        if (\is_a($value, $class, \is_string($value))) {
+            static::reportInvalidArgument(sprintf(
+                $message ?: 'Expected an instance of this class or to this class among his parents other than %2$s. Got: %s',
+                static::typeToString($value),
+                $class
+            ));
+        }
+    }
+
+    /**
+     * @psalm-pure
+     * @psalm-param array<class-string> $classes
+     *
+     * @param object|string $value
+     * @param string[]      $classes
+     * @param string        $message
+     *
+     * @throws InvalidArgumentException
+     */
+    public static function isAnyOf($value, array $classes, $message = '')
+    {
+        foreach ($classes as $class) {
+            static::string($class, 'Expected class as a string. Got: %s');
+
+            if (\is_a($value, $class, \is_string($value))) {
+                return;
+            }
+        }
+
+        static::reportInvalidArgument(sprintf(
+            $message ?: 'Expected an any of instance of this class or to this class among his parents other than %2$s. Got: %s',
+            static::typeToString($value),
+            \implode(', ', \array_map(array('static', 'valueToString'), $classes))
+        ));
+    }
+
+    /**
+     * @psalm-pure
+     * @psalm-assert empty $value
+     *
+     * @param mixed  $value
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     */
+    public static function isEmpty($value, $message = '')
+    {
+        if (!empty($value)) {
+            static::reportInvalidArgument(\sprintf(
+                $message ?: 'Expected an empty value. Got: %s',
+                static::valueToString($value)
+            ));
+        }
+    }
+
+    /**
+     * @psalm-pure
+     * @psalm-assert !empty $value
+     *
+     * @param mixed  $value
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     */
+    public static function notEmpty($value, $message = '')
+    {
+        if (empty($value)) {
+            static::reportInvalidArgument(\sprintf(
+                $message ?: 'Expected a non-empty value. Got: %s',
+                static::valueToString($value)
+            ));
+        }
+    }
+
+    /**
+     * @psalm-pure
+     * @psalm-assert null $value
+     *
+     * @param mixed  $value
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     */
+    public static function null($value, $message = '')
+    {
+        if (null !== $value) {
+            static::reportInvalidArgument(\sprintf(
+                $message ?: 'Expected null. Got: %s',
+                static::valueToString($value)
+            ));
+        }
+    }
+
+    /**
+     * @psalm-pure
+     * @psalm-assert !null $value
+     *
+     * @param mixed  $value
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     */
+    public static function notNull($value, $message = '')
+    {
+        if (null === $value) {
+            static::reportInvalidArgument(
+                $message ?: 'Expected a value other than null.'
+            );
+        }
+    }
+
+    /**
+     * @psalm-pure
+     * @psalm-assert true $value
+     *
+     * @param mixed  $value
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     */
+    public static function true($value, $message = '')
+    {
+        if (true !== $value) {
+            static::reportInvalidArgument(\sprintf(
+                $message ?: 'Expected a value to be true. Got: %s',
+                static::valueToString($value)
+            ));
+        }
+    }
+
+    /**
+     * @psalm-pure
+     * @psalm-assert false $value
+     *
+     * @param mixed  $value
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     */
+    public static function false($value, $message = '')
+    {
+        if (false !== $value) {
+            static::reportInvalidArgument(\sprintf(
+                $message ?: 'Expected a value to be false. Got: %s',
+                static::valueToString($value)
+            ));
+        }
+    }
+
+    /**
+     * @psalm-pure
+     * @psalm-assert !false $value
+     *
+     * @param mixed  $value
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     */
+    public static function notFalse($value, $message = '')
+    {
+        if (false === $value) {
+            static::reportInvalidArgument(
+                $message ?: 'Expected a value other than false.'
+            );
+        }
+    }
+
+    /**
+     * @param mixed  $value
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     */
+    public static function ip($value, $message = '')
+    {
+        if (false === \filter_var($value, \FILTER_VALIDATE_IP)) {
+            static::reportInvalidArgument(\sprintf(
+                $message ?: 'Expected a value to be an IP. Got: %s',
+                static::valueToString($value)
+            ));
+        }
+    }
+
+    /**
+     * @param mixed  $value
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     */
+    public static function ipv4($value, $message = '')
+    {
+        if (false === \filter_var($value, \FILTER_VALIDATE_IP, \FILTER_FLAG_IPV4)) {
+            static::reportInvalidArgument(\sprintf(
+                $message ?: 'Expected a value to be an IPv4. Got: %s',
+                static::valueToString($value)
+            ));
+        }
+    }
+
+    /**
+     * @param mixed  $value
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     */
+    public static function ipv6($value, $message = '')
+    {
+        if (false === \filter_var($value, \FILTER_VALIDATE_IP, \FILTER_FLAG_IPV6)) {
+            static::reportInvalidArgument(\sprintf(
+                $message ?: 'Expected a value to be an IPv6. Got: %s',
+                static::valueToString($value)
+            ));
+        }
+    }
+
+    /**
+     * @param mixed  $value
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     */
+    public static function email($value, $message = '')
+    {
+        if (false === \filter_var($value, FILTER_VALIDATE_EMAIL)) {
+            static::reportInvalidArgument(\sprintf(
+                $message ?: 'Expected a value to be a valid e-mail address. Got: %s',
+                static::valueToString($value)
+            ));
+        }
+    }
+
+    /**
+     * Does non strict comparisons on the items, so ['3', 3] will not pass the assertion.
+     *
+     * @param array  $values
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     */
+    public static function uniqueValues(array $values, $message = '')
+    {
+        $allValues = \count($values);
+        $uniqueValues = \count(\array_unique($values));
+
+        if ($allValues !== $uniqueValues) {
+            $difference = $allValues - $uniqueValues;
+
+            static::reportInvalidArgument(\sprintf(
+                $message ?: 'Expected an array of unique values, but %s of them %s duplicated',
+                $difference,
+                (1 === $difference ? 'is' : 'are')
+            ));
+        }
+    }
+
+    /**
+     * @param mixed  $value
+     * @param mixed  $expect
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     */
+    public static function eq($value, $expect, $message = '')
+    {
+        if ($expect != $value) {
+            static::reportInvalidArgument(\sprintf(
+                $message ?: 'Expected a value equal to %2$s. Got: %s',
+                static::valueToString($value),
+                static::valueToString($expect)
+            ));
+        }
+    }
+
+    /**
+     * @param mixed  $value
+     * @param mixed  $expect
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     */
+    public static function notEq($value, $expect, $message = '')
+    {
+        if ($expect == $value) {
+            static::reportInvalidArgument(\sprintf(
+                $message ?: 'Expected a different value than %s.',
+                static::valueToString($expect)
+            ));
+        }
+    }
+
+    /**
+     * @psalm-pure
+     *
+     * @param mixed  $value
+     * @param mixed  $expect
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     */
+    public static function same($value, $expect, $message = '')
+    {
+        if ($expect !== $value) {
+            static::reportInvalidArgument(\sprintf(
+                $message ?: 'Expected a value identical to %2$s. Got: %s',
+                static::valueToString($value),
+                static::valueToString($expect)
+            ));
+        }
+    }
+
+    /**
+     * @psalm-pure
+     *
+     * @param mixed  $value
+     * @param mixed  $expect
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     */
+    public static function notSame($value, $expect, $message = '')
+    {
+        if ($expect === $value) {
+            static::reportInvalidArgument(\sprintf(
+                $message ?: 'Expected a value not identical to %s.',
+                static::valueToString($expect)
+            ));
+        }
+    }
+
+    /**
+     * @psalm-pure
+     *
+     * @param mixed  $value
+     * @param mixed  $limit
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     */
+    public static function greaterThan($value, $limit, $message = '')
+    {
+        if ($value <= $limit) {
+            static::reportInvalidArgument(\sprintf(
+                $message ?: 'Expected a value greater than %2$s. Got: %s',
+                static::valueToString($value),
+                static::valueToString($limit)
+            ));
+        }
+    }
+
+    /**
+     * @psalm-pure
+     *
+     * @param mixed  $value
+     * @param mixed  $limit
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     */
+    public static function greaterThanEq($value, $limit, $message = '')
+    {
+        if ($value < $limit) {
+            static::reportInvalidArgument(\sprintf(
+                $message ?: 'Expected a value greater than or equal to %2$s. Got: %s',
+                static::valueToString($value),
+                static::valueToString($limit)
+            ));
+        }
+    }
+
+    /**
+     * @psalm-pure
+     *
+     * @param mixed  $value
+     * @param mixed  $limit
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     */
+    public static function lessThan($value, $limit, $message = '')
+    {
+        if ($value >= $limit) {
+            static::reportInvalidArgument(\sprintf(
+                $message ?: 'Expected a value less than %2$s. Got: %s',
+                static::valueToString($value),
+                static::valueToString($limit)
+            ));
+        }
+    }
+
+    /**
+     * @psalm-pure
+     *
+     * @param mixed  $value
+     * @param mixed  $limit
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     */
+    public static function lessThanEq($value, $limit, $message = '')
+    {
+        if ($value > $limit) {
+            static::reportInvalidArgument(\sprintf(
+                $message ?: 'Expected a value less than or equal to %2$s. Got: %s',
+                static::valueToString($value),
+                static::valueToString($limit)
+            ));
+        }
+    }
+
+    /**
+     * Inclusive range, so Assert::(3, 3, 5) passes.
+     *
+     * @psalm-pure
+     *
+     * @param mixed  $value
+     * @param mixed  $min
+     * @param mixed  $max
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     */
+    public static function range($value, $min, $max, $message = '')
+    {
+        if ($value < $min || $value > $max) {
+            static::reportInvalidArgument(\sprintf(
+                $message ?: 'Expected a value between %2$s and %3$s. Got: %s',
+                static::valueToString($value),
+                static::valueToString($min),
+                static::valueToString($max)
+            ));
+        }
+    }
+
+    /**
+     * A more human-readable alias of Assert::inArray().
+     *
+     * @psalm-pure
+     *
+     * @param mixed  $value
+     * @param array  $values
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     */
+    public static function oneOf($value, array $values, $message = '')
+    {
+        static::inArray($value, $values, $message);
+    }
+
+    /**
+     * Does strict comparison, so Assert::inArray(3, ['3']) does not pass the assertion.
+     *
+     * @psalm-pure
+     *
+     * @param mixed  $value
+     * @param array  $values
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     */
+    public static function inArray($value, array $values, $message = '')
+    {
+        if (!\in_array($value, $values, true)) {
+            static::reportInvalidArgument(\sprintf(
+                $message ?: 'Expected one of: %2$s. Got: %s',
+                static::valueToString($value),
+                \implode(', ', \array_map(array('static', 'valueToString'), $values))
+            ));
+        }
+    }
+
+    /**
+     * @psalm-pure
+     *
+     * @param string $value
+     * @param string $subString
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     */
+    public static function contains($value, $subString, $message = '')
+    {
+        if (false === \strpos($value, $subString)) {
+            static::reportInvalidArgument(\sprintf(
+                $message ?: 'Expected a value to contain %2$s. Got: %s',
+                static::valueToString($value),
+                static::valueToString($subString)
+            ));
+        }
+    }
+
+    /**
+     * @psalm-pure
+     *
+     * @param string $value
+     * @param string $subString
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     */
+    public static function notContains($value, $subString, $message = '')
+    {
+        if (false !== \strpos($value, $subString)) {
+            static::reportInvalidArgument(\sprintf(
+                $message ?: '%2$s was not expected to be contained in a value. Got: %s',
+                static::valueToString($value),
+                static::valueToString($subString)
+            ));
+        }
+    }
+
+    /**
+     * @psalm-pure
+     *
+     * @param string $value
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     */
+    public static function notWhitespaceOnly($value, $message = '')
+    {
+        if (\preg_match('/^\s*$/', $value)) {
+            static::reportInvalidArgument(\sprintf(
+                $message ?: 'Expected a non-whitespace string. Got: %s',
+                static::valueToString($value)
+            ));
+        }
+    }
+
+    /**
+     * @psalm-pure
+     *
+     * @param string $value
+     * @param string $prefix
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     */
+    public static function startsWith($value, $prefix, $message = '')
+    {
+        if (0 !== \strpos($value, $prefix)) {
+            static::reportInvalidArgument(\sprintf(
+                $message ?: 'Expected a value to start with %2$s. Got: %s',
+                static::valueToString($value),
+                static::valueToString($prefix)
+            ));
+        }
+    }
+
+    /**
+     * @psalm-pure
+     *
+     * @param string $value
+     * @param string $prefix
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     */
+    public static function notStartsWith($value, $prefix, $message = '')
+    {
+        if (0 === \strpos($value, $prefix)) {
+            static::reportInvalidArgument(\sprintf(
+                $message ?: 'Expected a value not to start with %2$s. Got: %s',
+                static::valueToString($value),
+                static::valueToString($prefix)
+            ));
+        }
+    }
+
+    /**
+     * @psalm-pure
+     *
+     * @param mixed  $value
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     */
+    public static function startsWithLetter($value, $message = '')
+    {
+        static::string($value);
+
+        $valid = isset($value[0]);
+
+        if ($valid) {
+            $locale = \setlocale(LC_CTYPE, 0);
+            \setlocale(LC_CTYPE, 'C');
+            $valid = \ctype_alpha($value[0]);
+            \setlocale(LC_CTYPE, $locale);
+        }
+
+        if (!$valid) {
+            static::reportInvalidArgument(\sprintf(
+                $message ?: 'Expected a value to start with a letter. Got: %s',
+                static::valueToString($value)
+            ));
+        }
+    }
+
+    /**
+     * @psalm-pure
+     *
+     * @param string $value
+     * @param string $suffix
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     */
+    public static function endsWith($value, $suffix, $message = '')
+    {
+        if ($suffix !== \substr($value, -\strlen($suffix))) {
+            static::reportInvalidArgument(\sprintf(
+                $message ?: 'Expected a value to end with %2$s. Got: %s',
+                static::valueToString($value),
+                static::valueToString($suffix)
+            ));
+        }
+    }
+
+    /**
+     * @psalm-pure
+     *
+     * @param string $value
+     * @param string $suffix
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     */
+    public static function notEndsWith($value, $suffix, $message = '')
+    {
+        if ($suffix === \substr($value, -\strlen($suffix))) {
+            static::reportInvalidArgument(\sprintf(
+                $message ?: 'Expected a value not to end with %2$s. Got: %s',
+                static::valueToString($value),
+                static::valueToString($suffix)
+            ));
+        }
+    }
+
+    /**
+     * @psalm-pure
+     *
+     * @param string $value
+     * @param string $pattern
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     */
+    public static function regex($value, $pattern, $message = '')
+    {
+        if (!\preg_match($pattern, $value)) {
+            static::reportInvalidArgument(\sprintf(
+                $message ?: 'The value %s does not match the expected pattern.',
+                static::valueToString($value)
+            ));
+        }
+    }
+
+    /**
+     * @psalm-pure
+     *
+     * @param string $value
+     * @param string $pattern
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     */
+    public static function notRegex($value, $pattern, $message = '')
+    {
+        if (\preg_match($pattern, $value, $matches, PREG_OFFSET_CAPTURE)) {
+            static::reportInvalidArgument(\sprintf(
+                $message ?: 'The value %s matches the pattern %s (at offset %d).',
+                static::valueToString($value),
+                static::valueToString($pattern),
+                $matches[0][1]
+            ));
+        }
+    }
+
+    /**
+     * @psalm-pure
+     *
+     * @param mixed  $value
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     */
+    public static function unicodeLetters($value, $message = '')
+    {
+        static::string($value);
+
+        if (!\preg_match('/^\p{L}+$/u', $value)) {
+            static::reportInvalidArgument(\sprintf(
+                $message ?: 'Expected a value to contain only Unicode letters. Got: %s',
+                static::valueToString($value)
+            ));
+        }
+    }
+
+    /**
+     * @psalm-pure
+     *
+     * @param mixed  $value
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     */
+    public static function alpha($value, $message = '')
+    {
+        static::string($value);
+
+        $locale = \setlocale(LC_CTYPE, 0);
+        \setlocale(LC_CTYPE, 'C');
+        $valid = !\ctype_alpha($value);
+        \setlocale(LC_CTYPE, $locale);
+
+        if ($valid) {
+            static::reportInvalidArgument(\sprintf(
+                $message ?: 'Expected a value to contain only letters. Got: %s',
+                static::valueToString($value)
+            ));
+        }
+    }
+
+    /**
+     * @psalm-pure
+     *
+     * @param string $value
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     */
+    public static function digits($value, $message = '')
+    {
+        $locale = \setlocale(LC_CTYPE, 0);
+        \setlocale(LC_CTYPE, 'C');
+        $valid = !\ctype_digit($value);
+        \setlocale(LC_CTYPE, $locale);
+
+        if ($valid) {
+            static::reportInvalidArgument(\sprintf(
+                $message ?: 'Expected a value to contain digits only. Got: %s',
+                static::valueToString($value)
+            ));
+        }
+    }
+
+    /**
+     * @psalm-pure
+     *
+     * @param string $value
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     */
+    public static function alnum($value, $message = '')
+    {
+        $locale = \setlocale(LC_CTYPE, 0);
+        \setlocale(LC_CTYPE, 'C');
+        $valid = !\ctype_alnum($value);
+        \setlocale(LC_CTYPE, $locale);
+
+        if ($valid) {
+            static::reportInvalidArgument(\sprintf(
+                $message ?: 'Expected a value to contain letters and digits only. Got: %s',
+                static::valueToString($value)
+            ));
+        }
+    }
+
+    /**
+     * @psalm-pure
+     * @psalm-assert lowercase-string $value
+     *
+     * @param string $value
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     */
+    public static function lower($value, $message = '')
+    {
+        $locale = \setlocale(LC_CTYPE, 0);
+        \setlocale(LC_CTYPE, 'C');
+        $valid = !\ctype_lower($value);
+        \setlocale(LC_CTYPE, $locale);
+
+        if ($valid) {
+            static::reportInvalidArgument(\sprintf(
+                $message ?: 'Expected a value to contain lowercase characters only. Got: %s',
+                static::valueToString($value)
+            ));
+        }
+    }
+
+    /**
+     * @psalm-pure
+     * @psalm-assert !lowercase-string $value
+     *
+     * @param string $value
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     */
+    public static function upper($value, $message = '')
+    {
+        $locale = \setlocale(LC_CTYPE, 0);
+        \setlocale(LC_CTYPE, 'C');
+        $valid = !\ctype_upper($value);
+        \setlocale(LC_CTYPE, $locale);
+
+        if ($valid) {
+            static::reportInvalidArgument(\sprintf(
+                $message ?: 'Expected a value to contain uppercase characters only. Got: %s',
+                static::valueToString($value)
+            ));
+        }
+    }
+
+    /**
+     * @psalm-pure
+     *
+     * @param string $value
+     * @param int    $length
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     */
+    public static function length($value, $length, $message = '')
+    {
+        if ($length !== static::strlen($value)) {
+            static::reportInvalidArgument(\sprintf(
+                $message ?: 'Expected a value to contain %2$s characters. Got: %s',
+                static::valueToString($value),
+                $length
+            ));
+        }
+    }
+
+    /**
+     * Inclusive min.
+     *
+     * @psalm-pure
+     *
+     * @param string    $value
+     * @param int|float $min
+     * @param string    $message
+     *
+     * @throws InvalidArgumentException
+     */
+    public static function minLength($value, $min, $message = '')
+    {
+        if (static::strlen($value) < $min) {
+            static::reportInvalidArgument(\sprintf(
+                $message ?: 'Expected a value to contain at least %2$s characters. Got: %s',
+                static::valueToString($value),
+                $min
+            ));
+        }
+    }
+
+    /**
+     * Inclusive max.
+     *
+     * @psalm-pure
+     *
+     * @param string    $value
+     * @param int|float $max
+     * @param string    $message
+     *
+     * @throws InvalidArgumentException
+     */
+    public static function maxLength($value, $max, $message = '')
+    {
+        if (static::strlen($value) > $max) {
+            static::reportInvalidArgument(\sprintf(
+                $message ?: 'Expected a value to contain at most %2$s characters. Got: %s',
+                static::valueToString($value),
+                $max
+            ));
+        }
+    }
+
+    /**
+     * Inclusive , so Assert::lengthBetween('asd', 3, 5); passes the assertion.
+     *
+     * @psalm-pure
+     *
+     * @param string    $value
+     * @param int|float $min
+     * @param int|float $max
+     * @param string    $message
+     *
+     * @throws InvalidArgumentException
+     */
+    public static function lengthBetween($value, $min, $max, $message = '')
+    {
+        $length = static::strlen($value);
+
+        if ($length < $min || $length > $max) {
+            static::reportInvalidArgument(\sprintf(
+                $message ?: 'Expected a value to contain between %2$s and %3$s characters. Got: %s',
+                static::valueToString($value),
+                $min,
+                $max
+            ));
+        }
+    }
+
+    /**
+     * Will also pass if $value is a directory, use Assert::file() instead if you need to be sure it is a file.
+     *
+     * @param mixed  $value
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     */
+    public static function fileExists($value, $message = '')
+    {
+        static::string($value);
+
+        if (!\file_exists($value)) {
+            static::reportInvalidArgument(\sprintf(
+                $message ?: 'The file %s does not exist.',
+                static::valueToString($value)
+            ));
+        }
+    }
+
+    /**
+     * @param mixed  $value
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     */
+    public static function file($value, $message = '')
+    {
+        static::fileExists($value, $message);
+
+        if (!\is_file($value)) {
+            static::reportInvalidArgument(\sprintf(
+                $message ?: 'The path %s is not a file.',
+                static::valueToString($value)
+            ));
+        }
+    }
+
+    /**
+     * @param mixed  $value
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     */
+    public static function directory($value, $message = '')
+    {
+        static::fileExists($value, $message);
+
+        if (!\is_dir($value)) {
+            static::reportInvalidArgument(\sprintf(
+                $message ?: 'The path %s is no directory.',
+                static::valueToString($value)
+            ));
+        }
+    }
+
+    /**
+     * @param string $value
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     */
+    public static function readable($value, $message = '')
+    {
+        if (!\is_readable($value)) {
+            static::reportInvalidArgument(\sprintf(
+                $message ?: 'The path %s is not readable.',
+                static::valueToString($value)
+            ));
+        }
+    }
+
+    /**
+     * @param string $value
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     */
+    public static function writable($value, $message = '')
+    {
+        if (!\is_writable($value)) {
+            static::reportInvalidArgument(\sprintf(
+                $message ?: 'The path %s is not writable.',
+                static::valueToString($value)
+            ));
+        }
+    }
+
+    /**
+     * @psalm-assert class-string $value
+     *
+     * @param mixed  $value
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     */
+    public static function classExists($value, $message = '')
+    {
+        if (!\class_exists($value)) {
+            static::reportInvalidArgument(\sprintf(
+                $message ?: 'Expected an existing class name. Got: %s',
+                static::valueToString($value)
+            ));
+        }
+    }
+
+    /**
+     * @psalm-pure
+     * @psalm-template ExpectedType of object
+     * @psalm-param class-string<ExpectedType> $class
+     * @psalm-assert class-string<ExpectedType>|ExpectedType $value
+     *
+     * @param mixed         $value
+     * @param string|object $class
+     * @param string        $message
+     *
+     * @throws InvalidArgumentException
+     */
+    public static function subclassOf($value, $class, $message = '')
+    {
+        if (!\is_subclass_of($value, $class)) {
+            static::reportInvalidArgument(\sprintf(
+                $message ?: 'Expected a sub-class of %2$s. Got: %s',
+                static::valueToString($value),
+                static::valueToString($class)
+            ));
+        }
+    }
+
+    /**
+     * @psalm-assert class-string $value
+     *
+     * @param mixed  $value
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     */
+    public static function interfaceExists($value, $message = '')
+    {
+        if (!\interface_exists($value)) {
+            static::reportInvalidArgument(\sprintf(
+                $message ?: 'Expected an existing interface name. got %s',
+                static::valueToString($value)
+            ));
+        }
+    }
+
+    /**
+     * @psalm-pure
+     * @psalm-template ExpectedType of object
+     * @psalm-param class-string<ExpectedType> $interface
+     * @psalm-assert class-string<ExpectedType> $value
+     *
+     * @param mixed  $value
+     * @param mixed  $interface
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     */
+    public static function implementsInterface($value, $interface, $message = '')
+    {
+        if (!\in_array($interface, \class_implements($value))) {
+            static::reportInvalidArgument(\sprintf(
+                $message ?: 'Expected an implementation of %2$s. Got: %s',
+                static::valueToString($value),
+                static::valueToString($interface)
+            ));
+        }
+    }
+
+    /**
+     * @psalm-pure
+     * @psalm-param class-string|object $classOrObject
+     *
+     * @param string|object $classOrObject
+     * @param mixed         $property
+     * @param string        $message
+     *
+     * @throws InvalidArgumentException
+     */
+    public static function propertyExists($classOrObject, $property, $message = '')
+    {
+        if (!\property_exists($classOrObject, $property)) {
+            static::reportInvalidArgument(\sprintf(
+                $message ?: 'Expected the property %s to exist.',
+                static::valueToString($property)
+            ));
+        }
+    }
+
+    /**
+     * @psalm-pure
+     * @psalm-param class-string|object $classOrObject
+     *
+     * @param string|object $classOrObject
+     * @param mixed         $property
+     * @param string        $message
+     *
+     * @throws InvalidArgumentException
+     */
+    public static function propertyNotExists($classOrObject, $property, $message = '')
+    {
+        if (\property_exists($classOrObject, $property)) {
+            static::reportInvalidArgument(\sprintf(
+                $message ?: 'Expected the property %s to not exist.',
+                static::valueToString($property)
+            ));
+        }
+    }
+
+    /**
+     * @psalm-pure
+     * @psalm-param class-string|object $classOrObject
+     *
+     * @param string|object $classOrObject
+     * @param mixed         $method
+     * @param string        $message
+     *
+     * @throws InvalidArgumentException
+     */
+    public static function methodExists($classOrObject, $method, $message = '')
+    {
+        if (!(\is_string($classOrObject) || \is_object($classOrObject)) || !\method_exists($classOrObject, $method)) {
+            static::reportInvalidArgument(\sprintf(
+                $message ?: 'Expected the method %s to exist.',
+                static::valueToString($method)
+            ));
+        }
+    }
+
+    /**
+     * @psalm-pure
+     * @psalm-param class-string|object $classOrObject
+     *
+     * @param string|object $classOrObject
+     * @param mixed         $method
+     * @param string        $message
+     *
+     * @throws InvalidArgumentException
+     */
+    public static function methodNotExists($classOrObject, $method, $message = '')
+    {
+        if ((\is_string($classOrObject) || \is_object($classOrObject)) && \method_exists($classOrObject, $method)) {
+            static::reportInvalidArgument(\sprintf(
+                $message ?: 'Expected the method %s to not exist.',
+                static::valueToString($method)
+            ));
+        }
+    }
+
+    /**
+     * @psalm-pure
+     *
+     * @param array      $array
+     * @param string|int $key
+     * @param string     $message
+     *
+     * @throws InvalidArgumentException
+     */
+    public static function keyExists($array, $key, $message = '')
+    {
+        if (!(isset($array[$key]) || \array_key_exists($key, $array))) {
+            static::reportInvalidArgument(\sprintf(
+                $message ?: 'Expected the key %s to exist.',
+                static::valueToString($key)
+            ));
+        }
+    }
+
+    /**
+     * @psalm-pure
+     *
+     * @param array      $array
+     * @param string|int $key
+     * @param string     $message
+     *
+     * @throws InvalidArgumentException
+     */
+    public static function keyNotExists($array, $key, $message = '')
+    {
+        if (isset($array[$key]) || \array_key_exists($key, $array)) {
+            static::reportInvalidArgument(\sprintf(
+                $message ?: 'Expected the key %s to not exist.',
+                static::valueToString($key)
+            ));
+        }
+    }
+
+    /**
+     * Checks if a value is a valid array key (int or string).
+     *
+     * @psalm-pure
+     * @psalm-assert array-key $value
+     *
+     * @param mixed  $value
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     */
+    public static function validArrayKey($value, $message = '')
+    {
+        if (!(\is_int($value) || \is_string($value))) {
+            static::reportInvalidArgument(\sprintf(
+                $message ?: 'Expected string or integer. Got: %s',
+                static::typeToString($value)
+            ));
+        }
+    }
+
+    /**
+     * Does not check if $array is countable, this can generate a warning on php versions after 7.2.
+     *
+     * @param Countable|array $array
+     * @param int             $number
+     * @param string          $message
+     *
+     * @throws InvalidArgumentException
+     */
+    public static function count($array, $number, $message = '')
+    {
+        static::eq(
+            \count($array),
+            $number,
+            \sprintf(
+                $message ?: 'Expected an array to contain %d elements. Got: %d.',
+                $number,
+                \count($array)
+            )
+        );
+    }
+
+    /**
+     * Does not check if $array is countable, this can generate a warning on php versions after 7.2.
+     *
+     * @param Countable|array $array
+     * @param int|float       $min
+     * @param string          $message
+     *
+     * @throws InvalidArgumentException
+     */
+    public static function minCount($array, $min, $message = '')
+    {
+        if (\count($array) < $min) {
+            static::reportInvalidArgument(\sprintf(
+                $message ?: 'Expected an array to contain at least %2$d elements. Got: %d',
+                \count($array),
+                $min
+            ));
+        }
+    }
+
+    /**
+     * Does not check if $array is countable, this can generate a warning on php versions after 7.2.
+     *
+     * @param Countable|array $array
+     * @param int|float       $max
+     * @param string          $message
+     *
+     * @throws InvalidArgumentException
+     */
+    public static function maxCount($array, $max, $message = '')
+    {
+        if (\count($array) > $max) {
+            static::reportInvalidArgument(\sprintf(
+                $message ?: 'Expected an array to contain at most %2$d elements. Got: %d',
+                \count($array),
+                $max
+            ));
+        }
+    }
+
+    /**
+     * Does not check if $array is countable, this can generate a warning on php versions after 7.2.
+     *
+     * @param Countable|array $array
+     * @param int|float       $min
+     * @param int|float       $max
+     * @param string          $message
+     *
+     * @throws InvalidArgumentException
+     */
+    public static function countBetween($array, $min, $max, $message = '')
+    {
+        $count = \count($array);
+
+        if ($count < $min || $count > $max) {
+            static::reportInvalidArgument(\sprintf(
+                $message ?: 'Expected an array to contain between %2$d and %3$d elements. Got: %d',
+                $count,
+                $min,
+                $max
+            ));
+        }
+    }
+
+    /**
+     * @psalm-pure
+     * @psalm-assert list $array
+     *
+     * @param mixed  $array
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     */
+    public static function isList($array, $message = '')
+    {
+        if (!\is_array($array) || $array !== \array_values($array)) {
+            static::reportInvalidArgument(
+                $message ?: 'Expected list - non-associative array.'
+            );
+        }
+    }
+
+    /**
+     * @psalm-pure
+     * @psalm-assert non-empty-list $array
+     *
+     * @param mixed  $array
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     */
+    public static function isNonEmptyList($array, $message = '')
+    {
+        static::isList($array, $message);
+        static::notEmpty($array, $message);
+    }
+
+    /**
+     * @psalm-pure
+     * @psalm-template T
+     * @psalm-param mixed|array<T> $array
+     * @psalm-assert array<string, T> $array
+     *
+     * @param mixed  $array
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     */
+    public static function isMap($array, $message = '')
+    {
+        if (
+            !\is_array($array) ||
+            \array_keys($array) !== \array_filter(\array_keys($array), '\is_string')
+        ) {
+            static::reportInvalidArgument(
+                $message ?: 'Expected map - associative array with string keys.'
+            );
+        }
+    }
+
+    /**
+     * @psalm-pure
+     * @psalm-template T
+     * @psalm-param mixed|array<T> $array
+     * @psalm-assert array<string, T> $array
+     * @psalm-assert !empty $array
+     *
+     * @param mixed  $array
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     */
+    public static function isNonEmptyMap($array, $message = '')
+    {
+        static::isMap($array, $message);
+        static::notEmpty($array, $message);
+    }
+
+    /**
+     * @psalm-pure
+     *
+     * @param string $value
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     */
+    public static function uuid($value, $message = '')
+    {
+        $value = \str_replace(array('urn:', 'uuid:', '{', '}'), '', $value);
+
+        // The nil UUID is special form of UUID that is specified to have all
+        // 128 bits set to zero.
+        if ('00000000-0000-0000-0000-000000000000' === $value) {
+            return;
+        }
+
+        if (!\preg_match('/^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{12}$/', $value)) {
+            static::reportInvalidArgument(\sprintf(
+                $message ?: 'Value %s is not a valid UUID.',
+                static::valueToString($value)
+            ));
+        }
+    }
+
+    /**
+     * @psalm-param class-string<Throwable> $class
+     *
+     * @param Closure $expression
+     * @param string  $class
+     * @param string  $message
+     *
+     * @throws InvalidArgumentException
+     */
+    public static function throws(Closure $expression, $class = 'Exception', $message = '')
+    {
+        static::string($class);
+
+        $actual = 'none';
+
+        try {
+            $expression();
+        } catch (Exception $e) {
+            $actual = \get_class($e);
+            if ($e instanceof $class) {
+                return;
+            }
+        } catch (Throwable $e) {
+            $actual = \get_class($e);
+            if ($e instanceof $class) {
+                return;
+            }
+        }
+
+        static::reportInvalidArgument($message ?: \sprintf(
+            'Expected to throw "%s", got "%s"',
+            $class,
+            $actual
+        ));
+    }
+
+    /**
+     * @throws BadMethodCallException
+     */
+    public static function __callStatic($name, $arguments)
+    {
+        if ('nullOr' === \substr($name, 0, 6)) {
+            if (null !== $arguments[0]) {
+                $method = \lcfirst(\substr($name, 6));
+                \call_user_func_array(array('static', $method), $arguments);
+            }
+
+            return;
+        }
+
+        if ('all' === \substr($name, 0, 3)) {
+            static::isIterable($arguments[0]);
+
+            $method = \lcfirst(\substr($name, 3));
+            $args = $arguments;
+
+            foreach ($arguments[0] as $entry) {
+                $args[0] = $entry;
+
+                \call_user_func_array(array('static', $method), $args);
+            }
+
+            return;
+        }
+
+        throw new BadMethodCallException('No such method: '.$name);
+    }
+
+    /**
+     * @param mixed $value
+     *
+     * @return string
+     */
+    protected static function valueToString($value)
+    {
+        if (null === $value) {
+            return 'null';
+        }
+
+        if (true === $value) {
+            return 'true';
+        }
+
+        if (false === $value) {
+            return 'false';
+        }
+
+        if (\is_array($value)) {
+            return 'array';
+        }
+
+        if (\is_object($value)) {
+            if (\method_exists($value, '__toString')) {
+                return \get_class($value).': '.self::valueToString($value->__toString());
+            }
+
+            if ($value instanceof DateTime || $value instanceof DateTimeImmutable) {
+                return \get_class($value).': '.self::valueToString($value->format('c'));
+            }
+
+            return \get_class($value);
+        }
+
+        if (\is_resource($value)) {
+            return 'resource';
+        }
+
+        if (\is_string($value)) {
+            return '"'.$value.'"';
+        }
+
+        return (string) $value;
+    }
+
+    /**
+     * @param mixed $value
+     *
+     * @return string
+     */
+    protected static function typeToString($value)
+    {
+        return \is_object($value) ? \get_class($value) : \gettype($value);
+    }
+
+    protected static function strlen($value)
+    {
+        if (!\function_exists('mb_detect_encoding')) {
+            return \strlen($value);
+        }
+
+        if (false === $encoding = \mb_detect_encoding($value)) {
+            return \strlen($value);
+        }
+
+        return \mb_strlen($value, $encoding);
+    }
+
+    /**
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @psalm-pure this method is not supposed to perform side-effects
+     */
+    protected static function reportInvalidArgument($message)
+    {
+        throw new InvalidArgumentException($message);
+    }
+
+    private function __construct()
+    {
+    }
+}
diff --git a/vendor/webmozart/assert/src/InvalidArgumentException.php b/vendor/webmozart/assert/src/InvalidArgumentException.php
new file mode 100644
index 0000000000000000000000000000000000000000..9d95a58c50061c6bab033016c8c04d974c2fc4f1
--- /dev/null
+++ b/vendor/webmozart/assert/src/InvalidArgumentException.php
@@ -0,0 +1,16 @@
+<?php
+
+/*
+ * This file is part of the webmozart/assert package.
+ *
+ * (c) Bernhard Schussek <bschussek@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Webmozart\Assert;
+
+class InvalidArgumentException extends \InvalidArgumentException
+{
+}
diff --git a/vendor/webmozart/assert/src/Mixin.php b/vendor/webmozart/assert/src/Mixin.php
new file mode 100644
index 0000000000000000000000000000000000000000..5e98823d40d2d273a5207cfb482b62076c361359
--- /dev/null
+++ b/vendor/webmozart/assert/src/Mixin.php
@@ -0,0 +1,2916 @@
+<?php
+
+/**
+ * provides type inference and auto-completion for magic static methods of Assert.
+ */
+
+namespace Webmozart\Assert;
+
+use ArrayAccess;
+use Closure;
+use Countable;
+use Throwable;
+
+/**
+ * This trait aids static analysis tooling in introspecting assertion magic methods.
+ * Do not use this trait directly: it will change, and is not designed for reuse.
+ */
+trait Mixin
+{
+    /**
+     * @psalm-pure
+     * @psalm-assert string|null $value
+     *
+     * @param mixed  $value
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function nullOrString($value, $message = '')
+    {
+        static::__callStatic('nullOrString', array($value, $message));
+    }
+
+    /**
+     * @psalm-pure
+     * @psalm-assert iterable<string> $value
+     *
+     * @param mixed  $value
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function allString($value, $message = '')
+    {
+        static::__callStatic('allString', array($value, $message));
+    }
+
+    /**
+     * @psalm-pure
+     * @psalm-assert non-empty-string|null $value
+     *
+     * @param mixed  $value
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function nullOrStringNotEmpty($value, $message = '')
+    {
+        static::__callStatic('nullOrStringNotEmpty', array($value, $message));
+    }
+
+    /**
+     * @psalm-pure
+     * @psalm-assert iterable<non-empty-string> $value
+     *
+     * @param mixed  $value
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function allStringNotEmpty($value, $message = '')
+    {
+        static::__callStatic('allStringNotEmpty', array($value, $message));
+    }
+
+    /**
+     * @psalm-pure
+     * @psalm-assert int|null $value
+     *
+     * @param mixed  $value
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function nullOrInteger($value, $message = '')
+    {
+        static::__callStatic('nullOrInteger', array($value, $message));
+    }
+
+    /**
+     * @psalm-pure
+     * @psalm-assert iterable<int> $value
+     *
+     * @param mixed  $value
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function allInteger($value, $message = '')
+    {
+        static::__callStatic('allInteger', array($value, $message));
+    }
+
+    /**
+     * @psalm-pure
+     * @psalm-assert numeric|null $value
+     *
+     * @param mixed  $value
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function nullOrIntegerish($value, $message = '')
+    {
+        static::__callStatic('nullOrIntegerish', array($value, $message));
+    }
+
+    /**
+     * @psalm-pure
+     * @psalm-assert iterable<numeric> $value
+     *
+     * @param mixed  $value
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function allIntegerish($value, $message = '')
+    {
+        static::__callStatic('allIntegerish', array($value, $message));
+    }
+
+    /**
+     * @psalm-pure
+     * @psalm-assert positive-int|null $value
+     *
+     * @param mixed  $value
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function nullOrPositiveInteger($value, $message = '')
+    {
+        static::__callStatic('nullOrPositiveInteger', array($value, $message));
+    }
+
+    /**
+     * @psalm-pure
+     * @psalm-assert iterable<positive-int> $value
+     *
+     * @param mixed  $value
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function allPositiveInteger($value, $message = '')
+    {
+        static::__callStatic('allPositiveInteger', array($value, $message));
+    }
+
+    /**
+     * @psalm-pure
+     * @psalm-assert float|null $value
+     *
+     * @param mixed  $value
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function nullOrFloat($value, $message = '')
+    {
+        static::__callStatic('nullOrFloat', array($value, $message));
+    }
+
+    /**
+     * @psalm-pure
+     * @psalm-assert iterable<float> $value
+     *
+     * @param mixed  $value
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function allFloat($value, $message = '')
+    {
+        static::__callStatic('allFloat', array($value, $message));
+    }
+
+    /**
+     * @psalm-pure
+     * @psalm-assert numeric|null $value
+     *
+     * @param mixed  $value
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function nullOrNumeric($value, $message = '')
+    {
+        static::__callStatic('nullOrNumeric', array($value, $message));
+    }
+
+    /**
+     * @psalm-pure
+     * @psalm-assert iterable<numeric> $value
+     *
+     * @param mixed  $value
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function allNumeric($value, $message = '')
+    {
+        static::__callStatic('allNumeric', array($value, $message));
+    }
+
+    /**
+     * @psalm-pure
+     * @psalm-assert positive-int|0|null $value
+     *
+     * @param mixed  $value
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function nullOrNatural($value, $message = '')
+    {
+        static::__callStatic('nullOrNatural', array($value, $message));
+    }
+
+    /**
+     * @psalm-pure
+     * @psalm-assert iterable<positive-int|0> $value
+     *
+     * @param mixed  $value
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function allNatural($value, $message = '')
+    {
+        static::__callStatic('allNatural', array($value, $message));
+    }
+
+    /**
+     * @psalm-pure
+     * @psalm-assert bool|null $value
+     *
+     * @param mixed  $value
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function nullOrBoolean($value, $message = '')
+    {
+        static::__callStatic('nullOrBoolean', array($value, $message));
+    }
+
+    /**
+     * @psalm-pure
+     * @psalm-assert iterable<bool> $value
+     *
+     * @param mixed  $value
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function allBoolean($value, $message = '')
+    {
+        static::__callStatic('allBoolean', array($value, $message));
+    }
+
+    /**
+     * @psalm-pure
+     * @psalm-assert scalar|null $value
+     *
+     * @param mixed  $value
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function nullOrScalar($value, $message = '')
+    {
+        static::__callStatic('nullOrScalar', array($value, $message));
+    }
+
+    /**
+     * @psalm-pure
+     * @psalm-assert iterable<scalar> $value
+     *
+     * @param mixed  $value
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function allScalar($value, $message = '')
+    {
+        static::__callStatic('allScalar', array($value, $message));
+    }
+
+    /**
+     * @psalm-pure
+     * @psalm-assert object|null $value
+     *
+     * @param mixed  $value
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function nullOrObject($value, $message = '')
+    {
+        static::__callStatic('nullOrObject', array($value, $message));
+    }
+
+    /**
+     * @psalm-pure
+     * @psalm-assert iterable<object> $value
+     *
+     * @param mixed  $value
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function allObject($value, $message = '')
+    {
+        static::__callStatic('allObject', array($value, $message));
+    }
+
+    /**
+     * @psalm-pure
+     * @psalm-assert resource|null $value
+     *
+     * @param mixed       $value
+     * @param string|null $type    type of resource this should be. @see https://www.php.net/manual/en/function.get-resource-type.php
+     * @param string      $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function nullOrResource($value, $type = null, $message = '')
+    {
+        static::__callStatic('nullOrResource', array($value, $type, $message));
+    }
+
+    /**
+     * @psalm-pure
+     * @psalm-assert iterable<resource> $value
+     *
+     * @param mixed       $value
+     * @param string|null $type    type of resource this should be. @see https://www.php.net/manual/en/function.get-resource-type.php
+     * @param string      $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function allResource($value, $type = null, $message = '')
+    {
+        static::__callStatic('allResource', array($value, $type, $message));
+    }
+
+    /**
+     * @psalm-pure
+     * @psalm-assert callable|null $value
+     *
+     * @param mixed  $value
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function nullOrIsCallable($value, $message = '')
+    {
+        static::__callStatic('nullOrIsCallable', array($value, $message));
+    }
+
+    /**
+     * @psalm-pure
+     * @psalm-assert iterable<callable> $value
+     *
+     * @param mixed  $value
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function allIsCallable($value, $message = '')
+    {
+        static::__callStatic('allIsCallable', array($value, $message));
+    }
+
+    /**
+     * @psalm-pure
+     * @psalm-assert array|null $value
+     *
+     * @param mixed  $value
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function nullOrIsArray($value, $message = '')
+    {
+        static::__callStatic('nullOrIsArray', array($value, $message));
+    }
+
+    /**
+     * @psalm-pure
+     * @psalm-assert iterable<array> $value
+     *
+     * @param mixed  $value
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function allIsArray($value, $message = '')
+    {
+        static::__callStatic('allIsArray', array($value, $message));
+    }
+
+    /**
+     * @psalm-pure
+     * @psalm-assert iterable|null $value
+     *
+     * @deprecated use "isIterable" or "isInstanceOf" instead
+     *
+     * @param mixed  $value
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function nullOrIsTraversable($value, $message = '')
+    {
+        static::__callStatic('nullOrIsTraversable', array($value, $message));
+    }
+
+    /**
+     * @psalm-pure
+     * @psalm-assert iterable<iterable> $value
+     *
+     * @deprecated use "isIterable" or "isInstanceOf" instead
+     *
+     * @param mixed  $value
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function allIsTraversable($value, $message = '')
+    {
+        static::__callStatic('allIsTraversable', array($value, $message));
+    }
+
+    /**
+     * @psalm-pure
+     * @psalm-assert array|ArrayAccess|null $value
+     *
+     * @param mixed  $value
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function nullOrIsArrayAccessible($value, $message = '')
+    {
+        static::__callStatic('nullOrIsArrayAccessible', array($value, $message));
+    }
+
+    /**
+     * @psalm-pure
+     * @psalm-assert iterable<array|ArrayAccess> $value
+     *
+     * @param mixed  $value
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function allIsArrayAccessible($value, $message = '')
+    {
+        static::__callStatic('allIsArrayAccessible', array($value, $message));
+    }
+
+    /**
+     * @psalm-pure
+     * @psalm-assert countable|null $value
+     *
+     * @param mixed  $value
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function nullOrIsCountable($value, $message = '')
+    {
+        static::__callStatic('nullOrIsCountable', array($value, $message));
+    }
+
+    /**
+     * @psalm-pure
+     * @psalm-assert iterable<countable> $value
+     *
+     * @param mixed  $value
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function allIsCountable($value, $message = '')
+    {
+        static::__callStatic('allIsCountable', array($value, $message));
+    }
+
+    /**
+     * @psalm-pure
+     * @psalm-assert iterable|null $value
+     *
+     * @param mixed  $value
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function nullOrIsIterable($value, $message = '')
+    {
+        static::__callStatic('nullOrIsIterable', array($value, $message));
+    }
+
+    /**
+     * @psalm-pure
+     * @psalm-assert iterable<iterable> $value
+     *
+     * @param mixed  $value
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function allIsIterable($value, $message = '')
+    {
+        static::__callStatic('allIsIterable', array($value, $message));
+    }
+
+    /**
+     * @psalm-pure
+     * @psalm-template ExpectedType of object
+     * @psalm-param class-string<ExpectedType> $class
+     * @psalm-assert ExpectedType|null $value
+     *
+     * @param mixed         $value
+     * @param string|object $class
+     * @param string        $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function nullOrIsInstanceOf($value, $class, $message = '')
+    {
+        static::__callStatic('nullOrIsInstanceOf', array($value, $class, $message));
+    }
+
+    /**
+     * @psalm-pure
+     * @psalm-template ExpectedType of object
+     * @psalm-param class-string<ExpectedType> $class
+     * @psalm-assert iterable<ExpectedType> $value
+     *
+     * @param mixed         $value
+     * @param string|object $class
+     * @param string        $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function allIsInstanceOf($value, $class, $message = '')
+    {
+        static::__callStatic('allIsInstanceOf', array($value, $class, $message));
+    }
+
+    /**
+     * @psalm-pure
+     * @psalm-template ExpectedType of object
+     * @psalm-param class-string<ExpectedType> $class
+     *
+     * @param mixed         $value
+     * @param string|object $class
+     * @param string        $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function nullOrNotInstanceOf($value, $class, $message = '')
+    {
+        static::__callStatic('nullOrNotInstanceOf', array($value, $class, $message));
+    }
+
+    /**
+     * @psalm-pure
+     * @psalm-template ExpectedType of object
+     * @psalm-param class-string<ExpectedType> $class
+     *
+     * @param mixed         $value
+     * @param string|object $class
+     * @param string        $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function allNotInstanceOf($value, $class, $message = '')
+    {
+        static::__callStatic('allNotInstanceOf', array($value, $class, $message));
+    }
+
+    /**
+     * @psalm-pure
+     * @psalm-param array<class-string> $classes
+     *
+     * @param mixed                $value
+     * @param array<object|string> $classes
+     * @param string               $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function nullOrIsInstanceOfAny($value, $classes, $message = '')
+    {
+        static::__callStatic('nullOrIsInstanceOfAny', array($value, $classes, $message));
+    }
+
+    /**
+     * @psalm-pure
+     * @psalm-param array<class-string> $classes
+     *
+     * @param mixed                $value
+     * @param array<object|string> $classes
+     * @param string               $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function allIsInstanceOfAny($value, $classes, $message = '')
+    {
+        static::__callStatic('allIsInstanceOfAny', array($value, $classes, $message));
+    }
+
+    /**
+     * @psalm-pure
+     * @psalm-template ExpectedType of object
+     * @psalm-param class-string<ExpectedType> $class
+     * @psalm-assert ExpectedType|class-string<ExpectedType>|null $value
+     *
+     * @param object|string|null $value
+     * @param string             $class
+     * @param string             $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function nullOrIsAOf($value, $class, $message = '')
+    {
+        static::__callStatic('nullOrIsAOf', array($value, $class, $message));
+    }
+
+    /**
+     * @psalm-pure
+     * @psalm-template ExpectedType of object
+     * @psalm-param class-string<ExpectedType> $class
+     * @psalm-assert iterable<ExpectedType|class-string<ExpectedType>> $value
+     *
+     * @param iterable<object|string> $value
+     * @param string                  $class
+     * @param string                  $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function allIsAOf($value, $class, $message = '')
+    {
+        static::__callStatic('allIsAOf', array($value, $class, $message));
+    }
+
+    /**
+     * @psalm-pure
+     * @psalm-template UnexpectedType of object
+     * @psalm-param class-string<UnexpectedType> $class
+     *
+     * @param object|string|null $value
+     * @param string             $class
+     * @param string             $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function nullOrIsNotA($value, $class, $message = '')
+    {
+        static::__callStatic('nullOrIsNotA', array($value, $class, $message));
+    }
+
+    /**
+     * @psalm-pure
+     * @psalm-template UnexpectedType of object
+     * @psalm-param class-string<UnexpectedType> $class
+     *
+     * @param iterable<object|string> $value
+     * @param string                  $class
+     * @param string                  $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function allIsNotA($value, $class, $message = '')
+    {
+        static::__callStatic('allIsNotA', array($value, $class, $message));
+    }
+
+    /**
+     * @psalm-pure
+     * @psalm-param array<class-string> $classes
+     *
+     * @param object|string|null $value
+     * @param string[]           $classes
+     * @param string             $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function nullOrIsAnyOf($value, $classes, $message = '')
+    {
+        static::__callStatic('nullOrIsAnyOf', array($value, $classes, $message));
+    }
+
+    /**
+     * @psalm-pure
+     * @psalm-param array<class-string> $classes
+     *
+     * @param iterable<object|string> $value
+     * @param string[]                $classes
+     * @param string                  $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function allIsAnyOf($value, $classes, $message = '')
+    {
+        static::__callStatic('allIsAnyOf', array($value, $classes, $message));
+    }
+
+    /**
+     * @psalm-pure
+     * @psalm-assert empty $value
+     *
+     * @param mixed  $value
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function nullOrIsEmpty($value, $message = '')
+    {
+        static::__callStatic('nullOrIsEmpty', array($value, $message));
+    }
+
+    /**
+     * @psalm-pure
+     * @psalm-assert iterable<empty> $value
+     *
+     * @param mixed  $value
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function allIsEmpty($value, $message = '')
+    {
+        static::__callStatic('allIsEmpty', array($value, $message));
+    }
+
+    /**
+     * @psalm-pure
+     *
+     * @param mixed  $value
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function nullOrNotEmpty($value, $message = '')
+    {
+        static::__callStatic('nullOrNotEmpty', array($value, $message));
+    }
+
+    /**
+     * @psalm-pure
+     *
+     * @param mixed  $value
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function allNotEmpty($value, $message = '')
+    {
+        static::__callStatic('allNotEmpty', array($value, $message));
+    }
+
+    /**
+     * @psalm-pure
+     * @psalm-assert iterable<null> $value
+     *
+     * @param mixed  $value
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function allNull($value, $message = '')
+    {
+        static::__callStatic('allNull', array($value, $message));
+    }
+
+    /**
+     * @psalm-pure
+     *
+     * @param mixed  $value
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function allNotNull($value, $message = '')
+    {
+        static::__callStatic('allNotNull', array($value, $message));
+    }
+
+    /**
+     * @psalm-pure
+     * @psalm-assert true|null $value
+     *
+     * @param mixed  $value
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function nullOrTrue($value, $message = '')
+    {
+        static::__callStatic('nullOrTrue', array($value, $message));
+    }
+
+    /**
+     * @psalm-pure
+     * @psalm-assert iterable<true> $value
+     *
+     * @param mixed  $value
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function allTrue($value, $message = '')
+    {
+        static::__callStatic('allTrue', array($value, $message));
+    }
+
+    /**
+     * @psalm-pure
+     * @psalm-assert false|null $value
+     *
+     * @param mixed  $value
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function nullOrFalse($value, $message = '')
+    {
+        static::__callStatic('nullOrFalse', array($value, $message));
+    }
+
+    /**
+     * @psalm-pure
+     * @psalm-assert iterable<false> $value
+     *
+     * @param mixed  $value
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function allFalse($value, $message = '')
+    {
+        static::__callStatic('allFalse', array($value, $message));
+    }
+
+    /**
+     * @psalm-pure
+     *
+     * @param mixed  $value
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function nullOrNotFalse($value, $message = '')
+    {
+        static::__callStatic('nullOrNotFalse', array($value, $message));
+    }
+
+    /**
+     * @psalm-pure
+     *
+     * @param mixed  $value
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function allNotFalse($value, $message = '')
+    {
+        static::__callStatic('allNotFalse', array($value, $message));
+    }
+
+    /**
+     * @param mixed  $value
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function nullOrIp($value, $message = '')
+    {
+        static::__callStatic('nullOrIp', array($value, $message));
+    }
+
+    /**
+     * @param mixed  $value
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function allIp($value, $message = '')
+    {
+        static::__callStatic('allIp', array($value, $message));
+    }
+
+    /**
+     * @param mixed  $value
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function nullOrIpv4($value, $message = '')
+    {
+        static::__callStatic('nullOrIpv4', array($value, $message));
+    }
+
+    /**
+     * @param mixed  $value
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function allIpv4($value, $message = '')
+    {
+        static::__callStatic('allIpv4', array($value, $message));
+    }
+
+    /**
+     * @param mixed  $value
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function nullOrIpv6($value, $message = '')
+    {
+        static::__callStatic('nullOrIpv6', array($value, $message));
+    }
+
+    /**
+     * @param mixed  $value
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function allIpv6($value, $message = '')
+    {
+        static::__callStatic('allIpv6', array($value, $message));
+    }
+
+    /**
+     * @param mixed  $value
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function nullOrEmail($value, $message = '')
+    {
+        static::__callStatic('nullOrEmail', array($value, $message));
+    }
+
+    /**
+     * @param mixed  $value
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function allEmail($value, $message = '')
+    {
+        static::__callStatic('allEmail', array($value, $message));
+    }
+
+    /**
+     * @param array|null $values
+     * @param string     $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function nullOrUniqueValues($values, $message = '')
+    {
+        static::__callStatic('nullOrUniqueValues', array($values, $message));
+    }
+
+    /**
+     * @param iterable<array> $values
+     * @param string          $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function allUniqueValues($values, $message = '')
+    {
+        static::__callStatic('allUniqueValues', array($values, $message));
+    }
+
+    /**
+     * @param mixed  $value
+     * @param mixed  $expect
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function nullOrEq($value, $expect, $message = '')
+    {
+        static::__callStatic('nullOrEq', array($value, $expect, $message));
+    }
+
+    /**
+     * @param mixed  $value
+     * @param mixed  $expect
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function allEq($value, $expect, $message = '')
+    {
+        static::__callStatic('allEq', array($value, $expect, $message));
+    }
+
+    /**
+     * @param mixed  $value
+     * @param mixed  $expect
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function nullOrNotEq($value, $expect, $message = '')
+    {
+        static::__callStatic('nullOrNotEq', array($value, $expect, $message));
+    }
+
+    /**
+     * @param mixed  $value
+     * @param mixed  $expect
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function allNotEq($value, $expect, $message = '')
+    {
+        static::__callStatic('allNotEq', array($value, $expect, $message));
+    }
+
+    /**
+     * @psalm-pure
+     *
+     * @param mixed  $value
+     * @param mixed  $expect
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function nullOrSame($value, $expect, $message = '')
+    {
+        static::__callStatic('nullOrSame', array($value, $expect, $message));
+    }
+
+    /**
+     * @psalm-pure
+     *
+     * @param mixed  $value
+     * @param mixed  $expect
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function allSame($value, $expect, $message = '')
+    {
+        static::__callStatic('allSame', array($value, $expect, $message));
+    }
+
+    /**
+     * @psalm-pure
+     *
+     * @param mixed  $value
+     * @param mixed  $expect
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function nullOrNotSame($value, $expect, $message = '')
+    {
+        static::__callStatic('nullOrNotSame', array($value, $expect, $message));
+    }
+
+    /**
+     * @psalm-pure
+     *
+     * @param mixed  $value
+     * @param mixed  $expect
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function allNotSame($value, $expect, $message = '')
+    {
+        static::__callStatic('allNotSame', array($value, $expect, $message));
+    }
+
+    /**
+     * @psalm-pure
+     *
+     * @param mixed  $value
+     * @param mixed  $limit
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function nullOrGreaterThan($value, $limit, $message = '')
+    {
+        static::__callStatic('nullOrGreaterThan', array($value, $limit, $message));
+    }
+
+    /**
+     * @psalm-pure
+     *
+     * @param mixed  $value
+     * @param mixed  $limit
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function allGreaterThan($value, $limit, $message = '')
+    {
+        static::__callStatic('allGreaterThan', array($value, $limit, $message));
+    }
+
+    /**
+     * @psalm-pure
+     *
+     * @param mixed  $value
+     * @param mixed  $limit
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function nullOrGreaterThanEq($value, $limit, $message = '')
+    {
+        static::__callStatic('nullOrGreaterThanEq', array($value, $limit, $message));
+    }
+
+    /**
+     * @psalm-pure
+     *
+     * @param mixed  $value
+     * @param mixed  $limit
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function allGreaterThanEq($value, $limit, $message = '')
+    {
+        static::__callStatic('allGreaterThanEq', array($value, $limit, $message));
+    }
+
+    /**
+     * @psalm-pure
+     *
+     * @param mixed  $value
+     * @param mixed  $limit
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function nullOrLessThan($value, $limit, $message = '')
+    {
+        static::__callStatic('nullOrLessThan', array($value, $limit, $message));
+    }
+
+    /**
+     * @psalm-pure
+     *
+     * @param mixed  $value
+     * @param mixed  $limit
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function allLessThan($value, $limit, $message = '')
+    {
+        static::__callStatic('allLessThan', array($value, $limit, $message));
+    }
+
+    /**
+     * @psalm-pure
+     *
+     * @param mixed  $value
+     * @param mixed  $limit
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function nullOrLessThanEq($value, $limit, $message = '')
+    {
+        static::__callStatic('nullOrLessThanEq', array($value, $limit, $message));
+    }
+
+    /**
+     * @psalm-pure
+     *
+     * @param mixed  $value
+     * @param mixed  $limit
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function allLessThanEq($value, $limit, $message = '')
+    {
+        static::__callStatic('allLessThanEq', array($value, $limit, $message));
+    }
+
+    /**
+     * @psalm-pure
+     *
+     * @param mixed  $value
+     * @param mixed  $min
+     * @param mixed  $max
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function nullOrRange($value, $min, $max, $message = '')
+    {
+        static::__callStatic('nullOrRange', array($value, $min, $max, $message));
+    }
+
+    /**
+     * @psalm-pure
+     *
+     * @param mixed  $value
+     * @param mixed  $min
+     * @param mixed  $max
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function allRange($value, $min, $max, $message = '')
+    {
+        static::__callStatic('allRange', array($value, $min, $max, $message));
+    }
+
+    /**
+     * @psalm-pure
+     *
+     * @param mixed  $value
+     * @param array  $values
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function nullOrOneOf($value, $values, $message = '')
+    {
+        static::__callStatic('nullOrOneOf', array($value, $values, $message));
+    }
+
+    /**
+     * @psalm-pure
+     *
+     * @param mixed  $value
+     * @param array  $values
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function allOneOf($value, $values, $message = '')
+    {
+        static::__callStatic('allOneOf', array($value, $values, $message));
+    }
+
+    /**
+     * @psalm-pure
+     *
+     * @param mixed  $value
+     * @param array  $values
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function nullOrInArray($value, $values, $message = '')
+    {
+        static::__callStatic('nullOrInArray', array($value, $values, $message));
+    }
+
+    /**
+     * @psalm-pure
+     *
+     * @param mixed  $value
+     * @param array  $values
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function allInArray($value, $values, $message = '')
+    {
+        static::__callStatic('allInArray', array($value, $values, $message));
+    }
+
+    /**
+     * @psalm-pure
+     *
+     * @param string|null $value
+     * @param string      $subString
+     * @param string      $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function nullOrContains($value, $subString, $message = '')
+    {
+        static::__callStatic('nullOrContains', array($value, $subString, $message));
+    }
+
+    /**
+     * @psalm-pure
+     *
+     * @param iterable<string> $value
+     * @param string           $subString
+     * @param string           $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function allContains($value, $subString, $message = '')
+    {
+        static::__callStatic('allContains', array($value, $subString, $message));
+    }
+
+    /**
+     * @psalm-pure
+     *
+     * @param string|null $value
+     * @param string      $subString
+     * @param string      $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function nullOrNotContains($value, $subString, $message = '')
+    {
+        static::__callStatic('nullOrNotContains', array($value, $subString, $message));
+    }
+
+    /**
+     * @psalm-pure
+     *
+     * @param iterable<string> $value
+     * @param string           $subString
+     * @param string           $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function allNotContains($value, $subString, $message = '')
+    {
+        static::__callStatic('allNotContains', array($value, $subString, $message));
+    }
+
+    /**
+     * @psalm-pure
+     *
+     * @param string|null $value
+     * @param string      $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function nullOrNotWhitespaceOnly($value, $message = '')
+    {
+        static::__callStatic('nullOrNotWhitespaceOnly', array($value, $message));
+    }
+
+    /**
+     * @psalm-pure
+     *
+     * @param iterable<string> $value
+     * @param string           $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function allNotWhitespaceOnly($value, $message = '')
+    {
+        static::__callStatic('allNotWhitespaceOnly', array($value, $message));
+    }
+
+    /**
+     * @psalm-pure
+     *
+     * @param string|null $value
+     * @param string      $prefix
+     * @param string      $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function nullOrStartsWith($value, $prefix, $message = '')
+    {
+        static::__callStatic('nullOrStartsWith', array($value, $prefix, $message));
+    }
+
+    /**
+     * @psalm-pure
+     *
+     * @param iterable<string> $value
+     * @param string           $prefix
+     * @param string           $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function allStartsWith($value, $prefix, $message = '')
+    {
+        static::__callStatic('allStartsWith', array($value, $prefix, $message));
+    }
+
+    /**
+     * @psalm-pure
+     *
+     * @param string|null $value
+     * @param string      $prefix
+     * @param string      $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function nullOrNotStartsWith($value, $prefix, $message = '')
+    {
+        static::__callStatic('nullOrNotStartsWith', array($value, $prefix, $message));
+    }
+
+    /**
+     * @psalm-pure
+     *
+     * @param iterable<string> $value
+     * @param string           $prefix
+     * @param string           $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function allNotStartsWith($value, $prefix, $message = '')
+    {
+        static::__callStatic('allNotStartsWith', array($value, $prefix, $message));
+    }
+
+    /**
+     * @psalm-pure
+     *
+     * @param mixed  $value
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function nullOrStartsWithLetter($value, $message = '')
+    {
+        static::__callStatic('nullOrStartsWithLetter', array($value, $message));
+    }
+
+    /**
+     * @psalm-pure
+     *
+     * @param mixed  $value
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function allStartsWithLetter($value, $message = '')
+    {
+        static::__callStatic('allStartsWithLetter', array($value, $message));
+    }
+
+    /**
+     * @psalm-pure
+     *
+     * @param string|null $value
+     * @param string      $suffix
+     * @param string      $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function nullOrEndsWith($value, $suffix, $message = '')
+    {
+        static::__callStatic('nullOrEndsWith', array($value, $suffix, $message));
+    }
+
+    /**
+     * @psalm-pure
+     *
+     * @param iterable<string> $value
+     * @param string           $suffix
+     * @param string           $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function allEndsWith($value, $suffix, $message = '')
+    {
+        static::__callStatic('allEndsWith', array($value, $suffix, $message));
+    }
+
+    /**
+     * @psalm-pure
+     *
+     * @param string|null $value
+     * @param string      $suffix
+     * @param string      $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function nullOrNotEndsWith($value, $suffix, $message = '')
+    {
+        static::__callStatic('nullOrNotEndsWith', array($value, $suffix, $message));
+    }
+
+    /**
+     * @psalm-pure
+     *
+     * @param iterable<string> $value
+     * @param string           $suffix
+     * @param string           $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function allNotEndsWith($value, $suffix, $message = '')
+    {
+        static::__callStatic('allNotEndsWith', array($value, $suffix, $message));
+    }
+
+    /**
+     * @psalm-pure
+     *
+     * @param string|null $value
+     * @param string      $pattern
+     * @param string      $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function nullOrRegex($value, $pattern, $message = '')
+    {
+        static::__callStatic('nullOrRegex', array($value, $pattern, $message));
+    }
+
+    /**
+     * @psalm-pure
+     *
+     * @param iterable<string> $value
+     * @param string           $pattern
+     * @param string           $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function allRegex($value, $pattern, $message = '')
+    {
+        static::__callStatic('allRegex', array($value, $pattern, $message));
+    }
+
+    /**
+     * @psalm-pure
+     *
+     * @param string|null $value
+     * @param string      $pattern
+     * @param string      $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function nullOrNotRegex($value, $pattern, $message = '')
+    {
+        static::__callStatic('nullOrNotRegex', array($value, $pattern, $message));
+    }
+
+    /**
+     * @psalm-pure
+     *
+     * @param iterable<string> $value
+     * @param string           $pattern
+     * @param string           $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function allNotRegex($value, $pattern, $message = '')
+    {
+        static::__callStatic('allNotRegex', array($value, $pattern, $message));
+    }
+
+    /**
+     * @psalm-pure
+     *
+     * @param mixed  $value
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function nullOrUnicodeLetters($value, $message = '')
+    {
+        static::__callStatic('nullOrUnicodeLetters', array($value, $message));
+    }
+
+    /**
+     * @psalm-pure
+     *
+     * @param mixed  $value
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function allUnicodeLetters($value, $message = '')
+    {
+        static::__callStatic('allUnicodeLetters', array($value, $message));
+    }
+
+    /**
+     * @psalm-pure
+     *
+     * @param mixed  $value
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function nullOrAlpha($value, $message = '')
+    {
+        static::__callStatic('nullOrAlpha', array($value, $message));
+    }
+
+    /**
+     * @psalm-pure
+     *
+     * @param mixed  $value
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function allAlpha($value, $message = '')
+    {
+        static::__callStatic('allAlpha', array($value, $message));
+    }
+
+    /**
+     * @psalm-pure
+     *
+     * @param string|null $value
+     * @param string      $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function nullOrDigits($value, $message = '')
+    {
+        static::__callStatic('nullOrDigits', array($value, $message));
+    }
+
+    /**
+     * @psalm-pure
+     *
+     * @param iterable<string> $value
+     * @param string           $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function allDigits($value, $message = '')
+    {
+        static::__callStatic('allDigits', array($value, $message));
+    }
+
+    /**
+     * @psalm-pure
+     *
+     * @param string|null $value
+     * @param string      $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function nullOrAlnum($value, $message = '')
+    {
+        static::__callStatic('nullOrAlnum', array($value, $message));
+    }
+
+    /**
+     * @psalm-pure
+     *
+     * @param iterable<string> $value
+     * @param string           $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function allAlnum($value, $message = '')
+    {
+        static::__callStatic('allAlnum', array($value, $message));
+    }
+
+    /**
+     * @psalm-pure
+     * @psalm-assert lowercase-string|null $value
+     *
+     * @param string|null $value
+     * @param string      $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function nullOrLower($value, $message = '')
+    {
+        static::__callStatic('nullOrLower', array($value, $message));
+    }
+
+    /**
+     * @psalm-pure
+     * @psalm-assert iterable<lowercase-string> $value
+     *
+     * @param iterable<string> $value
+     * @param string           $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function allLower($value, $message = '')
+    {
+        static::__callStatic('allLower', array($value, $message));
+    }
+
+    /**
+     * @psalm-pure
+     *
+     * @param string|null $value
+     * @param string      $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function nullOrUpper($value, $message = '')
+    {
+        static::__callStatic('nullOrUpper', array($value, $message));
+    }
+
+    /**
+     * @psalm-pure
+     *
+     * @param iterable<string> $value
+     * @param string           $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function allUpper($value, $message = '')
+    {
+        static::__callStatic('allUpper', array($value, $message));
+    }
+
+    /**
+     * @psalm-pure
+     *
+     * @param string|null $value
+     * @param int         $length
+     * @param string      $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function nullOrLength($value, $length, $message = '')
+    {
+        static::__callStatic('nullOrLength', array($value, $length, $message));
+    }
+
+    /**
+     * @psalm-pure
+     *
+     * @param iterable<string> $value
+     * @param int              $length
+     * @param string           $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function allLength($value, $length, $message = '')
+    {
+        static::__callStatic('allLength', array($value, $length, $message));
+    }
+
+    /**
+     * @psalm-pure
+     *
+     * @param string|null $value
+     * @param int|float   $min
+     * @param string      $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function nullOrMinLength($value, $min, $message = '')
+    {
+        static::__callStatic('nullOrMinLength', array($value, $min, $message));
+    }
+
+    /**
+     * @psalm-pure
+     *
+     * @param iterable<string> $value
+     * @param int|float        $min
+     * @param string           $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function allMinLength($value, $min, $message = '')
+    {
+        static::__callStatic('allMinLength', array($value, $min, $message));
+    }
+
+    /**
+     * @psalm-pure
+     *
+     * @param string|null $value
+     * @param int|float   $max
+     * @param string      $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function nullOrMaxLength($value, $max, $message = '')
+    {
+        static::__callStatic('nullOrMaxLength', array($value, $max, $message));
+    }
+
+    /**
+     * @psalm-pure
+     *
+     * @param iterable<string> $value
+     * @param int|float        $max
+     * @param string           $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function allMaxLength($value, $max, $message = '')
+    {
+        static::__callStatic('allMaxLength', array($value, $max, $message));
+    }
+
+    /**
+     * @psalm-pure
+     *
+     * @param string|null $value
+     * @param int|float   $min
+     * @param int|float   $max
+     * @param string      $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function nullOrLengthBetween($value, $min, $max, $message = '')
+    {
+        static::__callStatic('nullOrLengthBetween', array($value, $min, $max, $message));
+    }
+
+    /**
+     * @psalm-pure
+     *
+     * @param iterable<string> $value
+     * @param int|float        $min
+     * @param int|float        $max
+     * @param string           $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function allLengthBetween($value, $min, $max, $message = '')
+    {
+        static::__callStatic('allLengthBetween', array($value, $min, $max, $message));
+    }
+
+    /**
+     * @param mixed  $value
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function nullOrFileExists($value, $message = '')
+    {
+        static::__callStatic('nullOrFileExists', array($value, $message));
+    }
+
+    /**
+     * @param mixed  $value
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function allFileExists($value, $message = '')
+    {
+        static::__callStatic('allFileExists', array($value, $message));
+    }
+
+    /**
+     * @param mixed  $value
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function nullOrFile($value, $message = '')
+    {
+        static::__callStatic('nullOrFile', array($value, $message));
+    }
+
+    /**
+     * @param mixed  $value
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function allFile($value, $message = '')
+    {
+        static::__callStatic('allFile', array($value, $message));
+    }
+
+    /**
+     * @param mixed  $value
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function nullOrDirectory($value, $message = '')
+    {
+        static::__callStatic('nullOrDirectory', array($value, $message));
+    }
+
+    /**
+     * @param mixed  $value
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function allDirectory($value, $message = '')
+    {
+        static::__callStatic('allDirectory', array($value, $message));
+    }
+
+    /**
+     * @param string|null $value
+     * @param string      $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function nullOrReadable($value, $message = '')
+    {
+        static::__callStatic('nullOrReadable', array($value, $message));
+    }
+
+    /**
+     * @param iterable<string> $value
+     * @param string           $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function allReadable($value, $message = '')
+    {
+        static::__callStatic('allReadable', array($value, $message));
+    }
+
+    /**
+     * @param string|null $value
+     * @param string      $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function nullOrWritable($value, $message = '')
+    {
+        static::__callStatic('nullOrWritable', array($value, $message));
+    }
+
+    /**
+     * @param iterable<string> $value
+     * @param string           $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function allWritable($value, $message = '')
+    {
+        static::__callStatic('allWritable', array($value, $message));
+    }
+
+    /**
+     * @psalm-assert class-string|null $value
+     *
+     * @param mixed  $value
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function nullOrClassExists($value, $message = '')
+    {
+        static::__callStatic('nullOrClassExists', array($value, $message));
+    }
+
+    /**
+     * @psalm-assert iterable<class-string> $value
+     *
+     * @param mixed  $value
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function allClassExists($value, $message = '')
+    {
+        static::__callStatic('allClassExists', array($value, $message));
+    }
+
+    /**
+     * @psalm-pure
+     * @psalm-template ExpectedType of object
+     * @psalm-param class-string<ExpectedType> $class
+     * @psalm-assert class-string<ExpectedType>|ExpectedType|null $value
+     *
+     * @param mixed         $value
+     * @param string|object $class
+     * @param string        $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function nullOrSubclassOf($value, $class, $message = '')
+    {
+        static::__callStatic('nullOrSubclassOf', array($value, $class, $message));
+    }
+
+    /**
+     * @psalm-pure
+     * @psalm-template ExpectedType of object
+     * @psalm-param class-string<ExpectedType> $class
+     * @psalm-assert iterable<class-string<ExpectedType>|ExpectedType> $value
+     *
+     * @param mixed         $value
+     * @param string|object $class
+     * @param string        $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function allSubclassOf($value, $class, $message = '')
+    {
+        static::__callStatic('allSubclassOf', array($value, $class, $message));
+    }
+
+    /**
+     * @psalm-assert class-string|null $value
+     *
+     * @param mixed  $value
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function nullOrInterfaceExists($value, $message = '')
+    {
+        static::__callStatic('nullOrInterfaceExists', array($value, $message));
+    }
+
+    /**
+     * @psalm-assert iterable<class-string> $value
+     *
+     * @param mixed  $value
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function allInterfaceExists($value, $message = '')
+    {
+        static::__callStatic('allInterfaceExists', array($value, $message));
+    }
+
+    /**
+     * @psalm-pure
+     * @psalm-template ExpectedType of object
+     * @psalm-param class-string<ExpectedType> $interface
+     * @psalm-assert class-string<ExpectedType>|null $value
+     *
+     * @param mixed  $value
+     * @param mixed  $interface
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function nullOrImplementsInterface($value, $interface, $message = '')
+    {
+        static::__callStatic('nullOrImplementsInterface', array($value, $interface, $message));
+    }
+
+    /**
+     * @psalm-pure
+     * @psalm-template ExpectedType of object
+     * @psalm-param class-string<ExpectedType> $interface
+     * @psalm-assert iterable<class-string<ExpectedType>> $value
+     *
+     * @param mixed  $value
+     * @param mixed  $interface
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function allImplementsInterface($value, $interface, $message = '')
+    {
+        static::__callStatic('allImplementsInterface', array($value, $interface, $message));
+    }
+
+    /**
+     * @psalm-pure
+     * @psalm-param class-string|object|null $classOrObject
+     *
+     * @param string|object|null $classOrObject
+     * @param mixed              $property
+     * @param string             $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function nullOrPropertyExists($classOrObject, $property, $message = '')
+    {
+        static::__callStatic('nullOrPropertyExists', array($classOrObject, $property, $message));
+    }
+
+    /**
+     * @psalm-pure
+     * @psalm-param iterable<class-string|object> $classOrObject
+     *
+     * @param iterable<string|object> $classOrObject
+     * @param mixed                   $property
+     * @param string                  $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function allPropertyExists($classOrObject, $property, $message = '')
+    {
+        static::__callStatic('allPropertyExists', array($classOrObject, $property, $message));
+    }
+
+    /**
+     * @psalm-pure
+     * @psalm-param class-string|object|null $classOrObject
+     *
+     * @param string|object|null $classOrObject
+     * @param mixed              $property
+     * @param string             $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function nullOrPropertyNotExists($classOrObject, $property, $message = '')
+    {
+        static::__callStatic('nullOrPropertyNotExists', array($classOrObject, $property, $message));
+    }
+
+    /**
+     * @psalm-pure
+     * @psalm-param iterable<class-string|object> $classOrObject
+     *
+     * @param iterable<string|object> $classOrObject
+     * @param mixed                   $property
+     * @param string                  $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function allPropertyNotExists($classOrObject, $property, $message = '')
+    {
+        static::__callStatic('allPropertyNotExists', array($classOrObject, $property, $message));
+    }
+
+    /**
+     * @psalm-pure
+     * @psalm-param class-string|object|null $classOrObject
+     *
+     * @param string|object|null $classOrObject
+     * @param mixed              $method
+     * @param string             $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function nullOrMethodExists($classOrObject, $method, $message = '')
+    {
+        static::__callStatic('nullOrMethodExists', array($classOrObject, $method, $message));
+    }
+
+    /**
+     * @psalm-pure
+     * @psalm-param iterable<class-string|object> $classOrObject
+     *
+     * @param iterable<string|object> $classOrObject
+     * @param mixed                   $method
+     * @param string                  $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function allMethodExists($classOrObject, $method, $message = '')
+    {
+        static::__callStatic('allMethodExists', array($classOrObject, $method, $message));
+    }
+
+    /**
+     * @psalm-pure
+     * @psalm-param class-string|object|null $classOrObject
+     *
+     * @param string|object|null $classOrObject
+     * @param mixed              $method
+     * @param string             $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function nullOrMethodNotExists($classOrObject, $method, $message = '')
+    {
+        static::__callStatic('nullOrMethodNotExists', array($classOrObject, $method, $message));
+    }
+
+    /**
+     * @psalm-pure
+     * @psalm-param iterable<class-string|object> $classOrObject
+     *
+     * @param iterable<string|object> $classOrObject
+     * @param mixed                   $method
+     * @param string                  $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function allMethodNotExists($classOrObject, $method, $message = '')
+    {
+        static::__callStatic('allMethodNotExists', array($classOrObject, $method, $message));
+    }
+
+    /**
+     * @psalm-pure
+     *
+     * @param array|null $array
+     * @param string|int $key
+     * @param string     $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function nullOrKeyExists($array, $key, $message = '')
+    {
+        static::__callStatic('nullOrKeyExists', array($array, $key, $message));
+    }
+
+    /**
+     * @psalm-pure
+     *
+     * @param iterable<array> $array
+     * @param string|int      $key
+     * @param string          $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function allKeyExists($array, $key, $message = '')
+    {
+        static::__callStatic('allKeyExists', array($array, $key, $message));
+    }
+
+    /**
+     * @psalm-pure
+     *
+     * @param array|null $array
+     * @param string|int $key
+     * @param string     $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function nullOrKeyNotExists($array, $key, $message = '')
+    {
+        static::__callStatic('nullOrKeyNotExists', array($array, $key, $message));
+    }
+
+    /**
+     * @psalm-pure
+     *
+     * @param iterable<array> $array
+     * @param string|int      $key
+     * @param string          $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function allKeyNotExists($array, $key, $message = '')
+    {
+        static::__callStatic('allKeyNotExists', array($array, $key, $message));
+    }
+
+    /**
+     * @psalm-pure
+     * @psalm-assert array-key|null $value
+     *
+     * @param mixed  $value
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function nullOrValidArrayKey($value, $message = '')
+    {
+        static::__callStatic('nullOrValidArrayKey', array($value, $message));
+    }
+
+    /**
+     * @psalm-pure
+     * @psalm-assert iterable<array-key> $value
+     *
+     * @param mixed  $value
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function allValidArrayKey($value, $message = '')
+    {
+        static::__callStatic('allValidArrayKey', array($value, $message));
+    }
+
+    /**
+     * @param Countable|array|null $array
+     * @param int                  $number
+     * @param string               $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function nullOrCount($array, $number, $message = '')
+    {
+        static::__callStatic('nullOrCount', array($array, $number, $message));
+    }
+
+    /**
+     * @param iterable<Countable|array> $array
+     * @param int                       $number
+     * @param string                    $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function allCount($array, $number, $message = '')
+    {
+        static::__callStatic('allCount', array($array, $number, $message));
+    }
+
+    /**
+     * @param Countable|array|null $array
+     * @param int|float            $min
+     * @param string               $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function nullOrMinCount($array, $min, $message = '')
+    {
+        static::__callStatic('nullOrMinCount', array($array, $min, $message));
+    }
+
+    /**
+     * @param iterable<Countable|array> $array
+     * @param int|float                 $min
+     * @param string                    $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function allMinCount($array, $min, $message = '')
+    {
+        static::__callStatic('allMinCount', array($array, $min, $message));
+    }
+
+    /**
+     * @param Countable|array|null $array
+     * @param int|float            $max
+     * @param string               $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function nullOrMaxCount($array, $max, $message = '')
+    {
+        static::__callStatic('nullOrMaxCount', array($array, $max, $message));
+    }
+
+    /**
+     * @param iterable<Countable|array> $array
+     * @param int|float                 $max
+     * @param string                    $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function allMaxCount($array, $max, $message = '')
+    {
+        static::__callStatic('allMaxCount', array($array, $max, $message));
+    }
+
+    /**
+     * @param Countable|array|null $array
+     * @param int|float            $min
+     * @param int|float            $max
+     * @param string               $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function nullOrCountBetween($array, $min, $max, $message = '')
+    {
+        static::__callStatic('nullOrCountBetween', array($array, $min, $max, $message));
+    }
+
+    /**
+     * @param iterable<Countable|array> $array
+     * @param int|float                 $min
+     * @param int|float                 $max
+     * @param string                    $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function allCountBetween($array, $min, $max, $message = '')
+    {
+        static::__callStatic('allCountBetween', array($array, $min, $max, $message));
+    }
+
+    /**
+     * @psalm-pure
+     * @psalm-assert list|null $array
+     *
+     * @param mixed  $array
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function nullOrIsList($array, $message = '')
+    {
+        static::__callStatic('nullOrIsList', array($array, $message));
+    }
+
+    /**
+     * @psalm-pure
+     * @psalm-assert iterable<list> $array
+     *
+     * @param mixed  $array
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function allIsList($array, $message = '')
+    {
+        static::__callStatic('allIsList', array($array, $message));
+    }
+
+    /**
+     * @psalm-pure
+     * @psalm-assert non-empty-list|null $array
+     *
+     * @param mixed  $array
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function nullOrIsNonEmptyList($array, $message = '')
+    {
+        static::__callStatic('nullOrIsNonEmptyList', array($array, $message));
+    }
+
+    /**
+     * @psalm-pure
+     * @psalm-assert iterable<non-empty-list> $array
+     *
+     * @param mixed  $array
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function allIsNonEmptyList($array, $message = '')
+    {
+        static::__callStatic('allIsNonEmptyList', array($array, $message));
+    }
+
+    /**
+     * @psalm-pure
+     * @psalm-template T
+     * @psalm-param mixed|array<T>|null $array
+     * @psalm-assert array<string, T>|null $array
+     *
+     * @param mixed  $array
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function nullOrIsMap($array, $message = '')
+    {
+        static::__callStatic('nullOrIsMap', array($array, $message));
+    }
+
+    /**
+     * @psalm-pure
+     * @psalm-template T
+     * @psalm-param iterable<mixed|array<T>> $array
+     * @psalm-assert iterable<array<string, T>> $array
+     *
+     * @param mixed  $array
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function allIsMap($array, $message = '')
+    {
+        static::__callStatic('allIsMap', array($array, $message));
+    }
+
+    /**
+     * @psalm-pure
+     * @psalm-template T
+     * @psalm-param mixed|array<T>|null $array
+     *
+     * @param mixed  $array
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function nullOrIsNonEmptyMap($array, $message = '')
+    {
+        static::__callStatic('nullOrIsNonEmptyMap', array($array, $message));
+    }
+
+    /**
+     * @psalm-pure
+     * @psalm-template T
+     * @psalm-param iterable<mixed|array<T>> $array
+     *
+     * @param mixed  $array
+     * @param string $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function allIsNonEmptyMap($array, $message = '')
+    {
+        static::__callStatic('allIsNonEmptyMap', array($array, $message));
+    }
+
+    /**
+     * @psalm-pure
+     *
+     * @param string|null $value
+     * @param string      $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function nullOrUuid($value, $message = '')
+    {
+        static::__callStatic('nullOrUuid', array($value, $message));
+    }
+
+    /**
+     * @psalm-pure
+     *
+     * @param iterable<string> $value
+     * @param string           $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function allUuid($value, $message = '')
+    {
+        static::__callStatic('allUuid', array($value, $message));
+    }
+
+    /**
+     * @psalm-param class-string<Throwable> $class
+     *
+     * @param Closure|null $expression
+     * @param string       $class
+     * @param string       $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function nullOrThrows($expression, $class = 'Exception', $message = '')
+    {
+        static::__callStatic('nullOrThrows', array($expression, $class, $message));
+    }
+
+    /**
+     * @psalm-param class-string<Throwable> $class
+     *
+     * @param iterable<Closure> $expression
+     * @param string            $class
+     * @param string            $message
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return void
+     */
+    public static function allThrows($expression, $class = 'Exception', $message = '')
+    {
+        static::__callStatic('allThrows', array($expression, $class, $message));
+    }
+}