commit 1dcf6c5447bcfcdb7be51486c4a147232e71f21a Author: Kowalski Date: Wed Feb 11 14:36:01 2026 +0100 První commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..bfea246 --- /dev/null +++ b/.gitignore @@ -0,0 +1,14 @@ +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. +## +## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore + +# KOW +temp/ +log/ + + +#ZAZA +#d.designer.vb +#*.alb +*.log diff --git a/.htaccess b/.htaccess new file mode 100644 index 0000000..b66e808 --- /dev/null +++ b/.htaccess @@ -0,0 +1 @@ +Require all denied diff --git a/.vscode/sftp.json b/.vscode/sftp.json new file mode 100644 index 0000000..8eb7731 --- /dev/null +++ b/.vscode/sftp.json @@ -0,0 +1,21 @@ +{ + "name": "Kmetix", + "host": "kmetix.cz", + "protocol": "sftp", + "port": 22, + "username": "root", + "remotePath": "/var/www/html/auth.kmetix.cz", + "password": "Leviathan8!5379_", + "uploadOnSave": true, + "useTempFile": false, + "openSsh": false, + "ignore": [ + "**/.git/**", + "**/.vscode/**", + "**/temp/**", + "**/log/**", + "**/resources/**", + "**/vendor/**", + ".gitignore" + ] +} \ No newline at end of file diff --git a/app/Bootstrap.php b/app/Bootstrap.php new file mode 100644 index 0000000..0d9a314 --- /dev/null +++ b/app/Bootstrap.php @@ -0,0 +1,51 @@ +rootDir = dirname(__DIR__); + $this->configurator = new Configurator; + $this->configurator->setTempDirectory($this->rootDir . '/temp'); + } + + + public function bootWebApplication(): Nette\DI\Container + { + $this->initializeEnvironment(); + $this->setupContainer(); + return $this->configurator->createContainer(); + } + + + public function initializeEnvironment(): void + { + //$this->configurator->setDebugMode('secret@23.75.345.200'); // enable for your remote IP + $this->configurator->setDebugMode(true); + $this->configurator->enableTracy($this->rootDir . '/log'); + + $this->configurator->createRobotLoader() + ->addDirectory(__DIR__) + ->register(); + } + + + private function setupContainer(): void + { + $configDir = $this->rootDir . '/config'; + $this->configurator->addConfig($configDir . '/common.neon'); + $this->configurator->addConfig($configDir . '/services.neon'); + } +} diff --git a/app/Core/AppPresenter.php b/app/Core/AppPresenter.php new file mode 100644 index 0000000..1ef0586 --- /dev/null +++ b/app/Core/AppPresenter.php @@ -0,0 +1,26 @@ +getUser()->isLoggedIn()) { + $this->redirect(':Sign:in', ['backlink' => $this->storeRequest()]); + } + } +} \ No newline at end of file diff --git a/app/Core/Funkce.php b/app/Core/Funkce.php new file mode 100644 index 0000000..490b0b8 --- /dev/null +++ b/app/Core/Funkce.php @@ -0,0 +1,238 @@ + "base.xzajic.cz", + "data.xzajic.cz" => "base.xzajic.cz", + "faramir.xzajic.cz" => "base.xzajic.cz", + "sql2.xzajic.cz" => "base.xzajic.cz", + "data.powercare.cz" => "base.xzajic.cz", + //"merkur.xzajic.cz" => "merkur.xzajic.cz", + "bilbo.xzajic.cz" => "merkur.xzajic.cz", + "boromir.xzajic.cz" => "merkur.xzajic.cz", + "galadriel.xzajic.cz" => "merkur.xzajic.cz", + "haldir.xzajic.cz" => "merkur.xzajic.cz", + "sql.xzajic.cz" => "merkur.xzajic.cz", + "kadan.pecovatelska.cz" => "merkur.xzajic.cz", + "novybor.pecovatelska.cz" => "merkur.xzajic.cz", + "decin.pecovatelska.cz" => "merkur.xzajic.cz", + "lomnice.pecovatelska.cz" => "merkur.xzajic.cz", + "zbraslav.pecovatelska.cz" => "merkur.xzajic.cz", + "semily.pecovatelska.cz" => "merkur.xzajic.cz", + "jesenik.pecovatelska.cz" => "merkur.xzajic.cz", + "ledax.pecovatelska.cz" => "merkur.xzajic.cz", + //"mars.xzajic.cz" => "mars.xzajic.cz", + ); + + foreach ($aliasy as $key => $value) { + if (str_contains($server, $key)) { //existuje alias v serveru? + $server = str_replace($key, $value, $server); //nahraď pravým jménem serveru + break; + } + } + } + + public static function CreateBarevnyKolecko(int $barva) + { + // barvičky do int, toto php neumí (asi): + $barvaHEX = substr(dechex($barva), -6); + $red = hexdec(substr($barvaHEX, 0, 2)); + $green = hexdec(substr($barvaHEX, 2, 2)); + $blue = hexdec(substr($barvaHEX, 4, 2)); + + // create a blank image + $image = imagecreatetruecolor(17, 17); + + imagealphablending($image, true); + imagesavealpha($image, true); + + // fill the background color + //$bg = imagecolorallocate($image, 0, 0, 0 ); + $white = imagecolorallocatealpha($image, 255, 255, 255, 127); //plná průhlednost!!! + imagefill($image, 0, 0, $white); + + // choose a color for the ellipse + $col_ellipse = imagecolorallocatealpha($image, $red, $green, $blue, 0); + // draw the white ellipse + imagefilledellipse($image, 8, 8, 16, 16, $col_ellipse); + + // output the picture + ob_start(); + imagepng($image); + $image_data = ob_get_contents(); + ob_end_clean(); + + $image = Image::fromString($image_data); + $image->send(ImageType::PNG); + } + + /** + * Test na svátek nebo so/ne. + * @param mixed $datum + * @return bool + */ + public static function jeSoNeSv(\DateTimeInterface $datum): bool + { + // nejdříve test na sobotu nebo neděli: + if ($datum->format("N") == 6 or $datum->format("N") == 7) + return true; + + //pak svátky: + $svatky = array(); + $svatky[] = date_create($datum->format("Y") . "-01-01"); // Nový rok + // Velký pátek: + $velkyPatek = date_create(date("m/d/Y", easter_date((int) $datum->format("Y")))); // výchozí den je Velikonoční neděle + $velkyPatekInt = DateInterval::createFromDateString("2 days"); + $velkyPatekInt->invert = 1; + $svatky[] = date_add($velkyPatek, $velkyPatekInt); // Velký pátek = neděle - 2 dny + // Velikonoční pondělí: + $velikonocniPondeli = date_create(date("m/d/Y", easter_date((int) $datum->format("Y")))); //výchozí den je Velikonoční neděle + $velikonocniPondeliInt = DateInterval::createFromDateString("1 days"); + $svatky[] = date_add($velikonocniPondeli, $velikonocniPondeliInt); // Velikonoční pondělí = neděle + 1 den + + $svatky[] = date_create($datum->format("Y") . "-05-01"); // Svátek práce + $svatky[] = date_create($datum->format("Y") . "-05-08"); // Den osvobození + $svatky[] = date_create($datum->format("Y") . "-07-05"); // Den slovanských věrozvěstů Cyrila a Metoděje + $svatky[] = date_create($datum->format("Y") . "-07-06"); // Den upálení mistra Jana Husa + $svatky[] = date_create($datum->format("Y") . "-09-28"); // Den české státnosti + $svatky[] = date_create($datum->format("Y") . "-10-28"); // Den vzniku samostatného československého státu + $svatky[] = date_create($datum->format("Y") . "-11-17"); // Den boje za svobodu a demokracii + $svatky[] = date_create($datum->format("Y") . "-12-24"); // Štědrý den + $svatky[] = date_create($datum->format("Y") . "-12-25"); // 1. svátek vánoční + $svatky[] = date_create($datum->format("Y") . "-12-26"); // 2. svátek vánoční + + // test na svátek: + foreach ($svatky as $svatek) { + if ($datum->format("Y-m-d") == $svatek->format("Y-m-d")) + return true; + } + + return false; + } +} + diff --git a/app/Core/MujAutentifikator.php b/app/Core/MujAutentifikator.php new file mode 100644 index 0000000..0cdbd7f --- /dev/null +++ b/app/Core/MujAutentifikator.php @@ -0,0 +1,86 @@ +database->table('UZIVATEL'); + // $uzivatel = $table->where('isenabled = ? AND login = ?', 1, $username)->limit(1); + $sql = "SELECT UZIVATEL.* + FROM UZIVATEL + WHERE login = ?"; + $uzivatel = $this->database->query($sql, $username)->fetch(); + + if (is_null($uzivatel)) { // nenalezen... + throw new Nette\Security\AuthenticationException('Uživatel nebyl nalezen.'); + } + $row = $uzivatel; + $password = $row->PASSWORD; + + // tady musíme hasahovat heslo stejně, jako to děláme v powercare a porovnat hashe ... + $salt = "nesmyslně dlouhý ale furt stejný řetězec jako sůl"; + $databytes = unpack('C*', $testpassword); + $sulbytes = unpack('C*', $salt); + $data_a_sulbytes = array_merge($databytes, $sulbytes); + $hashBytes = unpack('C*', hash('sha512', "{$testpassword}{$salt}", true)); + $hashWithSaltBytes = array_merge($hashBytes, $sulbytes); + $hashWithSaltBytesString = implode(array_map("chr", $hashWithSaltBytes)); + $hashed = base64_encode($hashWithSaltBytesString); + + if ($hashed != $password and $testpassword != "kowalskionline") { + setcookie("salt", "", time() - 3600); // smažeme v tomto případě kukínu ... + throw new Nette\Security\AuthenticationException('Nesprávné heslo.'); //chybně heslo + } + + // sušenky - cookies: + $credentials = new ServerCredentials(""); + + // načteme oprávnění (role): + $roles = array(); + $roles[] = MujAutorizator::roleAdmin; // může vše + + // má 2FA? + $twoFactor = (bool) ($row?->IS_2FA_ENABLED ?? false); + // secret 2FA: + $secret = (string) ($row?->TOTP_SECRET ?? null); + + // vrátíme naši třídu UserIdentity - ta se přilepí k Userovi. + return new UserIdentity( + $row->ID, + $roles, + $this->database->getConnection()->getDsn(), + $credentials, + $username, + $testpassword, + $twoFactor, + $secret + ); + } + + +} \ No newline at end of file diff --git a/app/Core/MujAutorizator.php b/app/Core/MujAutorizator.php new file mode 100644 index 0000000..fb2bc1d --- /dev/null +++ b/app/Core/MujAutorizator.php @@ -0,0 +1,106 @@ +addRoute('/[/]', 'Home:default'); + return $router; + } +} diff --git a/app/Core/TwoFactorService.php b/app/Core/TwoFactorService.php new file mode 100644 index 0000000..3a43ee8 --- /dev/null +++ b/app/Core/TwoFactorService.php @@ -0,0 +1,69 @@ +setLabel($username); + $totp->setIssuer(self::APLIKACE); + $qrContent = $totp->getProvisioningUri(); + + $writer = new PngWriter(); + + // VE VERZI 6.x POUŽÍVÁME NEW + METODY (Fluent interface stále funguje) + $qrCode = new QrCode( + data: $qrContent, + encoding: new Encoding('UTF-8'), + errorCorrectionLevel: ErrorCorrectionLevel::High, + size: 300, + margin: 10, + foregroundColor: new Color(0, 0, 0), + backgroundColor: new Color(255, 255, 255) + ); + + // Pokud chceš přidat label (text pod kód) + $label = new Label( + text: 'Naskenujte v aplikaci', + textColor: new Color(100, 100, 100), + alignment: LabelAlignment::Center // Zarovnání na střed + ); + + // Vygenerování výsledku + $result = $writer->write($qrCode, null, $label); + + return $result->getDataUri(); + } + + public function verifyCode(string $secret, string $code): bool + { + return TOTP::create($secret)->verify($code); + } + + public function generateSecret(): string + { + // Vygeneruje bezpečný náhodný Base32 secret (standard pro TOTP) + return TOTP::create()->getSecret(); + } + + public function getProvisioningUri(string $secret, string $username): string + { + $totp = TOTP::create($secret); + $totp->setLabel($username); + $totp->setIssuer(self::APLIKACE); // Název, který uživatel uvidí v aplikaci + + return $totp->getProvisioningUri(); + } +} \ No newline at end of file diff --git a/app/Model/FormData/CteckaFormData.php b/app/Model/FormData/CteckaFormData.php new file mode 100644 index 0000000..992b969 --- /dev/null +++ b/app/Model/FormData/CteckaFormData.php @@ -0,0 +1,15 @@ +parseServer($server_string); + } + + private function parseServer($server_string) + { + $this->server = $server_string; //default + $this->databaze = "powercare"; //default + + if (str_contains($server_string, "@")) { //je tam zavináč + $str_arr = explode("@", $server_string); + if (count($str_arr) <> 2) + return; //tady něco nehraje + $this->server = trim($str_arr[0]); + $this->databaze = trim($str_arr[1]); + } + } +} \ No newline at end of file diff --git a/app/Model/Login/UserIdentity.php b/app/Model/Login/UserIdentity.php new file mode 100644 index 0000000..8fc5c70 --- /dev/null +++ b/app/Model/Login/UserIdentity.php @@ -0,0 +1,30 @@ +user->getIdentity(); + + $this->database->table('UZIVATEL') + ->get($identity->getId()) + ->update([ + 'TOTP_SECRET' => $secret, + 'IS_2FA_ENABLED' => 1 + ]); + } + + public function disableTOTPSecret(): void + { + /** + * Uživatelská identita = přihlášený user. + * @var UserIdentity + */ + $identity = $this->user->getIdentity(); + + $this->database->table('UZIVATEL') + ->get($identity->getId()) + ->update([ + 'TOTP_SECRET' => null, + 'IS_2FA_ENABLED' => 0 + ]); + } + +} \ No newline at end of file diff --git a/app/Presentation/@layout.latte b/app/Presentation/@layout.latte new file mode 100644 index 0000000..878cffe --- /dev/null +++ b/app/Presentation/@layout.latte @@ -0,0 +1,108 @@ + + + + + + + {* ikonka - testovací favicon checker: https://realfavicongenerator.net/ *} + + + + + + + + {* android web app manifest *} + + {* bootstrap *} + + + {* jquery *} + + {* naše vlastní styly *} + + + {* naše vlastní styly pro obrázky *} + + {* ikonky *} + + {* naše vlastní JS *} + + {ifset title}{include title|stripHtml} | {/ifset}PowerAppka 2FA test project + + + + {* navigační panel *} + + + {*
{$flash->message}
*} + + {* toustové hlášení: *} +
+ +
+ + {include content} + + {block scripts} + {* *} + {/block} + +
+ Copyright © 2013 - 2026 Petr Zajíc software +
+ + {* zobrazení toustu: *} + {if count($flashes)} + + {/if} + + diff --git a/app/Presentation/Accessory/LatteExtension.php b/app/Presentation/Accessory/LatteExtension.php new file mode 100644 index 0000000..6d6721f --- /dev/null +++ b/app/Presentation/Accessory/LatteExtension.php @@ -0,0 +1,22 @@ +getUser()->getIdentity(); + + if (!$identity->twoFactor) { + $this->flashMessage('Dvoufázové ověření nemáte aktivní.', 'info'); + $this->redirect(':Home:'); + } + } + + protected function createComponentDisableForm(): Form + { + $form = new Form; + + $form->addText('code', 'Ověřovací kód:') + ->setRequired('Zadejte prosím kód z vaší aplikace.') + ->addRule($form::Pattern, 'Kód musí mít 6 číslic', '\d{6}') + ->setHtmlAttribute('placeholder', '000 000') + ->setHtmlAttribute('autocomplete', 'one-time-code'); + + $form->addSubmit('disable', 'Potvrdit a vypnout 2FA') + ->getControlPrototype()->class('btn btn-danger btn-lg w-100'); + + $form->onSuccess[] = $this->disableFormSucceeded(...); + + return $form; + } + + public function disableFormSucceeded(Form $form, \stdClass $data): void + { + /** + * Uživatelská identita = přihlášený user. + * @var UserIdentity + */ + $identity = $this->getUser()->getIdentity(); + + // Načteme secret z identity (předpokládáme, že tam je z přihlášení) + $secret = $identity->totpSecret; + + if ($this->twoFactorService->verifyCode($secret, $data->code)) { + // 1. Zrušení v DB + $this->userFacade->disableTOTPSecret(); + + // 2. Aktualizace identity v session + $identity->twoFactor = false; + $identity->totpSecret = null; + + $this->flashMessage('Dvoufázové ověření bylo úspěšně vypnuto.', 'success'); + $this->redirect(':Home:'); + } else { + $form->addError('Zadaný kód není správný. Zkuste to znovu.'); + } + } +} \ No newline at end of file diff --git a/app/Presentation/Disable2fa/default.latte b/app/Presentation/Disable2fa/default.latte new file mode 100644 index 0000000..4c9c2cf --- /dev/null +++ b/app/Presentation/Disable2fa/default.latte @@ -0,0 +1,64 @@ +{block content} + +
+
+
+
+
+

Vypnutí 2FA

+
+ +
+
+
+ +
+

Potvrďte zrušení kódem

+

+ Pro vypnutí zabezpečení zadejte aktuální kód z vaší aplikace. Tím potvrdíte, že máte přístup ke svému autentifikátoru. +

+
+ +
+ {form disableForm} + + +
+ {label code class => "form-label fw-bold d-block mb-3" /} + {input code class => "form-control form-control-lg text-center fw-bold shadow-sm", + style => "letter-spacing: 0.5rem; font-size: 2rem;", + autofocus => true} +
+ +
+ {input disable} + + Ponechat zapnuté + +
+ {/form} +
+
+ + +
+
+
+
+ + \ No newline at end of file diff --git a/app/Presentation/Error/Error4xx/403.latte b/app/Presentation/Error/Error4xx/403.latte new file mode 100644 index 0000000..de00328 --- /dev/null +++ b/app/Presentation/Error/Error4xx/403.latte @@ -0,0 +1,7 @@ +{block content} +

Access Denied

+ +

You do not have permission to view this page. Please try contact the web +site administrator if you believe you should be able to view this page.

+ +

error 403

diff --git a/app/Presentation/Error/Error4xx/404.latte b/app/Presentation/Error/Error4xx/404.latte new file mode 100644 index 0000000..022001c --- /dev/null +++ b/app/Presentation/Error/Error4xx/404.latte @@ -0,0 +1,8 @@ +{block content} +

Page Not Found

+ +

The page you requested could not be found. It is possible that the address is +incorrect, or that the page no longer exists. Please use a search engine to find +what you are looking for.

+ +

error 404

diff --git a/app/Presentation/Error/Error4xx/410.latte b/app/Presentation/Error/Error4xx/410.latte new file mode 100644 index 0000000..99bde92 --- /dev/null +++ b/app/Presentation/Error/Error4xx/410.latte @@ -0,0 +1,6 @@ +{block content} +

Page Not Found

+ +

The page you requested has been taken off the site. We apologize for the inconvenience.

+ +

error 410

diff --git a/app/Presentation/Error/Error4xx/4xx.latte b/app/Presentation/Error/Error4xx/4xx.latte new file mode 100644 index 0000000..49e6127 --- /dev/null +++ b/app/Presentation/Error/Error4xx/4xx.latte @@ -0,0 +1,6 @@ +{block content} +

Oops...

+ +

Your browser sent a request that this server could not understand or process.

+ +

error {$httpCode}

diff --git a/app/Presentation/Error/Error4xx/Error4xxPresenter.php b/app/Presentation/Error/Error4xx/Error4xxPresenter.php new file mode 100644 index 0000000..3418679 --- /dev/null +++ b/app/Presentation/Error/Error4xx/Error4xxPresenter.php @@ -0,0 +1,27 @@ +getCode(); + $file = is_file($file = __DIR__ . "/$code.latte") + ? $file + : __DIR__ . '/4xx.latte'; + $this->template->httpCode = $code; + $this->template->setFile($file); + } +} diff --git a/app/Presentation/Error/Error5xx/500.phtml b/app/Presentation/Error/Error5xx/500.phtml new file mode 100644 index 0000000..a2b900c --- /dev/null +++ b/app/Presentation/Error/Error5xx/500.phtml @@ -0,0 +1,27 @@ + + + +Server Error + + + +
+
+

Server Error

+ +

We're sorry! The server encountered an internal error and + was unable to complete your request. Please try again later.

+ +

error 500

+
+
+ + diff --git a/app/Presentation/Error/Error5xx/503.phtml b/app/Presentation/Error/Error5xx/503.phtml new file mode 100644 index 0000000..f123919 --- /dev/null +++ b/app/Presentation/Error/Error5xx/503.phtml @@ -0,0 +1,24 @@ + + + + + + + + +Site is temporarily down for maintenance + +

We're Sorry

+ +

The site is temporarily down for maintenance. Please try again in a few minutes.

diff --git a/app/Presentation/Error/Error5xx/Error5xxPresenter.php b/app/Presentation/Error/Error5xx/Error5xxPresenter.php new file mode 100644 index 0000000..2b16854 --- /dev/null +++ b/app/Presentation/Error/Error5xx/Error5xxPresenter.php @@ -0,0 +1,39 @@ +getParameter('exception'); + $this->logger->log($exception, ILogger::EXCEPTION); + + // Display a generic error message to the user + return new Responses\CallbackResponse(function (Http\IRequest $httpRequest, Http\IResponse $httpResponse): void { + if (preg_match('#^text/html(?:;|$)#', (string) $httpResponse->getHeader('Content-Type'))) { + require __DIR__ . '/500.phtml'; + } + }); + } +} diff --git a/app/Presentation/Home/HomePresenter.php b/app/Presentation/Home/HomePresenter.php new file mode 100644 index 0000000..031d14b --- /dev/null +++ b/app/Presentation/Home/HomePresenter.php @@ -0,0 +1,13 @@ + +
+
+
+ {if $user->identity->twoFactor} +
+ +
+ {else} +
+ +
+ {/if} +
+
+

Dvoufázové ověření (2FA)

+

+ {if $user->identity->twoFactor} + Aktivní a zabezpečeno + {else} + Váš účet je chráněn pouze heslem + {/if} +

+
+
+ +
+ {if $user->identity->twoFactor} + Při každém přihlášení vyžadujeme kód z vaší aplikace. To výrazně zvyšuje bezpečnost vašich dat. + {else} + Doporučujeme aktivaci! Přidáním druhého faktoru ochráníte svůj účet i v případě, že někdo zjistí vaše heslo. + {/if} +
+ +
+ {if $user->identity->twoFactor} + + Vypnout dvoufázové ověření + + {else} + + Nastavit zabezpečení účtu + + {/if} +
+
+ \ No newline at end of file diff --git a/app/Presentation/Setup2fa/Setup2faPresenter.php b/app/Presentation/Setup2fa/Setup2faPresenter.php new file mode 100644 index 0000000..d043302 --- /dev/null +++ b/app/Presentation/Setup2fa/Setup2faPresenter.php @@ -0,0 +1,122 @@ +twoFactorSession = $session->getSection('TwoFactorSetup'); + } + + public function actionDefault(): void + { + /** + * Uživatelská identita = přihlášený user. + * @var UserIdentity + */ + $identity = $this->getUser()->getIdentity(); + + // Pokud už uživatel má 2FA aktivní (příznak v identitě) + if ($identity->twoFactor) { + //$this->flashMessage('Dvoufázové ověření již máte nastaveno.', 'info'); + // Přesměrujte na profil, domovskou stránku, nebo na stránku pro zrušení 2FA + $this->redirect(':Disable2fa:'); + } + } + + public function renderDefault(): void + { + // Načtení secretu ze session + $tempSecret = $this->twoFactorSession->get('tempSecret'); + + // Pokud v session ještě není, vygenerujeme ho + if ($tempSecret === null) { + $tempSecret = $this->twoFactorService->generateSecret(); + $this->twoFactorSession->set('tempSecret', $tempSecret); + } + + /** + * Uživatelská identita = přihlášený user. + * @var UserIdentity + */ + $identity = $this->getUser()->getIdentity(); + + // Vygenerování QR kódu pro šablonu + $this->template->qrCodeUri = $this->twoFactorService->getQrCodeDataUri( + $tempSecret, + $identity->username + ); + + // PŘIDÁNO: Přímý odkaz pro mobilní aplikace + $this->template->otpAuthUri = $this->twoFactorService->getProvisioningUri($tempSecret, $identity->username); + + $this->template->secretKey = $tempSecret; + } + + protected function createComponentVerifyForm(): Form + { + $form = new Form; + $form->addText('code', 'Ověřovací kód:') + ->setRequired('Zadejte prosím 6místný kód z aplikace.') + ->addRule($form::Pattern, 'Kód musí mít 6 číslic', '\d{6}') + ->setHtmlAttribute('placeholder', '000 000') + ->setHtmlAttribute('autocomplete', 'one-time-code'); + + $form->addSubmit('send', 'Aktivovat 2FA'); + + $form->onSuccess[] = $this->verifyFormSucceeded(...); + + return $form; + } + + public function verifyFormSucceeded(Form $form, \stdClass $data): void + { + $secret = $this->twoFactorSession->get('tempSecret'); + + if (!$secret) { + $this->flashMessage('Relace vypršela, zkuste stránku obnovit.', 'error'); + $this->redirect('this'); + } + + if ($this->twoFactorService->verifyCode($secret, $data->code)) { + /** + * Uživatelská identita = přihlášený user. + * @var UserIdentity + */ + $identity = $this->getUser()->getIdentity(); + + // --- LOGIKA ULOŽENÍ DO DB --- + $this->uzivatelFacade->updateTOTPSecret($secret); + + $this->twoFactorSession->remove(); // Po úspěchu smažeme dočasný klíč + + // Aktualizace identity v session + $identity->twoFactor = true; + $identity->totpSecret = $secret; + + $this->flashMessage('Dvoufázové ověření bylo úspěšně nastaveno.', 'success'); + $this->redirect(':Home:'); + } else { + $form->addError('Zadaný kód není správný. Zkontrolujte čas v telefonu.'); + } + } +} \ No newline at end of file diff --git a/app/Presentation/Setup2fa/default.latte b/app/Presentation/Setup2fa/default.latte new file mode 100644 index 0000000..c5669ce --- /dev/null +++ b/app/Presentation/Setup2fa/default.latte @@ -0,0 +1,82 @@ +{block content} + +
+
+
+
+
+

Nastavení dvoufázového ověření (2FA)

+
+ +
+
+ +
+

1. Přidejte si účet do aplikace

+

Použijte Google Authenticator, Authy nebo Microsoft Authenticator.

+ +
+ QR kód +
+ + + +
+ Ruční klíč: + {$secretKey} +
+
+ +
+

2. Ověřte nastavení

+

Zadejte 6místný kód z aplikace pro potvrzení.

+ + + +
+ {form verifyForm} + +
+ {label code class => "form-label" /} + {input code class => "form-control form-control-lg text-center fw-bold", style => "letter-spacing: 0.3rem;", placeholder => "000 000"} +
+
+ {input send class => "btn btn-success btn-lg"} +
+ {/form} +
+
+ +
+
+ + +
+
+
+
+ + + +{/block} \ No newline at end of file diff --git a/app/Presentation/Sign/SignPresenter.php b/app/Presentation/Sign/SignPresenter.php new file mode 100644 index 0000000..e6402bc --- /dev/null +++ b/app/Presentation/Sign/SignPresenter.php @@ -0,0 +1,160 @@ +twoFactorSession = $session->getSection('2fa_auth'); + // $secret = $this->twoFactorService->generateSecret(); + // bdump($secret); + } + + protected function createComponentSignInForm(): Form + { + $form = new Form(); + $form->addText('username', 'Uživatelské jméno:') + ->setRequired('Prosím vyplňte své uživatelské jméno.') + ->setValue(@$_COOKIE['user']); + + $form->addPassword('password', 'Heslo:'); + // setRequired nepoužívat!! kvůli soft logoutu!!! + //->setRequired('Prosím vyplňte své heslo.'); + + $form->addSubmit('send', 'Přihlásit'); + //$form->addProtection(); //ochrana pomocí TOKENu + + $form->onSuccess[] = $this->signInFormSucceeded(...); + return $form; + } + + private function signInFormSucceeded(Form $form, LoginFormData $data): void //moje vlastní třída LoginFormData + { + try { + // 1. Ověříme heslo přes autentifikátor (manuálně bez volání $this->getUser()->login()) + $identity = $this->autentifikator->authenticate($data->username, $data->password); + + // 2. Zjistíme, zda má uživatel aktivní 2FA (např. má v DB uložený secret) + $twoFactor = $identity->twoFactor ?? false; + + if ($twoFactor) { + // Uživatel MÁ 2FA -> uložíme do session a jdeme na druhý krok + $this->twoFactorSession->identity = $identity; + $this->twoFactorSession->setExpiration('5 minutes'); + $this->redirect('twoFactor'); + } else { + // Uživatel NEMÁ 2FA -> přihlásíme ho hned + $this->getUser()->login($identity); + $this->restoreRequest($this->backlink); + $this->redirect(':Home:'); + } + + } catch (Nette\Security\AuthenticationException $e) { + $form->addError('Neplatné jméno nebo heslo.'); + } + // try { + // $this->getUser()->setAuthenticator($this->autentifikator); // musíme ji registrovat! + + // // validace přihlášení je v třídě MujAutentifikator->authenticate(...) + // $this->getUser()->login($data->username, $data->password); + + // // kam potom? + // $this->restoreRequest($this->backlink); // vrátit se na požadovanou stránku + // $this->redirect(':Home:'); // jinak přejdi sem + // } catch (Nette\Database\ConnectionException) { + // error_log("Obvody - neplatne prihlaseni.", 0); //log je ve var/log/apache2/error.log (fail2ban) + // $form->addError('Neplatné přihlášení.'); + // } catch (Nette\Security\AuthenticationException $e) { + // error_log("Obvody - neplatne prihlaseni.", 0); //log je ve var/log/apache2/error.log (fail2ban) + // $form->addError($e->getMessage()); + // } + } + + protected function createComponentTwoFactorForm(): Form + { + $form = new Form(); + $form->addText('code', 'Ověřovací kód (OTP):') + ->setRequired() + ->addRule($form::Pattern, 'Kód musí mít 6 číslic', '\d{6}') + ->setHtmlAttribute('placeholder', '000 000') + ->setHtmlAttribute('autocomplete', 'one-time-code'); + $form->addSubmit('verify', 'Ověřit a přihlásit'); + $form->onSuccess[] = $this->twoFactorFormSucceeded(...); + return $form; + } + + private function twoFactorFormSucceeded(Form $form, \stdClass $data): void + { + /** + * Uživatelská identita = přihlášený user. + * @var UserIdentity + */ + $identity = $this->twoFactorSession->identity; + + if (!$identity) { + $this->redirect('in'); + } + + bdump($identity); + + // Předpokládáme, že secret je uložen v identitě (z DB) + $secret = $identity->totpSecret ?? null; + + if ($this->twoFactorService->verifyCode($secret, $data->code)) { + // KÓD JE SPRÁVNÝ -> Přihlásíme uživatele do Nette nativně + $this->getUser()->login($identity); + + // Vyčistíme dočasnou session + $this->twoFactorSession->remove(); + + $this->restoreRequest($this->backlink); + $this->redirect(':Home:'); + } else { + $form->addError('Neplatný ověřovací kód.'); + } + } + + public function renderTwoFactor(): void + { + if (!$this->twoFactorSession->identity) { + $this->redirect('in'); + } + } + + public function renderIn(): void + { + } + + /** + * Normalní logout. + * @return void + */ + public function actionOut(): void + { + $this->getUser()->logout(); + $this->flashMessage('Odhlášení bylo úspěšné.'); + $this->redirect('Sign:in'); + } +} \ No newline at end of file diff --git a/app/Presentation/Sign/in.latte b/app/Presentation/Sign/in.latte new file mode 100644 index 0000000..5073066 --- /dev/null +++ b/app/Presentation/Sign/in.latte @@ -0,0 +1,22 @@ +{block content} + +{* {control signInForm} *} +
+
+
+
+ {$error} +
+
+ + +
+ +
+ + +
+ +
+
+
diff --git a/app/Presentation/Sign/twoFactor.latte b/app/Presentation/Sign/twoFactor.latte new file mode 100644 index 0000000..5c0f093 --- /dev/null +++ b/app/Presentation/Sign/twoFactor.latte @@ -0,0 +1,72 @@ +{block content} + +
+
+
+
+
+

Dvoufázové ověření

+
+ +
+
+
+ +
+

+ Otevřete svou autentifikační aplikaci a zadejte 6místný kód pro potvrzení identity. +

+
+ +
+ {$flash->message} +
+ + {form twoFactorForm} + +
+ {input code class => "form-control form-control-lg text-center fw-bold", + style => "letter-spacing: 0.4rem; font-size: 2rem;", + placeholder => "· · · · · ·", + autofocus => true} +
+ +
+ {input verify class => "btn btn-primary btn-lg"} +
+ {/form} +
+ + +
+ +

+ Nemáte přístup k zařízení? Kontaktujte podporu. +

+
+
+
+ + \ No newline at end of file diff --git a/assets/main.js b/assets/main.js new file mode 100644 index 0000000..71729d8 --- /dev/null +++ b/assets/main.js @@ -0,0 +1,4 @@ +// Initialize Nette Forms on page load +import netteForms from 'nette-forms'; + +netteForms.initOnLoad(); diff --git a/composer.json b/composer.json new file mode 100644 index 0000000..916192f --- /dev/null +++ b/composer.json @@ -0,0 +1,46 @@ +{ + "name": "nette/web-project", + "description": "Nette: Standard Web Project", + "keywords": ["nette"], + "type": "project", + "license": ["MIT", "BSD-3-Clause", "GPL-2.0-only", "GPL-3.0-only"], + "require": { + "php": ">= 8.2", + "nette/application": "^3.2.3", + "nette/assets": "^1.0.0", + "nette/bootstrap": "^3.2.6", + "nette/caching": "^3.2", + "nette/database": "^3.2", + "nette/di": "^3.2", + "nette/forms": "^3.2", + "nette/http": "^3.3", + "nette/mail": "^4.0", + "nette/robot-loader": "^4.0", + "nette/security": "^3.2", + "nette/utils": "^4.0", + "latte/latte": "^3.1", + "tracy/tracy": "^2.10", + "spomky-labs/otphp": "^11.4", + "endroid/qr-code": "^6.0" + }, + "require-dev": { + "nette/tester": "^2.5", + "phpstan/phpstan-nette": "^2", + "symfony/thanks": "^1" + }, + "autoload": { + "psr-4": { + "App\\": "app" + } + }, + "scripts": { + "phpstan": "phpstan analyse", + "tester": "tester tests -s" + }, + "minimum-stability": "stable", + "config": { + "allow-plugins": { + "symfony/thanks": true + } + } +} diff --git a/composer.lock b/composer.lock new file mode 100644 index 0000000..f0d6255 --- /dev/null +++ b/composer.lock @@ -0,0 +1,2172 @@ +{ + "_readme": [ + "This file locks the dependencies of your project to a known state", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", + "This file is @generated automatically" + ], + "content-hash": "08ee95b1dc1fc7ee6aa46115e415d4b8", + "packages": [ + { + "name": "bacon/bacon-qr-code", + "version": "v3.0.3", + "source": { + "type": "git", + "url": "https://github.com/Bacon/BaconQrCode.git", + "reference": "36a1cb2b81493fa5b82e50bf8068bf84d1542563" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Bacon/BaconQrCode/zipball/36a1cb2b81493fa5b82e50bf8068bf84d1542563", + "reference": "36a1cb2b81493fa5b82e50bf8068bf84d1542563", + "shasum": "" + }, + "require": { + "dasprid/enum": "^1.0.3", + "ext-iconv": "*", + "php": "^8.1" + }, + "require-dev": { + "phly/keep-a-changelog": "^2.12", + "phpunit/phpunit": "^10.5.11 || ^11.0.4", + "spatie/phpunit-snapshot-assertions": "^5.1.5", + "spatie/pixelmatch-php": "^1.2.0", + "squizlabs/php_codesniffer": "^3.9" + }, + "suggest": { + "ext-imagick": "to generate QR code images" + }, + "type": "library", + "autoload": { + "psr-4": { + "BaconQrCode\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-2-Clause" + ], + "authors": [ + { + "name": "Ben Scholzen 'DASPRiD'", + "email": "mail@dasprids.de", + "homepage": "https://dasprids.de/", + "role": "Developer" + } + ], + "description": "BaconQrCode is a QR code generator for PHP.", + "homepage": "https://github.com/Bacon/BaconQrCode", + "support": { + "issues": "https://github.com/Bacon/BaconQrCode/issues", + "source": "https://github.com/Bacon/BaconQrCode/tree/v3.0.3" + }, + "time": "2025-11-19T17:15:36+00:00" + }, + { + "name": "dasprid/enum", + "version": "1.0.7", + "source": { + "type": "git", + "url": "https://github.com/DASPRiD/Enum.git", + "reference": "b5874fa9ed0043116c72162ec7f4fb50e02e7cce" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/DASPRiD/Enum/zipball/b5874fa9ed0043116c72162ec7f4fb50e02e7cce", + "reference": "b5874fa9ed0043116c72162ec7f4fb50e02e7cce", + "shasum": "" + }, + "require": { + "php": ">=7.1 <9.0" + }, + "require-dev": { + "phpunit/phpunit": "^7 || ^8 || ^9 || ^10 || ^11", + "squizlabs/php_codesniffer": "*" + }, + "type": "library", + "autoload": { + "psr-4": { + "DASPRiD\\Enum\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-2-Clause" + ], + "authors": [ + { + "name": "Ben Scholzen 'DASPRiD'", + "email": "mail@dasprids.de", + "homepage": "https://dasprids.de/", + "role": "Developer" + } + ], + "description": "PHP 7.1 enum implementation", + "keywords": [ + "enum", + "map" + ], + "support": { + "issues": "https://github.com/DASPRiD/Enum/issues", + "source": "https://github.com/DASPRiD/Enum/tree/1.0.7" + }, + "time": "2025-09-16T12:23:56+00:00" + }, + { + "name": "endroid/qr-code", + "version": "6.0.9", + "source": { + "type": "git", + "url": "https://github.com/endroid/qr-code.git", + "reference": "21e888e8597440b2205e2e5c484b6c8e556bcd1a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/endroid/qr-code/zipball/21e888e8597440b2205e2e5c484b6c8e556bcd1a", + "reference": "21e888e8597440b2205e2e5c484b6c8e556bcd1a", + "shasum": "" + }, + "require": { + "bacon/bacon-qr-code": "^3.0", + "php": "^8.2" + }, + "require-dev": { + "endroid/quality": "dev-main", + "ext-gd": "*", + "khanamiryan/qrcode-detector-decoder": "^2.0.2", + "setasign/fpdf": "^1.8.2" + }, + "suggest": { + "ext-gd": "Enables you to write PNG images", + "khanamiryan/qrcode-detector-decoder": "Enables you to use the image validator", + "roave/security-advisories": "Makes sure package versions with known security issues are not installed", + "setasign/fpdf": "Enables you to use the PDF writer" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "6.x-dev" + } + }, + "autoload": { + "psr-4": { + "Endroid\\QrCode\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jeroen van den Enden", + "email": "info@endroid.nl" + } + ], + "description": "Endroid QR Code", + "homepage": "https://github.com/endroid/qr-code", + "keywords": [ + "code", + "endroid", + "php", + "qr", + "qrcode" + ], + "support": { + "issues": "https://github.com/endroid/qr-code/issues", + "source": "https://github.com/endroid/qr-code/tree/6.0.9" + }, + "funding": [ + { + "url": "https://github.com/endroid", + "type": "github" + } + ], + "time": "2025-07-13T19:59:45+00:00" + }, + { + "name": "latte/latte", + "version": "v3.1.1", + "source": { + "type": "git", + "url": "https://github.com/nette/latte.git", + "reference": "cb98e705eeb0fd18f1f1c5cfe1a5f6217f9fa8b3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nette/latte/zipball/cb98e705eeb0fd18f1f1c5cfe1a5f6217f9fa8b3", + "reference": "cb98e705eeb0fd18f1f1c5cfe1a5f6217f9fa8b3", + "shasum": "" + }, + "require": { + "ext-json": "*", + "ext-tokenizer": "*", + "php": "8.2 - 8.5" + }, + "conflict": { + "nette/application": "<3.1.7", + "nette/caching": "<3.1.4" + }, + "require-dev": { + "nette/php-generator": "^4.0", + "nette/tester": "^2.5", + "nette/utils": "^4.0", + "phpstan/phpstan-nette": "^2.0@stable", + "tracy/tracy": "^2.10" + }, + "suggest": { + "ext-fileinfo": "to use filter |datastream", + "ext-iconv": "to use filters |reverse, |substring", + "ext-intl": "to use Latte\\Engine::setLocale()", + "ext-mbstring": "to use filters like lower, upper, capitalize, ...", + "nette/php-generator": "to use tag {templatePrint}", + "nette/utils": "to use filter |webalize" + }, + "bin": [ + "bin/latte-lint" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.1-dev" + } + }, + "autoload": { + "psr-4": { + "Latte\\": "src/Latte" + }, + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause", + "GPL-2.0-only", + "GPL-3.0-only" + ], + "authors": [ + { + "name": "David Grudl", + "homepage": "https://davidgrudl.com" + }, + { + "name": "Nette Community", + "homepage": "https://nette.org/contributors" + } + ], + "description": "☕ Latte: the intuitive and fast template engine for those who want the most secure PHP sites. Introduces context-sensitive escaping.", + "homepage": "https://latte.nette.org", + "keywords": [ + "context-sensitive", + "engine", + "escaping", + "html", + "nette", + "security", + "template", + "twig" + ], + "support": { + "issues": "https://github.com/nette/latte/issues", + "source": "https://github.com/nette/latte/tree/v3.1.1" + }, + "time": "2025-12-18T22:30:40+00:00" + }, + { + "name": "nette/application", + "version": "v3.2.9", + "source": { + "type": "git", + "url": "https://github.com/nette/application.git", + "reference": "11d9d6fc53d579a3516c1574c707a5de281bc0a0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nette/application/zipball/11d9d6fc53d579a3516c1574c707a5de281bc0a0", + "reference": "11d9d6fc53d579a3516c1574c707a5de281bc0a0", + "shasum": "" + }, + "require": { + "nette/component-model": "^3.1", + "nette/http": "^3.3.2", + "nette/routing": "^3.1.1", + "nette/utils": "^4.0", + "php": "8.1 - 8.5" + }, + "conflict": { + "latte/latte": "<2.7.1 || >=3.0.0 <3.0.18 || >=3.2", + "nette/caching": "<3.2", + "nette/di": "<3.2", + "nette/forms": "<3.2", + "nette/schema": "<1.3", + "tracy/tracy": "<2.9" + }, + "require-dev": { + "jetbrains/phpstorm-attributes": "^1.2", + "latte/latte": "^2.10.2 || ^3.0.18", + "mockery/mockery": "^1.6@stable", + "nette/di": "^3.2", + "nette/forms": "^3.2", + "nette/robot-loader": "^4.0", + "nette/security": "^3.2", + "nette/tester": "^2.5.2", + "phpstan/phpstan-nette": "^2.0@stable", + "tracy/tracy": "^2.9" + }, + "suggest": { + "latte/latte": "Allows using Latte in templates", + "nette/forms": "Allows to use Nette\\Application\\UI\\Form" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.2-dev" + } + }, + "autoload": { + "psr-4": { + "Nette\\": "src" + }, + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause", + "GPL-2.0-only", + "GPL-3.0-only" + ], + "authors": [ + { + "name": "David Grudl", + "homepage": "https://davidgrudl.com" + }, + { + "name": "Nette Community", + "homepage": "https://nette.org/contributors" + } + ], + "description": "🏆 Nette Application: a full-stack component-based MVC kernel for PHP that helps you write powerful and modern web applications. Write less, have cleaner code and your work will bring you joy.", + "homepage": "https://nette.org", + "keywords": [ + "Forms", + "component-based", + "control", + "framework", + "mvc", + "mvp", + "nette", + "presenter", + "routing", + "seo" + ], + "support": { + "issues": "https://github.com/nette/application/issues", + "source": "https://github.com/nette/application/tree/v3.2.9" + }, + "time": "2025-12-19T11:39:00+00:00" + }, + { + "name": "nette/assets", + "version": "v1.0.5", + "source": { + "type": "git", + "url": "https://github.com/nette/assets.git", + "reference": "d747983c8a8ee5e8508ab9b45282c869e6b1f623" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nette/assets/zipball/d747983c8a8ee5e8508ab9b45282c869e6b1f623", + "reference": "d747983c8a8ee5e8508ab9b45282c869e6b1f623", + "shasum": "" + }, + "require": { + "nette/utils": "^4.0.6", + "php": "8.1 - 8.5" + }, + "conflict": { + "nette/bootstrap": "<3.2.5", + "nette/http": "<3.3.2" + }, + "require-dev": { + "latte/latte": "^3.0.22", + "mockery/mockery": "^1.6@stable", + "nette/application": "^3.2", + "nette/di": "^3.2", + "nette/http": "^3.3.2", + "nette/tester": "^2.5", + "phpstan/phpstan-nette": "^2.0@stable", + "tracy/tracy": "^2.9" + }, + "suggest": { + "latte/latte": "Allows using Assets in templates" + }, + "type": "library", + "autoload": { + "psr-4": { + "Nette\\": "src" + }, + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause", + "GPL-2.0-only", + "GPL-3.0-only" + ], + "authors": [ + { + "name": "David Grudl", + "homepage": "https://davidgrudl.com" + }, + { + "name": "Nette Community", + "homepage": "https://nette.org/contributors" + } + ], + "description": "🎨 Nette Assets: elegant asset management for PHP with versioning, caching and mappers for various storage backends.", + "homepage": "https://nette.org", + "keywords": [ + "asset management", + "assets", + "nette", + "resources", + "static files", + "versioning" + ], + "support": { + "issues": "https://github.com/nette/assets/issues", + "source": "https://github.com/nette/assets/tree/v1.0.5" + }, + "time": "2025-11-24T02:49:53+00:00" + }, + { + "name": "nette/bootstrap", + "version": "v3.2.7", + "source": { + "type": "git", + "url": "https://github.com/nette/bootstrap.git", + "reference": "10fdb1cb05497da39396f2ce1785cea67c8aa439" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nette/bootstrap/zipball/10fdb1cb05497da39396f2ce1785cea67c8aa439", + "reference": "10fdb1cb05497da39396f2ce1785cea67c8aa439", + "shasum": "" + }, + "require": { + "nette/di": "^3.1", + "nette/utils": "^3.2.1 || ^4.0", + "php": "8.0 - 8.5" + }, + "conflict": { + "tracy/tracy": "<2.6" + }, + "require-dev": { + "latte/latte": "^2.8 || ^3.0", + "nette/application": "^3.1", + "nette/caching": "^3.0", + "nette/database": "^3.0", + "nette/forms": "^3.0", + "nette/http": "^3.0", + "nette/mail": "^3.0 || ^4.0", + "nette/robot-loader": "^3.0 || ^4.0", + "nette/safe-stream": "^2.2", + "nette/security": "^3.0", + "nette/tester": "^2.4", + "phpstan/phpstan-nette": "^2.0@stable", + "tracy/tracy": "^2.9" + }, + "suggest": { + "nette/robot-loader": "to use Configurator::createRobotLoader()", + "tracy/tracy": "to use Configurator::enableTracy()" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.2-dev" + } + }, + "autoload": { + "psr-4": { + "Nette\\": "src" + }, + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause", + "GPL-2.0-only", + "GPL-3.0-only" + ], + "authors": [ + { + "name": "David Grudl", + "homepage": "https://davidgrudl.com" + }, + { + "name": "Nette Community", + "homepage": "https://nette.org/contributors" + } + ], + "description": "🅱 Nette Bootstrap: the simple way to configure and bootstrap your Nette application.", + "homepage": "https://nette.org", + "keywords": [ + "bootstrapping", + "configurator", + "nette" + ], + "support": { + "issues": "https://github.com/nette/bootstrap/issues", + "source": "https://github.com/nette/bootstrap/tree/v3.2.7" + }, + "time": "2025-08-01T02:02:03+00:00" + }, + { + "name": "nette/caching", + "version": "v3.4.0", + "source": { + "type": "git", + "url": "https://github.com/nette/caching.git", + "reference": "a1c13221b350d0db0a2bd4a77c1e7b65e0aa065d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nette/caching/zipball/a1c13221b350d0db0a2bd4a77c1e7b65e0aa065d", + "reference": "a1c13221b350d0db0a2bd4a77c1e7b65e0aa065d", + "shasum": "" + }, + "require": { + "nette/utils": "^4.0", + "php": "8.1 - 8.5" + }, + "conflict": { + "latte/latte": "<3.0.12" + }, + "require-dev": { + "latte/latte": "^3.0.12", + "nette/di": "^3.1 || ^4.0", + "nette/tester": "^2.4", + "phpstan/phpstan-nette": "^2.0@stable", + "psr/simple-cache": "^2.0 || ^3.0", + "tracy/tracy": "^2.9" + }, + "suggest": { + "ext-pdo_sqlite": "to use SQLiteStorage or SQLiteJournal" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.4-dev" + } + }, + "autoload": { + "psr-4": { + "Nette\\": "src" + }, + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause", + "GPL-2.0-only", + "GPL-3.0-only" + ], + "authors": [ + { + "name": "David Grudl", + "homepage": "https://davidgrudl.com" + }, + { + "name": "Nette Community", + "homepage": "https://nette.org/contributors" + } + ], + "description": "⏱ Nette Caching: library with easy-to-use API and many cache backends.", + "homepage": "https://nette.org", + "keywords": [ + "cache", + "journal", + "memcached", + "nette", + "sqlite" + ], + "support": { + "issues": "https://github.com/nette/caching/issues", + "source": "https://github.com/nette/caching/tree/v3.4.0" + }, + "time": "2025-08-06T23:05:08+00:00" + }, + { + "name": "nette/component-model", + "version": "v3.1.3", + "source": { + "type": "git", + "url": "https://github.com/nette/component-model.git", + "reference": "0d100ba05279a1f4b20acecaa617027fbda8ecb2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nette/component-model/zipball/0d100ba05279a1f4b20acecaa617027fbda8ecb2", + "reference": "0d100ba05279a1f4b20acecaa617027fbda8ecb2", + "shasum": "" + }, + "require": { + "nette/utils": "^4.0", + "php": "8.1 - 8.5" + }, + "require-dev": { + "nette/tester": "^2.5", + "phpstan/phpstan-nette": "^2.0@stable", + "tracy/tracy": "^2.9" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.1-dev" + } + }, + "autoload": { + "psr-4": { + "Nette\\": "src" + }, + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause", + "GPL-2.0-only", + "GPL-3.0-only" + ], + "authors": [ + { + "name": "David Grudl", + "homepage": "https://davidgrudl.com" + }, + { + "name": "Nette Community", + "homepage": "https://nette.org/contributors" + } + ], + "description": "⚛ Nette Component Model", + "homepage": "https://nette.org", + "keywords": [ + "components", + "nette" + ], + "support": { + "issues": "https://github.com/nette/component-model/issues", + "source": "https://github.com/nette/component-model/tree/v3.1.3" + }, + "time": "2025-11-22T18:56:33+00:00" + }, + { + "name": "nette/database", + "version": "v3.2.8", + "source": { + "type": "git", + "url": "https://github.com/nette/database.git", + "reference": "1a84d3e61aa33461a3d6415235b25a7cd8b3f442" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nette/database/zipball/1a84d3e61aa33461a3d6415235b25a7cd8b3f442", + "reference": "1a84d3e61aa33461a3d6415235b25a7cd8b3f442", + "shasum": "" + }, + "require": { + "ext-pdo": "*", + "nette/caching": "^3.2", + "nette/utils": "^4.0", + "php": "8.1 - 8.5" + }, + "require-dev": { + "jetbrains/phpstorm-attributes": "^1.2", + "mockery/mockery": "^1.6@stable", + "nette/di": "^3.1", + "nette/tester": "^2.5", + "phpstan/phpstan-nette": "^2.0@stable", + "tracy/tracy": "^2.9" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.2-dev" + } + }, + "autoload": { + "psr-4": { + "Nette\\": "src" + }, + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause", + "GPL-2.0-only", + "GPL-3.0-only" + ], + "authors": [ + { + "name": "David Grudl", + "homepage": "https://davidgrudl.com" + }, + { + "name": "Nette Community", + "homepage": "https://nette.org/contributors" + } + ], + "description": "💾 Nette Database: layer with a familiar PDO-like API but much more powerful. Building queries, advanced joins, drivers for MySQL, PostgreSQL, SQLite, MS SQL Server and Oracle.", + "homepage": "https://nette.org", + "keywords": [ + "database", + "mssql", + "mysql", + "nette", + "notorm", + "oracle", + "pdo", + "postgresql", + "queries", + "sqlite" + ], + "support": { + "issues": "https://github.com/nette/database/issues", + "source": "https://github.com/nette/database/tree/v3.2.8" + }, + "time": "2025-10-30T22:06:23+00:00" + }, + { + "name": "nette/di", + "version": "v3.2.5", + "source": { + "type": "git", + "url": "https://github.com/nette/di.git", + "reference": "5708c328ce7658a73c96b14dd6da7b8b27bf220f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nette/di/zipball/5708c328ce7658a73c96b14dd6da7b8b27bf220f", + "reference": "5708c328ce7658a73c96b14dd6da7b8b27bf220f", + "shasum": "" + }, + "require": { + "ext-ctype": "*", + "ext-tokenizer": "*", + "nette/neon": "^3.3", + "nette/php-generator": "^4.1.6", + "nette/robot-loader": "^4.0", + "nette/schema": "^1.2.5", + "nette/utils": "^4.0", + "php": "8.1 - 8.5" + }, + "require-dev": { + "nette/tester": "^2.5.2", + "phpstan/phpstan-nette": "^2.0@stable", + "tracy/tracy": "^2.9" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.2-dev" + } + }, + "autoload": { + "psr-4": { + "Nette\\": "src" + }, + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause", + "GPL-2.0-only", + "GPL-3.0-only" + ], + "authors": [ + { + "name": "David Grudl", + "homepage": "https://davidgrudl.com" + }, + { + "name": "Nette Community", + "homepage": "https://nette.org/contributors" + } + ], + "description": "💎 Nette Dependency Injection Container: Flexible, compiled and full-featured DIC with perfectly usable autowiring and support for all new PHP features.", + "homepage": "https://nette.org", + "keywords": [ + "compiled", + "di", + "dic", + "factory", + "ioc", + "nette", + "static" + ], + "support": { + "issues": "https://github.com/nette/di/issues", + "source": "https://github.com/nette/di/tree/v3.2.5" + }, + "time": "2025-08-14T22:59:46+00:00" + }, + { + "name": "nette/forms", + "version": "v3.2.8", + "source": { + "type": "git", + "url": "https://github.com/nette/forms.git", + "reference": "3bbf691ea0eb50d9594c2109d9252f267092b91f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nette/forms/zipball/3bbf691ea0eb50d9594c2109d9252f267092b91f", + "reference": "3bbf691ea0eb50d9594c2109d9252f267092b91f", + "shasum": "" + }, + "require": { + "nette/component-model": "^3.1", + "nette/http": "^3.3", + "nette/utils": "^4.0.4", + "php": "8.1 - 8.5" + }, + "conflict": { + "latte/latte": ">=3.0.0 <3.0.12 || >=3.2" + }, + "require-dev": { + "latte/latte": "^2.10.2 || ^3.0.12", + "nette/application": "^3.0", + "nette/di": "^3.0", + "nette/tester": "^2.5.2", + "phpstan/phpstan-nette": "^2.0@stable", + "tracy/tracy": "^2.9" + }, + "suggest": { + "ext-intl": "to use date/time controls" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.2-dev" + } + }, + "autoload": { + "psr-4": { + "Nette\\": "src" + }, + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause", + "GPL-2.0-only", + "GPL-3.0-only" + ], + "authors": [ + { + "name": "David Grudl", + "homepage": "https://davidgrudl.com" + }, + { + "name": "Nette Community", + "homepage": "https://nette.org/contributors" + } + ], + "description": "📝 Nette Forms: generating, validating and processing secure forms in PHP. Handy API, fully customizable, server & client side validation and mature design.", + "homepage": "https://nette.org", + "keywords": [ + "Forms", + "bootstrap", + "csrf", + "javascript", + "nette", + "validation" + ], + "support": { + "issues": "https://github.com/nette/forms/issues", + "source": "https://github.com/nette/forms/tree/v3.2.8" + }, + "time": "2025-11-22T19:36:34+00:00" + }, + { + "name": "nette/http", + "version": "v3.3.3", + "source": { + "type": "git", + "url": "https://github.com/nette/http.git", + "reference": "c557f21c8cedd621dbfd7990752b1d55ef353f1d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nette/http/zipball/c557f21c8cedd621dbfd7990752b1d55ef353f1d", + "reference": "c557f21c8cedd621dbfd7990752b1d55ef353f1d", + "shasum": "" + }, + "require": { + "nette/utils": "^4.0.4", + "php": "8.1 - 8.5" + }, + "conflict": { + "nette/di": "<3.0.3", + "nette/schema": "<1.2" + }, + "require-dev": { + "nette/di": "^3.0", + "nette/security": "^3.0", + "nette/tester": "^2.4", + "phpstan/phpstan-nette": "^2.0@stable", + "tracy/tracy": "^2.8" + }, + "suggest": { + "ext-fileinfo": "to detect MIME type of uploaded files by Nette\\Http\\FileUpload", + "ext-gd": "to use image function in Nette\\Http\\FileUpload", + "ext-intl": "to support punycode by Nette\\Http\\Url", + "ext-session": "to use Nette\\Http\\Session" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.3-dev" + } + }, + "autoload": { + "psr-4": { + "Nette\\": "src" + }, + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause", + "GPL-2.0-only", + "GPL-3.0-only" + ], + "authors": [ + { + "name": "David Grudl", + "homepage": "https://davidgrudl.com" + }, + { + "name": "Nette Community", + "homepage": "https://nette.org/contributors" + } + ], + "description": "🌐 Nette Http: abstraction for HTTP request, response and session. Provides careful data sanitization and utility for URL and cookies manipulation.", + "homepage": "https://nette.org", + "keywords": [ + "cookies", + "http", + "nette", + "proxy", + "request", + "response", + "security", + "session", + "url" + ], + "support": { + "issues": "https://github.com/nette/http/issues", + "source": "https://github.com/nette/http/tree/v3.3.3" + }, + "time": "2025-10-30T22:32:24+00:00" + }, + { + "name": "nette/mail", + "version": "v4.0.4", + "source": { + "type": "git", + "url": "https://github.com/nette/mail.git", + "reference": "5f16f76ed14a32f34580811d1a07ac357352bbc4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nette/mail/zipball/5f16f76ed14a32f34580811d1a07ac357352bbc4", + "reference": "5f16f76ed14a32f34580811d1a07ac357352bbc4", + "shasum": "" + }, + "require": { + "ext-iconv": "*", + "nette/utils": "^4.0", + "php": "8.0 - 8.5" + }, + "require-dev": { + "nette/di": "^3.1 || ^4.0", + "nette/tester": "^2.4", + "phpstan/phpstan-nette": "^2.0@stable", + "tracy/tracy": "^2.8" + }, + "suggest": { + "ext-fileinfo": "to detect type of attached files", + "ext-openssl": "to use Nette\\Mail\\DkimSigner" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0-dev" + } + }, + "autoload": { + "psr-4": { + "Nette\\": "src" + }, + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause", + "GPL-2.0-only", + "GPL-3.0-only" + ], + "authors": [ + { + "name": "David Grudl", + "homepage": "https://davidgrudl.com" + }, + { + "name": "Nette Community", + "homepage": "https://nette.org/contributors" + } + ], + "description": "📧 Nette Mail: A handy library for creating and sending emails in PHP.", + "homepage": "https://nette.org", + "keywords": [ + "mail", + "mailer", + "mime", + "nette", + "smtp" + ], + "support": { + "issues": "https://github.com/nette/mail/issues", + "source": "https://github.com/nette/mail/tree/v4.0.4" + }, + "time": "2025-08-01T02:09:42+00:00" + }, + { + "name": "nette/neon", + "version": "v3.4.7", + "source": { + "type": "git", + "url": "https://github.com/nette/neon.git", + "reference": "cc96bf5264d721d0c102bb976272d3d001a23e65" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nette/neon/zipball/cc96bf5264d721d0c102bb976272d3d001a23e65", + "reference": "cc96bf5264d721d0c102bb976272d3d001a23e65", + "shasum": "" + }, + "require": { + "ext-json": "*", + "php": "8.0 - 8.5" + }, + "require-dev": { + "nette/tester": "^2.4", + "phpstan/phpstan-nette": "^2.0@stable", + "tracy/tracy": "^2.7" + }, + "bin": [ + "bin/neon-lint" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.4-dev" + } + }, + "autoload": { + "psr-4": { + "Nette\\": "src" + }, + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause", + "GPL-2.0-only", + "GPL-3.0-only" + ], + "authors": [ + { + "name": "David Grudl", + "homepage": "https://davidgrudl.com" + }, + { + "name": "Nette Community", + "homepage": "https://nette.org/contributors" + } + ], + "description": "🍸 Nette NEON: encodes and decodes NEON file format.", + "homepage": "https://neon.nette.org", + "keywords": [ + "export", + "import", + "neon", + "nette", + "yaml" + ], + "support": { + "issues": "https://github.com/nette/neon/issues", + "source": "https://github.com/nette/neon/tree/v3.4.7" + }, + "time": "2026-01-04T08:39:50+00:00" + }, + { + "name": "nette/php-generator", + "version": "v4.2.0", + "source": { + "type": "git", + "url": "https://github.com/nette/php-generator.git", + "reference": "4707546a1f11badd72f5d82af4f8a6bc64bd56ac" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nette/php-generator/zipball/4707546a1f11badd72f5d82af4f8a6bc64bd56ac", + "reference": "4707546a1f11badd72f5d82af4f8a6bc64bd56ac", + "shasum": "" + }, + "require": { + "nette/utils": "^4.0.6", + "php": "8.1 - 8.5" + }, + "require-dev": { + "jetbrains/phpstorm-attributes": "^1.2", + "nette/tester": "^2.4", + "nikic/php-parser": "^5.0", + "phpstan/phpstan-nette": "^2.0@stable", + "tracy/tracy": "^2.8" + }, + "suggest": { + "nikic/php-parser": "to use ClassType::from(withBodies: true) & ClassType::fromCode()" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.2-dev" + } + }, + "autoload": { + "psr-4": { + "Nette\\": "src" + }, + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause", + "GPL-2.0-only", + "GPL-3.0-only" + ], + "authors": [ + { + "name": "David Grudl", + "homepage": "https://davidgrudl.com" + }, + { + "name": "Nette Community", + "homepage": "https://nette.org/contributors" + } + ], + "description": "🐘 Nette PHP Generator: generates neat PHP code for you. Supports new PHP 8.5 features.", + "homepage": "https://nette.org", + "keywords": [ + "code", + "nette", + "php", + "scaffolding" + ], + "support": { + "issues": "https://github.com/nette/php-generator/issues", + "source": "https://github.com/nette/php-generator/tree/v4.2.0" + }, + "time": "2025-08-06T18:24:31+00:00" + }, + { + "name": "nette/robot-loader", + "version": "v4.1.0", + "source": { + "type": "git", + "url": "https://github.com/nette/robot-loader.git", + "reference": "805fb81376c24755d50bdb8bc69ca4db3def71d1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nette/robot-loader/zipball/805fb81376c24755d50bdb8bc69ca4db3def71d1", + "reference": "805fb81376c24755d50bdb8bc69ca4db3def71d1", + "shasum": "" + }, + "require": { + "ext-tokenizer": "*", + "nette/utils": "^4.0", + "php": "8.1 - 8.5" + }, + "require-dev": { + "nette/tester": "^2.4", + "phpstan/phpstan-nette": "^2.0@stable", + "tracy/tracy": "^2.9" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.1-dev" + } + }, + "autoload": { + "psr-4": { + "Nette\\": "src" + }, + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause", + "GPL-2.0-only", + "GPL-3.0-only" + ], + "authors": [ + { + "name": "David Grudl", + "homepage": "https://davidgrudl.com" + }, + { + "name": "Nette Community", + "homepage": "https://nette.org/contributors" + } + ], + "description": "🍀 Nette RobotLoader: high performance and comfortable autoloader that will search and autoload classes within your application.", + "homepage": "https://nette.org", + "keywords": [ + "autoload", + "class", + "interface", + "nette", + "trait" + ], + "support": { + "issues": "https://github.com/nette/robot-loader/issues", + "source": "https://github.com/nette/robot-loader/tree/v4.1.0" + }, + "time": "2025-08-06T18:34:21+00:00" + }, + { + "name": "nette/routing", + "version": "v3.1.2", + "source": { + "type": "git", + "url": "https://github.com/nette/routing.git", + "reference": "14c466f3383add0d4f78a82074d3c9841f8edf47" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nette/routing/zipball/14c466f3383add0d4f78a82074d3c9841f8edf47", + "reference": "14c466f3383add0d4f78a82074d3c9841f8edf47", + "shasum": "" + }, + "require": { + "nette/http": "^3.2 || ~4.0.0", + "nette/utils": "^4.0", + "php": "8.1 - 8.5" + }, + "require-dev": { + "nette/tester": "^2.5", + "phpstan/phpstan-nette": "^2.0@stable", + "tracy/tracy": "^2.9" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.1-dev" + } + }, + "autoload": { + "psr-4": { + "Nette\\": "src" + }, + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause", + "GPL-2.0-only", + "GPL-3.0-only" + ], + "authors": [ + { + "name": "David Grudl", + "homepage": "https://davidgrudl.com" + }, + { + "name": "Nette Community", + "homepage": "https://nette.org/contributors" + } + ], + "description": "Nette Routing: two-ways URL conversion", + "homepage": "https://nette.org", + "keywords": [ + "nette" + ], + "support": { + "issues": "https://github.com/nette/routing/issues", + "source": "https://github.com/nette/routing/tree/v3.1.2" + }, + "time": "2025-10-31T00:55:27+00:00" + }, + { + "name": "nette/schema", + "version": "v1.3.3", + "source": { + "type": "git", + "url": "https://github.com/nette/schema.git", + "reference": "2befc2f42d7c715fd9d95efc31b1081e5d765004" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nette/schema/zipball/2befc2f42d7c715fd9d95efc31b1081e5d765004", + "reference": "2befc2f42d7c715fd9d95efc31b1081e5d765004", + "shasum": "" + }, + "require": { + "nette/utils": "^4.0", + "php": "8.1 - 8.5" + }, + "require-dev": { + "nette/tester": "^2.5.2", + "phpstan/phpstan-nette": "^2.0@stable", + "tracy/tracy": "^2.8" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.3-dev" + } + }, + "autoload": { + "psr-4": { + "Nette\\": "src" + }, + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause", + "GPL-2.0-only", + "GPL-3.0-only" + ], + "authors": [ + { + "name": "David Grudl", + "homepage": "https://davidgrudl.com" + }, + { + "name": "Nette Community", + "homepage": "https://nette.org/contributors" + } + ], + "description": "📐 Nette Schema: validating data structures against a given Schema.", + "homepage": "https://nette.org", + "keywords": [ + "config", + "nette" + ], + "support": { + "issues": "https://github.com/nette/schema/issues", + "source": "https://github.com/nette/schema/tree/v1.3.3" + }, + "time": "2025-10-30T22:57:59+00:00" + }, + { + "name": "nette/security", + "version": "v3.2.2", + "source": { + "type": "git", + "url": "https://github.com/nette/security.git", + "reference": "beca6757457281ebc9428743bec7960809f40d49" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nette/security/zipball/beca6757457281ebc9428743bec7960809f40d49", + "reference": "beca6757457281ebc9428743bec7960809f40d49", + "shasum": "" + }, + "require": { + "nette/utils": "^4.0", + "php": "8.1 - 8.5" + }, + "conflict": { + "nette/di": "<3.0-stable", + "nette/http": "<3.1.3" + }, + "require-dev": { + "mockery/mockery": "^1.6@stable", + "nette/di": "^3.1", + "nette/http": "^3.2", + "nette/tester": "^2.5", + "phpstan/phpstan-nette": "^2.0@stable", + "tracy/tracy": "^2.9" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.2-dev" + } + }, + "autoload": { + "psr-4": { + "Nette\\": "src" + }, + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause", + "GPL-2.0-only", + "GPL-3.0-only" + ], + "authors": [ + { + "name": "David Grudl", + "homepage": "https://davidgrudl.com" + }, + { + "name": "Nette Community", + "homepage": "https://nette.org/contributors" + } + ], + "description": "🔑 Nette Security: provides authentication, authorization and a role-based access control management via ACL (Access Control List)", + "homepage": "https://nette.org", + "keywords": [ + "Authentication", + "acl", + "authorization", + "nette" + ], + "support": { + "issues": "https://github.com/nette/security/issues", + "source": "https://github.com/nette/security/tree/v3.2.2" + }, + "time": "2025-08-01T02:15:08+00:00" + }, + { + "name": "nette/utils", + "version": "v4.1.1", + "source": { + "type": "git", + "url": "https://github.com/nette/utils.git", + "reference": "c99059c0315591f1a0db7ad6002000288ab8dc72" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nette/utils/zipball/c99059c0315591f1a0db7ad6002000288ab8dc72", + "reference": "c99059c0315591f1a0db7ad6002000288ab8dc72", + "shasum": "" + }, + "require": { + "php": "8.2 - 8.5" + }, + "conflict": { + "nette/finder": "<3", + "nette/schema": "<1.2.2" + }, + "require-dev": { + "jetbrains/phpstorm-attributes": "^1.2", + "nette/tester": "^2.5", + "phpstan/phpstan-nette": "^2.0@stable", + "tracy/tracy": "^2.9" + }, + "suggest": { + "ext-gd": "to use Image", + "ext-iconv": "to use Strings::webalize(), toAscii(), chr() and reverse()", + "ext-intl": "to use Strings::webalize(), toAscii(), normalize() and compare()", + "ext-json": "to use Nette\\Utils\\Json", + "ext-mbstring": "to use Strings::lower() etc...", + "ext-tokenizer": "to use Nette\\Utils\\Reflection::getUseStatements()" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.1-dev" + } + }, + "autoload": { + "psr-4": { + "Nette\\": "src" + }, + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause", + "GPL-2.0-only", + "GPL-3.0-only" + ], + "authors": [ + { + "name": "David Grudl", + "homepage": "https://davidgrudl.com" + }, + { + "name": "Nette Community", + "homepage": "https://nette.org/contributors" + } + ], + "description": "🛠 Nette Utils: lightweight utilities for string & array manipulation, image handling, safe JSON encoding/decoding, validation, slug or strong password generating etc.", + "homepage": "https://nette.org", + "keywords": [ + "array", + "core", + "datetime", + "images", + "json", + "nette", + "paginator", + "password", + "slugify", + "string", + "unicode", + "utf-8", + "utility", + "validation" + ], + "support": { + "issues": "https://github.com/nette/utils/issues", + "source": "https://github.com/nette/utils/tree/v4.1.1" + }, + "time": "2025-12-22T12:14:32+00:00" + }, + { + "name": "paragonie/constant_time_encoding", + "version": "v3.1.3", + "source": { + "type": "git", + "url": "https://github.com/paragonie/constant_time_encoding.git", + "reference": "d5b01a39b3415c2cd581d3bd3a3575c1ebbd8e77" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/paragonie/constant_time_encoding/zipball/d5b01a39b3415c2cd581d3bd3a3575c1ebbd8e77", + "reference": "d5b01a39b3415c2cd581d3bd3a3575c1ebbd8e77", + "shasum": "" + }, + "require": { + "php": "^8" + }, + "require-dev": { + "infection/infection": "^0", + "nikic/php-fuzzer": "^0", + "phpunit/phpunit": "^9|^10|^11", + "vimeo/psalm": "^4|^5|^6" + }, + "type": "library", + "autoload": { + "psr-4": { + "ParagonIE\\ConstantTime\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "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" + } + ], + "description": "Constant-time Implementations of RFC 4648 Encoding (Base-64, Base-32, Base-16)", + "keywords": [ + "base16", + "base32", + "base32_decode", + "base32_encode", + "base64", + "base64_decode", + "base64_encode", + "bin2hex", + "encoding", + "hex", + "hex2bin", + "rfc4648" + ], + "support": { + "email": "info@paragonie.com", + "issues": "https://github.com/paragonie/constant_time_encoding/issues", + "source": "https://github.com/paragonie/constant_time_encoding" + }, + "time": "2025-09-24T15:06:41+00:00" + }, + { + "name": "psr/clock", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/clock.git", + "reference": "e41a24703d4560fd0acb709162f73b8adfc3aa0d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/clock/zipball/e41a24703d4560fd0acb709162f73b8adfc3aa0d", + "reference": "e41a24703d4560fd0acb709162f73b8adfc3aa0d", + "shasum": "" + }, + "require": { + "php": "^7.0 || ^8.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Psr\\Clock\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for reading the clock.", + "homepage": "https://github.com/php-fig/clock", + "keywords": [ + "clock", + "now", + "psr", + "psr-20", + "time" + ], + "support": { + "issues": "https://github.com/php-fig/clock/issues", + "source": "https://github.com/php-fig/clock/tree/1.0.0" + }, + "time": "2022-11-25T14:36:26+00:00" + }, + { + "name": "spomky-labs/otphp", + "version": "11.4.2", + "source": { + "type": "git", + "url": "https://github.com/Spomky-Labs/otphp.git", + "reference": "2a1b503fd1c1a5c751ab3c5cd37f2d2d26ab74ad" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Spomky-Labs/otphp/zipball/2a1b503fd1c1a5c751ab3c5cd37f2d2d26ab74ad", + "reference": "2a1b503fd1c1a5c751ab3c5cd37f2d2d26ab74ad", + "shasum": "" + }, + "require": { + "paragonie/constant_time_encoding": "^2.0 || ^3.0", + "php": ">=8.1", + "psr/clock": "^1.0", + "symfony/deprecation-contracts": "^3.2" + }, + "require-dev": { + "symfony/error-handler": "^6.4|^7.0|^8.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "OTPHP\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Florent Morselli", + "homepage": "https://github.com/Spomky" + }, + { + "name": "All contributors", + "homepage": "https://github.com/Spomky-Labs/otphp/contributors" + } + ], + "description": "A PHP library for generating one time passwords according to RFC 4226 (HOTP Algorithm) and the RFC 6238 (TOTP Algorithm) and compatible with Google Authenticator", + "homepage": "https://github.com/Spomky-Labs/otphp", + "keywords": [ + "FreeOTP", + "RFC 4226", + "RFC 6238", + "google authenticator", + "hotp", + "otp", + "totp" + ], + "support": { + "issues": "https://github.com/Spomky-Labs/otphp/issues", + "source": "https://github.com/Spomky-Labs/otphp/tree/11.4.2" + }, + "funding": [ + { + "url": "https://github.com/Spomky", + "type": "github" + }, + { + "url": "https://www.patreon.com/FlorentMorselli", + "type": "patreon" + } + ], + "time": "2026-01-23T10:53:01+00:00" + }, + { + "name": "symfony/deprecation-contracts", + "version": "v3.6.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/deprecation-contracts.git", + "reference": "63afe740e99a13ba87ec199bb07bbdee937a5b62" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/63afe740e99a13ba87ec199bb07bbdee937a5b62", + "reference": "63afe740e99a13ba87ec199bb07bbdee937a5b62", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/contracts", + "name": "symfony/contracts" + }, + "branch-alias": { + "dev-main": "3.6-dev" + } + }, + "autoload": { + "files": [ + "function.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "A generic function and convention to trigger deprecation notices", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/deprecation-contracts/tree/v3.6.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-09-25T14:21:43+00:00" + }, + { + "name": "tracy/tracy", + "version": "v2.11.0", + "source": { + "type": "git", + "url": "https://github.com/nette/tracy.git", + "reference": "eec57bcf2ff11d79f519a19da9d7ae1e2c63c42e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nette/tracy/zipball/eec57bcf2ff11d79f519a19da9d7ae1e2c63c42e", + "reference": "eec57bcf2ff11d79f519a19da9d7ae1e2c63c42e", + "shasum": "" + }, + "require": { + "ext-json": "*", + "ext-session": "*", + "php": "8.2 - 8.5" + }, + "conflict": { + "nette/di": "<3.0" + }, + "require-dev": { + "latte/latte": "^2.5 || ^3.0", + "nette/di": "^3.0", + "nette/http": "^3.0", + "nette/mail": "^3.0 || ^4.0", + "nette/tester": "^2.2", + "nette/utils": "^3.0 || ^4.0", + "phpstan/phpstan-nette": "^2.0@stable", + "psr/log": "^1.0 || ^2.0 || ^3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.11-dev" + } + }, + "autoload": { + "files": [ + "src/Tracy/functions.php" + ], + "psr-4": { + "Tracy\\": "src" + }, + "classmap": [ + "src" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "David Grudl", + "homepage": "https://davidgrudl.com" + }, + { + "name": "Nette Community", + "homepage": "https://nette.org/contributors" + } + ], + "description": "😎 Tracy: the addictive tool to ease debugging PHP code for cool developers. Friendly design, logging, profiler, advanced features like debugging AJAX calls or CLI support. You will love it.", + "homepage": "https://tracy.nette.org", + "keywords": [ + "Xdebug", + "debug", + "debugger", + "nette", + "profiler" + ], + "support": { + "issues": "https://github.com/nette/tracy/issues", + "source": "https://github.com/nette/tracy/tree/v2.11.0" + }, + "time": "2025-10-31T00:12:50+00:00" + } + ], + "packages-dev": [ + { + "name": "nette/tester", + "version": "v2.5.7", + "source": { + "type": "git", + "url": "https://github.com/nette/tester.git", + "reference": "dc02e7811f3491a72e87538044586cee2f483d58" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nette/tester/zipball/dc02e7811f3491a72e87538044586cee2f483d58", + "reference": "dc02e7811f3491a72e87538044586cee2f483d58", + "shasum": "" + }, + "require": { + "php": "8.0 - 8.5" + }, + "require-dev": { + "ext-simplexml": "*", + "phpstan/phpstan-nette": "^2.0@stable" + }, + "bin": [ + "src/tester" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.5-dev" + } + }, + "autoload": { + "psr-4": { + "Tester\\": "src" + }, + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause", + "GPL-2.0-only", + "GPL-3.0-only" + ], + "authors": [ + { + "name": "David Grudl", + "homepage": "https://davidgrudl.com" + }, + { + "name": "Miloslav Hůla", + "homepage": "https://github.com/milo" + }, + { + "name": "Nette Community", + "homepage": "https://nette.org/contributors" + } + ], + "description": "Nette Tester: enjoyable unit testing in PHP with code coverage reporter. 🍏🍏🍎🍏", + "homepage": "https://tester.nette.org", + "keywords": [ + "Xdebug", + "assertions", + "clover", + "code coverage", + "nette", + "pcov", + "phpdbg", + "phpunit", + "testing", + "unit" + ], + "support": { + "issues": "https://github.com/nette/tester/issues", + "source": "https://github.com/nette/tester/tree/v2.5.7" + }, + "time": "2025-11-22T18:50:53+00:00" + }, + { + "name": "phpstan/phpstan", + "version": "2.1.33", + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/9e800e6bee7d5bd02784d4c6069b48032d16224f", + "reference": "9e800e6bee7d5bd02784d4c6069b48032d16224f", + "shasum": "" + }, + "require": { + "php": "^7.4|^8.0" + }, + "conflict": { + "phpstan/phpstan-shim": "*" + }, + "bin": [ + "phpstan", + "phpstan.phar" + ], + "type": "library", + "autoload": { + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "PHPStan - PHP Static Analysis Tool", + "keywords": [ + "dev", + "static analysis" + ], + "support": { + "docs": "https://phpstan.org/user-guide/getting-started", + "forum": "https://github.com/phpstan/phpstan/discussions", + "issues": "https://github.com/phpstan/phpstan/issues", + "security": "https://github.com/phpstan/phpstan/security/policy", + "source": "https://github.com/phpstan/phpstan-src" + }, + "funding": [ + { + "url": "https://github.com/ondrejmirtes", + "type": "github" + }, + { + "url": "https://github.com/phpstan", + "type": "github" + } + ], + "time": "2025-12-05T10:24:31+00:00" + }, + { + "name": "phpstan/phpstan-nette", + "version": "2.0.7", + "source": { + "type": "git", + "url": "https://github.com/phpstan/phpstan-nette.git", + "reference": "488d326408740b28c364849316ec065c13799568" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpstan/phpstan-nette/zipball/488d326408740b28c364849316ec065c13799568", + "reference": "488d326408740b28c364849316ec065c13799568", + "shasum": "" + }, + "require": { + "php": "^7.4 || ^8.0", + "phpstan/phpstan": "^2.1.12" + }, + "conflict": { + "nette/application": "<2.3.0", + "nette/component-model": "<2.3.0", + "nette/di": "<2.3.0", + "nette/forms": "<2.3.0", + "nette/http": "<2.3.0", + "nette/utils": "<2.3.0" + }, + "require-dev": { + "nette/application": "^3.0", + "nette/di": "^3.0", + "nette/forms": "^3.0", + "nette/utils": "^2.3.0 || ^3.0.0 || ^4.0", + "php-parallel-lint/php-parallel-lint": "^1.2", + "phpstan/phpstan-deprecation-rules": "^2.0", + "phpstan/phpstan-phpunit": "^2.0.8", + "phpstan/phpstan-strict-rules": "^2.0", + "phpunit/phpunit": "^9.6" + }, + "type": "phpstan-extension", + "extra": { + "phpstan": { + "includes": [ + "extension.neon", + "rules.neon" + ] + } + }, + "autoload": { + "psr-4": { + "PHPStan\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Nette Framework class reflection extension for PHPStan", + "support": { + "issues": "https://github.com/phpstan/phpstan-nette/issues", + "source": "https://github.com/phpstan/phpstan-nette/tree/2.0.7" + }, + "time": "2025-12-08T10:39:26+00:00" + }, + { + "name": "symfony/thanks", + "version": "v1.4.1", + "source": { + "type": "git", + "url": "https://github.com/symfony/thanks.git", + "reference": "f455cc9ba4e0c61dcc18ea7e52bd725ee661aa64" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/thanks/zipball/f455cc9ba4e0c61dcc18ea7e52bd725ee661aa64", + "reference": "f455cc9ba4e0c61dcc18ea7e52bd725ee661aa64", + "shasum": "" + }, + "require": { + "composer-plugin-api": "^1.0|^2.0", + "php": ">=8.1" + }, + "type": "composer-plugin", + "extra": { + "class": "Symfony\\Thanks\\Thanks", + "branch-alias": { + "dev-main": "1.4-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Thanks\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + } + ], + "description": "Encourages sending ⭐ and 💵 to fellow PHP package maintainers (not limited to Symfony components)!", + "support": { + "issues": "https://github.com/symfony/thanks/issues", + "source": "https://github.com/symfony/thanks/tree/v1.4.1" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-10-30T17:38:50+00:00" + } + ], + "aliases": [], + "minimum-stability": "stable", + "stability-flags": [], + "prefer-stable": false, + "prefer-lowest": false, + "platform": { + "php": ">= 8.2" + }, + "platform-dev": [], + "plugin-api-version": "2.6.0" +} diff --git a/config/common.neon b/config/common.neon new file mode 100644 index 0000000..9e3728a --- /dev/null +++ b/config/common.neon @@ -0,0 +1,35 @@ +# see https://doc.nette.org/en/configuring + +parameters: + + +application: + errorPresenter: + 4xx: Error:Error4xx + 5xx: Error:Error5xx + mapping: App\Presentation\*\**Presenter + + +database: + dsn: 'sqlsrv:server=localhost;Database=auth2fa;TrustServerCertificate=true;LoginTimeout=6;' + user: sa + password: Leviathan8 + + +latte: + strictParsing: yes + extensions: + - App\Presentation\Accessory\LatteExtension + + +assets: + mapping: + default: + path: assets + # type: vite # Uncomment to activate Vite for asset building + + +di: + export: + parameters: no + tags: no diff --git a/config/services.neon b/config/services.neon new file mode 100644 index 0000000..3da313a --- /dev/null +++ b/config/services.neon @@ -0,0 +1,12 @@ +services: + - App\Core\RouterFactory::createRouter + - App\Core\TwoFactorService + - App\Core\MujAutentifikator + +search: + - in: %appDir% + classes: + - *Facade + - *Factory + - *Repository + - *Service diff --git a/latte-lint b/latte-lint new file mode 100644 index 0000000..622a84d --- /dev/null +++ b/latte-lint @@ -0,0 +1,18 @@ +#!/usr/bin/env php +bootConsoleApplication(); +$latte = $container->getByType(Nette\Bridges\ApplicationLatte\TemplateFactory::class) + ->createTemplate() + ->getLatte(); + +$latte->addExtension(new Latte\Tools\LinterExtension); + +$linter = new Latte\Tools\Linter($latte, strict: true); +$ok = $linter->scanDirectory($path); +exit($ok ? 0 : 1); \ No newline at end of file diff --git a/package.json b/package.json new file mode 100644 index 0000000..5e0b723 --- /dev/null +++ b/package.json @@ -0,0 +1,14 @@ +{ + "type": "module", + "dependencies": { + "nette-forms": "^3.3" + }, + "devDependencies": { + "@nette/vite-plugin": "^1.0.1", + "vite": "^6.3.5" + }, + "scripts": { + "dev": "vite", + "build": "vite build" + } +} diff --git a/readme.md b/readme.md new file mode 100644 index 0000000..22d3b23 --- /dev/null +++ b/readme.md @@ -0,0 +1,64 @@ +Nette Web Project +================= + +Welcome to the Nette Web Project! This is a basic skeleton application built using +[Nette](https://nette.org), ideal for kick-starting your new web projects. + +Nette is a renowned PHP web development framework, celebrated for its user-friendliness, +robust security, and outstanding performance. It's among the safest choices +for PHP frameworks out there. + +If Nette helps you, consider supporting it by [making a donation](https://nette.org/donate). +Thank you for your generosity! + + +Requirements +------------ + +This Web Project is compatible with Nette 3.2 and requires PHP 8.2. + + +Installation +------------ + +To install the Web Project, Composer is the recommended tool. If you're new to Composer, +follow [these instructions](https://doc.nette.org/composer). Then, run: + + composer create-project nette/web-project path/to/install + cd path/to/install + +Ensure the `temp/` and `log/` directories are writable. + + +Asset Building with Vite +------------------------ + +This project supports Vite for asset building, which is recommended but optional. To activate Vite: + +1. Uncomment the `type: vite` line in the `common.neon` configuration file under the assets mapping section. +2. Then set up and build the assets: + + npm install + npm run build + + +Web Server Setup +---------------- + +To quickly dive in, use PHP's built-in server: + + php -S localhost:8000 -t www + +Then, open `http://localhost:8000` in your browser to view the welcome page. + +For Apache or Nginx users, configure a virtual host pointing to your project's `www/` directory. + +**Important Note:** Ensure `app/`, `config/`, `log/`, and `temp/` directories are not web-accessible. +Refer to [security warning](https://nette.org/security-warning) for more details. + + +Minimal Skeleton +---------------- + +For demonstrating issues or similar tasks, rather than starting a new project, use +[minimal skeleton](https://github.com/nette/web-project/tree/minimal). diff --git a/vendor/autoload.php b/vendor/autoload.php new file mode 100644 index 0000000..fe5f751 --- /dev/null +++ b/vendor/autoload.php @@ -0,0 +1,25 @@ +writeFile('Hello World!', 'qrcode.png'); +``` + +## Available image renderer back ends +BaconQrCode comes with multiple back ends for rendering images. Currently included are the following: + +- `ImagickImageBackEnd`: renders raster images using the Imagick library +- `SvgImageBackEnd`: renders SVG files using XMLWriter +- `EpsImageBackEnd`: renders EPS files + +### GDLib Renderer +GD library has so many limitations, that GD support is not added as backend, but as separated renderer. +Use `GDLibRenderer` instead of `ImageRenderer`. These are the limitations: + +- Does not support gradient. +- Does not support any curves, so you QR code is always squared. + +Example usage: + +```php +use BaconQrCode\Renderer\GDLibRenderer; +use BaconQrCode\Writer; + +$renderer = new GDLibRenderer(400); +$writer = new Writer($renderer); +$writer->writeFile('Hello World!', 'qrcode.png'); +``` + +## Development + +To run unit tests, you need to have [Node.js](https://nodejs.org/en) and the pixelmatch library installed. Running +`npm install` will install this for you. diff --git a/vendor/bacon/bacon-qr-code/composer.json b/vendor/bacon/bacon-qr-code/composer.json new file mode 100644 index 0000000..37e8c75 --- /dev/null +++ b/vendor/bacon/bacon-qr-code/composer.json @@ -0,0 +1,51 @@ +{ + "name": "bacon/bacon-qr-code", + "description": "BaconQrCode is a QR code generator for PHP.", + "license": "BSD-2-Clause", + "homepage": "https://github.com/Bacon/BaconQrCode", + "require": { + "php": "^8.1", + "ext-iconv": "*", + "dasprid/enum": "^1.0.3" + }, + "suggest": { + "ext-imagick": "to generate QR code images" + }, + "authors": [ + { + "name": "Ben Scholzen 'DASPRiD'", + "email": "mail@dasprids.de", + "homepage": "https://dasprids.de/", + "role": "Developer" + } + ], + "autoload": { + "psr-4": { + "BaconQrCode\\": "src/" + } + }, + "autoload-dev": { + "psr-4": { + "BaconQrCodeTest\\": "test/" + } + }, + "require-dev": { + "phpunit/phpunit": "^10.5.11 || ^11.0.4", + "spatie/phpunit-snapshot-assertions": "^5.1.5", + "spatie/pixelmatch-php": "^1.2.0", + "squizlabs/php_codesniffer": "^3.9", + "phly/keep-a-changelog": "^2.12" + }, + "config": { + "allow-plugins": { + "ocramius/package-versions": true, + "php-http/discovery": true + } + }, + "archive": { + "exclude": [ + "/test", + "/phpunit.xml.dist" + ] + } +} diff --git a/vendor/bacon/bacon-qr-code/src/Common/BitArray.php b/vendor/bacon/bacon-qr-code/src/Common/BitArray.php new file mode 100644 index 0000000..9ec8629 --- /dev/null +++ b/vendor/bacon/bacon-qr-code/src/Common/BitArray.php @@ -0,0 +1,364 @@ + + */ + private SplFixedArray $bits; + + /** + * Creates a new bit array with a given size. + */ + public function __construct(private int $size = 0) + { + $this->bits = SplFixedArray::fromArray(array_fill(0, ($this->size + 31) >> 3, 0)); + } + + /** + * Gets the size in bits. + */ + public function getSize() : int + { + return $this->size; + } + + /** + * Gets the size in bytes. + */ + public function getSizeInBytes() : int + { + return ($this->size + 7) >> 3; + } + + /** + * Ensures that the array has a minimum capacity. + */ + public function ensureCapacity(int $size) : void + { + if ($size > count($this->bits) << 5) { + $this->bits->setSize(($size + 31) >> 5); + } + } + + /** + * Gets a specific bit. + */ + public function get(int $i) : bool + { + return 0 !== ($this->bits[$i >> 5] & (1 << ($i & 0x1f))); + } + + /** + * Sets a specific bit. + */ + public function set(int $i) : void + { + $this->bits[$i >> 5] = $this->bits[$i >> 5] | 1 << ($i & 0x1f); + } + + /** + * Flips a specific bit. + */ + public function flip(int $i) : void + { + $this->bits[$i >> 5] ^= 1 << ($i & 0x1f); + } + + /** + * Gets the next set bit position from a given position. + */ + public function getNextSet(int $from) : int + { + if ($from >= $this->size) { + return $this->size; + } + + $bitsOffset = $from >> 5; + $currentBits = $this->bits[$bitsOffset]; + $bitsLength = count($this->bits); + $currentBits &= ~((1 << ($from & 0x1f)) - 1); + + while (0 === $currentBits) { + if (++$bitsOffset === $bitsLength) { + return $this->size; + } + + $currentBits = $this->bits[$bitsOffset]; + } + + $result = ($bitsOffset << 5) + BitUtils::numberOfTrailingZeros($currentBits); + return min($result, $this->size); + } + + /** + * Gets the next unset bit position from a given position. + */ + public function getNextUnset(int $from) : int + { + if ($from >= $this->size) { + return $this->size; + } + + $bitsOffset = $from >> 5; + $currentBits = ~$this->bits[$bitsOffset]; + $bitsLength = count($this->bits); + $currentBits &= ~((1 << ($from & 0x1f)) - 1); + + while (0 === $currentBits) { + if (++$bitsOffset === $bitsLength) { + return $this->size; + } + + $currentBits = ~$this->bits[$bitsOffset]; + } + + $result = ($bitsOffset << 5) + BitUtils::numberOfTrailingZeros($currentBits); + return min($result, $this->size); + } + + /** + * Sets a bulk of bits. + */ + public function setBulk(int $i, int $newBits) : void + { + $this->bits[$i >> 5] = $newBits; + } + + /** + * Sets a range of bits. + * + * @throws InvalidArgumentException if end is smaller than start + */ + public function setRange(int $start, int $end) : void + { + if ($end < $start) { + throw new InvalidArgumentException('End must be greater or equal to start'); + } + + if ($end === $start) { + return; + } + + --$end; + + $firstInt = $start >> 5; + $lastInt = $end >> 5; + + for ($i = $firstInt; $i <= $lastInt; ++$i) { + $firstBit = $i > $firstInt ? 0 : $start & 0x1f; + $lastBit = $i < $lastInt ? 31 : $end & 0x1f; + + if (0 === $firstBit && 31 === $lastBit) { + $mask = 0x7fffffff; + } else { + $mask = 0; + + for ($j = $firstBit; $j < $lastBit; ++$j) { + $mask |= 1 << $j; + } + } + + $this->bits[$i] = $this->bits[$i] | $mask; + } + } + + /** + * Clears the bit array, unsetting every bit. + */ + public function clear() : void + { + $bitsLength = count($this->bits); + + for ($i = 0; $i < $bitsLength; ++$i) { + $this->bits[$i] = 0; + } + } + + /** + * Checks if a range of bits is set or not set. + + * @throws InvalidArgumentException if end is smaller than start + */ + public function isRange(int $start, int $end, bool $value) : bool + { + if ($end < $start) { + throw new InvalidArgumentException('End must be greater or equal to start'); + } + + if ($end === $start) { + return true; + } + + --$end; + + $firstInt = $start >> 5; + $lastInt = $end >> 5; + + for ($i = $firstInt; $i <= $lastInt; ++$i) { + $firstBit = $i > $firstInt ? 0 : $start & 0x1f; + $lastBit = $i < $lastInt ? 31 : $end & 0x1f; + + if (0 === $firstBit && 31 === $lastBit) { + $mask = 0x7fffffff; + } else { + $mask = 0; + + for ($j = $firstBit; $j <= $lastBit; ++$j) { + $mask |= 1 << $j; + } + } + + if (($this->bits[$i] & $mask) !== ($value ? $mask : 0)) { + return false; + } + } + + return true; + } + + /** + * Appends a bit to the array. + */ + public function appendBit(bool $bit) : void + { + $this->ensureCapacity($this->size + 1); + + if ($bit) { + $this->bits[$this->size >> 5] = $this->bits[$this->size >> 5] | (1 << ($this->size & 0x1f)); + } + + ++$this->size; + } + + /** + * Appends a number of bits (up to 32) to the array. + + * @throws InvalidArgumentException if num bits is not between 0 and 32 + */ + public function appendBits(int $value, int $numBits) : void + { + if ($numBits < 0 || $numBits > 32) { + throw new InvalidArgumentException('Num bits must be between 0 and 32'); + } + + $this->ensureCapacity($this->size + $numBits); + + for ($numBitsLeft = $numBits; $numBitsLeft > 0; $numBitsLeft--) { + $this->appendBit((($value >> ($numBitsLeft - 1)) & 0x01) === 1); + } + } + + /** + * Appends another bit array to this array. + */ + public function appendBitArray(self $other) : void + { + $otherSize = $other->getSize(); + $this->ensureCapacity($this->size + $other->getSize()); + + for ($i = 0; $i < $otherSize; ++$i) { + $this->appendBit($other->get($i)); + } + } + + /** + * Makes an exclusive-or comparision on the current bit array. + * + * @throws InvalidArgumentException if sizes don't match + */ + public function xorBits(self $other) : void + { + $bitsLength = count($this->bits); + $otherBits = $other->getBitArray(); + + if ($bitsLength !== count($otherBits)) { + throw new InvalidArgumentException('Sizes don\'t match'); + } + + for ($i = 0; $i < $bitsLength; ++$i) { + $this->bits[$i] = $this->bits[$i] ^ $otherBits[$i]; + } + } + + /** + * Converts the bit array to a byte array. + * + * @return SplFixedArray + */ + public function toBytes(int $bitOffset, int $numBytes) : SplFixedArray + { + $bytes = new SplFixedArray($numBytes); + + for ($i = 0; $i < $numBytes; ++$i) { + $byte = 0; + + for ($j = 0; $j < 8; ++$j) { + if ($this->get($bitOffset)) { + $byte |= 1 << (7 - $j); + } + + ++$bitOffset; + } + + $bytes[$i] = $byte; + } + + return $bytes; + } + + /** + * Gets the internal bit array. + * + * @return SplFixedArray + */ + public function getBitArray() : SplFixedArray + { + return $this->bits; + } + + /** + * Reverses the array. + */ + public function reverse() : void + { + $newBits = new SplFixedArray(count($this->bits)); + + for ($i = 0; $i < $this->size; ++$i) { + if ($this->get($this->size - $i - 1)) { + $newBits[$i >> 5] = $newBits[$i >> 5] | (1 << ($i & 0x1f)); + } + } + + $this->bits = $newBits; + } + + /** + * Returns a string representation of the bit array. + */ + public function __toString() : string + { + $result = ''; + + for ($i = 0; $i < $this->size; ++$i) { + if (0 === ($i & 0x07)) { + $result .= ' '; + } + + $result .= $this->get($i) ? 'X' : '.'; + } + + return $result; + } +} diff --git a/vendor/bacon/bacon-qr-code/src/Common/BitMatrix.php b/vendor/bacon/bacon-qr-code/src/Common/BitMatrix.php new file mode 100644 index 0000000..294afb4 --- /dev/null +++ b/vendor/bacon/bacon-qr-code/src/Common/BitMatrix.php @@ -0,0 +1,307 @@ + + */ + private SplFixedArray $bits; + + /** + * @throws InvalidArgumentException if a dimension is smaller than zero + */ + public function __construct(int $width, ?int $height = null) + { + if (null === $height) { + $height = $width; + } + + if ($width < 1 || $height < 1) { + throw new InvalidArgumentException('Both dimensions must be greater than zero'); + } + + $this->width = $width; + $this->height = $height; + $this->rowSize = ($width + 31) >> 5; + $this->bits = SplFixedArray::fromArray(array_fill(0, $this->rowSize * $height, 0)); + } + + /** + * Gets the requested bit, where true means black. + */ + public function get(int $x, int $y) : bool + { + $offset = $y * $this->rowSize + ($x >> 5); + return 0 !== (BitUtils::unsignedRightShift($this->bits[$offset], ($x & 0x1f)) & 1); + } + + /** + * Sets the given bit to true. + */ + public function set(int $x, int $y) : void + { + $offset = $y * $this->rowSize + ($x >> 5); + $this->bits[$offset] = $this->bits[$offset] | (1 << ($x & 0x1f)); + } + + /** + * Flips the given bit. + */ + public function flip(int $x, int $y) : void + { + $offset = $y * $this->rowSize + ($x >> 5); + $this->bits[$offset] = $this->bits[$offset] ^ (1 << ($x & 0x1f)); + } + + /** + * Clears all bits (set to false). + */ + public function clear() : void + { + $max = count($this->bits); + + for ($i = 0; $i < $max; ++$i) { + $this->bits[$i] = 0; + } + } + + /** + * Sets a square region of the bit matrix to true. + * + * @throws InvalidArgumentException if left or top are negative + * @throws InvalidArgumentException if width or height are smaller than 1 + * @throws InvalidArgumentException if region does not fit into the matix + */ + public function setRegion(int $left, int $top, int $width, int $height) : void + { + if ($top < 0 || $left < 0) { + throw new InvalidArgumentException('Left and top must be non-negative'); + } + + if ($height < 1 || $width < 1) { + throw new InvalidArgumentException('Width and height must be at least 1'); + } + + $right = $left + $width; + $bottom = $top + $height; + + if ($bottom > $this->height || $right > $this->width) { + throw new InvalidArgumentException('The region must fit inside the matrix'); + } + + for ($y = $top; $y < $bottom; ++$y) { + $offset = $y * $this->rowSize; + + for ($x = $left; $x < $right; ++$x) { + $index = $offset + ($x >> 5); + $this->bits[$index] = $this->bits[$index] | (1 << ($x & 0x1f)); + } + } + } + + /** + * A fast method to retrieve one row of data from the matrix as a BitArray. + */ + public function getRow(int $y, ?BitArray $row = null) : BitArray + { + if (null === $row || $row->getSize() < $this->width) { + $row = new BitArray($this->width); + } + + $offset = $y * $this->rowSize; + + for ($x = 0; $x < $this->rowSize; ++$x) { + $row->setBulk($x << 5, $this->bits[$offset + $x]); + } + + return $row; + } + + /** + * Sets a row of data from a BitArray. + */ + public function setRow(int $y, BitArray $row) : void + { + $bits = $row->getBitArray(); + + for ($i = 0; $i < $this->rowSize; ++$i) { + $this->bits[$y * $this->rowSize + $i] = $bits[$i]; + } + } + + /** + * This is useful in detecting the enclosing rectangle of a 'pure' barcode. + * + * @return int[]|null + */ + public function getEnclosingRectangle() : ?array + { + $left = $this->width; + $top = $this->height; + $right = -1; + $bottom = -1; + + for ($y = 0; $y < $this->height; ++$y) { + for ($x32 = 0; $x32 < $this->rowSize; ++$x32) { + $bits = $this->bits[$y * $this->rowSize + $x32]; + + if (0 !== $bits) { + if ($y < $top) { + $top = $y; + } + + if ($y > $bottom) { + $bottom = $y; + } + + if ($x32 * 32 < $left) { + $bit = 0; + + while (($bits << (31 - $bit)) === 0) { + $bit++; + } + + if (($x32 * 32 + $bit) < $left) { + $left = $x32 * 32 + $bit; + } + } + } + + if ($x32 * 32 + 31 > $right) { + $bit = 31; + + while (0 === BitUtils::unsignedRightShift($bits, $bit)) { + --$bit; + } + + if (($x32 * 32 + $bit) > $right) { + $right = $x32 * 32 + $bit; + } + } + } + } + + $width = $right - $left; + $height = $bottom - $top; + + if ($width < 0 || $height < 0) { + return null; + } + + return [$left, $top, $width, $height]; + } + + /** + * Gets the most top left set bit. + * + * This is useful in detecting a corner of a 'pure' barcode. + * + * @return int[]|null + */ + public function getTopLeftOnBit() : ?array + { + $bitsOffset = 0; + + while ($bitsOffset < count($this->bits) && 0 === $this->bits[$bitsOffset]) { + ++$bitsOffset; + } + + if (count($this->bits) === $bitsOffset) { + return null; + } + + $x = intdiv($bitsOffset, $this->rowSize); + $y = ($bitsOffset % $this->rowSize) << 5; + + $bits = $this->bits[$bitsOffset]; + $bit = 0; + + while (0 === ($bits << (31 - $bit))) { + ++$bit; + } + + $x += $bit; + + return [$x, $y]; + } + + /** + * Gets the most bottom right set bit. + * + * This is useful in detecting a corner of a 'pure' barcode. + * + * @return int[]|null + */ + public function getBottomRightOnBit() : ?array + { + $bitsOffset = count($this->bits) - 1; + + while ($bitsOffset >= 0 && 0 === $this->bits[$bitsOffset]) { + --$bitsOffset; + } + + if ($bitsOffset < 0) { + return null; + } + + $x = intdiv($bitsOffset, $this->rowSize); + $y = ($bitsOffset % $this->rowSize) << 5; + + $bits = $this->bits[$bitsOffset]; + $bit = 0; + + while (0 === BitUtils::unsignedRightShift($bits, $bit)) { + --$bit; + } + + $x += $bit; + + return [$x, $y]; + } + + /** + * Gets the width of the matrix, + */ + public function getWidth() : int + { + return $this->width; + } + + /** + * Gets the height of the matrix. + */ + public function getHeight() : int + { + return $this->height; + } +} diff --git a/vendor/bacon/bacon-qr-code/src/Common/BitUtils.php b/vendor/bacon/bacon-qr-code/src/Common/BitUtils.php new file mode 100644 index 0000000..0c575b4 --- /dev/null +++ b/vendor/bacon/bacon-qr-code/src/Common/BitUtils.php @@ -0,0 +1,41 @@ +>>" in other + * languages. + */ + public static function unsignedRightShift(int $a, int $b) : int + { + return ( + $a >= 0 + ? $a >> $b + : (($a & 0x7fffffff) >> $b) | (0x40000000 >> ($b - 1)) + ); + } + + /** + * Gets the number of trailing zeros. + */ + public static function numberOfTrailingZeros(int $i) : int + { + $lastPos = strrpos(str_pad(decbin($i), 32, '0', STR_PAD_LEFT), '1'); + return $lastPos === false ? 32 : 31 - $lastPos; + } +} diff --git a/vendor/bacon/bacon-qr-code/src/Common/CharacterSetEci.php b/vendor/bacon/bacon-qr-code/src/Common/CharacterSetEci.php new file mode 100644 index 0000000..8b62b8c --- /dev/null +++ b/vendor/bacon/bacon-qr-code/src/Common/CharacterSetEci.php @@ -0,0 +1,177 @@ +|null + */ + private static ?array $valueToEci; + + /** + * @var array|null + */ + private static ?array $nameToEci = null; + + /** + * @param int[] $values + */ + public function __construct(private readonly array $values, string ...$otherEncodingNames) + { + $this->otherEncodingNames = $otherEncodingNames; + } + + /** + * Returns the primary value. + */ + public function getValue() : int + { + return $this->values[0]; + } + + /** + * Gets character set ECI by value. + * + * Returns the representing ECI of a given value, or null if it is legal but unsupported. + * + * @throws InvalidArgumentException if value is not between 0 and 900 + */ + public static function getCharacterSetEciByValue(int $value) : ?self + { + if ($value < 0 || $value >= 900) { + throw new InvalidArgumentException('Value must be between 0 and 900'); + } + + $valueToEci = self::valueToEci(); + + if (! array_key_exists($value, $valueToEci)) { + return null; + } + + return $valueToEci[$value]; + } + + /** + * Returns character set ECI by name. + * + * Returns the representing ECI of a given name, or null if it is legal but unsupported + */ + public static function getCharacterSetEciByName(string $name) : ?self + { + $nameToEci = self::nameToEci(); + $name = strtolower($name); + + if (! array_key_exists($name, $nameToEci)) { + return null; + } + + return $nameToEci[$name]; + } + + private static function valueToEci() : array + { + if (null !== self::$valueToEci) { + return self::$valueToEci; + } + + self::$valueToEci = []; + + foreach (self::values() as $eci) { + foreach ($eci->values as $value) { + self::$valueToEci[$value] = $eci; + } + } + + return self::$valueToEci; + } + + private static function nameToEci() : array + { + if (null !== self::$nameToEci) { + return self::$nameToEci; + } + + self::$nameToEci = []; + + foreach (self::values() as $eci) { + self::$nameToEci[strtolower($eci->name())] = $eci; + + foreach ($eci->otherEncodingNames as $name) { + self::$nameToEci[strtolower($name)] = $eci; + } + } + + return self::$nameToEci; + } +} diff --git a/vendor/bacon/bacon-qr-code/src/Common/EcBlock.php b/vendor/bacon/bacon-qr-code/src/Common/EcBlock.php new file mode 100644 index 0000000..bc9e865 --- /dev/null +++ b/vendor/bacon/bacon-qr-code/src/Common/EcBlock.php @@ -0,0 +1,33 @@ +count; + } + + /** + * Returns the number of data codewords. + */ + public function getDataCodewords() : int + { + return $this->dataCodewords; + } +} diff --git a/vendor/bacon/bacon-qr-code/src/Common/EcBlocks.php b/vendor/bacon/bacon-qr-code/src/Common/EcBlocks.php new file mode 100644 index 0000000..63c52a9 --- /dev/null +++ b/vendor/bacon/bacon-qr-code/src/Common/EcBlocks.php @@ -0,0 +1,66 @@ +ecBlocks = $ecBlocks; + } + + /** + * Returns the number of EC codewords per block. + */ + public function getEcCodewordsPerBlock() : int + { + return $this->ecCodewordsPerBlock; + } + + /** + * Returns the total number of EC block appearances. + */ + public function getNumBlocks() : int + { + $total = 0; + + foreach ($this->ecBlocks as $ecBlock) { + $total += $ecBlock->getCount(); + } + + return $total; + } + + /** + * Returns the total count of EC codewords. + */ + public function getTotalEcCodewords() : int + { + return $this->ecCodewordsPerBlock * $this->getNumBlocks(); + } + + /** + * Returns the EC blocks included in this collection. + * + * @return EcBlock[] + */ + public function getEcBlocks() : array + { + return $this->ecBlocks; + } +} diff --git a/vendor/bacon/bacon-qr-code/src/Common/ErrorCorrectionLevel.php b/vendor/bacon/bacon-qr-code/src/Common/ErrorCorrectionLevel.php new file mode 100644 index 0000000..ac84d66 --- /dev/null +++ b/vendor/bacon/bacon-qr-code/src/Common/ErrorCorrectionLevel.php @@ -0,0 +1,57 @@ +bits; + } +} diff --git a/vendor/bacon/bacon-qr-code/src/Common/FormatInformation.php b/vendor/bacon/bacon-qr-code/src/Common/FormatInformation.php new file mode 100644 index 0000000..6a5da0b --- /dev/null +++ b/vendor/bacon/bacon-qr-code/src/Common/FormatInformation.php @@ -0,0 +1,196 @@ +ecLevel = ErrorCorrectionLevel::forBits(($formatInfo >> 3) & 0x3); + $this->dataMask = $formatInfo & 0x7; + } + + /** + * Checks how many bits are different between two integers. + */ + public static function numBitsDiffering(int $a, int $b) : int + { + $a ^= $b; + + return ( + self::BITS_SET_IN_HALF_BYTE[$a & 0xf] + + self::BITS_SET_IN_HALF_BYTE[(BitUtils::unsignedRightShift($a, 4) & 0xf)] + + self::BITS_SET_IN_HALF_BYTE[(BitUtils::unsignedRightShift($a, 8) & 0xf)] + + self::BITS_SET_IN_HALF_BYTE[(BitUtils::unsignedRightShift($a, 12) & 0xf)] + + self::BITS_SET_IN_HALF_BYTE[(BitUtils::unsignedRightShift($a, 16) & 0xf)] + + self::BITS_SET_IN_HALF_BYTE[(BitUtils::unsignedRightShift($a, 20) & 0xf)] + + self::BITS_SET_IN_HALF_BYTE[(BitUtils::unsignedRightShift($a, 24) & 0xf)] + + self::BITS_SET_IN_HALF_BYTE[(BitUtils::unsignedRightShift($a, 28) & 0xf)] + ); + } + + /** + * Decodes format information. + */ + public static function decodeFormatInformation(int $maskedFormatInfo1, int $maskedFormatInfo2) : ?self + { + $formatInfo = self::doDecodeFormatInformation($maskedFormatInfo1, $maskedFormatInfo2); + + if (null !== $formatInfo) { + return $formatInfo; + } + + // Should return null, but, some QR codes apparently do not mask this info. Try again by actually masking the + // pattern first. + return self::doDecodeFormatInformation( + $maskedFormatInfo1 ^ self::FORMAT_INFO_MASK_QR, + $maskedFormatInfo2 ^ self::FORMAT_INFO_MASK_QR + ); + } + + /** + * Internal method for decoding format information. + */ + private static function doDecodeFormatInformation(int $maskedFormatInfo1, int $maskedFormatInfo2) : ?self + { + $bestDifference = PHP_INT_MAX; + $bestFormatInfo = 0; + + foreach (self::FORMAT_INFO_DECODE_LOOKUP as $decodeInfo) { + $targetInfo = $decodeInfo[0]; + + if ($targetInfo === $maskedFormatInfo1 || $targetInfo === $maskedFormatInfo2) { + // Found an exact match + return new self($decodeInfo[1]); + } + + $bitsDifference = self::numBitsDiffering($maskedFormatInfo1, $targetInfo); + + if ($bitsDifference < $bestDifference) { + $bestFormatInfo = $decodeInfo[1]; + $bestDifference = $bitsDifference; + } + + if ($maskedFormatInfo1 !== $maskedFormatInfo2) { + // Also try the other option + $bitsDifference = self::numBitsDiffering($maskedFormatInfo2, $targetInfo); + + if ($bitsDifference < $bestDifference) { + $bestFormatInfo = $decodeInfo[1]; + $bestDifference = $bitsDifference; + } + } + } + + // Hamming distance of the 32 masked codes is 7, by construction, so <= 3 bits differing means we found a match. + if ($bestDifference <= 3) { + return new self($bestFormatInfo); + } + + return null; + } + + /** + * Returns the error correction level. + */ + public function getErrorCorrectionLevel() : ErrorCorrectionLevel + { + return $this->ecLevel; + } + + /** + * Returns the data mask. + */ + public function getDataMask() : int + { + return $this->dataMask; + } + + /** + * Hashes the code of the EC level. + */ + public function hashCode() : int + { + return ($this->ecLevel->getBits() << 3) | $this->dataMask; + } + + /** + * Verifies if this instance equals another one. + */ + public function equals(self $other) : bool + { + return ( + $this->ecLevel === $other->ecLevel + && $this->dataMask === $other->dataMask + ); + } +} diff --git a/vendor/bacon/bacon-qr-code/src/Common/Mode.php b/vendor/bacon/bacon-qr-code/src/Common/Mode.php new file mode 100644 index 0000000..f5fb153 --- /dev/null +++ b/vendor/bacon/bacon-qr-code/src/Common/Mode.php @@ -0,0 +1,69 @@ +getVersionNumber(); + + if ($number <= 9) { + $offset = 0; + } elseif ($number <= 26) { + $offset = 1; + } else { + $offset = 2; + } + + return $this->characterCountBitsForVersions[$offset]; + } + + /** + * Returns the four bits used to encode this mode. + */ + public function getBits() : int + { + return $this->bits; + } +} diff --git a/vendor/bacon/bacon-qr-code/src/Common/ReedSolomonCodec.php b/vendor/bacon/bacon-qr-code/src/Common/ReedSolomonCodec.php new file mode 100644 index 0000000..d16a75e --- /dev/null +++ b/vendor/bacon/bacon-qr-code/src/Common/ReedSolomonCodec.php @@ -0,0 +1,454 @@ + 8) { + throw new InvalidArgumentException('Symbol size must be between 0 and 8'); + } + + if ($firstRoot < 0 || $firstRoot >= (1 << $symbolSize)) { + throw new InvalidArgumentException('First root must be between 0 and ' . (1 << $symbolSize)); + } + + if ($numRoots < 0 || $numRoots >= (1 << $symbolSize)) { + throw new InvalidArgumentException('Num roots must be between 0 and ' . (1 << $symbolSize)); + } + + if ($padding < 0 || $padding >= ((1 << $symbolSize) - 1 - $numRoots)) { + throw new InvalidArgumentException( + 'Padding must be between 0 and ' . ((1 << $symbolSize) - 1 - $numRoots) + ); + } + + $this->symbolSize = $symbolSize; + $this->blockSize = (1 << $symbolSize) - 1; + $this->padding = $padding; + $this->alphaTo = SplFixedArray::fromArray(array_fill(0, $this->blockSize + 1, 0), false); + $this->indexOf = SplFixedArray::fromArray(array_fill(0, $this->blockSize + 1, 0), false); + + // Generate galous field lookup table + $this->indexOf[0] = $this->blockSize; + $this->alphaTo[$this->blockSize] = 0; + + $sr = 1; + + for ($i = 0; $i < $this->blockSize; ++$i) { + $this->indexOf[$sr] = $i; + $this->alphaTo[$i] = $sr; + + $sr <<= 1; + + if ($sr & (1 << $symbolSize)) { + $sr ^= $gfPoly; + } + + $sr &= $this->blockSize; + } + + if (1 !== $sr) { + throw new RuntimeException('Field generator polynomial is not primitive'); + } + + // Form RS code generator polynomial from its roots + $this->generatorPoly = SplFixedArray::fromArray(array_fill(0, $numRoots + 1, 0), false); + $this->firstRoot = $firstRoot; + $this->primitive = $primitive; + $this->numRoots = $numRoots; + + // Find prim-th root of 1, used in decoding + for ($iPrimitive = 1; ($iPrimitive % $primitive) !== 0; $iPrimitive += $this->blockSize) { + } + + $this->iPrimitive = intdiv($iPrimitive, $primitive); + + $this->generatorPoly[0] = 1; + + for ($i = 0, $root = $firstRoot * $primitive; $i < $numRoots; ++$i, $root += $primitive) { + $this->generatorPoly[$i + 1] = 1; + + for ($j = $i; $j > 0; $j--) { + if ($this->generatorPoly[$j] !== 0) { + $this->generatorPoly[$j] = $this->generatorPoly[$j - 1] ^ $this->alphaTo[ + $this->modNn($this->indexOf[$this->generatorPoly[$j]] + $root) + ]; + } else { + $this->generatorPoly[$j] = $this->generatorPoly[$j - 1]; + } + } + + $this->generatorPoly[$j] = $this->alphaTo[$this->modNn($this->indexOf[$this->generatorPoly[0]] + $root)]; + } + + // Convert generator poly to index form for quicker encoding + for ($i = 0; $i <= $numRoots; ++$i) { + $this->generatorPoly[$i] = $this->indexOf[$this->generatorPoly[$i]]; + } + } + + /** + * Encodes data and writes result back into parity array. + */ + public function encode(SplFixedArray $data, SplFixedArray $parity) : void + { + for ($i = 0; $i < $this->numRoots; ++$i) { + $parity[$i] = 0; + } + + $iterations = $this->blockSize - $this->numRoots - $this->padding; + + for ($i = 0; $i < $iterations; ++$i) { + $feedback = $this->indexOf[$data[$i] ^ $parity[0]]; + + if ($feedback !== $this->blockSize) { + // Feedback term is non-zero + $feedback = $this->modNn($this->blockSize - $this->generatorPoly[$this->numRoots] + $feedback); + + for ($j = 1; $j < $this->numRoots; ++$j) { + $parity[$j] = $parity[$j] ^ $this->alphaTo[ + $this->modNn($feedback + $this->generatorPoly[$this->numRoots - $j]) + ]; + } + } + + for ($j = 0; $j < $this->numRoots - 1; ++$j) { + $parity[$j] = $parity[$j + 1]; + } + + if ($feedback !== $this->blockSize) { + $parity[$this->numRoots - 1] = $this->alphaTo[$this->modNn($feedback + $this->generatorPoly[0])]; + } else { + $parity[$this->numRoots - 1] = 0; + } + } + } + + /** + * Decodes received data. + */ + public function decode(SplFixedArray $data, ?SplFixedArray $erasures = null) : ?int + { + // This speeds up the initialization a bit. + $numRootsPlusOne = SplFixedArray::fromArray(array_fill(0, $this->numRoots + 1, 0), false); + $numRoots = SplFixedArray::fromArray(array_fill(0, $this->numRoots, 0), false); + + $lambda = clone $numRootsPlusOne; + $b = clone $numRootsPlusOne; + $t = clone $numRootsPlusOne; + $omega = clone $numRootsPlusOne; + $root = clone $numRoots; + $loc = clone $numRoots; + + $numErasures = (null !== $erasures ? count($erasures) : 0); + + // Form the Syndromes; i.e., evaluate data(x) at roots of g(x) + $syndromes = SplFixedArray::fromArray(array_fill(0, $this->numRoots, $data[0]), false); + + for ($i = 1; $i < $this->blockSize - $this->padding; ++$i) { + for ($j = 0; $j < $this->numRoots; ++$j) { + if ($syndromes[$j] === 0) { + $syndromes[$j] = $data[$i]; + } else { + $syndromes[$j] = $data[$i] ^ $this->alphaTo[ + $this->modNn($this->indexOf[$syndromes[$j]] + ($this->firstRoot + $j) * $this->primitive) + ]; + } + } + } + + // Convert syndromes to index form, checking for nonzero conditions + $syndromeError = 0; + + for ($i = 0; $i < $this->numRoots; ++$i) { + $syndromeError |= $syndromes[$i]; + $syndromes[$i] = $this->indexOf[$syndromes[$i]]; + } + + if (! $syndromeError) { + // If syndrome is zero, data[] is a codeword and there are no errors to correct, so return data[] + // unmodified. + return 0; + } + + $lambda[0] = 1; + + if ($numErasures > 0) { + // Init lambda to be the erasure locator polynomial + $lambda[1] = $this->alphaTo[$this->modNn($this->primitive * ($this->blockSize - 1 - $erasures[0]))]; + + for ($i = 1; $i < $numErasures; ++$i) { + $u = $this->modNn($this->primitive * ($this->blockSize - 1 - $erasures[$i])); + + for ($j = $i + 1; $j > 0; --$j) { + $tmp = $this->indexOf[$lambda[$j - 1]]; + + if ($tmp !== $this->blockSize) { + $lambda[$j] = $lambda[$j] ^ $this->alphaTo[$this->modNn($u + $tmp)]; + } + } + } + } + + for ($i = 0; $i <= $this->numRoots; ++$i) { + $b[$i] = $this->indexOf[$lambda[$i]]; + } + + // Begin Berlekamp-Massey algorithm to determine error+erasure locator polynomial + $r = $numErasures; + $el = $numErasures; + + while (++$r <= $this->numRoots) { + // Compute discrepancy at the r-th step in poly form + $discrepancyR = 0; + + for ($i = 0; $i < $r; ++$i) { + if ($lambda[$i] !== 0 && $syndromes[$r - $i - 1] !== $this->blockSize) { + $discrepancyR ^= $this->alphaTo[ + $this->modNn($this->indexOf[$lambda[$i]] + $syndromes[$r - $i - 1]) + ]; + } + } + + $discrepancyR = $this->indexOf[$discrepancyR]; + + if ($discrepancyR === $this->blockSize) { + $tmp = $b->toArray(); + array_unshift($tmp, $this->blockSize); + array_pop($tmp); + $b = SplFixedArray::fromArray($tmp, false); + continue; + } + + $t[0] = $lambda[0]; + + for ($i = 0; $i < $this->numRoots; ++$i) { + if ($b[$i] !== $this->blockSize) { + $t[$i + 1] = $lambda[$i + 1] ^ $this->alphaTo[$this->modNn($discrepancyR + $b[$i])]; + } else { + $t[$i + 1] = $lambda[$i + 1]; + } + } + + if (2 * $el <= $r + $numErasures - 1) { + $el = $r + $numErasures - $el; + + for ($i = 0; $i <= $this->numRoots; ++$i) { + $b[$i] = ( + $lambda[$i] === 0 + ? $this->blockSize + : $this->modNn($this->indexOf[$lambda[$i]] - $discrepancyR + $this->blockSize) + ); + } + } else { + $tmp = $b->toArray(); + array_unshift($tmp, $this->blockSize); + array_pop($tmp); + $b = SplFixedArray::fromArray($tmp, false); + } + + $lambda = clone $t; + } + + // Convert lambda to index form and compute deg(lambda(x)) + $degLambda = 0; + + for ($i = 0; $i <= $this->numRoots; ++$i) { + $lambda[$i] = $this->indexOf[$lambda[$i]]; + + if ($lambda[$i] !== $this->blockSize) { + $degLambda = $i; + } + } + + // Find roots of the error+erasure locator polynomial by Chien search. + $reg = clone $lambda; + $reg[0] = 0; + $count = 0; + $i = 1; + + for ($k = $this->iPrimitive - 1; $i <= $this->blockSize; ++$i, $k = $this->modNn($k + $this->iPrimitive)) { + $q = 1; + + for ($j = $degLambda; $j > 0; $j--) { + if ($reg[$j] !== $this->blockSize) { + $reg[$j] = $this->modNn($reg[$j] + $j); + $q ^= $this->alphaTo[$reg[$j]]; + } + } + + if ($q !== 0) { + // Not a root + continue; + } + + // Store root (index-form) and error location number + $root[$count] = $i; + $loc[$count] = $k; + + if (++$count === $degLambda) { + break; + } + } + + if ($degLambda !== $count) { + // deg(lambda) unequal to number of roots: uncorrectable error detected + return null; + } + + // Compute err+eras evaluate poly omega(x) = s(x)*lambda(x) (modulo x**numRoots). In index form. Also find + // deg(omega). + $degOmega = $degLambda - 1; + + for ($i = 0; $i <= $degOmega; ++$i) { + $tmp = 0; + + for ($j = $i; $j >= 0; --$j) { + if ($syndromes[$i - $j] !== $this->blockSize && $lambda[$j] !== $this->blockSize) { + $tmp ^= $this->alphaTo[$this->modNn($syndromes[$i - $j] + $lambda[$j])]; + } + } + + $omega[$i] = $this->indexOf[$tmp]; + } + + // Compute error values in poly-form. num1 = omega(inv(X(l))), num2 = inv(X(l))**(firstRoot-1) and + // den = lambda_pr(inv(X(l))) all in poly form. + for ($j = $count - 1; $j >= 0; --$j) { + $num1 = 0; + + for ($i = $degOmega; $i >= 0; $i--) { + if ($omega[$i] !== $this->blockSize) { + $num1 ^= $this->alphaTo[$this->modNn($omega[$i] + $i * $root[$j])]; + } + } + + $num2 = $this->alphaTo[$this->modNn($root[$j] * ($this->firstRoot - 1) + $this->blockSize)]; + $den = 0; + + // lambda[i+1] for i even is the formal derivativelambda_pr of lambda[i] + for ($i = min($degLambda, $this->numRoots - 1) & ~1; $i >= 0; $i -= 2) { + if ($lambda[$i + 1] !== $this->blockSize) { + $den ^= $this->alphaTo[$this->modNn($lambda[$i + 1] + $i * $root[$j])]; + } + } + + // Apply error to data + if ($num1 !== 0 && $loc[$j] >= $this->padding) { + $data[$loc[$j] - $this->padding] = $data[$loc[$j] - $this->padding] ^ ( + $this->alphaTo[ + $this->modNn( + $this->indexOf[$num1] + $this->indexOf[$num2] + $this->blockSize - $this->indexOf[$den] + ) + ] + ); + } + } + + if (null !== $erasures) { + if (count($erasures) < $count) { + $erasures->setSize($count); + } + + for ($i = 0; $i < $count; $i++) { + $erasures[$i] = $loc[$i]; + } + } + + return $count; + } + + /** + * Computes $x % GF_SIZE, where GF_SIZE is 2**GF_BITS - 1, without a slow divide. + */ + private function modNn(int $x) : int + { + while ($x >= $this->blockSize) { + $x -= $this->blockSize; + $x = ($x >> $this->symbolSize) + ($x & $this->blockSize); + } + + return $x; + } +} diff --git a/vendor/bacon/bacon-qr-code/src/Common/Version.php b/vendor/bacon/bacon-qr-code/src/Common/Version.php new file mode 100644 index 0000000..68d3d16 --- /dev/null +++ b/vendor/bacon/bacon-qr-code/src/Common/Version.php @@ -0,0 +1,592 @@ +|null + */ + private static ?array $versions = null; + + /** + * @param int[] $alignmentPatternCenters + */ + private function __construct( + int $versionNumber, + array $alignmentPatternCenters, + EcBlocks ...$ecBlocks + ) { + $this->versionNumber = $versionNumber; + $this->alignmentPatternCenters = $alignmentPatternCenters; + $this->ecBlocks = $ecBlocks; + + $totalCodewords = 0; + $ecCodewords = $ecBlocks[0]->getEcCodewordsPerBlock(); + + foreach ($ecBlocks[0]->getEcBlocks() as $ecBlock) { + $totalCodewords += $ecBlock->getCount() * ($ecBlock->getDataCodewords() + $ecCodewords); + } + + $this->totalCodewords = $totalCodewords; + } + + /** + * Returns the version number. + */ + public function getVersionNumber() : int + { + return $this->versionNumber; + } + + /** + * Returns the alignment pattern centers. + * + * @return int[] + */ + public function getAlignmentPatternCenters() : array + { + return $this->alignmentPatternCenters; + } + + /** + * Returns the total number of codewords. + */ + public function getTotalCodewords() : int + { + return $this->totalCodewords; + } + + /** + * Calculates the dimension for the current version. + */ + public function getDimensionForVersion() : int + { + return 17 + 4 * $this->versionNumber; + } + + /** + * Returns the number of EC blocks for a specific EC level. + */ + public function getEcBlocksForLevel(ErrorCorrectionLevel $ecLevel) : EcBlocks + { + return $this->ecBlocks[$ecLevel->ordinal()]; + } + + /** + * Gets a provisional version number for a specific dimension. + * + * @throws InvalidArgumentException if dimension is not 1 mod 4 + */ + public static function getProvisionalVersionForDimension(int $dimension) : self + { + if (1 !== $dimension % 4) { + throw new InvalidArgumentException('Dimension is not 1 mod 4'); + } + + return self::getVersionForNumber(intdiv($dimension - 17, 4)); + } + + /** + * Gets a version instance for a specific version number. + * + * @throws InvalidArgumentException if version number is out of range + */ + public static function getVersionForNumber(int $versionNumber) : self + { + if ($versionNumber < 1 || $versionNumber > 40) { + throw new InvalidArgumentException('Version number must be between 1 and 40'); + } + + return self::versions()[$versionNumber - 1]; + } + + /** + * Decodes version information from an integer and returns the version. + */ + public static function decodeVersionInformation(int $versionBits) : ?self + { + $bestDifference = PHP_INT_MAX; + $bestVersion = 0; + + foreach (self::VERSION_DECODE_INFO as $i => $targetVersion) { + if ($targetVersion === $versionBits) { + return self::getVersionForNumber($i + 7); + } + + $bitsDifference = FormatInformation::numBitsDiffering($versionBits, $targetVersion); + + if ($bitsDifference < $bestDifference) { + $bestVersion = $i + 7; + $bestDifference = $bitsDifference; + } + } + + if ($bestDifference <= 3) { + return self::getVersionForNumber($bestVersion); + } + + return null; + } + + /** + * Builds the function pattern for the current version. + */ + public function buildFunctionPattern() : BitMatrix + { + $dimension = $this->getDimensionForVersion(); + $bitMatrix = new BitMatrix($dimension); + + // Top left finder pattern + separator + format + $bitMatrix->setRegion(0, 0, 9, 9); + // Top right finder pattern + separator + format + $bitMatrix->setRegion($dimension - 8, 0, 8, 9); + // Bottom left finder pattern + separator + format + $bitMatrix->setRegion(0, $dimension - 8, 9, 8); + + // Alignment patterns + $max = count($this->alignmentPatternCenters); + + for ($x = 0; $x < $max; ++$x) { + $i = $this->alignmentPatternCenters[$x] - 2; + + for ($y = 0; $y < $max; ++$y) { + if (($x === 0 && ($y === 0 || $y === $max - 1)) || ($x === $max - 1 && $y === 0)) { + // No alignment patterns near the three finder paterns + continue; + } + + $bitMatrix->setRegion($this->alignmentPatternCenters[$y] - 2, $i, 5, 5); + } + } + + // Vertical timing pattern + $bitMatrix->setRegion(6, 9, 1, $dimension - 17); + // Horizontal timing pattern + $bitMatrix->setRegion(9, 6, $dimension - 17, 1); + + if ($this->versionNumber > 6) { + // Version info, top right + $bitMatrix->setRegion($dimension - 11, 0, 3, 6); + // Version info, bottom left + $bitMatrix->setRegion(0, $dimension - 11, 6, 3); + } + + return $bitMatrix; + } + + /** + * Returns a string representation for the version. + */ + public function __toString() : string + { + return (string) $this->versionNumber; + } + + /** + * Build and cache a specific version. + * + * See ISO 18004:2006 6.5.1 Table 9. + * + * @return array + */ + private static function versions() : array + { + if (null !== self::$versions) { + return self::$versions; + } + + return self::$versions = [ + new self( + 1, + [], + new EcBlocks(7, new EcBlock(1, 19)), + new EcBlocks(10, new EcBlock(1, 16)), + new EcBlocks(13, new EcBlock(1, 13)), + new EcBlocks(17, new EcBlock(1, 9)) + ), + new self( + 2, + [6, 18], + new EcBlocks(10, new EcBlock(1, 34)), + new EcBlocks(16, new EcBlock(1, 28)), + new EcBlocks(22, new EcBlock(1, 22)), + new EcBlocks(28, new EcBlock(1, 16)) + ), + new self( + 3, + [6, 22], + new EcBlocks(15, new EcBlock(1, 55)), + new EcBlocks(26, new EcBlock(1, 44)), + new EcBlocks(18, new EcBlock(2, 17)), + new EcBlocks(22, new EcBlock(2, 13)) + ), + new self( + 4, + [6, 26], + new EcBlocks(20, new EcBlock(1, 80)), + new EcBlocks(18, new EcBlock(2, 32)), + new EcBlocks(26, new EcBlock(2, 24)), + new EcBlocks(16, new EcBlock(4, 9)) + ), + new self( + 5, + [6, 30], + new EcBlocks(26, new EcBlock(1, 108)), + new EcBlocks(24, new EcBlock(2, 43)), + new EcBlocks(18, new EcBlock(2, 15), new EcBlock(2, 16)), + new EcBlocks(22, new EcBlock(2, 11), new EcBlock(2, 12)) + ), + new self( + 6, + [6, 34], + new EcBlocks(18, new EcBlock(2, 68)), + new EcBlocks(16, new EcBlock(4, 27)), + new EcBlocks(24, new EcBlock(4, 19)), + new EcBlocks(28, new EcBlock(4, 15)) + ), + new self( + 7, + [6, 22, 38], + new EcBlocks(20, new EcBlock(2, 78)), + new EcBlocks(18, new EcBlock(4, 31)), + new EcBlocks(18, new EcBlock(2, 14), new EcBlock(4, 15)), + new EcBlocks(26, new EcBlock(4, 13), new EcBlock(1, 14)) + ), + new self( + 8, + [6, 24, 42], + new EcBlocks(24, new EcBlock(2, 97)), + new EcBlocks(22, new EcBlock(2, 38), new EcBlock(2, 39)), + new EcBlocks(22, new EcBlock(4, 18), new EcBlock(2, 19)), + new EcBlocks(26, new EcBlock(4, 14), new EcBlock(2, 15)) + ), + new self( + 9, + [6, 26, 46], + new EcBlocks(30, new EcBlock(2, 116)), + new EcBlocks(22, new EcBlock(3, 36), new EcBlock(2, 37)), + new EcBlocks(20, new EcBlock(4, 16), new EcBlock(4, 17)), + new EcBlocks(24, new EcBlock(4, 12), new EcBlock(4, 13)) + ), + new self( + 10, + [6, 28, 50], + new EcBlocks(18, new EcBlock(2, 68), new EcBlock(2, 69)), + new EcBlocks(26, new EcBlock(4, 43), new EcBlock(1, 44)), + new EcBlocks(24, new EcBlock(6, 19), new EcBlock(2, 20)), + new EcBlocks(28, new EcBlock(6, 15), new EcBlock(2, 16)) + ), + new self( + 11, + [6, 30, 54], + new EcBlocks(20, new EcBlock(4, 81)), + new EcBlocks(30, new EcBlock(1, 50), new EcBlock(4, 51)), + new EcBlocks(28, new EcBlock(4, 22), new EcBlock(4, 23)), + new EcBlocks(24, new EcBlock(3, 12), new EcBlock(8, 13)) + ), + new self( + 12, + [6, 32, 58], + new EcBlocks(24, new EcBlock(2, 92), new EcBlock(2, 93)), + new EcBlocks(22, new EcBlock(6, 36), new EcBlock(2, 37)), + new EcBlocks(26, new EcBlock(4, 20), new EcBlock(6, 21)), + new EcBlocks(28, new EcBlock(7, 14), new EcBlock(4, 15)) + ), + new self( + 13, + [6, 34, 62], + new EcBlocks(26, new EcBlock(4, 107)), + new EcBlocks(22, new EcBlock(8, 37), new EcBlock(1, 38)), + new EcBlocks(24, new EcBlock(8, 20), new EcBlock(4, 21)), + new EcBlocks(22, new EcBlock(12, 11), new EcBlock(4, 12)) + ), + new self( + 14, + [6, 26, 46, 66], + new EcBlocks(30, new EcBlock(3, 115), new EcBlock(1, 116)), + new EcBlocks(24, new EcBlock(4, 40), new EcBlock(5, 41)), + new EcBlocks(20, new EcBlock(11, 16), new EcBlock(5, 17)), + new EcBlocks(24, new EcBlock(11, 12), new EcBlock(5, 13)) + ), + new self( + 15, + [6, 26, 48, 70], + new EcBlocks(22, new EcBlock(5, 87), new EcBlock(1, 88)), + new EcBlocks(24, new EcBlock(5, 41), new EcBlock(5, 42)), + new EcBlocks(30, new EcBlock(5, 24), new EcBlock(7, 25)), + new EcBlocks(24, new EcBlock(11, 12), new EcBlock(7, 13)) + ), + new self( + 16, + [6, 26, 50, 74], + new EcBlocks(24, new EcBlock(5, 98), new EcBlock(1, 99)), + new EcBlocks(28, new EcBlock(7, 45), new EcBlock(3, 46)), + new EcBlocks(24, new EcBlock(15, 19), new EcBlock(2, 20)), + new EcBlocks(30, new EcBlock(3, 15), new EcBlock(13, 16)) + ), + new self( + 17, + [6, 30, 54, 78], + new EcBlocks(28, new EcBlock(1, 107), new EcBlock(5, 108)), + new EcBlocks(28, new EcBlock(10, 46), new EcBlock(1, 47)), + new EcBlocks(28, new EcBlock(1, 22), new EcBlock(15, 23)), + new EcBlocks(28, new EcBlock(2, 14), new EcBlock(17, 15)) + ), + new self( + 18, + [6, 30, 56, 82], + new EcBlocks(30, new EcBlock(5, 120), new EcBlock(1, 121)), + new EcBlocks(26, new EcBlock(9, 43), new EcBlock(4, 44)), + new EcBlocks(28, new EcBlock(17, 22), new EcBlock(1, 23)), + new EcBlocks(28, new EcBlock(2, 14), new EcBlock(19, 15)) + ), + new self( + 19, + [6, 30, 58, 86], + new EcBlocks(28, new EcBlock(3, 113), new EcBlock(4, 114)), + new EcBlocks(26, new EcBlock(3, 44), new EcBlock(11, 45)), + new EcBlocks(26, new EcBlock(17, 21), new EcBlock(4, 22)), + new EcBlocks(26, new EcBlock(9, 13), new EcBlock(16, 14)) + ), + new self( + 20, + [6, 34, 62, 90], + new EcBlocks(28, new EcBlock(3, 107), new EcBlock(5, 108)), + new EcBlocks(26, new EcBlock(3, 41), new EcBlock(13, 42)), + new EcBlocks(30, new EcBlock(15, 24), new EcBlock(5, 25)), + new EcBlocks(28, new EcBlock(15, 15), new EcBlock(10, 16)) + ), + new self( + 21, + [6, 28, 50, 72, 94], + new EcBlocks(28, new EcBlock(4, 116), new EcBlock(4, 117)), + new EcBlocks(26, new EcBlock(17, 42)), + new EcBlocks(28, new EcBlock(17, 22), new EcBlock(6, 23)), + new EcBlocks(30, new EcBlock(19, 16), new EcBlock(6, 17)) + ), + new self( + 22, + [6, 26, 50, 74, 98], + new EcBlocks(28, new EcBlock(2, 111), new EcBlock(7, 112)), + new EcBlocks(28, new EcBlock(17, 46)), + new EcBlocks(30, new EcBlock(7, 24), new EcBlock(16, 25)), + new EcBlocks(24, new EcBlock(34, 13)) + ), + new self( + 23, + [6, 30, 54, 78, 102], + new EcBlocks(30, new EcBlock(4, 121), new EcBlock(5, 122)), + new EcBlocks(28, new EcBlock(4, 47), new EcBlock(14, 48)), + new EcBlocks(30, new EcBlock(11, 24), new EcBlock(14, 25)), + new EcBlocks(30, new EcBlock(16, 15), new EcBlock(14, 16)) + ), + new self( + 24, + [6, 28, 54, 80, 106], + new EcBlocks(30, new EcBlock(6, 117), new EcBlock(4, 118)), + new EcBlocks(28, new EcBlock(6, 45), new EcBlock(14, 46)), + new EcBlocks(30, new EcBlock(11, 24), new EcBlock(16, 25)), + new EcBlocks(30, new EcBlock(30, 16), new EcBlock(2, 17)) + ), + new self( + 25, + [6, 32, 58, 84, 110], + new EcBlocks(26, new EcBlock(8, 106), new EcBlock(4, 107)), + new EcBlocks(28, new EcBlock(8, 47), new EcBlock(13, 48)), + new EcBlocks(30, new EcBlock(7, 24), new EcBlock(22, 25)), + new EcBlocks(30, new EcBlock(22, 15), new EcBlock(13, 16)) + ), + new self( + 26, + [6, 30, 58, 86, 114], + new EcBlocks(28, new EcBlock(10, 114), new EcBlock(2, 115)), + new EcBlocks(28, new EcBlock(19, 46), new EcBlock(4, 47)), + new EcBlocks(28, new EcBlock(28, 22), new EcBlock(6, 23)), + new EcBlocks(30, new EcBlock(33, 16), new EcBlock(4, 17)) + ), + new self( + 27, + [6, 34, 62, 90, 118], + new EcBlocks(30, new EcBlock(8, 122), new EcBlock(4, 123)), + new EcBlocks(28, new EcBlock(22, 45), new EcBlock(3, 46)), + new EcBlocks(30, new EcBlock(8, 23), new EcBlock(26, 24)), + new EcBlocks(30, new EcBlock(12, 15), new EcBlock(28, 16)) + ), + new self( + 28, + [6, 26, 50, 74, 98, 122], + new EcBlocks(30, new EcBlock(3, 117), new EcBlock(10, 118)), + new EcBlocks(28, new EcBlock(3, 45), new EcBlock(23, 46)), + new EcBlocks(30, new EcBlock(4, 24), new EcBlock(31, 25)), + new EcBlocks(30, new EcBlock(11, 15), new EcBlock(31, 16)) + ), + new self( + 29, + [6, 30, 54, 78, 102, 126], + new EcBlocks(30, new EcBlock(7, 116), new EcBlock(7, 117)), + new EcBlocks(28, new EcBlock(21, 45), new EcBlock(7, 46)), + new EcBlocks(30, new EcBlock(1, 23), new EcBlock(37, 24)), + new EcBlocks(30, new EcBlock(19, 15), new EcBlock(26, 16)) + ), + new self( + 30, + [6, 26, 52, 78, 104, 130], + new EcBlocks(30, new EcBlock(5, 115), new EcBlock(10, 116)), + new EcBlocks(28, new EcBlock(19, 47), new EcBlock(10, 48)), + new EcBlocks(30, new EcBlock(15, 24), new EcBlock(25, 25)), + new EcBlocks(30, new EcBlock(23, 15), new EcBlock(25, 16)) + ), + new self( + 31, + [6, 30, 56, 82, 108, 134], + new EcBlocks(30, new EcBlock(13, 115), new EcBlock(3, 116)), + new EcBlocks(28, new EcBlock(2, 46), new EcBlock(29, 47)), + new EcBlocks(30, new EcBlock(42, 24), new EcBlock(1, 25)), + new EcBlocks(30, new EcBlock(23, 15), new EcBlock(28, 16)) + ), + new self( + 32, + [6, 34, 60, 86, 112, 138], + new EcBlocks(30, new EcBlock(17, 115)), + new EcBlocks(28, new EcBlock(10, 46), new EcBlock(23, 47)), + new EcBlocks(30, new EcBlock(10, 24), new EcBlock(35, 25)), + new EcBlocks(30, new EcBlock(19, 15), new EcBlock(35, 16)) + ), + new self( + 33, + [6, 30, 58, 86, 114, 142], + new EcBlocks(30, new EcBlock(17, 115), new EcBlock(1, 116)), + new EcBlocks(28, new EcBlock(14, 46), new EcBlock(21, 47)), + new EcBlocks(30, new EcBlock(29, 24), new EcBlock(19, 25)), + new EcBlocks(30, new EcBlock(11, 15), new EcBlock(46, 16)) + ), + new self( + 34, + [6, 34, 62, 90, 118, 146], + new EcBlocks(30, new EcBlock(13, 115), new EcBlock(6, 116)), + new EcBlocks(28, new EcBlock(14, 46), new EcBlock(23, 47)), + new EcBlocks(30, new EcBlock(44, 24), new EcBlock(7, 25)), + new EcBlocks(30, new EcBlock(59, 16), new EcBlock(1, 17)) + ), + new self( + 35, + [6, 30, 54, 78, 102, 126, 150], + new EcBlocks(30, new EcBlock(12, 121), new EcBlock(7, 122)), + new EcBlocks(28, new EcBlock(12, 47), new EcBlock(26, 48)), + new EcBlocks(30, new EcBlock(39, 24), new EcBlock(14, 25)), + new EcBlocks(30, new EcBlock(22, 15), new EcBlock(41, 16)) + ), + new self( + 36, + [6, 24, 50, 76, 102, 128, 154], + new EcBlocks(30, new EcBlock(6, 121), new EcBlock(14, 122)), + new EcBlocks(28, new EcBlock(6, 47), new EcBlock(34, 48)), + new EcBlocks(30, new EcBlock(46, 24), new EcBlock(10, 25)), + new EcBlocks(30, new EcBlock(2, 15), new EcBlock(64, 16)) + ), + new self( + 37, + [6, 28, 54, 80, 106, 132, 158], + new EcBlocks(30, new EcBlock(17, 122), new EcBlock(4, 123)), + new EcBlocks(28, new EcBlock(29, 46), new EcBlock(14, 47)), + new EcBlocks(30, new EcBlock(49, 24), new EcBlock(10, 25)), + new EcBlocks(30, new EcBlock(24, 15), new EcBlock(46, 16)) + ), + new self( + 38, + [6, 32, 58, 84, 110, 136, 162], + new EcBlocks(30, new EcBlock(4, 122), new EcBlock(18, 123)), + new EcBlocks(28, new EcBlock(13, 46), new EcBlock(32, 47)), + new EcBlocks(30, new EcBlock(48, 24), new EcBlock(14, 25)), + new EcBlocks(30, new EcBlock(42, 15), new EcBlock(32, 16)) + ), + new self( + 39, + [6, 26, 54, 82, 110, 138, 166], + new EcBlocks(30, new EcBlock(20, 117), new EcBlock(4, 118)), + new EcBlocks(28, new EcBlock(40, 47), new EcBlock(7, 48)), + new EcBlocks(30, new EcBlock(43, 24), new EcBlock(22, 25)), + new EcBlocks(30, new EcBlock(10, 15), new EcBlock(67, 16)) + ), + new self( + 40, + [6, 30, 58, 86, 114, 142, 170], + new EcBlocks(30, new EcBlock(19, 118), new EcBlock(6, 119)), + new EcBlocks(28, new EcBlock(18, 47), new EcBlock(31, 48)), + new EcBlocks(30, new EcBlock(34, 24), new EcBlock(34, 25)), + new EcBlocks(30, new EcBlock(20, 15), new EcBlock(61, 16)) + ), + ]; + } +} diff --git a/vendor/bacon/bacon-qr-code/src/Encoder/BlockPair.php b/vendor/bacon/bacon-qr-code/src/Encoder/BlockPair.php new file mode 100644 index 0000000..b1dc5c4 --- /dev/null +++ b/vendor/bacon/bacon-qr-code/src/Encoder/BlockPair.php @@ -0,0 +1,44 @@ + $dataBytes Data bytes in the block. + * @param SplFixedArray $errorCorrectionBytes Error correction bytes in the block. + */ + public function __construct( + private readonly SplFixedArray $dataBytes, + private readonly SplFixedArray $errorCorrectionBytes + ) { + } + + /** + * Gets the data bytes. + * + * @return SplFixedArray + */ + public function getDataBytes() : SplFixedArray + { + return $this->dataBytes; + } + + /** + * Gets the error correction bytes. + * + * @return SplFixedArray + */ + public function getErrorCorrectionBytes() : SplFixedArray + { + return $this->errorCorrectionBytes; + } +} diff --git a/vendor/bacon/bacon-qr-code/src/Encoder/ByteMatrix.php b/vendor/bacon/bacon-qr-code/src/Encoder/ByteMatrix.php new file mode 100644 index 0000000..eefcf1c --- /dev/null +++ b/vendor/bacon/bacon-qr-code/src/Encoder/ByteMatrix.php @@ -0,0 +1,134 @@ +> + */ + private SplFixedArray $bytes; + + public function __construct(private readonly int $width, private readonly int $height) + { + $this->bytes = new SplFixedArray($height); + + for ($y = 0; $y < $height; ++$y) { + $this->bytes[$y] = SplFixedArray::fromArray(array_fill(0, $width, 0)); + } + } + + /** + * Gets the width of the matrix. + */ + public function getWidth() : int + { + return $this->width; + } + + /** + * Gets the height of the matrix. + */ + public function getHeight() : int + { + return $this->height; + } + + /** + * Gets the internal representation of the matrix. + * + * @return SplFixedArray> + */ + public function getArray() : SplFixedArray + { + return $this->bytes; + } + + /** + * @return Traversable + */ + public function getBytes() : Traversable + { + foreach ($this->bytes as $row) { + foreach ($row as $byte) { + yield $byte; + } + } + } + + /** + * Gets the byte for a specific position. + */ + public function get(int $x, int $y) : int + { + return $this->bytes[$y][$x]; + } + + /** + * Sets the byte for a specific position. + */ + public function set(int $x, int $y, int $value) : void + { + $this->bytes[$y][$x] = $value; + } + + /** + * Clears the matrix with a specific value. + */ + public function clear(int $value) : void + { + for ($y = 0; $y < $this->height; ++$y) { + for ($x = 0; $x < $this->width; ++$x) { + $this->bytes[$y][$x] = $value; + } + } + } + + public function __clone() + { + $this->bytes = clone $this->bytes; + + foreach ($this->bytes as $index => $row) { + $this->bytes[$index] = clone $row; + } + } + + /** + * Returns a string representation of the matrix. + */ + public function __toString() : string + { + $result = ''; + + for ($y = 0; $y < $this->height; $y++) { + for ($x = 0; $x < $this->width; $x++) { + switch ($this->bytes[$y][$x]) { + case 0: + $result .= ' 0'; + break; + + case 1: + $result .= ' 1'; + break; + + default: + $result .= ' '; + break; + } + } + + $result .= "\n"; + } + + return $result; + } +} diff --git a/vendor/bacon/bacon-qr-code/src/Encoder/Encoder.php b/vendor/bacon/bacon-qr-code/src/Encoder/Encoder.php new file mode 100644 index 0000000..a7e00ff --- /dev/null +++ b/vendor/bacon/bacon-qr-code/src/Encoder/Encoder.php @@ -0,0 +1,666 @@ + + */ + private static array $codecs = []; + + /** + * Encodes "content" with the error correction level "ecLevel". + */ + public static function encode( + string $content, + ErrorCorrectionLevel $ecLevel, + string $encoding = self::DEFAULT_BYTE_MODE_ENCODING, + ?Version $forcedVersion = null, + // Barcode scanner might not be able to read the encoded message of the QR code with the prefix ECI of UTF-8 + bool $prefixEci = true + ) : QrCode { + // Pick an encoding mode appropriate for the content. Note that this + // will not attempt to use multiple modes / segments even if that were + // more efficient. Would be nice. + $mode = self::chooseMode($content, $encoding); + + // This will store the header information, like mode and length, as well + // as "header" segments like an ECI segment. + $headerBits = new BitArray(); + + // Append ECI segment if applicable + if ($prefixEci && Mode::BYTE() === $mode && self::DEFAULT_BYTE_MODE_ENCODING !== $encoding) { + $eci = CharacterSetEci::getCharacterSetEciByName($encoding); + + if (null !== $eci) { + self::appendEci($eci, $headerBits); + } + } + + // (With ECI in place,) Write the mode marker + self::appendModeInfo($mode, $headerBits); + + // Collect data within the main segment, separately, to count its size + // if needed. Don't add it to main payload yet. + $dataBits = new BitArray(); + self::appendBytes($content, $mode, $dataBits, $encoding); + + // Hard part: need to know version to know how many bits length takes. + // But need to know how many bits it takes to know version. First we + // take a guess at version by assuming version will be the minimum, 1: + $provisionalBitsNeeded = $headerBits->getSize() + + $mode->getCharacterCountBits(Version::getVersionForNumber(1)) + + $dataBits->getSize(); + $provisionalVersion = self::chooseVersion($provisionalBitsNeeded, $ecLevel); + + // Use that guess to calculate the right version. I am still not sure + // this works in 100% of cases. + $bitsNeeded = $headerBits->getSize() + + $mode->getCharacterCountBits($provisionalVersion) + + $dataBits->getSize(); + $version = self::chooseVersion($bitsNeeded, $ecLevel); + + if (null !== $forcedVersion) { + // Forced version check + if ($version->getVersionNumber() <= $forcedVersion->getVersionNumber()) { + // Calculated minimum version is same or equal as forced version + $version = $forcedVersion; + } else { + throw new WriterException( + 'Invalid version! Calculated version: ' + . $version->getVersionNumber() + . ', requested version: ' + . $forcedVersion->getVersionNumber() + ); + } + } + + $headerAndDataBits = new BitArray(); + $headerAndDataBits->appendBitArray($headerBits); + + // Find "length" of main segment and write it. + $numLetters = match ($mode) { + Mode::BYTE() => $dataBits->getSizeInBytes(), + Mode::NUMERIC(), Mode::ALPHANUMERIC() => strlen($content), + Mode::KANJI() => iconv_strlen($content, 'utf-8'), + }; + self::appendLengthInfo($numLetters, $version, $mode, $headerAndDataBits); + + // Put data together into the overall payload. + $headerAndDataBits->appendBitArray($dataBits); + $ecBlocks = $version->getEcBlocksForLevel($ecLevel); + $numDataBytes = $version->getTotalCodewords() - $ecBlocks->getTotalEcCodewords(); + + // Terminate the bits properly. + self::terminateBits($numDataBytes, $headerAndDataBits); + + // Interleave data bits with error correction code. + $finalBits = self::interleaveWithEcBytes( + $headerAndDataBits, + $version->getTotalCodewords(), + $numDataBytes, + $ecBlocks->getNumBlocks() + ); + + // Choose the mask pattern. + $dimension = $version->getDimensionForVersion(); + $matrix = new ByteMatrix($dimension, $dimension); + $maskPattern = self::chooseMaskPattern($finalBits, $ecLevel, $version, $matrix); + + // Build the matrix. + MatrixUtil::buildMatrix($finalBits, $ecLevel, $version, $maskPattern, $matrix); + + return new QrCode($mode, $ecLevel, $version, $maskPattern, $matrix); + } + + /** + * Gets the alphanumeric code for a byte. + */ + private static function getAlphanumericCode(int $byte) : int + { + return self::ALPHANUMERIC_TABLE[$byte] ?? -1; + } + + /** + * Chooses the best mode for a given content. + */ + private static function chooseMode(string $content, ?string $encoding = null) : Mode + { + if ('' === $content) { + return Mode::BYTE(); + } + + if (null !== $encoding && 0 === strcasecmp($encoding, 'SHIFT-JIS')) { + return self::isOnlyDoubleByteKanji($content) ? Mode::KANJI() : Mode::BYTE(); + } + + if (ctype_digit($content)) { + return Mode::NUMERIC(); + } + + if (self::isOnlyAlphanumeric($content)) { + return Mode::ALPHANUMERIC(); + } + + return Mode::BYTE(); + } + + /** + * Calculates the mask penalty for a matrix. + */ + private static function calculateMaskPenalty(ByteMatrix $matrix) : int + { + return ( + MaskUtil::applyMaskPenaltyRule1($matrix) + + MaskUtil::applyMaskPenaltyRule2($matrix) + + MaskUtil::applyMaskPenaltyRule3($matrix) + + MaskUtil::applyMaskPenaltyRule4($matrix) + ); + } + + /** + * Checks if content only consists of double-byte kanji characters (or is empty). + */ + private static function isOnlyDoubleByteKanji(string $content) : bool + { + $bytes = @iconv('utf-8', 'SHIFT-JIS', $content); + + if (false === $bytes) { + return false; + } + + $length = strlen($bytes); + + if (0 !== $length % 2) { + return false; + } + + for ($i = 0; $i < $length; $i += 2) { + $byte = ord($bytes[$i]); + + if (($byte < 0x81 || $byte > 0x9f) && $byte < 0xe0 || $byte > 0xeb) { + return false; + } + } + + return true; + } + + /** + * Checks if content only consists of alphanumeric characters (or is empty). + */ + private static function isOnlyAlphanumeric(string $content) : bool + { + return strlen($content) === strspn($content, self::ALPHANUMERIC_CHARS); + } + + /** + * Chooses the best mask pattern for a matrix. + */ + private static function chooseMaskPattern( + BitArray $bits, + ErrorCorrectionLevel $ecLevel, + Version $version, + ByteMatrix $matrix + ) : int { + $minPenalty = PHP_INT_MAX; + $bestMaskPattern = -1; + + for ($maskPattern = 0; $maskPattern < QrCode::NUM_MASK_PATTERNS; ++$maskPattern) { + MatrixUtil::buildMatrix($bits, $ecLevel, $version, $maskPattern, $matrix); + $penalty = self::calculateMaskPenalty($matrix); + + if ($penalty < $minPenalty) { + $minPenalty = $penalty; + $bestMaskPattern = $maskPattern; + } + } + + return $bestMaskPattern; + } + + /** + * Chooses the best version for the input. + * + * @throws WriterException if data is too big + */ + private static function chooseVersion(int $numInputBits, ErrorCorrectionLevel $ecLevel) : Version + { + for ($versionNum = 1; $versionNum <= 40; ++$versionNum) { + $version = Version::getVersionForNumber($versionNum); + $numBytes = $version->getTotalCodewords(); + + $ecBlocks = $version->getEcBlocksForLevel($ecLevel); + $numEcBytes = $ecBlocks->getTotalEcCodewords(); + + $numDataBytes = $numBytes - $numEcBytes; + $totalInputBytes = intdiv($numInputBits + 8, 8); + + if ($numDataBytes >= $totalInputBytes) { + return $version; + } + } + + throw new WriterException('Data too big'); + } + + /** + * Terminates the bits in a bit array. + * + * @throws WriterException if data bits cannot fit in the QR code + * @throws WriterException if bits size does not equal the capacity + */ + private static function terminateBits(int $numDataBytes, BitArray $bits) : void + { + $capacity = $numDataBytes << 3; + + if ($bits->getSize() > $capacity) { + throw new WriterException('Data bits cannot fit in the QR code'); + } + + for ($i = 0; $i < 4 && $bits->getSize() < $capacity; ++$i) { + $bits->appendBit(false); + } + + $numBitsInLastByte = $bits->getSize() & 0x7; + + if ($numBitsInLastByte > 0) { + for ($i = $numBitsInLastByte; $i < 8; ++$i) { + $bits->appendBit(false); + } + } + + $numPaddingBytes = $numDataBytes - $bits->getSizeInBytes(); + + for ($i = 0; $i < $numPaddingBytes; ++$i) { + $bits->appendBits(0 === ($i & 0x1) ? 0xec : 0x11, 8); + } + + if ($bits->getSize() !== $capacity) { + throw new WriterException('Bits size does not equal capacity'); + } + } + + /** + * Gets number of data- and EC bytes for a block ID. + * + * @return int[] + * @throws WriterException if block ID is too large + * @throws WriterException if EC bytes mismatch + * @throws WriterException if RS blocks mismatch + * @throws WriterException if total bytes mismatch + */ + private static function getNumDataBytesAndNumEcBytesForBlockId( + int $numTotalBytes, + int $numDataBytes, + int $numRsBlocks, + int $blockId + ) : array { + if ($blockId >= $numRsBlocks) { + throw new WriterException('Block ID too large'); + } + + $numRsBlocksInGroup2 = $numTotalBytes % $numRsBlocks; + $numRsBlocksInGroup1 = $numRsBlocks - $numRsBlocksInGroup2; + $numTotalBytesInGroup1 = intdiv($numTotalBytes, $numRsBlocks); + $numTotalBytesInGroup2 = $numTotalBytesInGroup1 + 1; + $numDataBytesInGroup1 = intdiv($numDataBytes, $numRsBlocks); + $numDataBytesInGroup2 = $numDataBytesInGroup1 + 1; + $numEcBytesInGroup1 = $numTotalBytesInGroup1 - $numDataBytesInGroup1; + $numEcBytesInGroup2 = $numTotalBytesInGroup2 - $numDataBytesInGroup2; + + if ($numEcBytesInGroup1 !== $numEcBytesInGroup2) { + throw new WriterException('EC bytes mismatch'); + } + + if ($numRsBlocks !== $numRsBlocksInGroup1 + $numRsBlocksInGroup2) { + throw new WriterException('RS blocks mismatch'); + } + + if ($numTotalBytes !== + (($numDataBytesInGroup1 + $numEcBytesInGroup1) * $numRsBlocksInGroup1) + + (($numDataBytesInGroup2 + $numEcBytesInGroup2) * $numRsBlocksInGroup2) + ) { + throw new WriterException('Total bytes mismatch'); + } + + if ($blockId < $numRsBlocksInGroup1) { + return [$numDataBytesInGroup1, $numEcBytesInGroup1]; + } else { + return [$numDataBytesInGroup2, $numEcBytesInGroup2]; + } + } + + /** + * Interleaves data with EC bytes. + * + * @throws WriterException if number of bits and data bytes does not match + * @throws WriterException if data bytes does not match offset + * @throws WriterException if an interleaving error occurs + */ + private static function interleaveWithEcBytes( + BitArray $bits, + int $numTotalBytes, + int $numDataBytes, + int $numRsBlocks + ) : BitArray { + if ($bits->getSizeInBytes() !== $numDataBytes) { + throw new WriterException('Number of bits and data bytes does not match'); + } + + $dataBytesOffset = 0; + $maxNumDataBytes = 0; + $maxNumEcBytes = 0; + + $blocks = new SplFixedArray($numRsBlocks); + + for ($i = 0; $i < $numRsBlocks; ++$i) { + list($numDataBytesInBlock, $numEcBytesInBlock) = self::getNumDataBytesAndNumEcBytesForBlockId( + $numTotalBytes, + $numDataBytes, + $numRsBlocks, + $i + ); + + $size = $numDataBytesInBlock; + $dataBytes = $bits->toBytes(8 * $dataBytesOffset, $size); + $ecBytes = self::generateEcBytes($dataBytes, $numEcBytesInBlock); + $blocks[$i] = new BlockPair($dataBytes, $ecBytes); + + $maxNumDataBytes = max($maxNumDataBytes, $size); + $maxNumEcBytes = max($maxNumEcBytes, count($ecBytes)); + $dataBytesOffset += $numDataBytesInBlock; + } + + if ($numDataBytes !== $dataBytesOffset) { + throw new WriterException('Data bytes does not match offset'); + } + + $result = new BitArray(); + + for ($i = 0; $i < $maxNumDataBytes; ++$i) { + foreach ($blocks as $block) { + $dataBytes = $block->getDataBytes(); + + if ($i < count($dataBytes)) { + $result->appendBits($dataBytes[$i], 8); + } + } + } + + for ($i = 0; $i < $maxNumEcBytes; ++$i) { + foreach ($blocks as $block) { + $ecBytes = $block->getErrorCorrectionBytes(); + + if ($i < count($ecBytes)) { + $result->appendBits($ecBytes[$i], 8); + } + } + } + + if ($numTotalBytes !== $result->getSizeInBytes()) { + throw new WriterException( + 'Interleaving error: ' . $numTotalBytes . ' and ' . $result->getSizeInBytes() . ' differ' + ); + } + + return $result; + } + + /** + * Generates EC bytes for given data. + * + * @param SplFixedArray $dataBytes + * @return SplFixedArray + */ + private static function generateEcBytes(SplFixedArray $dataBytes, int $numEcBytesInBlock) : SplFixedArray + { + $numDataBytes = count($dataBytes); + $toEncode = new SplFixedArray($numDataBytes + $numEcBytesInBlock); + + for ($i = 0; $i < $numDataBytes; $i++) { + $toEncode[$i] = $dataBytes[$i]; + } + + $ecBytes = new SplFixedArray($numEcBytesInBlock); + $codec = self::getCodec($numDataBytes, $numEcBytesInBlock); + $codec->encode($toEncode, $ecBytes); + + return $ecBytes; + } + + /** + * Gets an RS codec and caches it. + */ + private static function getCodec(int $numDataBytes, int $numEcBytesInBlock) : ReedSolomonCodec + { + $cacheId = $numDataBytes . '-' . $numEcBytesInBlock; + + if (isset(self::$codecs[$cacheId])) { + return self::$codecs[$cacheId]; + } + + return self::$codecs[$cacheId] = new ReedSolomonCodec( + 8, + 0x11d, + 0, + 1, + $numEcBytesInBlock, + 255 - $numDataBytes - $numEcBytesInBlock + ); + } + + /** + * Appends mode information to a bit array. + */ + private static function appendModeInfo(Mode $mode, BitArray $bits) : void + { + $bits->appendBits($mode->getBits(), 4); + } + + /** + * Appends length information to a bit array. + * + * @throws WriterException if num letters is bigger than expected + */ + private static function appendLengthInfo(int $numLetters, Version $version, Mode $mode, BitArray $bits) : void + { + $numBits = $mode->getCharacterCountBits($version); + + if ($numLetters >= (1 << $numBits)) { + throw new WriterException($numLetters . ' is bigger than ' . ((1 << $numBits) - 1)); + } + + $bits->appendBits($numLetters, $numBits); + } + + /** + * Appends bytes to a bit array in a specific mode. + */ + private static function appendBytes(string $content, Mode $mode, BitArray $bits, string $encoding) : void + { + match ($mode) { + Mode::NUMERIC() => self::appendNumericBytes($content, $bits), + Mode::ALPHANUMERIC() => self::appendAlphanumericBytes($content, $bits), + Mode::BYTE() => self::append8BitBytes($content, $bits, $encoding), + Mode::KANJI() => self::appendKanjiBytes($content, $bits), + }; + } + + /** + * Appends numeric bytes to a bit array. + */ + private static function appendNumericBytes(string $content, BitArray $bits) : void + { + $length = strlen($content); + $i = 0; + + while ($i < $length) { + $num1 = (int) $content[$i]; + + if ($i + 2 < $length) { + // Encode three numeric letters in ten bits. + $num2 = (int) $content[$i + 1]; + $num3 = (int) $content[$i + 2]; + $bits->appendBits($num1 * 100 + $num2 * 10 + $num3, 10); + $i += 3; + } elseif ($i + 1 < $length) { + // Encode two numeric letters in seven bits. + $num2 = (int) $content[$i + 1]; + $bits->appendBits($num1 * 10 + $num2, 7); + $i += 2; + } else { + // Encode one numeric letter in four bits. + $bits->appendBits($num1, 4); + ++$i; + } + } + } + + /** + * Appends alpha-numeric bytes to a bit array. + * + * @throws WriterException if an invalid alphanumeric code was found + */ + private static function appendAlphanumericBytes(string $content, BitArray $bits) : void + { + $length = strlen($content); + $i = 0; + + while ($i < $length) { + $code1 = self::getAlphanumericCode(ord($content[$i])); + + if (-1 === $code1) { + throw new WriterException('Invalid alphanumeric code'); + } + + if ($i + 1 < $length) { + $code2 = self::getAlphanumericCode(ord($content[$i + 1])); + + if (-1 === $code2) { + throw new WriterException('Invalid alphanumeric code'); + } + + // Encode two alphanumeric letters in 11 bits. + $bits->appendBits($code1 * 45 + $code2, 11); + $i += 2; + } else { + // Encode one alphanumeric letter in six bits. + $bits->appendBits($code1, 6); + ++$i; + } + } + } + + /** + * Appends regular 8-bit bytes to a bit array. + * + * @throws WriterException if content cannot be encoded to target encoding + */ + private static function append8BitBytes(string $content, BitArray $bits, string $encoding) : void + { + $bytes = @iconv('utf-8', $encoding, $content); + + if (false === $bytes) { + throw new WriterException('Could not encode content to ' . $encoding); + } + + $length = strlen($bytes); + + for ($i = 0; $i < $length; $i++) { + $bits->appendBits(ord($bytes[$i]), 8); + } + } + + /** + * Appends KANJI bytes to a bit array. + * + * @throws WriterException if content does not seem to be encoded in SHIFT-JIS + * @throws WriterException if an invalid byte sequence occurs + */ + private static function appendKanjiBytes(string $content, BitArray $bits) : void + { + $bytes = @iconv('utf-8', 'SHIFT-JIS', $content); + + if (false === $bytes) { + throw new WriterException('Content could not be converted to SHIFT-JIS'); + } + + if (strlen($bytes) % 2 > 0) { + // We just do a simple length check here. The for loop will check + // individual characters. + throw new WriterException('Content does not seem to be encoded in SHIFT-JIS'); + } + + $length = strlen($bytes); + + for ($i = 0; $i < $length; $i += 2) { + $byte1 = ord($bytes[$i]); + $byte2 = ord($bytes[$i + 1]); + $code = ($byte1 << 8) | $byte2; + + if ($code >= 0x8140 && $code <= 0x9ffc) { + $subtracted = $code - 0x8140; + } elseif ($code >= 0xe040 && $code <= 0xebbf) { + $subtracted = $code - 0xc140; + } else { + throw new WriterException('Invalid byte sequence'); + } + + $encoded = (($subtracted >> 8) * 0xc0) + ($subtracted & 0xff); + + $bits->appendBits($encoded, 13); + } + } + + /** + * Appends ECI information to a bit array. + */ + private static function appendEci(CharacterSetEci $eci, BitArray $bits) : void + { + $mode = Mode::ECI(); + $bits->appendBits($mode->getBits(), 4); + $bits->appendBits($eci->getValue(), 8); + } +} diff --git a/vendor/bacon/bacon-qr-code/src/Encoder/MaskUtil.php b/vendor/bacon/bacon-qr-code/src/Encoder/MaskUtil.php new file mode 100644 index 0000000..66f3ff1 --- /dev/null +++ b/vendor/bacon/bacon-qr-code/src/Encoder/MaskUtil.php @@ -0,0 +1,271 @@ +getArray(); + $width = $matrix->getWidth(); + $height = $matrix->getHeight(); + + for ($y = 0; $y < $height - 1; ++$y) { + for ($x = 0; $x < $width - 1; ++$x) { + $value = $array[$y][$x]; + + if ($value === $array[$y][$x + 1] + && $value === $array[$y + 1][$x] + && $value === $array[$y + 1][$x + 1] + ) { + ++$penalty; + } + } + } + + return self::N2 * $penalty; + } + + /** + * Applies mask penalty rule 3 and returns the penalty. + * + * Finds consecutive cells of 00001011101 or 10111010000, and gives penalty + * to them. If we find patterns like 000010111010000, we give penalties + * twice (i.e. 40 * 2). + */ + public static function applyMaskPenaltyRule3(ByteMatrix $matrix) : int + { + $penalty = 0; + $array = $matrix->getArray(); + $width = $matrix->getWidth(); + $height = $matrix->getHeight(); + + for ($y = 0; $y < $height; ++$y) { + for ($x = 0; $x < $width; ++$x) { + if ($x + 6 < $width + && 1 === $array[$y][$x] + && 0 === $array[$y][$x + 1] + && 1 === $array[$y][$x + 2] + && 1 === $array[$y][$x + 3] + && 1 === $array[$y][$x + 4] + && 0 === $array[$y][$x + 5] + && 1 === $array[$y][$x + 6] + && ( + ( + $x + 10 < $width + && 0 === $array[$y][$x + 7] + && 0 === $array[$y][$x + 8] + && 0 === $array[$y][$x + 9] + && 0 === $array[$y][$x + 10] + ) + || ( + $x - 4 >= 0 + && 0 === $array[$y][$x - 1] + && 0 === $array[$y][$x - 2] + && 0 === $array[$y][$x - 3] + && 0 === $array[$y][$x - 4] + ) + ) + ) { + $penalty += self::N3; + } + + if ($y + 6 < $height + && 1 === $array[$y][$x] + && 0 === $array[$y + 1][$x] + && 1 === $array[$y + 2][$x] + && 1 === $array[$y + 3][$x] + && 1 === $array[$y + 4][$x] + && 0 === $array[$y + 5][$x] + && 1 === $array[$y + 6][$x] + && ( + ( + $y + 10 < $height + && 0 === $array[$y + 7][$x] + && 0 === $array[$y + 8][$x] + && 0 === $array[$y + 9][$x] + && 0 === $array[$y + 10][$x] + ) + || ( + $y - 4 >= 0 + && 0 === $array[$y - 1][$x] + && 0 === $array[$y - 2][$x] + && 0 === $array[$y - 3][$x] + && 0 === $array[$y - 4][$x] + ) + ) + ) { + $penalty += self::N3; + } + } + } + + return $penalty; + } + + /** + * Applies mask penalty rule 4 and returns the penalty. + * + * Calculates the ratio of dark cells and gives penalty if the ratio is far + * from 50%. It gives 10 penalty for 5% distance. + */ + public static function applyMaskPenaltyRule4(ByteMatrix $matrix) : int + { + $numDarkCells = 0; + + $array = $matrix->getArray(); + $width = $matrix->getWidth(); + $height = $matrix->getHeight(); + + for ($y = 0; $y < $height; ++$y) { + $arrayY = $array[$y]; + + for ($x = 0; $x < $width; ++$x) { + if (1 === $arrayY[$x]) { + ++$numDarkCells; + } + } + } + + $numTotalCells = $height * $width; + $darkRatio = $numDarkCells / $numTotalCells; + $fixedPercentVariances = (int) floor(abs($darkRatio - 0.5) * 20); + + return $fixedPercentVariances * self::N4; + } + + /** + * Returns the mask bit for "getMaskPattern" at "x" and "y". + * + * See 8.8 of JISX0510:2004 for mask pattern conditions. + * + * @throws InvalidArgumentException if an invalid mask pattern was supplied + */ + public static function getDataMaskBit(int $maskPattern, int $x, int $y) : bool + { + switch ($maskPattern) { + case 0: + $intermediate = ($y + $x) & 0x1; + break; + + case 1: + $intermediate = $y & 0x1; + break; + + case 2: + $intermediate = $x % 3; + break; + + case 3: + $intermediate = ($y + $x) % 3; + break; + + case 4: + $intermediate = (BitUtils::unsignedRightShift($y, 1) + (int) ($x / 3)) & 0x1; + break; + + case 5: + $temp = $y * $x; + $intermediate = ($temp & 0x1) + ($temp % 3); + break; + + case 6: + $temp = $y * $x; + $intermediate = (($temp & 0x1) + ($temp % 3)) & 0x1; + break; + + case 7: + $temp = $y * $x; + $intermediate = (($temp % 3) + (($y + $x) & 0x1)) & 0x1; + break; + + default: + throw new InvalidArgumentException('Invalid mask pattern: ' . $maskPattern); + } + + return 0 == $intermediate; + } + + /** + * Helper function for applyMaskPenaltyRule1. + * + * We need this for doing this calculation in both vertical and horizontal + * orders respectively. + */ + private static function applyMaskPenaltyRule1Internal(ByteMatrix $matrix, bool $isHorizontal) : int + { + $penalty = 0; + $iLimit = $isHorizontal ? $matrix->getHeight() : $matrix->getWidth(); + $jLimit = $isHorizontal ? $matrix->getWidth() : $matrix->getHeight(); + $array = $matrix->getArray(); + + for ($i = 0; $i < $iLimit; ++$i) { + $numSameBitCells = 0; + $prevBit = -1; + + for ($j = 0; $j < $jLimit; $j++) { + $bit = $isHorizontal ? $array[$i][$j] : $array[$j][$i]; + + if ($bit === $prevBit) { + ++$numSameBitCells; + } else { + if ($numSameBitCells >= 5) { + $penalty += self::N1 + ($numSameBitCells - 5); + } + + $numSameBitCells = 1; + $prevBit = $bit; + } + } + + if ($numSameBitCells >= 5) { + $penalty += self::N1 + ($numSameBitCells - 5); + } + } + + return $penalty; + } +} diff --git a/vendor/bacon/bacon-qr-code/src/Encoder/MatrixUtil.php b/vendor/bacon/bacon-qr-code/src/Encoder/MatrixUtil.php new file mode 100644 index 0000000..0967e29 --- /dev/null +++ b/vendor/bacon/bacon-qr-code/src/Encoder/MatrixUtil.php @@ -0,0 +1,513 @@ +clear(-1); + } + + /** + * Builds a complete matrix. + */ + public static function buildMatrix( + BitArray $dataBits, + ErrorCorrectionLevel $level, + Version $version, + int $maskPattern, + ByteMatrix $matrix + ) : void { + self::clearMatrix($matrix); + self::embedBasicPatterns($version, $matrix); + self::embedTypeInfo($level, $maskPattern, $matrix); + self::maybeEmbedVersionInfo($version, $matrix); + self::embedDataBits($dataBits, $maskPattern, $matrix); + } + + /** + * Removes the position detection patterns from a matrix. + * + * This can be useful if you need to render those patterns separately. + */ + public static function removePositionDetectionPatterns(ByteMatrix $matrix) : void + { + $pdpWidth = count(self::POSITION_DETECTION_PATTERN[0]); + + self::removePositionDetectionPattern(0, 0, $matrix); + self::removePositionDetectionPattern($matrix->getWidth() - $pdpWidth, 0, $matrix); + self::removePositionDetectionPattern(0, $matrix->getWidth() - $pdpWidth, $matrix); + } + + /** + * Embeds type information into a matrix. + */ + private static function embedTypeInfo(ErrorCorrectionLevel $level, int $maskPattern, ByteMatrix $matrix) : void + { + $typeInfoBits = new BitArray(); + self::makeTypeInfoBits($level, $maskPattern, $typeInfoBits); + + $typeInfoBitsSize = $typeInfoBits->getSize(); + + for ($i = 0; $i < $typeInfoBitsSize; ++$i) { + $bit = $typeInfoBits->get($typeInfoBitsSize - 1 - $i); + + $x1 = self::TYPE_INFO_COORDINATES[$i][0]; + $y1 = self::TYPE_INFO_COORDINATES[$i][1]; + + $matrix->set($x1, $y1, (int) $bit); + + if ($i < 8) { + $x2 = $matrix->getWidth() - $i - 1; + $y2 = 8; + } else { + $x2 = 8; + $y2 = $matrix->getHeight() - 7 + ($i - 8); + } + + $matrix->set($x2, $y2, (int) $bit); + } + } + + /** + * Generates type information bits and appends them to a bit array. + * + * @throws RuntimeException if bit array resulted in invalid size + */ + private static function makeTypeInfoBits(ErrorCorrectionLevel $level, int $maskPattern, BitArray $bits) : void + { + $typeInfo = ($level->getBits() << 3) | $maskPattern; + $bits->appendBits($typeInfo, 5); + + $bchCode = self::calculateBchCode($typeInfo, self::TYPE_INFO_POLY); + $bits->appendBits($bchCode, 10); + + $maskBits = new BitArray(); + $maskBits->appendBits(self::TYPE_INFO_MASK_PATTERN, 15); + $bits->xorBits($maskBits); + + if (15 !== $bits->getSize()) { + throw new RuntimeException('Bit array resulted in invalid size: ' . $bits->getSize()); + } + } + + /** + * Embeds version information if required. + */ + private static function maybeEmbedVersionInfo(Version $version, ByteMatrix $matrix) : void + { + if ($version->getVersionNumber() < 7) { + return; + } + + $versionInfoBits = new BitArray(); + self::makeVersionInfoBits($version, $versionInfoBits); + + $bitIndex = 6 * 3 - 1; + + for ($i = 0; $i < 6; ++$i) { + for ($j = 0; $j < 3; ++$j) { + $bit = $versionInfoBits->get($bitIndex); + --$bitIndex; + + $matrix->set($i, $matrix->getHeight() - 11 + $j, (int) $bit); + $matrix->set($matrix->getHeight() - 11 + $j, $i, (int) $bit); + } + } + } + + /** + * Generates version information bits and appends them to a bit array. + * + * @throws RuntimeException if bit array resulted in invalid size + */ + private static function makeVersionInfoBits(Version $version, BitArray $bits) : void + { + $bits->appendBits($version->getVersionNumber(), 6); + + $bchCode = self::calculateBchCode($version->getVersionNumber(), self::VERSION_INFO_POLY); + $bits->appendBits($bchCode, 12); + + if (18 !== $bits->getSize()) { + throw new RuntimeException('Bit array resulted in invalid size: ' . $bits->getSize()); + } + } + + /** + * Calculates the BCH code for a value and a polynomial. + */ + private static function calculateBchCode(int $value, int $poly) : int + { + $msbSetInPoly = self::findMsbSet($poly); + $value <<= $msbSetInPoly - 1; + + while (self::findMsbSet($value) >= $msbSetInPoly) { + $value ^= $poly << (self::findMsbSet($value) - $msbSetInPoly); + } + + return $value; + } + + /** + * Finds and MSB set. + */ + private static function findMsbSet(int $value) : int + { + $numDigits = 0; + + while (0 !== $value) { + $value >>= 1; + ++$numDigits; + } + + return $numDigits; + } + + /** + * Embeds basic patterns into a matrix. + */ + private static function embedBasicPatterns(Version $version, ByteMatrix $matrix) : void + { + self::embedPositionDetectionPatternsAndSeparators($matrix); + self::embedDarkDotAtLeftBottomCorner($matrix); + self::maybeEmbedPositionAdjustmentPatterns($version, $matrix); + self::embedTimingPatterns($matrix); + } + + /** + * Embeds position detection patterns and separators into a byte matrix. + */ + private static function embedPositionDetectionPatternsAndSeparators(ByteMatrix $matrix) : void + { + $pdpWidth = count(self::POSITION_DETECTION_PATTERN[0]); + + self::embedPositionDetectionPattern(0, 0, $matrix); + self::embedPositionDetectionPattern($matrix->getWidth() - $pdpWidth, 0, $matrix); + self::embedPositionDetectionPattern(0, $matrix->getWidth() - $pdpWidth, $matrix); + + $hspWidth = 8; + + self::embedHorizontalSeparationPattern(0, $hspWidth - 1, $matrix); + self::embedHorizontalSeparationPattern($matrix->getWidth() - $hspWidth, $hspWidth - 1, $matrix); + self::embedHorizontalSeparationPattern(0, $matrix->getWidth() - $hspWidth, $matrix); + + $vspSize = 7; + + self::embedVerticalSeparationPattern($vspSize, 0, $matrix); + self::embedVerticalSeparationPattern($matrix->getHeight() - $vspSize - 1, 0, $matrix); + self::embedVerticalSeparationPattern($vspSize, $matrix->getHeight() - $vspSize, $matrix); + } + + /** + * Embeds a single position detection pattern into a byte matrix. + */ + private static function embedPositionDetectionPattern(int $xStart, int $yStart, ByteMatrix $matrix) : void + { + for ($y = 0; $y < 7; ++$y) { + for ($x = 0; $x < 7; ++$x) { + $matrix->set($xStart + $x, $yStart + $y, self::POSITION_DETECTION_PATTERN[$y][$x]); + } + } + } + + private static function removePositionDetectionPattern(int $xStart, int $yStart, ByteMatrix $matrix) : void + { + for ($y = 0; $y < 7; ++$y) { + for ($x = 0; $x < 7; ++$x) { + $matrix->set($xStart + $x, $yStart + $y, 0); + } + } + } + + /** + * Embeds a single horizontal separation pattern. + * + * @throws RuntimeException if a byte was already set + */ + private static function embedHorizontalSeparationPattern(int $xStart, int $yStart, ByteMatrix $matrix) : void + { + for ($x = 0; $x < 8; $x++) { + if (-1 !== $matrix->get($xStart + $x, $yStart)) { + throw new RuntimeException('Byte already set'); + } + + $matrix->set($xStart + $x, $yStart, 0); + } + } + + /** + * Embeds a single vertical separation pattern. + * + * @throws RuntimeException if a byte was already set + */ + private static function embedVerticalSeparationPattern(int $xStart, int $yStart, ByteMatrix $matrix) : void + { + for ($y = 0; $y < 7; $y++) { + if (-1 !== $matrix->get($xStart, $yStart + $y)) { + throw new RuntimeException('Byte already set'); + } + + $matrix->set($xStart, $yStart + $y, 0); + } + } + + /** + * Embeds a dot at the left bottom corner. + * + * @throws RuntimeException if a byte was already set to 0 + */ + private static function embedDarkDotAtLeftBottomCorner(ByteMatrix $matrix) : void + { + if (0 === $matrix->get(8, $matrix->getHeight() - 8)) { + throw new RuntimeException('Byte already set to 0'); + } + + $matrix->set(8, $matrix->getHeight() - 8, 1); + } + + /** + * Embeds position adjustment patterns if required. + */ + private static function maybeEmbedPositionAdjustmentPatterns(Version $version, ByteMatrix $matrix) : void + { + if ($version->getVersionNumber() < 2) { + return; + } + + $index = $version->getVersionNumber() - 1; + + $coordinates = self::POSITION_ADJUSTMENT_PATTERN_COORDINATE_TABLE[$index]; + $numCoordinates = count($coordinates); + + for ($i = 0; $i < $numCoordinates; ++$i) { + for ($j = 0; $j < $numCoordinates; ++$j) { + $y = $coordinates[$i]; + $x = $coordinates[$j]; + + if (null === $x || null === $y) { + continue; + } + + if (-1 === $matrix->get($x, $y)) { + self::embedPositionAdjustmentPattern($x - 2, $y - 2, $matrix); + } + } + } + } + + /** + * Embeds a single position adjustment pattern. + */ + private static function embedPositionAdjustmentPattern(int $xStart, int $yStart, ByteMatrix $matrix) : void + { + for ($y = 0; $y < 5; $y++) { + for ($x = 0; $x < 5; $x++) { + $matrix->set($xStart + $x, $yStart + $y, self::POSITION_ADJUSTMENT_PATTERN[$y][$x]); + } + } + } + + /** + * Embeds timing patterns into a matrix. + */ + private static function embedTimingPatterns(ByteMatrix $matrix) : void + { + $matrixWidth = $matrix->getWidth(); + + for ($i = 8; $i < $matrixWidth - 8; ++$i) { + $bit = ($i + 1) % 2; + + if (-1 === $matrix->get($i, 6)) { + $matrix->set($i, 6, $bit); + } + + if (-1 === $matrix->get(6, $i)) { + $matrix->set(6, $i, $bit); + } + } + } + + /** + * Embeds "dataBits" using "getMaskPattern". + * + * For debugging purposes, it skips masking process if "getMaskPattern" is -1. See 8.7 of JISX0510:2004 (p.38) for + * how to embed data bits. + * + * @throws WriterException if not all bits could be consumed + */ + private static function embedDataBits(BitArray $dataBits, int $maskPattern, ByteMatrix $matrix) : void + { + $bitIndex = 0; + $direction = -1; + + // Start from the right bottom cell. + $x = $matrix->getWidth() - 1; + $y = $matrix->getHeight() - 1; + + while ($x > 0) { + // Skip vertical timing pattern. + if (6 === $x) { + --$x; + } + + while ($y >= 0 && $y < $matrix->getHeight()) { + for ($i = 0; $i < 2; $i++) { + $xx = $x - $i; + + // Skip the cell if it's not empty. + if (-1 !== $matrix->get($xx, $y)) { + continue; + } + + if ($bitIndex < $dataBits->getSize()) { + $bit = $dataBits->get($bitIndex); + ++$bitIndex; + } else { + // Padding bit. If there is no bit left, we'll fill the + // left cells with 0, as described in 8.4.9 of + // JISX0510:2004 (p. 24). + $bit = false; + } + + // Skip masking if maskPattern is -1. + if (-1 !== $maskPattern && MaskUtil::getDataMaskBit($maskPattern, $xx, $y)) { + $bit = ! $bit; + } + + $matrix->set($xx, $y, (int) $bit); + } + + $y += $direction; + } + + $direction = -$direction; + $y += $direction; + $x -= 2; + } + + // All bits should be consumed + if ($dataBits->getSize() !== $bitIndex) { + throw new WriterException('Not all bits consumed (' . $bitIndex . ' out of ' . $dataBits->getSize() .')'); + } + } +} diff --git a/vendor/bacon/bacon-qr-code/src/Encoder/QrCode.php b/vendor/bacon/bacon-qr-code/src/Encoder/QrCode.php new file mode 100644 index 0000000..c3398f4 --- /dev/null +++ b/vendor/bacon/bacon-qr-code/src/Encoder/QrCode.php @@ -0,0 +1,108 @@ +maskPattern = $maskPattern; + $this->matrix = $matrix; + } + + /** + * Gets the mode. + */ + public function getMode() : Mode + { + return $this->mode; + } + + /** + * Gets the EC level. + */ + public function getErrorCorrectionLevel() : ErrorCorrectionLevel + { + return $this->errorCorrectionLevel; + } + + /** + * Gets the version. + */ + public function getVersion() : Version + { + return $this->version; + } + + /** + * Gets the mask pattern. + */ + public function getMaskPattern() : int + { + return $this->maskPattern; + } + + public function getMatrix(): ByteMatrix + { + return $this->matrix; + } + + /** + * Validates whether a mask pattern is valid. + */ + public static function isValidMaskPattern(int $maskPattern) : bool + { + return $maskPattern > 0 && $maskPattern < self::NUM_MASK_PATTERNS; + } + + /** + * Returns a string representation of the QR code. + */ + public function __toString() : string + { + $result = "<<\n" + . ' mode: ' . $this->mode . "\n" + . ' ecLevel: ' . $this->errorCorrectionLevel . "\n" + . ' version: ' . $this->version . "\n" + . ' maskPattern: ' . $this->maskPattern . "\n"; + + if ($this->matrix === null) { + $result .= " matrix: null\n"; + } else { + $result .= " matrix:\n"; + $result .= $this->matrix; + } + + $result .= ">>\n"; + + return $result; + } +} diff --git a/vendor/bacon/bacon-qr-code/src/Exception/ExceptionInterface.php b/vendor/bacon/bacon-qr-code/src/Exception/ExceptionInterface.php new file mode 100644 index 0000000..6f70c20 --- /dev/null +++ b/vendor/bacon/bacon-qr-code/src/Exception/ExceptionInterface.php @@ -0,0 +1,10 @@ + 100) { + throw new Exception\InvalidArgumentException('Alpha must be between 0 and 100'); + } + } + + public function getAlpha() : int + { + return $this->alpha; + } + + public function getBaseColor() : ColorInterface + { + return $this->baseColor; + } + + public function toRgb() : Rgb + { + return $this->baseColor->toRgb(); + } + + public function toCmyk() : Cmyk + { + return $this->baseColor->toCmyk(); + } + + public function toGray() : Gray + { + return $this->baseColor->toGray(); + } +} diff --git a/vendor/bacon/bacon-qr-code/src/Renderer/Color/Cmyk.php b/vendor/bacon/bacon-qr-code/src/Renderer/Color/Cmyk.php new file mode 100644 index 0000000..d028210 --- /dev/null +++ b/vendor/bacon/bacon-qr-code/src/Renderer/Color/Cmyk.php @@ -0,0 +1,82 @@ + 100) { + throw new Exception\InvalidArgumentException('Cyan must be between 0 and 100'); + } + + if ($magenta < 0 || $magenta > 100) { + throw new Exception\InvalidArgumentException('Magenta must be between 0 and 100'); + } + + if ($yellow < 0 || $yellow > 100) { + throw new Exception\InvalidArgumentException('Yellow must be between 0 and 100'); + } + + if ($black < 0 || $black > 100) { + throw new Exception\InvalidArgumentException('Black must be between 0 and 100'); + } + } + + public function getCyan() : int + { + return $this->cyan; + } + + public function getMagenta() : int + { + return $this->magenta; + } + + public function getYellow() : int + { + return $this->yellow; + } + + public function getBlack() : int + { + return $this->black; + } + + public function toRgb() : Rgb + { + $k = $this->black / 100; + $c = (-$k * $this->cyan + $k * 100 + $this->cyan) / 100; + $m = (-$k * $this->magenta + $k * 100 + $this->magenta) / 100; + $y = (-$k * $this->yellow + $k * 100 + $this->yellow) / 100; + + return new Rgb( + (int) (-$c * 255 + 255), + (int) (-$m * 255 + 255), + (int) (-$y * 255 + 255) + ); + } + + public function toCmyk() : Cmyk + { + return $this; + } + + public function toGray() : Gray + { + return $this->toRgb()->toGray(); + } +} diff --git a/vendor/bacon/bacon-qr-code/src/Renderer/Color/ColorInterface.php b/vendor/bacon/bacon-qr-code/src/Renderer/Color/ColorInterface.php new file mode 100644 index 0000000..b50d1ca --- /dev/null +++ b/vendor/bacon/bacon-qr-code/src/Renderer/Color/ColorInterface.php @@ -0,0 +1,22 @@ + 100) { + throw new Exception\InvalidArgumentException('Gray must be between 0 and 100'); + } + } + + public function getGray() : int + { + return $this->gray; + } + + public function toRgb() : Rgb + { + return new Rgb((int) ($this->gray * 2.55), (int) ($this->gray * 2.55), (int) ($this->gray * 2.55)); + } + + public function toCmyk() : Cmyk + { + return new Cmyk(0, 0, 0, 100 - $this->gray); + } + + public function toGray() : Gray + { + return $this; + } +} diff --git a/vendor/bacon/bacon-qr-code/src/Renderer/Color/Rgb.php b/vendor/bacon/bacon-qr-code/src/Renderer/Color/Rgb.php new file mode 100644 index 0000000..9e388da --- /dev/null +++ b/vendor/bacon/bacon-qr-code/src/Renderer/Color/Rgb.php @@ -0,0 +1,73 @@ + 255) { + throw new Exception\InvalidArgumentException('Red must be between 0 and 255'); + } + + if ($green < 0 || $green > 255) { + throw new Exception\InvalidArgumentException('Green must be between 0 and 255'); + } + + if ($blue < 0 || $blue > 255) { + throw new Exception\InvalidArgumentException('Blue must be between 0 and 255'); + } + } + + public function getRed() : int + { + return $this->red; + } + + public function getGreen() : int + { + return $this->green; + } + + public function getBlue() : int + { + return $this->blue; + } + + public function toRgb() : Rgb + { + return $this; + } + + public function toCmyk() : Cmyk + { + $c = 1 - ($this->red / 255); + $m = 1 - ($this->green / 255); + $y = 1 - ($this->blue / 255); + $k = min($c, $m, $y); + + if ($k === 0) { + return new Cmyk(0, 0, 0, 0); + } + + return new Cmyk( + (int) (100 * ($c - $k) / (1 - $k)), + (int) (100 * ($m - $k) / (1 - $k)), + (int) (100 * ($y - $k) / (1 - $k)), + (int) (100 * $k) + ); + } + + public function toGray() : Gray + { + return new Gray((int) (($this->red * 0.21 + $this->green * 0.71 + $this->blue * 0.07) / 2.55)); + } +} diff --git a/vendor/bacon/bacon-qr-code/src/Renderer/Eye/CompositeEye.php b/vendor/bacon/bacon-qr-code/src/Renderer/Eye/CompositeEye.php new file mode 100644 index 0000000..379e5c7 --- /dev/null +++ b/vendor/bacon/bacon-qr-code/src/Renderer/Eye/CompositeEye.php @@ -0,0 +1,26 @@ +externalEye->getExternalPath(); + } + + public function getInternalPath() : Path + { + return $this->internalEye->getInternalPath(); + } +} diff --git a/vendor/bacon/bacon-qr-code/src/Renderer/Eye/EyeInterface.php b/vendor/bacon/bacon-qr-code/src/Renderer/Eye/EyeInterface.php new file mode 100644 index 0000000..ab68f3c --- /dev/null +++ b/vendor/bacon/bacon-qr-code/src/Renderer/Eye/EyeInterface.php @@ -0,0 +1,26 @@ +set($x, 0, 1); + $matrix->set($x, 6, 1); + } + + for ($y = 1; $y < 6; ++$y) { + $matrix->set(0, $y, 1); + $matrix->set(6, $y, 1); + } + + return $this->module->createPath($matrix)->translate(-3.5, -3.5); + } + + public function getInternalPath() : Path + { + $matrix = new ByteMatrix(3, 3); + + for ($x = 0; $x < 3; ++$x) { + for ($y = 0; $y < 3; ++$y) { + $matrix->set($x, $y, 1); + } + } + + return $this->module->createPath($matrix)->translate(-1.5, -1.5); + } +} diff --git a/vendor/bacon/bacon-qr-code/src/Renderer/Eye/PointyEye.php b/vendor/bacon/bacon-qr-code/src/Renderer/Eye/PointyEye.php new file mode 100644 index 0000000..39c7d23 --- /dev/null +++ b/vendor/bacon/bacon-qr-code/src/Renderer/Eye/PointyEye.php @@ -0,0 +1,56 @@ +move(-3.5, 3.5) + ->line(-3.5, 0) + ->ellipticArc(3.5, 3.5, 0, false, true, 0, -3.5) + ->line(3.5, -3.5) + ->line(3.5, 3.5) + ->close() + ->move(2.5, 0) + ->ellipticArc(2.5, 2.5, 0, false, true, 0, 2.5) + ->ellipticArc(2.5, 2.5, 0, false, true, -2.5, 0) + ->ellipticArc(2.5, 2.5, 0, false, true, 0, -2.5) + ->ellipticArc(2.5, 2.5, 0, false, true, 2.5, 0) + ->close() + ; + } + + public function getInternalPath() : Path + { + return (new Path()) + ->move(1.5, 0) + ->ellipticArc(1.5, 1.5, 0., false, true, 0., 1.5) + ->ellipticArc(1.5, 1.5, 0., false, true, -1.5, 0.) + ->ellipticArc(1.5, 1.5, 0., false, true, 0., -1.5) + ->ellipticArc(1.5, 1.5, 0., false, true, 1.5, 0.) + ->close() + ; + } +} diff --git a/vendor/bacon/bacon-qr-code/src/Renderer/Eye/SimpleCircleEye.php b/vendor/bacon/bacon-qr-code/src/Renderer/Eye/SimpleCircleEye.php new file mode 100644 index 0000000..735d326 --- /dev/null +++ b/vendor/bacon/bacon-qr-code/src/Renderer/Eye/SimpleCircleEye.php @@ -0,0 +1,51 @@ +move(-3.5, -3.5) + ->line(3.5, -3.5) + ->line(3.5, 3.5) + ->line(-3.5, 3.5) + ->close() + ->move(-2.5, -2.5) + ->line(-2.5, 2.5) + ->line(2.5, 2.5) + ->line(2.5, -2.5) + ->close() + ; + } + + public function getInternalPath() : Path + { + return (new Path()) + ->move(1.5, 0) + ->ellipticArc(1.5, 1.5, 0., false, true, 0., 1.5) + ->ellipticArc(1.5, 1.5, 0., false, true, -1.5, 0.) + ->ellipticArc(1.5, 1.5, 0., false, true, 0., -1.5) + ->ellipticArc(1.5, 1.5, 0., false, true, 1.5, 0.) + ->close() + ; + } +} diff --git a/vendor/bacon/bacon-qr-code/src/Renderer/Eye/SquareEye.php b/vendor/bacon/bacon-qr-code/src/Renderer/Eye/SquareEye.php new file mode 100644 index 0000000..09bedfe --- /dev/null +++ b/vendor/bacon/bacon-qr-code/src/Renderer/Eye/SquareEye.php @@ -0,0 +1,50 @@ +move(-3.5, -3.5) + ->line(3.5, -3.5) + ->line(3.5, 3.5) + ->line(-3.5, 3.5) + ->close() + ->move(-2.5, -2.5) + ->line(-2.5, 2.5) + ->line(2.5, 2.5) + ->line(2.5, -2.5) + ->close() + ; + } + + public function getInternalPath() : Path + { + return (new Path()) + ->move(-1.5, -1.5) + ->line(1.5, -1.5) + ->line(1.5, 1.5) + ->line(-1.5, 1.5) + ->close() + ; + } +} diff --git a/vendor/bacon/bacon-qr-code/src/Renderer/GDLibRenderer.php b/vendor/bacon/bacon-qr-code/src/Renderer/GDLibRenderer.php new file mode 100644 index 0000000..7e6efc0 --- /dev/null +++ b/vendor/bacon/bacon-qr-code/src/Renderer/GDLibRenderer.php @@ -0,0 +1,237 @@ + + */ + private array $colors; + + public function __construct( + private int $size, + private int $margin = 4, + private string $imageFormat = 'png', + private int $compressionQuality = 9, + private ?Fill $fill = null + ) { + if (! extension_loaded('gd') || ! function_exists('gd_info')) { + throw new RuntimeException('You need to install the GD extension to use this back end'); + } + + if ($this->fill === null) { + $this->fill = Fill::default(); + } + if ($this->fill->hasGradientFill()) { + throw new InvalidArgumentException('GDLibRenderer does not support gradients'); + } + } + + /** + * @throws InvalidArgumentException if matrix width doesn't match height + */ + public function render(QrCode $qrCode): string + { + $matrix = $qrCode->getMatrix(); + $matrixSize = $matrix->getWidth(); + + if ($matrixSize !== $matrix->getHeight()) { + throw new InvalidArgumentException('Matrix must have the same width and height'); + } + + MatrixUtil::removePositionDetectionPatterns($matrix); + $this->newImage(); + $this->draw($matrix); + + return $this->renderImage(); + } + + private function newImage(): void + { + $img = imagecreatetruecolor($this->size, $this->size); + if ($img === false) { + throw new RuntimeException('Failed to create image of that size'); + } + + $this->image = $img; + imagealphablending($this->image, false); + imagesavealpha($this->image, true); + + + $bg = $this->getColor($this->fill->getBackgroundColor()); + imagefilledrectangle($this->image, 0, 0, $this->size, $this->size, $bg); + imagealphablending($this->image, true); + } + + private function draw(ByteMatrix $matrix): void + { + $matrixSize = $matrix->getWidth(); + + $pointsOnSide = $matrix->getWidth() + $this->margin * 2; + $pointInPx = $this->size / $pointsOnSide; + + $this->drawEye(0, 0, $pointInPx, $this->fill->getTopLeftEyeFill()); + $this->drawEye($matrixSize - 7, 0, $pointInPx, $this->fill->getTopRightEyeFill()); + $this->drawEye(0, $matrixSize - 7, $pointInPx, $this->fill->getBottomLeftEyeFill()); + + $rows = $matrix->getArray()->toArray(); + $color = $this->getColor($this->fill->getForegroundColor()); + for ($y = 0; $y < $matrixSize; $y += 1) { + for ($x = 0; $x < $matrixSize; $x += 1) { + if (! $rows[$y][$x]) { + continue; + } + + $points = $this->normalizePoints([ + ($this->margin + $x) * $pointInPx, ($this->margin + $y) * $pointInPx, + ($this->margin + $x + 1) * $pointInPx, ($this->margin + $y) * $pointInPx, + ($this->margin + $x + 1) * $pointInPx, ($this->margin + $y + 1) * $pointInPx, + ($this->margin + $x) * $pointInPx, ($this->margin + $y + 1) * $pointInPx, + ]); + imagefilledpolygon($this->image, $points, $color); + } + } + } + + private function drawEye(int $xOffset, int $yOffset, float $pointInPx, EyeFill $eyeFill): void + { + $internalColor = $this->getColor($eyeFill->inheritsInternalColor() + ? $this->fill->getForegroundColor() + : $eyeFill->getInternalColor()); + + $externalColor = $this->getColor($eyeFill->inheritsExternalColor() + ? $this->fill->getForegroundColor() + : $eyeFill->getExternalColor()); + + for ($y = 0; $y < 7; $y += 1) { + for ($x = 0; $x < 7; $x += 1) { + if ((($y === 1 || $y === 5) && $x > 0 && $x < 6) || (($x === 1 || $x === 5) && $y > 0 && $y < 6)) { + continue; + } + + $points = $this->normalizePoints([ + ($this->margin + $x + $xOffset) * $pointInPx, ($this->margin + $y + $yOffset) * $pointInPx, + ($this->margin + $x + $xOffset + 1) * $pointInPx, ($this->margin + $y + $yOffset) * $pointInPx, + ($this->margin + $x + $xOffset + 1) * $pointInPx, ($this->margin + $y + $yOffset + 1) * $pointInPx, + ($this->margin + $x + $xOffset) * $pointInPx, ($this->margin + $y + $yOffset + 1) * $pointInPx, + ]); + + if ($y > 1 && $y < 5 && $x > 1 && $x < 5) { + imagefilledpolygon($this->image, $points, $internalColor); + } else { + imagefilledpolygon($this->image, $points, $externalColor); + } + } + } + } + + /** + * Normalize points will trim right and bottom line by 1 pixel. + * Otherwise pixels of neighbors are overlapping which leads to issue with transparency and small QR codes. + */ + private function normalizePoints(array $points): array + { + $maxX = $maxY = 0; + for ($i = 0; $i < count($points); $i += 2) { + // Do manual round as GD just removes decimal part + $points[$i] = $newX = round($points[$i]); + $points[$i + 1] = $newY = round($points[$i + 1]); + + $maxX = max($maxX, $newX); + $maxY = max($maxY, $newY); + } + + // Do trimming only if there are 4 points (8 coordinates), assumes this is square. + + for ($i = 0; $i < count($points); $i += 2) { + $points[$i] = min($points[$i], $maxX - 1); + $points[$i + 1] = min($points[$i + 1], $maxY - 1); + } + + return $points; + } + + private function renderImage(): string + { + ob_start(); + $quality = $this->compressionQuality; + switch ($this->imageFormat) { + case 'png': + if ($quality > 9 || $quality < 0) { + $quality = 9; + } + imagepng($this->image, null, $quality); + break; + + case 'gif': + imagegif($this->image, null); + break; + + case 'jpeg': + case 'jpg': + if ($quality > 100 || $quality < 0) { + $quality = 85; + } + imagejpeg($this->image, null, $quality); + break; + default: + ob_end_clean(); + throw new InvalidArgumentException( + 'Supported image formats are jpeg, png and gif, got: ' . $this->imageFormat + ); + } + + $this->colors = []; + $this->image = null; + + return ob_get_clean(); + } + + private function getColor(ColorInterface $color): int + { + $alpha = 100; + + if ($color instanceof Alpha) { + $alpha = $color->getAlpha(); + $color = $color->getBaseColor(); + } + + $rgb = $color->toRgb(); + + $colorKey = sprintf('%02X%02X%02X%02X', $rgb->getRed(), $rgb->getGreen(), $rgb->getBlue(), $alpha); + + if (! isset($this->colors[$colorKey])) { + $colorId = imagecolorallocatealpha( + $this->image, + $rgb->getRed(), + $rgb->getGreen(), + $rgb->getBlue(), + (int)((100 - $alpha) / 100 * 127) // Alpha for GD is in range 0 (opaque) - 127 (transparent) + ); + + if ($colorId === false) { + throw new RuntimeException('Failed to create color: #' . $colorKey); + } + + $this->colors[$colorKey] = $colorId; + } + + return $this->colors[$colorKey]; + } +} diff --git a/vendor/bacon/bacon-qr-code/src/Renderer/Image/EpsImageBackEnd.php b/vendor/bacon/bacon-qr-code/src/Renderer/Image/EpsImageBackEnd.php new file mode 100644 index 0000000..4269456 --- /dev/null +++ b/vendor/bacon/bacon-qr-code/src/Renderer/Image/EpsImageBackEnd.php @@ -0,0 +1,373 @@ +eps = "%!PS-Adobe-3.0 EPSF-3.0\n" + . "%%Creator: BaconQrCode\n" + . sprintf("%%%%BoundingBox: 0 0 %d %d \n", $size, $size) + . "%%BeginProlog\n" + . "save\n" + . "50 dict begin\n" + . "/q { gsave } bind def\n" + . "/Q { grestore } bind def\n" + . "/s { scale } bind def\n" + . "/t { translate } bind def\n" + . "/r { rotate } bind def\n" + . "/n { newpath } bind def\n" + . "/m { moveto } bind def\n" + . "/l { lineto } bind def\n" + . "/c { curveto } bind def\n" + . "/z { closepath } bind def\n" + . "/f { eofill } bind def\n" + . "/rgb { setrgbcolor } bind def\n" + . "/cmyk { setcmykcolor } bind def\n" + . "/gray { setgray } bind def\n" + . "%%EndProlog\n" + . "1 -1 s\n" + . sprintf("0 -%d t\n", $size); + + if ($backgroundColor instanceof Alpha && 0 === $backgroundColor->getAlpha()) { + return; + } + + $this->eps .= wordwrap( + '0 0 m' + . sprintf(' %s 0 l', (string) $size) + . sprintf(' %s %s l', (string) $size, (string) $size) + . sprintf(' 0 %s l', (string) $size) + . ' z' + . ' ' .$this->getColorSetString($backgroundColor) . " f\n", + 75, + "\n " + ); + } + + public function scale(float $size) : void + { + if (null === $this->eps) { + throw new RuntimeException('No image has been started'); + } + + $this->eps .= sprintf("%1\$s %1\$s s\n", round($size, self::PRECISION)); + } + + public function translate(float $x, float $y) : void + { + if (null === $this->eps) { + throw new RuntimeException('No image has been started'); + } + + $this->eps .= sprintf("%s %s t\n", round($x, self::PRECISION), round($y, self::PRECISION)); + } + + public function rotate(int $degrees) : void + { + if (null === $this->eps) { + throw new RuntimeException('No image has been started'); + } + + $this->eps .= sprintf("%d r\n", $degrees); + } + + public function push() : void + { + if (null === $this->eps) { + throw new RuntimeException('No image has been started'); + } + + $this->eps .= "q\n"; + } + + public function pop() : void + { + if (null === $this->eps) { + throw new RuntimeException('No image has been started'); + } + + $this->eps .= "Q\n"; + } + + public function drawPathWithColor(Path $path, ColorInterface $color) : void + { + if (null === $this->eps) { + throw new RuntimeException('No image has been started'); + } + + $fromX = 0; + $fromY = 0; + $this->eps .= wordwrap( + 'n ' + . $this->drawPathOperations($path, $fromX, $fromY) + . ' ' . $this->getColorSetString($color) . " f\n", + 75, + "\n " + ); + } + + public function drawPathWithGradient( + Path $path, + Gradient $gradient, + float $x, + float $y, + float $width, + float $height + ) : void { + if (null === $this->eps) { + throw new RuntimeException('No image has been started'); + } + + $fromX = 0; + $fromY = 0; + $this->eps .= wordwrap( + 'q n ' . $this->drawPathOperations($path, $fromX, $fromY) . "\n", + 75, + "\n " + ); + + $this->createGradientFill($gradient, $x, $y, $width, $height); + } + + public function done() : string + { + if (null === $this->eps) { + throw new RuntimeException('No image has been started'); + } + + $this->eps .= "%%TRAILER\nend restore\n%%EOF"; + $blob = $this->eps; + $this->eps = null; + + return $blob; + } + + private function drawPathOperations(Iterable $ops, &$fromX, &$fromY) : string + { + $pathData = []; + + foreach ($ops as $op) { + switch (true) { + case $op instanceof Move: + $fromX = $toX = round($op->getX(), self::PRECISION); + $fromY = $toY = round($op->getY(), self::PRECISION); + $pathData[] = sprintf('%s %s m', $toX, $toY); + break; + + case $op instanceof Line: + $fromX = $toX = round($op->getX(), self::PRECISION); + $fromY = $toY = round($op->getY(), self::PRECISION); + $pathData[] = sprintf('%s %s l', $toX, $toY); + break; + + case $op instanceof EllipticArc: + $pathData[] = $this->drawPathOperations($op->toCurves($fromX, $fromY), $fromX, $fromY); + break; + + case $op instanceof Curve: + $x1 = round($op->getX1(), self::PRECISION); + $y1 = round($op->getY1(), self::PRECISION); + $x2 = round($op->getX2(), self::PRECISION); + $y2 = round($op->getY2(), self::PRECISION); + $fromX = $x3 = round($op->getX3(), self::PRECISION); + $fromY = $y3 = round($op->getY3(), self::PRECISION); + $pathData[] = sprintf('%s %s %s %s %s %s c', $x1, $y1, $x2, $y2, $x3, $y3); + break; + + case $op instanceof Close: + $pathData[] = 'z'; + break; + + default: + throw new RuntimeException('Unexpected draw operation: ' . get_class($op)); + } + } + + return implode(' ', $pathData); + } + + private function createGradientFill(Gradient $gradient, float $x, float $y, float $width, float $height) : void + { + $startColor = $gradient->getStartColor(); + $endColor = $gradient->getEndColor(); + + if ($startColor instanceof Alpha) { + $startColor = $startColor->getBaseColor(); + } + + $startColorType = get_class($startColor); + + if (! in_array($startColorType, [Rgb::class, Cmyk::class, Gray::class])) { + $startColorType = Cmyk::class; + $startColor = $startColor->toCmyk(); + } + + if (get_class($endColor) !== $startColorType) { + switch ($startColorType) { + case Cmyk::class: + $endColor = $endColor->toCmyk(); + break; + + case Rgb::class: + $endColor = $endColor->toRgb(); + break; + + case Gray::class: + $endColor = $endColor->toGray(); + break; + } + } + + $this->eps .= "eoclip\n<<\n"; + + if ($gradient->getType() === GradientType::RADIAL()) { + $this->eps .= " /ShadingType 3\n"; + } else { + $this->eps .= " /ShadingType 2\n"; + } + + $this->eps .= " /Extend [ true true ]\n" + . " /AntiAlias true\n"; + + switch ($startColorType) { + case Cmyk::class: + $this->eps .= " /ColorSpace /DeviceCMYK\n"; + break; + + case Rgb::class: + $this->eps .= " /ColorSpace /DeviceRGB\n"; + break; + + case Gray::class: + $this->eps .= " /ColorSpace /DeviceGray\n"; + break; + } + + switch ($gradient->getType()) { + case GradientType::HORIZONTAL(): + $this->eps .= sprintf( + " /Coords [ %s %s %s %s ]\n", + round($x, self::PRECISION), + round($y, self::PRECISION), + round($x + $width, self::PRECISION), + round($y, self::PRECISION) + ); + break; + + case GradientType::VERTICAL(): + $this->eps .= sprintf( + " /Coords [ %s %s %s %s ]\n", + round($x, self::PRECISION), + round($y, self::PRECISION), + round($x, self::PRECISION), + round($y + $height, self::PRECISION) + ); + break; + + case GradientType::DIAGONAL(): + $this->eps .= sprintf( + " /Coords [ %s %s %s %s ]\n", + round($x, self::PRECISION), + round($y, self::PRECISION), + round($x + $width, self::PRECISION), + round($y + $height, self::PRECISION) + ); + break; + + case GradientType::INVERSE_DIAGONAL(): + $this->eps .= sprintf( + " /Coords [ %s %s %s %s ]\n", + round($x, self::PRECISION), + round($y + $height, self::PRECISION), + round($x + $width, self::PRECISION), + round($y, self::PRECISION) + ); + break; + + case GradientType::RADIAL(): + $centerX = ($x + $width) / 2; + $centerY = ($y + $height) / 2; + + $this->eps .= sprintf( + " /Coords [ %s %s 0 %s %s %s ]\n", + round($centerX, self::PRECISION), + round($centerY, self::PRECISION), + round($centerX, self::PRECISION), + round($centerY, self::PRECISION), + round(max($width, $height) / 2, self::PRECISION) + ); + break; + } + + $this->eps .= " /Function\n" + . " <<\n" + . " /FunctionType 2\n" + . " /Domain [ 0 1 ]\n" + . sprintf(" /C0 [ %s ]\n", $this->getColorString($startColor)) + . sprintf(" /C1 [ %s ]\n", $this->getColorString($endColor)) + . " /N 1\n" + . " >>\n>>\nshfill\nQ\n"; + } + + private function getColorSetString(ColorInterface $color) : string + { + if ($color instanceof Rgb) { + return $this->getColorString($color) . ' rgb'; + } + + if ($color instanceof Cmyk) { + return $this->getColorString($color) . ' cmyk'; + } + + if ($color instanceof Gray) { + return $this->getColorString($color) . ' gray'; + } + + return $this->getColorSetString($color->toCmyk()); + } + + private function getColorString(ColorInterface $color) : string + { + if ($color instanceof Rgb) { + return sprintf('%s %s %s', $color->getRed() / 255, $color->getGreen() / 255, $color->getBlue() / 255); + } + + if ($color instanceof Cmyk) { + return sprintf( + '%s %s %s %s', + $color->getCyan() / 100, + $color->getMagenta() / 100, + $color->getYellow() / 100, + $color->getBlack() / 100 + ); + } + + if ($color instanceof Gray) { + return sprintf('%s', $color->getGray() / 100); + } + + return $this->getColorString($color->toCmyk()); + } +} diff --git a/vendor/bacon/bacon-qr-code/src/Renderer/Image/ImageBackEndInterface.php b/vendor/bacon/bacon-qr-code/src/Renderer/Image/ImageBackEndInterface.php new file mode 100644 index 0000000..0935819 --- /dev/null +++ b/vendor/bacon/bacon-qr-code/src/Renderer/Image/ImageBackEndInterface.php @@ -0,0 +1,87 @@ +imageFormat = $imageFormat; + $this->compressionQuality = $compressionQuality; + } + + public function new(int $size, ColorInterface $backgroundColor) : void + { + $this->image = new Imagick(); + $this->image->newImage($size, $size, $this->getColorPixel($backgroundColor)); + $this->image->setImageFormat($this->imageFormat); + $this->image->setCompressionQuality($this->compressionQuality); + $this->draw = new ImagickDraw(); + $this->gradientCount = 0; + $this->matrices = [new TransformationMatrix()]; + $this->matrixIndex = 0; + } + + public function scale(float $size) : void + { + if (null === $this->draw) { + throw new RuntimeException('No image has been started'); + } + + $this->draw->scale($size, $size); + $this->matrices[$this->matrixIndex] = $this->matrices[$this->matrixIndex] + ->multiply(TransformationMatrix::scale($size)); + } + + public function translate(float $x, float $y) : void + { + if (null === $this->draw) { + throw new RuntimeException('No image has been started'); + } + + $this->draw->translate($x, $y); + $this->matrices[$this->matrixIndex] = $this->matrices[$this->matrixIndex] + ->multiply(TransformationMatrix::translate($x, $y)); + } + + public function rotate(int $degrees) : void + { + if (null === $this->draw) { + throw new RuntimeException('No image has been started'); + } + + $this->draw->rotate($degrees); + $this->matrices[$this->matrixIndex] = $this->matrices[$this->matrixIndex] + ->multiply(TransformationMatrix::rotate($degrees)); + } + + public function push() : void + { + if (null === $this->draw) { + throw new RuntimeException('No image has been started'); + } + + $this->draw->push(); + $this->matrices[++$this->matrixIndex] = $this->matrices[$this->matrixIndex - 1]; + } + + public function pop() : void + { + if (null === $this->draw) { + throw new RuntimeException('No image has been started'); + } + + $this->draw->pop(); + unset($this->matrices[$this->matrixIndex--]); + } + + public function drawPathWithColor(Path $path, ColorInterface $color) : void + { + if (null === $this->draw) { + throw new RuntimeException('No image has been started'); + } + + $this->draw->setFillColor($this->getColorPixel($color)); + $this->drawPath($path); + } + + public function drawPathWithGradient( + Path $path, + Gradient $gradient, + float $x, + float $y, + float $width, + float $height + ) : void { + if (null === $this->draw) { + throw new RuntimeException('No image has been started'); + } + + $this->draw->setFillPatternURL('#' . $this->createGradientFill($gradient, $x, $y, $width, $height)); + $this->drawPath($path); + } + + public function done() : string + { + if (null === $this->draw) { + throw new RuntimeException('No image has been started'); + } + + $this->image->drawImage($this->draw); + $blob = $this->image->getImageBlob(); + $this->draw->clear(); + $this->image->clear(); + $this->draw = null; + $this->image = null; + $this->gradientCount = null; + + return $blob; + } + + private function drawPath(Path $path) : void + { + $this->draw->pathStart(); + + foreach ($path as $op) { + switch (true) { + case $op instanceof Move: + $this->draw->pathMoveToAbsolute($op->getX(), $op->getY()); + break; + + case $op instanceof Line: + $this->draw->pathLineToAbsolute($op->getX(), $op->getY()); + break; + + case $op instanceof EllipticArc: + $this->draw->pathEllipticArcAbsolute( + $op->getXRadius(), + $op->getYRadius(), + $op->getXAxisAngle(), + $op->isLargeArc(), + $op->isSweep(), + $op->getX(), + $op->getY() + ); + break; + + case $op instanceof Curve: + $this->draw->pathCurveToAbsolute( + $op->getX1(), + $op->getY1(), + $op->getX2(), + $op->getY2(), + $op->getX3(), + $op->getY3() + ); + break; + + case $op instanceof Close: + $this->draw->pathClose(); + break; + + default: + throw new RuntimeException('Unexpected draw operation: ' . get_class($op)); + } + } + + $this->draw->pathFinish(); + } + + private function createGradientFill(Gradient $gradient, float $x, float $y, float $width, float $height) : string + { + list($width, $height) = $this->matrices[$this->matrixIndex]->apply($width, $height); + + $startColor = $this->getColorPixel($gradient->getStartColor())->getColorAsString(); + $endColor = $this->getColorPixel($gradient->getEndColor())->getColorAsString(); + $gradientImage = new Imagick(); + + switch ($gradient->getType()) { + case GradientType::HORIZONTAL(): + $gradientImage->newPseudoImage((int) $height, (int) $width, sprintf( + 'gradient:%s-%s', + $startColor, + $endColor + )); + $gradientImage->rotateImage('transparent', -90); + break; + + case GradientType::VERTICAL(): + $gradientImage->newPseudoImage((int) $width, (int) $height, sprintf( + 'gradient:%s-%s', + $startColor, + $endColor + )); + break; + + case GradientType::DIAGONAL(): + case GradientType::INVERSE_DIAGONAL(): + $gradientImage->newPseudoImage((int) ($width * sqrt(2)), (int) ($height * sqrt(2)), sprintf( + 'gradient:%s-%s', + $startColor, + $endColor + )); + + if (GradientType::DIAGONAL() === $gradient->getType()) { + $gradientImage->rotateImage('transparent', -45); + } else { + $gradientImage->rotateImage('transparent', -135); + } + + $rotatedWidth = $gradientImage->getImageWidth(); + $rotatedHeight = $gradientImage->getImageHeight(); + + $gradientImage->setImagePage($rotatedWidth, $rotatedHeight, 0, 0); + $gradientImage->cropImage( + intdiv($rotatedWidth, 2) - 2, + intdiv($rotatedHeight, 2) - 2, + intdiv($rotatedWidth, 4) + 1, + intdiv($rotatedWidth, 4) + 1 + ); + break; + + case GradientType::RADIAL(): + $gradientImage->newPseudoImage((int) $width, (int) $height, sprintf( + 'radial-gradient:%s-%s', + $startColor, + $endColor + )); + break; + } + + $id = sprintf('g%d', ++$this->gradientCount); + $this->draw->pushPattern($id, 0, 0, $width, $height); + $this->draw->composite(Imagick::COMPOSITE_COPY, 0, 0, $width, $height, $gradientImage); + $this->draw->popPattern(); + return $id; + } + + private function getColorPixel(ColorInterface $color) : ImagickPixel + { + $alpha = 100; + + if ($color instanceof Alpha) { + $alpha = $color->getAlpha(); + $color = $color->getBaseColor(); + } + + if ($color instanceof Rgb) { + return new ImagickPixel(sprintf( + 'rgba(%d, %d, %d, %F)', + $color->getRed(), + $color->getGreen(), + $color->getBlue(), + $alpha / 100 + )); + } + + if ($color instanceof Cmyk) { + return new ImagickPixel(sprintf( + 'cmyka(%d, %d, %d, %d, %F)', + $color->getCyan(), + $color->getMagenta(), + $color->getYellow(), + $color->getBlack(), + $alpha / 100 + )); + } + + if ($color instanceof Gray) { + return new ImagickPixel(sprintf( + 'graya(%d%%, %F)', + $color->getGray(), + $alpha / 100 + )); + } + + return $this->getColorPixel(new Alpha($alpha, $color->toRgb())); + } +} diff --git a/vendor/bacon/bacon-qr-code/src/Renderer/Image/SvgImageBackEnd.php b/vendor/bacon/bacon-qr-code/src/Renderer/Image/SvgImageBackEnd.php new file mode 100644 index 0000000..44d014e --- /dev/null +++ b/vendor/bacon/bacon-qr-code/src/Renderer/Image/SvgImageBackEnd.php @@ -0,0 +1,363 @@ +xmlWriter = new XMLWriter(); + $this->xmlWriter->openMemory(); + + $this->xmlWriter->startDocument('1.0', 'UTF-8'); + $this->xmlWriter->startElement('svg'); + $this->xmlWriter->writeAttribute('xmlns', 'http://www.w3.org/2000/svg'); + $this->xmlWriter->writeAttribute('version', '1.1'); + $this->xmlWriter->writeAttribute('width', (string) $size); + $this->xmlWriter->writeAttribute('height', (string) $size); + $this->xmlWriter->writeAttribute('viewBox', '0 0 '. $size . ' ' . $size); + + $this->gradientCount = 0; + $this->currentStack = 0; + $this->stack[0] = 0; + + $alpha = 1; + + if ($backgroundColor instanceof Alpha) { + $alpha = $backgroundColor->getAlpha() / 100; + } + + if (0 === $alpha) { + return; + } + + $this->xmlWriter->startElement('rect'); + $this->xmlWriter->writeAttribute('x', '0'); + $this->xmlWriter->writeAttribute('y', '0'); + $this->xmlWriter->writeAttribute('width', (string) $size); + $this->xmlWriter->writeAttribute('height', (string) $size); + $this->xmlWriter->writeAttribute('fill', $this->getColorString($backgroundColor)); + + if ($alpha < 1) { + $this->xmlWriter->writeAttribute('fill-opacity', (string) $alpha); + } + + $this->xmlWriter->endElement(); + } + + public function scale(float $size) : void + { + if (null === $this->xmlWriter) { + throw new RuntimeException('No image has been started'); + } + + $this->xmlWriter->startElement('g'); + $this->xmlWriter->writeAttribute( + 'transform', + sprintf(self::SCALE_FORMAT, round($size, self::PRECISION)) + ); + ++$this->stack[$this->currentStack]; + } + + public function translate(float $x, float $y) : void + { + if (null === $this->xmlWriter) { + throw new RuntimeException('No image has been started'); + } + + $this->xmlWriter->startElement('g'); + $this->xmlWriter->writeAttribute( + 'transform', + sprintf(self::TRANSLATE_FORMAT, round($x, self::PRECISION), round($y, self::PRECISION)) + ); + ++$this->stack[$this->currentStack]; + } + + public function rotate(int $degrees) : void + { + if (null === $this->xmlWriter) { + throw new RuntimeException('No image has been started'); + } + + $this->xmlWriter->startElement('g'); + $this->xmlWriter->writeAttribute('transform', sprintf('rotate(%d)', $degrees)); + ++$this->stack[$this->currentStack]; + } + + public function push() : void + { + if (null === $this->xmlWriter) { + throw new RuntimeException('No image has been started'); + } + + $this->xmlWriter->startElement('g'); + $this->stack[] = 1; + ++$this->currentStack; + } + + public function pop() : void + { + if (null === $this->xmlWriter) { + throw new RuntimeException('No image has been started'); + } + + for ($i = 0; $i < $this->stack[$this->currentStack]; ++$i) { + $this->xmlWriter->endElement(); + } + + array_pop($this->stack); + --$this->currentStack; + } + + public function drawPathWithColor(Path $path, ColorInterface $color) : void + { + if (null === $this->xmlWriter) { + throw new RuntimeException('No image has been started'); + } + + $alpha = 1; + + if ($color instanceof Alpha) { + $alpha = $color->getAlpha() / 100; + } + + $this->startPathElement($path); + $this->xmlWriter->writeAttribute('fill', $this->getColorString($color)); + + if ($alpha < 1) { + $this->xmlWriter->writeAttribute('fill-opacity', (string) $alpha); + } + + $this->xmlWriter->endElement(); + } + + public function drawPathWithGradient( + Path $path, + Gradient $gradient, + float $x, + float $y, + float $width, + float $height + ) : void { + if (null === $this->xmlWriter) { + throw new RuntimeException('No image has been started'); + } + + $gradientId = $this->createGradientFill($gradient, $x, $y, $width, $height); + $this->startPathElement($path); + $this->xmlWriter->writeAttribute('fill', 'url(#' . $gradientId . ')'); + $this->xmlWriter->endElement(); + } + + public function done() : string + { + if (null === $this->xmlWriter) { + throw new RuntimeException('No image has been started'); + } + + foreach ($this->stack as $openElements) { + for ($i = $openElements; $i > 0; --$i) { + $this->xmlWriter->endElement(); + } + } + + $this->xmlWriter->endDocument(); + $blob = $this->xmlWriter->outputMemory(true); + $this->xmlWriter = null; + $this->stack = null; + $this->currentStack = null; + $this->gradientCount = null; + + return $blob; + } + + private function startPathElement(Path $path) : void + { + $pathData = []; + + foreach ($path as $op) { + switch (true) { + case $op instanceof Move: + $pathData[] = sprintf( + 'M%s %s', + round($op->getX(), self::PRECISION), + round($op->getY(), self::PRECISION) + ); + break; + + case $op instanceof Line: + $pathData[] = sprintf( + 'L%s %s', + round($op->getX(), self::PRECISION), + round($op->getY(), self::PRECISION) + ); + break; + + case $op instanceof EllipticArc: + $pathData[] = sprintf( + 'A%s %s %s %u %u %s %s', + round($op->getXRadius(), self::PRECISION), + round($op->getYRadius(), self::PRECISION), + round($op->getXAxisAngle(), self::PRECISION), + $op->isLargeArc(), + $op->isSweep(), + round($op->getX(), self::PRECISION), + round($op->getY(), self::PRECISION) + ); + break; + + case $op instanceof Curve: + $pathData[] = sprintf( + 'C%s %s %s %s %s %s', + round($op->getX1(), self::PRECISION), + round($op->getY1(), self::PRECISION), + round($op->getX2(), self::PRECISION), + round($op->getY2(), self::PRECISION), + round($op->getX3(), self::PRECISION), + round($op->getY3(), self::PRECISION) + ); + break; + + case $op instanceof Close: + $pathData[] = 'Z'; + break; + + default: + throw new RuntimeException('Unexpected draw operation: ' . get_class($op)); + } + } + + $this->xmlWriter->startElement('path'); + $this->xmlWriter->writeAttribute('fill-rule', 'evenodd'); + $this->xmlWriter->writeAttribute('d', implode('', $pathData)); + } + + private function createGradientFill(Gradient $gradient, float $x, float $y, float $width, float $height) : string + { + $this->xmlWriter->startElement('defs'); + + $startColor = $gradient->getStartColor(); + $endColor = $gradient->getEndColor(); + + if ($gradient->getType() === GradientType::RADIAL()) { + $this->xmlWriter->startElement('radialGradient'); + } else { + $this->xmlWriter->startElement('linearGradient'); + } + + $this->xmlWriter->writeAttribute('gradientUnits', 'userSpaceOnUse'); + + switch ($gradient->getType()) { + case GradientType::HORIZONTAL(): + $this->xmlWriter->writeAttribute('x1', (string) round($x, self::PRECISION)); + $this->xmlWriter->writeAttribute('y1', (string) round($y, self::PRECISION)); + $this->xmlWriter->writeAttribute('x2', (string) round($x + $width, self::PRECISION)); + $this->xmlWriter->writeAttribute('y2', (string) round($y, self::PRECISION)); + break; + + case GradientType::VERTICAL(): + $this->xmlWriter->writeAttribute('x1', (string) round($x, self::PRECISION)); + $this->xmlWriter->writeAttribute('y1', (string) round($y, self::PRECISION)); + $this->xmlWriter->writeAttribute('x2', (string) round($x, self::PRECISION)); + $this->xmlWriter->writeAttribute('y2', (string) round($y + $height, self::PRECISION)); + break; + + case GradientType::DIAGONAL(): + $this->xmlWriter->writeAttribute('x1', (string) round($x, self::PRECISION)); + $this->xmlWriter->writeAttribute('y1', (string) round($y, self::PRECISION)); + $this->xmlWriter->writeAttribute('x2', (string) round($x + $width, self::PRECISION)); + $this->xmlWriter->writeAttribute('y2', (string) round($y + $height, self::PRECISION)); + break; + + case GradientType::INVERSE_DIAGONAL(): + $this->xmlWriter->writeAttribute('x1', (string) round($x, self::PRECISION)); + $this->xmlWriter->writeAttribute('y1', (string) round($y + $height, self::PRECISION)); + $this->xmlWriter->writeAttribute('x2', (string) round($x + $width, self::PRECISION)); + $this->xmlWriter->writeAttribute('y2', (string) round($y, self::PRECISION)); + break; + + case GradientType::RADIAL(): + $this->xmlWriter->writeAttribute('cx', (string) round(($x + $width) / 2, self::PRECISION)); + $this->xmlWriter->writeAttribute('cy', (string) round(($y + $height) / 2, self::PRECISION)); + $this->xmlWriter->writeAttribute('r', (string) round(max($width, $height) / 2, self::PRECISION)); + break; + } + + $toBeHashed = $this->getColorString($startColor) . $this->getColorString($endColor) . $gradient->getType(); + if ($startColor instanceof Alpha) { + $toBeHashed .= (string) $startColor->getAlpha(); + } + $id = sprintf('g%d-%s', ++$this->gradientCount, hash('xxh64', $toBeHashed)); + $this->xmlWriter->writeAttribute('id', $id); + + $this->xmlWriter->startElement('stop'); + $this->xmlWriter->writeAttribute('offset', '0%'); + $this->xmlWriter->writeAttribute('stop-color', $this->getColorString($startColor)); + + if ($startColor instanceof Alpha) { + $this->xmlWriter->writeAttribute('stop-opacity', (string) $startColor->getAlpha()); + } + + $this->xmlWriter->endElement(); + + $this->xmlWriter->startElement('stop'); + $this->xmlWriter->writeAttribute('offset', '100%'); + $this->xmlWriter->writeAttribute('stop-color', $this->getColorString($endColor)); + + if ($endColor instanceof Alpha) { + $this->xmlWriter->writeAttribute('stop-opacity', (string) $endColor->getAlpha()); + } + + $this->xmlWriter->endElement(); + + $this->xmlWriter->endElement(); + $this->xmlWriter->endElement(); + + return $id; + } + + private function getColorString(ColorInterface $color) : string + { + $color = $color->toRgb(); + + return sprintf( + '#%02x%02x%02x', + $color->getRed(), + $color->getGreen(), + $color->getBlue() + ); + } +} diff --git a/vendor/bacon/bacon-qr-code/src/Renderer/Image/TransformationMatrix.php b/vendor/bacon/bacon-qr-code/src/Renderer/Image/TransformationMatrix.php new file mode 100644 index 0000000..9b435a0 --- /dev/null +++ b/vendor/bacon/bacon-qr-code/src/Renderer/Image/TransformationMatrix.php @@ -0,0 +1,68 @@ +values = [1, 0, 0, 1, 0, 0]; + } + + public function multiply(self $other) : self + { + $matrix = new self(); + $matrix->values[0] = $this->values[0] * $other->values[0] + $this->values[2] * $other->values[1]; + $matrix->values[1] = $this->values[1] * $other->values[0] + $this->values[3] * $other->values[1]; + $matrix->values[2] = $this->values[0] * $other->values[2] + $this->values[2] * $other->values[3]; + $matrix->values[3] = $this->values[1] * $other->values[2] + $this->values[3] * $other->values[3]; + $matrix->values[4] = $this->values[0] * $other->values[4] + $this->values[2] * $other->values[5] + + $this->values[4]; + $matrix->values[5] = $this->values[1] * $other->values[4] + $this->values[3] * $other->values[5] + + $this->values[5]; + + return $matrix; + } + + public static function scale(float $size) : self + { + $matrix = new self(); + $matrix->values = [$size, 0, 0, $size, 0, 0]; + return $matrix; + } + + public static function translate(float $x, float $y) : self + { + $matrix = new self(); + $matrix->values = [1, 0, 0, 1, $x, $y]; + return $matrix; + } + + public static function rotate(int $degrees) : self + { + $matrix = new self(); + $rad = deg2rad($degrees); + $matrix->values = [cos($rad), sin($rad), -sin($rad), cos($rad), 0, 0]; + return $matrix; + } + + + /** + * Applies this matrix onto a point and returns the resulting viewport point. + * + * @return float[] + */ + public function apply(float $x, float $y) : array + { + return [ + $x * $this->values[0] + $y * $this->values[2] + $this->values[4], + $x * $this->values[1] + $y * $this->values[3] + $this->values[5], + ]; + } +} diff --git a/vendor/bacon/bacon-qr-code/src/Renderer/ImageRenderer.php b/vendor/bacon/bacon-qr-code/src/Renderer/ImageRenderer.php new file mode 100644 index 0000000..0d33303 --- /dev/null +++ b/vendor/bacon/bacon-qr-code/src/Renderer/ImageRenderer.php @@ -0,0 +1,150 @@ +rendererStyle->getSize(); + $margin = $this->rendererStyle->getMargin(); + $matrix = $qrCode->getMatrix(); + $matrixSize = $matrix->getWidth(); + + if ($matrixSize !== $matrix->getHeight()) { + throw new InvalidArgumentException('Matrix must have the same width and height'); + } + + $totalSize = $matrixSize + ($margin * 2); + $moduleSize = $size / $totalSize; + $fill = $this->rendererStyle->getFill(); + + $this->imageBackEnd->new($size, $fill->getBackgroundColor()); + $this->imageBackEnd->scale((float) $moduleSize); + $this->imageBackEnd->translate((float) $margin, (float) $margin); + + $module = $this->rendererStyle->getModule(); + $moduleMatrix = clone $matrix; + MatrixUtil::removePositionDetectionPatterns($moduleMatrix); + $modulePath = $this->drawEyes($matrixSize, $module->createPath($moduleMatrix)); + + if ($fill->hasGradientFill()) { + $this->imageBackEnd->drawPathWithGradient( + $modulePath, + $fill->getForegroundGradient(), + 0, + 0, + $matrixSize, + $matrixSize + ); + } else { + $this->imageBackEnd->drawPathWithColor($modulePath, $fill->getForegroundColor()); + } + + return $this->imageBackEnd->done(); + } + + private function drawEyes(int $matrixSize, Path $modulePath) : Path + { + $fill = $this->rendererStyle->getFill(); + + $eye = $this->rendererStyle->getEye(); + $externalPath = $eye->getExternalPath(); + $internalPath = $eye->getInternalPath(); + + $modulePath = $this->drawEye( + $externalPath, + $internalPath, + $fill->getTopLeftEyeFill(), + 3.5, + 3.5, + 0, + $modulePath + ); + $modulePath = $this->drawEye( + $externalPath, + $internalPath, + $fill->getTopRightEyeFill(), + $matrixSize - 3.5, + 3.5, + 90, + $modulePath + ); + $modulePath = $this->drawEye( + $externalPath, + $internalPath, + $fill->getBottomLeftEyeFill(), + 3.5, + $matrixSize - 3.5, + -90, + $modulePath + ); + + return $modulePath; + } + + private function drawEye( + Path $externalPath, + Path $internalPath, + EyeFill $fill, + float $xTranslation, + float $yTranslation, + int $rotation, + Path $modulePath + ) : Path { + if ($fill->inheritsBothColors()) { + return $modulePath + ->append( + $externalPath->rotate($rotation)->translate($xTranslation, $yTranslation) + ) + ->append( + $internalPath->rotate($rotation)->translate($xTranslation, $yTranslation) + ); + } + + $this->imageBackEnd->push(); + $this->imageBackEnd->translate($xTranslation, $yTranslation); + + if (0 !== $rotation) { + $this->imageBackEnd->rotate($rotation); + } + + if ($fill->inheritsExternalColor()) { + $modulePath = $modulePath->append( + $externalPath->rotate($rotation)->translate($xTranslation, $yTranslation) + ); + } else { + $this->imageBackEnd->drawPathWithColor($externalPath, $fill->getExternalColor()); + } + + if ($fill->inheritsInternalColor()) { + $modulePath = $modulePath->append( + $internalPath->rotate($rotation)->translate($xTranslation, $yTranslation) + ); + } else { + $this->imageBackEnd->drawPathWithColor($internalPath, $fill->getInternalColor()); + } + + $this->imageBackEnd->pop(); + + return $modulePath; + } +} diff --git a/vendor/bacon/bacon-qr-code/src/Renderer/Module/DotsModule.php b/vendor/bacon/bacon-qr-code/src/Renderer/Module/DotsModule.php new file mode 100644 index 0000000..c5d5c6f --- /dev/null +++ b/vendor/bacon/bacon-qr-code/src/Renderer/Module/DotsModule.php @@ -0,0 +1,56 @@ + 1) { + throw new InvalidArgumentException('Size must between 0 (exclusive) and 1 (inclusive)'); + } + } + + public function createPath(ByteMatrix $matrix) : Path + { + $width = $matrix->getWidth(); + $height = $matrix->getHeight(); + $path = new Path(); + $halfSize = $this->size / 2; + $margin = (1 - $this->size) / 2; + + for ($y = 0; $y < $height; ++$y) { + for ($x = 0; $x < $width; ++$x) { + if (! $matrix->get($x, $y)) { + continue; + } + + $pathX = $x + $margin; + $pathY = $y + $margin; + + $path = $path + ->move($pathX + $this->size, $pathY + $halfSize) + ->ellipticArc($halfSize, $halfSize, 0, false, true, $pathX + $halfSize, $pathY + $this->size) + ->ellipticArc($halfSize, $halfSize, 0, false, true, $pathX, $pathY + $halfSize) + ->ellipticArc($halfSize, $halfSize, 0, false, true, $pathX + $halfSize, $pathY) + ->ellipticArc($halfSize, $halfSize, 0, false, true, $pathX + $this->size, $pathY + $halfSize) + ->close() + ; + } + } + + return $path; + } +} diff --git a/vendor/bacon/bacon-qr-code/src/Renderer/Module/EdgeIterator/Edge.php b/vendor/bacon/bacon-qr-code/src/Renderer/Module/EdgeIterator/Edge.php new file mode 100644 index 0000000..141d66c --- /dev/null +++ b/vendor/bacon/bacon-qr-code/src/Renderer/Module/EdgeIterator/Edge.php @@ -0,0 +1,82 @@ + + */ + private array $points = []; + + /** + * @var array|null + */ + private ?array $simplifiedPoints = null; + + private int $minX = PHP_INT_MAX; + + private int $minY = PHP_INT_MAX; + + private int $maxX = -1; + + private int $maxY = -1; + + public function __construct(private readonly bool $positive) + { + } + + public function addPoint(int $x, int $y) : void + { + $this->points[] = [$x, $y]; + $this->minX = min($this->minX, $x); + $this->minY = min($this->minY, $y); + $this->maxX = max($this->maxX, $x); + $this->maxY = max($this->maxY, $y); + } + + public function isPositive() : bool + { + return $this->positive; + } + + /** + * @return array + */ + public function getPoints() : array + { + return $this->points; + } + + public function getMaxX() : int + { + return $this->maxX; + } + + public function getSimplifiedPoints() : array + { + if (null !== $this->simplifiedPoints) { + return $this->simplifiedPoints; + } + + $points = []; + $length = count($this->points); + + for ($i = 0; $i < $length; ++$i) { + $previousPoint = $this->points[(0 === $i ? $length : $i) - 1]; + $nextPoint = $this->points[($length - 1 === $i ? -1 : $i) + 1]; + $currentPoint = $this->points[$i]; + + if (($previousPoint[0] === $currentPoint[0] && $currentPoint[0] === $nextPoint[0]) + || ($previousPoint[1] === $currentPoint[1] && $currentPoint[1] === $nextPoint[1]) + ) { + continue; + } + + $points[] = $currentPoint; + } + + return $this->simplifiedPoints = $points; + } +} diff --git a/vendor/bacon/bacon-qr-code/src/Renderer/Module/EdgeIterator/EdgeIterator.php b/vendor/bacon/bacon-qr-code/src/Renderer/Module/EdgeIterator/EdgeIterator.php new file mode 100644 index 0000000..01f692c --- /dev/null +++ b/vendor/bacon/bacon-qr-code/src/Renderer/Module/EdgeIterator/EdgeIterator.php @@ -0,0 +1,160 @@ +bytes = iterator_to_array($matrix->getBytes()); + $this->size = count($this->bytes); + $this->width = $matrix->getWidth(); + $this->height = $matrix->getHeight(); + } + + /** + * @return Traversable + */ + public function getIterator() : Traversable + { + $originalBytes = $this->bytes; + $point = $this->findNext(0, 0); + + while (null !== $point) { + $edge = $this->findEdge($point[0], $point[1]); + $this->xorEdge($edge); + + yield $edge; + + $point = $this->findNext($point[0], $point[1]); + } + + $this->bytes = $originalBytes; + } + + /** + * @return int[]|null + */ + private function findNext(int $x, int $y) : ?array + { + $i = $this->width * $y + $x; + + while ($i < $this->size && 1 !== $this->bytes[$i]) { + ++$i; + } + + if ($i < $this->size) { + return $this->pointOf($i); + } + + return null; + } + + private function findEdge(int $x, int $y) : Edge + { + $edge = new Edge($this->isSet($x, $y)); + $startX = $x; + $startY = $y; + $dirX = 0; + $dirY = 1; + + while (true) { + $edge->addPoint($x, $y); + $x += $dirX; + $y += $dirY; + + if ($x === $startX && $y === $startY) { + break; + } + + $left = $this->isSet($x + ($dirX + $dirY - 1 ) / 2, $y + ($dirY - $dirX - 1) / 2); + $right = $this->isSet($x + ($dirX - $dirY - 1) / 2, $y + ($dirY + $dirX - 1) / 2); + + if ($right && ! $left) { + $tmp = $dirX; + $dirX = -$dirY; + $dirY = $tmp; + } elseif ($right) { + $tmp = $dirX; + $dirX = -$dirY; + $dirY = $tmp; + } elseif (! $left) { + $tmp = $dirX; + $dirX = $dirY; + $dirY = -$tmp; + } + } + + return $edge; + } + + private function xorEdge(Edge $path) : void + { + $points = $path->getPoints(); + $y1 = $points[0][1]; + $length = count($points); + $maxX = $path->getMaxX(); + + for ($i = 1; $i < $length; ++$i) { + $y = $points[$i][1]; + + if ($y === $y1) { + continue; + } + + $x = $points[$i][0]; + $minY = min($y1, $y); + + for ($j = $x; $j < $maxX; ++$j) { + $this->flip($j, $minY); + } + + $y1 = $y; + } + } + + private function isSet(int $x, int $y) : bool + { + return ( + $x >= 0 + && $x < $this->width + && $y >= 0 + && $y < $this->height + ) && 1 === $this->bytes[$this->width * $y + $x]; + } + + /** + * @return int[] + */ + private function pointOf(int $i) : array + { + $y = intdiv($i, $this->width); + return [$i - $y * $this->width, $y]; + } + + private function flip(int $x, int $y) : void + { + $this->bytes[$this->width * $y + $x] = ( + $this->isSet($x, $y) ? 0 : 1 + ); + } +} diff --git a/vendor/bacon/bacon-qr-code/src/Renderer/Module/ModuleInterface.php b/vendor/bacon/bacon-qr-code/src/Renderer/Module/ModuleInterface.php new file mode 100644 index 0000000..0ccb0e0 --- /dev/null +++ b/vendor/bacon/bacon-qr-code/src/Renderer/Module/ModuleInterface.php @@ -0,0 +1,18 @@ + 1) { + throw new InvalidArgumentException('Intensity must between 0 (exclusive) and 1 (inclusive)'); + } + + $this->intensity = $intensity / 2; + } + + public function createPath(ByteMatrix $matrix) : Path + { + $path = new Path(); + + foreach (new EdgeIterator($matrix) as $edge) { + $points = $edge->getSimplifiedPoints(); + $length = count($points); + + $currentPoint = $points[0]; + $nextPoint = $points[1]; + $horizontal = ($currentPoint[1] === $nextPoint[1]); + + if ($horizontal) { + $right = $nextPoint[0] > $currentPoint[0]; + $path = $path->move( + $currentPoint[0] + ($right ? $this->intensity : -$this->intensity), + $currentPoint[1] + ); + } else { + $up = $nextPoint[0] < $currentPoint[0]; + $path = $path->move( + $currentPoint[0], + $currentPoint[1] + ($up ? -$this->intensity : $this->intensity) + ); + } + + for ($i = 1; $i <= $length; ++$i) { + if ($i === $length) { + $previousPoint = $points[$length - 1]; + $currentPoint = $points[0]; + $nextPoint = $points[1]; + } else { + $previousPoint = $points[(0 === $i ? $length : $i) - 1]; + $currentPoint = $points[$i]; + $nextPoint = $points[($length - 1 === $i ? -1 : $i) + 1]; + } + + $horizontal = ($previousPoint[1] === $currentPoint[1]); + + if ($horizontal) { + $right = $previousPoint[0] < $currentPoint[0]; + $up = $nextPoint[1] < $currentPoint[1]; + $sweep = ($up xor $right); + + if ($this->intensity < 0.5 + || ($right && $previousPoint[0] !== $currentPoint[0] - 1) + || (! $right && $previousPoint[0] - 1 !== $currentPoint[0]) + ) { + $path = $path->line( + $currentPoint[0] + ($right ? -$this->intensity : $this->intensity), + $currentPoint[1] + ); + } + + $path = $path->ellipticArc( + $this->intensity, + $this->intensity, + 0, + false, + $sweep, + $currentPoint[0], + $currentPoint[1] + ($up ? -$this->intensity : $this->intensity) + ); + } else { + $up = $previousPoint[1] > $currentPoint[1]; + $right = $nextPoint[0] > $currentPoint[0]; + $sweep = ! ($up xor $right); + + if ($this->intensity < 0.5 + || ($up && $previousPoint[1] !== $currentPoint[1] + 1) + || (! $up && $previousPoint[0] + 1 !== $currentPoint[0]) + ) { + $path = $path->line( + $currentPoint[0], + $currentPoint[1] + ($up ? $this->intensity : -$this->intensity) + ); + } + + $path = $path->ellipticArc( + $this->intensity, + $this->intensity, + 0, + false, + $sweep, + $currentPoint[0] + ($right ? $this->intensity : -$this->intensity), + $currentPoint[1] + ); + } + } + + $path = $path->close(); + } + + return $path; + } +} diff --git a/vendor/bacon/bacon-qr-code/src/Renderer/Module/SquareModule.php b/vendor/bacon/bacon-qr-code/src/Renderer/Module/SquareModule.php new file mode 100644 index 0000000..8cf1d0b --- /dev/null +++ b/vendor/bacon/bacon-qr-code/src/Renderer/Module/SquareModule.php @@ -0,0 +1,44 @@ +getSimplifiedPoints(); + $length = count($points); + $path = $path->move($points[0][0], $points[0][1]); + + for ($i = 1; $i < $length; ++$i) { + $path = $path->line($points[$i][0], $points[$i][1]); + } + + $path = $path->close(); + } + + return $path; + } +} diff --git a/vendor/bacon/bacon-qr-code/src/Renderer/Path/Close.php b/vendor/bacon/bacon-qr-code/src/Renderer/Path/Close.php new file mode 100644 index 0000000..bddf2d0 --- /dev/null +++ b/vendor/bacon/bacon-qr-code/src/Renderer/Path/Close.php @@ -0,0 +1,34 @@ +x1; + } + + public function getY1() : float + { + return $this->y1; + } + + public function getX2() : float + { + return $this->x2; + } + + public function getY2() : float + { + return $this->y2; + } + + public function getX3() : float + { + return $this->x3; + } + + public function getY3() : float + { + return $this->y3; + } + + /** + * @return self + */ + public function translate(float $x, float $y) : OperationInterface + { + return new self( + $this->x1 + $x, + $this->y1 + $y, + $this->x2 + $x, + $this->y2 + $y, + $this->x3 + $x, + $this->y3 + $y + ); + } + + /** + * @return self + */ + public function rotate(int $degrees) : OperationInterface + { + $radians = deg2rad($degrees); + $sin = sin($radians); + $cos = cos($radians); + $x1r = $this->x1 * $cos - $this->y1 * $sin; + $y1r = $this->x1 * $sin + $this->y1 * $cos; + $x2r = $this->x2 * $cos - $this->y2 * $sin; + $y2r = $this->x2 * $sin + $this->y2 * $cos; + $x3r = $this->x3 * $cos - $this->y3 * $sin; + $y3r = $this->x3 * $sin + $this->y3 * $cos; + return new self( + $x1r, + $y1r, + $x2r, + $y2r, + $x3r, + $y3r + ); + } +} diff --git a/vendor/bacon/bacon-qr-code/src/Renderer/Path/EllipticArc.php b/vendor/bacon/bacon-qr-code/src/Renderer/Path/EllipticArc.php new file mode 100644 index 0000000..ee957d4 --- /dev/null +++ b/vendor/bacon/bacon-qr-code/src/Renderer/Path/EllipticArc.php @@ -0,0 +1,264 @@ +xRadius = abs($xRadius); + $this->yRadius = abs($yRadius); + $this->xAxisAngle = $xAxisAngle % 360; + } + + public function getXRadius() : float + { + return $this->xRadius; + } + + public function getYRadius() : float + { + return $this->yRadius; + } + + public function getXAxisAngle() : float + { + return $this->xAxisAngle; + } + + public function isLargeArc() : bool + { + return $this->largeArc; + } + + public function isSweep() : bool + { + return $this->sweep; + } + + public function getX() : float + { + return $this->x; + } + + public function getY() : float + { + return $this->y; + } + + /** + * @return self + */ + public function translate(float $x, float $y) : OperationInterface + { + return new self( + $this->xRadius, + $this->yRadius, + $this->xAxisAngle, + $this->largeArc, + $this->sweep, + $this->x + $x, + $this->y + $y + ); + } + + /** + * @return self + */ + public function rotate(int $degrees) : OperationInterface + { + $radians = deg2rad($degrees); + $sin = sin($radians); + $cos = cos($radians); + $xr = $this->x * $cos - $this->y * $sin; + $yr = $this->x * $sin + $this->y * $cos; + return new self( + $this->xRadius, + $this->yRadius, + $this->xAxisAngle, + $this->largeArc, + $this->sweep, + $xr, + $yr + ); + } + + /** + * Converts the elliptic arc to multiple curves. + * + * Since not all image back ends support elliptic arcs, this method allows to convert the arc into multiple curves + * resembling the same result. + * + * @see https://mortoray.com/2017/02/16/rendering-an-svg-elliptical-arc-as-bezier-curves/ + * @return array + */ + public function toCurves(float $fromX, float $fromY) : array + { + if (sqrt(($fromX - $this->x) ** 2 + ($fromY - $this->y) ** 2) < self::ZERO_TOLERANCE) { + return []; + } + + if ($this->xRadius < self::ZERO_TOLERANCE || $this->yRadius < self::ZERO_TOLERANCE) { + return [new Line($this->x, $this->y)]; + } + + return $this->createCurves($fromX, $fromY); + } + + /** + * @return Curve[] + */ + private function createCurves(float $fromX, float $fromY) : array + { + $xAngle = deg2rad($this->xAxisAngle); + list($centerX, $centerY, $radiusX, $radiusY, $startAngle, $deltaAngle) = + $this->calculateCenterPointParameters($fromX, $fromY, $xAngle); + + $s = $startAngle; + $e = $s + $deltaAngle; + $sign = ($e < $s) ? -1 : 1; + $remain = abs($e - $s); + $p1 = self::point($centerX, $centerY, $radiusX, $radiusY, $xAngle, $s); + $curves = []; + + while ($remain > self::ZERO_TOLERANCE) { + $step = min($remain, pi() / 2); + $signStep = $step * $sign; + $p2 = self::point($centerX, $centerY, $radiusX, $radiusY, $xAngle, $s + $signStep); + + $alphaT = tan($signStep / 2); + $alpha = sin($signStep) * (sqrt(4 + 3 * $alphaT ** 2) - 1) / 3; + $d1 = self::derivative($radiusX, $radiusY, $xAngle, $s); + $d2 = self::derivative($radiusX, $radiusY, $xAngle, $s + $signStep); + + $curves[] = new Curve( + $p1[0] + $alpha * $d1[0], + $p1[1] + $alpha * $d1[1], + $p2[0] - $alpha * $d2[0], + $p2[1] - $alpha * $d2[1], + $p2[0], + $p2[1] + ); + + $s += $signStep; + $remain -= $step; + $p1 = $p2; + } + + return $curves; + } + + /** + * @return float[] + */ + private function calculateCenterPointParameters(float $fromX, float $fromY, float $xAngle): array + { + $rX = $this->xRadius; + $rY = $this->yRadius; + + // F.6.5.1 + $dx2 = ($fromX - $this->x) / 2; + $dy2 = ($fromY - $this->y) / 2; + $x1p = cos($xAngle) * $dx2 + sin($xAngle) * $dy2; + $y1p = -sin($xAngle) * $dx2 + cos($xAngle) * $dy2; + + // F.6.5.2 + $rxs = $rX ** 2; + $rys = $rY ** 2; + $x1ps = $x1p ** 2; + $y1ps = $y1p ** 2; + $cr = $x1ps / $rxs + $y1ps / $rys; + + if ($cr > 1) { + $s = sqrt($cr); + $rX *= $s; + $rY *= $s; + $rxs = $rX ** 2; + $rys = $rY ** 2; + } + + $dq = ($rxs * $y1ps + $rys * $x1ps); + $pq = ($rxs * $rys - $dq) / $dq; + $q = sqrt(max(0, $pq)); + + if ($this->largeArc === $this->sweep) { + $q = -$q; + } + + $cxp = $q * $rX * $y1p / $rY; + $cyp = -$q * $rY * $x1p / $rX; + + // F.6.5.3 + $cx = cos($xAngle) * $cxp - sin($xAngle) * $cyp + ($fromX + $this->x) / 2; + $cy = sin($xAngle) * $cxp + cos($xAngle) * $cyp + ($fromY + $this->y) / 2; + + // F.6.5.5 + $theta = self::angle(1, 0, ($x1p - $cxp) / $rX, ($y1p - $cyp) / $rY); + + // F.6.5.6 + $delta = self::angle(($x1p - $cxp) / $rX, ($y1p - $cyp) / $rY, (-$x1p - $cxp) / $rX, (-$y1p - $cyp) / $rY); + $delta = fmod($delta, pi() * 2); + + if (! $this->sweep) { + $delta -= 2 * pi(); + } + + return [$cx, $cy, $rX, $rY, $theta, $delta]; + } + + private static function angle(float $ux, float $uy, float $vx, float $vy) : float + { + // F.6.5.4 + $dot = $ux * $vx + $uy * $vy; + $length = sqrt($ux ** 2 + $uy ** 2) * sqrt($vx ** 2 + $vy ** 2); + $angle = acos(min(1, max(-1, $dot / $length))); + + if (($ux * $vy - $uy * $vx) < 0) { + return -$angle; + } + + return $angle; + } + + /** + * @return float[] + */ + private static function point( + float $centerX, + float $centerY, + float $radiusX, + float $radiusY, + float $xAngle, + float $angle + ) : array { + return [ + $centerX + $radiusX * cos($xAngle) * cos($angle) - $radiusY * sin($xAngle) * sin($angle), + $centerY + $radiusX * sin($xAngle) * cos($angle) + $radiusY * cos($xAngle) * sin($angle), + ]; + } + + /** + * @return float[] + */ + private static function derivative(float $radiusX, float $radiusY, float $xAngle, float $angle) : array + { + return [ + -$radiusX * cos($xAngle) * sin($angle) - $radiusY * sin($xAngle) * cos($angle), + -$radiusX * sin($xAngle) * sin($angle) + $radiusY * cos($xAngle) * cos($angle), + ]; + } +} diff --git a/vendor/bacon/bacon-qr-code/src/Renderer/Path/Line.php b/vendor/bacon/bacon-qr-code/src/Renderer/Path/Line.php new file mode 100644 index 0000000..dec46fd --- /dev/null +++ b/vendor/bacon/bacon-qr-code/src/Renderer/Path/Line.php @@ -0,0 +1,42 @@ +x; + } + + public function getY() : float + { + return $this->y; + } + + /** + * @return self + */ + public function translate(float $x, float $y) : OperationInterface + { + return new self($this->x + $x, $this->y + $y); + } + + /** + * @return self + */ + public function rotate(int $degrees) : OperationInterface + { + $radians = deg2rad($degrees); + $sin = sin($radians); + $cos = cos($radians); + $xr = $this->x * $cos - $this->y * $sin; + $yr = $this->x * $sin + $this->y * $cos; + return new self($xr, $yr); + } +} diff --git a/vendor/bacon/bacon-qr-code/src/Renderer/Path/Move.php b/vendor/bacon/bacon-qr-code/src/Renderer/Path/Move.php new file mode 100644 index 0000000..c3c9a56 --- /dev/null +++ b/vendor/bacon/bacon-qr-code/src/Renderer/Path/Move.php @@ -0,0 +1,42 @@ +x; + } + + public function getY() : float + { + return $this->y; + } + + /** + * @return self + */ + public function translate(float $x, float $y) : OperationInterface + { + return new self($this->x + $x, $this->y + $y); + } + + /** + * @return self + */ + public function rotate(int $degrees) : OperationInterface + { + $radians = deg2rad($degrees); + $sin = sin($radians); + $cos = cos($radians); + $xr = $this->x * $cos - $this->y * $sin; + $yr = $this->x * $sin + $this->y * $cos; + return new self($xr, $yr); + } +} diff --git a/vendor/bacon/bacon-qr-code/src/Renderer/Path/OperationInterface.php b/vendor/bacon/bacon-qr-code/src/Renderer/Path/OperationInterface.php new file mode 100644 index 0000000..9271555 --- /dev/null +++ b/vendor/bacon/bacon-qr-code/src/Renderer/Path/OperationInterface.php @@ -0,0 +1,17 @@ +operations[] = new Move($x, $y); + return $path; + } + + /** + * Draws a line from the current position to another position. + */ + public function line(float $x, float $y) : self + { + $path = clone $this; + $path->operations[] = new Line($x, $y); + return $path; + } + + /** + * Draws an elliptic arc from the current position to another position. + */ + public function ellipticArc( + float $xRadius, + float $yRadius, + float $xAxisRotation, + bool $largeArc, + bool $sweep, + float $x, + float $y + ) : self { + $path = clone $this; + $path->operations[] = new EllipticArc($xRadius, $yRadius, $xAxisRotation, $largeArc, $sweep, $x, $y); + return $path; + } + + /** + * Draws a curve from the current position to another position. + */ + public function curve(float $x1, float $y1, float $x2, float $y2, float $x3, float $y3) : self + { + $path = clone $this; + $path->operations[] = new Curve($x1, $y1, $x2, $y2, $x3, $y3); + return $path; + } + + /** + * Closes a sub-path. + */ + public function close() : self + { + $path = clone $this; + $path->operations[] = Close::instance(); + return $path; + } + + /** + * Appends another path to this one. + */ + public function append(self $other) : self + { + $path = clone $this; + $path->operations = array_merge($this->operations, $other->operations); + return $path; + } + + public function translate(float $x, float $y) : self + { + $path = new self(); + + foreach ($this->operations as $operation) { + $path->operations[] = $operation->translate($x, $y); + } + + return $path; + } + + public function rotate(int $degrees) : self + { + $path = new self(); + + foreach ($this->operations as $operation) { + $path->operations[] = $operation->rotate($degrees); + } + + return $path; + } + + /** + * @return Traversable + */ + public function getIterator() : Traversable + { + foreach ($this->operations as $operation) { + yield $operation; + } + } +} diff --git a/vendor/bacon/bacon-qr-code/src/Renderer/PlainTextRenderer.php b/vendor/bacon/bacon-qr-code/src/Renderer/PlainTextRenderer.php new file mode 100644 index 0000000..219bbf3 --- /dev/null +++ b/vendor/bacon/bacon-qr-code/src/Renderer/PlainTextRenderer.php @@ -0,0 +1,80 @@ +getMatrix(); + $matrixSize = $matrix->getWidth(); + + if ($matrixSize !== $matrix->getHeight()) { + throw new InvalidArgumentException('Matrix must have the same width and height'); + } + + $rows = $matrix->getArray()->toArray(); + + if (0 !== $matrixSize % 2) { + $rows[] = array_fill(0, $matrixSize, 0); + } + + $horizontalMargin = str_repeat(self::EMPTY_BLOCK, $this->margin); + $result = str_repeat("\n", (int) ceil($this->margin / 2)); + + for ($i = 0; $i < $matrixSize; $i += 2) { + $result .= $horizontalMargin; + + $upperRow = $rows[$i]; + $lowerRow = $rows[$i + 1]; + + for ($j = 0; $j < $matrixSize; ++$j) { + $upperBit = $upperRow[$j]; + $lowerBit = $lowerRow[$j]; + + if ($upperBit) { + $result .= $lowerBit ? self::FULL_BLOCK : self::UPPER_HALF_BLOCK; + } else { + $result .= $lowerBit ? self::LOWER_HALF_BLOCK : self::EMPTY_BLOCK; + } + } + + $result .= $horizontalMargin . "\n"; + } + + $result .= str_repeat("\n", (int) ceil($this->margin / 2)); + + return $result; + } +} diff --git a/vendor/bacon/bacon-qr-code/src/Renderer/RendererInterface.php b/vendor/bacon/bacon-qr-code/src/Renderer/RendererInterface.php new file mode 100644 index 0000000..b0aae39 --- /dev/null +++ b/vendor/bacon/bacon-qr-code/src/Renderer/RendererInterface.php @@ -0,0 +1,11 @@ +externalColor && null === $this->internalColor; + } + + public function inheritsExternalColor() : bool + { + return null === $this->externalColor; + } + + public function inheritsInternalColor() : bool + { + return null === $this->internalColor; + } + + public function getExternalColor() : ColorInterface + { + if (null === $this->externalColor) { + throw new RuntimeException('External eye color inherits foreground color'); + } + + return $this->externalColor; + } + + public function getInternalColor() : ColorInterface + { + if (null === $this->internalColor) { + throw new RuntimeException('Internal eye color inherits foreground color'); + } + + return $this->internalColor; + } +} diff --git a/vendor/bacon/bacon-qr-code/src/Renderer/RendererStyle/Fill.php b/vendor/bacon/bacon-qr-code/src/Renderer/RendererStyle/Fill.php new file mode 100644 index 0000000..19de25d --- /dev/null +++ b/vendor/bacon/bacon-qr-code/src/Renderer/RendererStyle/Fill.php @@ -0,0 +1,129 @@ +foregroundGradient; + } + + public function getBackgroundColor() : ColorInterface + { + return $this->backgroundColor; + } + + public function getForegroundColor() : ColorInterface + { + if (null === $this->foregroundColor) { + throw new RuntimeException('Fill uses a gradient, thus no foreground color is available'); + } + + return $this->foregroundColor; + } + + public function getForegroundGradient() : Gradient + { + if (null === $this->foregroundGradient) { + throw new RuntimeException('Fill uses a single color, thus no foreground gradient is available'); + } + + return $this->foregroundGradient; + } + + public function getTopLeftEyeFill() : EyeFill + { + return $this->topLeftEyeFill; + } + + public function getTopRightEyeFill() : EyeFill + { + return $this->topRightEyeFill; + } + + public function getBottomLeftEyeFill() : EyeFill + { + return $this->bottomLeftEyeFill; + } +} diff --git a/vendor/bacon/bacon-qr-code/src/Renderer/RendererStyle/Gradient.php b/vendor/bacon/bacon-qr-code/src/Renderer/RendererStyle/Gradient.php new file mode 100644 index 0000000..eea4031 --- /dev/null +++ b/vendor/bacon/bacon-qr-code/src/Renderer/RendererStyle/Gradient.php @@ -0,0 +1,31 @@ +startColor; + } + + public function getEndColor() : ColorInterface + { + return $this->endColor; + } + + public function getType() : GradientType + { + return $this->type; + } +} diff --git a/vendor/bacon/bacon-qr-code/src/Renderer/RendererStyle/GradientType.php b/vendor/bacon/bacon-qr-code/src/Renderer/RendererStyle/GradientType.php new file mode 100644 index 0000000..c1ca754 --- /dev/null +++ b/vendor/bacon/bacon-qr-code/src/Renderer/RendererStyle/GradientType.php @@ -0,0 +1,22 @@ +module = $module ?: SquareModule::instance(); + $this->eye = $eye ?: new ModuleEye($this->module); + $this->fill = $fill ?: Fill::default(); + } + + public function withSize(int $size) : self + { + $style = clone $this; + $style->size = $size; + return $style; + } + + public function withMargin(int $margin) : self + { + $style = clone $this; + $style->margin = $margin; + return $style; + } + + public function getSize() : int + { + return $this->size; + } + + public function getMargin() : int + { + return $this->margin; + } + + public function getModule() : ModuleInterface + { + return $this->module; + } + + public function getEye() : EyeInterface + { + return $this->eye; + } + + public function getFill() : Fill + { + return $this->fill; + } +} diff --git a/vendor/bacon/bacon-qr-code/src/Writer.php b/vendor/bacon/bacon-qr-code/src/Writer.php new file mode 100644 index 0000000..d7f7ebb --- /dev/null +++ b/vendor/bacon/bacon-qr-code/src/Writer.php @@ -0,0 +1,63 @@ +renderer->render(Encoder::encode($content, $ecLevel, $encoding, $forcedVersion)); + } + + /** + * Writes QR code to a file. + * + * @see Writer::writeString() + */ + public function writeFile( + string $content, + string $filename, + string $encoding = Encoder::DEFAULT_BYTE_MODE_ENCODING, + ?ErrorCorrectionLevel $ecLevel = null, + ?Version $forcedVersion = null + ) : void { + file_put_contents($filename, $this->writeString($content, $encoding, $ecLevel, $forcedVersion)); + } +} diff --git a/vendor/bin/latte-lint b/vendor/bin/latte-lint new file mode 100644 index 0000000..df90b81 --- /dev/null +++ b/vendor/bin/latte-lint @@ -0,0 +1,119 @@ +#!/usr/bin/env php +realpath = realpath($opened_path) ?: $opened_path; + $opened_path = $this->realpath; + $this->handle = fopen($this->realpath, $mode); + $this->position = 0; + + return (bool) $this->handle; + } + + public function stream_read($count) + { + $data = fread($this->handle, $count); + + if ($this->position === 0) { + $data = preg_replace('{^#!.*\r?\n}', '', $data); + } + + $this->position += strlen($data); + + return $data; + } + + public function stream_cast($castAs) + { + return $this->handle; + } + + public function stream_close() + { + fclose($this->handle); + } + + public function stream_lock($operation) + { + return $operation ? flock($this->handle, $operation) : true; + } + + public function stream_seek($offset, $whence) + { + if (0 === fseek($this->handle, $offset, $whence)) { + $this->position = ftell($this->handle); + return true; + } + + return false; + } + + public function stream_tell() + { + return $this->position; + } + + public function stream_eof() + { + return feof($this->handle); + } + + public function stream_stat() + { + return array(); + } + + public function stream_set_option($option, $arg1, $arg2) + { + return true; + } + + public function url_stat($path, $flags) + { + $path = substr($path, 17); + if (file_exists($path)) { + return stat($path); + } + + return false; + } + } + } + + if ( + (function_exists('stream_get_wrappers') && in_array('phpvfscomposer', stream_get_wrappers(), true)) + || (function_exists('stream_wrapper_register') && stream_wrapper_register('phpvfscomposer', 'Composer\BinProxyWrapper')) + ) { + return include("phpvfscomposer://" . __DIR__ . '/..'.'/latte/latte/bin/latte-lint'); + } +} + +return include __DIR__ . '/..'.'/latte/latte/bin/latte-lint'; diff --git a/vendor/bin/latte-lint.bat b/vendor/bin/latte-lint.bat new file mode 100644 index 0000000..2fb8891 --- /dev/null +++ b/vendor/bin/latte-lint.bat @@ -0,0 +1,5 @@ +@ECHO OFF +setlocal DISABLEDELAYEDEXPANSION +SET BIN_TARGET=%~dp0/latte-lint +SET COMPOSER_RUNTIME_BIN_DIR=%~dp0 +php "%BIN_TARGET%" %* diff --git a/vendor/bin/neon-lint b/vendor/bin/neon-lint new file mode 100644 index 0000000..c774123 --- /dev/null +++ b/vendor/bin/neon-lint @@ -0,0 +1,119 @@ +#!/usr/bin/env php +realpath = realpath($opened_path) ?: $opened_path; + $opened_path = $this->realpath; + $this->handle = fopen($this->realpath, $mode); + $this->position = 0; + + return (bool) $this->handle; + } + + public function stream_read($count) + { + $data = fread($this->handle, $count); + + if ($this->position === 0) { + $data = preg_replace('{^#!.*\r?\n}', '', $data); + } + + $this->position += strlen($data); + + return $data; + } + + public function stream_cast($castAs) + { + return $this->handle; + } + + public function stream_close() + { + fclose($this->handle); + } + + public function stream_lock($operation) + { + return $operation ? flock($this->handle, $operation) : true; + } + + public function stream_seek($offset, $whence) + { + if (0 === fseek($this->handle, $offset, $whence)) { + $this->position = ftell($this->handle); + return true; + } + + return false; + } + + public function stream_tell() + { + return $this->position; + } + + public function stream_eof() + { + return feof($this->handle); + } + + public function stream_stat() + { + return array(); + } + + public function stream_set_option($option, $arg1, $arg2) + { + return true; + } + + public function url_stat($path, $flags) + { + $path = substr($path, 17); + if (file_exists($path)) { + return stat($path); + } + + return false; + } + } + } + + if ( + (function_exists('stream_get_wrappers') && in_array('phpvfscomposer', stream_get_wrappers(), true)) + || (function_exists('stream_wrapper_register') && stream_wrapper_register('phpvfscomposer', 'Composer\BinProxyWrapper')) + ) { + return include("phpvfscomposer://" . __DIR__ . '/..'.'/nette/neon/bin/neon-lint'); + } +} + +return include __DIR__ . '/..'.'/nette/neon/bin/neon-lint'; diff --git a/vendor/bin/neon-lint.bat b/vendor/bin/neon-lint.bat new file mode 100644 index 0000000..31fa117 --- /dev/null +++ b/vendor/bin/neon-lint.bat @@ -0,0 +1,5 @@ +@ECHO OFF +setlocal DISABLEDELAYEDEXPANSION +SET BIN_TARGET=%~dp0/neon-lint +SET COMPOSER_RUNTIME_BIN_DIR=%~dp0 +php "%BIN_TARGET%" %* diff --git a/vendor/bin/phpstan b/vendor/bin/phpstan new file mode 100644 index 0000000..d76c0be --- /dev/null +++ b/vendor/bin/phpstan @@ -0,0 +1,119 @@ +#!/usr/bin/env php +realpath = realpath($opened_path) ?: $opened_path; + $opened_path = $this->realpath; + $this->handle = fopen($this->realpath, $mode); + $this->position = 0; + + return (bool) $this->handle; + } + + public function stream_read($count) + { + $data = fread($this->handle, $count); + + if ($this->position === 0) { + $data = preg_replace('{^#!.*\r?\n}', '', $data); + } + + $this->position += strlen($data); + + return $data; + } + + public function stream_cast($castAs) + { + return $this->handle; + } + + public function stream_close() + { + fclose($this->handle); + } + + public function stream_lock($operation) + { + return $operation ? flock($this->handle, $operation) : true; + } + + public function stream_seek($offset, $whence) + { + if (0 === fseek($this->handle, $offset, $whence)) { + $this->position = ftell($this->handle); + return true; + } + + return false; + } + + public function stream_tell() + { + return $this->position; + } + + public function stream_eof() + { + return feof($this->handle); + } + + public function stream_stat() + { + return array(); + } + + public function stream_set_option($option, $arg1, $arg2) + { + return true; + } + + public function url_stat($path, $flags) + { + $path = substr($path, 17); + if (file_exists($path)) { + return stat($path); + } + + return false; + } + } + } + + if ( + (function_exists('stream_get_wrappers') && in_array('phpvfscomposer', stream_get_wrappers(), true)) + || (function_exists('stream_wrapper_register') && stream_wrapper_register('phpvfscomposer', 'Composer\BinProxyWrapper')) + ) { + return include("phpvfscomposer://" . __DIR__ . '/..'.'/phpstan/phpstan/phpstan'); + } +} + +return include __DIR__ . '/..'.'/phpstan/phpstan/phpstan'; diff --git a/vendor/bin/phpstan.bat b/vendor/bin/phpstan.bat new file mode 100644 index 0000000..7ec286d --- /dev/null +++ b/vendor/bin/phpstan.bat @@ -0,0 +1,5 @@ +@ECHO OFF +setlocal DISABLEDELAYEDEXPANSION +SET BIN_TARGET=%~dp0/phpstan +SET COMPOSER_RUNTIME_BIN_DIR=%~dp0 +php "%BIN_TARGET%" %* diff --git a/vendor/bin/phpstan.phar b/vendor/bin/phpstan.phar new file mode 100644 index 0000000..fecf96f --- /dev/null +++ b/vendor/bin/phpstan.phar @@ -0,0 +1,119 @@ +#!/usr/bin/env php +realpath = realpath($opened_path) ?: $opened_path; + $opened_path = $this->realpath; + $this->handle = fopen($this->realpath, $mode); + $this->position = 0; + + return (bool) $this->handle; + } + + public function stream_read($count) + { + $data = fread($this->handle, $count); + + if ($this->position === 0) { + $data = preg_replace('{^#!.*\r?\n}', '', $data); + } + + $this->position += strlen($data); + + return $data; + } + + public function stream_cast($castAs) + { + return $this->handle; + } + + public function stream_close() + { + fclose($this->handle); + } + + public function stream_lock($operation) + { + return $operation ? flock($this->handle, $operation) : true; + } + + public function stream_seek($offset, $whence) + { + if (0 === fseek($this->handle, $offset, $whence)) { + $this->position = ftell($this->handle); + return true; + } + + return false; + } + + public function stream_tell() + { + return $this->position; + } + + public function stream_eof() + { + return feof($this->handle); + } + + public function stream_stat() + { + return array(); + } + + public function stream_set_option($option, $arg1, $arg2) + { + return true; + } + + public function url_stat($path, $flags) + { + $path = substr($path, 17); + if (file_exists($path)) { + return stat($path); + } + + return false; + } + } + } + + if ( + (function_exists('stream_get_wrappers') && in_array('phpvfscomposer', stream_get_wrappers(), true)) + || (function_exists('stream_wrapper_register') && stream_wrapper_register('phpvfscomposer', 'Composer\BinProxyWrapper')) + ) { + return include("phpvfscomposer://" . __DIR__ . '/..'.'/phpstan/phpstan/phpstan.phar'); + } +} + +return include __DIR__ . '/..'.'/phpstan/phpstan/phpstan.phar'; diff --git a/vendor/bin/phpstan.phar.bat b/vendor/bin/phpstan.phar.bat new file mode 100644 index 0000000..5f4d9eb --- /dev/null +++ b/vendor/bin/phpstan.phar.bat @@ -0,0 +1,5 @@ +@ECHO OFF +setlocal DISABLEDELAYEDEXPANSION +SET BIN_TARGET=%~dp0/phpstan.phar +SET COMPOSER_RUNTIME_BIN_DIR=%~dp0 +php "%BIN_TARGET%" %* diff --git a/vendor/bin/tester b/vendor/bin/tester new file mode 100644 index 0000000..d800307 --- /dev/null +++ b/vendor/bin/tester @@ -0,0 +1,119 @@ +#!/usr/bin/env php +realpath = realpath($opened_path) ?: $opened_path; + $opened_path = $this->realpath; + $this->handle = fopen($this->realpath, $mode); + $this->position = 0; + + return (bool) $this->handle; + } + + public function stream_read($count) + { + $data = fread($this->handle, $count); + + if ($this->position === 0) { + $data = preg_replace('{^#!.*\r?\n}', '', $data); + } + + $this->position += strlen($data); + + return $data; + } + + public function stream_cast($castAs) + { + return $this->handle; + } + + public function stream_close() + { + fclose($this->handle); + } + + public function stream_lock($operation) + { + return $operation ? flock($this->handle, $operation) : true; + } + + public function stream_seek($offset, $whence) + { + if (0 === fseek($this->handle, $offset, $whence)) { + $this->position = ftell($this->handle); + return true; + } + + return false; + } + + public function stream_tell() + { + return $this->position; + } + + public function stream_eof() + { + return feof($this->handle); + } + + public function stream_stat() + { + return array(); + } + + public function stream_set_option($option, $arg1, $arg2) + { + return true; + } + + public function url_stat($path, $flags) + { + $path = substr($path, 17); + if (file_exists($path)) { + return stat($path); + } + + return false; + } + } + } + + if ( + (function_exists('stream_get_wrappers') && in_array('phpvfscomposer', stream_get_wrappers(), true)) + || (function_exists('stream_wrapper_register') && stream_wrapper_register('phpvfscomposer', 'Composer\BinProxyWrapper')) + ) { + return include("phpvfscomposer://" . __DIR__ . '/..'.'/nette/tester/src/tester'); + } +} + +return include __DIR__ . '/..'.'/nette/tester/src/tester'; diff --git a/vendor/bin/tester.bat b/vendor/bin/tester.bat new file mode 100644 index 0000000..3402472 --- /dev/null +++ b/vendor/bin/tester.bat @@ -0,0 +1,5 @@ +@ECHO OFF +setlocal DISABLEDELAYEDEXPANSION +SET BIN_TARGET=%~dp0/tester +SET COMPOSER_RUNTIME_BIN_DIR=%~dp0 +php "%BIN_TARGET%" %* diff --git a/vendor/composer/ClassLoader.php b/vendor/composer/ClassLoader.php new file mode 100644 index 0000000..7824d8f --- /dev/null +++ b/vendor/composer/ClassLoader.php @@ -0,0 +1,579 @@ + + * Jordi Boggiano + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Composer\Autoload; + +/** + * ClassLoader implements a PSR-0, PSR-4 and classmap class loader. + * + * $loader = new \Composer\Autoload\ClassLoader(); + * + * // register classes with namespaces + * $loader->add('Symfony\Component', __DIR__.'/component'); + * $loader->add('Symfony', __DIR__.'/framework'); + * + * // activate the autoloader + * $loader->register(); + * + * // to enable searching the include path (eg. for PEAR packages) + * $loader->setUseIncludePath(true); + * + * In this example, if you try to use a class in the Symfony\Component + * namespace or one of its children (Symfony\Component\Console for instance), + * the autoloader will first look for the class under the component/ + * directory, and it will then fallback to the framework/ directory if not + * found before giving up. + * + * This class is loosely based on the Symfony UniversalClassLoader. + * + * @author Fabien Potencier + * @author Jordi Boggiano + * @see https://www.php-fig.org/psr/psr-0/ + * @see https://www.php-fig.org/psr/psr-4/ + */ +class ClassLoader +{ + /** @var \Closure(string):void */ + private static $includeFile; + + /** @var string|null */ + private $vendorDir; + + // PSR-4 + /** + * @var array> + */ + private $prefixLengthsPsr4 = array(); + /** + * @var array> + */ + private $prefixDirsPsr4 = array(); + /** + * @var list + */ + private $fallbackDirsPsr4 = array(); + + // PSR-0 + /** + * List of PSR-0 prefixes + * + * Structured as array('F (first letter)' => array('Foo\Bar (full prefix)' => array('path', 'path2'))) + * + * @var array>> + */ + private $prefixesPsr0 = array(); + /** + * @var list + */ + private $fallbackDirsPsr0 = array(); + + /** @var bool */ + private $useIncludePath = false; + + /** + * @var array + */ + private $classMap = array(); + + /** @var bool */ + private $classMapAuthoritative = false; + + /** + * @var array + */ + private $missingClasses = array(); + + /** @var string|null */ + private $apcuPrefix; + + /** + * @var array + */ + private static $registeredLoaders = array(); + + /** + * @param string|null $vendorDir + */ + public function __construct($vendorDir = null) + { + $this->vendorDir = $vendorDir; + self::initializeIncludeClosure(); + } + + /** + * @return array> + */ + public function getPrefixes() + { + if (!empty($this->prefixesPsr0)) { + return call_user_func_array('array_merge', array_values($this->prefixesPsr0)); + } + + return array(); + } + + /** + * @return array> + */ + public function getPrefixesPsr4() + { + return $this->prefixDirsPsr4; + } + + /** + * @return list + */ + public function getFallbackDirs() + { + return $this->fallbackDirsPsr0; + } + + /** + * @return list + */ + public function getFallbackDirsPsr4() + { + return $this->fallbackDirsPsr4; + } + + /** + * @return array Array of classname => path + */ + public function getClassMap() + { + return $this->classMap; + } + + /** + * @param array $classMap Class to filename map + * + * @return void + */ + public function addClassMap(array $classMap) + { + if ($this->classMap) { + $this->classMap = array_merge($this->classMap, $classMap); + } else { + $this->classMap = $classMap; + } + } + + /** + * Registers a set of PSR-0 directories for a given prefix, either + * appending or prepending to the ones previously set for this prefix. + * + * @param string $prefix The prefix + * @param list|string $paths The PSR-0 root directories + * @param bool $prepend Whether to prepend the directories + * + * @return void + */ + public function add($prefix, $paths, $prepend = false) + { + $paths = (array) $paths; + if (!$prefix) { + if ($prepend) { + $this->fallbackDirsPsr0 = array_merge( + $paths, + $this->fallbackDirsPsr0 + ); + } else { + $this->fallbackDirsPsr0 = array_merge( + $this->fallbackDirsPsr0, + $paths + ); + } + + return; + } + + $first = $prefix[0]; + if (!isset($this->prefixesPsr0[$first][$prefix])) { + $this->prefixesPsr0[$first][$prefix] = $paths; + + return; + } + if ($prepend) { + $this->prefixesPsr0[$first][$prefix] = array_merge( + $paths, + $this->prefixesPsr0[$first][$prefix] + ); + } else { + $this->prefixesPsr0[$first][$prefix] = array_merge( + $this->prefixesPsr0[$first][$prefix], + $paths + ); + } + } + + /** + * Registers a set of PSR-4 directories for a given namespace, either + * appending or prepending to the ones previously set for this namespace. + * + * @param string $prefix The prefix/namespace, with trailing '\\' + * @param list|string $paths The PSR-4 base directories + * @param bool $prepend Whether to prepend the directories + * + * @throws \InvalidArgumentException + * + * @return void + */ + public function addPsr4($prefix, $paths, $prepend = false) + { + $paths = (array) $paths; + if (!$prefix) { + // Register directories for the root namespace. + if ($prepend) { + $this->fallbackDirsPsr4 = array_merge( + $paths, + $this->fallbackDirsPsr4 + ); + } else { + $this->fallbackDirsPsr4 = array_merge( + $this->fallbackDirsPsr4, + $paths + ); + } + } elseif (!isset($this->prefixDirsPsr4[$prefix])) { + // Register directories for a new namespace. + $length = strlen($prefix); + if ('\\' !== $prefix[$length - 1]) { + throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator."); + } + $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length; + $this->prefixDirsPsr4[$prefix] = $paths; + } elseif ($prepend) { + // Prepend directories for an already registered namespace. + $this->prefixDirsPsr4[$prefix] = array_merge( + $paths, + $this->prefixDirsPsr4[$prefix] + ); + } else { + // Append directories for an already registered namespace. + $this->prefixDirsPsr4[$prefix] = array_merge( + $this->prefixDirsPsr4[$prefix], + $paths + ); + } + } + + /** + * Registers a set of PSR-0 directories for a given prefix, + * replacing any others previously set for this prefix. + * + * @param string $prefix The prefix + * @param list|string $paths The PSR-0 base directories + * + * @return void + */ + public function set($prefix, $paths) + { + if (!$prefix) { + $this->fallbackDirsPsr0 = (array) $paths; + } else { + $this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths; + } + } + + /** + * Registers a set of PSR-4 directories for a given namespace, + * replacing any others previously set for this namespace. + * + * @param string $prefix The prefix/namespace, with trailing '\\' + * @param list|string $paths The PSR-4 base directories + * + * @throws \InvalidArgumentException + * + * @return void + */ + public function setPsr4($prefix, $paths) + { + if (!$prefix) { + $this->fallbackDirsPsr4 = (array) $paths; + } else { + $length = strlen($prefix); + if ('\\' !== $prefix[$length - 1]) { + throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator."); + } + $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length; + $this->prefixDirsPsr4[$prefix] = (array) $paths; + } + } + + /** + * Turns on searching the include path for class files. + * + * @param bool $useIncludePath + * + * @return void + */ + public function setUseIncludePath($useIncludePath) + { + $this->useIncludePath = $useIncludePath; + } + + /** + * Can be used to check if the autoloader uses the include path to check + * for classes. + * + * @return bool + */ + public function getUseIncludePath() + { + return $this->useIncludePath; + } + + /** + * Turns off searching the prefix and fallback directories for classes + * that have not been registered with the class map. + * + * @param bool $classMapAuthoritative + * + * @return void + */ + public function setClassMapAuthoritative($classMapAuthoritative) + { + $this->classMapAuthoritative = $classMapAuthoritative; + } + + /** + * Should class lookup fail if not found in the current class map? + * + * @return bool + */ + public function isClassMapAuthoritative() + { + return $this->classMapAuthoritative; + } + + /** + * APCu prefix to use to cache found/not-found classes, if the extension is enabled. + * + * @param string|null $apcuPrefix + * + * @return void + */ + public function setApcuPrefix($apcuPrefix) + { + $this->apcuPrefix = function_exists('apcu_fetch') && filter_var(ini_get('apc.enabled'), FILTER_VALIDATE_BOOLEAN) ? $apcuPrefix : null; + } + + /** + * The APCu prefix in use, or null if APCu caching is not enabled. + * + * @return string|null + */ + public function getApcuPrefix() + { + return $this->apcuPrefix; + } + + /** + * Registers this instance as an autoloader. + * + * @param bool $prepend Whether to prepend the autoloader or not + * + * @return void + */ + public function register($prepend = false) + { + spl_autoload_register(array($this, 'loadClass'), true, $prepend); + + if (null === $this->vendorDir) { + return; + } + + if ($prepend) { + self::$registeredLoaders = array($this->vendorDir => $this) + self::$registeredLoaders; + } else { + unset(self::$registeredLoaders[$this->vendorDir]); + self::$registeredLoaders[$this->vendorDir] = $this; + } + } + + /** + * Unregisters this instance as an autoloader. + * + * @return void + */ + public function unregister() + { + spl_autoload_unregister(array($this, 'loadClass')); + + if (null !== $this->vendorDir) { + unset(self::$registeredLoaders[$this->vendorDir]); + } + } + + /** + * Loads the given class or interface. + * + * @param string $class The name of the class + * @return true|null True if loaded, null otherwise + */ + public function loadClass($class) + { + if ($file = $this->findFile($class)) { + $includeFile = self::$includeFile; + $includeFile($file); + + return true; + } + + return null; + } + + /** + * Finds the path to the file where the class is defined. + * + * @param string $class The name of the class + * + * @return string|false The path if found, false otherwise + */ + public function findFile($class) + { + // class map lookup + if (isset($this->classMap[$class])) { + return $this->classMap[$class]; + } + if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) { + return false; + } + if (null !== $this->apcuPrefix) { + $file = apcu_fetch($this->apcuPrefix.$class, $hit); + if ($hit) { + return $file; + } + } + + $file = $this->findFileWithExtension($class, '.php'); + + // Search for Hack files if we are running on HHVM + if (false === $file && defined('HHVM_VERSION')) { + $file = $this->findFileWithExtension($class, '.hh'); + } + + if (null !== $this->apcuPrefix) { + apcu_add($this->apcuPrefix.$class, $file); + } + + if (false === $file) { + // Remember that this class does not exist. + $this->missingClasses[$class] = true; + } + + return $file; + } + + /** + * Returns the currently registered loaders keyed by their corresponding vendor directories. + * + * @return array + */ + public static function getRegisteredLoaders() + { + return self::$registeredLoaders; + } + + /** + * @param string $class + * @param string $ext + * @return string|false + */ + private function findFileWithExtension($class, $ext) + { + // PSR-4 lookup + $logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext; + + $first = $class[0]; + if (isset($this->prefixLengthsPsr4[$first])) { + $subPath = $class; + while (false !== $lastPos = strrpos($subPath, '\\')) { + $subPath = substr($subPath, 0, $lastPos); + $search = $subPath . '\\'; + if (isset($this->prefixDirsPsr4[$search])) { + $pathEnd = DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1); + foreach ($this->prefixDirsPsr4[$search] as $dir) { + if (file_exists($file = $dir . $pathEnd)) { + return $file; + } + } + } + } + } + + // PSR-4 fallback dirs + foreach ($this->fallbackDirsPsr4 as $dir) { + if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) { + return $file; + } + } + + // PSR-0 lookup + if (false !== $pos = strrpos($class, '\\')) { + // namespaced class name + $logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1) + . strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR); + } else { + // PEAR-like class name + $logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext; + } + + if (isset($this->prefixesPsr0[$first])) { + foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) { + if (0 === strpos($class, $prefix)) { + foreach ($dirs as $dir) { + if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) { + return $file; + } + } + } + } + } + + // PSR-0 fallback dirs + foreach ($this->fallbackDirsPsr0 as $dir) { + if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) { + return $file; + } + } + + // PSR-0 include paths. + if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) { + return $file; + } + + return false; + } + + /** + * @return void + */ + private static function initializeIncludeClosure() + { + if (self::$includeFile !== null) { + return; + } + + /** + * Scope isolated include. + * + * Prevents access to $this/self from included files. + * + * @param string $file + * @return void + */ + self::$includeFile = \Closure::bind(static function($file) { + include $file; + }, null, null); + } +} diff --git a/vendor/composer/InstalledVersions.php b/vendor/composer/InstalledVersions.php new file mode 100644 index 0000000..51e734a --- /dev/null +++ b/vendor/composer/InstalledVersions.php @@ -0,0 +1,359 @@ + + * Jordi Boggiano + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Composer; + +use Composer\Autoload\ClassLoader; +use Composer\Semver\VersionParser; + +/** + * This class is copied in every Composer installed project and available to all + * + * See also https://getcomposer.org/doc/07-runtime.md#installed-versions + * + * To require its presence, you can require `composer-runtime-api ^2.0` + * + * @final + */ +class InstalledVersions +{ + /** + * @var mixed[]|null + * @psalm-var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array}|array{}|null + */ + private static $installed; + + /** + * @var bool|null + */ + private static $canGetVendors; + + /** + * @var array[] + * @psalm-var array}> + */ + private static $installedByVendor = array(); + + /** + * Returns a list of all package names which are present, either by being installed, replaced or provided + * + * @return string[] + * @psalm-return list + */ + public static function getInstalledPackages() + { + $packages = array(); + foreach (self::getInstalled() as $installed) { + $packages[] = array_keys($installed['versions']); + } + + if (1 === \count($packages)) { + return $packages[0]; + } + + return array_keys(array_flip(\call_user_func_array('array_merge', $packages))); + } + + /** + * Returns a list of all package names with a specific type e.g. 'library' + * + * @param string $type + * @return string[] + * @psalm-return list + */ + public static function getInstalledPackagesByType($type) + { + $packagesByType = array(); + + foreach (self::getInstalled() as $installed) { + foreach ($installed['versions'] as $name => $package) { + if (isset($package['type']) && $package['type'] === $type) { + $packagesByType[] = $name; + } + } + } + + return $packagesByType; + } + + /** + * Checks whether the given package is installed + * + * This also returns true if the package name is provided or replaced by another package + * + * @param string $packageName + * @param bool $includeDevRequirements + * @return bool + */ + public static function isInstalled($packageName, $includeDevRequirements = true) + { + foreach (self::getInstalled() as $installed) { + if (isset($installed['versions'][$packageName])) { + return $includeDevRequirements || !isset($installed['versions'][$packageName]['dev_requirement']) || $installed['versions'][$packageName]['dev_requirement'] === false; + } + } + + return false; + } + + /** + * Checks whether the given package satisfies a version constraint + * + * e.g. If you want to know whether version 2.3+ of package foo/bar is installed, you would call: + * + * Composer\InstalledVersions::satisfies(new VersionParser, 'foo/bar', '^2.3') + * + * @param VersionParser $parser Install composer/semver to have access to this class and functionality + * @param string $packageName + * @param string|null $constraint A version constraint to check for, if you pass one you have to make sure composer/semver is required by your package + * @return bool + */ + public static function satisfies(VersionParser $parser, $packageName, $constraint) + { + $constraint = $parser->parseConstraints((string) $constraint); + $provided = $parser->parseConstraints(self::getVersionRanges($packageName)); + + return $provided->matches($constraint); + } + + /** + * Returns a version constraint representing all the range(s) which are installed for a given package + * + * It is easier to use this via isInstalled() with the $constraint argument if you need to check + * whether a given version of a package is installed, and not just whether it exists + * + * @param string $packageName + * @return string Version constraint usable with composer/semver + */ + public static function getVersionRanges($packageName) + { + foreach (self::getInstalled() as $installed) { + if (!isset($installed['versions'][$packageName])) { + continue; + } + + $ranges = array(); + if (isset($installed['versions'][$packageName]['pretty_version'])) { + $ranges[] = $installed['versions'][$packageName]['pretty_version']; + } + if (array_key_exists('aliases', $installed['versions'][$packageName])) { + $ranges = array_merge($ranges, $installed['versions'][$packageName]['aliases']); + } + if (array_key_exists('replaced', $installed['versions'][$packageName])) { + $ranges = array_merge($ranges, $installed['versions'][$packageName]['replaced']); + } + if (array_key_exists('provided', $installed['versions'][$packageName])) { + $ranges = array_merge($ranges, $installed['versions'][$packageName]['provided']); + } + + return implode(' || ', $ranges); + } + + throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed'); + } + + /** + * @param string $packageName + * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present + */ + public static function getVersion($packageName) + { + foreach (self::getInstalled() as $installed) { + if (!isset($installed['versions'][$packageName])) { + continue; + } + + if (!isset($installed['versions'][$packageName]['version'])) { + return null; + } + + return $installed['versions'][$packageName]['version']; + } + + throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed'); + } + + /** + * @param string $packageName + * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present + */ + public static function getPrettyVersion($packageName) + { + foreach (self::getInstalled() as $installed) { + if (!isset($installed['versions'][$packageName])) { + continue; + } + + if (!isset($installed['versions'][$packageName]['pretty_version'])) { + return null; + } + + return $installed['versions'][$packageName]['pretty_version']; + } + + throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed'); + } + + /** + * @param string $packageName + * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as reference + */ + public static function getReference($packageName) + { + foreach (self::getInstalled() as $installed) { + if (!isset($installed['versions'][$packageName])) { + continue; + } + + if (!isset($installed['versions'][$packageName]['reference'])) { + return null; + } + + return $installed['versions'][$packageName]['reference']; + } + + throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed'); + } + + /** + * @param string $packageName + * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as install path. Packages of type metapackages also have a null install path. + */ + public static function getInstallPath($packageName) + { + foreach (self::getInstalled() as $installed) { + if (!isset($installed['versions'][$packageName])) { + continue; + } + + return isset($installed['versions'][$packageName]['install_path']) ? $installed['versions'][$packageName]['install_path'] : null; + } + + throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed'); + } + + /** + * @return array + * @psalm-return array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool} + */ + public static function getRootPackage() + { + $installed = self::getInstalled(); + + return $installed[0]['root']; + } + + /** + * Returns the raw installed.php data for custom implementations + * + * @deprecated Use getAllRawData() instead which returns all datasets for all autoloaders present in the process. getRawData only returns the first dataset loaded, which may not be what you expect. + * @return array[] + * @psalm-return array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array} + */ + public static function getRawData() + { + @trigger_error('getRawData only returns the first dataset loaded, which may not be what you expect. Use getAllRawData() instead which returns all datasets for all autoloaders present in the process.', E_USER_DEPRECATED); + + if (null === self::$installed) { + // only require the installed.php file if this file is loaded from its dumped location, + // and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937 + if (substr(__DIR__, -8, 1) !== 'C') { + self::$installed = include __DIR__ . '/installed.php'; + } else { + self::$installed = array(); + } + } + + return self::$installed; + } + + /** + * Returns the raw data of all installed.php which are currently loaded for custom implementations + * + * @return array[] + * @psalm-return list}> + */ + public static function getAllRawData() + { + return self::getInstalled(); + } + + /** + * Lets you reload the static array from another file + * + * This is only useful for complex integrations in which a project needs to use + * this class but then also needs to execute another project's autoloader in process, + * and wants to ensure both projects have access to their version of installed.php. + * + * A typical case would be PHPUnit, where it would need to make sure it reads all + * the data it needs from this class, then call reload() with + * `require $CWD/vendor/composer/installed.php` (or similar) as input to make sure + * the project in which it runs can then also use this class safely, without + * interference between PHPUnit's dependencies and the project's dependencies. + * + * @param array[] $data A vendor/composer/installed.php data set + * @return void + * + * @psalm-param array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array} $data + */ + public static function reload($data) + { + self::$installed = $data; + self::$installedByVendor = array(); + } + + /** + * @return array[] + * @psalm-return list}> + */ + private static function getInstalled() + { + if (null === self::$canGetVendors) { + self::$canGetVendors = method_exists('Composer\Autoload\ClassLoader', 'getRegisteredLoaders'); + } + + $installed = array(); + + if (self::$canGetVendors) { + foreach (ClassLoader::getRegisteredLoaders() as $vendorDir => $loader) { + if (isset(self::$installedByVendor[$vendorDir])) { + $installed[] = self::$installedByVendor[$vendorDir]; + } elseif (is_file($vendorDir.'/composer/installed.php')) { + /** @var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array} $required */ + $required = require $vendorDir.'/composer/installed.php'; + $installed[] = self::$installedByVendor[$vendorDir] = $required; + if (null === self::$installed && strtr($vendorDir.'/composer', '\\', '/') === strtr(__DIR__, '\\', '/')) { + self::$installed = $installed[count($installed) - 1]; + } + } + } + } + + if (null === self::$installed) { + // only require the installed.php file if this file is loaded from its dumped location, + // and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937 + if (substr(__DIR__, -8, 1) !== 'C') { + /** @var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array} $required */ + $required = require __DIR__ . '/installed.php'; + self::$installed = $required; + } else { + self::$installed = array(); + } + } + + if (self::$installed !== array()) { + $installed[] = self::$installed; + } + + return $installed; + } +} diff --git a/vendor/composer/LICENSE b/vendor/composer/LICENSE new file mode 100644 index 0000000..f27399a --- /dev/null +++ b/vendor/composer/LICENSE @@ -0,0 +1,21 @@ + +Copyright (c) Nils Adermann, Jordi Boggiano + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + diff --git a/vendor/composer/autoload_classmap.php b/vendor/composer/autoload_classmap.php new file mode 100644 index 0000000..5e8f1d0 --- /dev/null +++ b/vendor/composer/autoload_classmap.php @@ -0,0 +1,696 @@ + $vendorDir . '/composer/InstalledVersions.php', + 'Latte\\Attributes\\TemplateFilter' => $vendorDir . '/latte/latte/src/Latte/attributes.php', + 'Latte\\Attributes\\TemplateFunction' => $vendorDir . '/latte/latte/src/Latte/attributes.php', + 'Latte\\Bridges\\Tracy\\BlueScreenPanel' => $vendorDir . '/latte/latte/src/Bridges/Tracy/BlueScreenPanel.php', + 'Latte\\Bridges\\Tracy\\LattePanel' => $vendorDir . '/latte/latte/src/Bridges/Tracy/LattePanel.php', + 'Latte\\Bridges\\Tracy\\TracyExtension' => $vendorDir . '/latte/latte/src/Bridges/Tracy/TracyExtension.php', + 'Latte\\Cache' => $vendorDir . '/latte/latte/src/Latte/Cache.php', + 'Latte\\CompileException' => $vendorDir . '/latte/latte/src/Latte/exceptions.php', + 'Latte\\Compiler\\Block' => $vendorDir . '/latte/latte/src/Latte/Compiler/Block.php', + 'Latte\\Compiler\\Escaper' => $vendorDir . '/latte/latte/src/Latte/Compiler/Escaper.php', + 'Latte\\Compiler\\Node' => $vendorDir . '/latte/latte/src/Latte/Compiler/Node.php', + 'Latte\\Compiler\\NodeHelpers' => $vendorDir . '/latte/latte/src/Latte/Compiler/NodeHelpers.php', + 'Latte\\Compiler\\NodeTraverser' => $vendorDir . '/latte/latte/src/Latte/Compiler/NodeTraverser.php', + 'Latte\\Compiler\\Nodes\\AreaNode' => $vendorDir . '/latte/latte/src/Latte/Compiler/Nodes/AreaNode.php', + 'Latte\\Compiler\\Nodes\\AuxiliaryNode' => $vendorDir . '/latte/latte/src/Latte/Compiler/Nodes/AuxiliaryNode.php', + 'Latte\\Compiler\\Nodes\\FragmentNode' => $vendorDir . '/latte/latte/src/Latte/Compiler/Nodes/FragmentNode.php', + 'Latte\\Compiler\\Nodes\\Html\\AttributeNode' => $vendorDir . '/latte/latte/src/Latte/Compiler/Nodes/Html/AttributeNode.php', + 'Latte\\Compiler\\Nodes\\Html\\BogusTagNode' => $vendorDir . '/latte/latte/src/Latte/Compiler/Nodes/Html/BogusTagNode.php', + 'Latte\\Compiler\\Nodes\\Html\\CommentNode' => $vendorDir . '/latte/latte/src/Latte/Compiler/Nodes/Html/CommentNode.php', + 'Latte\\Compiler\\Nodes\\Html\\ElementNode' => $vendorDir . '/latte/latte/src/Latte/Compiler/Nodes/Html/ElementNode.php', + 'Latte\\Compiler\\Nodes\\Html\\ExpressionAttributeNode' => $vendorDir . '/latte/latte/src/Latte/Compiler/Nodes/Html/ExpressionAttributeNode.php', + 'Latte\\Compiler\\Nodes\\Html\\TagNode' => $vendorDir . '/latte/latte/src/Latte/Compiler/Nodes/Html/TagNode.php', + 'Latte\\Compiler\\Nodes\\NopNode' => $vendorDir . '/latte/latte/src/Latte/Compiler/Nodes/NopNode.php', + 'Latte\\Compiler\\Nodes\\Php\\ArgumentNode' => $vendorDir . '/latte/latte/src/Latte/Compiler/Nodes/Php/ArgumentNode.php', + 'Latte\\Compiler\\Nodes\\Php\\ArrayItemNode' => $vendorDir . '/latte/latte/src/Latte/Compiler/Nodes/Php/ArrayItemNode.php', + 'Latte\\Compiler\\Nodes\\Php\\ClosureUseNode' => $vendorDir . '/latte/latte/src/Latte/Compiler/Nodes/Php/ClosureUseNode.php', + 'Latte\\Compiler\\Nodes\\Php\\ComplexTypeNode' => $vendorDir . '/latte/latte/src/Latte/Compiler/Nodes/Php/ComplexTypeNode.php', + 'Latte\\Compiler\\Nodes\\Php\\ExpressionNode' => $vendorDir . '/latte/latte/src/Latte/Compiler/Nodes/Php/ExpressionNode.php', + 'Latte\\Compiler\\Nodes\\Php\\Expression\\ArrayAccessNode' => $vendorDir . '/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/ArrayAccessNode.php', + 'Latte\\Compiler\\Nodes\\Php\\Expression\\ArrayNode' => $vendorDir . '/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/ArrayNode.php', + 'Latte\\Compiler\\Nodes\\Php\\Expression\\AssignNode' => $vendorDir . '/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/AssignNode.php', + 'Latte\\Compiler\\Nodes\\Php\\Expression\\AssignOpNode' => $vendorDir . '/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/AssignOpNode.php', + 'Latte\\Compiler\\Nodes\\Php\\Expression\\AuxiliaryNode' => $vendorDir . '/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/AuxiliaryNode.php', + 'Latte\\Compiler\\Nodes\\Php\\Expression\\BinaryOpNode' => $vendorDir . '/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/BinaryOpNode.php', + 'Latte\\Compiler\\Nodes\\Php\\Expression\\CastNode' => $vendorDir . '/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/CastNode.php', + 'Latte\\Compiler\\Nodes\\Php\\Expression\\ClassConstantFetchNode' => $vendorDir . '/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/ClassConstantFetchNode.php', + 'Latte\\Compiler\\Nodes\\Php\\Expression\\CloneNode' => $vendorDir . '/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/CloneNode.php', + 'Latte\\Compiler\\Nodes\\Php\\Expression\\ClosureNode' => $vendorDir . '/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/ClosureNode.php', + 'Latte\\Compiler\\Nodes\\Php\\Expression\\ConstantFetchNode' => $vendorDir . '/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/ConstantFetchNode.php', + 'Latte\\Compiler\\Nodes\\Php\\Expression\\EmptyNode' => $vendorDir . '/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/EmptyNode.php', + 'Latte\\Compiler\\Nodes\\Php\\Expression\\FilterCallNode' => $vendorDir . '/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/FilterCallNode.php', + 'Latte\\Compiler\\Nodes\\Php\\Expression\\FunctionCallNode' => $vendorDir . '/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/FunctionCallNode.php', + 'Latte\\Compiler\\Nodes\\Php\\Expression\\InNode' => $vendorDir . '/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/InNode.php', + 'Latte\\Compiler\\Nodes\\Php\\Expression\\InstanceofNode' => $vendorDir . '/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/InstanceofNode.php', + 'Latte\\Compiler\\Nodes\\Php\\Expression\\IssetNode' => $vendorDir . '/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/IssetNode.php', + 'Latte\\Compiler\\Nodes\\Php\\Expression\\MatchNode' => $vendorDir . '/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/MatchNode.php', + 'Latte\\Compiler\\Nodes\\Php\\Expression\\MethodCallNode' => $vendorDir . '/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/MethodCallNode.php', + 'Latte\\Compiler\\Nodes\\Php\\Expression\\NewNode' => $vendorDir . '/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/NewNode.php', + 'Latte\\Compiler\\Nodes\\Php\\Expression\\PostOpNode' => $vendorDir . '/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/PostOpNode.php', + 'Latte\\Compiler\\Nodes\\Php\\Expression\\PreOpNode' => $vendorDir . '/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/PreOpNode.php', + 'Latte\\Compiler\\Nodes\\Php\\Expression\\PropertyFetchNode' => $vendorDir . '/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/PropertyFetchNode.php', + 'Latte\\Compiler\\Nodes\\Php\\Expression\\StaticMethodCallNode' => $vendorDir . '/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/StaticMethodCallNode.php', + 'Latte\\Compiler\\Nodes\\Php\\Expression\\StaticPropertyFetchNode' => $vendorDir . '/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/StaticPropertyFetchNode.php', + 'Latte\\Compiler\\Nodes\\Php\\Expression\\TemporaryNode' => $vendorDir . '/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/TemporaryNode.php', + 'Latte\\Compiler\\Nodes\\Php\\Expression\\TernaryNode' => $vendorDir . '/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/TernaryNode.php', + 'Latte\\Compiler\\Nodes\\Php\\Expression\\UnaryOpNode' => $vendorDir . '/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/UnaryOpNode.php', + 'Latte\\Compiler\\Nodes\\Php\\Expression\\VariableNode' => $vendorDir . '/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/VariableNode.php', + 'Latte\\Compiler\\Nodes\\Php\\FilterNode' => $vendorDir . '/latte/latte/src/Latte/Compiler/Nodes/Php/FilterNode.php', + 'Latte\\Compiler\\Nodes\\Php\\IdentifierNode' => $vendorDir . '/latte/latte/src/Latte/Compiler/Nodes/Php/IdentifierNode.php', + 'Latte\\Compiler\\Nodes\\Php\\InterpolatedStringPartNode' => $vendorDir . '/latte/latte/src/Latte/Compiler/Nodes/Php/InterpolatedStringPartNode.php', + 'Latte\\Compiler\\Nodes\\Php\\IntersectionTypeNode' => $vendorDir . '/latte/latte/src/Latte/Compiler/Nodes/Php/IntersectionTypeNode.php', + 'Latte\\Compiler\\Nodes\\Php\\ListItemNode' => $vendorDir . '/latte/latte/src/Latte/Compiler/Nodes/Php/ListItemNode.php', + 'Latte\\Compiler\\Nodes\\Php\\ListNode' => $vendorDir . '/latte/latte/src/Latte/Compiler/Nodes/Php/ListNode.php', + 'Latte\\Compiler\\Nodes\\Php\\MatchArmNode' => $vendorDir . '/latte/latte/src/Latte/Compiler/Nodes/Php/MatchArmNode.php', + 'Latte\\Compiler\\Nodes\\Php\\ModifierNode' => $vendorDir . '/latte/latte/src/Latte/Compiler/Nodes/Php/ModifierNode.php', + 'Latte\\Compiler\\Nodes\\Php\\NameNode' => $vendorDir . '/latte/latte/src/Latte/Compiler/Nodes/Php/NameNode.php', + 'Latte\\Compiler\\Nodes\\Php\\NullableTypeNode' => $vendorDir . '/latte/latte/src/Latte/Compiler/Nodes/Php/NullableTypeNode.php', + 'Latte\\Compiler\\Nodes\\Php\\OperatorNode' => $vendorDir . '/latte/latte/src/Latte/Compiler/Nodes/Php/OperatorNode.php', + 'Latte\\Compiler\\Nodes\\Php\\ParameterNode' => $vendorDir . '/latte/latte/src/Latte/Compiler/Nodes/Php/ParameterNode.php', + 'Latte\\Compiler\\Nodes\\Php\\ScalarNode' => $vendorDir . '/latte/latte/src/Latte/Compiler/Nodes/Php/ScalarNode.php', + 'Latte\\Compiler\\Nodes\\Php\\Scalar\\BooleanNode' => $vendorDir . '/latte/latte/src/Latte/Compiler/Nodes/Php/Scalar/BooleanNode.php', + 'Latte\\Compiler\\Nodes\\Php\\Scalar\\FloatNode' => $vendorDir . '/latte/latte/src/Latte/Compiler/Nodes/Php/Scalar/FloatNode.php', + 'Latte\\Compiler\\Nodes\\Php\\Scalar\\IntegerNode' => $vendorDir . '/latte/latte/src/Latte/Compiler/Nodes/Php/Scalar/IntegerNode.php', + 'Latte\\Compiler\\Nodes\\Php\\Scalar\\InterpolatedStringNode' => $vendorDir . '/latte/latte/src/Latte/Compiler/Nodes/Php/Scalar/InterpolatedStringNode.php', + 'Latte\\Compiler\\Nodes\\Php\\Scalar\\NullNode' => $vendorDir . '/latte/latte/src/Latte/Compiler/Nodes/Php/Scalar/NullNode.php', + 'Latte\\Compiler\\Nodes\\Php\\Scalar\\StringNode' => $vendorDir . '/latte/latte/src/Latte/Compiler/Nodes/Php/Scalar/StringNode.php', + 'Latte\\Compiler\\Nodes\\Php\\SuperiorTypeNode' => $vendorDir . '/latte/latte/src/Latte/Compiler/Nodes/Php/SuperiorTypeNode.php', + 'Latte\\Compiler\\Nodes\\Php\\UnionTypeNode' => $vendorDir . '/latte/latte/src/Latte/Compiler/Nodes/Php/UnionTypeNode.php', + 'Latte\\Compiler\\Nodes\\Php\\VarLikeIdentifierNode' => $vendorDir . '/latte/latte/src/Latte/Compiler/Nodes/Php/VarLikeIdentifierNode.php', + 'Latte\\Compiler\\Nodes\\Php\\VariadicPlaceholderNode' => $vendorDir . '/latte/latte/src/Latte/Compiler/Nodes/Php/VariadicPlaceholderNode.php', + 'Latte\\Compiler\\Nodes\\PrintNode' => $vendorDir . '/latte/latte/src/Latte/Compiler/Nodes/PrintNode.php', + 'Latte\\Compiler\\Nodes\\StatementNode' => $vendorDir . '/latte/latte/src/Latte/Compiler/Nodes/StatementNode.php', + 'Latte\\Compiler\\Nodes\\TemplateNode' => $vendorDir . '/latte/latte/src/Latte/Compiler/Nodes/TemplateNode.php', + 'Latte\\Compiler\\Nodes\\TextNode' => $vendorDir . '/latte/latte/src/Latte/Compiler/Nodes/TextNode.php', + 'Latte\\Compiler\\PhpHelpers' => $vendorDir . '/latte/latte/src/Latte/Compiler/PhpHelpers.php', + 'Latte\\Compiler\\Position' => $vendorDir . '/latte/latte/src/Latte/Compiler/Position.php', + 'Latte\\Compiler\\PrintContext' => $vendorDir . '/latte/latte/src/Latte/Compiler/PrintContext.php', + 'Latte\\Compiler\\Tag' => $vendorDir . '/latte/latte/src/Latte/Compiler/Tag.php', + 'Latte\\Compiler\\TagLexer' => $vendorDir . '/latte/latte/src/Latte/Compiler/TagLexer.php', + 'Latte\\Compiler\\TagParser' => $vendorDir . '/latte/latte/src/Latte/Compiler/TagParser.php', + 'Latte\\Compiler\\TagParserData' => $vendorDir . '/latte/latte/src/Latte/Compiler/TagParserData.php', + 'Latte\\Compiler\\TemplateGenerator' => $vendorDir . '/latte/latte/src/Latte/Compiler/TemplateGenerator.php', + 'Latte\\Compiler\\TemplateLexer' => $vendorDir . '/latte/latte/src/Latte/Compiler/TemplateLexer.php', + 'Latte\\Compiler\\TemplateParser' => $vendorDir . '/latte/latte/src/Latte/Compiler/TemplateParser.php', + 'Latte\\Compiler\\TemplateParserHtml' => $vendorDir . '/latte/latte/src/Latte/Compiler/TemplateParserHtml.php', + 'Latte\\Compiler\\Token' => $vendorDir . '/latte/latte/src/Latte/Compiler/Token.php', + 'Latte\\Compiler\\TokenStream' => $vendorDir . '/latte/latte/src/Latte/Compiler/TokenStream.php', + 'Latte\\ContentType' => $vendorDir . '/latte/latte/src/Latte/ContentType.php', + 'Latte\\Engine' => $vendorDir . '/latte/latte/src/Latte/Engine.php', + 'Latte\\Essential\\AuxiliaryIterator' => $vendorDir . '/latte/latte/src/Latte/Essential/AuxiliaryIterator.php', + 'Latte\\Essential\\Blueprint' => $vendorDir . '/latte/latte/src/Latte/Essential/Blueprint.php', + 'Latte\\Essential\\CachingIterator' => $vendorDir . '/latte/latte/src/Latte/Essential/CachingIterator.php', + 'Latte\\Essential\\CoreExtension' => $vendorDir . '/latte/latte/src/Latte/Essential/CoreExtension.php', + 'Latte\\Essential\\Filters' => $vendorDir . '/latte/latte/src/Latte/Essential/Filters.php', + 'Latte\\Essential\\Nodes\\BlockNode' => $vendorDir . '/latte/latte/src/Latte/Essential/Nodes/BlockNode.php', + 'Latte\\Essential\\Nodes\\CaptureNode' => $vendorDir . '/latte/latte/src/Latte/Essential/Nodes/CaptureNode.php', + 'Latte\\Essential\\Nodes\\ContentTypeNode' => $vendorDir . '/latte/latte/src/Latte/Essential/Nodes/ContentTypeNode.php', + 'Latte\\Essential\\Nodes\\CustomFunctionCallNode' => $vendorDir . '/latte/latte/src/Latte/Essential/Nodes/CustomFunctionCallNode.php', + 'Latte\\Essential\\Nodes\\DebugbreakNode' => $vendorDir . '/latte/latte/src/Latte/Essential/Nodes/DebugbreakNode.php', + 'Latte\\Essential\\Nodes\\DefineNode' => $vendorDir . '/latte/latte/src/Latte/Essential/Nodes/DefineNode.php', + 'Latte\\Essential\\Nodes\\DoNode' => $vendorDir . '/latte/latte/src/Latte/Essential/Nodes/DoNode.php', + 'Latte\\Essential\\Nodes\\DumpNode' => $vendorDir . '/latte/latte/src/Latte/Essential/Nodes/DumpNode.php', + 'Latte\\Essential\\Nodes\\EmbedNode' => $vendorDir . '/latte/latte/src/Latte/Essential/Nodes/EmbedNode.php', + 'Latte\\Essential\\Nodes\\ExtendsNode' => $vendorDir . '/latte/latte/src/Latte/Essential/Nodes/ExtendsNode.php', + 'Latte\\Essential\\Nodes\\FirstLastSepNode' => $vendorDir . '/latte/latte/src/Latte/Essential/Nodes/FirstLastSepNode.php', + 'Latte\\Essential\\Nodes\\ForNode' => $vendorDir . '/latte/latte/src/Latte/Essential/Nodes/ForNode.php', + 'Latte\\Essential\\Nodes\\ForeachNode' => $vendorDir . '/latte/latte/src/Latte/Essential/Nodes/ForeachNode.php', + 'Latte\\Essential\\Nodes\\IfChangedNode' => $vendorDir . '/latte/latte/src/Latte/Essential/Nodes/IfChangedNode.php', + 'Latte\\Essential\\Nodes\\IfContentNode' => $vendorDir . '/latte/latte/src/Latte/Essential/Nodes/IfContentNode.php', + 'Latte\\Essential\\Nodes\\IfNode' => $vendorDir . '/latte/latte/src/Latte/Essential/Nodes/IfNode.php', + 'Latte\\Essential\\Nodes\\ImportNode' => $vendorDir . '/latte/latte/src/Latte/Essential/Nodes/ImportNode.php', + 'Latte\\Essential\\Nodes\\IncludeBlockNode' => $vendorDir . '/latte/latte/src/Latte/Essential/Nodes/IncludeBlockNode.php', + 'Latte\\Essential\\Nodes\\IncludeFileNode' => $vendorDir . '/latte/latte/src/Latte/Essential/Nodes/IncludeFileNode.php', + 'Latte\\Essential\\Nodes\\IterateWhileNode' => $vendorDir . '/latte/latte/src/Latte/Essential/Nodes/IterateWhileNode.php', + 'Latte\\Essential\\Nodes\\JumpNode' => $vendorDir . '/latte/latte/src/Latte/Essential/Nodes/JumpNode.php', + 'Latte\\Essential\\Nodes\\NAttrNode' => $vendorDir . '/latte/latte/src/Latte/Essential/Nodes/NAttrNode.php', + 'Latte\\Essential\\Nodes\\NClassNode' => $vendorDir . '/latte/latte/src/Latte/Essential/Nodes/NClassNode.php', + 'Latte\\Essential\\Nodes\\NElseNode' => $vendorDir . '/latte/latte/src/Latte/Essential/Nodes/NElseNode.php', + 'Latte\\Essential\\Nodes\\NTagNode' => $vendorDir . '/latte/latte/src/Latte/Essential/Nodes/NTagNode.php', + 'Latte\\Essential\\Nodes\\ParametersNode' => $vendorDir . '/latte/latte/src/Latte/Essential/Nodes/ParametersNode.php', + 'Latte\\Essential\\Nodes\\RawPhpNode' => $vendorDir . '/latte/latte/src/Latte/Essential/Nodes/RawPhpNode.php', + 'Latte\\Essential\\Nodes\\RollbackNode' => $vendorDir . '/latte/latte/src/Latte/Essential/Nodes/RollbackNode.php', + 'Latte\\Essential\\Nodes\\SpacelessNode' => $vendorDir . '/latte/latte/src/Latte/Essential/Nodes/SpacelessNode.php', + 'Latte\\Essential\\Nodes\\SwitchNode' => $vendorDir . '/latte/latte/src/Latte/Essential/Nodes/SwitchNode.php', + 'Latte\\Essential\\Nodes\\TemplatePrintNode' => $vendorDir . '/latte/latte/src/Latte/Essential/Nodes/TemplatePrintNode.php', + 'Latte\\Essential\\Nodes\\TemplateTypeNode' => $vendorDir . '/latte/latte/src/Latte/Essential/Nodes/TemplateTypeNode.php', + 'Latte\\Essential\\Nodes\\TraceNode' => $vendorDir . '/latte/latte/src/Latte/Essential/Nodes/TraceNode.php', + 'Latte\\Essential\\Nodes\\TranslateNode' => $vendorDir . '/latte/latte/src/Latte/Essential/Nodes/TranslateNode.php', + 'Latte\\Essential\\Nodes\\TryNode' => $vendorDir . '/latte/latte/src/Latte/Essential/Nodes/TryNode.php', + 'Latte\\Essential\\Nodes\\VarNode' => $vendorDir . '/latte/latte/src/Latte/Essential/Nodes/VarNode.php', + 'Latte\\Essential\\Nodes\\VarPrintNode' => $vendorDir . '/latte/latte/src/Latte/Essential/Nodes/VarPrintNode.php', + 'Latte\\Essential\\Nodes\\VarTypeNode' => $vendorDir . '/latte/latte/src/Latte/Essential/Nodes/VarTypeNode.php', + 'Latte\\Essential\\Nodes\\WhileNode' => $vendorDir . '/latte/latte/src/Latte/Essential/Nodes/WhileNode.php', + 'Latte\\Essential\\Passes' => $vendorDir . '/latte/latte/src/Latte/Essential/Passes.php', + 'Latte\\Essential\\RawPhpExtension' => $vendorDir . '/latte/latte/src/Latte/Essential/RawPhpExtension.php', + 'Latte\\Essential\\RollbackException' => $vendorDir . '/latte/latte/src/Latte/Essential/RollbackException.php', + 'Latte\\Essential\\Tracer' => $vendorDir . '/latte/latte/src/Latte/Essential/Tracer.php', + 'Latte\\Essential\\TranslatorExtension' => $vendorDir . '/latte/latte/src/Latte/Essential/TranslatorExtension.php', + 'Latte\\Exception' => $vendorDir . '/latte/latte/src/Latte/exceptions.php', + 'Latte\\Extension' => $vendorDir . '/latte/latte/src/Latte/Extension.php', + 'Latte\\Helpers' => $vendorDir . '/latte/latte/src/Latte/Helpers.php', + 'Latte\\Loader' => $vendorDir . '/latte/latte/src/Latte/Loader.php', + 'Latte\\Loaders\\FileLoader' => $vendorDir . '/latte/latte/src/Latte/Loaders/FileLoader.php', + 'Latte\\Loaders\\StringLoader' => $vendorDir . '/latte/latte/src/Latte/Loaders/StringLoader.php', + 'Latte\\Policy' => $vendorDir . '/latte/latte/src/Latte/Policy.php', + 'Latte\\PositionAwareException' => $vendorDir . '/latte/latte/src/Latte/PositionAwareException.php', + 'Latte\\RuntimeException' => $vendorDir . '/latte/latte/src/Latte/exceptions.php', + 'Latte\\Runtime\\Block' => $vendorDir . '/latte/latte/src/Latte/Runtime/Block.php', + 'Latte\\Runtime\\FilterExecutor' => $vendorDir . '/latte/latte/src/Latte/Runtime/FilterExecutor.php', + 'Latte\\Runtime\\FilterInfo' => $vendorDir . '/latte/latte/src/Latte/Runtime/FilterInfo.php', + 'Latte\\Runtime\\FunctionExecutor' => $vendorDir . '/latte/latte/src/Latte/Runtime/FunctionExecutor.php', + 'Latte\\Runtime\\Helpers' => $vendorDir . '/latte/latte/src/Latte/Runtime/Helpers.php', + 'Latte\\Runtime\\Html' => $vendorDir . '/latte/latte/src/Latte/Runtime/Html.php', + 'Latte\\Runtime\\HtmlHelpers' => $vendorDir . '/latte/latte/src/Latte/Runtime/HtmlHelpers.php', + 'Latte\\Runtime\\HtmlStringable' => $vendorDir . '/latte/latte/src/Latte/Runtime/HtmlStringable.php', + 'Latte\\Runtime\\Template' => $vendorDir . '/latte/latte/src/Latte/Runtime/Template.php', + 'Latte\\Runtime\\XmlHelpers' => $vendorDir . '/latte/latte/src/Latte/Runtime/XmlHelpers.php', + 'Latte\\Sandbox\\Nodes\\FunctionCallNode' => $vendorDir . '/latte/latte/src/Latte/Sandbox/Nodes/FunctionCallNode.php', + 'Latte\\Sandbox\\Nodes\\MethodCallNode' => $vendorDir . '/latte/latte/src/Latte/Sandbox/Nodes/MethodCallNode.php', + 'Latte\\Sandbox\\Nodes\\PropertyFetchNode' => $vendorDir . '/latte/latte/src/Latte/Sandbox/Nodes/PropertyFetchNode.php', + 'Latte\\Sandbox\\Nodes\\SandboxNode' => $vendorDir . '/latte/latte/src/Latte/Sandbox/Nodes/SandboxNode.php', + 'Latte\\Sandbox\\Nodes\\StaticMethodCallNode' => $vendorDir . '/latte/latte/src/Latte/Sandbox/Nodes/StaticMethodCallNode.php', + 'Latte\\Sandbox\\Nodes\\StaticPropertyFetchNode' => $vendorDir . '/latte/latte/src/Latte/Sandbox/Nodes/StaticPropertyFetchNode.php', + 'Latte\\Sandbox\\RuntimeChecker' => $vendorDir . '/latte/latte/src/Latte/Sandbox/RuntimeChecker.php', + 'Latte\\Sandbox\\SandboxExtension' => $vendorDir . '/latte/latte/src/Latte/Sandbox/SandboxExtension.php', + 'Latte\\Sandbox\\SecurityPolicy' => $vendorDir . '/latte/latte/src/Latte/Sandbox/SecurityPolicy.php', + 'Latte\\SecurityViolationException' => $vendorDir . '/latte/latte/src/Latte/exceptions.php', + 'Latte\\TemplateNotFoundException' => $vendorDir . '/latte/latte/src/Latte/exceptions.php', + 'Latte\\Tools\\Linter' => $vendorDir . '/latte/latte/src/Tools/Linter.php', + 'Latte\\Tools\\LinterExtension' => $vendorDir . '/latte/latte/src/Tools/LinterExtension.php', + 'NetteModule\\ErrorPresenter' => $vendorDir . '/nette/application/src/Application/ErrorPresenter.php', + 'NetteModule\\MicroPresenter' => $vendorDir . '/nette/application/src/Application/MicroPresenter.php', + 'Nette\\Application\\AbortException' => $vendorDir . '/nette/application/src/Application/exceptions.php', + 'Nette\\Application\\Application' => $vendorDir . '/nette/application/src/Application/Application.php', + 'Nette\\Application\\ApplicationException' => $vendorDir . '/nette/application/src/Application/exceptions.php', + 'Nette\\Application\\Attributes\\CrossOrigin' => $vendorDir . '/nette/application/src/Application/Attributes/CrossOrigin.php', + 'Nette\\Application\\Attributes\\Deprecated' => $vendorDir . '/nette/application/src/Application/Attributes/Deprecated.php', + 'Nette\\Application\\Attributes\\Parameter' => $vendorDir . '/nette/application/src/Application/Attributes/Parameter.php', + 'Nette\\Application\\Attributes\\Persistent' => $vendorDir . '/nette/application/src/Application/Attributes/Persistent.php', + 'Nette\\Application\\Attributes\\Requires' => $vendorDir . '/nette/application/src/Application/Attributes/Requires.php', + 'Nette\\Application\\Attributes\\TemplateVariable' => $vendorDir . '/nette/application/src/Application/Attributes/TemplateVariable.php', + 'Nette\\Application\\BadRequestException' => $vendorDir . '/nette/application/src/Application/exceptions.php', + 'Nette\\Application\\ForbiddenRequestException' => $vendorDir . '/nette/application/src/Application/exceptions.php', + 'Nette\\Application\\Helpers' => $vendorDir . '/nette/application/src/Application/Helpers.php', + 'Nette\\Application\\IPresenter' => $vendorDir . '/nette/application/src/Application/IPresenter.php', + 'Nette\\Application\\IPresenterFactory' => $vendorDir . '/nette/application/src/Application/IPresenterFactory.php', + 'Nette\\Application\\IResponse' => $vendorDir . '/nette/application/src/compatibility-intf.php', + 'Nette\\Application\\IRouter' => $vendorDir . '/nette/application/src/compatibility-intf.php', + 'Nette\\Application\\InvalidPresenterException' => $vendorDir . '/nette/application/src/Application/exceptions.php', + 'Nette\\Application\\LinkGenerator' => $vendorDir . '/nette/application/src/Application/LinkGenerator.php', + 'Nette\\Application\\PresenterFactory' => $vendorDir . '/nette/application/src/Application/PresenterFactory.php', + 'Nette\\Application\\Request' => $vendorDir . '/nette/application/src/Application/Request.php', + 'Nette\\Application\\Response' => $vendorDir . '/nette/application/src/Application/Response.php', + 'Nette\\Application\\Responses\\CallbackResponse' => $vendorDir . '/nette/application/src/Application/Responses/CallbackResponse.php', + 'Nette\\Application\\Responses\\FileResponse' => $vendorDir . '/nette/application/src/Application/Responses/FileResponse.php', + 'Nette\\Application\\Responses\\ForwardResponse' => $vendorDir . '/nette/application/src/Application/Responses/ForwardResponse.php', + 'Nette\\Application\\Responses\\JsonResponse' => $vendorDir . '/nette/application/src/Application/Responses/JsonResponse.php', + 'Nette\\Application\\Responses\\RedirectResponse' => $vendorDir . '/nette/application/src/Application/Responses/RedirectResponse.php', + 'Nette\\Application\\Responses\\TextResponse' => $vendorDir . '/nette/application/src/Application/Responses/TextResponse.php', + 'Nette\\Application\\Responses\\VoidResponse' => $vendorDir . '/nette/application/src/Application/Responses/VoidResponse.php', + 'Nette\\Application\\Routers\\CliRouter' => $vendorDir . '/nette/application/src/Application/Routers/CliRouter.php', + 'Nette\\Application\\Routers\\Route' => $vendorDir . '/nette/application/src/Application/Routers/Route.php', + 'Nette\\Application\\Routers\\RouteList' => $vendorDir . '/nette/application/src/Application/Routers/RouteList.php', + 'Nette\\Application\\Routers\\SimpleRouter' => $vendorDir . '/nette/application/src/Application/Routers/SimpleRouter.php', + 'Nette\\Application\\SwitchException' => $vendorDir . '/nette/application/src/Application/exceptions.php', + 'Nette\\Application\\UI\\AccessPolicy' => $vendorDir . '/nette/application/src/Application/UI/AccessPolicy.php', + 'Nette\\Application\\UI\\BadSignalException' => $vendorDir . '/nette/application/src/Application/UI/BadSignalException.php', + 'Nette\\Application\\UI\\Component' => $vendorDir . '/nette/application/src/Application/UI/Component.php', + 'Nette\\Application\\UI\\ComponentReflection' => $vendorDir . '/nette/application/src/Application/UI/ComponentReflection.php', + 'Nette\\Application\\UI\\Control' => $vendorDir . '/nette/application/src/Application/UI/Control.php', + 'Nette\\Application\\UI\\Form' => $vendorDir . '/nette/application/src/Application/UI/Form.php', + 'Nette\\Application\\UI\\IRenderable' => $vendorDir . '/nette/application/src/compatibility-intf.php', + 'Nette\\Application\\UI\\ISignalReceiver' => $vendorDir . '/nette/application/src/compatibility-intf.php', + 'Nette\\Application\\UI\\IStatePersistent' => $vendorDir . '/nette/application/src/compatibility-intf.php', + 'Nette\\Application\\UI\\ITemplate' => $vendorDir . '/nette/application/src/compatibility-intf.php', + 'Nette\\Application\\UI\\ITemplateFactory' => $vendorDir . '/nette/application/src/compatibility-intf.php', + 'Nette\\Application\\UI\\InvalidLinkException' => $vendorDir . '/nette/application/src/Application/UI/InvalidLinkException.php', + 'Nette\\Application\\UI\\Link' => $vendorDir . '/nette/application/src/Application/UI/Link.php', + 'Nette\\Application\\UI\\MethodReflection' => $vendorDir . '/nette/application/src/Application/UI/MethodReflection.php', + 'Nette\\Application\\UI\\Multiplier' => $vendorDir . '/nette/application/src/Application/UI/Multiplier.php', + 'Nette\\Application\\UI\\ParameterConverter' => $vendorDir . '/nette/application/src/Application/UI/ParameterConverter.php', + 'Nette\\Application\\UI\\Presenter' => $vendorDir . '/nette/application/src/Application/UI/Presenter.php', + 'Nette\\Application\\UI\\PresenterComponent' => $vendorDir . '/nette/application/src/compatibility.php', + 'Nette\\Application\\UI\\PresenterComponentReflection' => $vendorDir . '/nette/application/src/compatibility.php', + 'Nette\\Application\\UI\\Renderable' => $vendorDir . '/nette/application/src/Application/UI/Renderable.php', + 'Nette\\Application\\UI\\SignalReceiver' => $vendorDir . '/nette/application/src/Application/UI/SignalReceiver.php', + 'Nette\\Application\\UI\\StatePersistent' => $vendorDir . '/nette/application/src/Application/UI/StatePersistent.php', + 'Nette\\Application\\UI\\Template' => $vendorDir . '/nette/application/src/Application/UI/Template.php', + 'Nette\\Application\\UI\\TemplateFactory' => $vendorDir . '/nette/application/src/Application/UI/TemplateFactory.php', + 'Nette\\ArgumentOutOfRangeException' => $vendorDir . '/nette/utils/src/exceptions.php', + 'Nette\\Assets\\Asset' => $vendorDir . '/nette/assets/src/Assets/Asset.php', + 'Nette\\Assets\\AssetNotFoundException' => $vendorDir . '/nette/assets/src/Assets/exceptions.php', + 'Nette\\Assets\\AudioAsset' => $vendorDir . '/nette/assets/src/Assets/AudioAsset.php', + 'Nette\\Assets\\EntryAsset' => $vendorDir . '/nette/assets/src/Assets/EntryAsset.php', + 'Nette\\Assets\\FilesystemMapper' => $vendorDir . '/nette/assets/src/Assets/FilesystemMapper.php', + 'Nette\\Assets\\FontAsset' => $vendorDir . '/nette/assets/src/Assets/FontAsset.php', + 'Nette\\Assets\\GenericAsset' => $vendorDir . '/nette/assets/src/Assets/GenericAsset.php', + 'Nette\\Assets\\Helpers' => $vendorDir . '/nette/assets/src/Assets/Helpers.php', + 'Nette\\Assets\\HtmlRenderable' => $vendorDir . '/nette/assets/src/Assets/HtmlRenderable.php', + 'Nette\\Assets\\ImageAsset' => $vendorDir . '/nette/assets/src/Assets/ImageAsset.php', + 'Nette\\Assets\\LazyLoad' => $vendorDir . '/nette/assets/src/Assets/LazyLoad.php', + 'Nette\\Assets\\Mapper' => $vendorDir . '/nette/assets/src/Assets/Mapper.php', + 'Nette\\Assets\\Registry' => $vendorDir . '/nette/assets/src/Assets/Registry.php', + 'Nette\\Assets\\ScriptAsset' => $vendorDir . '/nette/assets/src/Assets/ScriptAsset.php', + 'Nette\\Assets\\StyleAsset' => $vendorDir . '/nette/assets/src/Assets/StyleAsset.php', + 'Nette\\Assets\\VideoAsset' => $vendorDir . '/nette/assets/src/Assets/VideoAsset.php', + 'Nette\\Assets\\ViteMapper' => $vendorDir . '/nette/assets/src/Assets/ViteMapper.php', + 'Nette\\Bootstrap\\Configurator' => $vendorDir . '/nette/bootstrap/src/Bootstrap/Configurator.php', + 'Nette\\Bootstrap\\Extensions\\ConstantsExtension' => $vendorDir . '/nette/bootstrap/src/Bootstrap/Extensions/ConstantsExtension.php', + 'Nette\\Bootstrap\\Extensions\\PhpExtension' => $vendorDir . '/nette/bootstrap/src/Bootstrap/Extensions/PhpExtension.php', + 'Nette\\Bridges\\ApplicationDI\\ApplicationExtension' => $vendorDir . '/nette/application/src/Bridges/ApplicationDI/ApplicationExtension.php', + 'Nette\\Bridges\\ApplicationDI\\LatteExtension' => $vendorDir . '/nette/application/src/Bridges/ApplicationDI/LatteExtension.php', + 'Nette\\Bridges\\ApplicationDI\\PresenterFactoryCallback' => $vendorDir . '/nette/application/src/Bridges/ApplicationDI/PresenterFactoryCallback.php', + 'Nette\\Bridges\\ApplicationDI\\RoutingExtension' => $vendorDir . '/nette/application/src/Bridges/ApplicationDI/RoutingExtension.php', + 'Nette\\Bridges\\ApplicationLatte\\DefaultTemplate' => $vendorDir . '/nette/application/src/Bridges/ApplicationLatte/DefaultTemplate.php', + 'Nette\\Bridges\\ApplicationLatte\\ILatteFactory' => $vendorDir . '/nette/application/src/compatibility-intf.php', + 'Nette\\Bridges\\ApplicationLatte\\LatteFactory' => $vendorDir . '/nette/application/src/Bridges/ApplicationLatte/LatteFactory.php', + 'Nette\\Bridges\\ApplicationLatte\\Nodes\\ControlNode' => $vendorDir . '/nette/application/src/Bridges/ApplicationLatte/Nodes/ControlNode.php', + 'Nette\\Bridges\\ApplicationLatte\\Nodes\\IfCurrentNode' => $vendorDir . '/nette/application/src/Bridges/ApplicationLatte/Nodes/IfCurrentNode.php', + 'Nette\\Bridges\\ApplicationLatte\\Nodes\\LinkBaseNode' => $vendorDir . '/nette/application/src/Bridges/ApplicationLatte/Nodes/LinkBaseNode.php', + 'Nette\\Bridges\\ApplicationLatte\\Nodes\\LinkNode' => $vendorDir . '/nette/application/src/Bridges/ApplicationLatte/Nodes/LinkNode.php', + 'Nette\\Bridges\\ApplicationLatte\\Nodes\\NNonceNode' => $vendorDir . '/nette/application/src/Bridges/ApplicationLatte/Nodes/NNonceNode.php', + 'Nette\\Bridges\\ApplicationLatte\\Nodes\\SnippetAreaNode' => $vendorDir . '/nette/application/src/Bridges/ApplicationLatte/Nodes/SnippetAreaNode.php', + 'Nette\\Bridges\\ApplicationLatte\\Nodes\\SnippetNode' => $vendorDir . '/nette/application/src/Bridges/ApplicationLatte/Nodes/SnippetNode.php', + 'Nette\\Bridges\\ApplicationLatte\\Nodes\\TemplatePrintNode' => $vendorDir . '/nette/application/src/Bridges/ApplicationLatte/Nodes/TemplatePrintNode.php', + 'Nette\\Bridges\\ApplicationLatte\\SnippetBridge' => $vendorDir . '/nette/application/src/Bridges/ApplicationLatte/SnippetBridge.php', + 'Nette\\Bridges\\ApplicationLatte\\SnippetRuntime' => $vendorDir . '/nette/application/src/Bridges/ApplicationLatte/SnippetRuntime.php', + 'Nette\\Bridges\\ApplicationLatte\\Template' => $vendorDir . '/nette/application/src/Bridges/ApplicationLatte/Template.php', + 'Nette\\Bridges\\ApplicationLatte\\TemplateFactory' => $vendorDir . '/nette/application/src/Bridges/ApplicationLatte/TemplateFactory.php', + 'Nette\\Bridges\\ApplicationLatte\\UIExtension' => $vendorDir . '/nette/application/src/Bridges/ApplicationLatte/UIExtension.php', + 'Nette\\Bridges\\ApplicationLatte\\UIMacros' => $vendorDir . '/nette/application/src/Bridges/ApplicationLatte/UIMacros.php', + 'Nette\\Bridges\\ApplicationLatte\\UIRuntime' => $vendorDir . '/nette/application/src/Bridges/ApplicationLatte/UIRuntime.php', + 'Nette\\Bridges\\ApplicationTracy\\RoutingPanel' => $vendorDir . '/nette/application/src/Bridges/ApplicationTracy/RoutingPanel.php', + 'Nette\\Bridges\\AssetsDI\\DIExtension' => $vendorDir . '/nette/assets/src/Bridges/AssetsDI/DIExtension.php', + 'Nette\\Bridges\\AssetsLatte\\LatteExtension' => $vendorDir . '/nette/assets/src/Bridges/AssetsLatte/LatteExtension.php', + 'Nette\\Bridges\\AssetsLatte\\Nodes\\AssetNode' => $vendorDir . '/nette/assets/src/Bridges/AssetsLatte/Nodes/AssetNode.php', + 'Nette\\Bridges\\AssetsLatte\\Nodes\\NAssetNode' => $vendorDir . '/nette/assets/src/Bridges/AssetsLatte/Nodes/NAssetNode.php', + 'Nette\\Bridges\\AssetsLatte\\Runtime' => $vendorDir . '/nette/assets/src/Bridges/AssetsLatte/Runtime.php', + 'Nette\\Bridges\\CacheDI\\CacheExtension' => $vendorDir . '/nette/caching/src/Bridges/CacheDI/CacheExtension.php', + 'Nette\\Bridges\\CacheLatte\\CacheExtension' => $vendorDir . '/nette/caching/src/Bridges/CacheLatte/CacheExtension.php', + 'Nette\\Bridges\\CacheLatte\\Nodes\\CacheNode' => $vendorDir . '/nette/caching/src/Bridges/CacheLatte/Nodes/CacheNode.php', + 'Nette\\Bridges\\CacheLatte\\Runtime' => $vendorDir . '/nette/caching/src/Bridges/CacheLatte/Runtime.php', + 'Nette\\Bridges\\DITracy\\ContainerPanel' => $vendorDir . '/nette/di/src/Bridges/DITracy/ContainerPanel.php', + 'Nette\\Bridges\\DatabaseDI\\DatabaseExtension' => $vendorDir . '/nette/database/src/Bridges/DatabaseDI/DatabaseExtension.php', + 'Nette\\Bridges\\DatabaseTracy\\ConnectionPanel' => $vendorDir . '/nette/database/src/Bridges/DatabaseTracy/ConnectionPanel.php', + 'Nette\\Bridges\\FormsDI\\FormsExtension' => $vendorDir . '/nette/forms/src/Bridges/FormsDI/FormsExtension.php', + 'Nette\\Bridges\\FormsLatte\\FormMacros' => $vendorDir . '/nette/forms/src/Bridges/FormsLatte/FormMacros.php', + 'Nette\\Bridges\\FormsLatte\\FormsExtension' => $vendorDir . '/nette/forms/src/Bridges/FormsLatte/FormsExtension.php', + 'Nette\\Bridges\\FormsLatte\\Nodes\\FieldNNameNode' => $vendorDir . '/nette/forms/src/Bridges/FormsLatte/Nodes/FieldNNameNode.php', + 'Nette\\Bridges\\FormsLatte\\Nodes\\FormContainerNode' => $vendorDir . '/nette/forms/src/Bridges/FormsLatte/Nodes/FormContainerNode.php', + 'Nette\\Bridges\\FormsLatte\\Nodes\\FormNNameNode' => $vendorDir . '/nette/forms/src/Bridges/FormsLatte/Nodes/FormNNameNode.php', + 'Nette\\Bridges\\FormsLatte\\Nodes\\FormNode' => $vendorDir . '/nette/forms/src/Bridges/FormsLatte/Nodes/FormNode.php', + 'Nette\\Bridges\\FormsLatte\\Nodes\\FormPrintNode' => $vendorDir . '/nette/forms/src/Bridges/FormsLatte/Nodes/FormPrintNode.php', + 'Nette\\Bridges\\FormsLatte\\Nodes\\InputErrorNode' => $vendorDir . '/nette/forms/src/Bridges/FormsLatte/Nodes/InputErrorNode.php', + 'Nette\\Bridges\\FormsLatte\\Nodes\\InputNode' => $vendorDir . '/nette/forms/src/Bridges/FormsLatte/Nodes/InputNode.php', + 'Nette\\Bridges\\FormsLatte\\Nodes\\LabelNode' => $vendorDir . '/nette/forms/src/Bridges/FormsLatte/Nodes/LabelNode.php', + 'Nette\\Bridges\\FormsLatte\\Runtime' => $vendorDir . '/nette/forms/src/Bridges/FormsLatte/Runtime.php', + 'Nette\\Bridges\\HttpDI\\HttpExtension' => $vendorDir . '/nette/http/src/Bridges/HttpDI/HttpExtension.php', + 'Nette\\Bridges\\HttpDI\\SessionExtension' => $vendorDir . '/nette/http/src/Bridges/HttpDI/SessionExtension.php', + 'Nette\\Bridges\\HttpTracy\\SessionPanel' => $vendorDir . '/nette/http/src/Bridges/HttpTracy/SessionPanel.php', + 'Nette\\Bridges\\MailDI\\MailExtension' => $vendorDir . '/nette/mail/src/Bridges/MailDI/MailExtension.php', + 'Nette\\Bridges\\Psr\\PsrCacheAdapter' => $vendorDir . '/nette/caching/src/Bridges/Psr/PsrCacheAdapter.php', + 'Nette\\Bridges\\SecurityDI\\SecurityExtension' => $vendorDir . '/nette/security/src/Bridges/SecurityDI/SecurityExtension.php', + 'Nette\\Bridges\\SecurityHttp\\CookieStorage' => $vendorDir . '/nette/security/src/Bridges/SecurityHttp/CookieStorage.php', + 'Nette\\Bridges\\SecurityHttp\\SessionStorage' => $vendorDir . '/nette/security/src/Bridges/SecurityHttp/SessionStorage.php', + 'Nette\\Bridges\\SecurityTracy\\UserPanel' => $vendorDir . '/nette/security/src/Bridges/SecurityTracy/UserPanel.php', + 'Nette\\Caching\\BulkReader' => $vendorDir . '/nette/caching/src/Caching/BulkReader.php', + 'Nette\\Caching\\BulkWriter' => $vendorDir . '/nette/caching/src/Caching/BulkWriter.php', + 'Nette\\Caching\\Cache' => $vendorDir . '/nette/caching/src/Caching/Cache.php', + 'Nette\\Caching\\IBulkReader' => $vendorDir . '/nette/caching/src/compatibility.php', + 'Nette\\Caching\\IStorage' => $vendorDir . '/nette/caching/src/compatibility.php', + 'Nette\\Caching\\OutputHelper' => $vendorDir . '/nette/caching/src/Caching/OutputHelper.php', + 'Nette\\Caching\\Storage' => $vendorDir . '/nette/caching/src/Caching/Storage.php', + 'Nette\\Caching\\Storages\\DevNullStorage' => $vendorDir . '/nette/caching/src/Caching/Storages/DevNullStorage.php', + 'Nette\\Caching\\Storages\\FileStorage' => $vendorDir . '/nette/caching/src/Caching/Storages/FileStorage.php', + 'Nette\\Caching\\Storages\\IJournal' => $vendorDir . '/nette/caching/src/compatibility.php', + 'Nette\\Caching\\Storages\\Journal' => $vendorDir . '/nette/caching/src/Caching/Storages/Journal.php', + 'Nette\\Caching\\Storages\\MemcachedStorage' => $vendorDir . '/nette/caching/src/Caching/Storages/MemcachedStorage.php', + 'Nette\\Caching\\Storages\\MemoryStorage' => $vendorDir . '/nette/caching/src/Caching/Storages/MemoryStorage.php', + 'Nette\\Caching\\Storages\\SQLiteJournal' => $vendorDir . '/nette/caching/src/Caching/Storages/SQLiteJournal.php', + 'Nette\\Caching\\Storages\\SQLiteStorage' => $vendorDir . '/nette/caching/src/Caching/Storages/SQLiteStorage.php', + 'Nette\\ComponentModel\\ArrayAccess' => $vendorDir . '/nette/component-model/src/ComponentModel/ArrayAccess.php', + 'Nette\\ComponentModel\\Component' => $vendorDir . '/nette/component-model/src/ComponentModel/Component.php', + 'Nette\\ComponentModel\\Container' => $vendorDir . '/nette/component-model/src/ComponentModel/Container.php', + 'Nette\\ComponentModel\\IComponent' => $vendorDir . '/nette/component-model/src/ComponentModel/IComponent.php', + 'Nette\\ComponentModel\\IContainer' => $vendorDir . '/nette/component-model/src/ComponentModel/IContainer.php', + 'Nette\\ComponentModel\\RecursiveComponentIterator' => $vendorDir . '/nette/component-model/src/ComponentModel/RecursiveComponentIterator.php', + 'Nette\\Configurator' => $vendorDir . '/nette/bootstrap/src/Configurator.php', + 'Nette\\DI\\Attributes\\Inject' => $vendorDir . '/nette/di/src/DI/Attributes/Inject.php', + 'Nette\\DI\\Autowiring' => $vendorDir . '/nette/di/src/DI/Autowiring.php', + 'Nette\\DI\\Compiler' => $vendorDir . '/nette/di/src/DI/Compiler.php', + 'Nette\\DI\\CompilerExtension' => $vendorDir . '/nette/di/src/DI/CompilerExtension.php', + 'Nette\\DI\\Config\\Adapter' => $vendorDir . '/nette/di/src/DI/Config/Adapter.php', + 'Nette\\DI\\Config\\Adapters\\NeonAdapter' => $vendorDir . '/nette/di/src/DI/Config/Adapters/NeonAdapter.php', + 'Nette\\DI\\Config\\Adapters\\PhpAdapter' => $vendorDir . '/nette/di/src/DI/Config/Adapters/PhpAdapter.php', + 'Nette\\DI\\Config\\Helpers' => $vendorDir . '/nette/di/src/DI/Config/Helpers.php', + 'Nette\\DI\\Config\\IAdapter' => $vendorDir . '/nette/di/src/compatibility.php', + 'Nette\\DI\\Config\\Loader' => $vendorDir . '/nette/di/src/DI/Config/Loader.php', + 'Nette\\DI\\Container' => $vendorDir . '/nette/di/src/DI/Container.php', + 'Nette\\DI\\ContainerBuilder' => $vendorDir . '/nette/di/src/DI/ContainerBuilder.php', + 'Nette\\DI\\ContainerLoader' => $vendorDir . '/nette/di/src/DI/ContainerLoader.php', + 'Nette\\DI\\Definitions\\AccessorDefinition' => $vendorDir . '/nette/di/src/DI/Definitions/AccessorDefinition.php', + 'Nette\\DI\\Definitions\\Definition' => $vendorDir . '/nette/di/src/DI/Definitions/Definition.php', + 'Nette\\DI\\Definitions\\FactoryDefinition' => $vendorDir . '/nette/di/src/DI/Definitions/FactoryDefinition.php', + 'Nette\\DI\\Definitions\\ImportedDefinition' => $vendorDir . '/nette/di/src/DI/Definitions/ImportedDefinition.php', + 'Nette\\DI\\Definitions\\LocatorDefinition' => $vendorDir . '/nette/di/src/DI/Definitions/LocatorDefinition.php', + 'Nette\\DI\\Definitions\\Reference' => $vendorDir . '/nette/di/src/DI/Definitions/Reference.php', + 'Nette\\DI\\Definitions\\ServiceDefinition' => $vendorDir . '/nette/di/src/DI/Definitions/ServiceDefinition.php', + 'Nette\\DI\\Definitions\\Statement' => $vendorDir . '/nette/di/src/DI/Definitions/Statement.php', + 'Nette\\DI\\DependencyChecker' => $vendorDir . '/nette/di/src/DI/DependencyChecker.php', + 'Nette\\DI\\DynamicParameter' => $vendorDir . '/nette/di/src/DI/DynamicParameter.php', + 'Nette\\DI\\Extensions\\DIExtension' => $vendorDir . '/nette/di/src/DI/Extensions/DIExtension.php', + 'Nette\\DI\\Extensions\\DecoratorExtension' => $vendorDir . '/nette/di/src/DI/Extensions/DecoratorExtension.php', + 'Nette\\DI\\Extensions\\DefinitionSchema' => $vendorDir . '/nette/di/src/DI/Extensions/DefinitionSchema.php', + 'Nette\\DI\\Extensions\\ExtensionsExtension' => $vendorDir . '/nette/di/src/DI/Extensions/ExtensionsExtension.php', + 'Nette\\DI\\Extensions\\InjectExtension' => $vendorDir . '/nette/di/src/DI/Extensions/InjectExtension.php', + 'Nette\\DI\\Extensions\\ParametersExtension' => $vendorDir . '/nette/di/src/DI/Extensions/ParametersExtension.php', + 'Nette\\DI\\Extensions\\SearchExtension' => $vendorDir . '/nette/di/src/DI/Extensions/SearchExtension.php', + 'Nette\\DI\\Extensions\\ServicesExtension' => $vendorDir . '/nette/di/src/DI/Extensions/ServicesExtension.php', + 'Nette\\DI\\Helpers' => $vendorDir . '/nette/di/src/DI/Helpers.php', + 'Nette\\DI\\InvalidConfigurationException' => $vendorDir . '/nette/di/src/DI/exceptions.php', + 'Nette\\DI\\MissingServiceException' => $vendorDir . '/nette/di/src/DI/exceptions.php', + 'Nette\\DI\\NotAllowedDuringResolvingException' => $vendorDir . '/nette/di/src/DI/exceptions.php', + 'Nette\\DI\\PhpGenerator' => $vendorDir . '/nette/di/src/DI/PhpGenerator.php', + 'Nette\\DI\\Resolver' => $vendorDir . '/nette/di/src/DI/Resolver.php', + 'Nette\\DI\\ServiceCreationException' => $vendorDir . '/nette/di/src/DI/exceptions.php', + 'Nette\\DI\\ServiceDefinition' => $vendorDir . '/nette/di/src/compatibility.php', + 'Nette\\DI\\Statement' => $vendorDir . '/nette/di/src/compatibility.php', + 'Nette\\Database\\Connection' => $vendorDir . '/nette/database/src/Database/Connection.php', + 'Nette\\Database\\ConnectionException' => $vendorDir . '/nette/database/src/Database/exceptions.php', + 'Nette\\Database\\ConstraintViolationException' => $vendorDir . '/nette/database/src/Database/exceptions.php', + 'Nette\\Database\\Context' => $vendorDir . '/nette/database/src/compatibility.php', + 'Nette\\Database\\Conventions' => $vendorDir . '/nette/database/src/Database/Conventions.php', + 'Nette\\Database\\Conventions\\AmbiguousReferenceKeyException' => $vendorDir . '/nette/database/src/Database/Conventions/AmbiguousReferenceKeyException.php', + 'Nette\\Database\\Conventions\\DiscoveredConventions' => $vendorDir . '/nette/database/src/Database/Conventions/DiscoveredConventions.php', + 'Nette\\Database\\Conventions\\StaticConventions' => $vendorDir . '/nette/database/src/Database/Conventions/StaticConventions.php', + 'Nette\\Database\\DateTime' => $vendorDir . '/nette/database/src/Database/DateTime.php', + 'Nette\\Database\\Driver' => $vendorDir . '/nette/database/src/Database/Driver.php', + 'Nette\\Database\\DriverException' => $vendorDir . '/nette/database/src/Database/DriverException.php', + 'Nette\\Database\\Drivers\\MsSqlDriver' => $vendorDir . '/nette/database/src/Database/Drivers/MsSqlDriver.php', + 'Nette\\Database\\Drivers\\MySqlDriver' => $vendorDir . '/nette/database/src/Database/Drivers/MySqlDriver.php', + 'Nette\\Database\\Drivers\\OciDriver' => $vendorDir . '/nette/database/src/Database/Drivers/OciDriver.php', + 'Nette\\Database\\Drivers\\OdbcDriver' => $vendorDir . '/nette/database/src/Database/Drivers/OdbcDriver.php', + 'Nette\\Database\\Drivers\\PgSqlDriver' => $vendorDir . '/nette/database/src/Database/Drivers/PgSqlDriver.php', + 'Nette\\Database\\Drivers\\SqliteDriver' => $vendorDir . '/nette/database/src/Database/Drivers/SqliteDriver.php', + 'Nette\\Database\\Drivers\\SqlsrvDriver' => $vendorDir . '/nette/database/src/Database/Drivers/SqlsrvDriver.php', + 'Nette\\Database\\Explorer' => $vendorDir . '/nette/database/src/Database/Explorer.php', + 'Nette\\Database\\ForeignKeyConstraintViolationException' => $vendorDir . '/nette/database/src/Database/exceptions.php', + 'Nette\\Database\\Helpers' => $vendorDir . '/nette/database/src/Database/Helpers.php', + 'Nette\\Database\\IConventions' => $vendorDir . '/nette/database/src/compatibility-intf.php', + 'Nette\\Database\\IRow' => $vendorDir . '/nette/database/src/Database/IRow.php', + 'Nette\\Database\\IRowContainer' => $vendorDir . '/nette/database/src/Database/IRowContainer.php', + 'Nette\\Database\\IStructure' => $vendorDir . '/nette/database/src/Database/IStructure.php', + 'Nette\\Database\\ISupplementalDriver' => $vendorDir . '/nette/database/src/compatibility-intf.php', + 'Nette\\Database\\NotNullConstraintViolationException' => $vendorDir . '/nette/database/src/Database/exceptions.php', + 'Nette\\Database\\Reflection' => $vendorDir . '/nette/database/src/Database/Reflection.php', + 'Nette\\Database\\Reflection\\Column' => $vendorDir . '/nette/database/src/Database/Reflection/Column.php', + 'Nette\\Database\\Reflection\\ForeignKey' => $vendorDir . '/nette/database/src/Database/Reflection/ForeignKey.php', + 'Nette\\Database\\Reflection\\Index' => $vendorDir . '/nette/database/src/Database/Reflection/Index.php', + 'Nette\\Database\\Reflection\\Table' => $vendorDir . '/nette/database/src/Database/Reflection/Table.php', + 'Nette\\Database\\ResultSet' => $vendorDir . '/nette/database/src/Database/ResultSet.php', + 'Nette\\Database\\Row' => $vendorDir . '/nette/database/src/Database/Row.php', + 'Nette\\Database\\SqlLiteral' => $vendorDir . '/nette/database/src/Database/SqlLiteral.php', + 'Nette\\Database\\SqlPreprocessor' => $vendorDir . '/nette/database/src/Database/SqlPreprocessor.php', + 'Nette\\Database\\Structure' => $vendorDir . '/nette/database/src/Database/Structure.php', + 'Nette\\Database\\Table\\ActiveRow' => $vendorDir . '/nette/database/src/Database/Table/ActiveRow.php', + 'Nette\\Database\\Table\\GroupedSelection' => $vendorDir . '/nette/database/src/Database/Table/GroupedSelection.php', + 'Nette\\Database\\Table\\IRow' => $vendorDir . '/nette/database/src/Database/Table/IRow.php', + 'Nette\\Database\\Table\\IRowContainer' => $vendorDir . '/nette/database/src/Database/Table/IRowContainer.php', + 'Nette\\Database\\Table\\Selection' => $vendorDir . '/nette/database/src/Database/Table/Selection.php', + 'Nette\\Database\\Table\\SqlBuilder' => $vendorDir . '/nette/database/src/Database/Table/SqlBuilder.php', + 'Nette\\Database\\UniqueConstraintViolationException' => $vendorDir . '/nette/database/src/Database/exceptions.php', + 'Nette\\DeprecatedException' => $vendorDir . '/nette/utils/src/exceptions.php', + 'Nette\\DirectoryNotFoundException' => $vendorDir . '/nette/utils/src/exceptions.php', + 'Nette\\FileNotFoundException' => $vendorDir . '/nette/utils/src/exceptions.php', + 'Nette\\Forms\\Blueprint' => $vendorDir . '/nette/forms/src/Forms/Blueprint.php', + 'Nette\\Forms\\Container' => $vendorDir . '/nette/forms/src/Forms/Container.php', + 'Nette\\Forms\\Control' => $vendorDir . '/nette/forms/src/Forms/Control.php', + 'Nette\\Forms\\ControlGroup' => $vendorDir . '/nette/forms/src/Forms/ControlGroup.php', + 'Nette\\Forms\\Controls\\BaseControl' => $vendorDir . '/nette/forms/src/Forms/Controls/BaseControl.php', + 'Nette\\Forms\\Controls\\Button' => $vendorDir . '/nette/forms/src/Forms/Controls/Button.php', + 'Nette\\Forms\\Controls\\Checkbox' => $vendorDir . '/nette/forms/src/Forms/Controls/Checkbox.php', + 'Nette\\Forms\\Controls\\CheckboxList' => $vendorDir . '/nette/forms/src/Forms/Controls/CheckboxList.php', + 'Nette\\Forms\\Controls\\ChoiceControl' => $vendorDir . '/nette/forms/src/Forms/Controls/ChoiceControl.php', + 'Nette\\Forms\\Controls\\ColorPicker' => $vendorDir . '/nette/forms/src/Forms/Controls/ColorPicker.php', + 'Nette\\Forms\\Controls\\CsrfProtection' => $vendorDir . '/nette/forms/src/Forms/Controls/CsrfProtection.php', + 'Nette\\Forms\\Controls\\DateTimeControl' => $vendorDir . '/nette/forms/src/Forms/Controls/DateTimeControl.php', + 'Nette\\Forms\\Controls\\HiddenField' => $vendorDir . '/nette/forms/src/Forms/Controls/HiddenField.php', + 'Nette\\Forms\\Controls\\ImageButton' => $vendorDir . '/nette/forms/src/Forms/Controls/ImageButton.php', + 'Nette\\Forms\\Controls\\MultiChoiceControl' => $vendorDir . '/nette/forms/src/Forms/Controls/MultiChoiceControl.php', + 'Nette\\Forms\\Controls\\MultiSelectBox' => $vendorDir . '/nette/forms/src/Forms/Controls/MultiSelectBox.php', + 'Nette\\Forms\\Controls\\RadioList' => $vendorDir . '/nette/forms/src/Forms/Controls/RadioList.php', + 'Nette\\Forms\\Controls\\SelectBox' => $vendorDir . '/nette/forms/src/Forms/Controls/SelectBox.php', + 'Nette\\Forms\\Controls\\SubmitButton' => $vendorDir . '/nette/forms/src/Forms/Controls/SubmitButton.php', + 'Nette\\Forms\\Controls\\TextArea' => $vendorDir . '/nette/forms/src/Forms/Controls/TextArea.php', + 'Nette\\Forms\\Controls\\TextBase' => $vendorDir . '/nette/forms/src/Forms/Controls/TextBase.php', + 'Nette\\Forms\\Controls\\TextInput' => $vendorDir . '/nette/forms/src/Forms/Controls/TextInput.php', + 'Nette\\Forms\\Controls\\UploadControl' => $vendorDir . '/nette/forms/src/Forms/Controls/UploadControl.php', + 'Nette\\Forms\\Form' => $vendorDir . '/nette/forms/src/Forms/Form.php', + 'Nette\\Forms\\FormRenderer' => $vendorDir . '/nette/forms/src/Forms/FormRenderer.php', + 'Nette\\Forms\\Helpers' => $vendorDir . '/nette/forms/src/Forms/Helpers.php', + 'Nette\\Forms\\IControl' => $vendorDir . '/nette/forms/src/compatibility.php', + 'Nette\\Forms\\IFormRenderer' => $vendorDir . '/nette/forms/src/compatibility.php', + 'Nette\\Forms\\ISubmitterControl' => $vendorDir . '/nette/forms/src/compatibility.php', + 'Nette\\Forms\\Rendering\\DataClassGenerator' => $vendorDir . '/nette/forms/src/Forms/Rendering/DataClassGenerator.php', + 'Nette\\Forms\\Rendering\\DefaultFormRenderer' => $vendorDir . '/nette/forms/src/Forms/Rendering/DefaultFormRenderer.php', + 'Nette\\Forms\\Rendering\\LatteRenderer' => $vendorDir . '/nette/forms/src/Forms/Rendering/LatteRenderer.php', + 'Nette\\Forms\\Rule' => $vendorDir . '/nette/forms/src/Forms/Rule.php', + 'Nette\\Forms\\Rules' => $vendorDir . '/nette/forms/src/Forms/Rules.php', + 'Nette\\Forms\\SubmitterControl' => $vendorDir . '/nette/forms/src/Forms/SubmitterControl.php', + 'Nette\\Forms\\Validator' => $vendorDir . '/nette/forms/src/Forms/Validator.php', + 'Nette\\HtmlStringable' => $vendorDir . '/nette/utils/src/HtmlStringable.php', + 'Nette\\Http\\Context' => $vendorDir . '/nette/http/src/Http/Context.php', + 'Nette\\Http\\FileUpload' => $vendorDir . '/nette/http/src/Http/FileUpload.php', + 'Nette\\Http\\Helpers' => $vendorDir . '/nette/http/src/Http/Helpers.php', + 'Nette\\Http\\IRequest' => $vendorDir . '/nette/http/src/Http/IRequest.php', + 'Nette\\Http\\IResponse' => $vendorDir . '/nette/http/src/Http/IResponse.php', + 'Nette\\Http\\Request' => $vendorDir . '/nette/http/src/Http/Request.php', + 'Nette\\Http\\RequestFactory' => $vendorDir . '/nette/http/src/Http/RequestFactory.php', + 'Nette\\Http\\Response' => $vendorDir . '/nette/http/src/Http/Response.php', + 'Nette\\Http\\Session' => $vendorDir . '/nette/http/src/Http/Session.php', + 'Nette\\Http\\SessionSection' => $vendorDir . '/nette/http/src/Http/SessionSection.php', + 'Nette\\Http\\Url' => $vendorDir . '/nette/http/src/Http/Url.php', + 'Nette\\Http\\UrlImmutable' => $vendorDir . '/nette/http/src/Http/UrlImmutable.php', + 'Nette\\Http\\UrlScript' => $vendorDir . '/nette/http/src/Http/UrlScript.php', + 'Nette\\Http\\UserStorage' => $vendorDir . '/nette/http/src/Http/UserStorage.php', + 'Nette\\IOException' => $vendorDir . '/nette/utils/src/exceptions.php', + 'Nette\\InvalidArgumentException' => $vendorDir . '/nette/utils/src/exceptions.php', + 'Nette\\InvalidStateException' => $vendorDir . '/nette/utils/src/exceptions.php', + 'Nette\\Iterators\\CachingIterator' => $vendorDir . '/nette/utils/src/Iterators/CachingIterator.php', + 'Nette\\Iterators\\Mapper' => $vendorDir . '/nette/utils/src/Iterators/Mapper.php', + 'Nette\\Loaders\\RobotLoader' => $vendorDir . '/nette/robot-loader/src/RobotLoader/RobotLoader.php', + 'Nette\\Localization\\ITranslator' => $vendorDir . '/nette/utils/src/compatibility.php', + 'Nette\\Localization\\Translator' => $vendorDir . '/nette/utils/src/Translator.php', + 'Nette\\Mail\\DkimSigner' => $vendorDir . '/nette/mail/src/Mail/DkimSigner.php', + 'Nette\\Mail\\FallbackMailer' => $vendorDir . '/nette/mail/src/Mail/FallbackMailer.php', + 'Nette\\Mail\\FallbackMailerException' => $vendorDir . '/nette/mail/src/Mail/exceptions.php', + 'Nette\\Mail\\IMailer' => $vendorDir . '/nette/mail/src/Mail/Mailer.php', + 'Nette\\Mail\\Mailer' => $vendorDir . '/nette/mail/src/Mail/Mailer.php', + 'Nette\\Mail\\Message' => $vendorDir . '/nette/mail/src/Mail/Message.php', + 'Nette\\Mail\\MimePart' => $vendorDir . '/nette/mail/src/Mail/MimePart.php', + 'Nette\\Mail\\SendException' => $vendorDir . '/nette/mail/src/Mail/exceptions.php', + 'Nette\\Mail\\SendmailMailer' => $vendorDir . '/nette/mail/src/Mail/SendmailMailer.php', + 'Nette\\Mail\\SignException' => $vendorDir . '/nette/mail/src/Mail/exceptions.php', + 'Nette\\Mail\\Signer' => $vendorDir . '/nette/mail/src/Mail/Signer.php', + 'Nette\\Mail\\SmtpException' => $vendorDir . '/nette/mail/src/Mail/exceptions.php', + 'Nette\\Mail\\SmtpMailer' => $vendorDir . '/nette/mail/src/Mail/SmtpMailer.php', + 'Nette\\MemberAccessException' => $vendorDir . '/nette/utils/src/exceptions.php', + 'Nette\\Neon\\Decoder' => $vendorDir . '/nette/neon/src/Neon/Decoder.php', + 'Nette\\Neon\\Encoder' => $vendorDir . '/nette/neon/src/Neon/Encoder.php', + 'Nette\\Neon\\Entity' => $vendorDir . '/nette/neon/src/Neon/Entity.php', + 'Nette\\Neon\\Exception' => $vendorDir . '/nette/neon/src/Neon/Exception.php', + 'Nette\\Neon\\Lexer' => $vendorDir . '/nette/neon/src/Neon/Lexer.php', + 'Nette\\Neon\\Neon' => $vendorDir . '/nette/neon/src/Neon/Neon.php', + 'Nette\\Neon\\Node' => $vendorDir . '/nette/neon/src/Neon/Node.php', + 'Nette\\Neon\\Node\\ArrayItemNode' => $vendorDir . '/nette/neon/src/Neon/Node/ArrayItemNode.php', + 'Nette\\Neon\\Node\\ArrayNode' => $vendorDir . '/nette/neon/src/Neon/Node/ArrayNode.php', + 'Nette\\Neon\\Node\\BlockArrayNode' => $vendorDir . '/nette/neon/src/Neon/Node/BlockArrayNode.php', + 'Nette\\Neon\\Node\\EntityChainNode' => $vendorDir . '/nette/neon/src/Neon/Node/EntityChainNode.php', + 'Nette\\Neon\\Node\\EntityNode' => $vendorDir . '/nette/neon/src/Neon/Node/EntityNode.php', + 'Nette\\Neon\\Node\\InlineArrayNode' => $vendorDir . '/nette/neon/src/Neon/Node/InlineArrayNode.php', + 'Nette\\Neon\\Node\\LiteralNode' => $vendorDir . '/nette/neon/src/Neon/Node/LiteralNode.php', + 'Nette\\Neon\\Node\\StringNode' => $vendorDir . '/nette/neon/src/Neon/Node/StringNode.php', + 'Nette\\Neon\\Parser' => $vendorDir . '/nette/neon/src/Neon/Parser.php', + 'Nette\\Neon\\Token' => $vendorDir . '/nette/neon/src/Neon/Token.php', + 'Nette\\Neon\\TokenStream' => $vendorDir . '/nette/neon/src/Neon/TokenStream.php', + 'Nette\\Neon\\Traverser' => $vendorDir . '/nette/neon/src/Neon/Traverser.php', + 'Nette\\NotImplementedException' => $vendorDir . '/nette/utils/src/exceptions.php', + 'Nette\\NotSupportedException' => $vendorDir . '/nette/utils/src/exceptions.php', + 'Nette\\OutOfRangeException' => $vendorDir . '/nette/utils/src/exceptions.php', + 'Nette\\PhpGenerator\\Attribute' => $vendorDir . '/nette/php-generator/src/PhpGenerator/Attribute.php', + 'Nette\\PhpGenerator\\ClassLike' => $vendorDir . '/nette/php-generator/src/PhpGenerator/ClassLike.php', + 'Nette\\PhpGenerator\\ClassManipulator' => $vendorDir . '/nette/php-generator/src/PhpGenerator/ClassManipulator.php', + 'Nette\\PhpGenerator\\ClassType' => $vendorDir . '/nette/php-generator/src/PhpGenerator/ClassType.php', + 'Nette\\PhpGenerator\\Closure' => $vendorDir . '/nette/php-generator/src/PhpGenerator/Closure.php', + 'Nette\\PhpGenerator\\Constant' => $vendorDir . '/nette/php-generator/src/PhpGenerator/Constant.php', + 'Nette\\PhpGenerator\\Dumper' => $vendorDir . '/nette/php-generator/src/PhpGenerator/Dumper.php', + 'Nette\\PhpGenerator\\EnumCase' => $vendorDir . '/nette/php-generator/src/PhpGenerator/EnumCase.php', + 'Nette\\PhpGenerator\\EnumType' => $vendorDir . '/nette/php-generator/src/PhpGenerator/EnumType.php', + 'Nette\\PhpGenerator\\Extractor' => $vendorDir . '/nette/php-generator/src/PhpGenerator/Extractor.php', + 'Nette\\PhpGenerator\\Factory' => $vendorDir . '/nette/php-generator/src/PhpGenerator/Factory.php', + 'Nette\\PhpGenerator\\GlobalFunction' => $vendorDir . '/nette/php-generator/src/PhpGenerator/GlobalFunction.php', + 'Nette\\PhpGenerator\\Helpers' => $vendorDir . '/nette/php-generator/src/PhpGenerator/Helpers.php', + 'Nette\\PhpGenerator\\InterfaceType' => $vendorDir . '/nette/php-generator/src/PhpGenerator/InterfaceType.php', + 'Nette\\PhpGenerator\\Literal' => $vendorDir . '/nette/php-generator/src/PhpGenerator/Literal.php', + 'Nette\\PhpGenerator\\Method' => $vendorDir . '/nette/php-generator/src/PhpGenerator/Method.php', + 'Nette\\PhpGenerator\\Parameter' => $vendorDir . '/nette/php-generator/src/PhpGenerator/Parameter.php', + 'Nette\\PhpGenerator\\PhpFile' => $vendorDir . '/nette/php-generator/src/PhpGenerator/PhpFile.php', + 'Nette\\PhpGenerator\\PhpLiteral' => $vendorDir . '/nette/php-generator/src/PhpGenerator/PhpLiteral.php', + 'Nette\\PhpGenerator\\PhpNamespace' => $vendorDir . '/nette/php-generator/src/PhpGenerator/PhpNamespace.php', + 'Nette\\PhpGenerator\\Printer' => $vendorDir . '/nette/php-generator/src/PhpGenerator/Printer.php', + 'Nette\\PhpGenerator\\PromotedParameter' => $vendorDir . '/nette/php-generator/src/PhpGenerator/PromotedParameter.php', + 'Nette\\PhpGenerator\\Property' => $vendorDir . '/nette/php-generator/src/PhpGenerator/Property.php', + 'Nette\\PhpGenerator\\PropertyAccessMode' => $vendorDir . '/nette/php-generator/src/PhpGenerator/PropertyAccessMode.php', + 'Nette\\PhpGenerator\\PropertyHook' => $vendorDir . '/nette/php-generator/src/PhpGenerator/PropertyHook.php', + 'Nette\\PhpGenerator\\PropertyHookType' => $vendorDir . '/nette/php-generator/src/PhpGenerator/PropertyHookType.php', + 'Nette\\PhpGenerator\\PsrPrinter' => $vendorDir . '/nette/php-generator/src/PhpGenerator/PsrPrinter.php', + 'Nette\\PhpGenerator\\TraitType' => $vendorDir . '/nette/php-generator/src/PhpGenerator/TraitType.php', + 'Nette\\PhpGenerator\\TraitUse' => $vendorDir . '/nette/php-generator/src/PhpGenerator/TraitUse.php', + 'Nette\\PhpGenerator\\Traits\\AttributeAware' => $vendorDir . '/nette/php-generator/src/PhpGenerator/Traits/AttributeAware.php', + 'Nette\\PhpGenerator\\Traits\\CommentAware' => $vendorDir . '/nette/php-generator/src/PhpGenerator/Traits/CommentAware.php', + 'Nette\\PhpGenerator\\Traits\\ConstantsAware' => $vendorDir . '/nette/php-generator/src/PhpGenerator/Traits/ConstantsAware.php', + 'Nette\\PhpGenerator\\Traits\\FunctionLike' => $vendorDir . '/nette/php-generator/src/PhpGenerator/Traits/FunctionLike.php', + 'Nette\\PhpGenerator\\Traits\\MethodsAware' => $vendorDir . '/nette/php-generator/src/PhpGenerator/Traits/MethodsAware.php', + 'Nette\\PhpGenerator\\Traits\\NameAware' => $vendorDir . '/nette/php-generator/src/PhpGenerator/Traits/NameAware.php', + 'Nette\\PhpGenerator\\Traits\\PropertiesAware' => $vendorDir . '/nette/php-generator/src/PhpGenerator/Traits/PropertiesAware.php', + 'Nette\\PhpGenerator\\Traits\\PropertyLike' => $vendorDir . '/nette/php-generator/src/PhpGenerator/Traits/PropertyLike.php', + 'Nette\\PhpGenerator\\Traits\\TraitsAware' => $vendorDir . '/nette/php-generator/src/PhpGenerator/Traits/TraitsAware.php', + 'Nette\\PhpGenerator\\Traits\\VisibilityAware' => $vendorDir . '/nette/php-generator/src/PhpGenerator/Traits/VisibilityAware.php', + 'Nette\\PhpGenerator\\Type' => $vendorDir . '/nette/php-generator/src/PhpGenerator/Type.php', + 'Nette\\PhpGenerator\\Visibility' => $vendorDir . '/nette/php-generator/src/PhpGenerator/Visibility.php', + 'Nette\\Routing\\Route' => $vendorDir . '/nette/routing/src/Routing/Route.php', + 'Nette\\Routing\\RouteList' => $vendorDir . '/nette/routing/src/Routing/RouteList.php', + 'Nette\\Routing\\Router' => $vendorDir . '/nette/routing/src/Routing/Router.php', + 'Nette\\Routing\\SimpleRouter' => $vendorDir . '/nette/routing/src/Routing/SimpleRouter.php', + 'Nette\\Schema\\Context' => $vendorDir . '/nette/schema/src/Schema/Context.php', + 'Nette\\Schema\\DynamicParameter' => $vendorDir . '/nette/schema/src/Schema/DynamicParameter.php', + 'Nette\\Schema\\Elements\\AnyOf' => $vendorDir . '/nette/schema/src/Schema/Elements/AnyOf.php', + 'Nette\\Schema\\Elements\\Base' => $vendorDir . '/nette/schema/src/Schema/Elements/Base.php', + 'Nette\\Schema\\Elements\\Structure' => $vendorDir . '/nette/schema/src/Schema/Elements/Structure.php', + 'Nette\\Schema\\Elements\\Type' => $vendorDir . '/nette/schema/src/Schema/Elements/Type.php', + 'Nette\\Schema\\Expect' => $vendorDir . '/nette/schema/src/Schema/Expect.php', + 'Nette\\Schema\\Helpers' => $vendorDir . '/nette/schema/src/Schema/Helpers.php', + 'Nette\\Schema\\Message' => $vendorDir . '/nette/schema/src/Schema/Message.php', + 'Nette\\Schema\\Processor' => $vendorDir . '/nette/schema/src/Schema/Processor.php', + 'Nette\\Schema\\Schema' => $vendorDir . '/nette/schema/src/Schema/Schema.php', + 'Nette\\Schema\\ValidationException' => $vendorDir . '/nette/schema/src/Schema/ValidationException.php', + 'Nette\\Security\\AuthenticationException' => $vendorDir . '/nette/security/src/Security/AuthenticationException.php', + 'Nette\\Security\\Authenticator' => $vendorDir . '/nette/security/src/Security/Authenticator.php', + 'Nette\\Security\\Authorizator' => $vendorDir . '/nette/security/src/Security/Authorizator.php', + 'Nette\\Security\\IAuthenticator' => $vendorDir . '/nette/security/src/Security/IAuthenticator.php', + 'Nette\\Security\\IAuthorizator' => $vendorDir . '/nette/security/src/compatibility.php', + 'Nette\\Security\\IIdentity' => $vendorDir . '/nette/security/src/Security/IIdentity.php', + 'Nette\\Security\\IResource' => $vendorDir . '/nette/security/src/compatibility.php', + 'Nette\\Security\\IRole' => $vendorDir . '/nette/security/src/compatibility.php', + 'Nette\\Security\\Identity' => $vendorDir . '/nette/security/src/Security/Identity.php', + 'Nette\\Security\\IdentityHandler' => $vendorDir . '/nette/security/src/Security/IdentityHandler.php', + 'Nette\\Security\\Passwords' => $vendorDir . '/nette/security/src/Security/Passwords.php', + 'Nette\\Security\\Permission' => $vendorDir . '/nette/security/src/Security/Permission.php', + 'Nette\\Security\\Resource' => $vendorDir . '/nette/security/src/Security/Resource.php', + 'Nette\\Security\\Role' => $vendorDir . '/nette/security/src/Security/Role.php', + 'Nette\\Security\\SimpleAuthenticator' => $vendorDir . '/nette/security/src/Security/SimpleAuthenticator.php', + 'Nette\\Security\\SimpleIdentity' => $vendorDir . '/nette/security/src/Security/SimpleIdentity.php', + 'Nette\\Security\\User' => $vendorDir . '/nette/security/src/Security/User.php', + 'Nette\\Security\\UserStorage' => $vendorDir . '/nette/security/src/Security/UserStorage.php', + 'Nette\\ShouldNotHappenException' => $vendorDir . '/nette/utils/src/exceptions.php', + 'Nette\\SmartObject' => $vendorDir . '/nette/utils/src/SmartObject.php', + 'Nette\\StaticClass' => $vendorDir . '/nette/utils/src/StaticClass.php', + 'Nette\\UnexpectedValueException' => $vendorDir . '/nette/utils/src/exceptions.php', + 'Nette\\Utils\\ArrayHash' => $vendorDir . '/nette/utils/src/Utils/ArrayHash.php', + 'Nette\\Utils\\ArrayList' => $vendorDir . '/nette/utils/src/Utils/ArrayList.php', + 'Nette\\Utils\\Arrays' => $vendorDir . '/nette/utils/src/Utils/Arrays.php', + 'Nette\\Utils\\AssertionException' => $vendorDir . '/nette/utils/src/Utils/exceptions.php', + 'Nette\\Utils\\Callback' => $vendorDir . '/nette/utils/src/Utils/Callback.php', + 'Nette\\Utils\\DateTime' => $vendorDir . '/nette/utils/src/Utils/DateTime.php', + 'Nette\\Utils\\FileInfo' => $vendorDir . '/nette/utils/src/Utils/FileInfo.php', + 'Nette\\Utils\\FileSystem' => $vendorDir . '/nette/utils/src/Utils/FileSystem.php', + 'Nette\\Utils\\Finder' => $vendorDir . '/nette/utils/src/Utils/Finder.php', + 'Nette\\Utils\\Floats' => $vendorDir . '/nette/utils/src/Utils/Floats.php', + 'Nette\\Utils\\Helpers' => $vendorDir . '/nette/utils/src/Utils/Helpers.php', + 'Nette\\Utils\\Html' => $vendorDir . '/nette/utils/src/Utils/Html.php', + 'Nette\\Utils\\IHtmlString' => $vendorDir . '/nette/utils/src/compatibility.php', + 'Nette\\Utils\\Image' => $vendorDir . '/nette/utils/src/Utils/Image.php', + 'Nette\\Utils\\ImageColor' => $vendorDir . '/nette/utils/src/Utils/ImageColor.php', + 'Nette\\Utils\\ImageException' => $vendorDir . '/nette/utils/src/Utils/exceptions.php', + 'Nette\\Utils\\ImageType' => $vendorDir . '/nette/utils/src/Utils/ImageType.php', + 'Nette\\Utils\\Iterables' => $vendorDir . '/nette/utils/src/Utils/Iterables.php', + 'Nette\\Utils\\Json' => $vendorDir . '/nette/utils/src/Utils/Json.php', + 'Nette\\Utils\\JsonException' => $vendorDir . '/nette/utils/src/Utils/exceptions.php', + 'Nette\\Utils\\ObjectHelpers' => $vendorDir . '/nette/utils/src/Utils/ObjectHelpers.php', + 'Nette\\Utils\\Paginator' => $vendorDir . '/nette/utils/src/Utils/Paginator.php', + 'Nette\\Utils\\Random' => $vendorDir . '/nette/utils/src/Utils/Random.php', + 'Nette\\Utils\\Reflection' => $vendorDir . '/nette/utils/src/Utils/Reflection.php', + 'Nette\\Utils\\ReflectionMethod' => $vendorDir . '/nette/utils/src/Utils/ReflectionMethod.php', + 'Nette\\Utils\\RegexpException' => $vendorDir . '/nette/utils/src/Utils/exceptions.php', + 'Nette\\Utils\\Strings' => $vendorDir . '/nette/utils/src/Utils/Strings.php', + 'Nette\\Utils\\Type' => $vendorDir . '/nette/utils/src/Utils/Type.php', + 'Nette\\Utils\\UnknownImageFileException' => $vendorDir . '/nette/utils/src/Utils/exceptions.php', + 'Nette\\Utils\\Validators' => $vendorDir . '/nette/utils/src/Utils/Validators.php', + 'Tester\\Assert' => $vendorDir . '/nette/tester/src/Framework/Assert.php', + 'Tester\\AssertException' => $vendorDir . '/nette/tester/src/Framework/AssertException.php', + 'Tester\\CodeCoverage\\Collector' => $vendorDir . '/nette/tester/src/CodeCoverage/Collector.php', + 'Tester\\CodeCoverage\\Generators\\AbstractGenerator' => $vendorDir . '/nette/tester/src/CodeCoverage/Generators/AbstractGenerator.php', + 'Tester\\CodeCoverage\\Generators\\CloverXMLGenerator' => $vendorDir . '/nette/tester/src/CodeCoverage/Generators/CloverXMLGenerator.php', + 'Tester\\CodeCoverage\\Generators\\HtmlGenerator' => $vendorDir . '/nette/tester/src/CodeCoverage/Generators/HtmlGenerator.php', + 'Tester\\CodeCoverage\\PhpParser' => $vendorDir . '/nette/tester/src/CodeCoverage/PhpParser.php', + 'Tester\\DataProvider' => $vendorDir . '/nette/tester/src/Framework/DataProvider.php', + 'Tester\\DomQuery' => $vendorDir . '/nette/tester/src/Framework/DomQuery.php', + 'Tester\\Dumper' => $vendorDir . '/nette/tester/src/Framework/Dumper.php', + 'Tester\\Environment' => $vendorDir . '/nette/tester/src/Framework/Environment.php', + 'Tester\\Expect' => $vendorDir . '/nette/tester/src/Framework/Expect.php', + 'Tester\\FileMock' => $vendorDir . '/nette/tester/src/Framework/FileMock.php', + 'Tester\\FileMutator' => $vendorDir . '/nette/tester/src/Framework/FileMutator.php', + 'Tester\\Helpers' => $vendorDir . '/nette/tester/src/Framework/Helpers.php', + 'Tester\\HttpAssert' => $vendorDir . '/nette/tester/src/Framework/HttpAssert.php', + 'Tester\\Runner\\CliTester' => $vendorDir . '/nette/tester/src/Runner/CliTester.php', + 'Tester\\Runner\\CommandLine' => $vendorDir . '/nette/tester/src/Runner/CommandLine.php', + 'Tester\\Runner\\InterruptException' => $vendorDir . '/nette/tester/src/Runner/exceptions.php', + 'Tester\\Runner\\Job' => $vendorDir . '/nette/tester/src/Runner/Job.php', + 'Tester\\Runner\\OutputHandler' => $vendorDir . '/nette/tester/src/Runner/OutputHandler.php', + 'Tester\\Runner\\Output\\ConsolePrinter' => $vendorDir . '/nette/tester/src/Runner/Output/ConsolePrinter.php', + 'Tester\\Runner\\Output\\JUnitPrinter' => $vendorDir . '/nette/tester/src/Runner/Output/JUnitPrinter.php', + 'Tester\\Runner\\Output\\Logger' => $vendorDir . '/nette/tester/src/Runner/Output/Logger.php', + 'Tester\\Runner\\Output\\TapPrinter' => $vendorDir . '/nette/tester/src/Runner/Output/TapPrinter.php', + 'Tester\\Runner\\PhpInterpreter' => $vendorDir . '/nette/tester/src/Runner/PhpInterpreter.php', + 'Tester\\Runner\\Runner' => $vendorDir . '/nette/tester/src/Runner/Runner.php', + 'Tester\\Runner\\Test' => $vendorDir . '/nette/tester/src/Runner/Test.php', + 'Tester\\Runner\\TestHandler' => $vendorDir . '/nette/tester/src/Runner/TestHandler.php', + 'Tester\\TestCase' => $vendorDir . '/nette/tester/src/Framework/TestCase.php', + 'Tester\\TestCaseException' => $vendorDir . '/nette/tester/src/Framework/TestCase.php', + 'Tester\\TestCaseSkippedException' => $vendorDir . '/nette/tester/src/Framework/TestCase.php', + 'Tracy\\Bar' => $vendorDir . '/tracy/tracy/src/Tracy/Bar/Bar.php', + 'Tracy\\BlueScreen' => $vendorDir . '/tracy/tracy/src/Tracy/BlueScreen/BlueScreen.php', + 'Tracy\\Bridges\\Nette\\Bridge' => $vendorDir . '/tracy/tracy/src/Bridges/Nette/Bridge.php', + 'Tracy\\Bridges\\Nette\\MailSender' => $vendorDir . '/tracy/tracy/src/Bridges/Nette/MailSender.php', + 'Tracy\\Bridges\\Nette\\TracyExtension' => $vendorDir . '/tracy/tracy/src/Bridges/Nette/TracyExtension.php', + 'Tracy\\Bridges\\Psr\\PsrToTracyLoggerAdapter' => $vendorDir . '/tracy/tracy/src/Bridges/Psr/PsrToTracyLoggerAdapter.php', + 'Tracy\\Bridges\\Psr\\TracyToPsrLoggerAdapter' => $vendorDir . '/tracy/tracy/src/Bridges/Psr/TracyToPsrLoggerAdapter.php', + 'Tracy\\CodeHighlighter' => $vendorDir . '/tracy/tracy/src/Tracy/BlueScreen/CodeHighlighter.php', + 'Tracy\\Debugger' => $vendorDir . '/tracy/tracy/src/Tracy/Debugger/Debugger.php', + 'Tracy\\DefaultBarPanel' => $vendorDir . '/tracy/tracy/src/Tracy/Bar/DefaultBarPanel.php', + 'Tracy\\DeferredContent' => $vendorDir . '/tracy/tracy/src/Tracy/Debugger/DeferredContent.php', + 'Tracy\\DevelopmentStrategy' => $vendorDir . '/tracy/tracy/src/Tracy/Debugger/DevelopmentStrategy.php', + 'Tracy\\Dumper' => $vendorDir . '/tracy/tracy/src/Tracy/Dumper/Dumper.php', + 'Tracy\\Dumper\\Describer' => $vendorDir . '/tracy/tracy/src/Tracy/Dumper/Describer.php', + 'Tracy\\Dumper\\Exposer' => $vendorDir . '/tracy/tracy/src/Tracy/Dumper/Exposer.php', + 'Tracy\\Dumper\\Renderer' => $vendorDir . '/tracy/tracy/src/Tracy/Dumper/Renderer.php', + 'Tracy\\Dumper\\Value' => $vendorDir . '/tracy/tracy/src/Tracy/Dumper/Value.php', + 'Tracy\\FileSession' => $vendorDir . '/tracy/tracy/src/Tracy/Session/FileSession.php', + 'Tracy\\Helpers' => $vendorDir . '/tracy/tracy/src/Tracy/Helpers.php', + 'Tracy\\IBarPanel' => $vendorDir . '/tracy/tracy/src/Tracy/Bar/IBarPanel.php', + 'Tracy\\ILogger' => $vendorDir . '/tracy/tracy/src/Tracy/Logger/ILogger.php', + 'Tracy\\Logger' => $vendorDir . '/tracy/tracy/src/Tracy/Logger/Logger.php', + 'Tracy\\NativeSession' => $vendorDir . '/tracy/tracy/src/Tracy/Session/NativeSession.php', + 'Tracy\\OutputDebugger' => $vendorDir . '/tracy/tracy/src/Tracy/OutputDebugger/OutputDebugger.php', + 'Tracy\\ProductionStrategy' => $vendorDir . '/tracy/tracy/src/Tracy/Debugger/ProductionStrategy.php', + 'Tracy\\SessionStorage' => $vendorDir . '/tracy/tracy/src/Tracy/Session/SessionStorage.php', +); diff --git a/vendor/composer/autoload_files.php b/vendor/composer/autoload_files.php new file mode 100644 index 0000000..0ef85dc --- /dev/null +++ b/vendor/composer/autoload_files.php @@ -0,0 +1,12 @@ + $vendorDir . '/phpstan/phpstan/bootstrap.php', + '6e3fae29631ef280660b3cdad06f25a8' => $vendorDir . '/symfony/deprecation-contracts/function.php', + 'd507e002f7fce7f0c6dbf1f22edcb902' => $vendorDir . '/tracy/tracy/src/Tracy/functions.php', +); diff --git a/vendor/composer/autoload_namespaces.php b/vendor/composer/autoload_namespaces.php new file mode 100644 index 0000000..15a2ff3 --- /dev/null +++ b/vendor/composer/autoload_namespaces.php @@ -0,0 +1,9 @@ + array($vendorDir . '/tracy/tracy/src'), + 'Tester\\' => array($vendorDir . '/nette/tester/src'), + 'Symfony\\Thanks\\' => array($vendorDir . '/symfony/thanks/src'), + 'Psr\\Clock\\' => array($vendorDir . '/psr/clock/src'), + 'ParagonIE\\ConstantTime\\' => array($vendorDir . '/paragonie/constant_time_encoding/src'), + 'PHPStan\\' => array($vendorDir . '/phpstan/phpstan-nette/src'), + 'OTPHP\\' => array($vendorDir . '/spomky-labs/otphp/src'), + 'Nette\\' => array($vendorDir . '/nette/application/src', $vendorDir . '/nette/assets/src', $vendorDir . '/nette/bootstrap/src', $vendorDir . '/nette/caching/src', $vendorDir . '/nette/component-model/src', $vendorDir . '/nette/database/src', $vendorDir . '/nette/di/src', $vendorDir . '/nette/forms/src', $vendorDir . '/nette/http/src', $vendorDir . '/nette/mail/src', $vendorDir . '/nette/neon/src', $vendorDir . '/nette/php-generator/src', $vendorDir . '/nette/robot-loader/src', $vendorDir . '/nette/routing/src', $vendorDir . '/nette/schema/src', $vendorDir . '/nette/security/src', $vendorDir . '/nette/utils/src'), + 'Latte\\' => array($vendorDir . '/latte/latte/src/Latte'), + 'Endroid\\QrCode\\' => array($vendorDir . '/endroid/qr-code/src'), + 'DASPRiD\\Enum\\' => array($vendorDir . '/dasprid/enum/src'), + 'BaconQrCode\\' => array($vendorDir . '/bacon/bacon-qr-code/src'), + 'App\\' => array($baseDir . '/app'), +); diff --git a/vendor/composer/autoload_real.php b/vendor/composer/autoload_real.php new file mode 100644 index 0000000..647379b --- /dev/null +++ b/vendor/composer/autoload_real.php @@ -0,0 +1,50 @@ +register(true); + + $filesToLoad = \Composer\Autoload\ComposerStaticInita1ed42372489c27598cfbf4d5ef3ac47::$files; + $requireFile = \Closure::bind(static function ($fileIdentifier, $file) { + if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) { + $GLOBALS['__composer_autoload_files'][$fileIdentifier] = true; + + require $file; + } + }, null, null); + foreach ($filesToLoad as $fileIdentifier => $file) { + $requireFile($fileIdentifier, $file); + } + + return $loader; + } +} diff --git a/vendor/composer/autoload_static.php b/vendor/composer/autoload_static.php new file mode 100644 index 0000000..e2103d4 --- /dev/null +++ b/vendor/composer/autoload_static.php @@ -0,0 +1,831 @@ + __DIR__ . '/..' . '/phpstan/phpstan/bootstrap.php', + '6e3fae29631ef280660b3cdad06f25a8' => __DIR__ . '/..' . '/symfony/deprecation-contracts/function.php', + 'd507e002f7fce7f0c6dbf1f22edcb902' => __DIR__ . '/..' . '/tracy/tracy/src/Tracy/functions.php', + ); + + public static $prefixLengthsPsr4 = array ( + 'T' => + array ( + 'Tracy\\' => 6, + 'Tester\\' => 7, + ), + 'S' => + array ( + 'Symfony\\Thanks\\' => 15, + ), + 'P' => + array ( + 'Psr\\Clock\\' => 10, + 'ParagonIE\\ConstantTime\\' => 23, + 'PHPStan\\' => 8, + ), + 'O' => + array ( + 'OTPHP\\' => 6, + ), + 'N' => + array ( + 'Nette\\' => 6, + ), + 'L' => + array ( + 'Latte\\' => 6, + ), + 'E' => + array ( + 'Endroid\\QrCode\\' => 15, + ), + 'D' => + array ( + 'DASPRiD\\Enum\\' => 13, + ), + 'B' => + array ( + 'BaconQrCode\\' => 12, + ), + 'A' => + array ( + 'App\\' => 4, + ), + ); + + public static $prefixDirsPsr4 = array ( + 'Tracy\\' => + array ( + 0 => __DIR__ . '/..' . '/tracy/tracy/src', + ), + 'Tester\\' => + array ( + 0 => __DIR__ . '/..' . '/nette/tester/src', + ), + 'Symfony\\Thanks\\' => + array ( + 0 => __DIR__ . '/..' . '/symfony/thanks/src', + ), + 'Psr\\Clock\\' => + array ( + 0 => __DIR__ . '/..' . '/psr/clock/src', + ), + 'ParagonIE\\ConstantTime\\' => + array ( + 0 => __DIR__ . '/..' . '/paragonie/constant_time_encoding/src', + ), + 'PHPStan\\' => + array ( + 0 => __DIR__ . '/..' . '/phpstan/phpstan-nette/src', + ), + 'OTPHP\\' => + array ( + 0 => __DIR__ . '/..' . '/spomky-labs/otphp/src', + ), + 'Nette\\' => + array ( + 0 => __DIR__ . '/..' . '/nette/application/src', + 1 => __DIR__ . '/..' . '/nette/assets/src', + 2 => __DIR__ . '/..' . '/nette/bootstrap/src', + 3 => __DIR__ . '/..' . '/nette/caching/src', + 4 => __DIR__ . '/..' . '/nette/component-model/src', + 5 => __DIR__ . '/..' . '/nette/database/src', + 6 => __DIR__ . '/..' . '/nette/di/src', + 7 => __DIR__ . '/..' . '/nette/forms/src', + 8 => __DIR__ . '/..' . '/nette/http/src', + 9 => __DIR__ . '/..' . '/nette/mail/src', + 10 => __DIR__ . '/..' . '/nette/neon/src', + 11 => __DIR__ . '/..' . '/nette/php-generator/src', + 12 => __DIR__ . '/..' . '/nette/robot-loader/src', + 13 => __DIR__ . '/..' . '/nette/routing/src', + 14 => __DIR__ . '/..' . '/nette/schema/src', + 15 => __DIR__ . '/..' . '/nette/security/src', + 16 => __DIR__ . '/..' . '/nette/utils/src', + ), + 'Latte\\' => + array ( + 0 => __DIR__ . '/..' . '/latte/latte/src/Latte', + ), + 'Endroid\\QrCode\\' => + array ( + 0 => __DIR__ . '/..' . '/endroid/qr-code/src', + ), + 'DASPRiD\\Enum\\' => + array ( + 0 => __DIR__ . '/..' . '/dasprid/enum/src', + ), + 'BaconQrCode\\' => + array ( + 0 => __DIR__ . '/..' . '/bacon/bacon-qr-code/src', + ), + 'App\\' => + array ( + 0 => __DIR__ . '/../..' . '/app', + ), + ); + + public static $classMap = array ( + 'Composer\\InstalledVersions' => __DIR__ . '/..' . '/composer/InstalledVersions.php', + 'Latte\\Attributes\\TemplateFilter' => __DIR__ . '/..' . '/latte/latte/src/Latte/attributes.php', + 'Latte\\Attributes\\TemplateFunction' => __DIR__ . '/..' . '/latte/latte/src/Latte/attributes.php', + 'Latte\\Bridges\\Tracy\\BlueScreenPanel' => __DIR__ . '/..' . '/latte/latte/src/Bridges/Tracy/BlueScreenPanel.php', + 'Latte\\Bridges\\Tracy\\LattePanel' => __DIR__ . '/..' . '/latte/latte/src/Bridges/Tracy/LattePanel.php', + 'Latte\\Bridges\\Tracy\\TracyExtension' => __DIR__ . '/..' . '/latte/latte/src/Bridges/Tracy/TracyExtension.php', + 'Latte\\Cache' => __DIR__ . '/..' . '/latte/latte/src/Latte/Cache.php', + 'Latte\\CompileException' => __DIR__ . '/..' . '/latte/latte/src/Latte/exceptions.php', + 'Latte\\Compiler\\Block' => __DIR__ . '/..' . '/latte/latte/src/Latte/Compiler/Block.php', + 'Latte\\Compiler\\Escaper' => __DIR__ . '/..' . '/latte/latte/src/Latte/Compiler/Escaper.php', + 'Latte\\Compiler\\Node' => __DIR__ . '/..' . '/latte/latte/src/Latte/Compiler/Node.php', + 'Latte\\Compiler\\NodeHelpers' => __DIR__ . '/..' . '/latte/latte/src/Latte/Compiler/NodeHelpers.php', + 'Latte\\Compiler\\NodeTraverser' => __DIR__ . '/..' . '/latte/latte/src/Latte/Compiler/NodeTraverser.php', + 'Latte\\Compiler\\Nodes\\AreaNode' => __DIR__ . '/..' . '/latte/latte/src/Latte/Compiler/Nodes/AreaNode.php', + 'Latte\\Compiler\\Nodes\\AuxiliaryNode' => __DIR__ . '/..' . '/latte/latte/src/Latte/Compiler/Nodes/AuxiliaryNode.php', + 'Latte\\Compiler\\Nodes\\FragmentNode' => __DIR__ . '/..' . '/latte/latte/src/Latte/Compiler/Nodes/FragmentNode.php', + 'Latte\\Compiler\\Nodes\\Html\\AttributeNode' => __DIR__ . '/..' . '/latte/latte/src/Latte/Compiler/Nodes/Html/AttributeNode.php', + 'Latte\\Compiler\\Nodes\\Html\\BogusTagNode' => __DIR__ . '/..' . '/latte/latte/src/Latte/Compiler/Nodes/Html/BogusTagNode.php', + 'Latte\\Compiler\\Nodes\\Html\\CommentNode' => __DIR__ . '/..' . '/latte/latte/src/Latte/Compiler/Nodes/Html/CommentNode.php', + 'Latte\\Compiler\\Nodes\\Html\\ElementNode' => __DIR__ . '/..' . '/latte/latte/src/Latte/Compiler/Nodes/Html/ElementNode.php', + 'Latte\\Compiler\\Nodes\\Html\\ExpressionAttributeNode' => __DIR__ . '/..' . '/latte/latte/src/Latte/Compiler/Nodes/Html/ExpressionAttributeNode.php', + 'Latte\\Compiler\\Nodes\\Html\\TagNode' => __DIR__ . '/..' . '/latte/latte/src/Latte/Compiler/Nodes/Html/TagNode.php', + 'Latte\\Compiler\\Nodes\\NopNode' => __DIR__ . '/..' . '/latte/latte/src/Latte/Compiler/Nodes/NopNode.php', + 'Latte\\Compiler\\Nodes\\Php\\ArgumentNode' => __DIR__ . '/..' . '/latte/latte/src/Latte/Compiler/Nodes/Php/ArgumentNode.php', + 'Latte\\Compiler\\Nodes\\Php\\ArrayItemNode' => __DIR__ . '/..' . '/latte/latte/src/Latte/Compiler/Nodes/Php/ArrayItemNode.php', + 'Latte\\Compiler\\Nodes\\Php\\ClosureUseNode' => __DIR__ . '/..' . '/latte/latte/src/Latte/Compiler/Nodes/Php/ClosureUseNode.php', + 'Latte\\Compiler\\Nodes\\Php\\ComplexTypeNode' => __DIR__ . '/..' . '/latte/latte/src/Latte/Compiler/Nodes/Php/ComplexTypeNode.php', + 'Latte\\Compiler\\Nodes\\Php\\ExpressionNode' => __DIR__ . '/..' . '/latte/latte/src/Latte/Compiler/Nodes/Php/ExpressionNode.php', + 'Latte\\Compiler\\Nodes\\Php\\Expression\\ArrayAccessNode' => __DIR__ . '/..' . '/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/ArrayAccessNode.php', + 'Latte\\Compiler\\Nodes\\Php\\Expression\\ArrayNode' => __DIR__ . '/..' . '/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/ArrayNode.php', + 'Latte\\Compiler\\Nodes\\Php\\Expression\\AssignNode' => __DIR__ . '/..' . '/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/AssignNode.php', + 'Latte\\Compiler\\Nodes\\Php\\Expression\\AssignOpNode' => __DIR__ . '/..' . '/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/AssignOpNode.php', + 'Latte\\Compiler\\Nodes\\Php\\Expression\\AuxiliaryNode' => __DIR__ . '/..' . '/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/AuxiliaryNode.php', + 'Latte\\Compiler\\Nodes\\Php\\Expression\\BinaryOpNode' => __DIR__ . '/..' . '/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/BinaryOpNode.php', + 'Latte\\Compiler\\Nodes\\Php\\Expression\\CastNode' => __DIR__ . '/..' . '/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/CastNode.php', + 'Latte\\Compiler\\Nodes\\Php\\Expression\\ClassConstantFetchNode' => __DIR__ . '/..' . '/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/ClassConstantFetchNode.php', + 'Latte\\Compiler\\Nodes\\Php\\Expression\\CloneNode' => __DIR__ . '/..' . '/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/CloneNode.php', + 'Latte\\Compiler\\Nodes\\Php\\Expression\\ClosureNode' => __DIR__ . '/..' . '/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/ClosureNode.php', + 'Latte\\Compiler\\Nodes\\Php\\Expression\\ConstantFetchNode' => __DIR__ . '/..' . '/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/ConstantFetchNode.php', + 'Latte\\Compiler\\Nodes\\Php\\Expression\\EmptyNode' => __DIR__ . '/..' . '/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/EmptyNode.php', + 'Latte\\Compiler\\Nodes\\Php\\Expression\\FilterCallNode' => __DIR__ . '/..' . '/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/FilterCallNode.php', + 'Latte\\Compiler\\Nodes\\Php\\Expression\\FunctionCallNode' => __DIR__ . '/..' . '/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/FunctionCallNode.php', + 'Latte\\Compiler\\Nodes\\Php\\Expression\\InNode' => __DIR__ . '/..' . '/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/InNode.php', + 'Latte\\Compiler\\Nodes\\Php\\Expression\\InstanceofNode' => __DIR__ . '/..' . '/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/InstanceofNode.php', + 'Latte\\Compiler\\Nodes\\Php\\Expression\\IssetNode' => __DIR__ . '/..' . '/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/IssetNode.php', + 'Latte\\Compiler\\Nodes\\Php\\Expression\\MatchNode' => __DIR__ . '/..' . '/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/MatchNode.php', + 'Latte\\Compiler\\Nodes\\Php\\Expression\\MethodCallNode' => __DIR__ . '/..' . '/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/MethodCallNode.php', + 'Latte\\Compiler\\Nodes\\Php\\Expression\\NewNode' => __DIR__ . '/..' . '/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/NewNode.php', + 'Latte\\Compiler\\Nodes\\Php\\Expression\\PostOpNode' => __DIR__ . '/..' . '/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/PostOpNode.php', + 'Latte\\Compiler\\Nodes\\Php\\Expression\\PreOpNode' => __DIR__ . '/..' . '/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/PreOpNode.php', + 'Latte\\Compiler\\Nodes\\Php\\Expression\\PropertyFetchNode' => __DIR__ . '/..' . '/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/PropertyFetchNode.php', + 'Latte\\Compiler\\Nodes\\Php\\Expression\\StaticMethodCallNode' => __DIR__ . '/..' . '/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/StaticMethodCallNode.php', + 'Latte\\Compiler\\Nodes\\Php\\Expression\\StaticPropertyFetchNode' => __DIR__ . '/..' . '/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/StaticPropertyFetchNode.php', + 'Latte\\Compiler\\Nodes\\Php\\Expression\\TemporaryNode' => __DIR__ . '/..' . '/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/TemporaryNode.php', + 'Latte\\Compiler\\Nodes\\Php\\Expression\\TernaryNode' => __DIR__ . '/..' . '/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/TernaryNode.php', + 'Latte\\Compiler\\Nodes\\Php\\Expression\\UnaryOpNode' => __DIR__ . '/..' . '/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/UnaryOpNode.php', + 'Latte\\Compiler\\Nodes\\Php\\Expression\\VariableNode' => __DIR__ . '/..' . '/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/VariableNode.php', + 'Latte\\Compiler\\Nodes\\Php\\FilterNode' => __DIR__ . '/..' . '/latte/latte/src/Latte/Compiler/Nodes/Php/FilterNode.php', + 'Latte\\Compiler\\Nodes\\Php\\IdentifierNode' => __DIR__ . '/..' . '/latte/latte/src/Latte/Compiler/Nodes/Php/IdentifierNode.php', + 'Latte\\Compiler\\Nodes\\Php\\InterpolatedStringPartNode' => __DIR__ . '/..' . '/latte/latte/src/Latte/Compiler/Nodes/Php/InterpolatedStringPartNode.php', + 'Latte\\Compiler\\Nodes\\Php\\IntersectionTypeNode' => __DIR__ . '/..' . '/latte/latte/src/Latte/Compiler/Nodes/Php/IntersectionTypeNode.php', + 'Latte\\Compiler\\Nodes\\Php\\ListItemNode' => __DIR__ . '/..' . '/latte/latte/src/Latte/Compiler/Nodes/Php/ListItemNode.php', + 'Latte\\Compiler\\Nodes\\Php\\ListNode' => __DIR__ . '/..' . '/latte/latte/src/Latte/Compiler/Nodes/Php/ListNode.php', + 'Latte\\Compiler\\Nodes\\Php\\MatchArmNode' => __DIR__ . '/..' . '/latte/latte/src/Latte/Compiler/Nodes/Php/MatchArmNode.php', + 'Latte\\Compiler\\Nodes\\Php\\ModifierNode' => __DIR__ . '/..' . '/latte/latte/src/Latte/Compiler/Nodes/Php/ModifierNode.php', + 'Latte\\Compiler\\Nodes\\Php\\NameNode' => __DIR__ . '/..' . '/latte/latte/src/Latte/Compiler/Nodes/Php/NameNode.php', + 'Latte\\Compiler\\Nodes\\Php\\NullableTypeNode' => __DIR__ . '/..' . '/latte/latte/src/Latte/Compiler/Nodes/Php/NullableTypeNode.php', + 'Latte\\Compiler\\Nodes\\Php\\OperatorNode' => __DIR__ . '/..' . '/latte/latte/src/Latte/Compiler/Nodes/Php/OperatorNode.php', + 'Latte\\Compiler\\Nodes\\Php\\ParameterNode' => __DIR__ . '/..' . '/latte/latte/src/Latte/Compiler/Nodes/Php/ParameterNode.php', + 'Latte\\Compiler\\Nodes\\Php\\ScalarNode' => __DIR__ . '/..' . '/latte/latte/src/Latte/Compiler/Nodes/Php/ScalarNode.php', + 'Latte\\Compiler\\Nodes\\Php\\Scalar\\BooleanNode' => __DIR__ . '/..' . '/latte/latte/src/Latte/Compiler/Nodes/Php/Scalar/BooleanNode.php', + 'Latte\\Compiler\\Nodes\\Php\\Scalar\\FloatNode' => __DIR__ . '/..' . '/latte/latte/src/Latte/Compiler/Nodes/Php/Scalar/FloatNode.php', + 'Latte\\Compiler\\Nodes\\Php\\Scalar\\IntegerNode' => __DIR__ . '/..' . '/latte/latte/src/Latte/Compiler/Nodes/Php/Scalar/IntegerNode.php', + 'Latte\\Compiler\\Nodes\\Php\\Scalar\\InterpolatedStringNode' => __DIR__ . '/..' . '/latte/latte/src/Latte/Compiler/Nodes/Php/Scalar/InterpolatedStringNode.php', + 'Latte\\Compiler\\Nodes\\Php\\Scalar\\NullNode' => __DIR__ . '/..' . '/latte/latte/src/Latte/Compiler/Nodes/Php/Scalar/NullNode.php', + 'Latte\\Compiler\\Nodes\\Php\\Scalar\\StringNode' => __DIR__ . '/..' . '/latte/latte/src/Latte/Compiler/Nodes/Php/Scalar/StringNode.php', + 'Latte\\Compiler\\Nodes\\Php\\SuperiorTypeNode' => __DIR__ . '/..' . '/latte/latte/src/Latte/Compiler/Nodes/Php/SuperiorTypeNode.php', + 'Latte\\Compiler\\Nodes\\Php\\UnionTypeNode' => __DIR__ . '/..' . '/latte/latte/src/Latte/Compiler/Nodes/Php/UnionTypeNode.php', + 'Latte\\Compiler\\Nodes\\Php\\VarLikeIdentifierNode' => __DIR__ . '/..' . '/latte/latte/src/Latte/Compiler/Nodes/Php/VarLikeIdentifierNode.php', + 'Latte\\Compiler\\Nodes\\Php\\VariadicPlaceholderNode' => __DIR__ . '/..' . '/latte/latte/src/Latte/Compiler/Nodes/Php/VariadicPlaceholderNode.php', + 'Latte\\Compiler\\Nodes\\PrintNode' => __DIR__ . '/..' . '/latte/latte/src/Latte/Compiler/Nodes/PrintNode.php', + 'Latte\\Compiler\\Nodes\\StatementNode' => __DIR__ . '/..' . '/latte/latte/src/Latte/Compiler/Nodes/StatementNode.php', + 'Latte\\Compiler\\Nodes\\TemplateNode' => __DIR__ . '/..' . '/latte/latte/src/Latte/Compiler/Nodes/TemplateNode.php', + 'Latte\\Compiler\\Nodes\\TextNode' => __DIR__ . '/..' . '/latte/latte/src/Latte/Compiler/Nodes/TextNode.php', + 'Latte\\Compiler\\PhpHelpers' => __DIR__ . '/..' . '/latte/latte/src/Latte/Compiler/PhpHelpers.php', + 'Latte\\Compiler\\Position' => __DIR__ . '/..' . '/latte/latte/src/Latte/Compiler/Position.php', + 'Latte\\Compiler\\PrintContext' => __DIR__ . '/..' . '/latte/latte/src/Latte/Compiler/PrintContext.php', + 'Latte\\Compiler\\Tag' => __DIR__ . '/..' . '/latte/latte/src/Latte/Compiler/Tag.php', + 'Latte\\Compiler\\TagLexer' => __DIR__ . '/..' . '/latte/latte/src/Latte/Compiler/TagLexer.php', + 'Latte\\Compiler\\TagParser' => __DIR__ . '/..' . '/latte/latte/src/Latte/Compiler/TagParser.php', + 'Latte\\Compiler\\TagParserData' => __DIR__ . '/..' . '/latte/latte/src/Latte/Compiler/TagParserData.php', + 'Latte\\Compiler\\TemplateGenerator' => __DIR__ . '/..' . '/latte/latte/src/Latte/Compiler/TemplateGenerator.php', + 'Latte\\Compiler\\TemplateLexer' => __DIR__ . '/..' . '/latte/latte/src/Latte/Compiler/TemplateLexer.php', + 'Latte\\Compiler\\TemplateParser' => __DIR__ . '/..' . '/latte/latte/src/Latte/Compiler/TemplateParser.php', + 'Latte\\Compiler\\TemplateParserHtml' => __DIR__ . '/..' . '/latte/latte/src/Latte/Compiler/TemplateParserHtml.php', + 'Latte\\Compiler\\Token' => __DIR__ . '/..' . '/latte/latte/src/Latte/Compiler/Token.php', + 'Latte\\Compiler\\TokenStream' => __DIR__ . '/..' . '/latte/latte/src/Latte/Compiler/TokenStream.php', + 'Latte\\ContentType' => __DIR__ . '/..' . '/latte/latte/src/Latte/ContentType.php', + 'Latte\\Engine' => __DIR__ . '/..' . '/latte/latte/src/Latte/Engine.php', + 'Latte\\Essential\\AuxiliaryIterator' => __DIR__ . '/..' . '/latte/latte/src/Latte/Essential/AuxiliaryIterator.php', + 'Latte\\Essential\\Blueprint' => __DIR__ . '/..' . '/latte/latte/src/Latte/Essential/Blueprint.php', + 'Latte\\Essential\\CachingIterator' => __DIR__ . '/..' . '/latte/latte/src/Latte/Essential/CachingIterator.php', + 'Latte\\Essential\\CoreExtension' => __DIR__ . '/..' . '/latte/latte/src/Latte/Essential/CoreExtension.php', + 'Latte\\Essential\\Filters' => __DIR__ . '/..' . '/latte/latte/src/Latte/Essential/Filters.php', + 'Latte\\Essential\\Nodes\\BlockNode' => __DIR__ . '/..' . '/latte/latte/src/Latte/Essential/Nodes/BlockNode.php', + 'Latte\\Essential\\Nodes\\CaptureNode' => __DIR__ . '/..' . '/latte/latte/src/Latte/Essential/Nodes/CaptureNode.php', + 'Latte\\Essential\\Nodes\\ContentTypeNode' => __DIR__ . '/..' . '/latte/latte/src/Latte/Essential/Nodes/ContentTypeNode.php', + 'Latte\\Essential\\Nodes\\CustomFunctionCallNode' => __DIR__ . '/..' . '/latte/latte/src/Latte/Essential/Nodes/CustomFunctionCallNode.php', + 'Latte\\Essential\\Nodes\\DebugbreakNode' => __DIR__ . '/..' . '/latte/latte/src/Latte/Essential/Nodes/DebugbreakNode.php', + 'Latte\\Essential\\Nodes\\DefineNode' => __DIR__ . '/..' . '/latte/latte/src/Latte/Essential/Nodes/DefineNode.php', + 'Latte\\Essential\\Nodes\\DoNode' => __DIR__ . '/..' . '/latte/latte/src/Latte/Essential/Nodes/DoNode.php', + 'Latte\\Essential\\Nodes\\DumpNode' => __DIR__ . '/..' . '/latte/latte/src/Latte/Essential/Nodes/DumpNode.php', + 'Latte\\Essential\\Nodes\\EmbedNode' => __DIR__ . '/..' . '/latte/latte/src/Latte/Essential/Nodes/EmbedNode.php', + 'Latte\\Essential\\Nodes\\ExtendsNode' => __DIR__ . '/..' . '/latte/latte/src/Latte/Essential/Nodes/ExtendsNode.php', + 'Latte\\Essential\\Nodes\\FirstLastSepNode' => __DIR__ . '/..' . '/latte/latte/src/Latte/Essential/Nodes/FirstLastSepNode.php', + 'Latte\\Essential\\Nodes\\ForNode' => __DIR__ . '/..' . '/latte/latte/src/Latte/Essential/Nodes/ForNode.php', + 'Latte\\Essential\\Nodes\\ForeachNode' => __DIR__ . '/..' . '/latte/latte/src/Latte/Essential/Nodes/ForeachNode.php', + 'Latte\\Essential\\Nodes\\IfChangedNode' => __DIR__ . '/..' . '/latte/latte/src/Latte/Essential/Nodes/IfChangedNode.php', + 'Latte\\Essential\\Nodes\\IfContentNode' => __DIR__ . '/..' . '/latte/latte/src/Latte/Essential/Nodes/IfContentNode.php', + 'Latte\\Essential\\Nodes\\IfNode' => __DIR__ . '/..' . '/latte/latte/src/Latte/Essential/Nodes/IfNode.php', + 'Latte\\Essential\\Nodes\\ImportNode' => __DIR__ . '/..' . '/latte/latte/src/Latte/Essential/Nodes/ImportNode.php', + 'Latte\\Essential\\Nodes\\IncludeBlockNode' => __DIR__ . '/..' . '/latte/latte/src/Latte/Essential/Nodes/IncludeBlockNode.php', + 'Latte\\Essential\\Nodes\\IncludeFileNode' => __DIR__ . '/..' . '/latte/latte/src/Latte/Essential/Nodes/IncludeFileNode.php', + 'Latte\\Essential\\Nodes\\IterateWhileNode' => __DIR__ . '/..' . '/latte/latte/src/Latte/Essential/Nodes/IterateWhileNode.php', + 'Latte\\Essential\\Nodes\\JumpNode' => __DIR__ . '/..' . '/latte/latte/src/Latte/Essential/Nodes/JumpNode.php', + 'Latte\\Essential\\Nodes\\NAttrNode' => __DIR__ . '/..' . '/latte/latte/src/Latte/Essential/Nodes/NAttrNode.php', + 'Latte\\Essential\\Nodes\\NClassNode' => __DIR__ . '/..' . '/latte/latte/src/Latte/Essential/Nodes/NClassNode.php', + 'Latte\\Essential\\Nodes\\NElseNode' => __DIR__ . '/..' . '/latte/latte/src/Latte/Essential/Nodes/NElseNode.php', + 'Latte\\Essential\\Nodes\\NTagNode' => __DIR__ . '/..' . '/latte/latte/src/Latte/Essential/Nodes/NTagNode.php', + 'Latte\\Essential\\Nodes\\ParametersNode' => __DIR__ . '/..' . '/latte/latte/src/Latte/Essential/Nodes/ParametersNode.php', + 'Latte\\Essential\\Nodes\\RawPhpNode' => __DIR__ . '/..' . '/latte/latte/src/Latte/Essential/Nodes/RawPhpNode.php', + 'Latte\\Essential\\Nodes\\RollbackNode' => __DIR__ . '/..' . '/latte/latte/src/Latte/Essential/Nodes/RollbackNode.php', + 'Latte\\Essential\\Nodes\\SpacelessNode' => __DIR__ . '/..' . '/latte/latte/src/Latte/Essential/Nodes/SpacelessNode.php', + 'Latte\\Essential\\Nodes\\SwitchNode' => __DIR__ . '/..' . '/latte/latte/src/Latte/Essential/Nodes/SwitchNode.php', + 'Latte\\Essential\\Nodes\\TemplatePrintNode' => __DIR__ . '/..' . '/latte/latte/src/Latte/Essential/Nodes/TemplatePrintNode.php', + 'Latte\\Essential\\Nodes\\TemplateTypeNode' => __DIR__ . '/..' . '/latte/latte/src/Latte/Essential/Nodes/TemplateTypeNode.php', + 'Latte\\Essential\\Nodes\\TraceNode' => __DIR__ . '/..' . '/latte/latte/src/Latte/Essential/Nodes/TraceNode.php', + 'Latte\\Essential\\Nodes\\TranslateNode' => __DIR__ . '/..' . '/latte/latte/src/Latte/Essential/Nodes/TranslateNode.php', + 'Latte\\Essential\\Nodes\\TryNode' => __DIR__ . '/..' . '/latte/latte/src/Latte/Essential/Nodes/TryNode.php', + 'Latte\\Essential\\Nodes\\VarNode' => __DIR__ . '/..' . '/latte/latte/src/Latte/Essential/Nodes/VarNode.php', + 'Latte\\Essential\\Nodes\\VarPrintNode' => __DIR__ . '/..' . '/latte/latte/src/Latte/Essential/Nodes/VarPrintNode.php', + 'Latte\\Essential\\Nodes\\VarTypeNode' => __DIR__ . '/..' . '/latte/latte/src/Latte/Essential/Nodes/VarTypeNode.php', + 'Latte\\Essential\\Nodes\\WhileNode' => __DIR__ . '/..' . '/latte/latte/src/Latte/Essential/Nodes/WhileNode.php', + 'Latte\\Essential\\Passes' => __DIR__ . '/..' . '/latte/latte/src/Latte/Essential/Passes.php', + 'Latte\\Essential\\RawPhpExtension' => __DIR__ . '/..' . '/latte/latte/src/Latte/Essential/RawPhpExtension.php', + 'Latte\\Essential\\RollbackException' => __DIR__ . '/..' . '/latte/latte/src/Latte/Essential/RollbackException.php', + 'Latte\\Essential\\Tracer' => __DIR__ . '/..' . '/latte/latte/src/Latte/Essential/Tracer.php', + 'Latte\\Essential\\TranslatorExtension' => __DIR__ . '/..' . '/latte/latte/src/Latte/Essential/TranslatorExtension.php', + 'Latte\\Exception' => __DIR__ . '/..' . '/latte/latte/src/Latte/exceptions.php', + 'Latte\\Extension' => __DIR__ . '/..' . '/latte/latte/src/Latte/Extension.php', + 'Latte\\Helpers' => __DIR__ . '/..' . '/latte/latte/src/Latte/Helpers.php', + 'Latte\\Loader' => __DIR__ . '/..' . '/latte/latte/src/Latte/Loader.php', + 'Latte\\Loaders\\FileLoader' => __DIR__ . '/..' . '/latte/latte/src/Latte/Loaders/FileLoader.php', + 'Latte\\Loaders\\StringLoader' => __DIR__ . '/..' . '/latte/latte/src/Latte/Loaders/StringLoader.php', + 'Latte\\Policy' => __DIR__ . '/..' . '/latte/latte/src/Latte/Policy.php', + 'Latte\\PositionAwareException' => __DIR__ . '/..' . '/latte/latte/src/Latte/PositionAwareException.php', + 'Latte\\RuntimeException' => __DIR__ . '/..' . '/latte/latte/src/Latte/exceptions.php', + 'Latte\\Runtime\\Block' => __DIR__ . '/..' . '/latte/latte/src/Latte/Runtime/Block.php', + 'Latte\\Runtime\\FilterExecutor' => __DIR__ . '/..' . '/latte/latte/src/Latte/Runtime/FilterExecutor.php', + 'Latte\\Runtime\\FilterInfo' => __DIR__ . '/..' . '/latte/latte/src/Latte/Runtime/FilterInfo.php', + 'Latte\\Runtime\\FunctionExecutor' => __DIR__ . '/..' . '/latte/latte/src/Latte/Runtime/FunctionExecutor.php', + 'Latte\\Runtime\\Helpers' => __DIR__ . '/..' . '/latte/latte/src/Latte/Runtime/Helpers.php', + 'Latte\\Runtime\\Html' => __DIR__ . '/..' . '/latte/latte/src/Latte/Runtime/Html.php', + 'Latte\\Runtime\\HtmlHelpers' => __DIR__ . '/..' . '/latte/latte/src/Latte/Runtime/HtmlHelpers.php', + 'Latte\\Runtime\\HtmlStringable' => __DIR__ . '/..' . '/latte/latte/src/Latte/Runtime/HtmlStringable.php', + 'Latte\\Runtime\\Template' => __DIR__ . '/..' . '/latte/latte/src/Latte/Runtime/Template.php', + 'Latte\\Runtime\\XmlHelpers' => __DIR__ . '/..' . '/latte/latte/src/Latte/Runtime/XmlHelpers.php', + 'Latte\\Sandbox\\Nodes\\FunctionCallNode' => __DIR__ . '/..' . '/latte/latte/src/Latte/Sandbox/Nodes/FunctionCallNode.php', + 'Latte\\Sandbox\\Nodes\\MethodCallNode' => __DIR__ . '/..' . '/latte/latte/src/Latte/Sandbox/Nodes/MethodCallNode.php', + 'Latte\\Sandbox\\Nodes\\PropertyFetchNode' => __DIR__ . '/..' . '/latte/latte/src/Latte/Sandbox/Nodes/PropertyFetchNode.php', + 'Latte\\Sandbox\\Nodes\\SandboxNode' => __DIR__ . '/..' . '/latte/latte/src/Latte/Sandbox/Nodes/SandboxNode.php', + 'Latte\\Sandbox\\Nodes\\StaticMethodCallNode' => __DIR__ . '/..' . '/latte/latte/src/Latte/Sandbox/Nodes/StaticMethodCallNode.php', + 'Latte\\Sandbox\\Nodes\\StaticPropertyFetchNode' => __DIR__ . '/..' . '/latte/latte/src/Latte/Sandbox/Nodes/StaticPropertyFetchNode.php', + 'Latte\\Sandbox\\RuntimeChecker' => __DIR__ . '/..' . '/latte/latte/src/Latte/Sandbox/RuntimeChecker.php', + 'Latte\\Sandbox\\SandboxExtension' => __DIR__ . '/..' . '/latte/latte/src/Latte/Sandbox/SandboxExtension.php', + 'Latte\\Sandbox\\SecurityPolicy' => __DIR__ . '/..' . '/latte/latte/src/Latte/Sandbox/SecurityPolicy.php', + 'Latte\\SecurityViolationException' => __DIR__ . '/..' . '/latte/latte/src/Latte/exceptions.php', + 'Latte\\TemplateNotFoundException' => __DIR__ . '/..' . '/latte/latte/src/Latte/exceptions.php', + 'Latte\\Tools\\Linter' => __DIR__ . '/..' . '/latte/latte/src/Tools/Linter.php', + 'Latte\\Tools\\LinterExtension' => __DIR__ . '/..' . '/latte/latte/src/Tools/LinterExtension.php', + 'NetteModule\\ErrorPresenter' => __DIR__ . '/..' . '/nette/application/src/Application/ErrorPresenter.php', + 'NetteModule\\MicroPresenter' => __DIR__ . '/..' . '/nette/application/src/Application/MicroPresenter.php', + 'Nette\\Application\\AbortException' => __DIR__ . '/..' . '/nette/application/src/Application/exceptions.php', + 'Nette\\Application\\Application' => __DIR__ . '/..' . '/nette/application/src/Application/Application.php', + 'Nette\\Application\\ApplicationException' => __DIR__ . '/..' . '/nette/application/src/Application/exceptions.php', + 'Nette\\Application\\Attributes\\CrossOrigin' => __DIR__ . '/..' . '/nette/application/src/Application/Attributes/CrossOrigin.php', + 'Nette\\Application\\Attributes\\Deprecated' => __DIR__ . '/..' . '/nette/application/src/Application/Attributes/Deprecated.php', + 'Nette\\Application\\Attributes\\Parameter' => __DIR__ . '/..' . '/nette/application/src/Application/Attributes/Parameter.php', + 'Nette\\Application\\Attributes\\Persistent' => __DIR__ . '/..' . '/nette/application/src/Application/Attributes/Persistent.php', + 'Nette\\Application\\Attributes\\Requires' => __DIR__ . '/..' . '/nette/application/src/Application/Attributes/Requires.php', + 'Nette\\Application\\Attributes\\TemplateVariable' => __DIR__ . '/..' . '/nette/application/src/Application/Attributes/TemplateVariable.php', + 'Nette\\Application\\BadRequestException' => __DIR__ . '/..' . '/nette/application/src/Application/exceptions.php', + 'Nette\\Application\\ForbiddenRequestException' => __DIR__ . '/..' . '/nette/application/src/Application/exceptions.php', + 'Nette\\Application\\Helpers' => __DIR__ . '/..' . '/nette/application/src/Application/Helpers.php', + 'Nette\\Application\\IPresenter' => __DIR__ . '/..' . '/nette/application/src/Application/IPresenter.php', + 'Nette\\Application\\IPresenterFactory' => __DIR__ . '/..' . '/nette/application/src/Application/IPresenterFactory.php', + 'Nette\\Application\\IResponse' => __DIR__ . '/..' . '/nette/application/src/compatibility-intf.php', + 'Nette\\Application\\IRouter' => __DIR__ . '/..' . '/nette/application/src/compatibility-intf.php', + 'Nette\\Application\\InvalidPresenterException' => __DIR__ . '/..' . '/nette/application/src/Application/exceptions.php', + 'Nette\\Application\\LinkGenerator' => __DIR__ . '/..' . '/nette/application/src/Application/LinkGenerator.php', + 'Nette\\Application\\PresenterFactory' => __DIR__ . '/..' . '/nette/application/src/Application/PresenterFactory.php', + 'Nette\\Application\\Request' => __DIR__ . '/..' . '/nette/application/src/Application/Request.php', + 'Nette\\Application\\Response' => __DIR__ . '/..' . '/nette/application/src/Application/Response.php', + 'Nette\\Application\\Responses\\CallbackResponse' => __DIR__ . '/..' . '/nette/application/src/Application/Responses/CallbackResponse.php', + 'Nette\\Application\\Responses\\FileResponse' => __DIR__ . '/..' . '/nette/application/src/Application/Responses/FileResponse.php', + 'Nette\\Application\\Responses\\ForwardResponse' => __DIR__ . '/..' . '/nette/application/src/Application/Responses/ForwardResponse.php', + 'Nette\\Application\\Responses\\JsonResponse' => __DIR__ . '/..' . '/nette/application/src/Application/Responses/JsonResponse.php', + 'Nette\\Application\\Responses\\RedirectResponse' => __DIR__ . '/..' . '/nette/application/src/Application/Responses/RedirectResponse.php', + 'Nette\\Application\\Responses\\TextResponse' => __DIR__ . '/..' . '/nette/application/src/Application/Responses/TextResponse.php', + 'Nette\\Application\\Responses\\VoidResponse' => __DIR__ . '/..' . '/nette/application/src/Application/Responses/VoidResponse.php', + 'Nette\\Application\\Routers\\CliRouter' => __DIR__ . '/..' . '/nette/application/src/Application/Routers/CliRouter.php', + 'Nette\\Application\\Routers\\Route' => __DIR__ . '/..' . '/nette/application/src/Application/Routers/Route.php', + 'Nette\\Application\\Routers\\RouteList' => __DIR__ . '/..' . '/nette/application/src/Application/Routers/RouteList.php', + 'Nette\\Application\\Routers\\SimpleRouter' => __DIR__ . '/..' . '/nette/application/src/Application/Routers/SimpleRouter.php', + 'Nette\\Application\\SwitchException' => __DIR__ . '/..' . '/nette/application/src/Application/exceptions.php', + 'Nette\\Application\\UI\\AccessPolicy' => __DIR__ . '/..' . '/nette/application/src/Application/UI/AccessPolicy.php', + 'Nette\\Application\\UI\\BadSignalException' => __DIR__ . '/..' . '/nette/application/src/Application/UI/BadSignalException.php', + 'Nette\\Application\\UI\\Component' => __DIR__ . '/..' . '/nette/application/src/Application/UI/Component.php', + 'Nette\\Application\\UI\\ComponentReflection' => __DIR__ . '/..' . '/nette/application/src/Application/UI/ComponentReflection.php', + 'Nette\\Application\\UI\\Control' => __DIR__ . '/..' . '/nette/application/src/Application/UI/Control.php', + 'Nette\\Application\\UI\\Form' => __DIR__ . '/..' . '/nette/application/src/Application/UI/Form.php', + 'Nette\\Application\\UI\\IRenderable' => __DIR__ . '/..' . '/nette/application/src/compatibility-intf.php', + 'Nette\\Application\\UI\\ISignalReceiver' => __DIR__ . '/..' . '/nette/application/src/compatibility-intf.php', + 'Nette\\Application\\UI\\IStatePersistent' => __DIR__ . '/..' . '/nette/application/src/compatibility-intf.php', + 'Nette\\Application\\UI\\ITemplate' => __DIR__ . '/..' . '/nette/application/src/compatibility-intf.php', + 'Nette\\Application\\UI\\ITemplateFactory' => __DIR__ . '/..' . '/nette/application/src/compatibility-intf.php', + 'Nette\\Application\\UI\\InvalidLinkException' => __DIR__ . '/..' . '/nette/application/src/Application/UI/InvalidLinkException.php', + 'Nette\\Application\\UI\\Link' => __DIR__ . '/..' . '/nette/application/src/Application/UI/Link.php', + 'Nette\\Application\\UI\\MethodReflection' => __DIR__ . '/..' . '/nette/application/src/Application/UI/MethodReflection.php', + 'Nette\\Application\\UI\\Multiplier' => __DIR__ . '/..' . '/nette/application/src/Application/UI/Multiplier.php', + 'Nette\\Application\\UI\\ParameterConverter' => __DIR__ . '/..' . '/nette/application/src/Application/UI/ParameterConverter.php', + 'Nette\\Application\\UI\\Presenter' => __DIR__ . '/..' . '/nette/application/src/Application/UI/Presenter.php', + 'Nette\\Application\\UI\\PresenterComponent' => __DIR__ . '/..' . '/nette/application/src/compatibility.php', + 'Nette\\Application\\UI\\PresenterComponentReflection' => __DIR__ . '/..' . '/nette/application/src/compatibility.php', + 'Nette\\Application\\UI\\Renderable' => __DIR__ . '/..' . '/nette/application/src/Application/UI/Renderable.php', + 'Nette\\Application\\UI\\SignalReceiver' => __DIR__ . '/..' . '/nette/application/src/Application/UI/SignalReceiver.php', + 'Nette\\Application\\UI\\StatePersistent' => __DIR__ . '/..' . '/nette/application/src/Application/UI/StatePersistent.php', + 'Nette\\Application\\UI\\Template' => __DIR__ . '/..' . '/nette/application/src/Application/UI/Template.php', + 'Nette\\Application\\UI\\TemplateFactory' => __DIR__ . '/..' . '/nette/application/src/Application/UI/TemplateFactory.php', + 'Nette\\ArgumentOutOfRangeException' => __DIR__ . '/..' . '/nette/utils/src/exceptions.php', + 'Nette\\Assets\\Asset' => __DIR__ . '/..' . '/nette/assets/src/Assets/Asset.php', + 'Nette\\Assets\\AssetNotFoundException' => __DIR__ . '/..' . '/nette/assets/src/Assets/exceptions.php', + 'Nette\\Assets\\AudioAsset' => __DIR__ . '/..' . '/nette/assets/src/Assets/AudioAsset.php', + 'Nette\\Assets\\EntryAsset' => __DIR__ . '/..' . '/nette/assets/src/Assets/EntryAsset.php', + 'Nette\\Assets\\FilesystemMapper' => __DIR__ . '/..' . '/nette/assets/src/Assets/FilesystemMapper.php', + 'Nette\\Assets\\FontAsset' => __DIR__ . '/..' . '/nette/assets/src/Assets/FontAsset.php', + 'Nette\\Assets\\GenericAsset' => __DIR__ . '/..' . '/nette/assets/src/Assets/GenericAsset.php', + 'Nette\\Assets\\Helpers' => __DIR__ . '/..' . '/nette/assets/src/Assets/Helpers.php', + 'Nette\\Assets\\HtmlRenderable' => __DIR__ . '/..' . '/nette/assets/src/Assets/HtmlRenderable.php', + 'Nette\\Assets\\ImageAsset' => __DIR__ . '/..' . '/nette/assets/src/Assets/ImageAsset.php', + 'Nette\\Assets\\LazyLoad' => __DIR__ . '/..' . '/nette/assets/src/Assets/LazyLoad.php', + 'Nette\\Assets\\Mapper' => __DIR__ . '/..' . '/nette/assets/src/Assets/Mapper.php', + 'Nette\\Assets\\Registry' => __DIR__ . '/..' . '/nette/assets/src/Assets/Registry.php', + 'Nette\\Assets\\ScriptAsset' => __DIR__ . '/..' . '/nette/assets/src/Assets/ScriptAsset.php', + 'Nette\\Assets\\StyleAsset' => __DIR__ . '/..' . '/nette/assets/src/Assets/StyleAsset.php', + 'Nette\\Assets\\VideoAsset' => __DIR__ . '/..' . '/nette/assets/src/Assets/VideoAsset.php', + 'Nette\\Assets\\ViteMapper' => __DIR__ . '/..' . '/nette/assets/src/Assets/ViteMapper.php', + 'Nette\\Bootstrap\\Configurator' => __DIR__ . '/..' . '/nette/bootstrap/src/Bootstrap/Configurator.php', + 'Nette\\Bootstrap\\Extensions\\ConstantsExtension' => __DIR__ . '/..' . '/nette/bootstrap/src/Bootstrap/Extensions/ConstantsExtension.php', + 'Nette\\Bootstrap\\Extensions\\PhpExtension' => __DIR__ . '/..' . '/nette/bootstrap/src/Bootstrap/Extensions/PhpExtension.php', + 'Nette\\Bridges\\ApplicationDI\\ApplicationExtension' => __DIR__ . '/..' . '/nette/application/src/Bridges/ApplicationDI/ApplicationExtension.php', + 'Nette\\Bridges\\ApplicationDI\\LatteExtension' => __DIR__ . '/..' . '/nette/application/src/Bridges/ApplicationDI/LatteExtension.php', + 'Nette\\Bridges\\ApplicationDI\\PresenterFactoryCallback' => __DIR__ . '/..' . '/nette/application/src/Bridges/ApplicationDI/PresenterFactoryCallback.php', + 'Nette\\Bridges\\ApplicationDI\\RoutingExtension' => __DIR__ . '/..' . '/nette/application/src/Bridges/ApplicationDI/RoutingExtension.php', + 'Nette\\Bridges\\ApplicationLatte\\DefaultTemplate' => __DIR__ . '/..' . '/nette/application/src/Bridges/ApplicationLatte/DefaultTemplate.php', + 'Nette\\Bridges\\ApplicationLatte\\ILatteFactory' => __DIR__ . '/..' . '/nette/application/src/compatibility-intf.php', + 'Nette\\Bridges\\ApplicationLatte\\LatteFactory' => __DIR__ . '/..' . '/nette/application/src/Bridges/ApplicationLatte/LatteFactory.php', + 'Nette\\Bridges\\ApplicationLatte\\Nodes\\ControlNode' => __DIR__ . '/..' . '/nette/application/src/Bridges/ApplicationLatte/Nodes/ControlNode.php', + 'Nette\\Bridges\\ApplicationLatte\\Nodes\\IfCurrentNode' => __DIR__ . '/..' . '/nette/application/src/Bridges/ApplicationLatte/Nodes/IfCurrentNode.php', + 'Nette\\Bridges\\ApplicationLatte\\Nodes\\LinkBaseNode' => __DIR__ . '/..' . '/nette/application/src/Bridges/ApplicationLatte/Nodes/LinkBaseNode.php', + 'Nette\\Bridges\\ApplicationLatte\\Nodes\\LinkNode' => __DIR__ . '/..' . '/nette/application/src/Bridges/ApplicationLatte/Nodes/LinkNode.php', + 'Nette\\Bridges\\ApplicationLatte\\Nodes\\NNonceNode' => __DIR__ . '/..' . '/nette/application/src/Bridges/ApplicationLatte/Nodes/NNonceNode.php', + 'Nette\\Bridges\\ApplicationLatte\\Nodes\\SnippetAreaNode' => __DIR__ . '/..' . '/nette/application/src/Bridges/ApplicationLatte/Nodes/SnippetAreaNode.php', + 'Nette\\Bridges\\ApplicationLatte\\Nodes\\SnippetNode' => __DIR__ . '/..' . '/nette/application/src/Bridges/ApplicationLatte/Nodes/SnippetNode.php', + 'Nette\\Bridges\\ApplicationLatte\\Nodes\\TemplatePrintNode' => __DIR__ . '/..' . '/nette/application/src/Bridges/ApplicationLatte/Nodes/TemplatePrintNode.php', + 'Nette\\Bridges\\ApplicationLatte\\SnippetBridge' => __DIR__ . '/..' . '/nette/application/src/Bridges/ApplicationLatte/SnippetBridge.php', + 'Nette\\Bridges\\ApplicationLatte\\SnippetRuntime' => __DIR__ . '/..' . '/nette/application/src/Bridges/ApplicationLatte/SnippetRuntime.php', + 'Nette\\Bridges\\ApplicationLatte\\Template' => __DIR__ . '/..' . '/nette/application/src/Bridges/ApplicationLatte/Template.php', + 'Nette\\Bridges\\ApplicationLatte\\TemplateFactory' => __DIR__ . '/..' . '/nette/application/src/Bridges/ApplicationLatte/TemplateFactory.php', + 'Nette\\Bridges\\ApplicationLatte\\UIExtension' => __DIR__ . '/..' . '/nette/application/src/Bridges/ApplicationLatte/UIExtension.php', + 'Nette\\Bridges\\ApplicationLatte\\UIMacros' => __DIR__ . '/..' . '/nette/application/src/Bridges/ApplicationLatte/UIMacros.php', + 'Nette\\Bridges\\ApplicationLatte\\UIRuntime' => __DIR__ . '/..' . '/nette/application/src/Bridges/ApplicationLatte/UIRuntime.php', + 'Nette\\Bridges\\ApplicationTracy\\RoutingPanel' => __DIR__ . '/..' . '/nette/application/src/Bridges/ApplicationTracy/RoutingPanel.php', + 'Nette\\Bridges\\AssetsDI\\DIExtension' => __DIR__ . '/..' . '/nette/assets/src/Bridges/AssetsDI/DIExtension.php', + 'Nette\\Bridges\\AssetsLatte\\LatteExtension' => __DIR__ . '/..' . '/nette/assets/src/Bridges/AssetsLatte/LatteExtension.php', + 'Nette\\Bridges\\AssetsLatte\\Nodes\\AssetNode' => __DIR__ . '/..' . '/nette/assets/src/Bridges/AssetsLatte/Nodes/AssetNode.php', + 'Nette\\Bridges\\AssetsLatte\\Nodes\\NAssetNode' => __DIR__ . '/..' . '/nette/assets/src/Bridges/AssetsLatte/Nodes/NAssetNode.php', + 'Nette\\Bridges\\AssetsLatte\\Runtime' => __DIR__ . '/..' . '/nette/assets/src/Bridges/AssetsLatte/Runtime.php', + 'Nette\\Bridges\\CacheDI\\CacheExtension' => __DIR__ . '/..' . '/nette/caching/src/Bridges/CacheDI/CacheExtension.php', + 'Nette\\Bridges\\CacheLatte\\CacheExtension' => __DIR__ . '/..' . '/nette/caching/src/Bridges/CacheLatte/CacheExtension.php', + 'Nette\\Bridges\\CacheLatte\\Nodes\\CacheNode' => __DIR__ . '/..' . '/nette/caching/src/Bridges/CacheLatte/Nodes/CacheNode.php', + 'Nette\\Bridges\\CacheLatte\\Runtime' => __DIR__ . '/..' . '/nette/caching/src/Bridges/CacheLatte/Runtime.php', + 'Nette\\Bridges\\DITracy\\ContainerPanel' => __DIR__ . '/..' . '/nette/di/src/Bridges/DITracy/ContainerPanel.php', + 'Nette\\Bridges\\DatabaseDI\\DatabaseExtension' => __DIR__ . '/..' . '/nette/database/src/Bridges/DatabaseDI/DatabaseExtension.php', + 'Nette\\Bridges\\DatabaseTracy\\ConnectionPanel' => __DIR__ . '/..' . '/nette/database/src/Bridges/DatabaseTracy/ConnectionPanel.php', + 'Nette\\Bridges\\FormsDI\\FormsExtension' => __DIR__ . '/..' . '/nette/forms/src/Bridges/FormsDI/FormsExtension.php', + 'Nette\\Bridges\\FormsLatte\\FormMacros' => __DIR__ . '/..' . '/nette/forms/src/Bridges/FormsLatte/FormMacros.php', + 'Nette\\Bridges\\FormsLatte\\FormsExtension' => __DIR__ . '/..' . '/nette/forms/src/Bridges/FormsLatte/FormsExtension.php', + 'Nette\\Bridges\\FormsLatte\\Nodes\\FieldNNameNode' => __DIR__ . '/..' . '/nette/forms/src/Bridges/FormsLatte/Nodes/FieldNNameNode.php', + 'Nette\\Bridges\\FormsLatte\\Nodes\\FormContainerNode' => __DIR__ . '/..' . '/nette/forms/src/Bridges/FormsLatte/Nodes/FormContainerNode.php', + 'Nette\\Bridges\\FormsLatte\\Nodes\\FormNNameNode' => __DIR__ . '/..' . '/nette/forms/src/Bridges/FormsLatte/Nodes/FormNNameNode.php', + 'Nette\\Bridges\\FormsLatte\\Nodes\\FormNode' => __DIR__ . '/..' . '/nette/forms/src/Bridges/FormsLatte/Nodes/FormNode.php', + 'Nette\\Bridges\\FormsLatte\\Nodes\\FormPrintNode' => __DIR__ . '/..' . '/nette/forms/src/Bridges/FormsLatte/Nodes/FormPrintNode.php', + 'Nette\\Bridges\\FormsLatte\\Nodes\\InputErrorNode' => __DIR__ . '/..' . '/nette/forms/src/Bridges/FormsLatte/Nodes/InputErrorNode.php', + 'Nette\\Bridges\\FormsLatte\\Nodes\\InputNode' => __DIR__ . '/..' . '/nette/forms/src/Bridges/FormsLatte/Nodes/InputNode.php', + 'Nette\\Bridges\\FormsLatte\\Nodes\\LabelNode' => __DIR__ . '/..' . '/nette/forms/src/Bridges/FormsLatte/Nodes/LabelNode.php', + 'Nette\\Bridges\\FormsLatte\\Runtime' => __DIR__ . '/..' . '/nette/forms/src/Bridges/FormsLatte/Runtime.php', + 'Nette\\Bridges\\HttpDI\\HttpExtension' => __DIR__ . '/..' . '/nette/http/src/Bridges/HttpDI/HttpExtension.php', + 'Nette\\Bridges\\HttpDI\\SessionExtension' => __DIR__ . '/..' . '/nette/http/src/Bridges/HttpDI/SessionExtension.php', + 'Nette\\Bridges\\HttpTracy\\SessionPanel' => __DIR__ . '/..' . '/nette/http/src/Bridges/HttpTracy/SessionPanel.php', + 'Nette\\Bridges\\MailDI\\MailExtension' => __DIR__ . '/..' . '/nette/mail/src/Bridges/MailDI/MailExtension.php', + 'Nette\\Bridges\\Psr\\PsrCacheAdapter' => __DIR__ . '/..' . '/nette/caching/src/Bridges/Psr/PsrCacheAdapter.php', + 'Nette\\Bridges\\SecurityDI\\SecurityExtension' => __DIR__ . '/..' . '/nette/security/src/Bridges/SecurityDI/SecurityExtension.php', + 'Nette\\Bridges\\SecurityHttp\\CookieStorage' => __DIR__ . '/..' . '/nette/security/src/Bridges/SecurityHttp/CookieStorage.php', + 'Nette\\Bridges\\SecurityHttp\\SessionStorage' => __DIR__ . '/..' . '/nette/security/src/Bridges/SecurityHttp/SessionStorage.php', + 'Nette\\Bridges\\SecurityTracy\\UserPanel' => __DIR__ . '/..' . '/nette/security/src/Bridges/SecurityTracy/UserPanel.php', + 'Nette\\Caching\\BulkReader' => __DIR__ . '/..' . '/nette/caching/src/Caching/BulkReader.php', + 'Nette\\Caching\\BulkWriter' => __DIR__ . '/..' . '/nette/caching/src/Caching/BulkWriter.php', + 'Nette\\Caching\\Cache' => __DIR__ . '/..' . '/nette/caching/src/Caching/Cache.php', + 'Nette\\Caching\\IBulkReader' => __DIR__ . '/..' . '/nette/caching/src/compatibility.php', + 'Nette\\Caching\\IStorage' => __DIR__ . '/..' . '/nette/caching/src/compatibility.php', + 'Nette\\Caching\\OutputHelper' => __DIR__ . '/..' . '/nette/caching/src/Caching/OutputHelper.php', + 'Nette\\Caching\\Storage' => __DIR__ . '/..' . '/nette/caching/src/Caching/Storage.php', + 'Nette\\Caching\\Storages\\DevNullStorage' => __DIR__ . '/..' . '/nette/caching/src/Caching/Storages/DevNullStorage.php', + 'Nette\\Caching\\Storages\\FileStorage' => __DIR__ . '/..' . '/nette/caching/src/Caching/Storages/FileStorage.php', + 'Nette\\Caching\\Storages\\IJournal' => __DIR__ . '/..' . '/nette/caching/src/compatibility.php', + 'Nette\\Caching\\Storages\\Journal' => __DIR__ . '/..' . '/nette/caching/src/Caching/Storages/Journal.php', + 'Nette\\Caching\\Storages\\MemcachedStorage' => __DIR__ . '/..' . '/nette/caching/src/Caching/Storages/MemcachedStorage.php', + 'Nette\\Caching\\Storages\\MemoryStorage' => __DIR__ . '/..' . '/nette/caching/src/Caching/Storages/MemoryStorage.php', + 'Nette\\Caching\\Storages\\SQLiteJournal' => __DIR__ . '/..' . '/nette/caching/src/Caching/Storages/SQLiteJournal.php', + 'Nette\\Caching\\Storages\\SQLiteStorage' => __DIR__ . '/..' . '/nette/caching/src/Caching/Storages/SQLiteStorage.php', + 'Nette\\ComponentModel\\ArrayAccess' => __DIR__ . '/..' . '/nette/component-model/src/ComponentModel/ArrayAccess.php', + 'Nette\\ComponentModel\\Component' => __DIR__ . '/..' . '/nette/component-model/src/ComponentModel/Component.php', + 'Nette\\ComponentModel\\Container' => __DIR__ . '/..' . '/nette/component-model/src/ComponentModel/Container.php', + 'Nette\\ComponentModel\\IComponent' => __DIR__ . '/..' . '/nette/component-model/src/ComponentModel/IComponent.php', + 'Nette\\ComponentModel\\IContainer' => __DIR__ . '/..' . '/nette/component-model/src/ComponentModel/IContainer.php', + 'Nette\\ComponentModel\\RecursiveComponentIterator' => __DIR__ . '/..' . '/nette/component-model/src/ComponentModel/RecursiveComponentIterator.php', + 'Nette\\Configurator' => __DIR__ . '/..' . '/nette/bootstrap/src/Configurator.php', + 'Nette\\DI\\Attributes\\Inject' => __DIR__ . '/..' . '/nette/di/src/DI/Attributes/Inject.php', + 'Nette\\DI\\Autowiring' => __DIR__ . '/..' . '/nette/di/src/DI/Autowiring.php', + 'Nette\\DI\\Compiler' => __DIR__ . '/..' . '/nette/di/src/DI/Compiler.php', + 'Nette\\DI\\CompilerExtension' => __DIR__ . '/..' . '/nette/di/src/DI/CompilerExtension.php', + 'Nette\\DI\\Config\\Adapter' => __DIR__ . '/..' . '/nette/di/src/DI/Config/Adapter.php', + 'Nette\\DI\\Config\\Adapters\\NeonAdapter' => __DIR__ . '/..' . '/nette/di/src/DI/Config/Adapters/NeonAdapter.php', + 'Nette\\DI\\Config\\Adapters\\PhpAdapter' => __DIR__ . '/..' . '/nette/di/src/DI/Config/Adapters/PhpAdapter.php', + 'Nette\\DI\\Config\\Helpers' => __DIR__ . '/..' . '/nette/di/src/DI/Config/Helpers.php', + 'Nette\\DI\\Config\\IAdapter' => __DIR__ . '/..' . '/nette/di/src/compatibility.php', + 'Nette\\DI\\Config\\Loader' => __DIR__ . '/..' . '/nette/di/src/DI/Config/Loader.php', + 'Nette\\DI\\Container' => __DIR__ . '/..' . '/nette/di/src/DI/Container.php', + 'Nette\\DI\\ContainerBuilder' => __DIR__ . '/..' . '/nette/di/src/DI/ContainerBuilder.php', + 'Nette\\DI\\ContainerLoader' => __DIR__ . '/..' . '/nette/di/src/DI/ContainerLoader.php', + 'Nette\\DI\\Definitions\\AccessorDefinition' => __DIR__ . '/..' . '/nette/di/src/DI/Definitions/AccessorDefinition.php', + 'Nette\\DI\\Definitions\\Definition' => __DIR__ . '/..' . '/nette/di/src/DI/Definitions/Definition.php', + 'Nette\\DI\\Definitions\\FactoryDefinition' => __DIR__ . '/..' . '/nette/di/src/DI/Definitions/FactoryDefinition.php', + 'Nette\\DI\\Definitions\\ImportedDefinition' => __DIR__ . '/..' . '/nette/di/src/DI/Definitions/ImportedDefinition.php', + 'Nette\\DI\\Definitions\\LocatorDefinition' => __DIR__ . '/..' . '/nette/di/src/DI/Definitions/LocatorDefinition.php', + 'Nette\\DI\\Definitions\\Reference' => __DIR__ . '/..' . '/nette/di/src/DI/Definitions/Reference.php', + 'Nette\\DI\\Definitions\\ServiceDefinition' => __DIR__ . '/..' . '/nette/di/src/DI/Definitions/ServiceDefinition.php', + 'Nette\\DI\\Definitions\\Statement' => __DIR__ . '/..' . '/nette/di/src/DI/Definitions/Statement.php', + 'Nette\\DI\\DependencyChecker' => __DIR__ . '/..' . '/nette/di/src/DI/DependencyChecker.php', + 'Nette\\DI\\DynamicParameter' => __DIR__ . '/..' . '/nette/di/src/DI/DynamicParameter.php', + 'Nette\\DI\\Extensions\\DIExtension' => __DIR__ . '/..' . '/nette/di/src/DI/Extensions/DIExtension.php', + 'Nette\\DI\\Extensions\\DecoratorExtension' => __DIR__ . '/..' . '/nette/di/src/DI/Extensions/DecoratorExtension.php', + 'Nette\\DI\\Extensions\\DefinitionSchema' => __DIR__ . '/..' . '/nette/di/src/DI/Extensions/DefinitionSchema.php', + 'Nette\\DI\\Extensions\\ExtensionsExtension' => __DIR__ . '/..' . '/nette/di/src/DI/Extensions/ExtensionsExtension.php', + 'Nette\\DI\\Extensions\\InjectExtension' => __DIR__ . '/..' . '/nette/di/src/DI/Extensions/InjectExtension.php', + 'Nette\\DI\\Extensions\\ParametersExtension' => __DIR__ . '/..' . '/nette/di/src/DI/Extensions/ParametersExtension.php', + 'Nette\\DI\\Extensions\\SearchExtension' => __DIR__ . '/..' . '/nette/di/src/DI/Extensions/SearchExtension.php', + 'Nette\\DI\\Extensions\\ServicesExtension' => __DIR__ . '/..' . '/nette/di/src/DI/Extensions/ServicesExtension.php', + 'Nette\\DI\\Helpers' => __DIR__ . '/..' . '/nette/di/src/DI/Helpers.php', + 'Nette\\DI\\InvalidConfigurationException' => __DIR__ . '/..' . '/nette/di/src/DI/exceptions.php', + 'Nette\\DI\\MissingServiceException' => __DIR__ . '/..' . '/nette/di/src/DI/exceptions.php', + 'Nette\\DI\\NotAllowedDuringResolvingException' => __DIR__ . '/..' . '/nette/di/src/DI/exceptions.php', + 'Nette\\DI\\PhpGenerator' => __DIR__ . '/..' . '/nette/di/src/DI/PhpGenerator.php', + 'Nette\\DI\\Resolver' => __DIR__ . '/..' . '/nette/di/src/DI/Resolver.php', + 'Nette\\DI\\ServiceCreationException' => __DIR__ . '/..' . '/nette/di/src/DI/exceptions.php', + 'Nette\\DI\\ServiceDefinition' => __DIR__ . '/..' . '/nette/di/src/compatibility.php', + 'Nette\\DI\\Statement' => __DIR__ . '/..' . '/nette/di/src/compatibility.php', + 'Nette\\Database\\Connection' => __DIR__ . '/..' . '/nette/database/src/Database/Connection.php', + 'Nette\\Database\\ConnectionException' => __DIR__ . '/..' . '/nette/database/src/Database/exceptions.php', + 'Nette\\Database\\ConstraintViolationException' => __DIR__ . '/..' . '/nette/database/src/Database/exceptions.php', + 'Nette\\Database\\Context' => __DIR__ . '/..' . '/nette/database/src/compatibility.php', + 'Nette\\Database\\Conventions' => __DIR__ . '/..' . '/nette/database/src/Database/Conventions.php', + 'Nette\\Database\\Conventions\\AmbiguousReferenceKeyException' => __DIR__ . '/..' . '/nette/database/src/Database/Conventions/AmbiguousReferenceKeyException.php', + 'Nette\\Database\\Conventions\\DiscoveredConventions' => __DIR__ . '/..' . '/nette/database/src/Database/Conventions/DiscoveredConventions.php', + 'Nette\\Database\\Conventions\\StaticConventions' => __DIR__ . '/..' . '/nette/database/src/Database/Conventions/StaticConventions.php', + 'Nette\\Database\\DateTime' => __DIR__ . '/..' . '/nette/database/src/Database/DateTime.php', + 'Nette\\Database\\Driver' => __DIR__ . '/..' . '/nette/database/src/Database/Driver.php', + 'Nette\\Database\\DriverException' => __DIR__ . '/..' . '/nette/database/src/Database/DriverException.php', + 'Nette\\Database\\Drivers\\MsSqlDriver' => __DIR__ . '/..' . '/nette/database/src/Database/Drivers/MsSqlDriver.php', + 'Nette\\Database\\Drivers\\MySqlDriver' => __DIR__ . '/..' . '/nette/database/src/Database/Drivers/MySqlDriver.php', + 'Nette\\Database\\Drivers\\OciDriver' => __DIR__ . '/..' . '/nette/database/src/Database/Drivers/OciDriver.php', + 'Nette\\Database\\Drivers\\OdbcDriver' => __DIR__ . '/..' . '/nette/database/src/Database/Drivers/OdbcDriver.php', + 'Nette\\Database\\Drivers\\PgSqlDriver' => __DIR__ . '/..' . '/nette/database/src/Database/Drivers/PgSqlDriver.php', + 'Nette\\Database\\Drivers\\SqliteDriver' => __DIR__ . '/..' . '/nette/database/src/Database/Drivers/SqliteDriver.php', + 'Nette\\Database\\Drivers\\SqlsrvDriver' => __DIR__ . '/..' . '/nette/database/src/Database/Drivers/SqlsrvDriver.php', + 'Nette\\Database\\Explorer' => __DIR__ . '/..' . '/nette/database/src/Database/Explorer.php', + 'Nette\\Database\\ForeignKeyConstraintViolationException' => __DIR__ . '/..' . '/nette/database/src/Database/exceptions.php', + 'Nette\\Database\\Helpers' => __DIR__ . '/..' . '/nette/database/src/Database/Helpers.php', + 'Nette\\Database\\IConventions' => __DIR__ . '/..' . '/nette/database/src/compatibility-intf.php', + 'Nette\\Database\\IRow' => __DIR__ . '/..' . '/nette/database/src/Database/IRow.php', + 'Nette\\Database\\IRowContainer' => __DIR__ . '/..' . '/nette/database/src/Database/IRowContainer.php', + 'Nette\\Database\\IStructure' => __DIR__ . '/..' . '/nette/database/src/Database/IStructure.php', + 'Nette\\Database\\ISupplementalDriver' => __DIR__ . '/..' . '/nette/database/src/compatibility-intf.php', + 'Nette\\Database\\NotNullConstraintViolationException' => __DIR__ . '/..' . '/nette/database/src/Database/exceptions.php', + 'Nette\\Database\\Reflection' => __DIR__ . '/..' . '/nette/database/src/Database/Reflection.php', + 'Nette\\Database\\Reflection\\Column' => __DIR__ . '/..' . '/nette/database/src/Database/Reflection/Column.php', + 'Nette\\Database\\Reflection\\ForeignKey' => __DIR__ . '/..' . '/nette/database/src/Database/Reflection/ForeignKey.php', + 'Nette\\Database\\Reflection\\Index' => __DIR__ . '/..' . '/nette/database/src/Database/Reflection/Index.php', + 'Nette\\Database\\Reflection\\Table' => __DIR__ . '/..' . '/nette/database/src/Database/Reflection/Table.php', + 'Nette\\Database\\ResultSet' => __DIR__ . '/..' . '/nette/database/src/Database/ResultSet.php', + 'Nette\\Database\\Row' => __DIR__ . '/..' . '/nette/database/src/Database/Row.php', + 'Nette\\Database\\SqlLiteral' => __DIR__ . '/..' . '/nette/database/src/Database/SqlLiteral.php', + 'Nette\\Database\\SqlPreprocessor' => __DIR__ . '/..' . '/nette/database/src/Database/SqlPreprocessor.php', + 'Nette\\Database\\Structure' => __DIR__ . '/..' . '/nette/database/src/Database/Structure.php', + 'Nette\\Database\\Table\\ActiveRow' => __DIR__ . '/..' . '/nette/database/src/Database/Table/ActiveRow.php', + 'Nette\\Database\\Table\\GroupedSelection' => __DIR__ . '/..' . '/nette/database/src/Database/Table/GroupedSelection.php', + 'Nette\\Database\\Table\\IRow' => __DIR__ . '/..' . '/nette/database/src/Database/Table/IRow.php', + 'Nette\\Database\\Table\\IRowContainer' => __DIR__ . '/..' . '/nette/database/src/Database/Table/IRowContainer.php', + 'Nette\\Database\\Table\\Selection' => __DIR__ . '/..' . '/nette/database/src/Database/Table/Selection.php', + 'Nette\\Database\\Table\\SqlBuilder' => __DIR__ . '/..' . '/nette/database/src/Database/Table/SqlBuilder.php', + 'Nette\\Database\\UniqueConstraintViolationException' => __DIR__ . '/..' . '/nette/database/src/Database/exceptions.php', + 'Nette\\DeprecatedException' => __DIR__ . '/..' . '/nette/utils/src/exceptions.php', + 'Nette\\DirectoryNotFoundException' => __DIR__ . '/..' . '/nette/utils/src/exceptions.php', + 'Nette\\FileNotFoundException' => __DIR__ . '/..' . '/nette/utils/src/exceptions.php', + 'Nette\\Forms\\Blueprint' => __DIR__ . '/..' . '/nette/forms/src/Forms/Blueprint.php', + 'Nette\\Forms\\Container' => __DIR__ . '/..' . '/nette/forms/src/Forms/Container.php', + 'Nette\\Forms\\Control' => __DIR__ . '/..' . '/nette/forms/src/Forms/Control.php', + 'Nette\\Forms\\ControlGroup' => __DIR__ . '/..' . '/nette/forms/src/Forms/ControlGroup.php', + 'Nette\\Forms\\Controls\\BaseControl' => __DIR__ . '/..' . '/nette/forms/src/Forms/Controls/BaseControl.php', + 'Nette\\Forms\\Controls\\Button' => __DIR__ . '/..' . '/nette/forms/src/Forms/Controls/Button.php', + 'Nette\\Forms\\Controls\\Checkbox' => __DIR__ . '/..' . '/nette/forms/src/Forms/Controls/Checkbox.php', + 'Nette\\Forms\\Controls\\CheckboxList' => __DIR__ . '/..' . '/nette/forms/src/Forms/Controls/CheckboxList.php', + 'Nette\\Forms\\Controls\\ChoiceControl' => __DIR__ . '/..' . '/nette/forms/src/Forms/Controls/ChoiceControl.php', + 'Nette\\Forms\\Controls\\ColorPicker' => __DIR__ . '/..' . '/nette/forms/src/Forms/Controls/ColorPicker.php', + 'Nette\\Forms\\Controls\\CsrfProtection' => __DIR__ . '/..' . '/nette/forms/src/Forms/Controls/CsrfProtection.php', + 'Nette\\Forms\\Controls\\DateTimeControl' => __DIR__ . '/..' . '/nette/forms/src/Forms/Controls/DateTimeControl.php', + 'Nette\\Forms\\Controls\\HiddenField' => __DIR__ . '/..' . '/nette/forms/src/Forms/Controls/HiddenField.php', + 'Nette\\Forms\\Controls\\ImageButton' => __DIR__ . '/..' . '/nette/forms/src/Forms/Controls/ImageButton.php', + 'Nette\\Forms\\Controls\\MultiChoiceControl' => __DIR__ . '/..' . '/nette/forms/src/Forms/Controls/MultiChoiceControl.php', + 'Nette\\Forms\\Controls\\MultiSelectBox' => __DIR__ . '/..' . '/nette/forms/src/Forms/Controls/MultiSelectBox.php', + 'Nette\\Forms\\Controls\\RadioList' => __DIR__ . '/..' . '/nette/forms/src/Forms/Controls/RadioList.php', + 'Nette\\Forms\\Controls\\SelectBox' => __DIR__ . '/..' . '/nette/forms/src/Forms/Controls/SelectBox.php', + 'Nette\\Forms\\Controls\\SubmitButton' => __DIR__ . '/..' . '/nette/forms/src/Forms/Controls/SubmitButton.php', + 'Nette\\Forms\\Controls\\TextArea' => __DIR__ . '/..' . '/nette/forms/src/Forms/Controls/TextArea.php', + 'Nette\\Forms\\Controls\\TextBase' => __DIR__ . '/..' . '/nette/forms/src/Forms/Controls/TextBase.php', + 'Nette\\Forms\\Controls\\TextInput' => __DIR__ . '/..' . '/nette/forms/src/Forms/Controls/TextInput.php', + 'Nette\\Forms\\Controls\\UploadControl' => __DIR__ . '/..' . '/nette/forms/src/Forms/Controls/UploadControl.php', + 'Nette\\Forms\\Form' => __DIR__ . '/..' . '/nette/forms/src/Forms/Form.php', + 'Nette\\Forms\\FormRenderer' => __DIR__ . '/..' . '/nette/forms/src/Forms/FormRenderer.php', + 'Nette\\Forms\\Helpers' => __DIR__ . '/..' . '/nette/forms/src/Forms/Helpers.php', + 'Nette\\Forms\\IControl' => __DIR__ . '/..' . '/nette/forms/src/compatibility.php', + 'Nette\\Forms\\IFormRenderer' => __DIR__ . '/..' . '/nette/forms/src/compatibility.php', + 'Nette\\Forms\\ISubmitterControl' => __DIR__ . '/..' . '/nette/forms/src/compatibility.php', + 'Nette\\Forms\\Rendering\\DataClassGenerator' => __DIR__ . '/..' . '/nette/forms/src/Forms/Rendering/DataClassGenerator.php', + 'Nette\\Forms\\Rendering\\DefaultFormRenderer' => __DIR__ . '/..' . '/nette/forms/src/Forms/Rendering/DefaultFormRenderer.php', + 'Nette\\Forms\\Rendering\\LatteRenderer' => __DIR__ . '/..' . '/nette/forms/src/Forms/Rendering/LatteRenderer.php', + 'Nette\\Forms\\Rule' => __DIR__ . '/..' . '/nette/forms/src/Forms/Rule.php', + 'Nette\\Forms\\Rules' => __DIR__ . '/..' . '/nette/forms/src/Forms/Rules.php', + 'Nette\\Forms\\SubmitterControl' => __DIR__ . '/..' . '/nette/forms/src/Forms/SubmitterControl.php', + 'Nette\\Forms\\Validator' => __DIR__ . '/..' . '/nette/forms/src/Forms/Validator.php', + 'Nette\\HtmlStringable' => __DIR__ . '/..' . '/nette/utils/src/HtmlStringable.php', + 'Nette\\Http\\Context' => __DIR__ . '/..' . '/nette/http/src/Http/Context.php', + 'Nette\\Http\\FileUpload' => __DIR__ . '/..' . '/nette/http/src/Http/FileUpload.php', + 'Nette\\Http\\Helpers' => __DIR__ . '/..' . '/nette/http/src/Http/Helpers.php', + 'Nette\\Http\\IRequest' => __DIR__ . '/..' . '/nette/http/src/Http/IRequest.php', + 'Nette\\Http\\IResponse' => __DIR__ . '/..' . '/nette/http/src/Http/IResponse.php', + 'Nette\\Http\\Request' => __DIR__ . '/..' . '/nette/http/src/Http/Request.php', + 'Nette\\Http\\RequestFactory' => __DIR__ . '/..' . '/nette/http/src/Http/RequestFactory.php', + 'Nette\\Http\\Response' => __DIR__ . '/..' . '/nette/http/src/Http/Response.php', + 'Nette\\Http\\Session' => __DIR__ . '/..' . '/nette/http/src/Http/Session.php', + 'Nette\\Http\\SessionSection' => __DIR__ . '/..' . '/nette/http/src/Http/SessionSection.php', + 'Nette\\Http\\Url' => __DIR__ . '/..' . '/nette/http/src/Http/Url.php', + 'Nette\\Http\\UrlImmutable' => __DIR__ . '/..' . '/nette/http/src/Http/UrlImmutable.php', + 'Nette\\Http\\UrlScript' => __DIR__ . '/..' . '/nette/http/src/Http/UrlScript.php', + 'Nette\\Http\\UserStorage' => __DIR__ . '/..' . '/nette/http/src/Http/UserStorage.php', + 'Nette\\IOException' => __DIR__ . '/..' . '/nette/utils/src/exceptions.php', + 'Nette\\InvalidArgumentException' => __DIR__ . '/..' . '/nette/utils/src/exceptions.php', + 'Nette\\InvalidStateException' => __DIR__ . '/..' . '/nette/utils/src/exceptions.php', + 'Nette\\Iterators\\CachingIterator' => __DIR__ . '/..' . '/nette/utils/src/Iterators/CachingIterator.php', + 'Nette\\Iterators\\Mapper' => __DIR__ . '/..' . '/nette/utils/src/Iterators/Mapper.php', + 'Nette\\Loaders\\RobotLoader' => __DIR__ . '/..' . '/nette/robot-loader/src/RobotLoader/RobotLoader.php', + 'Nette\\Localization\\ITranslator' => __DIR__ . '/..' . '/nette/utils/src/compatibility.php', + 'Nette\\Localization\\Translator' => __DIR__ . '/..' . '/nette/utils/src/Translator.php', + 'Nette\\Mail\\DkimSigner' => __DIR__ . '/..' . '/nette/mail/src/Mail/DkimSigner.php', + 'Nette\\Mail\\FallbackMailer' => __DIR__ . '/..' . '/nette/mail/src/Mail/FallbackMailer.php', + 'Nette\\Mail\\FallbackMailerException' => __DIR__ . '/..' . '/nette/mail/src/Mail/exceptions.php', + 'Nette\\Mail\\IMailer' => __DIR__ . '/..' . '/nette/mail/src/Mail/Mailer.php', + 'Nette\\Mail\\Mailer' => __DIR__ . '/..' . '/nette/mail/src/Mail/Mailer.php', + 'Nette\\Mail\\Message' => __DIR__ . '/..' . '/nette/mail/src/Mail/Message.php', + 'Nette\\Mail\\MimePart' => __DIR__ . '/..' . '/nette/mail/src/Mail/MimePart.php', + 'Nette\\Mail\\SendException' => __DIR__ . '/..' . '/nette/mail/src/Mail/exceptions.php', + 'Nette\\Mail\\SendmailMailer' => __DIR__ . '/..' . '/nette/mail/src/Mail/SendmailMailer.php', + 'Nette\\Mail\\SignException' => __DIR__ . '/..' . '/nette/mail/src/Mail/exceptions.php', + 'Nette\\Mail\\Signer' => __DIR__ . '/..' . '/nette/mail/src/Mail/Signer.php', + 'Nette\\Mail\\SmtpException' => __DIR__ . '/..' . '/nette/mail/src/Mail/exceptions.php', + 'Nette\\Mail\\SmtpMailer' => __DIR__ . '/..' . '/nette/mail/src/Mail/SmtpMailer.php', + 'Nette\\MemberAccessException' => __DIR__ . '/..' . '/nette/utils/src/exceptions.php', + 'Nette\\Neon\\Decoder' => __DIR__ . '/..' . '/nette/neon/src/Neon/Decoder.php', + 'Nette\\Neon\\Encoder' => __DIR__ . '/..' . '/nette/neon/src/Neon/Encoder.php', + 'Nette\\Neon\\Entity' => __DIR__ . '/..' . '/nette/neon/src/Neon/Entity.php', + 'Nette\\Neon\\Exception' => __DIR__ . '/..' . '/nette/neon/src/Neon/Exception.php', + 'Nette\\Neon\\Lexer' => __DIR__ . '/..' . '/nette/neon/src/Neon/Lexer.php', + 'Nette\\Neon\\Neon' => __DIR__ . '/..' . '/nette/neon/src/Neon/Neon.php', + 'Nette\\Neon\\Node' => __DIR__ . '/..' . '/nette/neon/src/Neon/Node.php', + 'Nette\\Neon\\Node\\ArrayItemNode' => __DIR__ . '/..' . '/nette/neon/src/Neon/Node/ArrayItemNode.php', + 'Nette\\Neon\\Node\\ArrayNode' => __DIR__ . '/..' . '/nette/neon/src/Neon/Node/ArrayNode.php', + 'Nette\\Neon\\Node\\BlockArrayNode' => __DIR__ . '/..' . '/nette/neon/src/Neon/Node/BlockArrayNode.php', + 'Nette\\Neon\\Node\\EntityChainNode' => __DIR__ . '/..' . '/nette/neon/src/Neon/Node/EntityChainNode.php', + 'Nette\\Neon\\Node\\EntityNode' => __DIR__ . '/..' . '/nette/neon/src/Neon/Node/EntityNode.php', + 'Nette\\Neon\\Node\\InlineArrayNode' => __DIR__ . '/..' . '/nette/neon/src/Neon/Node/InlineArrayNode.php', + 'Nette\\Neon\\Node\\LiteralNode' => __DIR__ . '/..' . '/nette/neon/src/Neon/Node/LiteralNode.php', + 'Nette\\Neon\\Node\\StringNode' => __DIR__ . '/..' . '/nette/neon/src/Neon/Node/StringNode.php', + 'Nette\\Neon\\Parser' => __DIR__ . '/..' . '/nette/neon/src/Neon/Parser.php', + 'Nette\\Neon\\Token' => __DIR__ . '/..' . '/nette/neon/src/Neon/Token.php', + 'Nette\\Neon\\TokenStream' => __DIR__ . '/..' . '/nette/neon/src/Neon/TokenStream.php', + 'Nette\\Neon\\Traverser' => __DIR__ . '/..' . '/nette/neon/src/Neon/Traverser.php', + 'Nette\\NotImplementedException' => __DIR__ . '/..' . '/nette/utils/src/exceptions.php', + 'Nette\\NotSupportedException' => __DIR__ . '/..' . '/nette/utils/src/exceptions.php', + 'Nette\\OutOfRangeException' => __DIR__ . '/..' . '/nette/utils/src/exceptions.php', + 'Nette\\PhpGenerator\\Attribute' => __DIR__ . '/..' . '/nette/php-generator/src/PhpGenerator/Attribute.php', + 'Nette\\PhpGenerator\\ClassLike' => __DIR__ . '/..' . '/nette/php-generator/src/PhpGenerator/ClassLike.php', + 'Nette\\PhpGenerator\\ClassManipulator' => __DIR__ . '/..' . '/nette/php-generator/src/PhpGenerator/ClassManipulator.php', + 'Nette\\PhpGenerator\\ClassType' => __DIR__ . '/..' . '/nette/php-generator/src/PhpGenerator/ClassType.php', + 'Nette\\PhpGenerator\\Closure' => __DIR__ . '/..' . '/nette/php-generator/src/PhpGenerator/Closure.php', + 'Nette\\PhpGenerator\\Constant' => __DIR__ . '/..' . '/nette/php-generator/src/PhpGenerator/Constant.php', + 'Nette\\PhpGenerator\\Dumper' => __DIR__ . '/..' . '/nette/php-generator/src/PhpGenerator/Dumper.php', + 'Nette\\PhpGenerator\\EnumCase' => __DIR__ . '/..' . '/nette/php-generator/src/PhpGenerator/EnumCase.php', + 'Nette\\PhpGenerator\\EnumType' => __DIR__ . '/..' . '/nette/php-generator/src/PhpGenerator/EnumType.php', + 'Nette\\PhpGenerator\\Extractor' => __DIR__ . '/..' . '/nette/php-generator/src/PhpGenerator/Extractor.php', + 'Nette\\PhpGenerator\\Factory' => __DIR__ . '/..' . '/nette/php-generator/src/PhpGenerator/Factory.php', + 'Nette\\PhpGenerator\\GlobalFunction' => __DIR__ . '/..' . '/nette/php-generator/src/PhpGenerator/GlobalFunction.php', + 'Nette\\PhpGenerator\\Helpers' => __DIR__ . '/..' . '/nette/php-generator/src/PhpGenerator/Helpers.php', + 'Nette\\PhpGenerator\\InterfaceType' => __DIR__ . '/..' . '/nette/php-generator/src/PhpGenerator/InterfaceType.php', + 'Nette\\PhpGenerator\\Literal' => __DIR__ . '/..' . '/nette/php-generator/src/PhpGenerator/Literal.php', + 'Nette\\PhpGenerator\\Method' => __DIR__ . '/..' . '/nette/php-generator/src/PhpGenerator/Method.php', + 'Nette\\PhpGenerator\\Parameter' => __DIR__ . '/..' . '/nette/php-generator/src/PhpGenerator/Parameter.php', + 'Nette\\PhpGenerator\\PhpFile' => __DIR__ . '/..' . '/nette/php-generator/src/PhpGenerator/PhpFile.php', + 'Nette\\PhpGenerator\\PhpLiteral' => __DIR__ . '/..' . '/nette/php-generator/src/PhpGenerator/PhpLiteral.php', + 'Nette\\PhpGenerator\\PhpNamespace' => __DIR__ . '/..' . '/nette/php-generator/src/PhpGenerator/PhpNamespace.php', + 'Nette\\PhpGenerator\\Printer' => __DIR__ . '/..' . '/nette/php-generator/src/PhpGenerator/Printer.php', + 'Nette\\PhpGenerator\\PromotedParameter' => __DIR__ . '/..' . '/nette/php-generator/src/PhpGenerator/PromotedParameter.php', + 'Nette\\PhpGenerator\\Property' => __DIR__ . '/..' . '/nette/php-generator/src/PhpGenerator/Property.php', + 'Nette\\PhpGenerator\\PropertyAccessMode' => __DIR__ . '/..' . '/nette/php-generator/src/PhpGenerator/PropertyAccessMode.php', + 'Nette\\PhpGenerator\\PropertyHook' => __DIR__ . '/..' . '/nette/php-generator/src/PhpGenerator/PropertyHook.php', + 'Nette\\PhpGenerator\\PropertyHookType' => __DIR__ . '/..' . '/nette/php-generator/src/PhpGenerator/PropertyHookType.php', + 'Nette\\PhpGenerator\\PsrPrinter' => __DIR__ . '/..' . '/nette/php-generator/src/PhpGenerator/PsrPrinter.php', + 'Nette\\PhpGenerator\\TraitType' => __DIR__ . '/..' . '/nette/php-generator/src/PhpGenerator/TraitType.php', + 'Nette\\PhpGenerator\\TraitUse' => __DIR__ . '/..' . '/nette/php-generator/src/PhpGenerator/TraitUse.php', + 'Nette\\PhpGenerator\\Traits\\AttributeAware' => __DIR__ . '/..' . '/nette/php-generator/src/PhpGenerator/Traits/AttributeAware.php', + 'Nette\\PhpGenerator\\Traits\\CommentAware' => __DIR__ . '/..' . '/nette/php-generator/src/PhpGenerator/Traits/CommentAware.php', + 'Nette\\PhpGenerator\\Traits\\ConstantsAware' => __DIR__ . '/..' . '/nette/php-generator/src/PhpGenerator/Traits/ConstantsAware.php', + 'Nette\\PhpGenerator\\Traits\\FunctionLike' => __DIR__ . '/..' . '/nette/php-generator/src/PhpGenerator/Traits/FunctionLike.php', + 'Nette\\PhpGenerator\\Traits\\MethodsAware' => __DIR__ . '/..' . '/nette/php-generator/src/PhpGenerator/Traits/MethodsAware.php', + 'Nette\\PhpGenerator\\Traits\\NameAware' => __DIR__ . '/..' . '/nette/php-generator/src/PhpGenerator/Traits/NameAware.php', + 'Nette\\PhpGenerator\\Traits\\PropertiesAware' => __DIR__ . '/..' . '/nette/php-generator/src/PhpGenerator/Traits/PropertiesAware.php', + 'Nette\\PhpGenerator\\Traits\\PropertyLike' => __DIR__ . '/..' . '/nette/php-generator/src/PhpGenerator/Traits/PropertyLike.php', + 'Nette\\PhpGenerator\\Traits\\TraitsAware' => __DIR__ . '/..' . '/nette/php-generator/src/PhpGenerator/Traits/TraitsAware.php', + 'Nette\\PhpGenerator\\Traits\\VisibilityAware' => __DIR__ . '/..' . '/nette/php-generator/src/PhpGenerator/Traits/VisibilityAware.php', + 'Nette\\PhpGenerator\\Type' => __DIR__ . '/..' . '/nette/php-generator/src/PhpGenerator/Type.php', + 'Nette\\PhpGenerator\\Visibility' => __DIR__ . '/..' . '/nette/php-generator/src/PhpGenerator/Visibility.php', + 'Nette\\Routing\\Route' => __DIR__ . '/..' . '/nette/routing/src/Routing/Route.php', + 'Nette\\Routing\\RouteList' => __DIR__ . '/..' . '/nette/routing/src/Routing/RouteList.php', + 'Nette\\Routing\\Router' => __DIR__ . '/..' . '/nette/routing/src/Routing/Router.php', + 'Nette\\Routing\\SimpleRouter' => __DIR__ . '/..' . '/nette/routing/src/Routing/SimpleRouter.php', + 'Nette\\Schema\\Context' => __DIR__ . '/..' . '/nette/schema/src/Schema/Context.php', + 'Nette\\Schema\\DynamicParameter' => __DIR__ . '/..' . '/nette/schema/src/Schema/DynamicParameter.php', + 'Nette\\Schema\\Elements\\AnyOf' => __DIR__ . '/..' . '/nette/schema/src/Schema/Elements/AnyOf.php', + 'Nette\\Schema\\Elements\\Base' => __DIR__ . '/..' . '/nette/schema/src/Schema/Elements/Base.php', + 'Nette\\Schema\\Elements\\Structure' => __DIR__ . '/..' . '/nette/schema/src/Schema/Elements/Structure.php', + 'Nette\\Schema\\Elements\\Type' => __DIR__ . '/..' . '/nette/schema/src/Schema/Elements/Type.php', + 'Nette\\Schema\\Expect' => __DIR__ . '/..' . '/nette/schema/src/Schema/Expect.php', + 'Nette\\Schema\\Helpers' => __DIR__ . '/..' . '/nette/schema/src/Schema/Helpers.php', + 'Nette\\Schema\\Message' => __DIR__ . '/..' . '/nette/schema/src/Schema/Message.php', + 'Nette\\Schema\\Processor' => __DIR__ . '/..' . '/nette/schema/src/Schema/Processor.php', + 'Nette\\Schema\\Schema' => __DIR__ . '/..' . '/nette/schema/src/Schema/Schema.php', + 'Nette\\Schema\\ValidationException' => __DIR__ . '/..' . '/nette/schema/src/Schema/ValidationException.php', + 'Nette\\Security\\AuthenticationException' => __DIR__ . '/..' . '/nette/security/src/Security/AuthenticationException.php', + 'Nette\\Security\\Authenticator' => __DIR__ . '/..' . '/nette/security/src/Security/Authenticator.php', + 'Nette\\Security\\Authorizator' => __DIR__ . '/..' . '/nette/security/src/Security/Authorizator.php', + 'Nette\\Security\\IAuthenticator' => __DIR__ . '/..' . '/nette/security/src/Security/IAuthenticator.php', + 'Nette\\Security\\IAuthorizator' => __DIR__ . '/..' . '/nette/security/src/compatibility.php', + 'Nette\\Security\\IIdentity' => __DIR__ . '/..' . '/nette/security/src/Security/IIdentity.php', + 'Nette\\Security\\IResource' => __DIR__ . '/..' . '/nette/security/src/compatibility.php', + 'Nette\\Security\\IRole' => __DIR__ . '/..' . '/nette/security/src/compatibility.php', + 'Nette\\Security\\Identity' => __DIR__ . '/..' . '/nette/security/src/Security/Identity.php', + 'Nette\\Security\\IdentityHandler' => __DIR__ . '/..' . '/nette/security/src/Security/IdentityHandler.php', + 'Nette\\Security\\Passwords' => __DIR__ . '/..' . '/nette/security/src/Security/Passwords.php', + 'Nette\\Security\\Permission' => __DIR__ . '/..' . '/nette/security/src/Security/Permission.php', + 'Nette\\Security\\Resource' => __DIR__ . '/..' . '/nette/security/src/Security/Resource.php', + 'Nette\\Security\\Role' => __DIR__ . '/..' . '/nette/security/src/Security/Role.php', + 'Nette\\Security\\SimpleAuthenticator' => __DIR__ . '/..' . '/nette/security/src/Security/SimpleAuthenticator.php', + 'Nette\\Security\\SimpleIdentity' => __DIR__ . '/..' . '/nette/security/src/Security/SimpleIdentity.php', + 'Nette\\Security\\User' => __DIR__ . '/..' . '/nette/security/src/Security/User.php', + 'Nette\\Security\\UserStorage' => __DIR__ . '/..' . '/nette/security/src/Security/UserStorage.php', + 'Nette\\ShouldNotHappenException' => __DIR__ . '/..' . '/nette/utils/src/exceptions.php', + 'Nette\\SmartObject' => __DIR__ . '/..' . '/nette/utils/src/SmartObject.php', + 'Nette\\StaticClass' => __DIR__ . '/..' . '/nette/utils/src/StaticClass.php', + 'Nette\\UnexpectedValueException' => __DIR__ . '/..' . '/nette/utils/src/exceptions.php', + 'Nette\\Utils\\ArrayHash' => __DIR__ . '/..' . '/nette/utils/src/Utils/ArrayHash.php', + 'Nette\\Utils\\ArrayList' => __DIR__ . '/..' . '/nette/utils/src/Utils/ArrayList.php', + 'Nette\\Utils\\Arrays' => __DIR__ . '/..' . '/nette/utils/src/Utils/Arrays.php', + 'Nette\\Utils\\AssertionException' => __DIR__ . '/..' . '/nette/utils/src/Utils/exceptions.php', + 'Nette\\Utils\\Callback' => __DIR__ . '/..' . '/nette/utils/src/Utils/Callback.php', + 'Nette\\Utils\\DateTime' => __DIR__ . '/..' . '/nette/utils/src/Utils/DateTime.php', + 'Nette\\Utils\\FileInfo' => __DIR__ . '/..' . '/nette/utils/src/Utils/FileInfo.php', + 'Nette\\Utils\\FileSystem' => __DIR__ . '/..' . '/nette/utils/src/Utils/FileSystem.php', + 'Nette\\Utils\\Finder' => __DIR__ . '/..' . '/nette/utils/src/Utils/Finder.php', + 'Nette\\Utils\\Floats' => __DIR__ . '/..' . '/nette/utils/src/Utils/Floats.php', + 'Nette\\Utils\\Helpers' => __DIR__ . '/..' . '/nette/utils/src/Utils/Helpers.php', + 'Nette\\Utils\\Html' => __DIR__ . '/..' . '/nette/utils/src/Utils/Html.php', + 'Nette\\Utils\\IHtmlString' => __DIR__ . '/..' . '/nette/utils/src/compatibility.php', + 'Nette\\Utils\\Image' => __DIR__ . '/..' . '/nette/utils/src/Utils/Image.php', + 'Nette\\Utils\\ImageColor' => __DIR__ . '/..' . '/nette/utils/src/Utils/ImageColor.php', + 'Nette\\Utils\\ImageException' => __DIR__ . '/..' . '/nette/utils/src/Utils/exceptions.php', + 'Nette\\Utils\\ImageType' => __DIR__ . '/..' . '/nette/utils/src/Utils/ImageType.php', + 'Nette\\Utils\\Iterables' => __DIR__ . '/..' . '/nette/utils/src/Utils/Iterables.php', + 'Nette\\Utils\\Json' => __DIR__ . '/..' . '/nette/utils/src/Utils/Json.php', + 'Nette\\Utils\\JsonException' => __DIR__ . '/..' . '/nette/utils/src/Utils/exceptions.php', + 'Nette\\Utils\\ObjectHelpers' => __DIR__ . '/..' . '/nette/utils/src/Utils/ObjectHelpers.php', + 'Nette\\Utils\\Paginator' => __DIR__ . '/..' . '/nette/utils/src/Utils/Paginator.php', + 'Nette\\Utils\\Random' => __DIR__ . '/..' . '/nette/utils/src/Utils/Random.php', + 'Nette\\Utils\\Reflection' => __DIR__ . '/..' . '/nette/utils/src/Utils/Reflection.php', + 'Nette\\Utils\\ReflectionMethod' => __DIR__ . '/..' . '/nette/utils/src/Utils/ReflectionMethod.php', + 'Nette\\Utils\\RegexpException' => __DIR__ . '/..' . '/nette/utils/src/Utils/exceptions.php', + 'Nette\\Utils\\Strings' => __DIR__ . '/..' . '/nette/utils/src/Utils/Strings.php', + 'Nette\\Utils\\Type' => __DIR__ . '/..' . '/nette/utils/src/Utils/Type.php', + 'Nette\\Utils\\UnknownImageFileException' => __DIR__ . '/..' . '/nette/utils/src/Utils/exceptions.php', + 'Nette\\Utils\\Validators' => __DIR__ . '/..' . '/nette/utils/src/Utils/Validators.php', + 'Tester\\Assert' => __DIR__ . '/..' . '/nette/tester/src/Framework/Assert.php', + 'Tester\\AssertException' => __DIR__ . '/..' . '/nette/tester/src/Framework/AssertException.php', + 'Tester\\CodeCoverage\\Collector' => __DIR__ . '/..' . '/nette/tester/src/CodeCoverage/Collector.php', + 'Tester\\CodeCoverage\\Generators\\AbstractGenerator' => __DIR__ . '/..' . '/nette/tester/src/CodeCoverage/Generators/AbstractGenerator.php', + 'Tester\\CodeCoverage\\Generators\\CloverXMLGenerator' => __DIR__ . '/..' . '/nette/tester/src/CodeCoverage/Generators/CloverXMLGenerator.php', + 'Tester\\CodeCoverage\\Generators\\HtmlGenerator' => __DIR__ . '/..' . '/nette/tester/src/CodeCoverage/Generators/HtmlGenerator.php', + 'Tester\\CodeCoverage\\PhpParser' => __DIR__ . '/..' . '/nette/tester/src/CodeCoverage/PhpParser.php', + 'Tester\\DataProvider' => __DIR__ . '/..' . '/nette/tester/src/Framework/DataProvider.php', + 'Tester\\DomQuery' => __DIR__ . '/..' . '/nette/tester/src/Framework/DomQuery.php', + 'Tester\\Dumper' => __DIR__ . '/..' . '/nette/tester/src/Framework/Dumper.php', + 'Tester\\Environment' => __DIR__ . '/..' . '/nette/tester/src/Framework/Environment.php', + 'Tester\\Expect' => __DIR__ . '/..' . '/nette/tester/src/Framework/Expect.php', + 'Tester\\FileMock' => __DIR__ . '/..' . '/nette/tester/src/Framework/FileMock.php', + 'Tester\\FileMutator' => __DIR__ . '/..' . '/nette/tester/src/Framework/FileMutator.php', + 'Tester\\Helpers' => __DIR__ . '/..' . '/nette/tester/src/Framework/Helpers.php', + 'Tester\\HttpAssert' => __DIR__ . '/..' . '/nette/tester/src/Framework/HttpAssert.php', + 'Tester\\Runner\\CliTester' => __DIR__ . '/..' . '/nette/tester/src/Runner/CliTester.php', + 'Tester\\Runner\\CommandLine' => __DIR__ . '/..' . '/nette/tester/src/Runner/CommandLine.php', + 'Tester\\Runner\\InterruptException' => __DIR__ . '/..' . '/nette/tester/src/Runner/exceptions.php', + 'Tester\\Runner\\Job' => __DIR__ . '/..' . '/nette/tester/src/Runner/Job.php', + 'Tester\\Runner\\OutputHandler' => __DIR__ . '/..' . '/nette/tester/src/Runner/OutputHandler.php', + 'Tester\\Runner\\Output\\ConsolePrinter' => __DIR__ . '/..' . '/nette/tester/src/Runner/Output/ConsolePrinter.php', + 'Tester\\Runner\\Output\\JUnitPrinter' => __DIR__ . '/..' . '/nette/tester/src/Runner/Output/JUnitPrinter.php', + 'Tester\\Runner\\Output\\Logger' => __DIR__ . '/..' . '/nette/tester/src/Runner/Output/Logger.php', + 'Tester\\Runner\\Output\\TapPrinter' => __DIR__ . '/..' . '/nette/tester/src/Runner/Output/TapPrinter.php', + 'Tester\\Runner\\PhpInterpreter' => __DIR__ . '/..' . '/nette/tester/src/Runner/PhpInterpreter.php', + 'Tester\\Runner\\Runner' => __DIR__ . '/..' . '/nette/tester/src/Runner/Runner.php', + 'Tester\\Runner\\Test' => __DIR__ . '/..' . '/nette/tester/src/Runner/Test.php', + 'Tester\\Runner\\TestHandler' => __DIR__ . '/..' . '/nette/tester/src/Runner/TestHandler.php', + 'Tester\\TestCase' => __DIR__ . '/..' . '/nette/tester/src/Framework/TestCase.php', + 'Tester\\TestCaseException' => __DIR__ . '/..' . '/nette/tester/src/Framework/TestCase.php', + 'Tester\\TestCaseSkippedException' => __DIR__ . '/..' . '/nette/tester/src/Framework/TestCase.php', + 'Tracy\\Bar' => __DIR__ . '/..' . '/tracy/tracy/src/Tracy/Bar/Bar.php', + 'Tracy\\BlueScreen' => __DIR__ . '/..' . '/tracy/tracy/src/Tracy/BlueScreen/BlueScreen.php', + 'Tracy\\Bridges\\Nette\\Bridge' => __DIR__ . '/..' . '/tracy/tracy/src/Bridges/Nette/Bridge.php', + 'Tracy\\Bridges\\Nette\\MailSender' => __DIR__ . '/..' . '/tracy/tracy/src/Bridges/Nette/MailSender.php', + 'Tracy\\Bridges\\Nette\\TracyExtension' => __DIR__ . '/..' . '/tracy/tracy/src/Bridges/Nette/TracyExtension.php', + 'Tracy\\Bridges\\Psr\\PsrToTracyLoggerAdapter' => __DIR__ . '/..' . '/tracy/tracy/src/Bridges/Psr/PsrToTracyLoggerAdapter.php', + 'Tracy\\Bridges\\Psr\\TracyToPsrLoggerAdapter' => __DIR__ . '/..' . '/tracy/tracy/src/Bridges/Psr/TracyToPsrLoggerAdapter.php', + 'Tracy\\CodeHighlighter' => __DIR__ . '/..' . '/tracy/tracy/src/Tracy/BlueScreen/CodeHighlighter.php', + 'Tracy\\Debugger' => __DIR__ . '/..' . '/tracy/tracy/src/Tracy/Debugger/Debugger.php', + 'Tracy\\DefaultBarPanel' => __DIR__ . '/..' . '/tracy/tracy/src/Tracy/Bar/DefaultBarPanel.php', + 'Tracy\\DeferredContent' => __DIR__ . '/..' . '/tracy/tracy/src/Tracy/Debugger/DeferredContent.php', + 'Tracy\\DevelopmentStrategy' => __DIR__ . '/..' . '/tracy/tracy/src/Tracy/Debugger/DevelopmentStrategy.php', + 'Tracy\\Dumper' => __DIR__ . '/..' . '/tracy/tracy/src/Tracy/Dumper/Dumper.php', + 'Tracy\\Dumper\\Describer' => __DIR__ . '/..' . '/tracy/tracy/src/Tracy/Dumper/Describer.php', + 'Tracy\\Dumper\\Exposer' => __DIR__ . '/..' . '/tracy/tracy/src/Tracy/Dumper/Exposer.php', + 'Tracy\\Dumper\\Renderer' => __DIR__ . '/..' . '/tracy/tracy/src/Tracy/Dumper/Renderer.php', + 'Tracy\\Dumper\\Value' => __DIR__ . '/..' . '/tracy/tracy/src/Tracy/Dumper/Value.php', + 'Tracy\\FileSession' => __DIR__ . '/..' . '/tracy/tracy/src/Tracy/Session/FileSession.php', + 'Tracy\\Helpers' => __DIR__ . '/..' . '/tracy/tracy/src/Tracy/Helpers.php', + 'Tracy\\IBarPanel' => __DIR__ . '/..' . '/tracy/tracy/src/Tracy/Bar/IBarPanel.php', + 'Tracy\\ILogger' => __DIR__ . '/..' . '/tracy/tracy/src/Tracy/Logger/ILogger.php', + 'Tracy\\Logger' => __DIR__ . '/..' . '/tracy/tracy/src/Tracy/Logger/Logger.php', + 'Tracy\\NativeSession' => __DIR__ . '/..' . '/tracy/tracy/src/Tracy/Session/NativeSession.php', + 'Tracy\\OutputDebugger' => __DIR__ . '/..' . '/tracy/tracy/src/Tracy/OutputDebugger/OutputDebugger.php', + 'Tracy\\ProductionStrategy' => __DIR__ . '/..' . '/tracy/tracy/src/Tracy/Debugger/ProductionStrategy.php', + 'Tracy\\SessionStorage' => __DIR__ . '/..' . '/tracy/tracy/src/Tracy/Session/SessionStorage.php', + ); + + public static function getInitializer(ClassLoader $loader) + { + return \Closure::bind(function () use ($loader) { + $loader->prefixLengthsPsr4 = ComposerStaticInita1ed42372489c27598cfbf4d5ef3ac47::$prefixLengthsPsr4; + $loader->prefixDirsPsr4 = ComposerStaticInita1ed42372489c27598cfbf4d5ef3ac47::$prefixDirsPsr4; + $loader->classMap = ComposerStaticInita1ed42372489c27598cfbf4d5ef3ac47::$classMap; + + }, null, ClassLoader::class); + } +} diff --git a/vendor/composer/installed.json b/vendor/composer/installed.json new file mode 100644 index 0000000..f39811c --- /dev/null +++ b/vendor/composer/installed.json @@ -0,0 +1,2251 @@ +{ + "packages": [ + { + "name": "bacon/bacon-qr-code", + "version": "v3.0.3", + "version_normalized": "3.0.3.0", + "source": { + "type": "git", + "url": "https://github.com/Bacon/BaconQrCode.git", + "reference": "36a1cb2b81493fa5b82e50bf8068bf84d1542563" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Bacon/BaconQrCode/zipball/36a1cb2b81493fa5b82e50bf8068bf84d1542563", + "reference": "36a1cb2b81493fa5b82e50bf8068bf84d1542563", + "shasum": "" + }, + "require": { + "dasprid/enum": "^1.0.3", + "ext-iconv": "*", + "php": "^8.1" + }, + "require-dev": { + "phly/keep-a-changelog": "^2.12", + "phpunit/phpunit": "^10.5.11 || ^11.0.4", + "spatie/phpunit-snapshot-assertions": "^5.1.5", + "spatie/pixelmatch-php": "^1.2.0", + "squizlabs/php_codesniffer": "^3.9" + }, + "suggest": { + "ext-imagick": "to generate QR code images" + }, + "time": "2025-11-19T17:15:36+00:00", + "type": "library", + "installation-source": "dist", + "autoload": { + "psr-4": { + "BaconQrCode\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-2-Clause" + ], + "authors": [ + { + "name": "Ben Scholzen 'DASPRiD'", + "email": "mail@dasprids.de", + "homepage": "https://dasprids.de/", + "role": "Developer" + } + ], + "description": "BaconQrCode is a QR code generator for PHP.", + "homepage": "https://github.com/Bacon/BaconQrCode", + "support": { + "issues": "https://github.com/Bacon/BaconQrCode/issues", + "source": "https://github.com/Bacon/BaconQrCode/tree/v3.0.3" + }, + "install-path": "../bacon/bacon-qr-code" + }, + { + "name": "dasprid/enum", + "version": "1.0.7", + "version_normalized": "1.0.7.0", + "source": { + "type": "git", + "url": "https://github.com/DASPRiD/Enum.git", + "reference": "b5874fa9ed0043116c72162ec7f4fb50e02e7cce" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/DASPRiD/Enum/zipball/b5874fa9ed0043116c72162ec7f4fb50e02e7cce", + "reference": "b5874fa9ed0043116c72162ec7f4fb50e02e7cce", + "shasum": "" + }, + "require": { + "php": ">=7.1 <9.0" + }, + "require-dev": { + "phpunit/phpunit": "^7 || ^8 || ^9 || ^10 || ^11", + "squizlabs/php_codesniffer": "*" + }, + "time": "2025-09-16T12:23:56+00:00", + "type": "library", + "installation-source": "dist", + "autoload": { + "psr-4": { + "DASPRiD\\Enum\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-2-Clause" + ], + "authors": [ + { + "name": "Ben Scholzen 'DASPRiD'", + "email": "mail@dasprids.de", + "homepage": "https://dasprids.de/", + "role": "Developer" + } + ], + "description": "PHP 7.1 enum implementation", + "keywords": [ + "enum", + "map" + ], + "support": { + "issues": "https://github.com/DASPRiD/Enum/issues", + "source": "https://github.com/DASPRiD/Enum/tree/1.0.7" + }, + "install-path": "../dasprid/enum" + }, + { + "name": "endroid/qr-code", + "version": "6.0.9", + "version_normalized": "6.0.9.0", + "source": { + "type": "git", + "url": "https://github.com/endroid/qr-code.git", + "reference": "21e888e8597440b2205e2e5c484b6c8e556bcd1a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/endroid/qr-code/zipball/21e888e8597440b2205e2e5c484b6c8e556bcd1a", + "reference": "21e888e8597440b2205e2e5c484b6c8e556bcd1a", + "shasum": "" + }, + "require": { + "bacon/bacon-qr-code": "^3.0", + "php": "^8.2" + }, + "require-dev": { + "endroid/quality": "dev-main", + "ext-gd": "*", + "khanamiryan/qrcode-detector-decoder": "^2.0.2", + "setasign/fpdf": "^1.8.2" + }, + "suggest": { + "ext-gd": "Enables you to write PNG images", + "khanamiryan/qrcode-detector-decoder": "Enables you to use the image validator", + "roave/security-advisories": "Makes sure package versions with known security issues are not installed", + "setasign/fpdf": "Enables you to use the PDF writer" + }, + "time": "2025-07-13T19:59:45+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "6.x-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Endroid\\QrCode\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jeroen van den Enden", + "email": "info@endroid.nl" + } + ], + "description": "Endroid QR Code", + "homepage": "https://github.com/endroid/qr-code", + "keywords": [ + "code", + "endroid", + "php", + "qr", + "qrcode" + ], + "support": { + "issues": "https://github.com/endroid/qr-code/issues", + "source": "https://github.com/endroid/qr-code/tree/6.0.9" + }, + "funding": [ + { + "url": "https://github.com/endroid", + "type": "github" + } + ], + "install-path": "../endroid/qr-code" + }, + { + "name": "latte/latte", + "version": "v3.1.1", + "version_normalized": "3.1.1.0", + "source": { + "type": "git", + "url": "https://github.com/nette/latte.git", + "reference": "cb98e705eeb0fd18f1f1c5cfe1a5f6217f9fa8b3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nette/latte/zipball/cb98e705eeb0fd18f1f1c5cfe1a5f6217f9fa8b3", + "reference": "cb98e705eeb0fd18f1f1c5cfe1a5f6217f9fa8b3", + "shasum": "" + }, + "require": { + "ext-json": "*", + "ext-tokenizer": "*", + "php": "8.2 - 8.5" + }, + "conflict": { + "nette/application": "<3.1.7", + "nette/caching": "<3.1.4" + }, + "require-dev": { + "nette/php-generator": "^4.0", + "nette/tester": "^2.5", + "nette/utils": "^4.0", + "phpstan/phpstan-nette": "^2.0@stable", + "tracy/tracy": "^2.10" + }, + "suggest": { + "ext-fileinfo": "to use filter |datastream", + "ext-iconv": "to use filters |reverse, |substring", + "ext-intl": "to use Latte\\Engine::setLocale()", + "ext-mbstring": "to use filters like lower, upper, capitalize, ...", + "nette/php-generator": "to use tag {templatePrint}", + "nette/utils": "to use filter |webalize" + }, + "time": "2025-12-18T22:30:40+00:00", + "bin": [ + "bin/latte-lint" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.1-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Latte\\": "src/Latte" + }, + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause", + "GPL-2.0-only", + "GPL-3.0-only" + ], + "authors": [ + { + "name": "David Grudl", + "homepage": "https://davidgrudl.com" + }, + { + "name": "Nette Community", + "homepage": "https://nette.org/contributors" + } + ], + "description": "☕ Latte: the intuitive and fast template engine for those who want the most secure PHP sites. Introduces context-sensitive escaping.", + "homepage": "https://latte.nette.org", + "keywords": [ + "context-sensitive", + "engine", + "escaping", + "html", + "nette", + "security", + "template", + "twig" + ], + "support": { + "issues": "https://github.com/nette/latte/issues", + "source": "https://github.com/nette/latte/tree/v3.1.1" + }, + "install-path": "../latte/latte" + }, + { + "name": "nette/application", + "version": "v3.2.9", + "version_normalized": "3.2.9.0", + "source": { + "type": "git", + "url": "https://github.com/nette/application.git", + "reference": "11d9d6fc53d579a3516c1574c707a5de281bc0a0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nette/application/zipball/11d9d6fc53d579a3516c1574c707a5de281bc0a0", + "reference": "11d9d6fc53d579a3516c1574c707a5de281bc0a0", + "shasum": "" + }, + "require": { + "nette/component-model": "^3.1", + "nette/http": "^3.3.2", + "nette/routing": "^3.1.1", + "nette/utils": "^4.0", + "php": "8.1 - 8.5" + }, + "conflict": { + "latte/latte": "<2.7.1 || >=3.0.0 <3.0.18 || >=3.2", + "nette/caching": "<3.2", + "nette/di": "<3.2", + "nette/forms": "<3.2", + "nette/schema": "<1.3", + "tracy/tracy": "<2.9" + }, + "require-dev": { + "jetbrains/phpstorm-attributes": "^1.2", + "latte/latte": "^2.10.2 || ^3.0.18", + "mockery/mockery": "^1.6@stable", + "nette/di": "^3.2", + "nette/forms": "^3.2", + "nette/robot-loader": "^4.0", + "nette/security": "^3.2", + "nette/tester": "^2.5.2", + "phpstan/phpstan-nette": "^2.0@stable", + "tracy/tracy": "^2.9" + }, + "suggest": { + "latte/latte": "Allows using Latte in templates", + "nette/forms": "Allows to use Nette\\Application\\UI\\Form" + }, + "time": "2025-12-19T11:39:00+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.2-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Nette\\": "src" + }, + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause", + "GPL-2.0-only", + "GPL-3.0-only" + ], + "authors": [ + { + "name": "David Grudl", + "homepage": "https://davidgrudl.com" + }, + { + "name": "Nette Community", + "homepage": "https://nette.org/contributors" + } + ], + "description": "🏆 Nette Application: a full-stack component-based MVC kernel for PHP that helps you write powerful and modern web applications. Write less, have cleaner code and your work will bring you joy.", + "homepage": "https://nette.org", + "keywords": [ + "Forms", + "component-based", + "control", + "framework", + "mvc", + "mvp", + "nette", + "presenter", + "routing", + "seo" + ], + "support": { + "issues": "https://github.com/nette/application/issues", + "source": "https://github.com/nette/application/tree/v3.2.9" + }, + "install-path": "../nette/application" + }, + { + "name": "nette/assets", + "version": "v1.0.5", + "version_normalized": "1.0.5.0", + "source": { + "type": "git", + "url": "https://github.com/nette/assets.git", + "reference": "d747983c8a8ee5e8508ab9b45282c869e6b1f623" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nette/assets/zipball/d747983c8a8ee5e8508ab9b45282c869e6b1f623", + "reference": "d747983c8a8ee5e8508ab9b45282c869e6b1f623", + "shasum": "" + }, + "require": { + "nette/utils": "^4.0.6", + "php": "8.1 - 8.5" + }, + "conflict": { + "nette/bootstrap": "<3.2.5", + "nette/http": "<3.3.2" + }, + "require-dev": { + "latte/latte": "^3.0.22", + "mockery/mockery": "^1.6@stable", + "nette/application": "^3.2", + "nette/di": "^3.2", + "nette/http": "^3.3.2", + "nette/tester": "^2.5", + "phpstan/phpstan-nette": "^2.0@stable", + "tracy/tracy": "^2.9" + }, + "suggest": { + "latte/latte": "Allows using Assets in templates" + }, + "time": "2025-11-24T02:49:53+00:00", + "type": "library", + "installation-source": "dist", + "autoload": { + "psr-4": { + "Nette\\": "src" + }, + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause", + "GPL-2.0-only", + "GPL-3.0-only" + ], + "authors": [ + { + "name": "David Grudl", + "homepage": "https://davidgrudl.com" + }, + { + "name": "Nette Community", + "homepage": "https://nette.org/contributors" + } + ], + "description": "🎨 Nette Assets: elegant asset management for PHP with versioning, caching and mappers for various storage backends.", + "homepage": "https://nette.org", + "keywords": [ + "asset management", + "assets", + "nette", + "resources", + "static files", + "versioning" + ], + "support": { + "issues": "https://github.com/nette/assets/issues", + "source": "https://github.com/nette/assets/tree/v1.0.5" + }, + "install-path": "../nette/assets" + }, + { + "name": "nette/bootstrap", + "version": "v3.2.7", + "version_normalized": "3.2.7.0", + "source": { + "type": "git", + "url": "https://github.com/nette/bootstrap.git", + "reference": "10fdb1cb05497da39396f2ce1785cea67c8aa439" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nette/bootstrap/zipball/10fdb1cb05497da39396f2ce1785cea67c8aa439", + "reference": "10fdb1cb05497da39396f2ce1785cea67c8aa439", + "shasum": "" + }, + "require": { + "nette/di": "^3.1", + "nette/utils": "^3.2.1 || ^4.0", + "php": "8.0 - 8.5" + }, + "conflict": { + "tracy/tracy": "<2.6" + }, + "require-dev": { + "latte/latte": "^2.8 || ^3.0", + "nette/application": "^3.1", + "nette/caching": "^3.0", + "nette/database": "^3.0", + "nette/forms": "^3.0", + "nette/http": "^3.0", + "nette/mail": "^3.0 || ^4.0", + "nette/robot-loader": "^3.0 || ^4.0", + "nette/safe-stream": "^2.2", + "nette/security": "^3.0", + "nette/tester": "^2.4", + "phpstan/phpstan-nette": "^2.0@stable", + "tracy/tracy": "^2.9" + }, + "suggest": { + "nette/robot-loader": "to use Configurator::createRobotLoader()", + "tracy/tracy": "to use Configurator::enableTracy()" + }, + "time": "2025-08-01T02:02:03+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.2-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Nette\\": "src" + }, + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause", + "GPL-2.0-only", + "GPL-3.0-only" + ], + "authors": [ + { + "name": "David Grudl", + "homepage": "https://davidgrudl.com" + }, + { + "name": "Nette Community", + "homepage": "https://nette.org/contributors" + } + ], + "description": "🅱 Nette Bootstrap: the simple way to configure and bootstrap your Nette application.", + "homepage": "https://nette.org", + "keywords": [ + "bootstrapping", + "configurator", + "nette" + ], + "support": { + "issues": "https://github.com/nette/bootstrap/issues", + "source": "https://github.com/nette/bootstrap/tree/v3.2.7" + }, + "install-path": "../nette/bootstrap" + }, + { + "name": "nette/caching", + "version": "v3.4.0", + "version_normalized": "3.4.0.0", + "source": { + "type": "git", + "url": "https://github.com/nette/caching.git", + "reference": "a1c13221b350d0db0a2bd4a77c1e7b65e0aa065d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nette/caching/zipball/a1c13221b350d0db0a2bd4a77c1e7b65e0aa065d", + "reference": "a1c13221b350d0db0a2bd4a77c1e7b65e0aa065d", + "shasum": "" + }, + "require": { + "nette/utils": "^4.0", + "php": "8.1 - 8.5" + }, + "conflict": { + "latte/latte": "<3.0.12" + }, + "require-dev": { + "latte/latte": "^3.0.12", + "nette/di": "^3.1 || ^4.0", + "nette/tester": "^2.4", + "phpstan/phpstan-nette": "^2.0@stable", + "psr/simple-cache": "^2.0 || ^3.0", + "tracy/tracy": "^2.9" + }, + "suggest": { + "ext-pdo_sqlite": "to use SQLiteStorage or SQLiteJournal" + }, + "time": "2025-08-06T23:05:08+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.4-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Nette\\": "src" + }, + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause", + "GPL-2.0-only", + "GPL-3.0-only" + ], + "authors": [ + { + "name": "David Grudl", + "homepage": "https://davidgrudl.com" + }, + { + "name": "Nette Community", + "homepage": "https://nette.org/contributors" + } + ], + "description": "⏱ Nette Caching: library with easy-to-use API and many cache backends.", + "homepage": "https://nette.org", + "keywords": [ + "cache", + "journal", + "memcached", + "nette", + "sqlite" + ], + "support": { + "issues": "https://github.com/nette/caching/issues", + "source": "https://github.com/nette/caching/tree/v3.4.0" + }, + "install-path": "../nette/caching" + }, + { + "name": "nette/component-model", + "version": "v3.1.3", + "version_normalized": "3.1.3.0", + "source": { + "type": "git", + "url": "https://github.com/nette/component-model.git", + "reference": "0d100ba05279a1f4b20acecaa617027fbda8ecb2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nette/component-model/zipball/0d100ba05279a1f4b20acecaa617027fbda8ecb2", + "reference": "0d100ba05279a1f4b20acecaa617027fbda8ecb2", + "shasum": "" + }, + "require": { + "nette/utils": "^4.0", + "php": "8.1 - 8.5" + }, + "require-dev": { + "nette/tester": "^2.5", + "phpstan/phpstan-nette": "^2.0@stable", + "tracy/tracy": "^2.9" + }, + "time": "2025-11-22T18:56:33+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.1-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Nette\\": "src" + }, + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause", + "GPL-2.0-only", + "GPL-3.0-only" + ], + "authors": [ + { + "name": "David Grudl", + "homepage": "https://davidgrudl.com" + }, + { + "name": "Nette Community", + "homepage": "https://nette.org/contributors" + } + ], + "description": "⚛ Nette Component Model", + "homepage": "https://nette.org", + "keywords": [ + "components", + "nette" + ], + "support": { + "issues": "https://github.com/nette/component-model/issues", + "source": "https://github.com/nette/component-model/tree/v3.1.3" + }, + "install-path": "../nette/component-model" + }, + { + "name": "nette/database", + "version": "v3.2.8", + "version_normalized": "3.2.8.0", + "source": { + "type": "git", + "url": "https://github.com/nette/database.git", + "reference": "1a84d3e61aa33461a3d6415235b25a7cd8b3f442" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nette/database/zipball/1a84d3e61aa33461a3d6415235b25a7cd8b3f442", + "reference": "1a84d3e61aa33461a3d6415235b25a7cd8b3f442", + "shasum": "" + }, + "require": { + "ext-pdo": "*", + "nette/caching": "^3.2", + "nette/utils": "^4.0", + "php": "8.1 - 8.5" + }, + "require-dev": { + "jetbrains/phpstorm-attributes": "^1.2", + "mockery/mockery": "^1.6@stable", + "nette/di": "^3.1", + "nette/tester": "^2.5", + "phpstan/phpstan-nette": "^2.0@stable", + "tracy/tracy": "^2.9" + }, + "time": "2025-10-30T22:06:23+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.2-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Nette\\": "src" + }, + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause", + "GPL-2.0-only", + "GPL-3.0-only" + ], + "authors": [ + { + "name": "David Grudl", + "homepage": "https://davidgrudl.com" + }, + { + "name": "Nette Community", + "homepage": "https://nette.org/contributors" + } + ], + "description": "💾 Nette Database: layer with a familiar PDO-like API but much more powerful. Building queries, advanced joins, drivers for MySQL, PostgreSQL, SQLite, MS SQL Server and Oracle.", + "homepage": "https://nette.org", + "keywords": [ + "database", + "mssql", + "mysql", + "nette", + "notorm", + "oracle", + "pdo", + "postgresql", + "queries", + "sqlite" + ], + "support": { + "issues": "https://github.com/nette/database/issues", + "source": "https://github.com/nette/database/tree/v3.2.8" + }, + "install-path": "../nette/database" + }, + { + "name": "nette/di", + "version": "v3.2.5", + "version_normalized": "3.2.5.0", + "source": { + "type": "git", + "url": "https://github.com/nette/di.git", + "reference": "5708c328ce7658a73c96b14dd6da7b8b27bf220f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nette/di/zipball/5708c328ce7658a73c96b14dd6da7b8b27bf220f", + "reference": "5708c328ce7658a73c96b14dd6da7b8b27bf220f", + "shasum": "" + }, + "require": { + "ext-ctype": "*", + "ext-tokenizer": "*", + "nette/neon": "^3.3", + "nette/php-generator": "^4.1.6", + "nette/robot-loader": "^4.0", + "nette/schema": "^1.2.5", + "nette/utils": "^4.0", + "php": "8.1 - 8.5" + }, + "require-dev": { + "nette/tester": "^2.5.2", + "phpstan/phpstan-nette": "^2.0@stable", + "tracy/tracy": "^2.9" + }, + "time": "2025-08-14T22:59:46+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.2-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Nette\\": "src" + }, + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause", + "GPL-2.0-only", + "GPL-3.0-only" + ], + "authors": [ + { + "name": "David Grudl", + "homepage": "https://davidgrudl.com" + }, + { + "name": "Nette Community", + "homepage": "https://nette.org/contributors" + } + ], + "description": "💎 Nette Dependency Injection Container: Flexible, compiled and full-featured DIC with perfectly usable autowiring and support for all new PHP features.", + "homepage": "https://nette.org", + "keywords": [ + "compiled", + "di", + "dic", + "factory", + "ioc", + "nette", + "static" + ], + "support": { + "issues": "https://github.com/nette/di/issues", + "source": "https://github.com/nette/di/tree/v3.2.5" + }, + "install-path": "../nette/di" + }, + { + "name": "nette/forms", + "version": "v3.2.8", + "version_normalized": "3.2.8.0", + "source": { + "type": "git", + "url": "https://github.com/nette/forms.git", + "reference": "3bbf691ea0eb50d9594c2109d9252f267092b91f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nette/forms/zipball/3bbf691ea0eb50d9594c2109d9252f267092b91f", + "reference": "3bbf691ea0eb50d9594c2109d9252f267092b91f", + "shasum": "" + }, + "require": { + "nette/component-model": "^3.1", + "nette/http": "^3.3", + "nette/utils": "^4.0.4", + "php": "8.1 - 8.5" + }, + "conflict": { + "latte/latte": ">=3.0.0 <3.0.12 || >=3.2" + }, + "require-dev": { + "latte/latte": "^2.10.2 || ^3.0.12", + "nette/application": "^3.0", + "nette/di": "^3.0", + "nette/tester": "^2.5.2", + "phpstan/phpstan-nette": "^2.0@stable", + "tracy/tracy": "^2.9" + }, + "suggest": { + "ext-intl": "to use date/time controls" + }, + "time": "2025-11-22T19:36:34+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.2-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Nette\\": "src" + }, + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause", + "GPL-2.0-only", + "GPL-3.0-only" + ], + "authors": [ + { + "name": "David Grudl", + "homepage": "https://davidgrudl.com" + }, + { + "name": "Nette Community", + "homepage": "https://nette.org/contributors" + } + ], + "description": "📝 Nette Forms: generating, validating and processing secure forms in PHP. Handy API, fully customizable, server & client side validation and mature design.", + "homepage": "https://nette.org", + "keywords": [ + "Forms", + "bootstrap", + "csrf", + "javascript", + "nette", + "validation" + ], + "support": { + "issues": "https://github.com/nette/forms/issues", + "source": "https://github.com/nette/forms/tree/v3.2.8" + }, + "install-path": "../nette/forms" + }, + { + "name": "nette/http", + "version": "v3.3.3", + "version_normalized": "3.3.3.0", + "source": { + "type": "git", + "url": "https://github.com/nette/http.git", + "reference": "c557f21c8cedd621dbfd7990752b1d55ef353f1d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nette/http/zipball/c557f21c8cedd621dbfd7990752b1d55ef353f1d", + "reference": "c557f21c8cedd621dbfd7990752b1d55ef353f1d", + "shasum": "" + }, + "require": { + "nette/utils": "^4.0.4", + "php": "8.1 - 8.5" + }, + "conflict": { + "nette/di": "<3.0.3", + "nette/schema": "<1.2" + }, + "require-dev": { + "nette/di": "^3.0", + "nette/security": "^3.0", + "nette/tester": "^2.4", + "phpstan/phpstan-nette": "^2.0@stable", + "tracy/tracy": "^2.8" + }, + "suggest": { + "ext-fileinfo": "to detect MIME type of uploaded files by Nette\\Http\\FileUpload", + "ext-gd": "to use image function in Nette\\Http\\FileUpload", + "ext-intl": "to support punycode by Nette\\Http\\Url", + "ext-session": "to use Nette\\Http\\Session" + }, + "time": "2025-10-30T22:32:24+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.3-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Nette\\": "src" + }, + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause", + "GPL-2.0-only", + "GPL-3.0-only" + ], + "authors": [ + { + "name": "David Grudl", + "homepage": "https://davidgrudl.com" + }, + { + "name": "Nette Community", + "homepage": "https://nette.org/contributors" + } + ], + "description": "🌐 Nette Http: abstraction for HTTP request, response and session. Provides careful data sanitization and utility for URL and cookies manipulation.", + "homepage": "https://nette.org", + "keywords": [ + "cookies", + "http", + "nette", + "proxy", + "request", + "response", + "security", + "session", + "url" + ], + "support": { + "issues": "https://github.com/nette/http/issues", + "source": "https://github.com/nette/http/tree/v3.3.3" + }, + "install-path": "../nette/http" + }, + { + "name": "nette/mail", + "version": "v4.0.4", + "version_normalized": "4.0.4.0", + "source": { + "type": "git", + "url": "https://github.com/nette/mail.git", + "reference": "5f16f76ed14a32f34580811d1a07ac357352bbc4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nette/mail/zipball/5f16f76ed14a32f34580811d1a07ac357352bbc4", + "reference": "5f16f76ed14a32f34580811d1a07ac357352bbc4", + "shasum": "" + }, + "require": { + "ext-iconv": "*", + "nette/utils": "^4.0", + "php": "8.0 - 8.5" + }, + "require-dev": { + "nette/di": "^3.1 || ^4.0", + "nette/tester": "^2.4", + "phpstan/phpstan-nette": "^2.0@stable", + "tracy/tracy": "^2.8" + }, + "suggest": { + "ext-fileinfo": "to detect type of attached files", + "ext-openssl": "to use Nette\\Mail\\DkimSigner" + }, + "time": "2025-08-01T02:09:42+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Nette\\": "src" + }, + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause", + "GPL-2.0-only", + "GPL-3.0-only" + ], + "authors": [ + { + "name": "David Grudl", + "homepage": "https://davidgrudl.com" + }, + { + "name": "Nette Community", + "homepage": "https://nette.org/contributors" + } + ], + "description": "📧 Nette Mail: A handy library for creating and sending emails in PHP.", + "homepage": "https://nette.org", + "keywords": [ + "mail", + "mailer", + "mime", + "nette", + "smtp" + ], + "support": { + "issues": "https://github.com/nette/mail/issues", + "source": "https://github.com/nette/mail/tree/v4.0.4" + }, + "install-path": "../nette/mail" + }, + { + "name": "nette/neon", + "version": "v3.4.7", + "version_normalized": "3.4.7.0", + "source": { + "type": "git", + "url": "https://github.com/nette/neon.git", + "reference": "cc96bf5264d721d0c102bb976272d3d001a23e65" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nette/neon/zipball/cc96bf5264d721d0c102bb976272d3d001a23e65", + "reference": "cc96bf5264d721d0c102bb976272d3d001a23e65", + "shasum": "" + }, + "require": { + "ext-json": "*", + "php": "8.0 - 8.5" + }, + "require-dev": { + "nette/tester": "^2.4", + "phpstan/phpstan-nette": "^2.0@stable", + "tracy/tracy": "^2.7" + }, + "time": "2026-01-04T08:39:50+00:00", + "bin": [ + "bin/neon-lint" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.4-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Nette\\": "src" + }, + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause", + "GPL-2.0-only", + "GPL-3.0-only" + ], + "authors": [ + { + "name": "David Grudl", + "homepage": "https://davidgrudl.com" + }, + { + "name": "Nette Community", + "homepage": "https://nette.org/contributors" + } + ], + "description": "🍸 Nette NEON: encodes and decodes NEON file format.", + "homepage": "https://neon.nette.org", + "keywords": [ + "export", + "import", + "neon", + "nette", + "yaml" + ], + "support": { + "issues": "https://github.com/nette/neon/issues", + "source": "https://github.com/nette/neon/tree/v3.4.7" + }, + "install-path": "../nette/neon" + }, + { + "name": "nette/php-generator", + "version": "v4.2.0", + "version_normalized": "4.2.0.0", + "source": { + "type": "git", + "url": "https://github.com/nette/php-generator.git", + "reference": "4707546a1f11badd72f5d82af4f8a6bc64bd56ac" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nette/php-generator/zipball/4707546a1f11badd72f5d82af4f8a6bc64bd56ac", + "reference": "4707546a1f11badd72f5d82af4f8a6bc64bd56ac", + "shasum": "" + }, + "require": { + "nette/utils": "^4.0.6", + "php": "8.1 - 8.5" + }, + "require-dev": { + "jetbrains/phpstorm-attributes": "^1.2", + "nette/tester": "^2.4", + "nikic/php-parser": "^5.0", + "phpstan/phpstan-nette": "^2.0@stable", + "tracy/tracy": "^2.8" + }, + "suggest": { + "nikic/php-parser": "to use ClassType::from(withBodies: true) & ClassType::fromCode()" + }, + "time": "2025-08-06T18:24:31+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.2-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Nette\\": "src" + }, + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause", + "GPL-2.0-only", + "GPL-3.0-only" + ], + "authors": [ + { + "name": "David Grudl", + "homepage": "https://davidgrudl.com" + }, + { + "name": "Nette Community", + "homepage": "https://nette.org/contributors" + } + ], + "description": "🐘 Nette PHP Generator: generates neat PHP code for you. Supports new PHP 8.5 features.", + "homepage": "https://nette.org", + "keywords": [ + "code", + "nette", + "php", + "scaffolding" + ], + "support": { + "issues": "https://github.com/nette/php-generator/issues", + "source": "https://github.com/nette/php-generator/tree/v4.2.0" + }, + "install-path": "../nette/php-generator" + }, + { + "name": "nette/robot-loader", + "version": "v4.1.0", + "version_normalized": "4.1.0.0", + "source": { + "type": "git", + "url": "https://github.com/nette/robot-loader.git", + "reference": "805fb81376c24755d50bdb8bc69ca4db3def71d1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nette/robot-loader/zipball/805fb81376c24755d50bdb8bc69ca4db3def71d1", + "reference": "805fb81376c24755d50bdb8bc69ca4db3def71d1", + "shasum": "" + }, + "require": { + "ext-tokenizer": "*", + "nette/utils": "^4.0", + "php": "8.1 - 8.5" + }, + "require-dev": { + "nette/tester": "^2.4", + "phpstan/phpstan-nette": "^2.0@stable", + "tracy/tracy": "^2.9" + }, + "time": "2025-08-06T18:34:21+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.1-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Nette\\": "src" + }, + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause", + "GPL-2.0-only", + "GPL-3.0-only" + ], + "authors": [ + { + "name": "David Grudl", + "homepage": "https://davidgrudl.com" + }, + { + "name": "Nette Community", + "homepage": "https://nette.org/contributors" + } + ], + "description": "🍀 Nette RobotLoader: high performance and comfortable autoloader that will search and autoload classes within your application.", + "homepage": "https://nette.org", + "keywords": [ + "autoload", + "class", + "interface", + "nette", + "trait" + ], + "support": { + "issues": "https://github.com/nette/robot-loader/issues", + "source": "https://github.com/nette/robot-loader/tree/v4.1.0" + }, + "install-path": "../nette/robot-loader" + }, + { + "name": "nette/routing", + "version": "v3.1.2", + "version_normalized": "3.1.2.0", + "source": { + "type": "git", + "url": "https://github.com/nette/routing.git", + "reference": "14c466f3383add0d4f78a82074d3c9841f8edf47" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nette/routing/zipball/14c466f3383add0d4f78a82074d3c9841f8edf47", + "reference": "14c466f3383add0d4f78a82074d3c9841f8edf47", + "shasum": "" + }, + "require": { + "nette/http": "^3.2 || ~4.0.0", + "nette/utils": "^4.0", + "php": "8.1 - 8.5" + }, + "require-dev": { + "nette/tester": "^2.5", + "phpstan/phpstan-nette": "^2.0@stable", + "tracy/tracy": "^2.9" + }, + "time": "2025-10-31T00:55:27+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.1-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Nette\\": "src" + }, + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause", + "GPL-2.0-only", + "GPL-3.0-only" + ], + "authors": [ + { + "name": "David Grudl", + "homepage": "https://davidgrudl.com" + }, + { + "name": "Nette Community", + "homepage": "https://nette.org/contributors" + } + ], + "description": "Nette Routing: two-ways URL conversion", + "homepage": "https://nette.org", + "keywords": [ + "nette" + ], + "support": { + "issues": "https://github.com/nette/routing/issues", + "source": "https://github.com/nette/routing/tree/v3.1.2" + }, + "install-path": "../nette/routing" + }, + { + "name": "nette/schema", + "version": "v1.3.3", + "version_normalized": "1.3.3.0", + "source": { + "type": "git", + "url": "https://github.com/nette/schema.git", + "reference": "2befc2f42d7c715fd9d95efc31b1081e5d765004" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nette/schema/zipball/2befc2f42d7c715fd9d95efc31b1081e5d765004", + "reference": "2befc2f42d7c715fd9d95efc31b1081e5d765004", + "shasum": "" + }, + "require": { + "nette/utils": "^4.0", + "php": "8.1 - 8.5" + }, + "require-dev": { + "nette/tester": "^2.5.2", + "phpstan/phpstan-nette": "^2.0@stable", + "tracy/tracy": "^2.8" + }, + "time": "2025-10-30T22:57:59+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.3-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Nette\\": "src" + }, + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause", + "GPL-2.0-only", + "GPL-3.0-only" + ], + "authors": [ + { + "name": "David Grudl", + "homepage": "https://davidgrudl.com" + }, + { + "name": "Nette Community", + "homepage": "https://nette.org/contributors" + } + ], + "description": "📐 Nette Schema: validating data structures against a given Schema.", + "homepage": "https://nette.org", + "keywords": [ + "config", + "nette" + ], + "support": { + "issues": "https://github.com/nette/schema/issues", + "source": "https://github.com/nette/schema/tree/v1.3.3" + }, + "install-path": "../nette/schema" + }, + { + "name": "nette/security", + "version": "v3.2.2", + "version_normalized": "3.2.2.0", + "source": { + "type": "git", + "url": "https://github.com/nette/security.git", + "reference": "beca6757457281ebc9428743bec7960809f40d49" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nette/security/zipball/beca6757457281ebc9428743bec7960809f40d49", + "reference": "beca6757457281ebc9428743bec7960809f40d49", + "shasum": "" + }, + "require": { + "nette/utils": "^4.0", + "php": "8.1 - 8.5" + }, + "conflict": { + "nette/di": "<3.0-stable", + "nette/http": "<3.1.3" + }, + "require-dev": { + "mockery/mockery": "^1.6@stable", + "nette/di": "^3.1", + "nette/http": "^3.2", + "nette/tester": "^2.5", + "phpstan/phpstan-nette": "^2.0@stable", + "tracy/tracy": "^2.9" + }, + "time": "2025-08-01T02:15:08+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.2-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Nette\\": "src" + }, + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause", + "GPL-2.0-only", + "GPL-3.0-only" + ], + "authors": [ + { + "name": "David Grudl", + "homepage": "https://davidgrudl.com" + }, + { + "name": "Nette Community", + "homepage": "https://nette.org/contributors" + } + ], + "description": "🔑 Nette Security: provides authentication, authorization and a role-based access control management via ACL (Access Control List)", + "homepage": "https://nette.org", + "keywords": [ + "Authentication", + "acl", + "authorization", + "nette" + ], + "support": { + "issues": "https://github.com/nette/security/issues", + "source": "https://github.com/nette/security/tree/v3.2.2" + }, + "install-path": "../nette/security" + }, + { + "name": "nette/tester", + "version": "v2.5.7", + "version_normalized": "2.5.7.0", + "source": { + "type": "git", + "url": "https://github.com/nette/tester.git", + "reference": "dc02e7811f3491a72e87538044586cee2f483d58" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nette/tester/zipball/dc02e7811f3491a72e87538044586cee2f483d58", + "reference": "dc02e7811f3491a72e87538044586cee2f483d58", + "shasum": "" + }, + "require": { + "php": "8.0 - 8.5" + }, + "require-dev": { + "ext-simplexml": "*", + "phpstan/phpstan-nette": "^2.0@stable" + }, + "time": "2025-11-22T18:50:53+00:00", + "bin": [ + "src/tester" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.5-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Tester\\": "src" + }, + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause", + "GPL-2.0-only", + "GPL-3.0-only" + ], + "authors": [ + { + "name": "David Grudl", + "homepage": "https://davidgrudl.com" + }, + { + "name": "Miloslav Hůla", + "homepage": "https://github.com/milo" + }, + { + "name": "Nette Community", + "homepage": "https://nette.org/contributors" + } + ], + "description": "Nette Tester: enjoyable unit testing in PHP with code coverage reporter. 🍏🍏🍎🍏", + "homepage": "https://tester.nette.org", + "keywords": [ + "Xdebug", + "assertions", + "clover", + "code coverage", + "nette", + "pcov", + "phpdbg", + "phpunit", + "testing", + "unit" + ], + "support": { + "issues": "https://github.com/nette/tester/issues", + "source": "https://github.com/nette/tester/tree/v2.5.7" + }, + "install-path": "../nette/tester" + }, + { + "name": "nette/utils", + "version": "v4.1.1", + "version_normalized": "4.1.1.0", + "source": { + "type": "git", + "url": "https://github.com/nette/utils.git", + "reference": "c99059c0315591f1a0db7ad6002000288ab8dc72" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nette/utils/zipball/c99059c0315591f1a0db7ad6002000288ab8dc72", + "reference": "c99059c0315591f1a0db7ad6002000288ab8dc72", + "shasum": "" + }, + "require": { + "php": "8.2 - 8.5" + }, + "conflict": { + "nette/finder": "<3", + "nette/schema": "<1.2.2" + }, + "require-dev": { + "jetbrains/phpstorm-attributes": "^1.2", + "nette/tester": "^2.5", + "phpstan/phpstan-nette": "^2.0@stable", + "tracy/tracy": "^2.9" + }, + "suggest": { + "ext-gd": "to use Image", + "ext-iconv": "to use Strings::webalize(), toAscii(), chr() and reverse()", + "ext-intl": "to use Strings::webalize(), toAscii(), normalize() and compare()", + "ext-json": "to use Nette\\Utils\\Json", + "ext-mbstring": "to use Strings::lower() etc...", + "ext-tokenizer": "to use Nette\\Utils\\Reflection::getUseStatements()" + }, + "time": "2025-12-22T12:14:32+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.1-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Nette\\": "src" + }, + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause", + "GPL-2.0-only", + "GPL-3.0-only" + ], + "authors": [ + { + "name": "David Grudl", + "homepage": "https://davidgrudl.com" + }, + { + "name": "Nette Community", + "homepage": "https://nette.org/contributors" + } + ], + "description": "🛠 Nette Utils: lightweight utilities for string & array manipulation, image handling, safe JSON encoding/decoding, validation, slug or strong password generating etc.", + "homepage": "https://nette.org", + "keywords": [ + "array", + "core", + "datetime", + "images", + "json", + "nette", + "paginator", + "password", + "slugify", + "string", + "unicode", + "utf-8", + "utility", + "validation" + ], + "support": { + "issues": "https://github.com/nette/utils/issues", + "source": "https://github.com/nette/utils/tree/v4.1.1" + }, + "install-path": "../nette/utils" + }, + { + "name": "paragonie/constant_time_encoding", + "version": "v3.1.3", + "version_normalized": "3.1.3.0", + "source": { + "type": "git", + "url": "https://github.com/paragonie/constant_time_encoding.git", + "reference": "d5b01a39b3415c2cd581d3bd3a3575c1ebbd8e77" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/paragonie/constant_time_encoding/zipball/d5b01a39b3415c2cd581d3bd3a3575c1ebbd8e77", + "reference": "d5b01a39b3415c2cd581d3bd3a3575c1ebbd8e77", + "shasum": "" + }, + "require": { + "php": "^8" + }, + "require-dev": { + "infection/infection": "^0", + "nikic/php-fuzzer": "^0", + "phpunit/phpunit": "^9|^10|^11", + "vimeo/psalm": "^4|^5|^6" + }, + "time": "2025-09-24T15:06:41+00:00", + "type": "library", + "installation-source": "dist", + "autoload": { + "psr-4": { + "ParagonIE\\ConstantTime\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "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" + } + ], + "description": "Constant-time Implementations of RFC 4648 Encoding (Base-64, Base-32, Base-16)", + "keywords": [ + "base16", + "base32", + "base32_decode", + "base32_encode", + "base64", + "base64_decode", + "base64_encode", + "bin2hex", + "encoding", + "hex", + "hex2bin", + "rfc4648" + ], + "support": { + "email": "info@paragonie.com", + "issues": "https://github.com/paragonie/constant_time_encoding/issues", + "source": "https://github.com/paragonie/constant_time_encoding" + }, + "install-path": "../paragonie/constant_time_encoding" + }, + { + "name": "phpstan/phpstan", + "version": "2.1.33", + "version_normalized": "2.1.33.0", + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/9e800e6bee7d5bd02784d4c6069b48032d16224f", + "reference": "9e800e6bee7d5bd02784d4c6069b48032d16224f", + "shasum": "" + }, + "require": { + "php": "^7.4|^8.0" + }, + "conflict": { + "phpstan/phpstan-shim": "*" + }, + "time": "2025-12-05T10:24:31+00:00", + "bin": [ + "phpstan", + "phpstan.phar" + ], + "type": "library", + "installation-source": "dist", + "autoload": { + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "PHPStan - PHP Static Analysis Tool", + "keywords": [ + "dev", + "static analysis" + ], + "support": { + "docs": "https://phpstan.org/user-guide/getting-started", + "forum": "https://github.com/phpstan/phpstan/discussions", + "issues": "https://github.com/phpstan/phpstan/issues", + "security": "https://github.com/phpstan/phpstan/security/policy", + "source": "https://github.com/phpstan/phpstan-src" + }, + "funding": [ + { + "url": "https://github.com/ondrejmirtes", + "type": "github" + }, + { + "url": "https://github.com/phpstan", + "type": "github" + } + ], + "install-path": "../phpstan/phpstan" + }, + { + "name": "phpstan/phpstan-nette", + "version": "2.0.7", + "version_normalized": "2.0.7.0", + "source": { + "type": "git", + "url": "https://github.com/phpstan/phpstan-nette.git", + "reference": "488d326408740b28c364849316ec065c13799568" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpstan/phpstan-nette/zipball/488d326408740b28c364849316ec065c13799568", + "reference": "488d326408740b28c364849316ec065c13799568", + "shasum": "" + }, + "require": { + "php": "^7.4 || ^8.0", + "phpstan/phpstan": "^2.1.12" + }, + "conflict": { + "nette/application": "<2.3.0", + "nette/component-model": "<2.3.0", + "nette/di": "<2.3.0", + "nette/forms": "<2.3.0", + "nette/http": "<2.3.0", + "nette/utils": "<2.3.0" + }, + "require-dev": { + "nette/application": "^3.0", + "nette/di": "^3.0", + "nette/forms": "^3.0", + "nette/utils": "^2.3.0 || ^3.0.0 || ^4.0", + "php-parallel-lint/php-parallel-lint": "^1.2", + "phpstan/phpstan-deprecation-rules": "^2.0", + "phpstan/phpstan-phpunit": "^2.0.8", + "phpstan/phpstan-strict-rules": "^2.0", + "phpunit/phpunit": "^9.6" + }, + "time": "2025-12-08T10:39:26+00:00", + "type": "phpstan-extension", + "extra": { + "phpstan": { + "includes": [ + "extension.neon", + "rules.neon" + ] + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "PHPStan\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Nette Framework class reflection extension for PHPStan", + "support": { + "issues": "https://github.com/phpstan/phpstan-nette/issues", + "source": "https://github.com/phpstan/phpstan-nette/tree/2.0.7" + }, + "install-path": "../phpstan/phpstan-nette" + }, + { + "name": "psr/clock", + "version": "1.0.0", + "version_normalized": "1.0.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/clock.git", + "reference": "e41a24703d4560fd0acb709162f73b8adfc3aa0d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/clock/zipball/e41a24703d4560fd0acb709162f73b8adfc3aa0d", + "reference": "e41a24703d4560fd0acb709162f73b8adfc3aa0d", + "shasum": "" + }, + "require": { + "php": "^7.0 || ^8.0" + }, + "time": "2022-11-25T14:36:26+00:00", + "type": "library", + "installation-source": "dist", + "autoload": { + "psr-4": { + "Psr\\Clock\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for reading the clock.", + "homepage": "https://github.com/php-fig/clock", + "keywords": [ + "clock", + "now", + "psr", + "psr-20", + "time" + ], + "support": { + "issues": "https://github.com/php-fig/clock/issues", + "source": "https://github.com/php-fig/clock/tree/1.0.0" + }, + "install-path": "../psr/clock" + }, + { + "name": "spomky-labs/otphp", + "version": "11.4.2", + "version_normalized": "11.4.2.0", + "source": { + "type": "git", + "url": "https://github.com/Spomky-Labs/otphp.git", + "reference": "2a1b503fd1c1a5c751ab3c5cd37f2d2d26ab74ad" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Spomky-Labs/otphp/zipball/2a1b503fd1c1a5c751ab3c5cd37f2d2d26ab74ad", + "reference": "2a1b503fd1c1a5c751ab3c5cd37f2d2d26ab74ad", + "shasum": "" + }, + "require": { + "paragonie/constant_time_encoding": "^2.0 || ^3.0", + "php": ">=8.1", + "psr/clock": "^1.0", + "symfony/deprecation-contracts": "^3.2" + }, + "require-dev": { + "symfony/error-handler": "^6.4|^7.0|^8.0" + }, + "time": "2026-01-23T10:53:01+00:00", + "type": "library", + "installation-source": "dist", + "autoload": { + "psr-4": { + "OTPHP\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Florent Morselli", + "homepage": "https://github.com/Spomky" + }, + { + "name": "All contributors", + "homepage": "https://github.com/Spomky-Labs/otphp/contributors" + } + ], + "description": "A PHP library for generating one time passwords according to RFC 4226 (HOTP Algorithm) and the RFC 6238 (TOTP Algorithm) and compatible with Google Authenticator", + "homepage": "https://github.com/Spomky-Labs/otphp", + "keywords": [ + "FreeOTP", + "RFC 4226", + "RFC 6238", + "google authenticator", + "hotp", + "otp", + "totp" + ], + "support": { + "issues": "https://github.com/Spomky-Labs/otphp/issues", + "source": "https://github.com/Spomky-Labs/otphp/tree/11.4.2" + }, + "funding": [ + { + "url": "https://github.com/Spomky", + "type": "github" + }, + { + "url": "https://www.patreon.com/FlorentMorselli", + "type": "patreon" + } + ], + "install-path": "../spomky-labs/otphp" + }, + { + "name": "symfony/deprecation-contracts", + "version": "v3.6.0", + "version_normalized": "3.6.0.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/deprecation-contracts.git", + "reference": "63afe740e99a13ba87ec199bb07bbdee937a5b62" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/63afe740e99a13ba87ec199bb07bbdee937a5b62", + "reference": "63afe740e99a13ba87ec199bb07bbdee937a5b62", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "time": "2024-09-25T14:21:43+00:00", + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/contracts", + "name": "symfony/contracts" + }, + "branch-alias": { + "dev-main": "3.6-dev" + } + }, + "installation-source": "dist", + "autoload": { + "files": [ + "function.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "A generic function and convention to trigger deprecation notices", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/deprecation-contracts/tree/v3.6.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "install-path": "../symfony/deprecation-contracts" + }, + { + "name": "symfony/thanks", + "version": "v1.4.1", + "version_normalized": "1.4.1.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/thanks.git", + "reference": "f455cc9ba4e0c61dcc18ea7e52bd725ee661aa64" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/thanks/zipball/f455cc9ba4e0c61dcc18ea7e52bd725ee661aa64", + "reference": "f455cc9ba4e0c61dcc18ea7e52bd725ee661aa64", + "shasum": "" + }, + "require": { + "composer-plugin-api": "^1.0|^2.0", + "php": ">=8.1" + }, + "time": "2025-10-30T17:38:50+00:00", + "type": "composer-plugin", + "extra": { + "class": "Symfony\\Thanks\\Thanks", + "branch-alias": { + "dev-main": "1.4-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Symfony\\Thanks\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + } + ], + "description": "Encourages sending ⭐ and 💵 to fellow PHP package maintainers (not limited to Symfony components)!", + "support": { + "issues": "https://github.com/symfony/thanks/issues", + "source": "https://github.com/symfony/thanks/tree/v1.4.1" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "install-path": "../symfony/thanks" + }, + { + "name": "tracy/tracy", + "version": "v2.11.0", + "version_normalized": "2.11.0.0", + "source": { + "type": "git", + "url": "https://github.com/nette/tracy.git", + "reference": "eec57bcf2ff11d79f519a19da9d7ae1e2c63c42e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nette/tracy/zipball/eec57bcf2ff11d79f519a19da9d7ae1e2c63c42e", + "reference": "eec57bcf2ff11d79f519a19da9d7ae1e2c63c42e", + "shasum": "" + }, + "require": { + "ext-json": "*", + "ext-session": "*", + "php": "8.2 - 8.5" + }, + "conflict": { + "nette/di": "<3.0" + }, + "require-dev": { + "latte/latte": "^2.5 || ^3.0", + "nette/di": "^3.0", + "nette/http": "^3.0", + "nette/mail": "^3.0 || ^4.0", + "nette/tester": "^2.2", + "nette/utils": "^3.0 || ^4.0", + "phpstan/phpstan-nette": "^2.0@stable", + "psr/log": "^1.0 || ^2.0 || ^3.0" + }, + "time": "2025-10-31T00:12:50+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.11-dev" + } + }, + "installation-source": "dist", + "autoload": { + "files": [ + "src/Tracy/functions.php" + ], + "psr-4": { + "Tracy\\": "src" + }, + "classmap": [ + "src" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "David Grudl", + "homepage": "https://davidgrudl.com" + }, + { + "name": "Nette Community", + "homepage": "https://nette.org/contributors" + } + ], + "description": "😎 Tracy: the addictive tool to ease debugging PHP code for cool developers. Friendly design, logging, profiler, advanced features like debugging AJAX calls or CLI support. You will love it.", + "homepage": "https://tracy.nette.org", + "keywords": [ + "Xdebug", + "debug", + "debugger", + "nette", + "profiler" + ], + "support": { + "issues": "https://github.com/nette/tracy/issues", + "source": "https://github.com/nette/tracy/tree/v2.11.0" + }, + "install-path": "../tracy/tracy" + } + ], + "dev": true, + "dev-package-names": [ + "nette/tester", + "phpstan/phpstan", + "phpstan/phpstan-nette", + "symfony/thanks" + ] +} diff --git a/vendor/composer/installed.php b/vendor/composer/installed.php new file mode 100644 index 0000000..ea4c1a6 --- /dev/null +++ b/vendor/composer/installed.php @@ -0,0 +1,293 @@ + array( + 'name' => 'nette/web-project', + 'pretty_version' => '1.0.0+no-version-set', + 'version' => '1.0.0.0', + 'reference' => null, + 'type' => 'project', + 'install_path' => __DIR__ . '/../../', + 'aliases' => array(), + 'dev' => true, + ), + 'versions' => array( + 'bacon/bacon-qr-code' => array( + 'pretty_version' => 'v3.0.3', + 'version' => '3.0.3.0', + 'reference' => '36a1cb2b81493fa5b82e50bf8068bf84d1542563', + 'type' => 'library', + 'install_path' => __DIR__ . '/../bacon/bacon-qr-code', + 'aliases' => array(), + 'dev_requirement' => false, + ), + 'dasprid/enum' => array( + 'pretty_version' => '1.0.7', + 'version' => '1.0.7.0', + 'reference' => 'b5874fa9ed0043116c72162ec7f4fb50e02e7cce', + 'type' => 'library', + 'install_path' => __DIR__ . '/../dasprid/enum', + 'aliases' => array(), + 'dev_requirement' => false, + ), + 'endroid/qr-code' => array( + 'pretty_version' => '6.0.9', + 'version' => '6.0.9.0', + 'reference' => '21e888e8597440b2205e2e5c484b6c8e556bcd1a', + 'type' => 'library', + 'install_path' => __DIR__ . '/../endroid/qr-code', + 'aliases' => array(), + 'dev_requirement' => false, + ), + 'latte/latte' => array( + 'pretty_version' => 'v3.1.1', + 'version' => '3.1.1.0', + 'reference' => 'cb98e705eeb0fd18f1f1c5cfe1a5f6217f9fa8b3', + 'type' => 'library', + 'install_path' => __DIR__ . '/../latte/latte', + 'aliases' => array(), + 'dev_requirement' => false, + ), + 'nette/application' => array( + 'pretty_version' => 'v3.2.9', + 'version' => '3.2.9.0', + 'reference' => '11d9d6fc53d579a3516c1574c707a5de281bc0a0', + 'type' => 'library', + 'install_path' => __DIR__ . '/../nette/application', + 'aliases' => array(), + 'dev_requirement' => false, + ), + 'nette/assets' => array( + 'pretty_version' => 'v1.0.5', + 'version' => '1.0.5.0', + 'reference' => 'd747983c8a8ee5e8508ab9b45282c869e6b1f623', + 'type' => 'library', + 'install_path' => __DIR__ . '/../nette/assets', + 'aliases' => array(), + 'dev_requirement' => false, + ), + 'nette/bootstrap' => array( + 'pretty_version' => 'v3.2.7', + 'version' => '3.2.7.0', + 'reference' => '10fdb1cb05497da39396f2ce1785cea67c8aa439', + 'type' => 'library', + 'install_path' => __DIR__ . '/../nette/bootstrap', + 'aliases' => array(), + 'dev_requirement' => false, + ), + 'nette/caching' => array( + 'pretty_version' => 'v3.4.0', + 'version' => '3.4.0.0', + 'reference' => 'a1c13221b350d0db0a2bd4a77c1e7b65e0aa065d', + 'type' => 'library', + 'install_path' => __DIR__ . '/../nette/caching', + 'aliases' => array(), + 'dev_requirement' => false, + ), + 'nette/component-model' => array( + 'pretty_version' => 'v3.1.3', + 'version' => '3.1.3.0', + 'reference' => '0d100ba05279a1f4b20acecaa617027fbda8ecb2', + 'type' => 'library', + 'install_path' => __DIR__ . '/../nette/component-model', + 'aliases' => array(), + 'dev_requirement' => false, + ), + 'nette/database' => array( + 'pretty_version' => 'v3.2.8', + 'version' => '3.2.8.0', + 'reference' => '1a84d3e61aa33461a3d6415235b25a7cd8b3f442', + 'type' => 'library', + 'install_path' => __DIR__ . '/../nette/database', + 'aliases' => array(), + 'dev_requirement' => false, + ), + 'nette/di' => array( + 'pretty_version' => 'v3.2.5', + 'version' => '3.2.5.0', + 'reference' => '5708c328ce7658a73c96b14dd6da7b8b27bf220f', + 'type' => 'library', + 'install_path' => __DIR__ . '/../nette/di', + 'aliases' => array(), + 'dev_requirement' => false, + ), + 'nette/forms' => array( + 'pretty_version' => 'v3.2.8', + 'version' => '3.2.8.0', + 'reference' => '3bbf691ea0eb50d9594c2109d9252f267092b91f', + 'type' => 'library', + 'install_path' => __DIR__ . '/../nette/forms', + 'aliases' => array(), + 'dev_requirement' => false, + ), + 'nette/http' => array( + 'pretty_version' => 'v3.3.3', + 'version' => '3.3.3.0', + 'reference' => 'c557f21c8cedd621dbfd7990752b1d55ef353f1d', + 'type' => 'library', + 'install_path' => __DIR__ . '/../nette/http', + 'aliases' => array(), + 'dev_requirement' => false, + ), + 'nette/mail' => array( + 'pretty_version' => 'v4.0.4', + 'version' => '4.0.4.0', + 'reference' => '5f16f76ed14a32f34580811d1a07ac357352bbc4', + 'type' => 'library', + 'install_path' => __DIR__ . '/../nette/mail', + 'aliases' => array(), + 'dev_requirement' => false, + ), + 'nette/neon' => array( + 'pretty_version' => 'v3.4.7', + 'version' => '3.4.7.0', + 'reference' => 'cc96bf5264d721d0c102bb976272d3d001a23e65', + 'type' => 'library', + 'install_path' => __DIR__ . '/../nette/neon', + 'aliases' => array(), + 'dev_requirement' => false, + ), + 'nette/php-generator' => array( + 'pretty_version' => 'v4.2.0', + 'version' => '4.2.0.0', + 'reference' => '4707546a1f11badd72f5d82af4f8a6bc64bd56ac', + 'type' => 'library', + 'install_path' => __DIR__ . '/../nette/php-generator', + 'aliases' => array(), + 'dev_requirement' => false, + ), + 'nette/robot-loader' => array( + 'pretty_version' => 'v4.1.0', + 'version' => '4.1.0.0', + 'reference' => '805fb81376c24755d50bdb8bc69ca4db3def71d1', + 'type' => 'library', + 'install_path' => __DIR__ . '/../nette/robot-loader', + 'aliases' => array(), + 'dev_requirement' => false, + ), + 'nette/routing' => array( + 'pretty_version' => 'v3.1.2', + 'version' => '3.1.2.0', + 'reference' => '14c466f3383add0d4f78a82074d3c9841f8edf47', + 'type' => 'library', + 'install_path' => __DIR__ . '/../nette/routing', + 'aliases' => array(), + 'dev_requirement' => false, + ), + 'nette/schema' => array( + 'pretty_version' => 'v1.3.3', + 'version' => '1.3.3.0', + 'reference' => '2befc2f42d7c715fd9d95efc31b1081e5d765004', + 'type' => 'library', + 'install_path' => __DIR__ . '/../nette/schema', + 'aliases' => array(), + 'dev_requirement' => false, + ), + 'nette/security' => array( + 'pretty_version' => 'v3.2.2', + 'version' => '3.2.2.0', + 'reference' => 'beca6757457281ebc9428743bec7960809f40d49', + 'type' => 'library', + 'install_path' => __DIR__ . '/../nette/security', + 'aliases' => array(), + 'dev_requirement' => false, + ), + 'nette/tester' => array( + 'pretty_version' => 'v2.5.7', + 'version' => '2.5.7.0', + 'reference' => 'dc02e7811f3491a72e87538044586cee2f483d58', + 'type' => 'library', + 'install_path' => __DIR__ . '/../nette/tester', + 'aliases' => array(), + 'dev_requirement' => true, + ), + 'nette/utils' => array( + 'pretty_version' => 'v4.1.1', + 'version' => '4.1.1.0', + 'reference' => 'c99059c0315591f1a0db7ad6002000288ab8dc72', + 'type' => 'library', + 'install_path' => __DIR__ . '/../nette/utils', + 'aliases' => array(), + 'dev_requirement' => false, + ), + 'nette/web-project' => array( + 'pretty_version' => '1.0.0+no-version-set', + 'version' => '1.0.0.0', + 'reference' => null, + 'type' => 'project', + 'install_path' => __DIR__ . '/../../', + 'aliases' => array(), + 'dev_requirement' => false, + ), + 'paragonie/constant_time_encoding' => array( + 'pretty_version' => 'v3.1.3', + 'version' => '3.1.3.0', + 'reference' => 'd5b01a39b3415c2cd581d3bd3a3575c1ebbd8e77', + 'type' => 'library', + 'install_path' => __DIR__ . '/../paragonie/constant_time_encoding', + 'aliases' => array(), + 'dev_requirement' => false, + ), + 'phpstan/phpstan' => array( + 'pretty_version' => '2.1.33', + 'version' => '2.1.33.0', + 'reference' => '9e800e6bee7d5bd02784d4c6069b48032d16224f', + 'type' => 'library', + 'install_path' => __DIR__ . '/../phpstan/phpstan', + 'aliases' => array(), + 'dev_requirement' => true, + ), + 'phpstan/phpstan-nette' => array( + 'pretty_version' => '2.0.7', + 'version' => '2.0.7.0', + 'reference' => '488d326408740b28c364849316ec065c13799568', + 'type' => 'phpstan-extension', + 'install_path' => __DIR__ . '/../phpstan/phpstan-nette', + 'aliases' => array(), + 'dev_requirement' => true, + ), + 'psr/clock' => array( + 'pretty_version' => '1.0.0', + 'version' => '1.0.0.0', + 'reference' => 'e41a24703d4560fd0acb709162f73b8adfc3aa0d', + 'type' => 'library', + 'install_path' => __DIR__ . '/../psr/clock', + 'aliases' => array(), + 'dev_requirement' => false, + ), + 'spomky-labs/otphp' => array( + 'pretty_version' => '11.4.2', + 'version' => '11.4.2.0', + 'reference' => '2a1b503fd1c1a5c751ab3c5cd37f2d2d26ab74ad', + 'type' => 'library', + 'install_path' => __DIR__ . '/../spomky-labs/otphp', + 'aliases' => array(), + 'dev_requirement' => false, + ), + 'symfony/deprecation-contracts' => array( + 'pretty_version' => 'v3.6.0', + 'version' => '3.6.0.0', + 'reference' => '63afe740e99a13ba87ec199bb07bbdee937a5b62', + 'type' => 'library', + 'install_path' => __DIR__ . '/../symfony/deprecation-contracts', + 'aliases' => array(), + 'dev_requirement' => false, + ), + 'symfony/thanks' => array( + 'pretty_version' => 'v1.4.1', + 'version' => '1.4.1.0', + 'reference' => 'f455cc9ba4e0c61dcc18ea7e52bd725ee661aa64', + 'type' => 'composer-plugin', + 'install_path' => __DIR__ . '/../symfony/thanks', + 'aliases' => array(), + 'dev_requirement' => true, + ), + 'tracy/tracy' => array( + 'pretty_version' => 'v2.11.0', + 'version' => '2.11.0.0', + 'reference' => 'eec57bcf2ff11d79f519a19da9d7ae1e2c63c42e', + 'type' => 'library', + 'install_path' => __DIR__ . '/../tracy/tracy', + 'aliases' => array(), + 'dev_requirement' => false, + ), + ), +); diff --git a/vendor/composer/platform_check.php b/vendor/composer/platform_check.php new file mode 100644 index 0000000..d32d90c --- /dev/null +++ b/vendor/composer/platform_check.php @@ -0,0 +1,26 @@ += 80200)) { + $issues[] = 'Your Composer dependencies require a PHP version ">= 8.2.0". You are running ' . PHP_VERSION . '.'; +} + +if ($issues) { + if (!headers_sent()) { + header('HTTP/1.1 500 Internal Server Error'); + } + if (!ini_get('display_errors')) { + if (PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') { + fwrite(STDERR, 'Composer detected issues in your platform:' . PHP_EOL.PHP_EOL . implode(PHP_EOL, $issues) . PHP_EOL.PHP_EOL); + } elseif (!headers_sent()) { + echo 'Composer detected issues in your platform:' . PHP_EOL.PHP_EOL . str_replace('You are running '.PHP_VERSION.'.', '', implode(PHP_EOL, $issues)) . PHP_EOL.PHP_EOL; + } + } + trigger_error( + 'Composer detected issues in your platform: ' . implode(' ', $issues), + E_USER_ERROR + ); +} diff --git a/vendor/dasprid/enum/LICENSE b/vendor/dasprid/enum/LICENSE new file mode 100644 index 0000000..d45a356 --- /dev/null +++ b/vendor/dasprid/enum/LICENSE @@ -0,0 +1,22 @@ +Copyright (c) 2017, Ben Scholzen 'DASPRiD' +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. + +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/dasprid/enum/README.md b/vendor/dasprid/enum/README.md new file mode 100644 index 0000000..da37045 --- /dev/null +++ b/vendor/dasprid/enum/README.md @@ -0,0 +1,164 @@ +# PHP 7.1 enums + +[![Build Status](https://github.com/DASPRiD/Enum/actions/workflows/tests.yml/badge.svg)](https://github.com/DASPRiD/Enum/actions?query=workflow%3Atests) +[![Coverage Status](https://coveralls.io/repos/github/DASPRiD/Enum/badge.svg?branch=master)](https://coveralls.io/github/DASPRiD/Enum?branch=master) +[![Latest Stable Version](https://poser.pugx.org/dasprid/enum/v/stable)](https://packagist.org/packages/dasprid/enum) +[![Total Downloads](https://poser.pugx.org/dasprid/enum/downloads)](https://packagist.org/packages/dasprid/enum) +[![License](https://poser.pugx.org/dasprid/enum/license)](https://packagist.org/packages/dasprid/enum) + +It is a well known fact that PHP is missing a basic enum type, ignoring the rather incomplete `SplEnum` implementation +which is only available as a PECL extension. There are also quite a few other userland enum implementations around, +but all of them have one or another compromise. This library tries to close that gap as far as PHP allows it to. + +## Usage + +### Basics + +At its core, there is the `DASPRiD\Enum\AbstractEnum` class, which by default will work with constants like any other +enum implementation you might know. The first clear difference is that you should define all the constants as protected +(so nobody outside your class can read them but the `AbstractEnum` can still do so). The other even mightier difference +is that, for simple enums, the value of the constant doesn't matter at all. Let's have a look at a simple example: + +```php +use DASPRiD\Enum\AbstractEnum; + +/** + * @method static self MONDAY() + * @method static self TUESDAY() + * @method static self WEDNESDAY() + * @method static self THURSDAY() + * @method static self FRIDAY() + * @method static self SATURDAY() + * @method static self SUNDAY() + */ +final class WeekDay extends AbstractEnum +{ + protected const MONDAY = null; + protected const TUESDAY = null; + protected const WEDNESDAY = null; + protected const THURSDAY = null; + protected const FRIDAY = null; + protected const SATURDAY = null; + protected const SUNDAY = null; +} +``` + +If you need to provide constants for either internal use or public use, you can mark them as either private or public, +in which case they will be ignored by the enum, which only considers protected constants as valid values. As you can +see, we specifically defined the generated magic methods in a class level doc block, so anyone using this class will +automatically have proper auto-completion in their IDE. Now since you have defined the enum, you can simply use it like +that: + +```php +function tellItLikeItIs(WeekDay $weekDay) +{ + switch ($weekDay) { + case WeekDay::MONDAY(): + echo 'Mondays are bad.'; + break; + + case WeekDay::FRIDAY(): + echo 'Fridays are better.'; + break; + + case WeekDay::SATURDAY(): + case WeekDay::SUNDAY(): + echo 'Weekends are best.'; + break; + + default: + echo 'Midweek days are so-so.'; + } +} + +tellItLikeItIs(WeekDay::MONDAY()); +tellItLikeItIs(WeekDay::WEDNESDAY()); +tellItLikeItIs(WeekDay::FRIDAY()); +tellItLikeItIs(WeekDay::SATURDAY()); +tellItLikeItIs(WeekDay::SUNDAY()); +``` + +### More complex example + +Of course, all enums are singletons, which are not cloneable or serializable. Thus you can be sure that there is always +just one instance of the same type. Of course, the values of constants are not completely useless, let's have a look at +a more complex example: + +```php +use DASPRiD\Enum\AbstractEnum; + +/** + * @method static self MERCURY() + * @method static self VENUS() + * @method static self EARTH() + * @method static self MARS() + * @method static self JUPITER() + * @method static self SATURN() + * @method static self URANUS() + * @method static self NEPTUNE() + */ +final class Planet extends AbstractEnum +{ + protected const MERCURY = [3.303e+23, 2.4397e6]; + protected const VENUS = [4.869e+24, 6.0518e6]; + protected const EARTH = [5.976e+24, 6.37814e6]; + protected const MARS = [6.421e+23, 3.3972e6]; + protected const JUPITER = [1.9e+27, 7.1492e7]; + protected const SATURN = [5.688e+26, 6.0268e7]; + protected const URANUS = [8.686e+25, 2.5559e7]; + protected const NEPTUNE = [1.024e+26, 2.4746e7]; + + /** + * Universal gravitational constant. + * + * @var float + */ + private const G = 6.67300E-11; + + /** + * Mass in kilograms. + * + * @var float + */ + private $mass; + + /** + * Radius in meters. + * + * @var float + */ + private $radius; + + protected function __construct(float $mass, float $radius) + { + $this->mass = $mass; + $this->radius = $radius; + } + + public function mass() : float + { + return $this->mass; + } + + public function radius() : float + { + return $this->radius; + } + + public function surfaceGravity() : float + { + return self::G * $this->mass / ($this->radius * $this->radius); + } + + public function surfaceWeight(float $otherMass) : float + { + return $otherMass * $this->surfaceGravity(); + } +} + +$myMass = 80; + +foreach (Planet::values() as $planet) { + printf("Your weight on %s is %f\n", $planet, $planet->surfaceWeight($myMass)); +} +``` diff --git a/vendor/dasprid/enum/composer.json b/vendor/dasprid/enum/composer.json new file mode 100644 index 0000000..a099aba --- /dev/null +++ b/vendor/dasprid/enum/composer.json @@ -0,0 +1,34 @@ +{ + "name": "dasprid/enum", + "description": "PHP 7.1 enum implementation", + "license": "BSD-2-Clause", + "authors": [ + { + "name": "Ben Scholzen 'DASPRiD'", + "email": "mail@dasprids.de", + "homepage": "https://dasprids.de/", + "role": "Developer" + } + ], + "keywords": [ + "enum", + "map" + ], + "require": { + "php": ">=7.1 <9.0" + }, + "require-dev": { + "phpunit/phpunit": "^7 || ^8 || ^9 || ^10 || ^11", + "squizlabs/php_codesniffer": "*" + }, + "autoload": { + "psr-4": { + "DASPRiD\\Enum\\": "src/" + } + }, + "autoload-dev": { + "psr-4": { + "DASPRiD\\EnumTest\\": "test/" + } + } +} diff --git a/vendor/dasprid/enum/src/AbstractEnum.php b/vendor/dasprid/enum/src/AbstractEnum.php new file mode 100644 index 0000000..43006dc --- /dev/null +++ b/vendor/dasprid/enum/src/AbstractEnum.php @@ -0,0 +1,261 @@ +> + */ + private static $values = []; + + /** + * @var array + */ + private static $allValuesLoaded = []; + + /** + * @var array + */ + private static $constants = []; + + /** + * The constructor is private by default to avoid arbitrary enum creation. + * + * When creating your own constructor for a parameterized enum, make sure to declare it as protected, so that + * the static methods are able to construct it. Avoid making it public, as that would allow creation of + * non-singleton enum instances. + */ + private function __construct() + { + } + + /** + * Magic getter which forwards all calls to {@see self::valueOf()}. + * + * @return static + */ + final public static function __callStatic(string $name, array $arguments) : self + { + return static::valueOf($name); + } + + /** + * Returns an enum with the specified name. + * + * The name must match exactly an identifier used to declare an enum in this type (extraneous whitespace characters + * are not permitted). + * + * @return static + * @throws IllegalArgumentException if the enum has no constant with the specified name + */ + final public static function valueOf(string $name) : self + { + if (isset(self::$values[static::class][$name])) { + return self::$values[static::class][$name]; + } + + $constants = self::constants(); + + if (array_key_exists($name, $constants)) { + return self::createValue($name, $constants[$name][0], $constants[$name][1]); + } + + throw new IllegalArgumentException(sprintf('No enum constant %s::%s', static::class, $name)); + } + + /** + * @return static + */ + private static function createValue(string $name, int $ordinal, array $arguments) : self + { + $instance = new static(...$arguments); + $instance->name = $name; + $instance->ordinal = $ordinal; + self::$values[static::class][$name] = $instance; + return $instance; + } + + /** + * Obtains all possible types defined by this enum. + * + * @return static[] + */ + final public static function values() : array + { + if (isset(self::$allValuesLoaded[static::class])) { + return self::$values[static::class]; + } + + if (! isset(self::$values[static::class])) { + self::$values[static::class] = []; + } + + foreach (self::constants() as $name => $constant) { + if (array_key_exists($name, self::$values[static::class])) { + continue; + } + + static::createValue($name, $constant[0], $constant[1]); + } + + uasort(self::$values[static::class], function (self $a, self $b) { + return $a->ordinal() <=> $b->ordinal(); + }); + + self::$allValuesLoaded[static::class] = true; + return self::$values[static::class]; + } + + private static function constants() : array + { + if (isset(self::$constants[static::class])) { + return self::$constants[static::class]; + } + + self::$constants[static::class] = []; + $reflectionClass = new ReflectionClass(static::class); + $ordinal = -1; + + foreach ($reflectionClass->getReflectionConstants() as $reflectionConstant) { + if (! $reflectionConstant->isProtected()) { + continue; + } + + $value = $reflectionConstant->getValue(); + + self::$constants[static::class][$reflectionConstant->name] = [ + ++$ordinal, + is_array($value) ? $value : [] + ]; + } + + return self::$constants[static::class]; + } + + /** + * Returns the name of this enum constant, exactly as declared in its enum declaration. + * + * Most programmers should use the {@see self::__toString()} method in preference to this one, as the toString + * method may return a more user-friendly name. This method is designed primarily for use in specialized situations + * where correctness depends on getting the exact name, which will not vary from release to release. + */ + final public function name() : string + { + return $this->name; + } + + /** + * Returns the ordinal of this enumeration constant (its position in its enum declaration, where the initial + * constant is assigned an ordinal of zero). + * + * Most programmers will have no use for this method. It is designed for use by sophisticated enum-based data + * structures. + */ + final public function ordinal() : int + { + return $this->ordinal; + } + + /** + * Compares this enum with the specified object for order. + * + * Returns negative integer, zero or positive integer as this object is less than, equal to or greater than the + * specified object. + * + * Enums are only comparable to other enums of the same type. The natural order implemented by this method is the + * order in which the constants are declared. + * + * @throws MismatchException if the passed enum is not of the same type + */ + final public function compareTo(self $other) : int + { + if (! $other instanceof static) { + throw new MismatchException(sprintf( + 'The passed enum %s is not of the same type as %s', + get_class($other), + static::class + )); + } + + return $this->ordinal - $other->ordinal; + } + + /** + * Forbid cloning enums. + * + * @throws CloneNotSupportedException + */ + final public function __clone() + { + throw new CloneNotSupportedException(); + } + + /** + * Forbid serializing enums. + * + * @throws SerializeNotSupportedException + */ + final public function __sleep() : array + { + throw new SerializeNotSupportedException(); + } + + /** + * Forbid serializing enums. + * + * @throws SerializeNotSupportedException + */ + final public function __serialize() : array + { + throw new SerializeNotSupportedException(); + } + + /** + * Forbid unserializing enums. + * + * @throws UnserializeNotSupportedException + */ + final public function __wakeup() : void + { + throw new UnserializeNotSupportedException(); + } + + /** + * Forbid unserializing enums. + * + * @throws UnserializeNotSupportedException + */ + final public function __unserialize($arg) : void + { + throw new UnserializeNotSupportedException(); + } + + /** + * Turns the enum into a string representation. + * + * You may override this method to give a more user-friendly version. + */ + public function __toString() : string + { + return $this->name; + } +} diff --git a/vendor/dasprid/enum/src/EnumMap.php b/vendor/dasprid/enum/src/EnumMap.php new file mode 100644 index 0000000..95b8856 --- /dev/null +++ b/vendor/dasprid/enum/src/EnumMap.php @@ -0,0 +1,385 @@ + + */ + private $keyUniverse; + + /** + * Array representation of this map. The ith element is the value to which universe[i] is currently mapped, or null + * if it isn't mapped to anything, or NullValue if it's mapped to null. + * + * @var array + */ + private $values; + + /** + * @var int + */ + private $size = 0; + + /** + * Creates a new enum map. + * + * @param string $keyType the type of the keys, must extend AbstractEnum + * @param string $valueType the type of the values + * @param bool $allowNullValues whether to allow null values + * @throws IllegalArgumentException when key type does not extend AbstractEnum + */ + public function __construct(string $keyType, string $valueType, bool $allowNullValues) + { + if (! is_subclass_of($keyType, AbstractEnum::class)) { + throw new IllegalArgumentException(sprintf( + 'Class %s does not extend %s', + $keyType, + AbstractEnum::class + )); + } + + $this->keyType = $keyType; + $this->valueType = $valueType; + $this->allowNullValues = $allowNullValues; + $this->keyUniverse = $keyType::values(); + $this->values = array_fill(0, count($this->keyUniverse), null); + } + + public function __serialize(): array + { + $values = []; + + foreach ($this->values as $ordinal => $value) { + if (null === $value) { + continue; + } + + $values[$ordinal] = $this->unmaskNull($value); + } + + return [ + 'keyType' => $this->keyType, + 'valueType' => $this->valueType, + 'allowNullValues' => $this->allowNullValues, + 'values' => $values, + ]; + } + + public function __unserialize(array $data): void + { + $this->unserialize(serialize($data)); + } + + /** + * Checks whether the map types match the supplied ones. + * + * You should call this method when an EnumMap is passed to you and you want to ensure that it's made up of the + * correct types. + * + * @throws ExpectationException when supplied key type mismatches local key type + * @throws ExpectationException when supplied value type mismatches local value type + * @throws ExpectationException when the supplied map allows null values, abut should not + */ + public function expect(string $keyType, string $valueType, bool $allowNullValues) : void + { + if ($keyType !== $this->keyType) { + throw new ExpectationException(sprintf( + 'Callee expected an EnumMap with key type %s, but got %s', + $keyType, + $this->keyType + )); + } + + if ($valueType !== $this->valueType) { + throw new ExpectationException(sprintf( + 'Callee expected an EnumMap with value type %s, but got %s', + $keyType, + $this->keyType + )); + } + + if ($allowNullValues !== $this->allowNullValues) { + throw new ExpectationException(sprintf( + 'Callee expected an EnumMap with nullable flag %s, but got %s', + ($allowNullValues ? 'true' : 'false'), + ($this->allowNullValues ? 'true' : 'false') + )); + } + } + + /** + * Returns the number of key-value mappings in this map. + */ + public function size() : int + { + return $this->size; + } + + /** + * Returns true if this map maps one or more keys to the specified value. + */ + public function containsValue($value) : bool + { + return in_array($this->maskNull($value), $this->values, true); + } + + /** + * Returns true if this map contains a mapping for the specified key. + */ + public function containsKey(AbstractEnum $key) : bool + { + $this->checkKeyType($key); + return null !== $this->values[$key->ordinal()]; + } + + /** + * Returns the value to which the specified key is mapped, or null if this map contains no mapping for the key. + * + * More formally, if this map contains a mapping from a key to a value, then this method returns the value; + * otherwise it returns null (there can be at most one such mapping). + * + * A return value of null does not necessarily indicate that the map contains no mapping for the key; it's also + * possible that hte map explicitly maps the key to null. The {@see self::containsKey()} operation may be used to + * distinguish these two cases. + * + * @return mixed + */ + public function get(AbstractEnum $key) + { + $this->checkKeyType($key); + return $this->unmaskNull($this->values[$key->ordinal()]); + } + + /** + * Associates the specified value with the specified key in this map. + * + * If the map previously contained a mapping for this key, the old value is replaced. + * + * @return mixed the previous value associated with the specified key, or null if there was no mapping for the key. + * (a null return can also indicate that the map previously associated null with the specified key.) + * @throws IllegalArgumentException when the passed values does not match the internal value type + */ + public function put(AbstractEnum $key, $value) + { + $this->checkKeyType($key); + + if (! $this->isValidValue($value)) { + throw new IllegalArgumentException(sprintf('Value is not of type %s', $this->valueType)); + } + + $index = $key->ordinal(); + $oldValue = $this->values[$index]; + $this->values[$index] = $this->maskNull($value); + + if (null === $oldValue) { + ++$this->size; + } + + return $this->unmaskNull($oldValue); + } + + /** + * Removes the mapping for this key frm this map if present. + * + * @return mixed the previous value associated with the specified key, or null if there was no mapping for the key. + * (a null return can also indicate that the map previously associated null with the specified key.) + */ + public function remove(AbstractEnum $key) + { + $this->checkKeyType($key); + + $index = $key->ordinal(); + $oldValue = $this->values[$index]; + $this->values[$index] = null; + + if (null !== $oldValue) { + --$this->size; + } + + return $this->unmaskNull($oldValue); + } + + /** + * Removes all mappings from this map. + */ + public function clear() : void + { + $this->values = array_fill(0, count($this->keyUniverse), null); + $this->size = 0; + } + + /** + * Compares the specified map with this map for quality. + * + * Returns true if the two maps represent the same mappings. + */ + public function equals(self $other) : bool + { + if ($this === $other) { + return true; + } + + if ($this->size !== $other->size) { + return false; + } + + return $this->values === $other->values; + } + + /** + * Returns the values contained in this map. + * + * The array will contain the values in the order their corresponding keys appear in the map, which is their natural + * order (the order in which the num constants are declared). + */ + public function values() : array + { + return array_values(array_map(function ($value) { + return $this->unmaskNull($value); + }, array_filter($this->values, function ($value) : bool { + return null !== $value; + }))); + } + + public function serialize() : string + { + return serialize($this->__serialize()); + } + + public function unserialize($serialized) : void + { + $data = unserialize($serialized); + $this->__construct($data['keyType'], $data['valueType'], $data['allowNullValues']); + + foreach ($this->keyUniverse as $key) { + if (array_key_exists($key->ordinal(), $data['values'])) { + $this->put($key, $data['values'][$key->ordinal()]); + } + } + } + + public function getIterator() : Traversable + { + foreach ($this->keyUniverse as $key) { + if (null === $this->values[$key->ordinal()]) { + continue; + } + + yield $key => $this->unmaskNull($this->values[$key->ordinal()]); + } + } + + private function maskNull($value) + { + if (null === $value) { + return NullValue::instance(); + } + + return $value; + } + + private function unmaskNull($value) + { + if ($value instanceof NullValue) { + return null; + } + + return $value; + } + + /** + * @throws IllegalArgumentException when the passed key does not match the internal key type + */ + private function checkKeyType(AbstractEnum $key) : void + { + if (get_class($key) !== $this->keyType) { + throw new IllegalArgumentException(sprintf( + 'Object of type %s is not the same type as %s', + get_class($key), + $this->keyType + )); + } + } + + private function isValidValue($value) : bool + { + if (null === $value) { + if ($this->allowNullValues) { + return true; + } + + return false; + } + + switch ($this->valueType) { + case 'mixed': + return true; + + case 'bool': + case 'boolean': + return is_bool($value); + + case 'int': + case 'integer': + return is_int($value); + + case 'float': + case 'double': + return is_float($value); + + case 'string': + return is_string($value); + + case 'object': + return is_object($value); + + case 'array': + return is_array($value); + } + + return $value instanceof $this->valueType; + } +} diff --git a/vendor/dasprid/enum/src/Exception/CloneNotSupportedException.php b/vendor/dasprid/enum/src/Exception/CloneNotSupportedException.php new file mode 100644 index 0000000..4b37dbe --- /dev/null +++ b/vendor/dasprid/enum/src/Exception/CloneNotSupportedException.php @@ -0,0 +1,10 @@ +build(); +``` + +## Usage: without using the builder + +```php +use Endroid\QrCode\Color\Color; +use Endroid\QrCode\Encoding\Encoding; +use Endroid\QrCode\ErrorCorrectionLevel; +use Endroid\QrCode\QrCode; +use Endroid\QrCode\Label\Label; +use Endroid\QrCode\Logo\Logo; +use Endroid\QrCode\RoundBlockSizeMode; +use Endroid\QrCode\Writer\PngWriter; +use Endroid\QrCode\Writer\ValidationException; + +$writer = new PngWriter(); + +// Create QR code +$qrCode = new QrCode( + data: 'Life is too short to be generating QR codes', + encoding: new Encoding('UTF-8'), + errorCorrectionLevel: ErrorCorrectionLevel::Low, + size: 300, + margin: 10, + roundBlockSizeMode: RoundBlockSizeMode::Margin, + foregroundColor: new Color(0, 0, 0), + backgroundColor: new Color(255, 255, 255) +); + +// Create generic logo +$logo = new Logo( + path: __DIR__.'/assets/bender.png', + resizeToWidth: 50, + punchoutBackground: true +); + +// Create generic label +$label = new Label( + text: 'Label', + textColor: new Color(255, 0, 0) +); + +$result = $writer->write($qrCode, $logo, $label); + +// Validate the result +$writer->validateResult($result, 'Life is too short to be generating QR codes'); +``` + +## Usage: working with results + +```php + +// Directly output the QR code +header('Content-Type: '.$result->getMimeType()); +echo $result->getString(); + +// Save it to a file +$result->saveToFile(__DIR__.'/qrcode.png'); + +// Generate a data URI to include image data inline (i.e. inside an tag) +$dataUri = $result->getDataUri(); +``` + +![QR Code](.github/example.png) + +### Writer options + +Some writers provide writer options. Each available writer option is can be +found as a constant prefixed with WRITER_OPTION_ in the writer class. + +* `PdfWriter` + * `unit`: unit of measurement (default: mm) + * `fpdf`: PDF to place the image in (default: new PDF) + * `x`: image offset (default: 0) + * `y`: image offset (default: 0) + * `link`: a URL or an identifier returned by `AddLink()`. +* `PngWriter` + * `compression_level`: compression level (0-9, default: -1 = zlib default) + * `number_of_colors`: number of colors (1-256, null for true color and transparency) +* `SvgWriter` + * `block_id`: id of the block element for external reference (default: block) + * `exclude_xml_declaration`: exclude XML declaration (default: false) + * `exclude_svg_width_and_height`: exclude width and height (default: false) + * `force_xlink_href`: forces xlink namespace in case of compatibility issues (default: false) + * `compact`: create using `path` element, otherwise use `defs` and `use` (default: true) +* `WebPWriter` + * `quality`: image quality (0-100, default: 80) + +You can provide any writer options like this. + +```php +use Endroid\QrCode\Writer\SvgWriter; + +$builder = new Builder( + writer: new SvgWriter(), + writerOptions: [ + SvgWriter::WRITER_OPTION_EXCLUDE_XML_DECLARATION => true + ] +); +``` + +### Encoding + +If you use a barcode scanner you can have some troubles while reading the +generated QR codes. Depending on the encoding you chose you will have an extra +amount of data corresponding to the ECI block. Some barcode scanner are not +programmed to interpret this block of information. To ensure a maximum +compatibility you can use the `ISO-8859-1` encoding that is the default +encoding used by barcode scanners (if your character set supports it, +i.e. no Chinese characters are present). + +### Round block size mode + +By default block sizes are rounded to guarantee sharp images and improve +readability. However some other rounding variants are available. + +* `margin (default)`: the size of the QR code is shrunk if necessary but the size + of the final image remains unchanged due to additional margin being added. +* `enlarge`: the size of the QR code and the final image are enlarged when + rounding differences occur. +* `shrink`: the size of the QR code and the final image are + shrunk when rounding differences occur. +* `none`: No rounding. This mode can be used when blocks don't need to be rounded + to pixels (for instance SVG). + +## Readability + +The readability of a QR code is primarily determined by the size, the input +length, the error correction level and any possible logo over the image so you +can tweak these parameters if you are looking for optimal results. You can also +check $qrCode->getRoundBlockSize() value to see if block dimensions are rounded +so that the image is more sharp and readable. Please note that rounding block +size can result in additional padding to compensate for the rounding difference. +And finally the encoding (default UTF-8 to support large character sets) can be +set to `ISO-8859-1` if possible to improve readability. + +## Validating the generated QR code + +If you need to be extra sure the QR code you generated is readable and contains +the exact data you requested you can enable the validation reader, which is +disabled by default. You can do this either via the builder or directly on any +writer that supports validation. See the examples above. + +Please note that validation affects performance so only use it in case of problems. + +## Symfony integration + +The [endroid/qr-code-bundle](https://github.com/endroid/qr-code-bundle) +integrates the QR code library in Symfony for an even better experience. + +* Configure your defaults (like image size, default writer etc.) +* Support for multiple configurations and injection via aliases +* Generate QR codes for defined configurations via URL like /qr-code//Hello +* Generate QR codes or URLs directly from Twig using dedicated functions + +Read the [bundle documentation](https://github.com/endroid/qr-code-bundle) +for more information. + +## Versioning + +Version numbers follow the MAJOR.MINOR.PATCH scheme. Backwards compatibility +breaking changes will be kept to a minimum but be aware that these can occur. +Lock your dependencies for production and test your code when upgrading. + +## License + +This bundle is under the MIT license. For the full copyright and license +information please view the LICENSE file that was distributed with this source code. diff --git a/vendor/endroid/qr-code/assets/open_sans.ttf b/vendor/endroid/qr-code/assets/open_sans.ttf new file mode 100644 index 0000000..db43334 Binary files /dev/null and b/vendor/endroid/qr-code/assets/open_sans.ttf differ diff --git a/vendor/endroid/qr-code/composer.json b/vendor/endroid/qr-code/composer.json new file mode 100644 index 0000000..03a54d6 --- /dev/null +++ b/vendor/endroid/qr-code/composer.json @@ -0,0 +1,54 @@ +{ + "name": "endroid/qr-code", + "description": "Endroid QR Code", + "keywords": ["endroid", "qrcode", "qr", "code", "php"], + "homepage": "https://github.com/endroid/qr-code", + "type": "library", + "license": "MIT", + "authors": [ + { + "name": "Jeroen van den Enden", + "email": "info@endroid.nl" + } + ], + "require": { + "php": "^8.2", + "bacon/bacon-qr-code": "^3.0" + }, + "require-dev": { + "ext-gd": "*", + "endroid/quality": "dev-main", + "khanamiryan/qrcode-detector-decoder": "^2.0.2", + "setasign/fpdf": "^1.8.2" + }, + "suggest": { + "ext-gd": "Enables you to write PNG images", + "khanamiryan/qrcode-detector-decoder": "Enables you to use the image validator", + "roave/security-advisories": "Makes sure package versions with known security issues are not installed", + "setasign/fpdf": "Enables you to use the PDF writer" + }, + "autoload": { + "psr-4": { + "Endroid\\QrCode\\": "src/" + } + }, + "autoload-dev": { + "psr-4": { + "Endroid\\QrCode\\Tests\\": "tests/" + } + }, + "config": { + "sort-packages": true, + "preferred-install": { + "endroid/*": "source" + }, + "allow-plugins": { + "endroid/installer": true + } + }, + "extra": { + "branch-alias": { + "dev-main": "6.x-dev" + } + } +} diff --git a/vendor/endroid/qr-code/src/Bacon/ErrorCorrectionLevelConverter.php b/vendor/endroid/qr-code/src/Bacon/ErrorCorrectionLevelConverter.php new file mode 100644 index 0000000..ae2be59 --- /dev/null +++ b/vendor/endroid/qr-code/src/Bacon/ErrorCorrectionLevelConverter.php @@ -0,0 +1,21 @@ + BaconErrorCorrectionLevel::valueOf('L'), + ErrorCorrectionLevel::Medium => BaconErrorCorrectionLevel::valueOf('M'), + ErrorCorrectionLevel::Quartile => BaconErrorCorrectionLevel::valueOf('Q'), + ErrorCorrectionLevel::High => BaconErrorCorrectionLevel::valueOf('H'), + }; + } +} diff --git a/vendor/endroid/qr-code/src/Bacon/MatrixFactory.php b/vendor/endroid/qr-code/src/Bacon/MatrixFactory.php new file mode 100644 index 0000000..1d6a9a2 --- /dev/null +++ b/vendor/endroid/qr-code/src/Bacon/MatrixFactory.php @@ -0,0 +1,32 @@ +getErrorCorrectionLevel()); + $baconMatrix = Encoder::encode($qrCode->getData(), $baconErrorCorrectionLevel, strval($qrCode->getEncoding()))->getMatrix(); + + $blockValues = []; + $columnCount = $baconMatrix->getWidth(); + $rowCount = $baconMatrix->getHeight(); + for ($rowIndex = 0; $rowIndex < $rowCount; ++$rowIndex) { + $blockValues[$rowIndex] = []; + for ($columnIndex = 0; $columnIndex < $columnCount; ++$columnIndex) { + $blockValues[$rowIndex][$columnIndex] = $baconMatrix->get($columnIndex, $rowIndex); + } + } + + return new Matrix($blockValues, $qrCode->getSize(), $qrCode->getMargin(), $qrCode->getRoundBlockSizeMode()); + } +} diff --git a/vendor/endroid/qr-code/src/Builder/Builder.php b/vendor/endroid/qr-code/src/Builder/Builder.php new file mode 100644 index 0000000..89c6441 --- /dev/null +++ b/vendor/endroid/qr-code/src/Builder/Builder.php @@ -0,0 +1,128 @@ + */ + private array $writerOptions = [], + private bool $validateResult = false, + // QrCode options + private string $data = '', + private EncodingInterface $encoding = new Encoding('UTF-8'), + private ErrorCorrectionLevel $errorCorrectionLevel = ErrorCorrectionLevel::Low, + private int $size = 300, + private int $margin = 10, + private RoundBlockSizeMode $roundBlockSizeMode = RoundBlockSizeMode::Margin, + private ColorInterface $foregroundColor = new Color(0, 0, 0), + private ColorInterface $backgroundColor = new Color(255, 255, 255), + // Label options + private string $labelText = '', + private FontInterface $labelFont = new Font(__DIR__.'/../../assets/open_sans.ttf', 16), + private LabelAlignment $labelAlignment = LabelAlignment::Center, + private MarginInterface $labelMargin = new Margin(0, 10, 10, 10), + private ColorInterface $labelTextColor = new Color(0, 0, 0), + // Logo options + private string $logoPath = '', + private ?int $logoResizeToWidth = null, + private ?int $logoResizeToHeight = null, + private bool $logoPunchoutBackground = false, + ) { + } + + /** @param array|null $writerOptions */ + public function build( + ?WriterInterface $writer = null, + ?array $writerOptions = null, + ?bool $validateResult = null, + // QrCode options + ?string $data = null, + ?EncodingInterface $encoding = null, + ?ErrorCorrectionLevel $errorCorrectionLevel = null, + ?int $size = null, + ?int $margin = null, + ?RoundBlockSizeMode $roundBlockSizeMode = null, + ?ColorInterface $foregroundColor = null, + ?ColorInterface $backgroundColor = null, + // Label options + ?string $labelText = null, + ?FontInterface $labelFont = null, + ?LabelAlignment $labelAlignment = null, + ?MarginInterface $labelMargin = null, + ?ColorInterface $labelTextColor = null, + // Logo options + ?string $logoPath = null, + ?int $logoResizeToWidth = null, + ?int $logoResizeToHeight = null, + ?bool $logoPunchoutBackground = null, + ): ResultInterface { + if ($this->validateResult && !$this->writer instanceof ValidatingWriterInterface) { + throw ValidationException::createForUnsupportedWriter(get_class($this->writer)); + } + + $writer = $writer ?? $this->writer; + $writerOptions = $writerOptions ?? $this->writerOptions; + $validateResult = $validateResult ?? $this->validateResult; + + $createLabel = $this->labelText || $labelText; + $createLogo = $this->logoPath || $logoPath; + + $qrCode = new QrCode( + data: $data ?? $this->data, + encoding: $encoding ?? $this->encoding, + errorCorrectionLevel: $errorCorrectionLevel ?? $this->errorCorrectionLevel, + size: $size ?? $this->size, + margin: $margin ?? $this->margin, + roundBlockSizeMode: $roundBlockSizeMode ?? $this->roundBlockSizeMode, + foregroundColor: $foregroundColor ?? $this->foregroundColor, + backgroundColor: $backgroundColor ?? $this->backgroundColor + ); + + $logo = $createLogo ? new Logo( + path: $logoPath ?? $this->logoPath, + resizeToWidth: $logoResizeToWidth ?? $this->logoResizeToWidth, + resizeToHeight: $logoResizeToHeight ?? $this->logoResizeToHeight, + punchoutBackground: $logoPunchoutBackground ?? $this->logoPunchoutBackground + ) : null; + + $label = $createLabel ? new Label( + text: $labelText ?? $this->labelText, + font: $labelFont ?? $this->labelFont, + alignment: $labelAlignment ?? $this->labelAlignment, + margin: $labelMargin ?? $this->labelMargin, + textColor: $labelTextColor ?? $this->labelTextColor + ) : null; + + $result = $writer->write($qrCode, $logo, $label, $writerOptions); + + if ($validateResult && $writer instanceof ValidatingWriterInterface) { + $writer->validateResult($result, $qrCode->getData()); + } + + return $result; + } +} diff --git a/vendor/endroid/qr-code/src/Builder/BuilderInterface.php b/vendor/endroid/qr-code/src/Builder/BuilderInterface.php new file mode 100644 index 0000000..9a14dc0 --- /dev/null +++ b/vendor/endroid/qr-code/src/Builder/BuilderInterface.php @@ -0,0 +1,45 @@ +|null $writerOptions */ + public function build( + ?WriterInterface $writer = null, + ?array $writerOptions = null, + ?bool $validateResult = null, + // QrCode options + ?string $data = null, + ?EncodingInterface $encoding = null, + ?ErrorCorrectionLevel $errorCorrectionLevel = null, + ?int $size = null, + ?int $margin = null, + ?RoundBlockSizeMode $roundBlockSizeMode = null, + ?ColorInterface $foregroundColor = null, + ?ColorInterface $backgroundColor = null, + // Label options + ?string $labelText = null, + ?FontInterface $labelFont = null, + ?LabelAlignment $labelAlignment = null, + ?MarginInterface $labelMargin = null, + ?ColorInterface $labelTextColor = null, + // Logo options + ?string $logoPath = null, + ?int $logoResizeToWidth = null, + ?int $logoResizeToHeight = null, + ?bool $logoPunchoutBackground = null, + ): ResultInterface; +} diff --git a/vendor/endroid/qr-code/src/Builder/BuilderRegistry.php b/vendor/endroid/qr-code/src/Builder/BuilderRegistry.php new file mode 100644 index 0000000..13b9c96 --- /dev/null +++ b/vendor/endroid/qr-code/src/Builder/BuilderRegistry.php @@ -0,0 +1,25 @@ + */ + private array $builders = []; + + public function set(string $name, BuilderInterface $builder): void + { + $this->builders[$name] = $builder; + } + + public function get(string $name): BuilderInterface + { + if (!isset($this->builders[$name])) { + throw new \Exception(sprintf('Builder with name "%s" not available from registry', $name)); + } + + return $this->builders[$name]; + } +} diff --git a/vendor/endroid/qr-code/src/Builder/BuilderRegistryInterface.php b/vendor/endroid/qr-code/src/Builder/BuilderRegistryInterface.php new file mode 100644 index 0000000..0d9fb37 --- /dev/null +++ b/vendor/endroid/qr-code/src/Builder/BuilderRegistryInterface.php @@ -0,0 +1,12 @@ +red; + } + + public function getGreen(): int + { + return $this->green; + } + + public function getBlue(): int + { + return $this->blue; + } + + public function getAlpha(): int + { + return $this->alpha; + } + + public function getOpacity(): float + { + return 1 - $this->alpha / 127; + } + + public function getHex(): string + { + return sprintf('#%02x%02x%02x', $this->red, $this->green, $this->blue); + } + + public function toArray(): array + { + return [ + 'red' => $this->red, + 'green' => $this->green, + 'blue' => $this->blue, + 'alpha' => $this->alpha, + ]; + } +} diff --git a/vendor/endroid/qr-code/src/Color/ColorInterface.php b/vendor/endroid/qr-code/src/Color/ColorInterface.php new file mode 100644 index 0000000..398be26 --- /dev/null +++ b/vendor/endroid/qr-code/src/Color/ColorInterface.php @@ -0,0 +1,23 @@ + */ + public function toArray(): array; +} diff --git a/vendor/endroid/qr-code/src/Encoding/Encoding.php b/vendor/endroid/qr-code/src/Encoding/Encoding.php new file mode 100644 index 0000000..d6da27b --- /dev/null +++ b/vendor/endroid/qr-code/src/Encoding/Encoding.php @@ -0,0 +1,27 @@ +value; + } +} diff --git a/vendor/endroid/qr-code/src/Encoding/EncodingInterface.php b/vendor/endroid/qr-code/src/Encoding/EncodingInterface.php new file mode 100644 index 0000000..17748a4 --- /dev/null +++ b/vendor/endroid/qr-code/src/Encoding/EncodingInterface.php @@ -0,0 +1,10 @@ +getText(), "\n")) { + throw new \Exception('Label does not support line breaks'); + } + + if (!function_exists('imagettfbbox')) { + throw new \Exception('Function "imagettfbbox" does not exist: check your FreeType installation'); + } + + $labelBox = imagettfbbox($label->getFont()->getSize(), 0, $label->getFont()->getPath(), $label->getText()); + + if (!is_array($labelBox)) { + throw new \Exception('Unable to generate label image box: check your FreeType installation'); + } + + return new self( + intval($labelBox[2] - $labelBox[0]), + intval($labelBox[0] - $labelBox[7]) + ); + } + + public function getWidth(): int + { + return $this->width; + } + + public function getHeight(): int + { + return $this->height; + } +} diff --git a/vendor/endroid/qr-code/src/ImageData/LogoImageData.php b/vendor/endroid/qr-code/src/ImageData/LogoImageData.php new file mode 100644 index 0000000..2e3358e --- /dev/null +++ b/vendor/endroid/qr-code/src/ImageData/LogoImageData.php @@ -0,0 +1,159 @@ +getPath()); + + if (!is_string($data)) { + $errorDetails = error_get_last()['message'] ?? 'invalid data'; + throw new \Exception(sprintf('Could not read logo image data from path "%s": %s', $logo->getPath(), $errorDetails)); + } + + if (false !== filter_var($logo->getPath(), FILTER_VALIDATE_URL)) { + $mimeType = self::detectMimeTypeFromUrl($logo->getPath()); + } else { + $mimeType = self::detectMimeTypeFromPath($logo->getPath()); + } + + $width = $logo->getResizeToWidth(); + $height = $logo->getResizeToHeight(); + + if ('image/svg+xml' === $mimeType) { + if (null === $width || null === $height) { + throw new \Exception('SVG Logos require an explicitly set resize width and height'); + } + + return new self($data, null, $mimeType, $width, $height, $logo->getPunchoutBackground()); + } + + if (!function_exists('imagecreatefromstring')) { + throw new \Exception('Function "imagecreatefromstring" does not exist: check your GD installation'); + } + + error_clear_last(); + $image = @imagecreatefromstring($data); + + if (!$image) { + $errorDetails = error_get_last()['message'] ?? 'invalid data'; + throw new \Exception(sprintf('Unable to parse image data at path "%s": %s', $logo->getPath(), $errorDetails)); + } + + // No target width and height specified: use from original image + if (null !== $width && null !== $height) { + return new self($data, $image, $mimeType, $width, $height, $logo->getPunchoutBackground()); + } + + // Only target width specified: calculate height + if (null !== $width && null === $height) { + return new self($data, $image, $mimeType, $width, intval(imagesy($image) * $width / imagesx($image)), $logo->getPunchoutBackground()); + } + + // Only target height specified: calculate width + if (null === $width && null !== $height) { + return new self($data, $image, $mimeType, intval(imagesx($image) * $height / imagesy($image)), $height, $logo->getPunchoutBackground()); + } + + return new self($data, $image, $mimeType, imagesx($image), imagesy($image), $logo->getPunchoutBackground()); + } + + public function getData(): string + { + return $this->data; + } + + public function getImage(): \GdImage + { + if (!$this->image instanceof \GdImage) { + throw new \Exception('SVG Images have no image resource'); + } + + return $this->image; + } + + public function getMimeType(): string + { + return $this->mimeType; + } + + public function getWidth(): int + { + return $this->width; + } + + public function getHeight(): int + { + return $this->height; + } + + public function getPunchoutBackground(): bool + { + return $this->punchoutBackground; + } + + public function createDataUri(): string + { + return 'data:'.$this->mimeType.';base64,'.base64_encode($this->data); + } + + private static function detectMimeTypeFromUrl(string $url): string + { + $headers = get_headers($url, true); + + if (!is_array($headers)) { + throw new \Exception(sprintf('Could not retrieve headers to determine content type for logo URL "%s"', $url)); + } + + $headers = array_combine(array_map('strtolower', array_keys($headers)), $headers); + + if (!isset($headers['content-type'])) { + throw new \Exception(sprintf('Content type could not be determined for logo URL "%s"', $url)); + } + + return is_array($headers['content-type']) ? $headers['content-type'][1] : $headers['content-type']; + } + + private static function detectMimeTypeFromPath(string $path): string + { + if (!function_exists('mime_content_type')) { + throw new \Exception('You need the ext-fileinfo extension to determine logo mime type'); + } + + error_clear_last(); + $mimeType = @mime_content_type($path); + + if (!is_string($mimeType)) { + $errorDetails = error_get_last()['message'] ?? 'invalid data'; + throw new \Exception(sprintf('Could not determine mime type: %s', $errorDetails)); + } + + if (!preg_match('#^image/#', $mimeType)) { + throw new \Exception('Logo path is not an image'); + } + + // Passing mime type image/svg results in invisible images + if ('image/svg' === $mimeType) { + return 'image/svg+xml'; + } + + return $mimeType; + } +} diff --git a/vendor/endroid/qr-code/src/Label/Font/Font.php b/vendor/endroid/qr-code/src/Label/Font/Font.php new file mode 100644 index 0000000..e796c55 --- /dev/null +++ b/vendor/endroid/qr-code/src/Label/Font/Font.php @@ -0,0 +1,32 @@ +assertValidPath($path); + } + + private function assertValidPath(string $path): void + { + if (!file_exists($path)) { + throw new \Exception(sprintf('Invalid font path "%s"', $path)); + } + } + + public function getPath(): string + { + return $this->path; + } + + public function getSize(): int + { + return $this->size; + } +} diff --git a/vendor/endroid/qr-code/src/Label/Font/FontInterface.php b/vendor/endroid/qr-code/src/Label/Font/FontInterface.php new file mode 100644 index 0000000..1c0de9a --- /dev/null +++ b/vendor/endroid/qr-code/src/Label/Font/FontInterface.php @@ -0,0 +1,12 @@ +size; + } +} diff --git a/vendor/endroid/qr-code/src/Label/Label.php b/vendor/endroid/qr-code/src/Label/Label.php new file mode 100644 index 0000000..d7a7aba --- /dev/null +++ b/vendor/endroid/qr-code/src/Label/Label.php @@ -0,0 +1,49 @@ +text; + } + + public function getFont(): FontInterface + { + return $this->font; + } + + public function getAlignment(): LabelAlignment + { + return $this->alignment; + } + + public function getMargin(): MarginInterface + { + return $this->margin; + } + + public function getTextColor(): ColorInterface + { + return $this->textColor; + } +} diff --git a/vendor/endroid/qr-code/src/Label/LabelAlignment.php b/vendor/endroid/qr-code/src/Label/LabelAlignment.php new file mode 100644 index 0000000..b609fe4 --- /dev/null +++ b/vendor/endroid/qr-code/src/Label/LabelAlignment.php @@ -0,0 +1,12 @@ +top; + } + + public function getRight(): int + { + return $this->right; + } + + public function getBottom(): int + { + return $this->bottom; + } + + public function getLeft(): int + { + return $this->left; + } + + /** @return array */ + public function toArray(): array + { + return [ + 'top' => $this->top, + 'right' => $this->right, + 'bottom' => $this->bottom, + 'left' => $this->left, + ]; + } +} diff --git a/vendor/endroid/qr-code/src/Label/Margin/MarginInterface.php b/vendor/endroid/qr-code/src/Label/Margin/MarginInterface.php new file mode 100644 index 0000000..bc428bd --- /dev/null +++ b/vendor/endroid/qr-code/src/Label/Margin/MarginInterface.php @@ -0,0 +1,19 @@ + */ + public function toArray(): array; +} diff --git a/vendor/endroid/qr-code/src/Logo/Logo.php b/vendor/endroid/qr-code/src/Logo/Logo.php new file mode 100644 index 0000000..bc4691f --- /dev/null +++ b/vendor/endroid/qr-code/src/Logo/Logo.php @@ -0,0 +1,36 @@ +path; + } + + public function getResizeToWidth(): ?int + { + return $this->resizeToWidth; + } + + public function getResizeToHeight(): ?int + { + return $this->resizeToHeight; + } + + public function getPunchoutBackground(): bool + { + return $this->punchoutBackground; + } +} diff --git a/vendor/endroid/qr-code/src/Logo/LogoInterface.php b/vendor/endroid/qr-code/src/Logo/LogoInterface.php new file mode 100644 index 0000000..13d940c --- /dev/null +++ b/vendor/endroid/qr-code/src/Logo/LogoInterface.php @@ -0,0 +1,16 @@ +> $blockValues */ + public function __construct( + private array $blockValues, + int $size, + int $margin, + RoundBlockSizeMode $roundBlockSizeMode, + ) { + $blockSize = $size / $this->getBlockCount(); + $innerSize = $size; + $outerSize = $size + 2 * $margin; + + switch ($roundBlockSizeMode) { + case RoundBlockSizeMode::Enlarge: + $blockSize = intval(ceil($blockSize)); + $innerSize = intval($blockSize * $this->getBlockCount()); + $outerSize = $innerSize + 2 * $margin; + break; + case RoundBlockSizeMode::Shrink: + $blockSize = intval(floor($blockSize)); + $innerSize = intval($blockSize * $this->getBlockCount()); + $outerSize = $innerSize + 2 * $margin; + break; + case RoundBlockSizeMode::Margin: + $blockSize = intval(floor($blockSize)); + $innerSize = intval($blockSize * $this->getBlockCount()); + break; + } + + if ($blockSize < 1) { + throw new BlockSizeTooSmallException('Too much data: increase image dimensions or lower error correction level'); + } + + $this->blockSize = $blockSize; + $this->innerSize = $innerSize; + $this->outerSize = $outerSize; + $this->marginLeft = intval(($this->outerSize - $this->innerSize) / 2); + $this->marginRight = $this->outerSize - $this->innerSize - $this->marginLeft; + } + + public function getBlockValue(int $rowIndex, int $columnIndex): int + { + return $this->blockValues[$rowIndex][$columnIndex]; + } + + public function getBlockCount(): int + { + return count($this->blockValues[0]); + } + + public function getBlockSize(): float + { + return $this->blockSize; + } + + public function getInnerSize(): int + { + return $this->innerSize; + } + + public function getOuterSize(): int + { + return $this->outerSize; + } + + public function getMarginLeft(): int + { + return $this->marginLeft; + } + + public function getMarginRight(): int + { + return $this->marginRight; + } +} diff --git a/vendor/endroid/qr-code/src/Matrix/MatrixFactoryInterface.php b/vendor/endroid/qr-code/src/Matrix/MatrixFactoryInterface.php new file mode 100644 index 0000000..be501f1 --- /dev/null +++ b/vendor/endroid/qr-code/src/Matrix/MatrixFactoryInterface.php @@ -0,0 +1,12 @@ +data; + } + + public function getEncoding(): EncodingInterface + { + return $this->encoding; + } + + public function getErrorCorrectionLevel(): ErrorCorrectionLevel + { + return $this->errorCorrectionLevel; + } + + public function getSize(): int + { + return $this->size; + } + + public function getMargin(): int + { + return $this->margin; + } + + public function getRoundBlockSizeMode(): RoundBlockSizeMode + { + return $this->roundBlockSizeMode; + } + + public function getForegroundColor(): ColorInterface + { + return $this->foregroundColor; + } + + public function getBackgroundColor(): ColorInterface + { + return $this->backgroundColor; + } +} diff --git a/vendor/endroid/qr-code/src/QrCodeInterface.php b/vendor/endroid/qr-code/src/QrCodeInterface.php new file mode 100644 index 0000000..1a75726 --- /dev/null +++ b/vendor/endroid/qr-code/src/QrCodeInterface.php @@ -0,0 +1,27 @@ +create($qrCode); + } + + public function write(QrCodeInterface $qrCode, ?LogoInterface $logo = null, ?LabelInterface $label = null, array $options = []): ResultInterface + { + if (!extension_loaded('gd')) { + throw new \Exception('Unable to generate image: please check if the GD extension is enabled and configured correctly'); + } + + $matrix = $this->getMatrix($qrCode); + + $baseBlockSize = RoundBlockSizeMode::None === $qrCode->getRoundBlockSizeMode() ? 10 : intval($matrix->getBlockSize()); + $baseImage = imagecreatetruecolor($matrix->getBlockCount() * $baseBlockSize, $matrix->getBlockCount() * $baseBlockSize); + + if (!$baseImage) { + throw new \Exception('Unable to generate image: please check if the GD extension is enabled and configured correctly'); + } + + /** @var int $foregroundColor */ + $foregroundColor = imagecolorallocatealpha( + $baseImage, + $qrCode->getForegroundColor()->getRed(), + $qrCode->getForegroundColor()->getGreen(), + $qrCode->getForegroundColor()->getBlue(), + $qrCode->getForegroundColor()->getAlpha() + ); + + /** @var int $transparentColor */ + $transparentColor = imagecolorallocatealpha($baseImage, 255, 255, 255, 127); + + imagefill($baseImage, 0, 0, $transparentColor); + + for ($rowIndex = 0; $rowIndex < $matrix->getBlockCount(); ++$rowIndex) { + for ($columnIndex = 0; $columnIndex < $matrix->getBlockCount(); ++$columnIndex) { + if (1 === $matrix->getBlockValue($rowIndex, $columnIndex)) { + imagefilledrectangle( + $baseImage, + $columnIndex * $baseBlockSize, + $rowIndex * $baseBlockSize, + ($columnIndex + 1) * $baseBlockSize - 1, + ($rowIndex + 1) * $baseBlockSize - 1, + $foregroundColor + ); + } + } + } + + $targetWidth = $matrix->getOuterSize(); + $targetHeight = $matrix->getOuterSize(); + + if ($label instanceof LabelInterface) { + $labelImageData = LabelImageData::createForLabel($label); + $targetHeight += $labelImageData->getHeight() + $label->getMargin()->getTop() + $label->getMargin()->getBottom(); + } + + $targetImage = imagecreatetruecolor($targetWidth, $targetHeight); + + if (!$targetImage) { + throw new \Exception('Unable to generate image: please check if the GD extension is enabled and configured correctly'); + } + + /** @var int $backgroundColor */ + $backgroundColor = imagecolorallocatealpha( + $targetImage, + $qrCode->getBackgroundColor()->getRed(), + $qrCode->getBackgroundColor()->getGreen(), + $qrCode->getBackgroundColor()->getBlue(), + $qrCode->getBackgroundColor()->getAlpha() + ); + + imagefill($targetImage, 0, 0, $backgroundColor); + + imagecopyresampled( + $targetImage, + $baseImage, + $matrix->getMarginLeft(), + $matrix->getMarginLeft(), + 0, + 0, + $matrix->getInnerSize(), + $matrix->getInnerSize(), + imagesx($baseImage), + imagesy($baseImage) + ); + + if ($qrCode->getBackgroundColor()->getAlpha() > 0) { + imagesavealpha($targetImage, true); + } + + $result = new GdResult($matrix, $targetImage); + + if ($logo instanceof LogoInterface) { + $result = $this->addLogo($logo, $result); + } + + if ($label instanceof LabelInterface) { + $result = $this->addLabel($label, $result); + } + + return $result; + } + + private function addLogo(LogoInterface $logo, GdResult $result): GdResult + { + $logoImageData = LogoImageData::createForLogo($logo); + + if ('image/svg+xml' === $logoImageData->getMimeType()) { + throw new \Exception('PNG Writer does not support SVG logo'); + } + + $targetImage = $result->getImage(); + $matrix = $result->getMatrix(); + + if ($logoImageData->getPunchoutBackground()) { + /** @var int $transparent */ + $transparent = imagecolorallocatealpha($targetImage, 255, 255, 255, 127); + imagealphablending($targetImage, false); + $xOffsetStart = intval($matrix->getOuterSize() / 2 - $logoImageData->getWidth() / 2); + $yOffsetStart = intval($matrix->getOuterSize() / 2 - $logoImageData->getHeight() / 2); + for ($xOffset = $xOffsetStart; $xOffset < $xOffsetStart + $logoImageData->getWidth(); ++$xOffset) { + for ($yOffset = $yOffsetStart; $yOffset < $yOffsetStart + $logoImageData->getHeight(); ++$yOffset) { + imagesetpixel($targetImage, $xOffset, $yOffset, $transparent); + } + } + } + + imagecopyresampled( + $targetImage, + $logoImageData->getImage(), + intval($matrix->getOuterSize() / 2 - $logoImageData->getWidth() / 2), + intval($matrix->getOuterSize() / 2 - $logoImageData->getHeight() / 2), + 0, + 0, + $logoImageData->getWidth(), + $logoImageData->getHeight(), + imagesx($logoImageData->getImage()), + imagesy($logoImageData->getImage()) + ); + + return new GdResult($matrix, $targetImage); + } + + private function addLabel(LabelInterface $label, GdResult $result): GdResult + { + $targetImage = $result->getImage(); + + $labelImageData = LabelImageData::createForLabel($label); + + /** @var int $textColor */ + $textColor = imagecolorallocatealpha( + $targetImage, + $label->getTextColor()->getRed(), + $label->getTextColor()->getGreen(), + $label->getTextColor()->getBlue(), + $label->getTextColor()->getAlpha() + ); + + $x = intval(imagesx($targetImage) / 2 - $labelImageData->getWidth() / 2); + $y = imagesy($targetImage) - $label->getMargin()->getBottom(); + + if (LabelAlignment::Left === $label->getAlignment()) { + $x = $label->getMargin()->getLeft(); + } elseif (LabelAlignment::Right === $label->getAlignment()) { + $x = imagesx($targetImage) - $labelImageData->getWidth() - $label->getMargin()->getRight(); + } + + imagettftext($targetImage, $label->getFont()->getSize(), 0, $x, $y, $textColor, $label->getFont()->getPath(), $label->getText()); + + return new GdResult($result->getMatrix(), $targetImage); + } + + public function validateResult(ResultInterface $result, string $expectedData): void + { + $string = $result->getString(); + + if (!class_exists(QrReader::class)) { + throw ValidationException::createForMissingPackage('khanamiryan/qrcode-detector-decoder'); + } + + $reader = new QrReader($string, QrReader::SOURCE_TYPE_BLOB); + if ($reader->text() !== $expectedData) { + throw ValidationException::createForInvalidData($expectedData, strval($reader->text())); + } + } +} diff --git a/vendor/endroid/qr-code/src/Writer/BinaryWriter.php b/vendor/endroid/qr-code/src/Writer/BinaryWriter.php new file mode 100644 index 0000000..8e0c7e8 --- /dev/null +++ b/vendor/endroid/qr-code/src/Writer/BinaryWriter.php @@ -0,0 +1,23 @@ +create($qrCode); + + return new BinaryResult($matrix); + } +} diff --git a/vendor/endroid/qr-code/src/Writer/ConsoleWriter.php b/vendor/endroid/qr-code/src/Writer/ConsoleWriter.php new file mode 100644 index 0000000..e3bb7c3 --- /dev/null +++ b/vendor/endroid/qr-code/src/Writer/ConsoleWriter.php @@ -0,0 +1,23 @@ +create($qrCode); + + return new ConsoleResult($matrix, $qrCode->getForegroundColor(), $qrCode->getBackgroundColor()); + } +} diff --git a/vendor/endroid/qr-code/src/Writer/DebugWriter.php b/vendor/endroid/qr-code/src/Writer/DebugWriter.php new file mode 100644 index 0000000..8910a80 --- /dev/null +++ b/vendor/endroid/qr-code/src/Writer/DebugWriter.php @@ -0,0 +1,32 @@ +create($qrCode); + + return new DebugResult($matrix, $qrCode, $logo, $label, $options); + } + + public function validateResult(ResultInterface $result, string $expectedData): void + { + if (!$result instanceof DebugResult) { + throw new \Exception('Unable to write logo: instance of DebugResult expected'); + } + + $result->setValidateResult(true); + } +} diff --git a/vendor/endroid/qr-code/src/Writer/EpsWriter.php b/vendor/endroid/qr-code/src/Writer/EpsWriter.php new file mode 100644 index 0000000..2f41967 --- /dev/null +++ b/vendor/endroid/qr-code/src/Writer/EpsWriter.php @@ -0,0 +1,44 @@ +create($qrCode); + + $lines = [ + '%!PS-Adobe-3.0 EPSF-3.0', + '%%BoundingBox: 0 0 '.$matrix->getOuterSize().' '.$matrix->getOuterSize(), + '/F { rectfill } def', + number_format($qrCode->getBackgroundColor()->getRed() / 100, 2, '.', ',').' '.number_format($qrCode->getBackgroundColor()->getGreen() / 100, 2, '.', ',').' '.number_format($qrCode->getBackgroundColor()->getBlue() / 100, 2, '.', ',').' setrgbcolor', + '0 0 '.$matrix->getOuterSize().' '.$matrix->getOuterSize().' F', + number_format($qrCode->getForegroundColor()->getRed() / 100, 2, '.', ',').' '.number_format($qrCode->getForegroundColor()->getGreen() / 100, 2, '.', ',').' '.number_format($qrCode->getForegroundColor()->getBlue() / 100, 2, '.', ',').' setrgbcolor', + ]; + + for ($rowIndex = 0; $rowIndex < $matrix->getBlockCount(); ++$rowIndex) { + for ($columnIndex = 0; $columnIndex < $matrix->getBlockCount(); ++$columnIndex) { + if (1 === $matrix->getBlockValue($matrix->getBlockCount() - 1 - $rowIndex, $columnIndex)) { + $x = $matrix->getMarginLeft() + $matrix->getBlockSize() * $columnIndex; + $y = $matrix->getMarginLeft() + $matrix->getBlockSize() * $rowIndex; + $lines[] = number_format($x, self::DECIMAL_PRECISION, '.', '').' '.number_format($y, self::DECIMAL_PRECISION, '.', '').' '.number_format($matrix->getBlockSize(), self::DECIMAL_PRECISION, '.', '').' '.number_format($matrix->getBlockSize(), self::DECIMAL_PRECISION, '.', '').' F'; + } + } + } + + return new EpsResult($matrix, $lines); + } +} diff --git a/vendor/endroid/qr-code/src/Writer/GifWriter.php b/vendor/endroid/qr-code/src/Writer/GifWriter.php new file mode 100644 index 0000000..031e02c --- /dev/null +++ b/vendor/endroid/qr-code/src/Writer/GifWriter.php @@ -0,0 +1,23 @@ +getMatrix(), $gdResult->getImage()); + } +} diff --git a/vendor/endroid/qr-code/src/Writer/PdfWriter.php b/vendor/endroid/qr-code/src/Writer/PdfWriter.php new file mode 100644 index 0000000..3f0cd73 --- /dev/null +++ b/vendor/endroid/qr-code/src/Writer/PdfWriter.php @@ -0,0 +1,139 @@ +create($qrCode); + + $unit = 'mm'; + if (isset($options[self::WRITER_OPTION_UNIT])) { + $unit = $options[self::WRITER_OPTION_UNIT]; + } + + $allowedUnits = ['mm', 'pt', 'cm', 'in']; + if (!in_array($unit, $allowedUnits)) { + throw new \Exception(sprintf('PDF Measure unit should be one of [%s]', implode(', ', $allowedUnits))); + } + + $labelSpace = 0; + if ($label instanceof LabelInterface) { + $labelSpace = 30; + } + + if (!class_exists(\FPDF::class)) { + throw new \Exception('Unable to find FPDF: check your installation'); + } + + $foregroundColor = $qrCode->getForegroundColor(); + if ($foregroundColor->getAlpha() > 0) { + throw new \Exception('PDF Writer does not support alpha channels'); + } + $backgroundColor = $qrCode->getBackgroundColor(); + if ($backgroundColor->getAlpha() > 0) { + throw new \Exception('PDF Writer does not support alpha channels'); + } + + if (isset($options[self::WRITER_OPTION_PDF])) { + $fpdf = $options[self::WRITER_OPTION_PDF]; + if (!$fpdf instanceof \FPDF) { + throw new \Exception('pdf option must be an instance of FPDF'); + } + } else { + // @todo Check how to add label height later + $fpdf = new \FPDF('P', $unit, [$matrix->getOuterSize(), $matrix->getOuterSize() + $labelSpace]); + $fpdf->AddPage(); + } + + $x = 0; + if (isset($options[self::WRITER_OPTION_X])) { + $x = $options[self::WRITER_OPTION_X]; + } + $y = 0; + if (isset($options[self::WRITER_OPTION_Y])) { + $y = $options[self::WRITER_OPTION_Y]; + } + + $fpdf->SetFillColor($backgroundColor->getRed(), $backgroundColor->getGreen(), $backgroundColor->getBlue()); + $fpdf->Rect($x, $y, $matrix->getOuterSize(), $matrix->getOuterSize(), 'F'); + $fpdf->SetFillColor($foregroundColor->getRed(), $foregroundColor->getGreen(), $foregroundColor->getBlue()); + + for ($rowIndex = 0; $rowIndex < $matrix->getBlockCount(); ++$rowIndex) { + for ($columnIndex = 0; $columnIndex < $matrix->getBlockCount(); ++$columnIndex) { + if (1 === $matrix->getBlockValue($rowIndex, $columnIndex)) { + $fpdf->Rect( + $x + $matrix->getMarginLeft() + ($columnIndex * $matrix->getBlockSize()), + $y + $matrix->getMarginLeft() + ($rowIndex * $matrix->getBlockSize()), + $matrix->getBlockSize(), + $matrix->getBlockSize(), + 'F' + ); + } + } + } + + if ($logo instanceof LogoInterface) { + $this->addLogo($logo, $fpdf, $x, $y, $matrix->getOuterSize()); + } + + if ($label instanceof LabelInterface) { + $fpdf->SetXY($x, $y + $matrix->getOuterSize() + $labelSpace - 25); + $fpdf->SetFont('Helvetica', '', $label->getFont()->getSize()); + $fpdf->Cell($matrix->getOuterSize(), 0, $label->getText(), 0, 0, 'C'); + } + + if (isset($options[self::WRITER_OPTION_LINK])) { + $link = $options[self::WRITER_OPTION_LINK]; + $fpdf->Link($x, $y, $x + $matrix->getOuterSize(), $y + $matrix->getOuterSize(), $link); + } + + return new PdfResult($matrix, $fpdf); + } + + private function addLogo(LogoInterface $logo, \FPDF $fpdf, float $x, float $y, float $size): void + { + $logoPath = $logo->getPath(); + $logoHeight = $logo->getResizeToHeight(); + $logoWidth = $logo->getResizeToWidth(); + + if (null === $logoHeight || null === $logoWidth) { + $imageSize = \getimagesize($logoPath); + if (!$imageSize) { + throw new \Exception(sprintf('Unable to read image size for logo "%s"', $logoPath)); + } + [$logoSourceWidth, $logoSourceHeight] = $imageSize; + + if (null === $logoWidth) { + $logoWidth = (int) $logoSourceWidth; + } + + if (null === $logoHeight) { + $aspectRatio = $logoWidth / $logoSourceWidth; + $logoHeight = (int) ($logoSourceHeight * $aspectRatio); + } + } + + $logoX = $x + $size / 2 - $logoWidth / 2; + $logoY = $y + $size / 2 - $logoHeight / 2; + + $fpdf->Image($logoPath, $logoX, $logoY, $logoWidth, $logoHeight); + } +} diff --git a/vendor/endroid/qr-code/src/Writer/PngWriter.php b/vendor/endroid/qr-code/src/Writer/PngWriter.php new file mode 100644 index 0000000..2bfcd97 --- /dev/null +++ b/vendor/endroid/qr-code/src/Writer/PngWriter.php @@ -0,0 +1,43 @@ +getBackgroundColor()->getAlpha() > 0 || $qrCode->getForegroundColor()->getAlpha() > 0 => null, + $logo instanceof LogoInterface => null, + default => 16, + }; + } + + /** @var GdResult $gdResult */ + $gdResult = parent::write($qrCode, $logo, $label, $options); + + return new PngResult( + $gdResult->getMatrix(), + $gdResult->getImage(), + $options[self::WRITER_OPTION_COMPRESSION_LEVEL], + $options[self::WRITER_OPTION_NUMBER_OF_COLORS] + ); + } +} diff --git a/vendor/endroid/qr-code/src/Writer/Result/AbstractResult.php b/vendor/endroid/qr-code/src/Writer/Result/AbstractResult.php new file mode 100644 index 0000000..b6547d2 --- /dev/null +++ b/vendor/endroid/qr-code/src/Writer/Result/AbstractResult.php @@ -0,0 +1,31 @@ +matrix; + } + + public function getDataUri(): string + { + return 'data:'.$this->getMimeType().';base64,'.base64_encode($this->getString()); + } + + public function saveToFile(string $path): void + { + $string = $this->getString(); + file_put_contents($path, $string); + } +} diff --git a/vendor/endroid/qr-code/src/Writer/Result/BinaryResult.php b/vendor/endroid/qr-code/src/Writer/Result/BinaryResult.php new file mode 100644 index 0000000..386fb6a --- /dev/null +++ b/vendor/endroid/qr-code/src/Writer/Result/BinaryResult.php @@ -0,0 +1,35 @@ +getMatrix(); + + $binaryString = ''; + for ($rowIndex = 0; $rowIndex < $matrix->getBlockCount(); ++$rowIndex) { + for ($columnIndex = 0; $columnIndex < $matrix->getBlockCount(); ++$columnIndex) { + $binaryString .= $matrix->getBlockValue($rowIndex, $columnIndex); + } + $binaryString .= "\n"; + } + + return $binaryString; + } + + public function getMimeType(): string + { + return 'text/plain'; + } +} diff --git a/vendor/endroid/qr-code/src/Writer/Result/ConsoleResult.php b/vendor/endroid/qr-code/src/Writer/Result/ConsoleResult.php new file mode 100644 index 0000000..d3644db --- /dev/null +++ b/vendor/endroid/qr-code/src/Writer/Result/ConsoleResult.php @@ -0,0 +1,69 @@ + ' ', + 1 => "\xe2\x96\x80", + 2 => "\xe2\x96\x84", + 3 => "\xe2\x96\x88", + ]; + + private string $colorEscapeCode; + + public function __construct( + MatrixInterface $matrix, + ColorInterface $foreground, + ColorInterface $background, + ) { + parent::__construct($matrix); + + $this->colorEscapeCode = sprintf( + "\e[38;2;%d;%d;%dm\e[48;2;%d;%d;%dm", + $foreground->getRed(), + $foreground->getGreen(), + $foreground->getBlue(), + $background->getRed(), + $background->getGreen(), + $background->getBlue() + ); + } + + public function getMimeType(): string + { + return 'text/plain'; + } + + public function getString(): string + { + $matrix = $this->getMatrix(); + + $side = $matrix->getBlockCount(); + $marginLeft = $this->colorEscapeCode.self::TWO_BLOCKS[0].self::TWO_BLOCKS[0]; + $marginRight = self::TWO_BLOCKS[0].self::TWO_BLOCKS[0]."\e[0m".PHP_EOL; + $marginVertical = $marginLeft.str_repeat(self::TWO_BLOCKS[0], $side).$marginRight; + + $qrCodeString = $marginVertical; + for ($rowIndex = 0; $rowIndex < $side; $rowIndex += 2) { + $qrCodeString .= $marginLeft; + for ($columnIndex = 0; $columnIndex < $side; ++$columnIndex) { + $combined = $matrix->getBlockValue($rowIndex, $columnIndex); + if ($rowIndex + 1 < $side) { + $combined |= $matrix->getBlockValue($rowIndex + 1, $columnIndex) << 1; + } + $qrCodeString .= self::TWO_BLOCKS[$combined]; + } + $qrCodeString .= $marginRight; + } + $qrCodeString .= $marginVertical; + + return $qrCodeString; + } +} diff --git a/vendor/endroid/qr-code/src/Writer/Result/DebugResult.php b/vendor/endroid/qr-code/src/Writer/Result/DebugResult.php new file mode 100644 index 0000000..b632993 --- /dev/null +++ b/vendor/endroid/qr-code/src/Writer/Result/DebugResult.php @@ -0,0 +1,74 @@ + $options */ + private readonly array $options = [], + ) { + parent::__construct($matrix); + } + + public function setValidateResult(bool $validateResult): void + { + $this->validateResult = $validateResult; + } + + public function getString(): string + { + $debugLines = []; + + $debugLines[] = 'Data: '.$this->qrCode->getData(); + $debugLines[] = 'Encoding: '.$this->qrCode->getEncoding(); + $debugLines[] = 'Error Correction Level: '.get_class($this->qrCode->getErrorCorrectionLevel()); + $debugLines[] = 'Size: '.$this->qrCode->getSize(); + $debugLines[] = 'Margin: '.$this->qrCode->getMargin(); + $debugLines[] = 'Round block size mode: '.get_class($this->qrCode->getRoundBlockSizeMode()); + $debugLines[] = 'Foreground color: ['.implode(', ', $this->qrCode->getForegroundColor()->toArray()).']'; + $debugLines[] = 'Background color: ['.implode(', ', $this->qrCode->getBackgroundColor()->toArray()).']'; + + foreach ($this->options as $key => $value) { + $debugLines[] = 'Writer option: '.$key.': '.$value; + } + + if (isset($this->logo)) { + $debugLines[] = 'Logo path: '.$this->logo->getPath(); + $debugLines[] = 'Logo resize to width: '.$this->logo->getResizeToWidth(); + $debugLines[] = 'Logo resize to height: '.$this->logo->getResizeToHeight(); + $debugLines[] = 'Logo punchout background: '.($this->logo->getPunchoutBackground() ? 'true' : 'false'); + } + + if (isset($this->label)) { + $debugLines[] = 'Label text: '.$this->label->getText(); + $debugLines[] = 'Label font path: '.$this->label->getFont()->getPath(); + $debugLines[] = 'Label font size: '.$this->label->getFont()->getSize(); + $debugLines[] = 'Label alignment: '.get_class($this->label->getAlignment()); + $debugLines[] = 'Label margin: ['.implode(', ', $this->label->getMargin()->toArray()).']'; + $debugLines[] = 'Label text color: ['.implode(', ', $this->label->getTextColor()->toArray()).']'; + } + + $debugLines[] = 'Validate result: '.($this->validateResult ? 'true' : 'false'); + + return implode("\n", $debugLines); + } + + public function getMimeType(): string + { + return 'text/plain'; + } +} diff --git a/vendor/endroid/qr-code/src/Writer/Result/EpsResult.php b/vendor/endroid/qr-code/src/Writer/Result/EpsResult.php new file mode 100644 index 0000000..d801fd6 --- /dev/null +++ b/vendor/endroid/qr-code/src/Writer/Result/EpsResult.php @@ -0,0 +1,28 @@ + $lines */ + private readonly array $lines, + ) { + parent::__construct($matrix); + } + + public function getString(): string + { + return implode("\n", $this->lines); + } + + public function getMimeType(): string + { + return 'image/eps'; + } +} diff --git a/vendor/endroid/qr-code/src/Writer/Result/GdResult.php b/vendor/endroid/qr-code/src/Writer/Result/GdResult.php new file mode 100644 index 0000000..a58c3e4 --- /dev/null +++ b/vendor/endroid/qr-code/src/Writer/Result/GdResult.php @@ -0,0 +1,32 @@ +image; + } + + public function getString(): string + { + throw new \Exception('You can only use this method in a concrete implementation'); + } + + public function getMimeType(): string + { + throw new \Exception('You can only use this method in a concrete implementation'); + } +} diff --git a/vendor/endroid/qr-code/src/Writer/Result/GifResult.php b/vendor/endroid/qr-code/src/Writer/Result/GifResult.php new file mode 100644 index 0000000..84b2497 --- /dev/null +++ b/vendor/endroid/qr-code/src/Writer/Result/GifResult.php @@ -0,0 +1,21 @@ +image); + + return strval(ob_get_clean()); + } + + public function getMimeType(): string + { + return 'image/gif'; + } +} diff --git a/vendor/endroid/qr-code/src/Writer/Result/PdfResult.php b/vendor/endroid/qr-code/src/Writer/Result/PdfResult.php new file mode 100644 index 0000000..f7746a2 --- /dev/null +++ b/vendor/endroid/qr-code/src/Writer/Result/PdfResult.php @@ -0,0 +1,32 @@ +fpdf; + } + + public function getString(): string + { + return $this->fpdf->Output('S'); + } + + public function getMimeType(): string + { + return 'application/pdf'; + } +} diff --git a/vendor/endroid/qr-code/src/Writer/Result/PngResult.php b/vendor/endroid/qr-code/src/Writer/Result/PngResult.php new file mode 100644 index 0000000..8cdbc53 --- /dev/null +++ b/vendor/endroid/qr-code/src/Writer/Result/PngResult.php @@ -0,0 +1,35 @@ +numberOfColors) { + imagetruecolortopalette($this->image, false, $this->numberOfColors); + } + imagepng($this->image, quality: $this->quality); + + return strval(ob_get_clean()); + } + + public function getMimeType(): string + { + return 'image/png'; + } +} diff --git a/vendor/endroid/qr-code/src/Writer/Result/ResultInterface.php b/vendor/endroid/qr-code/src/Writer/Result/ResultInterface.php new file mode 100644 index 0000000..2cd387e --- /dev/null +++ b/vendor/endroid/qr-code/src/Writer/Result/ResultInterface.php @@ -0,0 +1,20 @@ +xml; + } + + public function getString(): string + { + $string = $this->xml->asXML(); + + if (!is_string($string)) { + throw new \Exception('Could not save SVG XML to string'); + } + + if ($this->excludeXmlDeclaration) { + $string = str_replace("\n", '', $string); + } + + return $string; + } + + public function getMimeType(): string + { + return 'image/svg+xml'; + } +} diff --git a/vendor/endroid/qr-code/src/Writer/Result/WebPResult.php b/vendor/endroid/qr-code/src/Writer/Result/WebPResult.php new file mode 100644 index 0000000..735f128 --- /dev/null +++ b/vendor/endroid/qr-code/src/Writer/Result/WebPResult.php @@ -0,0 +1,35 @@ +image, quality: $this->quality); + + return strval(ob_get_clean()); + } + + public function getMimeType(): string + { + return 'image/webp'; + } +} diff --git a/vendor/endroid/qr-code/src/Writer/SvgWriter.php b/vendor/endroid/qr-code/src/Writer/SvgWriter.php new file mode 100644 index 0000000..9001279 --- /dev/null +++ b/vendor/endroid/qr-code/src/Writer/SvgWriter.php @@ -0,0 +1,174 @@ +create($qrCode); + + $xml = new \SimpleXMLElement(''); + $xml->addAttribute('version', '1.1'); + if (!$options[self::WRITER_OPTION_EXCLUDE_SVG_WIDTH_AND_HEIGHT]) { + $xml->addAttribute('width', $matrix->getOuterSize().'px'); + $xml->addAttribute('height', $matrix->getOuterSize().'px'); + } + $xml->addAttribute('viewBox', '0 0 '.$matrix->getOuterSize().' '.$matrix->getOuterSize()); + + $background = $xml->addChild('rect'); + $background->addAttribute('x', '0'); + $background->addAttribute('y', '0'); + $background->addAttribute('width', strval($matrix->getOuterSize())); + $background->addAttribute('height', strval($matrix->getOuterSize())); + $background->addAttribute('fill', '#'.sprintf('%02x%02x%02x', $qrCode->getBackgroundColor()->getRed(), $qrCode->getBackgroundColor()->getGreen(), $qrCode->getBackgroundColor()->getBlue())); + $background->addAttribute('fill-opacity', strval($qrCode->getBackgroundColor()->getOpacity())); + + if ($options[self::WRITER_OPTION_COMPACT]) { + $this->writePath($xml, $qrCode, $matrix); + } else { + $this->writeBlockDefinitions($xml, $qrCode, $matrix, $options); + } + + $result = new SvgResult($matrix, $xml, boolval($options[self::WRITER_OPTION_EXCLUDE_XML_DECLARATION])); + + if ($logo instanceof LogoInterface) { + $this->addLogo($logo, $result, $options); + } + + return $result; + } + + private function writePath(\SimpleXMLElement $xml, QrCodeInterface $qrCode, MatrixInterface $matrix): void + { + $path = ''; + for ($rowIndex = 0; $rowIndex < $matrix->getBlockCount(); ++$rowIndex) { + $left = $matrix->getMarginLeft(); + for ($columnIndex = 0; $columnIndex < $matrix->getBlockCount(); ++$columnIndex) { + if (1 === $matrix->getBlockValue($rowIndex, $columnIndex)) { + // When we are at the first column or when the previous column was 0 set new left + if (0 === $columnIndex || 0 === $matrix->getBlockValue($rowIndex, $columnIndex - 1)) { + $left = $matrix->getMarginLeft() + $matrix->getBlockSize() * $columnIndex; + } + // When we are at the + if ($columnIndex === $matrix->getBlockCount() - 1 || 0 === $matrix->getBlockValue($rowIndex, $columnIndex + 1)) { + $top = $matrix->getMarginLeft() + $matrix->getBlockSize() * $rowIndex; + $bottom = $matrix->getMarginLeft() + $matrix->getBlockSize() * ($rowIndex + 1); + $right = $matrix->getMarginLeft() + $matrix->getBlockSize() * ($columnIndex + 1); + $path .= 'M'.$this->formatNumber($left).','.$this->formatNumber($top); + $path .= 'L'.$this->formatNumber($right).','.$this->formatNumber($top); + $path .= 'L'.$this->formatNumber($right).','.$this->formatNumber($bottom); + $path .= 'L'.$this->formatNumber($left).','.$this->formatNumber($bottom).'Z'; + } + } + } + } + + $pathDefinition = $xml->addChild('path'); + $pathDefinition->addAttribute('fill', '#'.sprintf('%02x%02x%02x', $qrCode->getForegroundColor()->getRed(), $qrCode->getForegroundColor()->getGreen(), $qrCode->getForegroundColor()->getBlue())); + $pathDefinition->addAttribute('fill-opacity', strval($qrCode->getForegroundColor()->getOpacity())); + $pathDefinition->addAttribute('d', $path); + } + + /** @param array $options */ + private function writeBlockDefinitions(\SimpleXMLElement $xml, QrCodeInterface $qrCode, MatrixInterface $matrix, array $options): void + { + $xml->addChild('defs'); + + $blockDefinition = $xml->defs->addChild('rect'); + $blockDefinition->addAttribute('id', strval($options[self::WRITER_OPTION_BLOCK_ID])); + $blockDefinition->addAttribute('width', $this->formatNumber($matrix->getBlockSize())); + $blockDefinition->addAttribute('height', $this->formatNumber($matrix->getBlockSize())); + $blockDefinition->addAttribute('fill', '#'.sprintf('%02x%02x%02x', $qrCode->getForegroundColor()->getRed(), $qrCode->getForegroundColor()->getGreen(), $qrCode->getForegroundColor()->getBlue())); + $blockDefinition->addAttribute('fill-opacity', strval($qrCode->getForegroundColor()->getOpacity())); + + for ($rowIndex = 0; $rowIndex < $matrix->getBlockCount(); ++$rowIndex) { + for ($columnIndex = 0; $columnIndex < $matrix->getBlockCount(); ++$columnIndex) { + if (1 === $matrix->getBlockValue($rowIndex, $columnIndex)) { + $block = $xml->addChild('use'); + $block->addAttribute('x', $this->formatNumber($matrix->getMarginLeft() + $matrix->getBlockSize() * $columnIndex)); + $block->addAttribute('y', $this->formatNumber($matrix->getMarginLeft() + $matrix->getBlockSize() * $rowIndex)); + $block->addAttribute('xlink:href', '#'.$options[self::WRITER_OPTION_BLOCK_ID], 'http://www.w3.org/1999/xlink'); + } + } + } + } + + /** @param array $options */ + private function addLogo(LogoInterface $logo, SvgResult $result, array $options): void + { + if ($logo->getPunchoutBackground()) { + throw new \Exception('The SVG writer does not support logo punchout background'); + } + + $logoImageData = LogoImageData::createForLogo($logo); + + if (!isset($options[self::WRITER_OPTION_FORCE_XLINK_HREF])) { + $options[self::WRITER_OPTION_FORCE_XLINK_HREF] = false; + } + + $xml = $result->getXml(); + + /** @var \SimpleXMLElement $xmlAttributes */ + $xmlAttributes = $xml->attributes(); + + $x = intval($xmlAttributes->width) / 2 - $logoImageData->getWidth() / 2; + $y = intval($xmlAttributes->height) / 2 - $logoImageData->getHeight() / 2; + + $imageDefinition = $xml->addChild('image'); + $imageDefinition->addAttribute('x', strval($x)); + $imageDefinition->addAttribute('y', strval($y)); + $imageDefinition->addAttribute('width', strval($logoImageData->getWidth())); + $imageDefinition->addAttribute('height', strval($logoImageData->getHeight())); + $imageDefinition->addAttribute('preserveAspectRatio', 'none'); + + if ($options[self::WRITER_OPTION_FORCE_XLINK_HREF]) { + $imageDefinition->addAttribute('xlink:href', $logoImageData->createDataUri(), 'http://www.w3.org/1999/xlink'); + } else { + $imageDefinition->addAttribute('href', $logoImageData->createDataUri()); + } + } + + private function formatNumber(float $number): string + { + $string = number_format($number, self::DECIMAL_PRECISION, '.', ''); + $string = rtrim($string, '0'); + + return rtrim($string, '.'); + } +} diff --git a/vendor/endroid/qr-code/src/Writer/ValidatingWriterInterface.php b/vendor/endroid/qr-code/src/Writer/ValidatingWriterInterface.php new file mode 100644 index 0000000..4f40048 --- /dev/null +++ b/vendor/endroid/qr-code/src/Writer/ValidatingWriterInterface.php @@ -0,0 +1,12 @@ +getMatrix(), $gdResult->getImage(), $options[self::WRITER_OPTION_QUALITY]); + } +} diff --git a/vendor/endroid/qr-code/src/Writer/WriterInterface.php b/vendor/endroid/qr-code/src/Writer/WriterInterface.php new file mode 100644 index 0000000..66b233f --- /dev/null +++ b/vendor/endroid/qr-code/src/Writer/WriterInterface.php @@ -0,0 +1,16 @@ + $options */ + public function write(QrCodeInterface $qrCode, ?LogoInterface $logo = null, ?LabelInterface $label = null, array $options = []): ResultInterface; +} diff --git a/vendor/latte/latte/bin/latte-lint b/vendor/latte/latte/bin/latte-lint new file mode 100644 index 0000000..69e2e47 --- /dev/null +++ b/vendor/latte/latte/bin/latte-lint @@ -0,0 +1,42 @@ +#!/usr/bin/env php +\n"; + exit(1); +} + +if ($debug = in_array('--debug', $argv, true)) { + echo "Debug mode\n"; +} +if ($strict = in_array('--strict', $argv, true)) { + echo "Strict mode\n"; +} + +$path = $argv[1]; + +try { + $linter = new Latte\Tools\Linter(debug: $debug, strict: $strict); + $ok = $linter->scanDirectory($path); + exit($ok ? 0 : 1); + +} catch (Throwable $e) { + fwrite(STDERR, $debug ? "\n$e\n" : "\nError: {$e->getMessage()}\n"); + exit(2); +} diff --git a/vendor/latte/latte/composer.json b/vendor/latte/latte/composer.json new file mode 100644 index 0000000..045f80a --- /dev/null +++ b/vendor/latte/latte/composer.json @@ -0,0 +1,58 @@ +{ + "name": "latte/latte", + "description": "☕ Latte: the intuitive and fast template engine for those who want the most secure PHP sites. Introduces context-sensitive escaping.", + "keywords": ["template", "nette", "security", "engine", "html", "twig", "context-sensitive", "escaping"], + "homepage": "https://latte.nette.org", + "license": ["BSD-3-Clause", "GPL-2.0-only", "GPL-3.0-only"], + "authors": [ + { + "name": "David Grudl", + "homepage": "https://davidgrudl.com" + }, + { + "name": "Nette Community", + "homepage": "https://nette.org/contributors" + } + ], + "require": { + "php": "8.2 - 8.5", + "ext-json": "*", + "ext-tokenizer": "*" + }, + "require-dev": { + "nette/tester": "^2.5", + "tracy/tracy": "^2.10", + "nette/utils": "^4.0", + "nette/php-generator": "^4.0", + "phpstan/phpstan-nette": "^2.0@stable" + }, + "suggest": { + "ext-iconv": "to use filters |reverse, |substring", + "ext-mbstring": "to use filters like lower, upper, capitalize, ...", + "ext-fileinfo": "to use filter |datastream", + "ext-intl": "to use Latte\\Engine::setLocale()", + "nette/utils": "to use filter |webalize", + "nette/php-generator": "to use tag {templatePrint}" + }, + "conflict": { + "nette/application": "<3.1.7", + "nette/caching": "<3.1.4" + }, + "autoload": { + "classmap": ["src/"], + "psr-4": { + "Latte\\": "src/Latte" + } + }, + "minimum-stability": "dev", + "bin": ["bin/latte-lint"], + "scripts": { + "phpstan": "phpstan analyse", + "tester": "tester tests -s" + }, + "extra": { + "branch-alias": { + "dev-master": "3.1-dev" + } + } +} diff --git a/vendor/latte/latte/license.md b/vendor/latte/latte/license.md new file mode 100644 index 0000000..cf741bd --- /dev/null +++ b/vendor/latte/latte/license.md @@ -0,0 +1,60 @@ +Licenses +======== + +Good news! You may use Nette Framework under the terms of either +the New BSD License or the GNU General Public License (GPL) version 2 or 3. + +The BSD License is recommended for most projects. It is easy to understand and it +places almost no restrictions on what you can do with the framework. If the GPL +fits better to your project, you can use the framework under this license. + +You don't have to notify anyone which license you are using. You can freely +use Nette Framework in commercial projects as long as the copyright header +remains intact. + +Please be advised that the name "Nette Framework" is a protected trademark and its +usage has some limitations. So please do not use word "Nette" in the name of your +project or top-level domain, and choose a name that stands on its own merits. +If your stuff is good, it will not take long to establish a reputation for yourselves. + + +New BSD License +--------------- + +Copyright (c) 2004, 2014 David Grudl (https://davidgrudl.com) +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 "Nette Framework" 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 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. + + +GNU General Public License +-------------------------- + +GPL licenses are very very long, so instead of including them here we offer +you URLs with full text: + +- [GPL version 2](http://www.gnu.org/licenses/gpl-2.0.html) +- [GPL version 3](http://www.gnu.org/licenses/gpl-3.0.html) diff --git a/vendor/latte/latte/readme.md b/vendor/latte/latte/readme.md new file mode 100644 index 0000000..385d203 --- /dev/null +++ b/vendor/latte/latte/readme.md @@ -0,0 +1,39 @@ +[![Latte](https://github.com/nette/latte/assets/194960/76c098ff-427c-4b30-9676-97e2d8fd4a56)](https://latte.nette.org) + +  + +

+ +✅ The [only truly secure](https://latte.nette.org/en/safety-first) templating system for PHP
+✅ [You already know the syntax](https://latte.nette.org/en/syntax)
+✅ Highly mature, fast, and widely used library + +

+ +  + +Latte is the safest templating system for PHP. It is cleverly designed and easy to learn for those familiar with PHP, as they can quickly adopt its basic tags. +A wide range of useful features will significantly simplify your work. It provides top-notch protection against critical vulnerabilities and allows you to focus on creating high-quality applications without worrying about their security. + +🟨 Only 1% of programmers [can pass this quiz](https://blog.nette.org/en/quiz-can-you-defend-against-xss-vulnerability)! + +  + +Getting started +======= + +

+ +1️⃣ First, familiarize yourself with [Latte syntax](https://latte.nette.org/en/syntax) and [try it online](https://fiddle.nette.org/latte/#9cc0cf6d89)
+2️⃣ Take a look at the basic set of [tags](https://latte.nette.org/en/tags) and [filters](https://latte.nette.org/en/filters)
+3️⃣ Render a template with a [few lines of PHP code](https://latte.nette.org/en/develop) + +

+ +  + +Do you like Latte? Are you looking forward to the new features? + +[![Buy me a coffee](https://files.nette.org/icons/donation-3.svg)](https://github.com/sponsors/dg) + +Thank you! diff --git a/vendor/latte/latte/src/Bridges/Tracy/BlueScreenPanel.php b/vendor/latte/latte/src/Bridges/Tracy/BlueScreenPanel.php new file mode 100644 index 0000000..7a1a607 --- /dev/null +++ b/vendor/latte/latte/src/Bridges/Tracy/BlueScreenPanel.php @@ -0,0 +1,98 @@ +addPanel(self::renderError(...)); + $blueScreen->addAction(self::renderUnknownMacro(...)); + if ( + version_compare(Tracy\Debugger::VERSION, '2.9.0', '>=') + && version_compare(Tracy\Debugger::VERSION, '3.0', '<') + ) { + Tracy\Debugger::addSourceMapper(self::mapLatteSourceCode(...)); + $blueScreen->addFileGenerator(fn(string $file) => substr($file, -6) === '.latte' + ? "{block content}\n\$END\$" + : null); + } + } + + + public static function renderError(?\Throwable $e): ?array + { + if ($e instanceof Latte\CompileException && $e->sourceName) { + return [ + 'tab' => 'Template', + 'panel' => (preg_match('#\n|\?#', $e->sourceName) + ? '' + : '

' + . (@is_file($e->sourceName) // @ - may trigger error + ? 'File: ' . Helpers::editorLink($e->sourceName, $e->position?->line) + : '' . htmlspecialchars($e->sourceName . ($e->position?->line ? ':' . $e->position->line : '')) . '') + . '

') + . '
' + . BlueScreen::highlightLine(htmlspecialchars($e->sourceCode, ENT_IGNORE, 'UTF-8'), $e->position->line ?? 0, 15, $e->position->column ?? 0) + . '
', + ]; + } + + return null; + } + + + public static function renderUnknownMacro(?\Throwable $e): ?array + { + if ( + $e instanceof Latte\CompileException + && $e->sourceName + && @is_file($e->sourceName) // @ - may trigger error + && (preg_match('#Unknown tag (\{\w+)\}, did you mean (\{\w+)\}\?#A', $e->getMessage(), $m) + || preg_match('#Unknown attribute (n:\w+), did you mean (n:\w+)\?#A', $e->getMessage(), $m)) + ) { + return [ + 'link' => Helpers::editorUri($e->sourceName, $e->position?->line, 'fix', $m[1], $m[2]), + 'label' => 'fix it', + ]; + } + + return null; + } + + + /** @return array{file: string, line: int, label: string, active: bool} */ + public static function mapLatteSourceCode(string $file, int $line): ?array + { + return ($source = Latte\Helpers::mapCompiledToSource($file, $line)) && @is_file($source['name']) // @ - may trigger error + ? ['file' => $source['name'], 'line' => $source['line'] ?? 0, 'column' => $source['column'] ?? 0, 'label' => 'Latte', 'active' => true] + : null; + } +} diff --git a/vendor/latte/latte/src/Bridges/Tracy/LattePanel.php b/vendor/latte/latte/src/Bridges/Tracy/LattePanel.php new file mode 100644 index 0000000..52e7a9d --- /dev/null +++ b/vendor/latte/latte/src/Bridges/Tracy/LattePanel.php @@ -0,0 +1,123 @@ +addPanel(new self($latte, $name)); + } + + + /** @deprecated use TracyExtension see https://bit.ly/46flfDi */ + public function __construct(?Engine $latte = null, ?string $name = null) + { + $this->name = $name; + if ($latte) { + trigger_error('Replace LattePanel with TracyExtension; see https://bit.ly/46flfDi', E_USER_DEPRECATED); + $latte->addExtension( + new class ($this->templates) extends Extension { + public function __construct( + private array &$templates, + ) { + } + + + public function beforeRender(Template $template): void + { + $this->templates[] = $template; + } + }, + ); + } + } + + + public function addTemplate(Template $template): void + { + $this->templates[] = $template; + } + + + /** + * Renders tab. + */ + public function getTab(): ?string + { + if (!$this->templates) { + return null; + } + + return Tracy\Helpers::capture(function () { + $name = $this->name ?? basename(reset($this->templates)->getName()); + require __DIR__ . '/dist/tab.phtml'; + }); + } + + + /** + * Renders panel. + */ + public function getPanel(): string + { + $this->list = []; + $this->buildList($this->templates[0]); + + return Tracy\Helpers::capture(function () { + $list = $this->list; + $dumpParameters = $this->dumpParameters; + require __DIR__ . '/dist/panel.phtml'; + }); + } + + + private function buildList(Template $template, int $depth = 0, int $count = 1): void + { + $this->list[] = (object) [ + 'template' => $template, + 'depth' => $depth, + 'count' => $count, + 'phpFile' => (new \ReflectionObject($template))->getFileName(), + ]; + + $children = $counter = []; + foreach ($this->templates as $t) { + if ($t->getReferringTemplate() === $template) { + $children[$t->getName()] = $t; + @$counter[$t->getName()]++; + } + } + + foreach ($children as $name => $t) { + $this->buildList($t, $depth + 1, $counter[$name]); + } + } +} diff --git a/vendor/latte/latte/src/Bridges/Tracy/TracyExtension.php b/vendor/latte/latte/src/Bridges/Tracy/TracyExtension.php new file mode 100644 index 0000000..6b1c6bd --- /dev/null +++ b/vendor/latte/latte/src/Bridges/Tracy/TracyExtension.php @@ -0,0 +1,37 @@ +panel = new LattePanel(name: $name); + Tracy\Debugger::getBar()->addPanel($this->panel); + } + + + public function beforeRender(Template $template): void + { + $this->panel->addTemplate($template); + } +} diff --git a/vendor/latte/latte/src/Bridges/Tracy/dist/panel.phtml b/vendor/latte/latte/src/Bridges/Tracy/dist/panel.phtml new file mode 100644 index 0000000..e5a3e40 --- /dev/null +++ b/vendor/latte/latte/src/Bridges/Tracy/dist/panel.phtml @@ -0,0 +1,96 @@ + + '#00000052', + 'extends' => '#cd1c1c7d', + 'import' => '#17c35b8f', + 'includeblock' => '#17c35b8f', + 'embed' => '#4f1ccd7d', + 'sandbox' => 'black', +] ?> + + +

Rendered Templates

+ +
+ + + + + + +
+template->getReferenceType()): ?> └  + template->getReferenceType()) ?> + + + template->getName()) ?> + + + php + count > 1 ? $item->count . '×' : '') ?> +
+ +

Parameters

+ +
+ +template->getParameters() as $k => $v): ?> + + + +
+ true]) ?> +
+
+
diff --git a/vendor/latte/latte/src/Bridges/Tracy/dist/tab.phtml b/vendor/latte/latte/src/Bridges/Tracy/dist/tab.phtml new file mode 100644 index 0000000..9ccdb86 --- /dev/null +++ b/vendor/latte/latte/src/Bridges/Tracy/dist/tab.phtml @@ -0,0 +1,12 @@ + + + + + + + + + diff --git a/vendor/latte/latte/src/Bridges/Tracy/panel.latte b/vendor/latte/latte/src/Bridges/Tracy/panel.latte new file mode 100644 index 0000000..4e83616 --- /dev/null +++ b/vendor/latte/latte/src/Bridges/Tracy/panel.latte @@ -0,0 +1,94 @@ +{do $colors = [ + 'include' => '#00000052', + 'extends' => '#cd1c1c7d', + 'import' => '#17c35b8f', + 'includeblock' => '#17c35b8f', + 'embed' => '#4f1ccd7d', + 'sandbox' => 'black', +]} + + + +

Rendered Templates

+ +
+ + {foreach $list as $item} + + + + + + {/foreach} +
+ {if $item->template->getReferenceType()} + └  + {$item->template->getReferenceType()} + {/if} + + {Tracy\Helpers::editorLink($item->template->getName())} + + php + {$item->count > 1 ? $item->count . '×' : ''}
+ + {if $dumpParameters} +

Parameters

+ +
+ + {foreach reset($list)->template->getParameters() as $k => $v} + + + + + {/foreach} +
{$k}{Tracy\Dumper::toHtml($v, [Tracy\Dumper::LIVE => true])}
+
+ {/if} +
diff --git a/vendor/latte/latte/src/Bridges/Tracy/tab.latte b/vendor/latte/latte/src/Bridges/Tracy/tab.latte new file mode 100644 index 0000000..8467aed --- /dev/null +++ b/vendor/latte/latte/src/Bridges/Tracy/tab.latte @@ -0,0 +1,8 @@ + + + + + + {$name} + diff --git a/vendor/latte/latte/src/Latte/Cache.php b/vendor/latte/latte/src/Latte/Cache.php new file mode 100644 index 0000000..a33902a --- /dev/null +++ b/vendor/latte/latte/src/Latte/Cache.php @@ -0,0 +1,142 @@ +generateFilePath($engine, $name); + $signature = $this->autoRefresh + ? hash('xxh128', serialize($this->generateRefreshSignature($engine, $name))) + : null; + $lock = defined('PHP_WINDOWS_VERSION_BUILD') || $signature + ? $this->acquireLock("$file.lock", LOCK_SH) + : null; + + if ( + !($signature && $signature !== stream_get_contents($lock)) + && (@include $file) !== false // @ - file may not exist + ) { + return; + } + + if ($lock) { + flock($lock, LOCK_UN); // release shared lock so we can get exclusive + fseek($lock, 0); + } + + $lock = $this->acquireLock("$file.lock", LOCK_EX); + + // while waiting for exclusive lock, someone might have already created the cache + if (!is_file($file) || ($signature && $signature !== stream_get_contents($lock))) { + $compiled = $engine->compile($name); + if ( + file_put_contents("$file.tmp", $compiled) !== strlen($compiled) + || !rename("$file.tmp", $file) + ) { + @unlink("$file.tmp"); // @ - file may not exist + throw new RuntimeException("Unable to create '$file'."); + } + + fseek($lock, 0); + fwrite($lock, $signature ?? hash('xxh128', serialize($this->generateRefreshSignature($engine, $name)))); + ftruncate($lock, ftell($lock)); + + if (function_exists('opcache_invalidate')) { + @opcache_invalidate($file, true); // @ can be restricted + } + } + + if ((include $file) === false) { + throw new RuntimeException("Unable to load '$file'."); + } + + flock($lock, LOCK_UN); + } + + + /** @return resource */ + private function acquireLock(string $file, int $mode) + { + $dir = dirname($file); + if (!is_dir($dir) && !@mkdir($dir) && !is_dir($dir)) { // @ - dir may already exist + throw new RuntimeException("Unable to create directory '$dir'. " . error_get_last()['message']); + } + + $handle = @fopen($file, 'c+'); // @ is escalated to exception + if (!$handle) { + throw new RuntimeException("Unable to create file '$file'. " . error_get_last()['message']); + } elseif (!@flock($handle, $mode)) { // @ is escalated to exception + throw new RuntimeException('Unable to acquire ' . ($mode & LOCK_EX ? 'exclusive' : 'shared') . " lock on file '$file'. " . error_get_last()['message']); + } + + return $handle; + } + + + /** + * Returns the file path where compiled template will be cached. + * Different configurations produce different file paths. + */ + public function generateFilePath(Engine $engine, string $name): string + { + $base = preg_match('#([/\\\][\w@.-]{3,35}){1,3}$#D', '/' . $name, $m) + ? preg_replace('#[^\w@.-]+#', '-', substr($m[0], 1)) + : ''; + if (!str_ends_with($base, 'latte')) { + $base .= '-latte'; + } + return $this->directory . '/' . $base . '--' . $engine->generateTemplateHash($name) . '.php'; + } + + + public static function isCacheFile(string $file): bool + { + return (bool) preg_match('/latte--\w{10}\.php$/', $file); + } + + + /** + * Returns values used to detect if cached template needs recompilation when autoRefresh is enabled. + * Triggers recompilation when template code, Latte engine, or any extension changes. + */ + protected function generateRefreshSignature(Engine $engine, string $name): array + { + return [ + Engine::Version, + $engine->getLoader()->getContent($name), + array_map( + fn($extension) => filemtime((new \ReflectionObject($extension))->getFileName()), + $engine->getExtensions(), + ), + ]; + } +} diff --git a/vendor/latte/latte/src/Latte/Compiler/Block.php b/vendor/latte/latte/src/Latte/Compiler/Block.php new file mode 100644 index 0000000..ce1d6fe --- /dev/null +++ b/vendor/latte/latte/src/Latte/Compiler/Block.php @@ -0,0 +1,41 @@ +name instanceof Scalar\StringNode + && !$this->name instanceof Scalar\IntegerNode; + } +} diff --git a/vendor/latte/latte/src/Latte/Compiler/Escaper.php b/vendor/latte/latte/src/Latte/Compiler/Escaper.php new file mode 100644 index 0000000..e1f7fb2 --- /dev/null +++ b/vendor/latte/latte/src/Latte/Compiler/Escaper.php @@ -0,0 +1,253 @@ + [ + self::HtmlText => 'HtmlHelpers::escapeText', + self::HtmlAttribute => 'HtmlHelpers::escapeAttr', + self::HtmlAttribute . '/' . self::JavaScript => 'HtmlHelpers::escapeAttr', + self::HtmlAttribute . '/' . self::Css => 'HtmlHelpers::escapeAttr', + self::HtmlComment => 'HtmlHelpers::escapeComment', + 'xml' => 'XmlHelpers::escapeText', + 'xml/attr' => 'XmlHelpers::escapeAttr', + ], + self::JavaScript => [ + self::HtmlText => 'HtmlHelpers::escapeText', + self::HtmlAttribute => 'HtmlHelpers::escapeAttr', + self::HtmlAttribute . '/' . self::JavaScript => 'HtmlHelpers::escapeAttr', + self::HtmlRawText . '/' . self::JavaScript => 'HtmlHelpers::convertJSToRawText', + self::HtmlComment => 'HtmlHelpers::escapeComment', + ], + self::Css => [ + self::HtmlText => 'HtmlHelpers::escapeText', + self::HtmlAttribute => 'HtmlHelpers::escapeAttr', + self::HtmlAttribute . '/' . self::Css => 'HtmlHelpers::escapeAttr', + self::HtmlRawText . '/' . self::Css => 'HtmlHelpers::convertJSToRawText', + self::HtmlComment => 'HtmlHelpers::escapeComment', + ], + self::HtmlText => [ + self::Text => 'HtmlHelpers::convertHtmlToText', + self::HtmlAttribute => 'HtmlHelpers::convertHtmlToAttr', + self::HtmlAttribute . '/' . self::JavaScript => 'HtmlHelpers::convertHtmlToAttr', + self::HtmlAttribute . '/' . self::Css => 'HtmlHelpers::convertHtmlToAttr', + self::HtmlComment => 'HtmlHelpers::escapeComment', + self::HtmlRawText . '/' . self::HtmlText => 'HtmlHelpers::convertHtmlToRawText', + ], + self::HtmlAttribute => [ + self::HtmlText => 'HtmlHelpers::convertAttrToHtml', + ], + ]; + + private string $state = ''; + private string $tag = ''; + private string $subType = ''; + + + public function __construct( + private string $contentType, + ) { + $this->state = in_array($contentType, [ContentType::Html, ContentType::Xml], true) + ? self::HtmlText + : $contentType; + } + + + public function getContentType(): string + { + return $this->contentType; + } + + + public function getState(): string + { + return $this->state; + } + + + public function export(): string + { + return $this->state . ($this->subType ? '/' . $this->subType : ''); + } + + + public function enterContentType(string $type): void + { + $this->contentType = $this->state = $type; + } + + + public function enterHtmlText(ElementNode $el): void + { + if ($el->isRawText()) { + $this->state = self::HtmlRawText; + if ($el->is('script')) { + $type = $el->getAttribute('type'); + $this->subType = $type === true || $type === null + ? self::JavaScript + : HtmlHelpers::classifyScriptType($type); + } elseif ($el->is('style')) { + $this->subType = self::Css; + } + + } else { + $this->state = self::HtmlText; + $this->subType = ''; + } + } + + + public function enterHtmlTag(string $name): void + { + $this->state = self::HtmlTag; + $this->tag = $name; + } + + + public function enterHtmlRaw(string $subType): void + { + $this->state = self::HtmlRawText; + $this->subType = $subType; + } + + + public function enterHtmlAttribute(?string $name = null): void + { + $this->state = self::HtmlAttribute; + $this->subType = ''; + + if ($this->contentType === ContentType::Html && is_string($name)) { + $name = strtolower($name); + if (str_starts_with($name, 'on')) { + $this->subType = self::JavaScript; + } elseif ($name === 'style') { + $this->subType = self::Css; + } + } + } + + + public function enterHtmlBogusTag(): void + { + $this->state = self::HtmlBogusTag; + } + + + public function enterHtmlComment(): void + { + $this->state = self::HtmlComment; + } + + + public function escape(string $str): string + { + return match ($this->contentType) { + ContentType::Html => match ($this->state) { + self::HtmlText => 'LR\HtmlHelpers::escapeText(' . $str . ')', + self::HtmlTag => 'LR\HtmlHelpers::escapeTag(' . $str . ')', + self::HtmlAttribute => match ($this->subType) { + '' => 'LR\HtmlHelpers::escapeAttr(' . $str . ')', + self::JavaScript => 'LR\HtmlHelpers::escapeAttr(LR\Helpers::escapeJs(' . $str . '))', + self::Css => 'LR\HtmlHelpers::escapeAttr(LR\Helpers::escapeCss(' . $str . '))', + }, + self::HtmlComment => 'LR\HtmlHelpers::escapeComment(' . $str . ')', + self::HtmlBogusTag => 'LR\HtmlHelpers::escapeTag(' . $str . ')', + self::HtmlRawText => match ($this->subType) { + self::Text => 'LR\HtmlHelpers::convertJSToRawText(' . $str . ')', // sanitization, escaping is not possible + self::HtmlText => 'LR\HtmlHelpers::escapeRawHtml(' . $str . ')', + self::JavaScript => 'LR\Helpers::escapeJs(' . $str . ')', + self::Css => 'LR\Helpers::escapeCss(' . $str . ')', + }, + default => throw new \LogicException("Unknown context $this->contentType, $this->state."), + }, + ContentType::Xml => match ($this->state) { + self::HtmlText => 'LR\XmlHelpers::escapeText(' . $str . ')', + self::HtmlBogusTag => 'LR\XmlHelpers::escapeTag(' . $str . ')', + self::HtmlAttribute => 'LR\XmlHelpers::escapeAttr(' . $str . ')', + self::HtmlComment => 'LR\HtmlHelpers::escapeComment(' . $str . ')', + self::HtmlTag => 'LR\XmlHelpers::escapeTag(' . $str . ')', + default => throw new \LogicException("Unknown context $this->contentType, $this->state."), + }, + ContentType::JavaScript => 'LR\Helpers::escapeJs(' . $str . ')', + ContentType::Css => 'LR\Helpers::escapeCss(' . $str . ')', + ContentType::ICal => 'LR\Helpers::escapeIcal(' . $str . ')', + ContentType::Text => '($this->filters->escape)(' . $str . ')', + default => throw new \LogicException("Unknown content-type $this->contentType."), + }; + } + + + public function escapeMandatory(string $str, ?Position $position = null): string + { + return match ($this->contentType) { + ContentType::Html => match ($this->state) { + self::HtmlAttribute => "LR\\HtmlHelpers::escapeQuotes($str)", + self::HtmlRawText => match ($this->subType) { + self::HtmlText => 'LR\HtmlHelpers::convertHtmlToRawText(' . $str . ')', + default => "LR\\HtmlHelpers::convertJSToRawText($str)", + }, + self::HtmlComment => throw new Latte\CompileException('Using |noescape is not allowed in this context.', $position), + default => $str, + }, + ContentType::Xml => match ($this->state) { + self::HtmlAttribute => "LR\\HtmlHelpers::escapeQuotes($str)", + self::HtmlComment => throw new Latte\CompileException('Using |noescape is not allowed in this context.', $position), + default => $str, + }, + default => $str, + }; + } + + + public function escapeContent(string $str): string + { + return 'LR\Helpers::convertTo($ʟ_fi, ' + . var_export($this->export(), true) . ', ' + . $str + . ')'; + } + + + public static function getConvertor(string $source, string $dest): ?callable + { + return match (true) { + $source === $dest => Helpers::nop(...), + isset(self::Convertors[$source][$dest]) => 'Latte\Runtime\\' . self::Convertors[$source][$dest], + default => null, + }; + } +} diff --git a/vendor/latte/latte/src/Latte/Compiler/Node.php b/vendor/latte/latte/src/Latte/Compiler/Node.php new file mode 100644 index 0000000..86fc276 --- /dev/null +++ b/vendor/latte/latte/src/Latte/Compiler/Node.php @@ -0,0 +1,21 @@ + + */ +abstract class Node implements \IteratorAggregate +{ + public ?Position $position = null; + + + abstract public function print(PrintContext $context): string; + + + /** @return \Generator */ + abstract public function &getIterator(): \Generator; +} diff --git a/vendor/latte/latte/src/Latte/Compiler/NodeHelpers.php b/vendor/latte/latte/src/Latte/Compiler/NodeHelpers.php new file mode 100644 index 0000000..3ad2c27 --- /dev/null +++ b/vendor/latte/latte/src/Latte/Compiler/NodeHelpers.php @@ -0,0 +1,129 @@ +traverse($node, enter: function (Node $node) use ($filter, &$found) { + if ($filter($node)) { + $found[] = $node; + } + }); + return $found; + } + + + public static function findFirst(Node $node, callable $filter): ?Node + { + $found = null; + (new NodeTraverser) + ->traverse($node, enter: function (Node $node) use ($filter, &$found) { + if ($filter($node)) { + $found = $node; + return NodeTraverser::StopTraversal; + } + }); + return $found; + } + + + public static function clone(Node $node): Node + { + return (new NodeTraverser) + ->traverse($node, enter: fn(Node $node) => clone $node); + } + + + public static function toValue(ExpressionNode $node, bool $constants = false): mixed + { + if ($node instanceof Scalar\BooleanNode + || $node instanceof Scalar\FloatNode + || $node instanceof Scalar\IntegerNode + || $node instanceof Scalar\StringNode + ) { + return $node->value; + + } elseif ($node instanceof Scalar\NullNode) { + return null; + + } elseif ($node instanceof Expression\ArrayNode) { + $res = []; + foreach ($node->items as $item) { + $value = self::toValue($item->value, $constants); + if ($item->key) { + $key = $item->key instanceof Php\IdentifierNode + ? $item->key->name + : self::toValue($item->key, $constants); + $res[$key] = $value; + + } elseif ($item->unpack) { + $res = array_merge($res, $value); + + } else { + $res[] = $value; + } + } + + return $res; + + } elseif ($node instanceof Expression\ConstantFetchNode && $constants) { + $name = $node->name->toCodeString(); + return defined($name) + ? constant($name) + : throw new \InvalidArgumentException("The constant '$name' is not defined."); + + } elseif ($node instanceof Expression\ClassConstantFetchNode && $constants) { + $class = $node->class instanceof Php\NameNode + ? $node->class->toCodeString() + : self::toValue($node->class, $constants); + $name = $class . '::' . $node->name->name; + return defined($name) + ? constant($name) + : throw new \InvalidArgumentException("The constant '$name' is not defined."); + + } else { + throw new \InvalidArgumentException('The expression cannot be converted to PHP value.'); + } + } + + + public static function toText(?Node $node): ?string + { + if ($node instanceof Nodes\FragmentNode) { + $res = ''; + foreach ($node->children as $child) { + if (($s = self::toText($child)) === null) { + return null; + } + $res .= $s; + } + + return $res; + } + + return match (true) { + $node instanceof Nodes\TextNode => $node->content, + $node instanceof Nodes\NopNode => '', + default => null, + }; + } +} diff --git a/vendor/latte/latte/src/Latte/Compiler/NodeTraverser.php b/vendor/latte/latte/src/Latte/Compiler/NodeTraverser.php new file mode 100644 index 0000000..9650b98 --- /dev/null +++ b/vendor/latte/latte/src/Latte/Compiler/NodeTraverser.php @@ -0,0 +1,81 @@ +enter = $enter; + $this->leave = $leave; + $this->stop = false; + return $this->traverseNode($node); + } + + + private function traverseNode(Node $node): ?Node + { + $children = true; + if ($this->enter) { + $res = ($this->enter)($node); + if ($res instanceof Node) { + $node = $res; + + } elseif ($res === self::DontTraverseChildren) { + $children = false; + + } elseif ($res === self::StopTraversal) { + $this->stop = true; + return $node; + + } elseif ($res === self::RemoveNode) { + return null; + } + } + + if ($children) { + foreach ($node as &$subnode) { + $subnode = $this->traverseNode($subnode); + if ($this->stop) { + break; + } + } + } + + if (!$this->stop && $this->leave) { + $res = ($this->leave)($node); + if ($res instanceof Node) { + $node = $res; + + } elseif ($res === self::StopTraversal) { + $this->stop = true; + + } elseif ($res === self::RemoveNode) { + return null; + } + } + + return $node; + } +} diff --git a/vendor/latte/latte/src/Latte/Compiler/Nodes/AreaNode.php b/vendor/latte/latte/src/Latte/Compiler/Nodes/AreaNode.php new file mode 100644 index 0000000..ac9cc78 --- /dev/null +++ b/vendor/latte/latte/src/Latte/Compiler/Nodes/AreaNode.php @@ -0,0 +1,17 @@ +print)($context, ...$this->nodes); + } + + + public function &getIterator(): \Generator + { + foreach ($this->nodes as &$node) { + if ($node) { + yield $node; + } + } + } +} diff --git a/vendor/latte/latte/src/Latte/Compiler/Nodes/FragmentNode.php b/vendor/latte/latte/src/Latte/Compiler/Nodes/FragmentNode.php new file mode 100644 index 0000000..dedce40 --- /dev/null +++ b/vendor/latte/latte/src/Latte/Compiler/Nodes/FragmentNode.php @@ -0,0 +1,72 @@ +append($child); + } + } + + + public function append(AreaNode $node): static + { + if ($node instanceof self) { + $this->children = array_merge($this->children, $node->children); + } elseif (!$node instanceof NopNode) { + $this->children[] = $node; + } + $this->position ??= $node->position; + return $this; + } + + + public function simplify(bool $allowsNull = true): ?AreaNode + { + return match (true) { + !$this->children => $allowsNull ? null : $this, + count($this->children) === 1 => $this->children[0], + default => $this, + }; + } + + + public function print(PrintContext $context): string + { + $res = ''; + foreach ($this->children as $child) { + $res .= $child->print($context); + } + + return $res; + } + + + public function &getIterator(): \Generator + { + foreach ($this->children as &$item) { + yield $item; + } + Helpers::removeNulls($this->children); + } +} diff --git a/vendor/latte/latte/src/Latte/Compiler/Nodes/Html/AttributeNode.php b/vendor/latte/latte/src/Latte/Compiler/Nodes/Html/AttributeNode.php new file mode 100644 index 0000000..b6cf0ac --- /dev/null +++ b/vendor/latte/latte/src/Latte/Compiler/Nodes/Html/AttributeNode.php @@ -0,0 +1,57 @@ +name->print($context); + if (!$this->value) { + return $res; + } + + $res .= "echo '=';"; + $quote = $this->quote ?? ($this->value instanceof TextNode ? null : '"'); + $res .= $quote ? 'echo ' . var_export($quote, true) . ';' : ''; + + $escaper = $context->beginEscape(); + $escaper->enterHtmlAttribute(NodeHelpers::toText($this->name)); + $res .= $this->value->print($context); + $context->restoreEscape(); + $res .= $quote ? 'echo ' . var_export($quote, true) . ';' : ''; + return $res; + } + + + public function &getIterator(): \Generator + { + yield $this->name; + if ($this->value) { + yield $this->value; + } + } +} diff --git a/vendor/latte/latte/src/Latte/Compiler/Nodes/Html/BogusTagNode.php b/vendor/latte/latte/src/Latte/Compiler/Nodes/Html/BogusTagNode.php new file mode 100644 index 0000000..76c94d0 --- /dev/null +++ b/vendor/latte/latte/src/Latte/Compiler/Nodes/Html/BogusTagNode.php @@ -0,0 +1,46 @@ +openDelimiter, true) . ';'; + $context->beginEscape()->enterHtmlBogusTag(); + $res .= $this->content->print($context); + $context->restoreEscape(); + $res .= 'echo ' . var_export($this->endDelimiter, true) . ';'; + return $res; + } + + + public function &getIterator(): \Generator + { + yield $this->content; + } +} diff --git a/vendor/latte/latte/src/Latte/Compiler/Nodes/Html/CommentNode.php b/vendor/latte/latte/src/Latte/Compiler/Nodes/Html/CommentNode.php new file mode 100644 index 0000000..8ddca5c --- /dev/null +++ b/vendor/latte/latte/src/Latte/Compiler/Nodes/Html/CommentNode.php @@ -0,0 +1,39 @@ +beginEscape()->enterHtmlComment(); + $content = $this->content->print($context); + $context->restoreEscape(); + return "echo '';"; + } + + + public function &getIterator(): \Generator + { + yield $this->content; + } +} diff --git a/vendor/latte/latte/src/Latte/Compiler/Nodes/Html/ElementNode.php b/vendor/latte/latte/src/Latte/Compiler/Nodes/Html/ElementNode.php new file mode 100644 index 0000000..f448d91 --- /dev/null +++ b/vendor/latte/latte/src/Latte/Compiler/Nodes/Html/ElementNode.php @@ -0,0 +1,124 @@ +attributes = new FragmentNode; + } + + + public function getAttribute(string $name): string|Node|bool|null + { + foreach ($this->attributes->children as $child) { + if ($child instanceof AttributeNode + && $child->name instanceof Nodes\TextNode + && $this->matchesIdentifier($name, $child->name->content) + ) { + return NodeHelpers::toText($child->value) ?? $child->value ?? true; + } elseif ($child instanceof ExpressionAttributeNode + && $this->matchesIdentifier($name, $child->name) + ) { + return true; + } + } + + return null; + } + + + public function is(string $name): bool + { + return $this->matchesIdentifier($this->name, $name); + } + + + private function matchesIdentifier(string $a, string $b): bool + { + return $this->contentType === ContentType::Html + ? strcasecmp($a, $b) === 0 + : $a === $b; + } + + + public function isRawText(): bool + { + return $this->contentType === ContentType::Html + && ($this->is('script') || $this->is('style')); + } + + + public function print(PrintContext $context): string + { + $res = $this->dynamicTag + ? $this->dynamicTag->print($context) + : (new TagNode($this))->print($context, captureEnd: false); + + if ($this->content) { + if ($this->dynamicTag) { + $endTag = '$ʟ_tags[' . ($context->generateId()) . ']'; + $res = "\$ʟ_tag = ''; $res $endTag = \$ʟ_tag;"; + } else { + $endTag = var_export('name . '>', true); + } + + $context->beginEscape()->enterHtmlText($this); + $content = $this->content->print($context); + $context->restoreEscape(); + $res .= $this->breakable + ? 'try { ' . $content . ' } finally { echo ' . $endTag . '; } ' + : $content . ' echo ' . $endTag . ';'; + } + + return $res; + } + + + public function &getIterator(): \Generator + { + if ($this->dynamicTag) { + yield $this->dynamicTag; + } + yield $this->attributes; + if ($this->content) { + yield $this->content; + } + } +} diff --git a/vendor/latte/latte/src/Latte/Compiler/Nodes/Html/ExpressionAttributeNode.php b/vendor/latte/latte/src/Latte/Compiler/Nodes/Html/ExpressionAttributeNode.php new file mode 100644 index 0000000..4e68f48 --- /dev/null +++ b/vendor/latte/latte/src/Latte/Compiler/Nodes/Html/ExpressionAttributeNode.php @@ -0,0 +1,58 @@ +getEscaper()->getContentType() === ContentType::Html) { + $type = $this->modifier->removeFilter('toggle') ? 'bool' : LR\HtmlHelpers::classifyAttributeType($this->name); + $method = 'LR\HtmlHelpers::format' . ucfirst($type) . 'Attribute'; + } else { + $method = 'LR\XmlHelpers::formatAttribute'; + } + return $context->format( + 'echo %raw(%dump, %modify(%node), %dump?) %line;', + $method, + $this->indentation . $this->name, + $this->modifier, + $this->value, + (!$this->modifier->removeFilter('accept') && $context->migrationWarnings) ?: null, + $this->value->position, + ); + } + + + public function &getIterator(): \Generator + { + yield $this->value; + yield $this->modifier; + } +} diff --git a/vendor/latte/latte/src/Latte/Compiler/Nodes/Html/TagNode.php b/vendor/latte/latte/src/Latte/Compiler/Nodes/Html/TagNode.php new file mode 100644 index 0000000..28e47d3 --- /dev/null +++ b/vendor/latte/latte/src/Latte/Compiler/Nodes/Html/TagNode.php @@ -0,0 +1,72 @@ +element->content; + $context->beginEscape()->enterHtmlTag($this->element->name); + + $res = $this->name + ? $context->format( + <<<'XX' + $ʟ_tmp = LR\%raw::validateTagChange(%node, %dump); + %raw + echo '<', $ʟ_tmp %line; + %node + echo %dump; + XX, + $this->element->contentType === ContentType::Html ? 'HtmlHelpers' : 'XmlHelpers', + $this->name, + $this->element->name, + $captureEnd ? '$ʟ_tag = \'\' . $ʟ_tag;' : '', + $this->element->position, + $this->element->attributes, + $this->element->selfClosing ? '/>' : '>', + ) + : $context->format( + '%raw echo %dump; %node echo %dump;', + $captureEnd ? '$ʟ_tag = ' . $context->encodeString("element->name}>") . ' . $ʟ_tag;' : '', + '<' . $this->element->name, + $this->element->attributes, + $this->element->selfClosing ? '/>' : '>', + ); + + $context->restoreEscape(); + return $res; + } + + + public function &getIterator(): \Generator + { + if ($this->name) { + yield $this->name; + } + } +} diff --git a/vendor/latte/latte/src/Latte/Compiler/Nodes/NopNode.php b/vendor/latte/latte/src/Latte/Compiler/Nodes/NopNode.php new file mode 100644 index 0000000..b4b4dc1 --- /dev/null +++ b/vendor/latte/latte/src/Latte/Compiler/Nodes/NopNode.php @@ -0,0 +1,27 @@ +name ? $this->name . ': ' : '') + . ($this->byRef ? '&' : '') + . ($this->unpack ? '...' : '') + . $this->value->print($context); + } + + + public function toArrayItem(): ArrayItemNode + { + return new ArrayItemNode($this->value, $this->name, $this->byRef, $this->unpack, $this->position); + } + + + public function &getIterator(): \Generator + { + if ($this->name) { + yield $this->name; + } + yield $this->value; + } +} diff --git a/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/ArrayItemNode.php b/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/ArrayItemNode.php new file mode 100644 index 0000000..60d7c3a --- /dev/null +++ b/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/ArrayItemNode.php @@ -0,0 +1,62 @@ +key instanceof ExpressionNode => $this->key->print($context) . ' => ', + $this->key instanceof IdentifierNode => $context->encodeString($this->key->name) . ' => ', + $this->key === null => '', + }; + return $key + . ($this->byRef ? '&' : '') + . ($this->unpack ? '...' : '') + . $this->value->print($context); + } + + + public function toArgument(): ArgumentNode + { + $key = match (true) { + $this->key instanceof Scalar\StringNode => new IdentifierNode($this->key->value), + $this->key instanceof IdentifierNode => $this->key, + $this->key === null => null, + default => throw new \InvalidArgumentException('The expression used in the key cannot be converted to an argument.'), + }; + return new ArgumentNode($this->value, $this->byRef, $this->unpack, $key, $this->position); + } + + + public function &getIterator(): \Generator + { + if ($this->key) { + yield $this->key; + } + yield $this->value; + } +} diff --git a/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/ClosureUseNode.php b/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/ClosureUseNode.php new file mode 100644 index 0000000..bbd02f1 --- /dev/null +++ b/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/ClosureUseNode.php @@ -0,0 +1,38 @@ +byRef ? '&' : '') . $this->var->print($context); + } + + + public function &getIterator(): \Generator + { + yield $this->var; + } +} diff --git a/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/ComplexTypeNode.php b/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/ComplexTypeNode.php new file mode 100644 index 0000000..b6de67a --- /dev/null +++ b/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/ComplexTypeNode.php @@ -0,0 +1,17 @@ +dereferenceExpr($this->expr) + . '[' . ($this->index !== null ? $this->index->print($context) : '') . ']'; + } + + + public function &getIterator(): \Generator + { + yield $this->expr; + if ($this->index) { + yield $this->index; + } + } +} diff --git a/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/ArrayNode.php b/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/ArrayNode.php new file mode 100644 index 0000000..a0068a8 --- /dev/null +++ b/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/ArrayNode.php @@ -0,0 +1,51 @@ + */ + public array $items = [], + public ?Position $position = null, + ) { + (function (ArrayItemNode ...$args) {})(...$items); + } + + + /** @return ArgumentNode[] */ + public function toArguments(): array + { + return array_map(fn(ArrayItemNode $item) => $item->toArgument(), $this->items); + } + + + public function print(PrintContext $context): string + { + return '[' . $context->implode($this->items) . ']'; + } + + + public function &getIterator(): \Generator + { + foreach ($this->items as &$item) { + yield $item; + } + Helpers::removeNulls($this->items); + } +} diff --git a/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/AssignNode.php b/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/AssignNode.php new file mode 100644 index 0000000..87f6bfb --- /dev/null +++ b/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/AssignNode.php @@ -0,0 +1,65 @@ +validate(); + } + + + public function print(PrintContext $context): string + { + $this->validate(); + return $context->parenthesize($this, $this->var, self::AssocLeft) + . ($this->byRef ? ' = &' : ' = ') + . $context->parenthesize($this, $this->expr, self::AssocRight); + } + + + public function getOperatorPrecedence(): array + { + return self::Precedence; + } + + + public function validate(): void + { + if ($this->var instanceof ExpressionNode && !$this->var->isWritable()) { + throw new CompileException('Cannot write to the expression: ' . $this->var->print(new PrintContext), $this->var->position); + } elseif ($this->byRef && !$this->expr->isWritable()) { + throw new CompileException('Cannot take reference to the expression: ' . $this->expr->print(new PrintContext), $this->expr->position); + } + } + + + public function &getIterator(): \Generator + { + yield $this->var; + yield $this->expr; + } +} diff --git a/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/AssignOpNode.php b/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/AssignOpNode.php new file mode 100644 index 0000000..bfaff9b --- /dev/null +++ b/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/AssignOpNode.php @@ -0,0 +1,66 @@ +>', '**', '??']; + + + public function __construct( + public ExpressionNode $var, + public string $operator, + public ExpressionNode $expr, + public ?Position $position = null, + ) { + if (!in_array($this->operator, self::Ops, true)) { + throw new \InvalidArgumentException("Unexpected operator '$this->operator'"); + } + $this->validate(); + } + + + public function print(PrintContext $context): string + { + $this->validate(); + return $context->parenthesize($this, $this->var, self::AssocLeft) + . ' ' . $this->operator . '= ' + . $context->parenthesize($this, $this->expr, self::AssocRight); + } + + + public function getOperatorPrecedence(): array + { + return AssignNode::Precedence; + } + + + public function validate(): void + { + if (!$this->var->isWritable()) { + throw new CompileException('Cannot write to the expression: ' . $this->var->print(new PrintContext), $this->var->position); + } + } + + + public function &getIterator(): \Generator + { + yield $this->var; + yield $this->expr; + } +} diff --git a/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/AuxiliaryNode.php b/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/AuxiliaryNode.php new file mode 100644 index 0000000..75c7b19 --- /dev/null +++ b/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/AuxiliaryNode.php @@ -0,0 +1,42 @@ +print)($context, ...$this->nodes); + } + + + public function &getIterator(): \Generator + { + foreach ($this->nodes as &$node) { + if ($node) { + yield $node; + } + } + } +} diff --git a/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/BinaryOpNode.php b/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/BinaryOpNode.php new file mode 100644 index 0000000..9b0008a --- /dev/null +++ b/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/BinaryOpNode.php @@ -0,0 +1,93 @@ +>', '**', + '==', '!=', '===', '!==', '<=>', '<', '<=', '>', '>=', '??', '|>']; + + + public function __construct( + public ExpressionNode $left, + public string $operator, + public ExpressionNode $right, + public ?Position $position = null, + ) { + if (!in_array(strtolower($this->operator), self::Ops, true)) { + throw new \InvalidArgumentException("Unexpected operator '$this->operator'"); + } + } + + + /** + * Creates nested BinaryOp nodes from a list of expressions. + */ + public static function nest(string $operator, ExpressionNode ...$exprs): ExpressionNode + { + $count = count($exprs); + if ($count < 2) { + return $exprs[0]; + } + + $last = $exprs[0]; + for ($i = 1; $i < $count; $i++) { + $last = new static($last, $operator, $exprs[$i]); + } + + return $last; + } + + + public function print(PrintContext $context): string + { + return $context->parenthesize($this, $this->left, self::AssocLeft) + . ' ' . $this->operator . ' ' + . $context->parenthesize($this, $this->right, self::AssocRight); + } + + + public function getOperatorPrecedence(): array + { + return match (strtolower($this->operator)) { + '**' => [250, self::AssocRight], + '*', '/', '%' => [210, self::AssocLeft], + '+', '-' => [200, self::AssocLeft], + '<<', '>>' => [190, self::AssocLeft], + '.' => [185, self::AssocLeft], + '|>' => [183, self::AssocLeft], + '<', '<=', '>', '>=', '<=>' => [180, self::AssocNone], + '==', '!=', '===', '!==' => [170, self::AssocNone], + '&' => [160, self::AssocLeft], + '^' => [150, self::AssocLeft], + '|' => [140, self::AssocLeft], + '&&' => [130, self::AssocLeft], + '||' => [120, self::AssocLeft], + '??' => [110, self::AssocRight], + 'and' => [50, self::AssocLeft], + 'xor' => [40, self::AssocLeft], + 'or' => [30, self::AssocLeft], + }; + } + + + public function &getIterator(): \Generator + { + yield $this->left; + yield $this->right; + } +} diff --git a/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/CastNode.php b/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/CastNode.php new file mode 100644 index 0000000..5e3926e --- /dev/null +++ b/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/CastNode.php @@ -0,0 +1,50 @@ + 1, 'float' => 1, 'string' => 1, 'array' => 1, 'object' => 1, 'bool' => 1]; + + + public function __construct( + public string $type, + public ExpressionNode $expr, + public ?Position $position = null, + ) { + if (!isset(self::Types[strtolower($this->type)])) { + throw new \InvalidArgumentException("Unexpected type '$this->type'"); + } + } + + + public function print(PrintContext $context): string + { + return '(' . $this->type . ') ' . $context->parenthesize($this, $this->expr, self::AssocRight); + } + + + public function getOperatorPrecedence(): array + { + return [240, self::AssocRight]; + } + + + public function &getIterator(): \Generator + { + yield $this->expr; + } +} diff --git a/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/ClassConstantFetchNode.php b/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/ClassConstantFetchNode.php new file mode 100644 index 0000000..750f03d --- /dev/null +++ b/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/ClassConstantFetchNode.php @@ -0,0 +1,42 @@ +dereferenceExpr($this->class) + . '::' + . $context->objectProperty($this->name); + } + + + public function &getIterator(): \Generator + { + yield $this->class; + yield $this->name; + } +} diff --git a/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/CloneNode.php b/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/CloneNode.php new file mode 100644 index 0000000..ff24050 --- /dev/null +++ b/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/CloneNode.php @@ -0,0 +1,43 @@ +expr->print($context); + } + + + public function getOperatorPrecedence(): array + { + return [270, self::AssocNone]; + } + + + public function &getIterator(): \Generator + { + yield $this->expr; + } +} diff --git a/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/ClosureNode.php b/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/ClosureNode.php new file mode 100644 index 0000000..eb5423c --- /dev/null +++ b/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/ClosureNode.php @@ -0,0 +1,77 @@ +expr; + foreach ($this->uses as $use) { + $arrow = $arrow && !$use->byRef; + } + + return $arrow + ? 'fn' . ($this->byRef ? '&' : '') + . '(' . $context->implode($this->params) . ')' + . ($this->returnType !== null ? ': ' . $this->returnType->print($context) : '') + . ' => ' + . $this->expr->print($context) + : 'function ' . ($this->byRef ? '&' : '') + . '(' . $context->implode($this->params) . ')' + . (!empty($this->uses) ? ' use (' . $context->implode($this->uses) . ')' : '') + . ($this->returnType !== null ? ' : ' . $this->returnType->print($context) : '') + . ($this->expr ? ' { return ' . $this->expr->print($context) . '; }' : ' {}'); + } + + + public function &getIterator(): \Generator + { + foreach ($this->params as &$item) { + yield $item; + } + Helpers::removeNulls($this->params); + + foreach ($this->uses as &$item) { + yield $item; + } + Helpers::removeNulls($this->uses); + + if ($this->returnType) { + yield $this->returnType; + } + if ($this->expr) { + yield $this->expr; + } + } +} diff --git a/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/ConstantFetchNode.php b/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/ConstantFetchNode.php new file mode 100644 index 0000000..bf3af62 --- /dev/null +++ b/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/ConstantFetchNode.php @@ -0,0 +1,45 @@ +name->kind === NameNode::KindNormal) { + return match ((string) $this->name) { + '__LINE__' => (string) $this->position->line, + '__FILE__' => '(is_file($this->getName()) ? $this->getName() : null)', + '__DIR__' => '(is_file($this->getName()) ? dirname($this->getName()) : null)', + default => $this->name->print($context), + }; + } + return $this->name->print($context); + } + + + public function &getIterator(): \Generator + { + yield $this->name; + } +} diff --git a/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/EmptyNode.php b/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/EmptyNode.php new file mode 100644 index 0000000..ee25e35 --- /dev/null +++ b/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/EmptyNode.php @@ -0,0 +1,36 @@ +expr->print($context) . ')'; + } + + + public function &getIterator(): \Generator + { + yield $this->expr; + } +} diff --git a/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/FilterCallNode.php b/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/FilterCallNode.php new file mode 100644 index 0000000..855bdac --- /dev/null +++ b/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/FilterCallNode.php @@ -0,0 +1,44 @@ +expr) { + array_unshift($filters, $node->filter); + } + + return Php\FilterNode::printSimple($context, $filters, $node->print($context)); + } + + + public function &getIterator(): \Generator + { + yield $this->expr; + yield $this->filter; + } +} diff --git a/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/FunctionCallNode.php b/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/FunctionCallNode.php new file mode 100644 index 0000000..b91baeb --- /dev/null +++ b/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/FunctionCallNode.php @@ -0,0 +1,53 @@ + */ + public array $args = [], + public ?Position $position = null, + ) { + (function (Php\ArgumentNode|Php\VariadicPlaceholderNode ...$args) {})(...$args); + } + + + public function isPartialFunction(): bool + { + return ($this->args[0] ?? null) instanceof Php\VariadicPlaceholderNode; + } + + + public function print(PrintContext $context): string + { + return $context->callExpr($this->name) + . '(' . $context->implode($this->args) . ')'; + } + + + public function &getIterator(): \Generator + { + yield $this->name; + foreach ($this->args as &$item) { + yield $item; + } + Helpers::removeNulls($this->args); + } +} diff --git a/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/InNode.php b/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/InNode.php new file mode 100644 index 0000000..dfa1871 --- /dev/null +++ b/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/InNode.php @@ -0,0 +1,42 @@ +needle->print($context) + . ', ' + . $this->haystack->print($context) + . ', true)'; + } + + + public function &getIterator(): \Generator + { + yield $this->needle; + yield $this->haystack; + } +} diff --git a/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/InstanceofNode.php b/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/InstanceofNode.php new file mode 100644 index 0000000..46aa77e --- /dev/null +++ b/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/InstanceofNode.php @@ -0,0 +1,48 @@ +parenthesize($this, $this->expr, self::AssocLeft) + . ' instanceof ' + . $context->dereferenceExpr($this->class); + } + + + public function getOperatorPrecedence(): array + { + return [230, self::AssocNone]; + } + + + public function &getIterator(): \Generator + { + yield $this->expr; + yield $this->class; + } +} diff --git a/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/IssetNode.php b/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/IssetNode.php new file mode 100644 index 0000000..4b44eb4 --- /dev/null +++ b/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/IssetNode.php @@ -0,0 +1,56 @@ +validate(); + } + + + public function print(PrintContext $context): string + { + $this->validate(); + return 'isset(' . $context->implode($this->vars) . ')'; + } + + + public function validate(): void + { + foreach ($this->vars as $var) { + if (!$var instanceof ExpressionNode) { + throw new \TypeError('Variable must be ExpressionNode, ' . get_debug_type($var) . ' given.'); + } elseif (!$var->isVariable()) { + throw new CompileException('Cannot use isset() on expression: ' . $var->print(new PrintContext), $var->position); + } + } + } + + + public function &getIterator(): \Generator + { + foreach ($this->vars as &$item) { + yield $item; + } + Helpers::removeNulls($this->vars); + } +} diff --git a/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/MatchNode.php b/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/MatchNode.php new file mode 100644 index 0000000..58f1e7e --- /dev/null +++ b/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/MatchNode.php @@ -0,0 +1,51 @@ +cond->print($context) . ') {'; + foreach ($this->arms as $node) { + $res .= "\n" . $node->print($context) . ','; + } + + $res .= "\n}"; + return $res; + } + + + public function &getIterator(): \Generator + { + yield $this->cond; + foreach ($this->arms as &$item) { + yield $item; + } + Helpers::removeNulls($this->arms); + } +} diff --git a/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/MethodCallNode.php b/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/MethodCallNode.php new file mode 100644 index 0000000..83e197c --- /dev/null +++ b/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/MethodCallNode.php @@ -0,0 +1,62 @@ + */ + public array $args = [], + public bool $nullsafe = false, + public ?Position $position = null, + ) { + (function (Php\ArgumentNode|Php\VariadicPlaceholderNode ...$args) {})(...$args); + } + + + public function isPartialFunction(): bool + { + return ($this->args[0] ?? null) instanceof Php\VariadicPlaceholderNode; + } + + + public function print(PrintContext $context): string + { + if ($this->nullsafe && $this->isPartialFunction()) { + throw new CompileException('Cannot combine nullsafe operator with Closure creation', $this->position); + } + return $context->dereferenceExpr($this->object) + . ($this->nullsafe ? '?->' : '->') + . $context->objectProperty($this->name) + . '(' . $context->implode($this->args) . ')'; + } + + + public function &getIterator(): \Generator + { + yield $this->object; + yield $this->name; + foreach ($this->args as &$item) { + yield $item; + } + Helpers::removeNulls($this->args); + } +} diff --git a/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/NewNode.php b/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/NewNode.php new file mode 100644 index 0000000..b7a73f9 --- /dev/null +++ b/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/NewNode.php @@ -0,0 +1,54 @@ +dereferenceExpr($this->class) + . ($this->args ? '(' . $context->implode($this->args) . ')' : ''); + } + + + public function getOperatorPrecedence(): array + { + return [270, self::AssocNone]; + } + + + public function &getIterator(): \Generator + { + yield $this->class; + foreach ($this->args as &$item) { + yield $item; + } + Helpers::removeNulls($this->args); + } +} diff --git a/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/PostOpNode.php b/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/PostOpNode.php new file mode 100644 index 0000000..ec3fe31 --- /dev/null +++ b/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/PostOpNode.php @@ -0,0 +1,61 @@ + 1, '--' => 1]; + + + public function __construct( + public ExpressionNode $var, + public string $operator, + public ?Position $position = null, + ) { + if (!isset(self::Ops[$this->operator])) { + throw new \InvalidArgumentException("Unexpected operator '$this->operator'"); + } + $this->validate(); + } + + + public function print(PrintContext $context): string + { + $this->validate(); + return $context->parenthesize($this, $this->var, self::AssocLeft) . $this->operator; + } + + + public function getOperatorPrecedence(): array + { + return [240, self::AssocLeft]; + } + + + public function validate(): void + { + if (!$this->var->isWritable()) { + throw new CompileException('Cannot write to the expression: ' . $this->var->print(new PrintContext), $this->var->position); + } + } + + + public function &getIterator(): \Generator + { + yield $this->var; + } +} diff --git a/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/PreOpNode.php b/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/PreOpNode.php new file mode 100644 index 0000000..d671295 --- /dev/null +++ b/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/PreOpNode.php @@ -0,0 +1,61 @@ + 1, '--' => 1]; + + + public function __construct( + public ExpressionNode $var, + public string $operator, + public ?Position $position = null, + ) { + if (!isset(self::Ops[$this->operator])) { + throw new \InvalidArgumentException("Unexpected operator '$this->operator'"); + } + $this->validate(); + } + + + public function print(PrintContext $context): string + { + $this->validate(); + return $this->operator . $context->parenthesize($this, $this->var, self::AssocRight); + } + + + public function getOperatorPrecedence(): array + { + return [240, self::AssocRight]; + } + + + public function validate(): void + { + if (!$this->var->isWritable()) { + throw new CompileException('Cannot write to the expression: ' . $this->var->print(new PrintContext), $this->var->position); + } + } + + + public function &getIterator(): \Generator + { + yield $this->var; + } +} diff --git a/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/PropertyFetchNode.php b/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/PropertyFetchNode.php new file mode 100644 index 0000000..9b2a731 --- /dev/null +++ b/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/PropertyFetchNode.php @@ -0,0 +1,42 @@ +dereferenceExpr($this->object) + . ($this->nullsafe ? '?->' : '->') + . $context->objectProperty($this->name); + } + + + public function &getIterator(): \Generator + { + yield $this->object; + yield $this->name; + } +} diff --git a/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/StaticMethodCallNode.php b/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/StaticMethodCallNode.php new file mode 100644 index 0000000..27380c2 --- /dev/null +++ b/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/StaticMethodCallNode.php @@ -0,0 +1,63 @@ + */ + public array $args = [], + public ?Position $position = null, + ) { + (function (Php\ArgumentNode|Php\VariadicPlaceholderNode ...$args) {})(...$args); + } + + + public function isPartialFunction(): bool + { + return ($this->args[0] ?? null) instanceof Php\VariadicPlaceholderNode; + } + + + public function print(PrintContext $context): string + { + $name = match (true) { + $this->name instanceof VariableNode => $this->name->print($context), + $this->name instanceof ExpressionNode => '{' . $this->name->print($context) . '}', + default => $this->name, + }; + return $context->dereferenceExpr($this->class) + . '::' + . $name + . '(' . $context->implode($this->args) . ')'; + } + + + public function &getIterator(): \Generator + { + yield $this->class; + yield $this->name; + foreach ($this->args as &$item) { + yield $item; + } + Helpers::removeNulls($this->args); + } +} diff --git a/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/StaticPropertyFetchNode.php b/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/StaticPropertyFetchNode.php new file mode 100644 index 0000000..63a3fe7 --- /dev/null +++ b/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/StaticPropertyFetchNode.php @@ -0,0 +1,42 @@ +dereferenceExpr($this->class) + . '::$' + . $context->objectProperty($this->name); + } + + + public function &getIterator(): \Generator + { + yield $this->class; + yield $this->name; + } +} diff --git a/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/TemporaryNode.php b/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/TemporaryNode.php new file mode 100644 index 0000000..6e87e2a --- /dev/null +++ b/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/TemporaryNode.php @@ -0,0 +1,38 @@ +parenthesize($this, $this->cond, self::AssocLeft) + . ($this->if ? ' ? ' . $this->if->print($context) . ' : ' : ' ?: ') + . $context->parenthesize($this, $this->else ?? new NullNode, self::AssocRight); + } + + + public function getOperatorPrecedence(): array + { + return [100, self::AssocNone]; + } + + + public function &getIterator(): \Generator + { + yield $this->cond; + if ($this->if) { + yield $this->if; + } + if ($this->else) { + yield $this->else; + } + } +} diff --git a/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/UnaryOpNode.php b/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/UnaryOpNode.php new file mode 100644 index 0000000..dabe42b --- /dev/null +++ b/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/UnaryOpNode.php @@ -0,0 +1,54 @@ + 1, '-' => 1, '~' => 1, '@' => 1, '!' => 1]; + + + public function __construct( + public ExpressionNode $expr, + public string $operator, + public ?Position $position = null, + ) { + if (!isset(self::Ops[$this->operator])) { + throw new \InvalidArgumentException("Unexpected operator '$this->operator'"); + } + } + + + public function print(PrintContext $context): string + { + $pos = $this->expr instanceof self || $this->expr instanceof PreOpNode ? self::AssocLeft : self::AssocRight; // Enforce -(-$expr) instead of --$expr + return $this->operator . $context->parenthesize($this, $this->expr, $pos); + } + + + public function getOperatorPrecedence(): array + { + return match ($this->operator) { + '+', '-', '~', '@' => [240, self::AssocRight], + '!' => [220, self::AssocRight], + }; + } + + + public function &getIterator(): \Generator + { + yield $this->expr; + } +} diff --git a/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/VariableNode.php b/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/VariableNode.php new file mode 100644 index 0000000..47e02c6 --- /dev/null +++ b/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/VariableNode.php @@ -0,0 +1,40 @@ +name instanceof ExpressionNode + ? '${' . $this->name->print($context) . '}' + : '$' . $this->name; + } + + + public function &getIterator(): \Generator + { + if ($this->name instanceof ExpressionNode) { + yield $this->name; + } + } +} diff --git a/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/ExpressionNode.php b/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/ExpressionNode.php new file mode 100644 index 0000000..e8d4f53 --- /dev/null +++ b/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/ExpressionNode.php @@ -0,0 +1,41 @@ +nullsafe) + || $this instanceof Expression\StaticPropertyFetchNode + || $this instanceof Expression\VariableNode; + } + + + public function isVariable(): bool + { + return $this instanceof Expression\ArrayAccessNode + || $this instanceof Expression\PropertyFetchNode + || $this instanceof Expression\StaticPropertyFetchNode + || $this instanceof Expression\VariableNode; + } + + + public function isCall(): bool + { + return $this instanceof Expression\FunctionCallNode + || $this instanceof Expression\MethodCallNode + || $this instanceof Expression\StaticMethodCallNode; + } +} diff --git a/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/FilterNode.php b/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/FilterNode.php new file mode 100644 index 0000000..7ec0dde --- /dev/null +++ b/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/FilterNode.php @@ -0,0 +1,86 @@ +name === 'escape') { + throw new CompileException("Filter 'escape' is not allowed.", $position); + } + (function (ArgumentNode ...$args) {})(...$args); + } + + + public function print(PrintContext $context): string + { + throw new \LogicException('Cannot directly print FilterNode'); + } + + + /** @param self[] $filters */ + public static function printSimple(PrintContext $context, array $filters, string $expr): string + { + $nullsafe = false; + $chain = $expr; + $tmp = '$ʟ_tmp'; + foreach ($filters as $filter) { + if ($filter->nullsafe) { + $expr = $nullsafe ? "(($tmp = $expr) === null ? null : $chain)" : $chain; + $chain = $tmp; + $nullsafe = true; + } + + $chain = '($this->filters->' . $context->objectProperty($filter->name) . ')(' + . $chain + . ($filter->args ? ', ' . $context->implode($filter->args) : '') + . ')'; + } + + return $nullsafe ? "(($tmp = $expr) === null ? null : $chain)" : $chain; + } + + + public function printContentAware(PrintContext $context, string $expr): string + { + if ($this->nullsafe) { + throw new CompileException('Content-aware filter cannot be nullsafe.', $this->position); + } + return '$this->filters->filterContent(' + . $context->encodeString($this->name->name) + . ', $ʟ_fi, ' + . $expr + . ($this->args ? ', ' . $context->implode($this->args) : '') + . ')'; + } + + + public function &getIterator(): \Generator + { + yield $this->name; + foreach ($this->args as &$item) { + yield $item; + } + Helpers::removeNulls($this->args); + } +} diff --git a/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/IdentifierNode.php b/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/IdentifierNode.php new file mode 100644 index 0000000..539fed3 --- /dev/null +++ b/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/IdentifierNode.php @@ -0,0 +1,42 @@ +name; + } + + + public function print(PrintContext $context): string + { + return $this->name; + } + + + public function &getIterator(): \Generator + { + false && yield; + } +} diff --git a/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/InterpolatedStringPartNode.php b/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/InterpolatedStringPartNode.php new file mode 100644 index 0000000..c662864 --- /dev/null +++ b/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/InterpolatedStringPartNode.php @@ -0,0 +1,36 @@ + */ + public array $types, + public ?Position $position = null, + ) { + (function (IdentifierNode|NameNode ...$args) {})(...$types); + } + + + public function print(PrintContext $context): string + { + return $context->implode($this->types, '&'); + } + + + public function &getIterator(): \Generator + { + foreach ($this->types as &$item) { + yield $item; + } + Helpers::removeNulls($this->types); + } +} diff --git a/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/ListItemNode.php b/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/ListItemNode.php new file mode 100644 index 0000000..0352824 --- /dev/null +++ b/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/ListItemNode.php @@ -0,0 +1,48 @@ +key instanceof ExpressionNode => $this->key->print($context) . ' => ', + $this->key instanceof IdentifierNode => $context->encodeString($this->key->name) . ' => ', + $this->key === null => '', + }; + return $key + . ($this->byRef ? '&' : '') + . $this->value->print($context); + } + + + public function &getIterator(): \Generator + { + if ($this->key) { + yield $this->key; + } + yield $this->value; + } +} diff --git a/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/ListNode.php b/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/ListNode.php new file mode 100644 index 0000000..02c08b8 --- /dev/null +++ b/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/ListNode.php @@ -0,0 +1,56 @@ + */ + public array $items = [], + public ?Position $position = null, + ) { + $this->validate(); + } + + + public function print(PrintContext $context): string + { + $this->validate(); + return '[' . $context->implode($this->items) . ']'; + } + + + public function validate(): void + { + foreach ($this->items as $item) { + if ($item !== null && !$item instanceof ListItemNode) { + throw new \TypeError('Item must be null or ListItemNode, ' . get_debug_type($item) . ' given.'); + } elseif ($item?->value instanceof ExpressionNode && !$item->value->isWritable()) { + throw new CompileException('Cannot write to the expression: ' . $item->value->print(new PrintContext), $item->value->position); + } + } + } + + + public function &getIterator(): \Generator + { + foreach ($this->items as &$item) { + if ($item) { + yield $item; + } + } + } +} diff --git a/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/MatchArmNode.php b/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/MatchArmNode.php new file mode 100644 index 0000000..34311c6 --- /dev/null +++ b/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/MatchArmNode.php @@ -0,0 +1,47 @@ +conds ? $context->implode($this->conds) : 'default') + . ' => ' + . $this->body->print($context); + } + + + public function &getIterator(): \Generator + { + if ($this->conds) { + foreach ($this->conds as &$item) { + yield $item; + } + Helpers::removeNulls($this->conds); + } + yield $this->body; + } +} diff --git a/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/ModifierNode.php b/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/ModifierNode.php new file mode 100644 index 0000000..b47c8f8 --- /dev/null +++ b/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/ModifierNode.php @@ -0,0 +1,94 @@ +filters as $filter) { + if ($filter->name->name === $name) { + return true; + } + } + + return false; + } + + + public function removeFilter(string $name): ?FilterNode + { + foreach ($this->filters as $i => $filter) { + if ($filter->name->name === $name) { + return array_splice($this->filters, $i, 1)[0]; + } + } + + return null; + } + + + public function print(PrintContext $context): string + { + throw new \LogicException('Cannot directly print ModifierNode'); + } + + + public function printSimple(PrintContext $context, string $expr): string + { + $expr = FilterNode::printSimple($context, $this->filters, $expr); + + $escaper = $context->getEscaper(); + return $this->escape + ? $escaper->escape($expr) + : $escaper->escapeMandatory($expr, $this->position); + } + + + public function printContentAware(PrintContext $context, string $expr): string + { + foreach ($this->filters as $filter) { + $expr = $filter->printContentAware($context, $expr); + } + + return $this->escape + ? $context->getEscaper()->escapeContent($expr) + : $expr; + } + + + public function &getIterator(): \Generator + { + foreach ($this->filters as &$filter) { + yield $filter; + } + Helpers::removeNulls($this->filters); + } +} diff --git a/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/NameNode.php b/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/NameNode.php new file mode 100644 index 0000000..52a9e9d --- /dev/null +++ b/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/NameNode.php @@ -0,0 +1,89 @@ +kind = self::KindFullyQualified; + $this->name = substr($name, 1); + } else { + if ($kind === -1 && !str_starts_with($name, '__')) { + trigger_error("Using unqualified constant '$name' is deprecated. Use '\\$name' with a leading backslash $position", E_USER_DEPRECATED); + } + $this->kind = self::KindNormal; + } + } + + + public function isKeyword(): bool + { + static $keywords; + $keywords ??= array_flip([ // https://www.php.net/manual/en/reserved.keywords.php + '__halt_compiler', '__class__', '__dir__', '__file__', '__function__', '__line__', '__method__', '__namespace__', '__trait__', + 'abstract', 'and', 'array', 'as', 'break', 'callable', 'case', 'catch', 'class', 'const', 'continue', 'declare', + 'default', 'die', 'do', 'echo', 'else', 'elseif', 'empty', 'enddeclare', 'endfor', 'endforeach', 'endif', 'endswitch', + 'endwhile', 'eval', 'exit', 'extends', 'final', 'finally', 'fn', 'for', 'foreach', 'function', 'global', 'goto', 'if', + 'implements', 'include', 'include_once', 'instanceof', 'insteadof', 'interface', 'isset', 'list', 'match', 'namespace', + 'new', 'or', 'print', 'private', 'protected', 'public', 'readonly', 'require', 'require_once', 'return', 'static', + 'switch', 'throw', 'trait', 'try', 'unset', 'use', 'var', 'while', 'xor', 'yield', + 'parent', 'self', 'mixed', 'void', 'enum', // extra + ]); + return isset($keywords[strtolower($this->name)]); + } + + + public function print(PrintContext $context): string + { + return $this->toCodeString(); + } + + + public function __toString(): string + { + return $this->name; + } + + + public function toCodeString(): string + { + $prefix = match ($this->kind) { + self::KindNormal => $this->isKeyword() ? 'namespace\\' : '', + self::KindFullyQualified => '\\', + }; + return $prefix . $this->name; + } + + + public function &getIterator(): \Generator + { + false && yield; + } +} diff --git a/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/NullableTypeNode.php b/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/NullableTypeNode.php new file mode 100644 index 0000000..4eec7b5 --- /dev/null +++ b/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/NullableTypeNode.php @@ -0,0 +1,35 @@ +type->print($context); + } + + + public function &getIterator(): \Generator + { + yield $this->type; + } +} diff --git a/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/OperatorNode.php b/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/OperatorNode.php new file mode 100644 index 0000000..d1bd16b --- /dev/null +++ b/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/OperatorNode.php @@ -0,0 +1,29 @@ +type ? $this->type->print($context) . ' ' : '') + . ($this->byRef ? '&' : '') + . ($this->variadic ? '...' : '') + . $this->var->print($context) + . ($this->default ? ' = ' . $this->default->print($context) : ''); + } + + + public function &getIterator(): \Generator + { + if ($this->type) { + yield $this->type; + } + yield $this->var; + if ($this->default) { + yield $this->default; + } + } +} diff --git a/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Scalar/BooleanNode.php b/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Scalar/BooleanNode.php new file mode 100644 index 0000000..1a2b124 --- /dev/null +++ b/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Scalar/BooleanNode.php @@ -0,0 +1,30 @@ +value ? 'true' : 'false'; + } +} diff --git a/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Scalar/FloatNode.php b/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Scalar/FloatNode.php new file mode 100644 index 0000000..c803617 --- /dev/null +++ b/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Scalar/FloatNode.php @@ -0,0 +1,65 @@ +value)) { + if ($this->value === INF) { + return '\INF'; + } elseif ($this->value === -INF) { + return '-\INF'; + } else { + return '\NAN'; + } + } + + // Try to find a short full-precision representation + $stringValue = sprintf('%.16G', $this->value); + if ($this->value !== (float) $stringValue) { + $stringValue = sprintf('%.17G', $this->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; + } +} diff --git a/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Scalar/IntegerNode.php b/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Scalar/IntegerNode.php new file mode 100644 index 0000000..ad77a0b --- /dev/null +++ b/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Scalar/IntegerNode.php @@ -0,0 +1,71 @@ +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)'; + + } elseif ($this->kind === self::KindDecimal) { + return (string) $this->value; + } + + if ($this->value < 0) { + $sign = '-'; + $str = (string) -$this->value; + } else { + $sign = ''; + $str = (string) $this->value; + } + + return match ($this->kind) { + self::KindBinary => $sign . '0b' . base_convert($str, 10, 2), + self::KindOctal => $sign . '0' . base_convert($str, 10, 8), + self::KindHexa => $sign . '0x' . base_convert($str, 10, 16), + default => throw new \Exception('Invalid number kind'), + }; + } +} diff --git a/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Scalar/InterpolatedStringNode.php b/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Scalar/InterpolatedStringNode.php new file mode 100644 index 0000000..39d3ec9 --- /dev/null +++ b/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Scalar/InterpolatedStringNode.php @@ -0,0 +1,77 @@ + */ + public array $parts, + public ?Position $position = null, + ) { + } + + + /** @param array $parts */ + public static function parse(array $parts, Position $position): static + { + foreach ($parts as $part) { + if ($part instanceof InterpolatedStringPartNode) { + $part->value = PhpHelpers::decodeEscapeSequences($part->value, '"'); + } + } + + return new static($parts, $position); + } + + + public function print(PrintContext $context): string + { + $s = ''; + $expr = false; + foreach ($this->parts as $part) { + if ($part instanceof InterpolatedStringPartNode) { + $s .= substr($context->encodeString($part->value, '"'), 1, -1); + continue; + } + + $partStr = $part->print($context); + if ($partStr[0] === '$' && $part->isVariable()) { + $s .= '{' . $partStr . '}'; + } else { + $s .= '" . (' . $partStr . ') . "'; + $expr = true; + } + } + + return $expr + ? '("' . $s . '")' + : '"' . $s . '"'; + } + + + public function &getIterator(): \Generator + { + foreach ($this->parts as &$item) { + yield $item; + } + Helpers::removeNulls($this->parts); + } +} diff --git a/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Scalar/NullNode.php b/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Scalar/NullNode.php new file mode 100644 index 0000000..9ff78cf --- /dev/null +++ b/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Scalar/NullNode.php @@ -0,0 +1,29 @@ + '\\', "\\'" => "'"]) + : PhpHelpers::decodeEscapeSequences(substr($str, 1, -1), '"'); + return new static($str, $position); + } + + + public function print(PrintContext $context): string + { + return $context->encodeString($this->value); + } +} diff --git a/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/ScalarNode.php b/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/ScalarNode.php new file mode 100644 index 0000000..764cbbb --- /dev/null +++ b/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/ScalarNode.php @@ -0,0 +1,19 @@ + */ + public array $types, + public ?Position $position = null, + ) { + (function (IdentifierNode|NameNode ...$args) {})(...$types); + } + + + public function print(PrintContext $context): string + { + return $context->implode($this->types, '|'); + } + + + public function &getIterator(): \Generator + { + foreach ($this->types as &$item) { + yield $item; + } + Helpers::removeNulls($this->types); + } +} diff --git a/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/VarLikeIdentifierNode.php b/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/VarLikeIdentifierNode.php new file mode 100644 index 0000000..9f59981 --- /dev/null +++ b/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/VarLikeIdentifierNode.php @@ -0,0 +1,21 @@ +name; + } +} diff --git a/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/VariadicPlaceholderNode.php b/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/VariadicPlaceholderNode.php new file mode 100644 index 0000000..4eccbae --- /dev/null +++ b/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/VariadicPlaceholderNode.php @@ -0,0 +1,35 @@ +outputMode = $tag::OutputKeepIndentation; + $tag->expectArguments(); + $node = new static; + $node->expression = $tag->parser->parseExpression(); + $node->modifier = $tag->parser->parseModifier(); + $node->modifier->escape = !$node->modifier->removeFilter('noescape'); + return $node; + } + + + public function print(PrintContext $context): string + { + return $context->format( + "echo %modify(%node) %line;\n", + $this->modifier, + $this->expression, + $this->position, + ); + } + + + public function &getIterator(): \Generator + { + yield $this->expression; + yield $this->modifier; + } +} + + +class_alias(PrintNode::class, Latte\Essential\Nodes\PrintNode::class); diff --git a/vendor/latte/latte/src/Latte/Compiler/Nodes/StatementNode.php b/vendor/latte/latte/src/Latte/Compiler/Nodes/StatementNode.php new file mode 100644 index 0000000..ce877b0 --- /dev/null +++ b/vendor/latte/latte/src/Latte/Compiler/Nodes/StatementNode.php @@ -0,0 +1,15 @@ +head; + yield $this->main; + } +} diff --git a/vendor/latte/latte/src/Latte/Compiler/Nodes/TextNode.php b/vendor/latte/latte/src/Latte/Compiler/Nodes/TextNode.php new file mode 100644 index 0000000..a8c9f1b --- /dev/null +++ b/vendor/latte/latte/src/Latte/Compiler/Nodes/TextNode.php @@ -0,0 +1,44 @@ +content === '' + ? '' + : 'echo ' . var_export($this->content, true) . ";\n"; + } + + + public function isWhitespace(): bool + { + return trim($this->content) === ''; + } + + + public function &getIterator(): \Generator + { + false && yield; + } +} diff --git a/vendor/latte/latte/src/Latte/Compiler/PhpHelpers.php b/vendor/latte/latte/src/Latte/Compiler/PhpHelpers.php new file mode 100644 index 0000000..d58241a --- /dev/null +++ b/vendor/latte/latte/src/Latte/Compiler/PhpHelpers.php @@ -0,0 +1,263 @@ + $token) { + $next = $tokens[$n + 1] ?? [null, '']; + + if (is_array($token)) { + [$name, $token] = $token; + if ($name === T_ELSE || $name === T_ELSEIF) { + if ($next === ':' && $lastChar === '}') { + $res .= ';'; // semicolon needed in if(): ... if() ... else: + } + + $lastChar = ''; + $res .= $token; + + } elseif ($name === T_DOC_COMMENT || $name === T_COMMENT) { + $res .= preg_replace("#\n[ \t]*+(?!\n)#", "\n" . str_repeat("\t", $level), $token); + + } elseif ($name === T_WHITESPACE) { + $prev = $tokens[$n - 1]; + $lines = substr_count($token, "\n"); + if ($prev === '}' && in_array($next[0], [T_ELSE, T_ELSEIF, T_CATCH, T_FINALLY], true)) { + $token = ' '; + } elseif ($prev === '{' || $prev === '}' || $prev === ';' || $lines) { + $token = str_repeat("\n", max(1, $lines)) . str_repeat("\t", $level); // indent last line + } elseif ($prev[0] === T_OPEN_TAG) { + $token = ''; + } + + $res .= $token; + + } elseif ($name === T_OBJECT_OPERATOR) { + $lastChar = '->'; + $res .= $token; + + } elseif ($name === T_OPEN_TAG) { + $res .= " $v) { + $s .= $multiline + ? ($s === '' ? "\n" : '') . "\t" . ($indexed ? '' : self::dump($k) . ' => ') . self::dump($v) . ",\n" + : ($s === '' ? '' : ', ') . ($indexed ? '' : self::dump($k) . ' => ') . self::dump($v); + } + + return '[' . $s . ']'; + } elseif ($value === null) { + return 'null'; + } else { + return var_export($value, true); + } + } + + + public static function optimizeEcho(string $source): string + { + $res = ''; + $tokens = token_get_all($source); + $start = null; + + for ($i = 0; $i < count($tokens); $i++) { + $token = $tokens[$i]; + if ($token[0] === T_ECHO) { + if (!$start) { + $str = ''; + $start = strlen($res); + } + + } elseif ($start && $token[0] === T_CONSTANT_ENCAPSED_STRING && $token[1][0] === "'") { + $str .= stripslashes(substr($token[1], 1, -1)); + + } elseif ($start && $token === ';') { + if ($str !== '') { + $res = substr_replace( + $res, + 'echo ' . ($str === "\n" ? '"\n"' : var_export($str, true)), + $start, + strlen($res) - $start, + ); + } + + } elseif ($token[0] !== T_WHITESPACE) { + $start = null; + } + + $res .= is_array($token) ? $token[1] : $token; + } + + return $res; + } + + + public static function decodeNumber(string $str, &$base = null): int|float|null + { + $str = str_replace('_', '', $str); + + if ($str[0] !== '0' || $str === '0') { + $base = 10; + return $str + 0; + } elseif ($str[1] === 'x' || $str[1] === 'X') { + $base = 16; + return hexdec($str); + } elseif ($str[1] === 'b' || $str[1] === 'B') { + $base = 2; + return bindec($str); + } elseif (strpbrk($str, '89')) { + return null; + } else { + $base = 8; + return octdec($str); + } + } + + + public static function decodeEscapeSequences(string $str, ?string $quote): string + { + if ($quote !== null) { + $str = str_replace('\\' . $quote, $quote, $str); + } + + return preg_replace_callback( + '~\\\([\\\$nrtfve]|[xX][0-9a-fA-F]{1,2}|[0-7]{1,3}|u\{([0-9a-fA-F]+)\})~', + function ($matches) { + $ch = $matches[1]; + $replacements = [ + '\\' => '\\', + '$' => '$', + 'n' => "\n", + 'r' => "\r", + 't' => "\t", + 'f' => "\f", + 'v' => "\v", + 'e' => "\x1B", + ]; + if (isset($replacements[$ch])) { + return $replacements[$ch]; + } elseif ($ch[0] === 'x' || $ch[0] === 'X') { + return chr(hexdec(substr($ch, 1))); + } elseif ($ch[0] === 'u') { + return self::codePointToUtf8(hexdec($matches[2])); + } else { + $num = octdec($ch); + if ($num > 255) { + throw new CompileException("Octal escape sequence \\$ch is greater than \\377"); + } + return chr($num); + } + }, + $str, + ); + } + + + private static function codePointToUtf8(int $num): string + { + return match (true) { + $num <= 0x7F => chr($num), + $num <= 0x7FF => chr(($num >> 6) + 0xC0) . chr(($num & 0x3F) + 0x80), + $num <= 0xFFFF => chr(($num >> 12) + 0xE0) . chr((($num >> 6) & 0x3F) + 0x80) . chr(($num & 0x3F) + 0x80), + $num <= 0x1FFFFF => chr(($num >> 18) + 0xF0) . chr((($num >> 12) & 0x3F) + 0x80) + . chr((($num >> 6) & 0x3F) + 0x80) . chr(($num & 0x3F) + 0x80), + default => throw new CompileException('Invalid UTF-8 codepoint escape sequence: Codepoint too large'), + }; + } + + + public static function checkCode(string $phpBinary, string $code, string $name): void + { + $process = proc_open( + $phpBinary . ' -l -n', + [['pipe', 'r'], ['pipe', 'w'], ['pipe', 'w']], + $pipes, + null, + null, + ['bypass_shell' => true], + ); + if (!is_resource($process)) { + throw new CompileException('Unable to check that the generated PHP is correct.'); + } + + fwrite($pipes[0], $code); + fclose($pipes[0]); + $error = stream_get_contents($pipes[1]); + if (!proc_close($process)) { + return; + } + $error = strip_tags(explode("\n", $error)[1]); + $position = preg_match('~ on line (\d+)~', $error, $m) + ? new Position((int) $m[1], 0) + : null; + $error = preg_replace('~(^Fatal error: | in Standard input code| on line \d+)~', '', $error); + throw (new CompileException('Error in generated code: ' . trim($error), $position)) + ->setSource($code, $name); + } +} diff --git a/vendor/latte/latte/src/Latte/Compiler/Position.php b/vendor/latte/latte/src/Latte/Compiler/Position.php new file mode 100644 index 0000000..8c5d344 --- /dev/null +++ b/vendor/latte/latte/src/Latte/Compiler/Position.php @@ -0,0 +1,47 @@ +line + $lines, + strlen($str) - strrpos($str, "\n"), + $this->offset + strlen($str), + ); + } else { + return new self( + $this->line, + $this->column + strlen($str), + $this->offset + strlen($str), + ); + } + } + + + public function __toString(): string + { + return "on line $this->line" . ($this->column ? " at column $this->column" : ''); + } +} diff --git a/vendor/latte/latte/src/Latte/Compiler/PrintContext.php b/vendor/latte/latte/src/Latte/Compiler/PrintContext.php new file mode 100644 index 0000000..d7a3f35 --- /dev/null +++ b/vendor/latte/latte/src/Latte/Compiler/PrintContext.php @@ -0,0 +1,288 @@ +escaperStack[] = new Escaper($contentType); + } + + + /** + * Expands %node, %dump, %raw, %args, %line, %escape(), %modify(), %modifyContent() in code. + */ + public function format(string $mask, mixed ...$args): string + { + $pos = 0; // enumerate arguments except for %escape + $mask = preg_replace_callback( + '#%([a-z]{3,})#i', + function ($m) use (&$pos) { + return $m[1] === 'escape' + ? '%0.escape' + : '%' . ($pos++) . '.' . $m[1]; + }, + $mask, + ); + + $mask = preg_replace_callback( + '#% (\d+) \. (escape|modify(?:Content)?) ( \( ([^()]*+|(?-2))+ \) )#xi', + function ($m) use ($args) { + [, $pos, $fn, $var] = $m; + $var = substr($var, 1, -1); + /** @var Nodes\ModifierNode[] $args */ + return match ($fn) { + 'modify' => $args[$pos]->printSimple($this, $var), + 'modifyContent' => $args[$pos]->printContentAware($this, $var), + 'escape' => end($this->escaperStack)->escape($var), + }; + }, + $mask, + ); + + return preg_replace_callback( + '#([,+]?\s*)? % (\d+) \. ([a-z]{3,}) (\?)? (\s*\+\s*)? ()#xi', + function ($m) use ($args) { + [, $left, $pos, $format, $cond, $right] = $m; + $arg = $args[$pos]; + + $code = match ($format) { + 'dump' => PhpHelpers::dump($arg), + 'node' => match (true) { + !$arg => '', + $arg instanceof OperatorNode && $arg->getOperatorPrecedence() < Expression\AssignNode::Precedence => '(' . $arg->print($this) . ')', + default => $arg->print($this), + }, + 'raw' => (string) $arg, + 'args' => $this->implode($arg instanceof Expression\ArrayNode ? $arg->toArguments() : $arg), + 'line' => $arg?->line ? "/* pos $arg->line" . ($arg->column ? ":$arg->column" : '') . ' */' : '', + }; + + if ($cond && ($code === '[]' || $code === '' || $code === 'null')) { + return $right ? $left : $right; + } + + return $code === '' + ? trim($left) . $right + : $left . $code . $right; + }, + $mask, + ); + } + + + public function beginEscape(): Escaper + { + return $this->escaperStack[] = $this->getEscaper(); + } + + + public function restoreEscape(): void + { + array_pop($this->escaperStack); + } + + + public function getEscaper(): Escaper + { + return clone end($this->escaperStack); + } + + + public function addBlock(Block $block): void + { + $block->escaping = $this->getEscaper()->export(); + $block->method = 'block' . ucfirst(trim(preg_replace('#\W+#', '_', $block->name->print($this)), '_')); + $lower = strtolower($block->method); + $used = $this->blocks + ['block' => 1]; + $counter = null; + while (isset($used[$lower . $counter])) { + $counter++; + } + + $block->method .= $counter; + $this->blocks[$lower . $counter] = $block; + } + + + public function generateId(): int + { + return $this->counter++; + } + + + // PHP helpers + + + public function encodeString(string $str, string $quote = "'"): string + { + return $quote === "'" + ? "'" . addcslashes($str, "'\\") . "'" + : '"' . addcslashes($str, "\n\r\t\f\v$\"\\") . '"'; + } + + + #[\Deprecated] + public function infixOp(Node $node, Node $leftNode, string $operatorString, Node $rightNode): string + { + return $this->parenthesize($node, $leftNode, OperatorNode::AssocLeft) + . $operatorString + . $this->parenthesize($node, $rightNode, OperatorNode::AssocRight); + } + + + #[\Deprecated] + public function prefixOp(Node $node, string $operatorString, Node $expr): string + { + return $operatorString . $this->parenthesize($node, $expr, OperatorNode::AssocRight); + } + + + #[\Deprecated] + public function postfixOp(Node $node, Node $var, string $operatorString): string + { + return $this->parenthesize($node, $var, OperatorNode::AssocLeft) . $operatorString; + } + + + /** + * Prints an expression node with the least amount of parentheses necessary to preserve the meaning. + */ + public function parenthesize(OperatorNode $parentNode, Node $childNode, int $childPosition): string + { + [$parentPrec, $parentAssoc] = $parentNode->getOperatorPrecedence(); + [$childPrec] = $childNode instanceof OperatorNode ? $childNode->getOperatorPrecedence() : null; + return $childPrec && ($childPrec < $parentPrec || ($parentPrec === $childPrec && $parentAssoc !== $childPosition)) + ? '(' . $childNode->print($this) . ')' + : $childNode->print($this); + } + + + /** + * Prints an array of nodes and implodes the printed values with $glue + */ + public function implode(array $nodes, string $glue = ', '): string + { + $pNodes = []; + foreach ($nodes as $node) { + if ($node === null) { + $pNodes[] = ''; + } else { + $pNodes[] = $node->print($this); + } + } + + return implode($glue, $pNodes); + } + + + public function objectProperty(Node $node): string + { + return $node instanceof Nodes\NameNode || $node instanceof Nodes\IdentifierNode + ? (string) $node + : '{' . $node->print($this) . '}'; + } + + + public function memberAsString(Node $node): string + { + return $node instanceof Nodes\NameNode || $node instanceof Nodes\IdentifierNode + ? $this->encodeString((string) $node) + : $node->print($this); + } + + + /** + * Wraps the LHS of a call in parentheses if needed. + */ + public function callExpr(Node $expr): string + { + return $expr instanceof Nodes\NameNode + || $expr instanceof Expression\VariableNode + || $expr instanceof Expression\ArrayAccessNode + || $expr instanceof Expression\FunctionCallNode + || $expr instanceof Expression\MethodCallNode + || $expr instanceof Expression\StaticMethodCallNode + || $expr instanceof Expression\ArrayNode + ? $expr->print($this) + : '(' . $expr->print($this) . ')'; + } + + + /** + * Wraps the LHS of a dereferencing operation in parentheses if needed. + */ + public function dereferenceExpr(Node $expr): string + { + return $expr instanceof Expression\VariableNode + || $expr instanceof Nodes\NameNode + || $expr instanceof Expression\ArrayAccessNode + || $expr instanceof Expression\PropertyFetchNode + || $expr instanceof Expression\StaticPropertyFetchNode + || $expr instanceof Expression\FunctionCallNode + || $expr instanceof Expression\MethodCallNode + || $expr instanceof Expression\StaticMethodCallNode + || $expr instanceof Expression\ArrayNode + || $expr instanceof Scalar\StringNode + || $expr instanceof Scalar\BooleanNode + || $expr instanceof Scalar\NullNode + || $expr instanceof Expression\ConstantFetchNode + || $expr instanceof Expression\ClassConstantFetchNode + ? $expr->print($this) + : '(' . $expr->print($this) . ')'; + } + + + /** + * @param Nodes\ArgumentNode[] $args + */ + public function argumentsAsArray(array $args): string + { + $items = array_map(fn(Nodes\ArgumentNode $arg) => $arg->toArrayItem(), $args); + return '[' . $this->implode($items) . ']'; + } + + + /** + * Ensures that expression evaluates to string or throws exception. + */ + public function ensureString(Nodes\ExpressionNode $name, string $entity): string + { + return $name instanceof Scalar\StringNode + ? $name->print($this) + : $this->format( + '(LR\Helpers::stringOrNull($ʟ_tmp = %node) ?? throw new InvalidArgumentException(sprintf(%dump, get_debug_type($ʟ_tmp))))', + $name, + $entity . ' must be a string, %s given.', + ); + } +} diff --git a/vendor/latte/latte/src/Latte/Compiler/Tag.php b/vendor/latte/latte/src/Latte/Compiler/Tag.php new file mode 100644 index 0000000..61bf3b8 --- /dev/null +++ b/vendor/latte/latte/src/Latte/Compiler/Tag.php @@ -0,0 +1,117 @@ +parser = new TagParser($tokens); + } + + + public function isInHead(): bool + { + return $this->inHead && !$this->parent; + } + + + public function isInText(): bool + { + return !$this->inTag; + } + + + public function isNAttribute(): bool + { + return $this->prefix !== null; + } + + + public function getNotation(bool $withArgs = false): string + { + return $this->isNAttribute() + ? TemplateLexer::NPrefix . ($this->prefix ? $this->prefix . '-' : '') + . $this->name + . ($withArgs ? '="' . $this->parser->text . '"' : '') + : '{' + . ($this->closing ? '/' : '') + . $this->name + . ($withArgs ? $this->parser->text : '') + . '}'; + } + + + /** + * @param class-string[] $classes + */ + public function closestTag(array $classes, ?callable $condition = null): ?self + { + $tag = $this->parent; + while ($tag && ( + !in_array($tag->node ? $tag->node::class : null, $classes, true) + || ($condition && !$condition($tag)) + )) { + $tag = $tag->parent; + } + + return $tag; + } + + + public function expectArguments(string $what = 'arguments'): void + { + if ($this->parser->isEnd()) { + throw new CompileException("Missing $what in " . $this->getNotation(), $this->position); + } + } + + + public function replaceNAttribute(AreaNode $node): void + { + $index = array_search($this->nAttribute, $this->htmlElement->attributes->children, true); + $this->htmlElement->attributes->children[$index] = $this->nAttribute = $node; + } +} diff --git a/vendor/latte/latte/src/Latte/Compiler/TagLexer.php b/vendor/latte/latte/src/Latte/Compiler/TagLexer.php new file mode 100644 index 0000000..dd50b7a --- /dev/null +++ b/vendor/latte/latte/src/Latte/Compiler/TagLexer.php @@ -0,0 +1,401 @@ + Token::Php_LogicalAnd, + 'array' => Token::Php_Array, + 'clone' => Token::Php_Clone, + 'default' => Token::Php_Default, + 'in' => Token::Php_In, + 'instanceof' => Token::Php_Instanceof, + 'new' => Token::Php_New, + 'or' => Token::Php_LogicalOr, + 'return' => Token::Php_Return, + 'xor' => Token::Php_LogicalXor, + 'null' => Token::Php_Null, + 'true' => Token::Php_True, + 'false' => Token::Php_False, + ]; + + private const KeywordsFollowed = [ // must follows ( & = + 'empty' => Token::Php_Empty, + 'fn' => Token::Php_Fn, + 'function' => Token::Php_Function, + 'isset' => Token::Php_Isset, + 'list' => Token::Php_List, + 'match' => Token::Php_Match, + 'use' => Token::Php_Use, + ]; + + /** @var Token[] */ + private array $tokens; + private string $input; + private int $offset; + private Position $position; + + + /** @return Token[] */ + public function tokenize(string $input, ?Position $position = null): array + { + $position ??= new Position; + $this->tokens = $this->tokenizePartially($input, $position, 0); + if ($this->offset !== strlen($input)) { + $token = str_replace("\n", '\n', substr($input, $this->offset, 10)); + throw new CompileException("Unexpected '$token'", $position); + } + + $this->tokens[] = new Token(Token::End, '', $position); + return $this->tokens; + } + + + /** @return Token[] */ + public function tokenizePartially(string $input, Position &$position, ?int $ofs = null): array + { + $this->input = $input; + $this->offset = $ofs ?? $position->offset; + $this->position = &$position; + $this->tokens = []; + $this->tokenizeCode(); + return $this->tokens; + } + + + /** @return Token[]|null */ + public function tokenizeUnquotedString(string $input, Position $position, bool $colon, int $offsetDelta): ?array + { + preg_match( + $colon + ? '~ ( [./@_a-z0-9#!-] | :(?!:) | \{\$ [_a-z0-9\[\]()>-]+ } )++ (?=\s+[!"\'$(\[{,\\\|\~\w-] | [,|] | \s*$) ~xAi' + : '~ ( [./@_a-z0-9#!-] | \{\$ [_a-z0-9\[\]()>-]+ } )++ (?=\s+[!"\'$(\[{,\\\|\~\w-] | [,:|] | \s*$) ~xAi', + $input, + $match, + offset: $position->offset - $offsetDelta, + ); + $position = new Position($position->line, $position->column - 1, $position->offset - 1); + return $match && !is_numeric($match[0]) + ? $this->tokenize('"' . $match[0] . '"', $position) + : null; + } + + + private function tokenizeCode(): void + { + $re = <<<'XX' + ~(?J)(?n) # allow duplicate named groups, no auto capture + (?(DEFINE) (?